7.9 KiB
7.9 KiB
出国行程变更申请功能优化说明
📋 修改时间
2025-10-13
🎯 修改目标
根据业务需求,优化出国行程变更申请流程:
- ✅ 修改选项卡名称:"全部变更" → "变更申请","我的变更" → "变更记录"
- ✅ 删除"变更记录"选项卡中的"新增变更申请"按钮
- ✅ 修改新增变更申请逻辑:从选择"出国记录"改为选择"已审批通过的出国申请"
- ✅ 流程优化:通过出国申请菜单下已审批通过的申请创建变更申请
📝 详细修改内容
一、前端修改
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">
移除"变更记录"选项卡中的新增按钮:
<!-- 删除前 -->
<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>
修改新增变更申请弹窗:
<!-- 修改前:选择出国记录 -->
<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. 业务逻辑调整
数据结构变更:
// 修改前
availableRecordList: [] as OverseasRecordVO[]
// 修改后
availableApplicationList: [] as OverseasApplicationVO[]
API调用变更:
// 修改前
import { getAvailableOverseasRecords, getOverseasRecordForChange }
// 修改后
import { getApprovedOverseasApplications, getOverseasApplication }
方法更新:
getAvailableRecordList()→getApprovedApplicationList()handleRecordChange(recordId)→handleApplicationChange(applicationId)- 验证规则:
recordId→applicationId
3. API接口更新 (web/src/api/rs/overseas.ts)
新增API方法:
// 获取已审批通过的出国申请列表(用于行程变更申请选择)
export function getApprovedOverseasApplications() {
return request({
url: '/rs/overseas/application/status/1',
method: 'get'
});
}
类型定义修改:
export interface ItineraryChangeForm {
changeId?: number | string;
recordId: number; // ❌ 删除/废弃
applicationId: number; // ✅ 新增必填
// ... 其他字段保持不变
}
二、后端修改
1. BO类修改 (RsOverseasItineraryChangeBo.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)
依赖注入调整:
// 新增
private final IRsOverseasApplicationService applicationService;
// 删除(不再使用)
// private final IRsOverseasRecordService recordService;
新增逻辑修改:
// 修改前:基于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("只能为已通过审批的出国申请提交变更申请");
}
数据来源变更:
// 修改前:从出国记录复制原始信息
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());
查重逻辑修改:
// 修改前:检查recordId
wrapper.eq(RsOverseasItineraryChange::getRecordId, bo.getRecordId())
// 修改后:检查applicationId
wrapper.eq(RsOverseasItineraryChange::getApplicationId, bo.getApplicationId())
🔄 业务流程对比
修改前流程
- 用户在"出国申请"菜单中提交出国申请
- 申请通过审批后,在"出国记录"选项卡中生成记录
- 用户在"行程变更"菜单中,选择"出国记录"创建变更申请
- 变更申请提交到审批流程
修改后流程
- 用户在"出国申请"菜单中提交出国申请
- 申请通过审批后(状态=1)
- 用户在"行程变更申请"选项卡中,直接选择已审批通过的出国申请创建变更申请
- 变更申请提交到审批流程
- 用户在"变更记录"选项卡中查看自己的变更历史
✨ 优化亮点
- 简化流程:不再依赖"出国记录",直接从已审批申请创建变更
- 状态验证:后端强制检查申请状态为"已通过"(status=1)才能创建变更
- UI优化:
- 选择框支持筛选(
filterable) - 清晰的选项卡命名(变更申请/变更记录)
- "变更记录"仅查看,不允许新增
- 选择框支持筛选(
- 数据一致性:直接从原始申请复制数据,避免中间环节
- 权限控制:保持原有权限体系不变
🧪 测试建议
前端测试
- ✅ 验证选项卡名称显示正确
- ✅ 验证"变更记录"选项卡无新增按钮
- ✅ 验证新增弹窗显示已审批通过的申请列表
- ✅ 验证选择申请后自动填充原始信息
- ✅ 验证筛选功能正常工作
后端测试
- ✅ 验证必填字段从recordId改为applicationId
- ✅ 验证只能选择status=1的申请
- ✅ 验证相同申请不能重复提交待审核的变更
- ✅ 验证数据来源为出国申请而非出国记录
- ✅ 验证编译通过无警告错误
📦 涉及文件清单
前端
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实现
⚠️ 注意事项
- 数据库兼容性:
record_id字段保留但不再必填,application_id字段成为必填 - 向后兼容:已有的变更记录仍然可以正常查看和处理
- 权限不变:所有权限配置保持原样,无需重新配置
- API不变:后端API路径和返回格式保持不变
🎉 完成状态
✅ 所有修改已完成并通过编译验证 ✅ 前端TypeScript类型检查通过 ✅ 后端Java编译成功 ✅ 业务逻辑符合需求 ✅ 代码质量良好(无警告)