9.5 KiB
9.5 KiB
出国行程变更申请 - 必填字段修复说明
📋 问题描述
问题现象:点击"新增变更申请"按钮,填写表单后点击提交,系统依次提示:
- ❌ "关联备案记录ID不能为空"
- ❌ "申请人ID不能为空"
根本原因:
- 数据库表
rs_overseas_itinerary_change中record_id和applicant_id字段为必填(NOT NULL) - 前端表单提交时未包含
recordId和applicantId字段 - 后端验证失败,返回错误提示
🔧 修复方案
1. 核心思路
通过出国申请ID(applicationId)获取对应的出国记录(record),从而获得 recordId。
数据关系链:
出国申请表 (rs_overseas_application)
↓ applicationId
出国记录表 (rs_overseas_record)
↓ recordId
行程变更表 (rs_overseas_itinerary_change)
2. 修复步骤
Step 1: 添加必填字段到 TypeScript 类型定义
文件: web/src/api/rs/overseas.ts
// 行程变更表单类型
export interface ItineraryChangeForm {
changeId?: number | string;
recordId: number; // ✅ 新增:关联出国记录ID(必填)
applicationId: number;
applicantId: number; // ✅ 新增:申请人ID(必填)
applicantName?: string;
// ... 其他字段
}
Step 2: 导入获取出国记录的 API
文件: web/src/views/rs/overseas/itinerary-change.vue
import {
// ... 其他导入
getOverseasRecordByApplication, // ✅ 新增:根据申请ID获取出国记录
type ItineraryChangeQuery,
type ItineraryChangeVO,
type ItineraryChangeForm,
type OverseasApplicationVO
} from '@/api/rs/overseas';
Step 3: 在选择出国申请时获取必填字段
文件: web/src/views/rs/overseas/itinerary-change.vue
// 选择原出国申请后,自动填充原申请信息
const handleApplicationChange = async (applicationId: number) => {
try {
// 1. 获取出国申请详情
const response = await getOverseasApplication(applicationId);
const selectedApplication = response.data;
// 2. ✅ 根据申请ID获取出国记录(包含recordId)
const recordResponse = await getOverseasRecordByApplication(applicationId);
const recordData = recordResponse.data;
if (selectedApplication && recordData) {
// ✅ 设置recordId(关键字段,必填)
state.form.recordId = recordData.recordId;
// ✅ 设置申请人ID(关键字段,必填)
state.form.applicantId = selectedApplication.applicantId;
// 填充其他字段...
}
} catch (error) {
console.error('获取申请详情失败:', error);
ElMessage.error('获取出国申请详情失败,请确保该申请已有对应的出国记录');
}
};
Step 4: 在表单重置时包含必填字段
文件: web/src/views/rs/overseas/itinerary-change.vue
// 重置表单
const resetForm = () => {
state.form = {
changeId: undefined,
recordId: undefined as any, // ✅ 新增
applicationId: undefined as any,
applicantId: undefined as any, // ✅ 新增
// ... 其他字段
};
state.changeTypes = [];
formRef.value?.resetFields();
};
✅ 修复效果
修复前
用户操作流程:
1. 点击"新增变更申请"
2. 选择原出国申请
3. 填写变更信息
4. 点击提交
❌ 错误提示:关联备案记录ID不能为空
修复后
用户操作流程:
1. 点击"新增变更申请"
2. 选择原出国申请
✅ 自动获取 applicationId
✅ 通过 applicationId 获取 recordId
✅ 设置 form.recordId
3. 填写变更信息
4. 点击提交
✅ 提交成功!变更申请已进入审批流程
✅ 数据流转到"出国行程变更审批"选项卡
🔍 数据流转
1. 前端提交数据结构
{
"changeId": null,
"recordId": 1849311999315025922, // ✅ 必填字段
"applicationId": 1849311999315025920,
"applicantId": 1001, // ✅ 必填字段
"applicantName": "张三",
"gender": "0",
"newDestination": "美国",
"newExitReason": "学术交流",
"changeReason": "会议时间调整",
"changeType": "时间变更",
// ... 其他字段
}
2. 后端数据库存储
INSERT INTO rs_overseas_itinerary_change (
change_id,
record_id, -- ✅ 从前端获取
application_id,
applicant_id, -- ✅ 从前端获取
applicant_name,
-- ... 其他字段
) VALUES (
1234567890123456789,
1849311999315025922, -- ✅ 成功插入
1849311999315025920,
1001, -- ✅ 成功插入
'张三',
-- ... 其他值
);
3. 审批流程
提交成功
↓
自动刷新列表(根据当前Tab)
↓
状态变更为"待审核"(status='0')
↓
流转到"出国行程变更审批"选项卡
↓
审批人可以查看并审批
📊 API 调用链
前端操作
↓
handleApplicationChange(applicationId)
↓
┌─────────────────────────────────────────┐
│ getOverseasApplication(applicationId) │ → 获取申请详情
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ getOverseasRecordByApplication( │ → 获取出国记录
│ applicationId │ (包含recordId)
│ ) │
└─────────────────────────────────────────┘
↓
设置 state.form.recordId = recordData.recordId
↓
用户填写变更信息
↓
submitForm()
↓
┌─────────────────────────────────────────┐
│ addItineraryChange(state.form) │ → 提交变更申请
│ { │ (包含必填字段)
│ recordId: 1849311999315025922, │
│ applicationId: 1849311999315025920, │
│ applicantId: 1001, │
│ ... │
│ } │
└─────────────────────────────────────────┘
↓
✅ 提交成功
🎯 关键要点
✅ 必须要做的
- 类型定义:
ItineraryChangeForm必须包含recordId: number和applicantId: number - API导入:导入
getOverseasRecordByApplication函数 - 获取必填字段:在选择出国申请时,同时获取对应的出国记录和申请人ID
- 表单重置:
resetForm中包含recordId和applicantId字段初始化
⚠️ 注意事项
- 错误处理:如果出国申请没有对应的出国记录,需要友好提示
- 数据验证:确保
recordId和applicantId在提交前不为空 - 用户体验:选择出国申请后,必填字段自动获取,用户无感知
📝 错误消息优化
catch (error) {
console.error('获取申请详情失败:', error);
ElMessage.error('获取出国申请详情失败,请确保该申请已有对应的出国记录');
}
🧪 测试验证
测试场景
场景1:正常流程
✅ 选择已审批通过的出国申请
✅ 系统自动获取 recordId
✅ 填写变更信息
✅ 提交成功
✅ 状态显示"待审核"
场景2:异常处理
❌ 选择的申请没有对应的出国记录
✅ 显示友好错误提示
✅ 用户可以重新选择其他申请
场景3:数据完整性
✅ 提交的数据包含 recordId 和 applicantId
✅ 后端验证通过
✅ 数据库记录正确插入
📁 修改文件清单
| 文件路径 | 修改内容 | 修改行数 |
|---|---|---|
web/src/api/rs/overseas.ts |
ItineraryChangeForm 添加 recordId 和 applicantId 字段 | +2 行 |
web/src/views/rs/overseas/itinerary-change.vue |
导入 getOverseasRecordByApplication | +1 行 |
web/src/views/rs/overseas/itinerary-change.vue |
handleApplicationChange 获取 recordId 和 applicantId | +7 行 |
web/src/views/rs/overseas/itinerary-change.vue |
resetForm 添加 recordId 和 applicantId 初始化 | +2 行 |
总计修改:3 个文件,+12 行代码
🎉 总结
问题根源:前端表单缺少必填字段 recordId 和 applicantId
解决方案:
- ✅ 类型定义中添加
recordId和applicantId字段 - ✅ 选择出国申请时,通过 API 自动获取
recordId和applicantId - ✅ 表单提交时包含所有必填字段
- ✅ 后端验证通过,数据成功存储
修复效果:
- ✅ 用户可以正常提交行程变更申请
- ✅ 变更申请成功流转到审批流程
- ✅ 显示在"出国行程变更审批"选项卡中
- ✅ 审批人可以正常审批
修复时间:2025-10-13
修复人员:Cursor AI Assistant
📚 相关文档
- 数据库表设计:
docs/设计文档/database/rs_overseas_itinerary_change_full.sql - API文档:待补充到
docs/开发文档/API/目录 - 表单优化:
行程变更申请表单优化-更新说明.md - 效果对比:
行程变更表单优化-效果对比.md
文档生成时间:2025-10-13
文档版本:v1.0