“编译修改”

This commit is contained in:
weizhong committed 2025-10-14 16:48:17 +08:00
1 parent e79bf5a26c
commit 2f2e303781
105 files changed
+26461

No files matched your search

+436
View File
@@ -0,0 +1,436 @@
import request from '@/utils/request';
// 出国登记查询参数类型
export interface OverseasRegistrationQuery {
pageNum: number;
pageSize: number;
name?: string; // 姓名(模糊查询)
gender?: string; // 性别
idNumber?: string; // 身份证号码(模糊查询)
politicalStatus?: string; // 政治面貌
department?: string; // 工作部门(模糊查询)
position?: string; // 职务职称(模糊查询)
administrativeLevel?: string; // 行政职级
personnelCategory?: string; // 人员类别代码
mobilePhone?: string; // 移动电话(模糊查询)
status?: string; // 登记状态
registrationTimeStart?: string; // 登记时间开始
registrationTimeEnd?: string; // 登记时间结束
createTimeStart?: string; // 创建时间开始
createTimeEnd?: string; // 创建时间结束
params?: Record<string, any>;
}
// 出国登记数据类型
export interface OverseasRegistrationVO {
registrationId: number | string;
registrantId: number;
registrantName: string;
idNumber: string;
contactPhone: string;
department: string;
travelType: string;
destination: string;
departureDate: string;
returnDate: string;
duration: number;
estimatedCost: number;
emergencyContact: string;
travelPurpose: string;
itinerary: string;
remarks: string;
status: string;
registrationTime: string;
confirmTime: string;
createTime: string;
updateTime: string;
createBy: string;
updateBy: string;
// 显示字段
statusText: string;
travelTypeText: string;
}
// 出国登记表单类型
export interface OverseasRegistrationForm {
registrationId?: number | string;
applicationId?: number | string; // 关联出国申请ID
name?: string; // 姓名
gender?: string; // 性别:0-男,1-女
birthDate?: string; // 出生日期
photo?: string; // 照片地址
idNumber?: string; // 公民身份号码(18位)
politicalStatus?: string; // 政治面貌
registeredAddress?: string; // 户籍所在地
department?: string; // 工作部门
position?: string; // 职务职称
administrativeLevel?: string; // 行政职级
personnelCategory?: string; // 人员类别代码
unitLeaderSignature?: string; // 负责人签名
officePhone?: string; // 办公电话
mobilePhone?: string; // 移动电话
remarks?: string; // 备注
}
// 登记历史查询参数类型
export interface OverseasRegistrationHistoryQuery {
pageNum: number;
pageSize: number;
registrantName?: string;
department?: string;
travelType?: string;
destination?: string;
completionStatus?: string;
registrantId?: number;
registrationId?: number;
actualDepartureDateBegin?: string;
actualDepartureDateEnd?: string;
actualReturnDateBegin?: string;
actualReturnDateEnd?: string;
params?: Record<string, any>;
}
// 登记历史数据类型
export interface OverseasRegistrationHistoryVO {
historyId: number | string;
registrationId: number;
registrantId: number;
registrantName: string;
idNumber: string;
contactPhone: string;
department: string;
travelType: string;
destination: string;
actualDepartureDate: string;
actualReturnDate: string;
actualDuration: number;
actualCost: number;
completionStatus: string;
completionNotes: string;
evidenceFiles: string;
createTime: string;
updateTime: string;
createBy: string;
updateBy: string;
// 显示字段
completionStatusText: string;
travelTypeText: string;
}
// 提交请求类型
export interface SubmitRegistrationRequest {
registrationId: number | string;
submitNotes?: string;
}
// 确认请求类型
export interface ConfirmRegistrationRequest {
registrationId: number | string;
confirmNotes?: string;
}
// ========================= 出国登记 API =========================
/**
* 查询出国登记列表
*/
export function getOverseasRegistrationList(query: OverseasRegistrationQuery) {
return request({
url: '/rs/overseas/registration/list',
method: 'get',
params: query
});
}
/**
* 查询出国登记详细
*/
export function getOverseasRegistration(registrationId: number | string) {
return request({
url: `/rs/overseas/registration/${registrationId}`,
method: 'get'
});
}
/**
* 新增出国登记
*/
export function addOverseasRegistration(data: OverseasRegistrationForm) {
return request({
url: '/rs/overseas/registration',
method: 'post',
data: data
});
}
/**
* 修改出国登记
*/
export function updateOverseasRegistration(data: OverseasRegistrationForm) {
return request({
url: '/rs/overseas/registration',
method: 'put',
data: data
});
}
/**
* 删除出国登记
*/
export function delOverseasRegistration(registrationId: number | string | Array<number | string>) {
return request({
url: `/rs/overseas/registration/${registrationId}`,
method: 'delete'
});
}
/**
* 提交出国登记
*/
export function submitOverseasRegistration(data: SubmitRegistrationRequest) {
return request({
url: `/rs/overseas/registration/submit/${data.registrationId}`,
method: 'put',
data: data
});
}
/**
* 撤回出国登记
*/
export function cancelOverseasRegistration(registrationId: number | string) {
return request({
url: `/rs/overseas/registration/withdraw/${registrationId}`,
method: 'put'
});
}
/**
* 确认出国登记
*/
export function confirmOverseasRegistration(data: ConfirmRegistrationRequest) {
return request({
url: `/rs/overseas/registration/confirm/${data.registrationId}`,
method: 'put',
data: data
});
}
/**
* 新增并提交出国登记
*/
export function addAndSubmitOverseasRegistration(data: OverseasRegistrationForm) {
return request({
url: '/rs/overseas/registration/addAndSubmit',
method: 'post',
data: data
});
}
/**
* 导出出国登记
*/
export function exportOverseasRegistration(query: OverseasRegistrationQuery) {
return request({
url: '/rs/overseas/registration/export',
method: 'post',
data: query,
responseType: 'blob'
});
}
/**
* 生成出国证明
*/
export function generateOverseasCertificate(registrationId: number | string) {
return request({
url: `/rs/overseas/registration/generateCertificate/${registrationId}`,
method: 'post',
responseType: 'blob'
});
}
// ========================= 登记历史 API =========================
/**
* 查询登记历史列表
*/
export function getOverseasRegistrationHistoryList(query: OverseasRegistrationHistoryQuery) {
return request({
url: '/rs/overseas/registration/history/list',
method: 'get',
params: query
});
}
/**
* 查询登记历史详细
*/
export function getOverseasRegistrationHistory(historyId: number | string) {
return request({
url: `/rs/overseas/registration/history/${historyId}`,
method: 'get'
});
}
/**
* 新增登记历史
*/
export function addOverseasRegistrationHistory(data: OverseasRegistrationHistoryVO) {
return request({
url: '/rs/overseas/registration/history',
method: 'post',
data: data
});
}
/**
* 修改登记历史
*/
export function updateOverseasRegistrationHistory(data: OverseasRegistrationHistoryVO) {
return request({
url: '/rs/overseas/registration/history',
method: 'put',
data: data
});
}
/**
* 删除登记历史
*/
export function delOverseasRegistrationHistory(historyId: number | string | Array<number | string>) {
return request({
url: `/rs/overseas/registration/history/${historyId}`,
method: 'delete'
});
}
/**
* 导出登记历史
*/
export function exportOverseasRegistrationHistory(query: OverseasRegistrationHistoryQuery) {
return request({
url: '/rs/overseas/registration/history/export',
method: 'post',
data: query,
responseType: 'blob'
});
}
/**
* 完成出国登记(更新为历史记录)
*/
export function completeOverseasRegistration(registrationId: number | string, data: any) {
return request({
url: `/rs/overseas/registration/complete/${registrationId}`,
method: 'put',
data: data
});
}
// ========================= 统计 API =========================
/**
* 获取出国登记统计数据
*/
export function getOverseasRegistrationStats() {
return request({
url: '/rs/overseas/registration/stats',
method: 'get'
});
}
/**
* 获取出国登记趋势数据
*/
export function getOverseasRegistrationTrend(params: any) {
return request({
url: '/rs/overseas/registration/trend',
method: 'get',
params: params
});
}
// ========================= 字典数据 API =========================
/**
* 获取出行类型选项
*/
export function getTravelTypeOptions() {
return request({
url: '/rs/overseas/registration/travelTypeOptions',
method: 'get'
});
}
/**
* 获取登记状态选项
*/
export function getRegistrationStatusOptions() {
return request({
url: '/rs/overseas/registration/statusOptions',
method: 'get'
});
}
/**
* 获取完成状态选项
*/
export function getCompletionStatusOptions() {
return request({
url: '/rs/overseas/registration/completionStatusOptions',
method: 'get'
});
}
// ========================= 审批 API =========================
/**
* 审批通过出国登记
*/
export function approveOverseasRegistration(registrationId: number | string, data?: { approveNotes?: string }) {
return request({
url: `/rs/overseas/registration/approve/${registrationId}`,
method: 'put',
data: data
});
}
/**
* 审批拒绝出国登记
*/
export function rejectOverseasRegistration(registrationId: number | string, data: { rejectReason: string }) {
return request({
url: `/rs/overseas/registration/reject/${registrationId}`,
method: 'put',
data: data
});
}
/**
* 批量审批通过
*/
export function batchApproveOverseasRegistration(registrationIds: Array<number | string>, data?: { approveNotes?: string }) {
return request({
url: '/rs/overseas/registration/batch/approve',
method: 'put',
data: {
registrationIds,
...data
}
});
}
/**
* 批量审批拒绝
*/
export function batchRejectOverseasRegistration(registrationIds: Array<number | string>, data: { rejectReason: string }) {
return request({
url: '/rs/overseas/registration/batch/reject',
method: 'put',
data: {
registrationIds,
...data
}
});
}
@@ -0,0 +1,291 @@
import request from '@/utils/request'
// 党籍保留查询参数
export interface PartyRetentionQuery extends PageQuery {
/** 申请人姓名 */
name?: string
/** 身份证号 */
idNumber?: string
/** 工作部门 */
department?: string
/** 目的地 */
destination?: string
/** 申请状态 */
status?: string
/** 申请时间开始 */
applicationTimeStart?: string
/** 申请时间结束 */
applicationTimeEnd?: string
}
// 党籍保留历史查询参数(实际使用与 PartyRetentionQuery 相同的字段)
export interface PartyRetentionHistoryQuery extends PageQuery {
/** 申请人姓名 */
name?: string
/** 目的地 */
destination?: string
/** 状态(后端会强制设置为'2'只查询已通过的记录) */
status?: string
}
// 党籍保留VO
export interface PartyRetentionVO {
/** 保留ID */
retentionId: string
/** 申请人姓名 */
name: string
/** 性别 */
gender: string
/** 身份证号 */
idNumber: string
/** 工作部门 */
department: string
/** 配偶姓名 */
spouse?: string
/** 亲属姓名(探望对象) */
relativeName?: string
/** 目的地 */
destination: string
/** 出国目的 */
purpose: string
/** 出国开始时间 */
travelStartDate: string
/** 出国结束时间 */
travelEndDate: string
/** 停留天数 */
stayDays: number
/** 费用自理 */
selfFunded: string
/** 党支部 */
partyBranch: string
/** 申请日期 */
applicationDate: string
/** 申请状态 */
status: string
/** 申请状态文本 */
statusText: string
/** 申请时间 */
applicationTime: string
/** 创建时间 */
createTime: string
/** 更新时间 */
updateTime: string
}
// 党籍保留历史VO
export interface PartyRetentionHistoryVO {
/** 历史ID */
historyId: string
/** 申请人姓名 */
applicantName: string
/** 出国原因 */
travelReason: string
/** 目的地 */
destination: string
/** 保留开始时间 */
retentionStartDate: string
/** 保留结束时间 */
retentionEndDate: string
/** 完成状态 */
completionStatus: string
/** 完成状态文本 */
completionStatusText: string
/** 创建时间 */
createTime: string
}
// 党籍保留表单
export interface PartyRetentionForm {
/** 保留ID */
retentionId?: string
/** 申请人姓名 */
name: string
/** 配偶姓名 */
spouse?: string
/** 亲属姓名(探望对象) */
relativeName?: string
/** 目的地 */
destination: string
/** 出国目的 */
purpose: string
/** 出国时间范围 */
travelPeriod?: string[]
/** 出国开始时间 */
travelStartDate?: string
/** 出国结束时间 */
travelEndDate?: string
/** 停留天数 */
stayDays: number
/** 费用自理 */
selfFunded: string
/** 党支部 */
partyBranch: string
/** 申请日期 */
applicationDate: string
/** 请求批准内容 */
requestApproval?: string
/** 最终批准内容 */
finalApproval?: string
}
// 查询党籍保留列表
export function getPartyRetentionList(query: PartyRetentionQuery) {
return request({
url: '/rs/party/retention/list',
method: 'get',
params: query
})
}
// 查询党籍保留详细
export function getPartyRetention(retentionId: string) {
return request({
url: '/rs/party/retention/' + retentionId,
method: 'get'
})
}
// 新增党籍保留
export function addPartyRetention(data: PartyRetentionForm) {
return request({
url: '/rs/party/retention',
method: 'post',
data: data
})
}
// 修改党籍保留
export function updatePartyRetention(data: PartyRetentionForm) {
return request({
url: '/rs/party/retention',
method: 'put',
data: data
})
}
// 删除党籍保留
export function delPartyRetention(retentionId: string) {
return request({
url: '/rs/party/retention/' + retentionId,
method: 'delete'
})
}
// 提交党籍保留申请
export function submitPartyRetention(data: { retentionId: string }) {
return request({
url: '/rs/party/retention/submit/' + data.retentionId,
method: 'put'
})
}
// 撤回党籍保留申请
export function cancelPartyRetention(retentionId: string) {
return request({
url: '/rs/party/retention/withdraw/' + retentionId,
method: 'put'
})
}
// 新增并提交党籍保留申请
export function addAndSubmitPartyRetention(data: PartyRetentionForm) {
return request({
url: '/rs/party/retention/saveAndSubmit',
method: 'post',
data: data
})
}
// 导出党籍保留列表
export function exportPartyRetention(query: PartyRetentionQuery) {
return request({
url: '/rs/party/retention/export',
method: 'post',
data: query,
responseType: 'blob'
})
}
// 查询党籍保留历史列表
export function getPartyRetentionHistoryList(query: PartyRetentionHistoryQuery) {
return request({
url: '/rs/party/retention/history/list',
method: 'get',
params: query
})
}
// 查询党籍保留历史详细
export function getPartyRetentionHistory(historyId: string) {
return request({
url: '/rs/party/retention/history/' + historyId,
method: 'get'
})
}
// 修改党籍保留历史
export function updatePartyRetentionHistory(data: any) {
return request({
url: '/rs/party/retention/history',
method: 'put',
data: data
})
}
// 导出党籍保留历史
export function exportPartyRetentionHistory(query: PartyRetentionHistoryQuery) {
return request({
url: '/rs/party/retention/history/export',
method: 'post',
data: query,
responseType: 'blob'
})
}
// 党籍保留审批查询参数
export interface PartyRetentionApprovalQuery extends PageQuery {
/** 申请人姓名 */
name?: string
/** 身份证号 */
idNumber?: string
/** 工作部门 */
department?: string
/** 目的地 */
destination?: string
/** 审批状态 */
status?: string
}
// 审批请求参数
export interface ApprovalRequest {
/** 保留ID */
retentionId: string
/** 审批意见 */
approvalOpinion: string
/** 是否通过 */
approved: boolean
}
// 查询待审批党籍保留列表
export function getPendingPartyRetentionList(query: PartyRetentionApprovalQuery) {
return request({
url: '/rs/party/retention/list',
method: 'get',
params: {
...query,
status: '1' // 只查询待审批状态
}
})
}
// 审批党籍保留
export function approvePartyRetention(data: ApprovalRequest) {
return request({
url: `/rs/party/retention/approve/${data.retentionId}`,
method: 'put',
params: {
approvalOpinion: data.approvalOpinion,
approved: data.approved
}
})
}
@@ -0,0 +1,390 @@
# 党籍保留API路径修正完成报告
## 📋 问题概述
**发现时间**: 2025-10-08
**问题现象**:
- 点击"保存并提交"按钮提示保存失败
- 浏览器F12 Network显示:`HTTP 405 - Request method 'POST' is not supported`
**问题根源**: 前端API路径与后端Controller接口路径不匹配
---
## 🔍 问题分析
### HTTP 405错误解释
- **405 Method Not Allowed**: 请求方法不被允许
- **常见原因**:
1. 前端请求路径错误,导致匹配到不支持该方法的接口
2. 前端请求方法与后端定义的方法不一致
3. 路径参数传递方式不正确
### 具体问题定位
通过对比前后端代码,发现以下3个接口存在路径或方法不匹配:
| 功能 | 前端路径/方法 | 后端路径/方法 | 状态 |
|------|--------------|--------------|------|
| 保存并提交 | `/addAndSubmit` POST | `/saveAndSubmit` POST | ❌ 路径错误 |
| 提交申请 | `/submit` POST + Body | `/submit/{retentionId}` PUT + Path | ❌ 方法和参数错误 |
| 撤回申请 | `/cancel/{retentionId}` PUT | `/withdraw/{retentionId}` PUT | ❌ 路径错误 |
---
## ✅ 修正内容
### 1. 保存并提交接口修正
**文件**: `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
})
}
```
**修改后**:
```typescript
// 新增并提交党籍保留申请
export function addAndSubmitPartyRetention(data: PartyRetentionForm) {
return request({
url: '/rs/party/retention/saveAndSubmit', // ✅ 正确路径
method: 'post',
data: data
})
}
```
**后端接口**:
```java
@PostMapping("/saveAndSubmit")
public R<Void> saveAndSubmit(@Validated(AddGroup.class) @RequestBody RsPartyMembershipRetentionBo bo)
```
---
### 2. 提交申请接口修正
**文件**: `web/src/api/rs/party-membership-retention.ts`
**修改前**:
```typescript
// 提交党籍保留申请
export function submitPartyRetention(data: { retentionId: string }) {
return request({
url: '/rs/party/retention/submit', // ❌ 缺少路径参数
method: 'post', // ❌ 错误方法
data: data // ❌ 应该用路径参数
})
}
```
**修改后**:
```typescript
// 提交党籍保留申请
export function submitPartyRetention(data: { retentionId: string }) {
return request({
url: '/rs/party/retention/submit/' + data.retentionId, // ✅ 添加路径参数
method: 'put' // ✅ 改为PUT方法
})
}
```
**后端接口**:
```java
@PutMapping("/submit/{retentionId}")
public R<Void> submit(@NotNull(message = "主键不能为空") @PathVariable Long retentionId)
```
---
### 3. 撤回申请接口修正
**文件**: `web/src/api/rs/party-membership-retention.ts`
**修改前**:
```typescript
// 撤回党籍保留申请
export function cancelPartyRetention(retentionId: string) {
return request({
url: '/rs/party/retention/cancel/' + retentionId, // ❌ 错误路径
method: 'put'
})
}
```
**修改后**:
```typescript
// 撤回党籍保留申请
export function cancelPartyRetention(retentionId: string) {
return request({
url: '/rs/party/retention/withdraw/' + retentionId, // ✅ 正确路径
method: 'put'
})
}
```
**后端接口**:
```java
@PutMapping("/withdraw/{retentionId}")
public R<Void> withdraw(@NotNull(message = "主键不能为空") @PathVariable Long retentionId)
```
---
## 📊 完整的前后端接口对照表
### 党籍保留主接口
| 序号 | 功能 | 前端方法 | 前端路径 | HTTP方法 | 后端路径 | 后端方法 | 状态 |
|------|------|---------|---------|---------|---------|---------|------|
| 1 | 查询列表 | `getPartyRetentionList` | `/list` | GET | `/list` | `list()` | ✅ 一致 |
| 2 | 查询详情 | `getPartyRetention` | `/{retentionId}` | GET | `/{retentionId}` | `getInfo()` | ✅ 一致 |
| 3 | 根据登记ID查询 | - | - | - | `/registration/{registrationId}` | `getByRegistrationId()` | ⚠️ 前端未实现 |
| 4 | 根据申请ID查询 | - | - | - | `/application/{applicationId}` | `getByApplicationId()` | ⚠️ 前端未实现 |
| 5 | 新增保留 | `addPartyRetention` | `/` | POST | `/` | `add()` | ✅ 一致 |
| 6 | 保存并提交 | `addAndSubmitPartyRetention` | `/saveAndSubmit` | POST | `/saveAndSubmit` | `saveAndSubmit()` | ✅ 已修正 |
| 7 | 修改保留 | `updatePartyRetention` | `/` | PUT | `/` | `edit()` | ✅ 一致 |
| 8 | 删除保留 | `delPartyRetention` | `/{retentionId}` | DELETE | `/{retentionIds}` | `remove()` | ✅ 一致 |
| 9 | 提交申请 | `submitPartyRetention` | `/submit/{retentionId}` | PUT | `/submit/{retentionId}` | `submit()` | ✅ 已修正 |
| 10 | 撤回申请 | `cancelPartyRetention` | `/withdraw/{retentionId}` | PUT | `/withdraw/{retentionId}` | `withdraw()` | ✅ 已修正 |
| 11 | 审批申请 | - | - | - | `/approve/{retentionId}` | `approve()` | ⚠️ 前端未实现 |
| 12 | 导出列表 | `exportPartyRetention` | `/export` | POST | `/export` | `export()` | ✅ 一致 |
### 党籍保留历史接口
| 序号 | 功能 | 前端方法 | 前端路径 | HTTP方法 | 后端路径 | 后端方法 | 状态 |
|------|------|---------|---------|---------|---------|---------|------|
| 1 | 查询历史列表 | `getPartyRetentionHistoryList` | `/history/list` | GET | `/history/list` | `listHistory()` | ✅ 一致 |
| 2 | 查询历史详情 | `getPartyRetentionHistory` | `/history/{historyId}` | GET | `/history/{historyId}` | `getHistoryInfo()` | ✅ 一致 |
| 3 | 修改历史 | `updatePartyRetentionHistory` | `/history` | PUT | `/history` | `editHistory()` | ✅ 一致 |
| 4 | 导出历史 | `exportPartyRetentionHistory` | `/history/export` | POST | `/history/export` | `exportHistory()` | ✅ 一致 |
---
## 🎯 REST API规范总结
### RESTful API设计原则
| HTTP方法 | 操作 | 路径示例 | 说明 |
|---------|------|---------|------|
| GET | 查询 | `/list`, `/{id}` | 幂等操作,不修改数据 |
| POST | 新增 | `/`, `/saveAndSubmit` | 创建新资源 |
| PUT | 修改 | `/`, `/{id}`, `/submit/{id}` | 更新资源(幂等) |
| DELETE | 删除 | `/{id}`, `/{ids}` | 删除资源(幂等) |
### 参数传递方式
| 参数类型 | 使用场景 | 前端写法 | 后端注解 |
|---------|---------|---------|---------|
| 路径参数 | 资源ID | `url: '/api/{id}'` | `@PathVariable Long id` |
| 查询参数 | 过滤条件 | `params: { name, status }` | `@RequestParam` 或 直接接收Query对象 |
| 请求体 | 复杂对象 | `data: formData` | `@RequestBody FormBO bo` |
### 本次修正的重点
1. **路径命名统一**: `saveAndSubmit` 而不是 `addAndSubmit`
2. **方法类型匹配**: 修改/提交/撤回操作使用 `PUT` 方法
3. **参数位置正确**:
- 资源ID应该放在路径中:`/submit/{retentionId}`
- 复杂对象放在请求体中:`@RequestBody Bo bo`
---
## ⚠️ 待补充的功能
### 前端缺失的接口(建议补充)
#### 1. 根据登记ID查询党籍保留
```typescript
// 根据登记ID查询党籍保留
export function getPartyRetentionByRegistrationId(registrationId: string) {
return request({
url: '/rs/party/retention/registration/' + registrationId,
method: 'get'
})
}
```
**使用场景**: 从出国登记页面跳转到党籍保留页面,自动加载对应的党籍保留信息
#### 2. 根据申请ID查询党籍保留
```typescript
// 根据申请ID查询党籍保留
export function getPartyRetentionByApplicationId(applicationId: string) {
return request({
url: '/rs/party/retention/application/' + applicationId,
method: 'get'
})
}
```
**使用场景**: 从出国申请页面跳转到党籍保留页面,自动加载对应的党籍保留信息
#### 3. 审批党籍保留申请
```typescript
// 审批党籍保留申请
export function approvePartyRetention(data: {
retentionId: string
approvalOpinion: string
approved: boolean
}) {
return request({
url: '/rs/party/retention/approve/' + data.retentionId,
method: 'put',
params: {
approvalOpinion: data.approvalOpinion,
approved: data.approved
}
})
}
```
**使用场景**: 管理员审批党籍保留申请
---
## ✅ 测试清单
### 基础功能测试
- [ ] 1. 查看党籍保留列表
- [ ] 2. 查看党籍保留详情
- [ ] 3. 新增党籍保留(仅保存草稿)
- [ ] 4. 新增并提交党籍保留(保存+提交)✅ **已修正**
- [ ] 5. 编辑草稿状态的党籍保留
- [ ] 6. 删除草稿状态的党籍保留
- [ ] 7. 提交草稿状态的党籍保留 ✅ **已修正**
- [ ] 8. 撤回已提交的党籍保留 ✅ **已修正**
- [ ] 9. 导出党籍保留列表
### 历史记录功能测试
- [ ] 1. 查看党籍保留历史列表
- [ ] 2. 查看党籍保留历史详情
- [ ] 3. 编辑党籍保留历史
- [ ] 4. 导出党籍保留历史
### 关联查询测试(待实现)
- [ ] 1. 根据登记ID查询党籍保留
- [ ] 2. 根据申请ID查询党籍保留
### 审批功能测试(待实现)
- [ ] 1. 审批通过党籍保留申请
- [ ] 2. 审批拒绝党籍保留申请
---
## 🚀 部署和测试步骤
### 1. 前端热更新(开发环境)
```bash
# 开发环境无需重启,Vite会自动热更新
# 保存文件后刷新浏览器即可
```
### 2. 清除浏览器缓存
- 按 `Ctrl + Shift + Delete`(Windows)或 `Cmd + Shift + Delete`(Mac)
- 选择"缓存的图像和文件"
- 点击"清除数据"
### 3. 刷新页面测试
1. 访问"人事管理 → 出国党籍保留"菜单
2. 点击"党籍保留"选项卡
3. 点击"新增登记"按钮
4. 填写表单
5. 点击"保存并提交"按钮
6. 预期结果:✅ 提示"保存并提交成功"
### 4. 测试其他修正的接口
- **提交功能**: 保存草稿后,点击"提交"按钮
- **撤回功能**: 已提交状态,点击"撤回"按钮
---
## 📝 修正统计
### 修正文件
- **文件**: `web/src/api/rs/party-membership-retention.ts`
- **修正接口数量**: 3个
- `addAndSubmitPartyRetention` - 路径修正
- `submitPartyRetention` - 路径+方法修正
- `cancelPartyRetention` - 路径修正
### 修正代码行数
- **修改行数**: 9行
- **工作量**: 约20分钟
---
## 💡 经验总结
### 1. 前后端接口对接规范
- ✅ **统一命名**: 前后端接口路径和方法名保持一致
- ✅ **REST规范**: 严格遵循RESTful API设计规范
- ✅ **参数位置**: 明确区分路径参数、查询参数、请求体
- ✅ **文档同步**: 前后端接口文档实时同步
### 2. 接口调试技巧
- 🔍 **F12 Network**: 查看请求路径、方法、参数
- 🔍 **Preview/Response**: 查看错误信息和响应数据
- 🔍 **Headers**: 确认Content-Type、Token等请求头
- 🔍 **对比代码**: 前端API文件 vs 后端Controller文件
### 3. 常见HTTP状态码
| 状态码 | 说明 | 可能原因 |
|--------|------|---------|
| 200 | 成功 | 请求正常处理 |
| 400 | 请求错误 | 参数格式错误、校验失败 |
| 401 | 未授权 | Token过期或无效 |
| 403 | 禁止访问 | 无权限 |
| 404 | 未找到 | 路径错误 |
| 405 | 方法不允许 | HTTP方法错误或路径错误 |
| 500 | 服务器错误 | 后端代码异常 |
### 4. 防范措施
- ✅ 使用TypeScript类型定义,避免参数错误
- ✅ 编写接口对照文档,前后端统一维护
- ✅ 使用API测试工具(Postman/Apifox)先验证后端接口
- ✅ 前端开发时对照后端Controller逐一核对
---
## 📞 后续工作
### 立即可测试
1. ✅ 测试"保存并提交"功能
2. ✅ 测试"提交申请"功能
3. ✅ 测试"撤回申请"功能
### 建议补充
1. ⏳ 补充"根据登记ID/申请ID查询"前端接口
2. ⏳ 实现"审批"功能的前端界面和API
3. ⏳ 编写完整的API接口文档
4. ⏳ 编写自动化测试脚本
---
## ✅ 完成确认
- [x] ✅ 定位问题原因(HTTP 405错误)
- [x] ✅ 修正"保存并提交"接口路径
- [x] ✅ 修正"提交申请"接口路径和方法
- [x] ✅ 修正"撤回申请"接口路径
- [x] ✅ 生成前后端接口对照表
- [x] ✅ 编写修正说明文档
- [ ] ⏳ 执行功能测试
- [ ] ⏳ 补充缺失的前端接口
---
**状态**: 🎉 **API路径修正已完成!可以进行功能测试!**
**修正人**: weizzzz
**完成时间**: 2025-10-08
**版本**: v1.0