332 lines
13 KiB
Markdown
332 lines
13 KiB
Markdown
# 党籍保留保存并提交功能修复报告
|
||
|
||
## 📋 问题描述
|
||
|
||
**现象**:在出国党籍保留菜单下的"党籍保留"选项卡中,点击"新增登记"按钮,填写内容后点击"保存并提交"按钮提示"保存并提交失败"。
|
||
|
||
**报告时间**:2025-10-05
|
||
**修复状态**:🔴 待修复
|
||
|
||
---
|
||
|
||
## 🔍 问题分析
|
||
|
||
### 根本原因
|
||
|
||
**后端代码完全缺失!**
|
||
|
||
根据 `backend/ruoyi-modules/ruoyi-rs/出国模块开发进程分析报告.md` 的记录:
|
||
|
||
```
|
||
### 2.3 出国党籍保留表 (rs_party_membership_retention)
|
||
|
||
#### ❌ 完成情况 (10%)
|
||
|
||
**后端代码** (❌ 全部未创建):
|
||
| 文件类型 | 文件路径 | 状态 |
|
||
|---------|----------|------|
|
||
| Entity实体 | domain/RsPartyMembershipRetention.java | ❌ 待创建 |
|
||
| VO类 | domain/vo/RsPartyMembershipRetentionVo.java | ❌ 待创建 |
|
||
| BO类 | domain/bo/RsPartyMembershipRetentionBo.java | ❌ 待创建 |
|
||
| Query类 | domain/query/RsPartyMembershipRetentionQuery.java | ❌ 待创建 |
|
||
| Mapper接口 | mapper/RsPartyMembershipRetentionMapper.java | ❌ 待创建 |
|
||
| Mapper XML | resources/mapper/rs/RsPartyMembershipRetentionMapper.xml | ❌ 待创建 |
|
||
| Service接口 | service/IRsPartyMembershipRetentionService.java | ❌ 待创建 |
|
||
| Service实现 | service/impl/RsPartyMembershipRetentionServiceImpl.java | ❌ 待创建 |
|
||
| Controller | controller/RsPartyMembershipRetentionController.java | ❌ 待创建 |
|
||
```
|
||
|
||
### 前端调用情况
|
||
|
||
前端代码已经完整开发:
|
||
|
||
**API接口定义**:`web/src/api/rs/party-membership-retention.ts`
|
||
```typescript
|
||
// 新增并提交党籍保留申请
|
||
export function addAndSubmitPartyRetention(data: PartyRetentionForm) {
|
||
return request({
|
||
url: '/rs/party/retention/addAndSubmit',
|
||
method: 'post',
|
||
data: data
|
||
})
|
||
}
|
||
```
|
||
|
||
**前端调用**:`web/src/views/rs/party-membership-retention/index.vue:882`
|
||
```typescript
|
||
const submitAndConfirmRetention = () => {
|
||
retentionFormRef.value?.validate(async (valid) => {
|
||
if (valid) {
|
||
retentionDialog.loading = true;
|
||
try {
|
||
await addAndSubmitPartyRetention(retentionForm.value);
|
||
ElMessage.success('保存并提交成功');
|
||
|
||
retentionDialog.visible = false;
|
||
resetRetentionForm();
|
||
getRetentionList();
|
||
} catch (error) {
|
||
ElMessage.error('保存并提交失败');
|
||
} finally {
|
||
retentionDialog.loading = false;
|
||
}
|
||
}
|
||
});
|
||
};
|
||
```
|
||
|
||
但后端**完全没有对应的Controller、Service、Mapper等任何代码**,导致前端调用404错误。
|
||
|
||
### 影响范围
|
||
|
||
- ❌ 整个党籍保留模块完全无法使用
|
||
- ❌ 所有API接口都不存在(列表查询、新增、修改、删除、提交等)
|
||
- ❌ 前端页面已开发完成但无法正常工作
|
||
|
||
---
|
||
|
||
## 🛠️ 修复方案
|
||
|
||
### 修复步骤概览
|
||
|
||
参考"出国登记"模块的成功案例,需要创建完整的后端代码:
|
||
|
||
1. ✅ **数据库表**:`rs_party_membership_retention` (SQL脚本已存在)
|
||
2. ❌ **Entity实体类**:`RsPartyMembershipRetention.java`
|
||
3. ❌ **VO类**:`RsPartyMembershipRetentionVo.java`
|
||
4. ❌ **BO类**:`RsPartyMembershipRetentionBo.java`
|
||
5. ❌ **Query类**:`RsPartyMembershipRetentionQuery.java`
|
||
6. ❌ **Mapper接口**:`RsPartyMembershipRetentionMapper.java`
|
||
7. ❌ **Mapper XML**:`RsPartyMembershipRetentionMapper.xml`
|
||
8. ❌ **Service接口**:`IRsPartyMembershipRetentionService.java`
|
||
9. ❌ **Service实现**:`RsPartyMembershipRetentionServiceImpl.java`
|
||
10. ❌ **Controller**:`RsPartyMembershipRetentionController.java`
|
||
|
||
### 需要实现的API接口
|
||
|
||
根据前端API文件 `web/src/api/rs/party-membership-retention.ts`,需要实现以下接口:
|
||
|
||
#### 基础接口
|
||
1. `GET /rs/party/retention/list` - 查询党籍保留列表(分页)
|
||
2. `GET /rs/party/retention/{retentionId}` - 查询党籍保留详情
|
||
3. `POST /rs/party/retention` - 新增党籍保留
|
||
4. `PUT /rs/party/retention` - 修改党籍保留
|
||
5. `DELETE /rs/party/retention/{retentionIds}` - 删除党籍保留
|
||
|
||
#### 业务接口
|
||
6. `POST /rs/party/retention/addAndSubmit` - **新增并提交党籍保留(核心功能)**
|
||
7. `POST /rs/party/retention/submit` - 提交党籍保留申请
|
||
8. `POST /rs/party/retention/cancel/{retentionId}` - 撤回党籍保留申请
|
||
9. `GET /rs/party/retention/history/list` - 查询历史记录列表
|
||
10. `POST /rs/party/retention/export` - 导出党籍保留列表
|
||
11. `POST /rs/party/retention/history/export` - 导出历史记录
|
||
|
||
---
|
||
|
||
## 📊 数据库表结构
|
||
|
||
### 表名:`rs_party_membership_retention`
|
||
|
||
根据 `backend/ruoyi-modules/ruoyi-rs/出国党籍保留表创建脚本.sql`:
|
||
|
||
```sql
|
||
CREATE TABLE `rs_party_membership_retention` (
|
||
-- ========== 主键和关联字段 ==========
|
||
`retention_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '党籍保留ID(主键)',
|
||
`application_id` bigint(20) NULL DEFAULT NULL COMMENT '关联出国申请ID',
|
||
`registration_id` bigint(20) NULL DEFAULT NULL COMMENT '关联出国登记ID',
|
||
|
||
-- ========== 基本信息字段 ==========
|
||
`name` varchar(50) NOT NULL COMMENT '我支部同志(姓名)',
|
||
`spouse` varchar(50) NULL DEFAULT NULL COMMENT '偕配偶姓名',
|
||
|
||
-- ========== 出国时间字段 ==========
|
||
`travel_start_date` date NOT NULL COMMENT '拟出国开始日期',
|
||
`travel_end_date` date NOT NULL COMMENT '拟出国结束日期',
|
||
`stay_days` int(11) NULL DEFAULT NULL COMMENT '在外停留天数',
|
||
|
||
-- ========== 出国目的和地点字段 ==========
|
||
`destination` varchar(100) NOT NULL COMMENT '因私赴XX(国家或地区)',
|
||
`purpose` text NULL COMMENT '出国目的详细说明',
|
||
`travel_reason` varchar(50) NULL DEFAULT NULL COMMENT '出国原因(简要)',
|
||
|
||
-- ========== 费用信息字段 ==========
|
||
`self_funded` char(1) NOT NULL DEFAULT '1' COMMENT '费用自理:1-是,0-否',
|
||
|
||
-- ========== 党组织信息字段 ==========
|
||
`party_branch` varchar(100) NOT NULL COMMENT '党支部名称',
|
||
`relative_name` varchar(50) NULL DEFAULT NULL COMMENT '国内亲属姓名',
|
||
`relative_phone` varchar(20) NULL DEFAULT NULL COMMENT '国内亲属联系电话',
|
||
|
||
-- ========== 签字信息字段 ==========
|
||
`applicant_signature` text NULL COMMENT '申请人签字(Base64图片)',
|
||
`application_date` date NULL DEFAULT NULL COMMENT '申请日期',
|
||
|
||
-- ========== 审批流程字段 ==========
|
||
`status` char(1) NOT NULL DEFAULT '0' COMMENT '状态:0-草稿,1-待审核,2-已通过,3-已拒绝,4-已撤回',
|
||
`submit_time` datetime NULL DEFAULT NULL COMMENT '提交时间',
|
||
`approval_time` datetime NULL DEFAULT NULL COMMENT '审批时间',
|
||
`approval_result` char(1) NULL DEFAULT NULL COMMENT '审批结果:1-通过,2-拒绝',
|
||
`approval_opinion` text NULL COMMENT '审批意见',
|
||
`approver_id` bigint(20) NULL DEFAULT NULL COMMENT '审批人ID',
|
||
`approver_name` varchar(50) NULL DEFAULT NULL COMMENT '审批人姓名',
|
||
|
||
-- ========== 系统字段 ==========
|
||
`create_dept` bigint(20) NULL DEFAULT NULL COMMENT '创建部门',
|
||
`create_by` bigint(20) NULL DEFAULT NULL COMMENT '创建者',
|
||
`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
|
||
`update_by` bigint(20) NULL DEFAULT NULL COMMENT '更新者',
|
||
`update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
|
||
`remark` varchar(500) NULL DEFAULT NULL COMMENT '备注',
|
||
`deleted` char(1) NOT NULL DEFAULT '0' COMMENT '删除标志:0-未删除,1-已删除',
|
||
`tenant_id` varchar(20) NULL DEFAULT '000000' COMMENT '租户编号',
|
||
|
||
PRIMARY KEY (`retention_id`),
|
||
KEY `idx_registration_id` (`registration_id`),
|
||
KEY `idx_application_id` (`application_id`),
|
||
KEY `idx_status` (`status`),
|
||
KEY `idx_create_time` (`create_time`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='出国党籍保留表';
|
||
```
|
||
|
||
---
|
||
|
||
## 🔧 详细修复步骤
|
||
|
||
### 第一步:验证数据库表
|
||
|
||
```sql
|
||
-- 检查表是否存在
|
||
SHOW TABLES LIKE 'rs_party_membership_retention';
|
||
|
||
-- 如果不存在,执行创建脚本
|
||
SOURCE backend/ruoyi-modules/ruoyi-rs/出国党籍保留表创建脚本.sql;
|
||
```
|
||
|
||
### 第二步:创建后端代码
|
||
|
||
参考"出国登记"模块的代码结构,创建完整的后端代码。
|
||
|
||
#### 核心接口实现重点
|
||
|
||
**1. addAndSubmit 方法(保存并提交)**
|
||
|
||
参考 `RsOverseasRegistrationServiceImpl.java:218-252` 的实现:
|
||
|
||
```java
|
||
@Override
|
||
@Transactional(rollbackFor = Exception.class)
|
||
public Boolean addAndSubmit(RsPartyMembershipRetentionBo bo) {
|
||
// ⚠️ 强制清空Bo中的基础字段,让MyBatis-Plus自动填充
|
||
bo.setCreateBy(null);
|
||
bo.setCreateTime(null);
|
||
bo.setUpdateBy(null);
|
||
bo.setUpdateTime(null);
|
||
|
||
// 1. 先新增党籍保留记录
|
||
RsPartyMembershipRetention add = MapstructUtils.convert(bo, RsPartyMembershipRetention.class);
|
||
|
||
// 直接设置为待审核状态
|
||
add.setStatus("1"); // 待审核
|
||
add.setSubmitTime(new Date());
|
||
|
||
// 计算停留天数
|
||
if (add.getTravelStartDate() != null && add.getTravelEndDate() != null) {
|
||
long days = (add.getTravelEndDate().getTime() - add.getTravelStartDate().getTime()) / (1000 * 60 * 60 * 24);
|
||
add.setStayDays((int) days);
|
||
}
|
||
|
||
boolean flag = baseMapper.insert(add) > 0;
|
||
if (!flag) {
|
||
throw new RuntimeException("保存党籍保留失败!");
|
||
}
|
||
|
||
bo.setRetentionId(add.getRetentionId());
|
||
log.info("新增并提交成功,retentionId: {}, createBy: {}, createTime: {}, submitTime: {}",
|
||
add.getRetentionId(), add.getCreateBy(), add.getCreateTime(), add.getSubmitTime());
|
||
return true;
|
||
}
|
||
```
|
||
|
||
**2. Controller接口**
|
||
|
||
```java
|
||
/**
|
||
* 新增并提交党籍保留申请
|
||
*/
|
||
@SaCheckPermission("rs:party:retention:add")
|
||
@Log(title = "党籍保留", businessType = BusinessType.INSERT)
|
||
@PostMapping("/addAndSubmit")
|
||
public R<Void> addAndSubmit(@Validated(AddGroup.class) @RequestBody RsPartyMembershipRetentionBo bo) {
|
||
return toAjax(retentionService.addAndSubmit(bo));
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 📝 参考资料
|
||
|
||
### 成功案例
|
||
- **出国登记模块修复报告**:`出国登记保存并提交功能修复报告.md`
|
||
- **出国登记Service实现**:`backend/ruoyi-modules/ruoyi-rs/src/main/java/org/dromara/rs/service/impl/RsOverseasRegistrationServiceImpl.java`
|
||
- **出国登记Controller**:`backend/ruoyi-modules/ruoyi-rs/src/main/java/org/dromara/rs/controller/RsOverseasRegistrationController.java`
|
||
|
||
### 设计文档
|
||
- **数据库脚本**:`backend/ruoyi-modules/ruoyi-rs/出国党籍保留表创建脚本.sql`
|
||
- **流程设计**:`backend/ruoyi-modules/ruoyi-rs/出国流程重新设计方案.md`
|
||
- **开发进度**:`backend/ruoyi-modules/ruoyi-rs/出国模块开发进程分析报告.md`
|
||
|
||
### 前端代码
|
||
- **API接口**:`web/src/api/rs/party-membership-retention.ts`
|
||
- **页面组件**:`web/src/views/rs/party-membership-retention/index.vue`
|
||
|
||
---
|
||
|
||
## ⚠️ 重要提示
|
||
|
||
1. **MyBatis-Plus自动填充问题**:
|
||
- 必须在 `addAndSubmit` 方法中清空 `createBy`、`createTime`、`updateBy`、`updateTime` 字段
|
||
- 否则会导致这些字段为null,无法正确记录操作人和时间
|
||
|
||
2. **状态管理**:
|
||
- 草稿状态:`0`
|
||
- 待审核状态:`1`(提交后的状态)
|
||
- 已通过:`2`
|
||
- 已拒绝:`3`
|
||
- 已撤回:`4`
|
||
|
||
3. **权限配置**:
|
||
- 需要在系统菜单中配置对应的权限标识
|
||
- 权限前缀:`rs:party:retention:`
|
||
|
||
---
|
||
|
||
## 📅 修复计划
|
||
|
||
| 步骤 | 任务 | 预计时间 | 状态 |
|
||
|------|------|----------|------|
|
||
| 1 | 验证数据库表是否存在 | 5分钟 | ⏳ 待开始 |
|
||
| 2 | 创建Entity实体类 | 15分钟 | ⏳ 待开始 |
|
||
| 3 | 创建VO、BO、Query类 | 20分钟 | ⏳ 待开始 |
|
||
| 4 | 创建Mapper接口和XML | 15分钟 | ⏳ 待开始 |
|
||
| 5 | 创建Service接口和实现 | 30分钟 | ⏳ 待开始 |
|
||
| 6 | 创建Controller控制器 | 20分钟 | ⏳ 待开始 |
|
||
| 7 | 测试所有接口 | 30分钟 | ⏳ 待开始 |
|
||
| 8 | 前后端联调测试 | 20分钟 | ⏳ 待开始 |
|
||
|
||
**总计**:约2.5小时
|
||
|
||
---
|
||
|
||
## 📌 总结
|
||
|
||
这是一个**前端已完成但后端完全缺失**的典型案例。需要参考"出国登记"模块的成功经验,完整创建后端代码才能解决问题。
|
||
|
||
**关键点**:
|
||
- ✅ 前端代码完整且正确
|
||
- ❌ 后端代码完全缺失
|
||
- ✅ 数据库设计已完成
|
||
- ✅ 有成功案例可参考(出国登记模块)
|
||
|
||
**下一步行动**:按照修复计划逐步创建后端代码。
|