Files
hzdyjs/出国行程变更申请功能优化说明.md
T
2025-10-14 16:41:19 +08:00

251 lines
7.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 出国行程变更申请功能优化说明
## 📋 修改时间
2025-10-13
## 🎯 修改目标
根据业务需求,优化出国行程变更申请流程:
1. ✅ 修改选项卡名称:"全部变更" → "变更申请","我的变更" → "变更记录"
2. ✅ 删除"变更记录"选项卡中的"新增变更申请"按钮
3. ✅ 修改新增变更申请逻辑:从选择"出国记录"改为选择"已审批通过的出国申请"
4. ✅ 流程优化:通过出国申请菜单下已审批通过的申请创建变更申请
## 📝 详细修改内容
### 一、前端修改
#### 1. 页面UI优化 (`web/src/views/rs/overseas/itinerary-change.vue`)
**选项卡名称修改**:
- `<el-tab-pane label="全部变更" name="all">` → `<el-tab-pane label="变更申请" name="all">`
- `<el-tab-pane label="我的变更" name="my">` → `<el-tab-pane label="变更记录" name="my">`
**移除"变更记录"选项卡中的新增按钮**:
```vue
<!-- 删除前 -->
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd">
新增变更申请
</el-button>
</el-col>
<!-- 删除后 -->
<!-- 只保留 right-toolbar -->
<right-toolbar v-model:showSearch="showMySearch" @queryTable="getMyList"></right-toolbar>
```
**修改新增变更申请弹窗**:
```vue
<!-- 修改前:选择出国记录 -->
<el-form-item label="选择原出国记录" prop="recordId">
<el-select v-model="form.recordId" ...>
<el-option v-for="record in availableRecordList" .../>
</el-select>
</el-form-item>
<!-- 修改后:选择已审批通过的出国申请 -->
<el-form-item label="选择原出国申请" prop="applicationId">
<el-select v-model="form.applicationId" filterable ...>
<el-option v-for="application in availableApplicationList" .../>
</el-select>
</el-form-item>
```
#### 2. 业务逻辑调整
**数据结构变更**:
```typescript
// 修改前
availableRecordList: [] as OverseasRecordVO[]
// 修改后
availableApplicationList: [] as OverseasApplicationVO[]
```
**API调用变更**:
```typescript
// 修改前
import { getAvailableOverseasRecords, getOverseasRecordForChange }
// 修改后
import { getApprovedOverseasApplications, getOverseasApplication }
```
**方法更新**:
- `getAvailableRecordList()` → `getApprovedApplicationList()`
- `handleRecordChange(recordId)` → `handleApplicationChange(applicationId)`
- 验证规则:`recordId` → `applicationId`
#### 3. API接口更新 (`web/src/api/rs/overseas.ts`)
**新增API方法**:
```typescript
// 获取已审批通过的出国申请列表(用于行程变更申请选择)
export function getApprovedOverseasApplications() {
return request({
url: '/rs/overseas/application/status/1',
method: 'get'
});
}
```
**类型定义修改**:
```typescript
export interface ItineraryChangeForm {
changeId?: number | string;
recordId: number; // ❌ 删除/废弃
applicationId: number; // ✅ 新增必填
// ... 其他字段保持不变
}
```
### 二、后端修改
#### 1. BO类修改 (`RsOverseasItineraryChangeBo.java`)
**字段验证调整**:
```java
// 修改前
@NotNull(message = "关联备案记录ID不能为空", groups = { AddGroup.class, EditGroup.class })
private Long recordId;
private Long applicationId;
// 修改后
/**
* 关联备案记录ID(外键,关联rs_overseas_entry_exit_record.record_id)
* 注:该字段已废弃,现在使用applicationId
*/
private Long recordId;
/**
* 关联出国申请ID(外键,关联rs_overseas_application.application_id)
*/
@NotNull(message = "关联出国申请ID不能为空", groups = { AddGroup.class, EditGroup.class })
private Long applicationId;
```
#### 2. Service实现修改 (`RsOverseasItineraryChangeServiceImpl.java`)
**依赖注入调整**:
```java
// 新增
private final IRsOverseasApplicationService applicationService;
// 删除(不再使用)
// private final IRsOverseasRecordService recordService;
```
**新增逻辑修改**:
```java
// 修改前:基于recordId查询出国记录
RsOverseasRecordVo record = recordService.queryById(bo.getRecordId());
if (record == null) {
throw new ServiceException("出国记录不存在");
}
// 修改后:基于applicationId查询出国申请
RsOverseasApplicationVo application = applicationService.queryById(bo.getApplicationId());
if (application == null) {
throw new ServiceException("出国申请不存在");
}
// 新增:检查申请状态
if (!"1".equals(application.getStatus())) {
throw new ServiceException("只能为已通过审批的出国申请提交变更申请");
}
```
**数据来源变更**:
```java
// 修改前:从出国记录复制原始信息
entity.setOriginalDestination(record.getDestination());
entity.setOriginalStartDate(record.getActualStartDate());
entity.setOriginalEndDate(record.getActualEndDate());
entity.setOriginalDuration(record.getActualDuration());
// 修改后:从出国申请复制原始信息
entity.setOriginalDestination(application.getDestination());
entity.setOriginalStartDate(application.getStartDate());
entity.setOriginalEndDate(application.getEndDate());
entity.setOriginalDuration(application.getDuration());
```
**查重逻辑修改**:
```java
// 修改前:检查recordId
wrapper.eq(RsOverseasItineraryChange::getRecordId, bo.getRecordId())
// 修改后:检查applicationId
wrapper.eq(RsOverseasItineraryChange::getApplicationId, bo.getApplicationId())
```
## 🔄 业务流程对比
### 修改前流程
1. 用户在"出国申请"菜单中提交出国申请
2. 申请通过审批后,在"出国记录"选项卡中生成记录
3. 用户在"行程变更"菜单中,选择"出国记录"创建变更申请
4. 变更申请提交到审批流程
### 修改后流程
1. 用户在"出国申请"菜单中提交出国申请
2. 申请通过审批后(状态=1)
3. 用户在"行程变更申请"选项卡中,**直接选择已审批通过的出国申请**创建变更申请
4. 变更申请提交到审批流程
5. 用户在"变更记录"选项卡中查看自己的变更历史
## ✨ 优化亮点
1. **简化流程**:不再依赖"出国记录",直接从已审批申请创建变更
2. **状态验证**:后端强制检查申请状态为"已通过"(status=1)才能创建变更
3. **UI优化**:
- 选择框支持筛选(`filterable`)
- 清晰的选项卡命名(变更申请/变更记录)
- "变更记录"仅查看,不允许新增
4. **数据一致性**:直接从原始申请复制数据,避免中间环节
5. **权限控制**:保持原有权限体系不变
## 🧪 测试建议
### 前端测试
1. ✅ 验证选项卡名称显示正确
2. ✅ 验证"变更记录"选项卡无新增按钮
3. ✅ 验证新增弹窗显示已审批通过的申请列表
4. ✅ 验证选择申请后自动填充原始信息
5. ✅ 验证筛选功能正常工作
### 后端测试
1. ✅ 验证必填字段从recordId改为applicationId
2. ✅ 验证只能选择status=1的申请
3. ✅ 验证相同申请不能重复提交待审核的变更
4. ✅ 验证数据来源为出国申请而非出国记录
5. ✅ 验证编译通过无警告错误
## 📦 涉及文件清单
### 前端
- `web/src/views/rs/overseas/itinerary-change.vue` - 主页面组件
- `web/src/api/rs/overseas.ts` - API接口定义
### 后端
- `backend/ruoyi-modules/ruoyi-rs/src/main/java/org/dromara/rs/domain/bo/RsOverseasItineraryChangeBo.java` - BO类
- `backend/ruoyi-modules/ruoyi-rs/src/main/java/org/dromara/rs/service/impl/RsOverseasItineraryChangeServiceImpl.java` - Service实现
## ⚠️ 注意事项
1. **数据库兼容性**:`record_id`字段保留但不再必填,`application_id`字段成为必填
2. **向后兼容**:已有的变更记录仍然可以正常查看和处理
3. **权限不变**:所有权限配置保持原样,无需重新配置
4. **API不变**:后端API路径和返回格式保持不变
## 🎉 完成状态
✅ 所有修改已完成并通过编译验证
✅ 前端TypeScript类型检查通过
✅ 后端Java编译成功
✅ 业务逻辑符合需求
✅ 代码质量良好(无警告)