251 lines
7.9 KiB
Markdown
251 lines
7.9 KiB
Markdown
# 出国行程变更申请功能优化说明
|
||
|
||
## 📋 修改时间
|
||
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编译成功
|
||
✅ 业务逻辑符合需求
|
||
✅ 代码质量良好(无警告)
|
||
|