输入文件:
- 租赁任务考核_2026年{1,2,3}月.xlsx (考核源数据)
- {1,2}月.xlsx (客户盈亏表)
- 车辆里程考核与奖金发放规则(V.1.2).docx
输出文件:
- 里程任务考核_{1,2,3}月核算.xlsx (月度核算结果)
- 里程任务考核_Q1汇总.xlsx (含车辆台账)
- 3月客户盈亏表(待填写).xlsx (模版)
.claude_memory: 项目记忆(规则/偏好/架构/测试车辆)
.claude_plans: 历次计划文件
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
235 lines
8.3 KiB
Markdown
235 lines
8.3 KiB
Markdown
# 合同管理全功能实现计划
|
||
|
||
## Context
|
||
|
||
原型有7个页面(列表、新增、查看、新增车辆、续签、变更三方、转正式),当前前端只实现了列表+新增/编辑的基础框架。需要补全所有功能,包括后端缺失字段/接口。
|
||
|
||
## 架构决策
|
||
|
||
1. **单组件多模式**: form.vue 通过 `mode` 支持 7 种模式(create/edit/view/renew/convertThirdParty/convertFormal/addVehicle),不创建额外组件
|
||
2. **服务费项目**: 在车辆表格中使用可展开行(expandedRowRender)显示服务费明细
|
||
3. **附件上传**: 使用现有 `uploadFile` API (`api/infra/file/index.ts`)
|
||
|
||
---
|
||
|
||
## Phase 1: 后端变更
|
||
|
||
### 1.1 SQL 迁移 — `asset_contract` 新增6字段
|
||
|
||
```sql
|
||
ALTER TABLE asset_contract
|
||
ADD COLUMN hydrogen_bearer VARCHAR(20) COMMENT '氢费承担方',
|
||
ADD COLUMN hydrogen_payment_method VARCHAR(20) COMMENT '氢气付款方式',
|
||
ADD COLUMN hydrogen_prepay DECIMAL(12,2) COMMENT '氢气预付款',
|
||
ADD COLUMN hydrogen_return_price DECIMAL(12,2) COMMENT '退还车氢气单价',
|
||
ADD COLUMN billing_method VARCHAR(50) COMMENT '账单计算方式',
|
||
ADD COLUMN main_vehicle_type VARCHAR(50) COMMENT '主车型';
|
||
```
|
||
|
||
### 1.2 更新 ContractDO
|
||
|
||
文件: `dal/dataobject/contract/ContractDO.java`
|
||
添加: `hydrogenBearer`, `hydrogenPaymentMethod`, `hydrogenPrepay`(BigDecimal), `hydrogenReturnPrice`(BigDecimal), `billingMethod`, `mainVehicleType`
|
||
|
||
### 1.3 更新 ContractBaseVO
|
||
|
||
文件: `controller/admin/contract/vo/ContractBaseVO.java`
|
||
添加同样6个字段(自动流入 SaveReqVO/RespVO/DetailRespVO)
|
||
|
||
### 1.4 更新 ContractPageReqVO
|
||
|
||
文件: `controller/admin/contract/vo/ContractPageReqVO.java`
|
||
添加: `signingCompany`(String), `businessManagerId`(Long), `creator`(String)
|
||
|
||
### 1.5 更新 ContractMapper.selectPage
|
||
|
||
文件: `dal/mysql/contract/ContractMapper.java`
|
||
添加3个查询条件: `.eqIfPresent(signingCompany)`, `.eqIfPresent(businessManagerId)`, `.likeIfPresent(creator)`
|
||
|
||
### 1.6 ContractRespVO 增加 vehicleCount/deliveredCount
|
||
|
||
文件: `controller/admin/contract/vo/ContractRespVO.java`
|
||
添加: `Integer vehicleCount`, `Integer deliveredCount`
|
||
在 Controller 的 page 方法中查询填充
|
||
|
||
### 1.7 新增 ContractAttachmentVO
|
||
|
||
新文件: `controller/admin/contract/vo/ContractAttachmentVO.java`
|
||
字段: `id`, `attachmentType`, `fileName`, `fileUrl`, `fileSize`, `uploadTime`
|
||
|
||
### 1.8 更新 ContractDetailRespVO
|
||
|
||
添加 `List<ContractAttachmentVO> attachments` 字段
|
||
|
||
### 1.9 新增错误码
|
||
|
||
文件: `enums/ErrorCodeConstants.java` (从 1_008_005_010 开始)
|
||
- CONTRACT_STATUS_NOT_ALLOW_CONVERT
|
||
- CONTRACT_STATUS_NOT_ALLOW_ADD_VEHICLE
|
||
- CONTRACT_TYPE_NOT_TRIAL
|
||
|
||
### 1.10 新增4个 Controller 端点
|
||
|
||
文件: `controller/admin/contract/ContractController.java`
|
||
|
||
| 端点 | 方法 | 说明 |
|
||
|------|------|------|
|
||
| POST /convert-to-third-party | convertToThirdParty(id, ContractSaveReqVO) | 从原合同创建三方合同 |
|
||
| POST /convert-to-formal | convertToFormal(id, ContractSaveReqVO) | 试用合同转正式 |
|
||
| POST /add-vehicle | addVehicle(id, List<VehicleSaveVO>) | 往现有合同追加车辆 |
|
||
| POST /upload-seal | uploadSeal(id, fileUrl, fileName) | 上传盖章附件 |
|
||
|
||
### 1.11 ContractService 新增方法
|
||
|
||
文件: `service/contract/ContractService.java` + `ContractServiceImpl.java`
|
||
|
||
- `convertToThirdParty`: 验证合同进行中 → 创建新合同(thirdPartyEnabled=true, originalContractId) → 记录变更历史
|
||
- `convertToFormal`: 验证试用合同+进行中 → 创建正式合同(type=2) → 原合同标记终止 → 记录变更历史
|
||
- `addVehiclesToContract`: 验证合同进行中 → 追加车辆+服务费 → 记录变更历史
|
||
- `uploadSealedContract`: 创建 ContractAttachmentDO(type=2)
|
||
|
||
---
|
||
|
||
## Phase 2: 前端 API
|
||
|
||
文件: `api/asset/contract.ts`
|
||
|
||
### 2.1 新增接口类型
|
||
|
||
```typescript
|
||
ContractAuthorized { id?, name, phone, idCard }
|
||
ContractAttachment { id?, attachmentType, fileName, fileUrl, fileSize?, uploadTime? }
|
||
ContractVehicleService { id?, serviceName, serviceFee, effectiveDate? }
|
||
```
|
||
|
||
### 2.2 更新 Contract 接口
|
||
|
||
添加: `hydrogenBearer`, `hydrogenPaymentMethod`, `hydrogenPrepay`, `hydrogenReturnPrice`, `billingMethod`, `mainVehicleType`, `authorizedPersons`, `attachments`
|
||
|
||
### 2.3 更新 ContractVehicle 接口
|
||
|
||
添加: `services?: ContractVehicleService[]`
|
||
|
||
### 2.4 新增 API 函数
|
||
|
||
`convertToThirdParty`, `convertToFormal`, `addVehicle`, `uploadSeal`
|
||
|
||
---
|
||
|
||
## Phase 3: 前端 data.ts
|
||
|
||
文件: `views/asset/contract/data.ts`
|
||
|
||
### 3.1 搜索表单增加字段
|
||
|
||
- `businessDeptId` — Select (业务部门)
|
||
- `businessManagerId` — Select (业务负责人)
|
||
- `creator` — Input (创建人)
|
||
|
||
### 3.2 新增服务费类型常量
|
||
|
||
`SERVICE_TYPE_OPTIONS` — 42项(代处理费用、罚款、违章处理违约金...)
|
||
|
||
---
|
||
|
||
## Phase 4: 前端 index.vue
|
||
|
||
文件: `views/asset/contract/index.vue`
|
||
|
||
### 4.1 新增操作处理函数
|
||
|
||
- `handleView(row)` → 打开 form modal, mode='view'
|
||
- `handleRenew(row)` → 打开 form modal, mode='renew'(替换占位)
|
||
- `handleConvertThirdParty(row)` → 打开 form modal, mode='convertThirdParty'
|
||
- `handleConvertFormal(row)` → 打开 form modal, mode='convertFormal'
|
||
- `handleAddVehicle(row)` → 打开 form modal, mode='addVehicle'
|
||
|
||
### 4.2 扩展 getRowActions
|
||
|
||
| 条件 | 操作 |
|
||
|------|------|
|
||
| 始终 | 查看 → handleView |
|
||
| draft/rejected/withdrawn | 编辑、提交审批、删除 |
|
||
| approving | 撤回审批 |
|
||
| contractStatus=2 (进行中) | 新增车辆、续签、终止 |
|
||
| contractStatus=2 且 !thirdPartyEnabled | 变更为三方 |
|
||
| contractStatus=2 且 contractType=1 (试用) | 转正式 |
|
||
| contractStatus=3 (已到期) | 续签 |
|
||
|
||
---
|
||
|
||
## Phase 5: 前端 form.vue 重构
|
||
|
||
文件: `views/asset/contract/modules/form.vue`
|
||
|
||
### 5.1 模式管理
|
||
|
||
```typescript
|
||
type FormMode = 'create' | 'edit' | 'view' | 'renew' | 'convertThirdParty' | 'convertFormal' | 'addVehicle'
|
||
const mode = ref<FormMode>('create')
|
||
const isReadOnly = computed(() => mode.value === 'view')
|
||
const isContractReadOnly = computed(() => ['view', 'addVehicle'].includes(mode.value))
|
||
```
|
||
|
||
### 5.2 Modal 标题
|
||
|
||
根据 mode 显示: 新增合同 / 编辑合同 / 查看合同 / 续签合同 / 变更为三方合同 / 转正式合同 / 新增车辆
|
||
|
||
### 5.3 onOpenChange 分模式加载
|
||
|
||
- `create`: 清空所有表单
|
||
- `edit`: 获取详情 → 填充全部
|
||
- `view`: 获取详情 → 填充全部 → 禁用
|
||
- `renew`: 获取详情 → 清ID → 修改contractCode后缀 → 可编辑
|
||
- `convertThirdParty`: 获取详情 → 清ID → 设thirdPartyEnabled=true
|
||
- `convertFormal`: 获取详情 → 清ID → 设contractType=2 → 固定
|
||
- `addVehicle`: 获取详情 → 合同信息只读 → 清空车辆列表
|
||
|
||
### 5.4 onConfirm 分模式提交
|
||
|
||
各模式调用对应 API (create/update/renew/convertToThirdParty/convertToFormal/addVehicle)
|
||
|
||
### 5.5 表单禁用控制
|
||
|
||
- view模式: 所有表单 disabled, 隐藏确认按钮
|
||
- addVehicle模式: 客户/合同/三方表单 disabled, 仅车辆可编辑
|
||
- convertFormal模式: contractType 字段 disabled
|
||
|
||
### 5.6 车辆服务费项目
|
||
|
||
使用 Ant Design Table 的 `expandedRowRender` slot:
|
||
- 展开行显示子表格: 服务名称(Select), 服务费(InputNumber), 生效日期(DatePicker)
|
||
- 支持新增/删除行
|
||
- serviceCost 列自动计算 = sum(services[].serviceFee)
|
||
|
||
### 5.7 附件上传集成
|
||
|
||
- 上传时调用 `uploadFile` 获取 fileUrl
|
||
- 提交时将 attachments 数组(type=1 原件)随合同数据保存
|
||
- 查看模式展示附件列表,可下载
|
||
- 续签/转正式:原合同附件标记 isOriginal=true 不可删除
|
||
|
||
### 5.8 氢气/计费数据绑定
|
||
|
||
将 `hydrogenBearer`, `hydrogenPaymentMethod`, `hydrogenPrepay`, `hydrogenReturnPrice`, `billingMethod` 纳入保存数据;编辑时回显
|
||
|
||
---
|
||
|
||
## 实施顺序
|
||
|
||
1. **后端**: SQL迁移 → DO/VO更新 → Mapper更新 → Service新增方法 → Controller新增端点 → 编译验证
|
||
2. **前端API**: 更新接口和函数
|
||
3. **前端data.ts**: 搜索表单 + 服务费常量
|
||
4. **前端form.vue**: 模式管理 → 禁用控制 → 分模式加载/提交 → 服务费展开行 → 附件上传 → 氢气/计费绑定
|
||
5. **前端index.vue**: 新操作函数 → getRowActions 扩展
|
||
6. **验证**: `mvn compile` + `pnpm run build:antd`
|
||
|
||
---
|
||
|
||
## 验证
|
||
|
||
- 后端: `mvn compile` 无报错
|
||
- 前端: `pnpm run build:antd` 无报错
|
||
- SQL: 通过 PyMySQL 执行 ALTER TABLE
|
||
- 功能: 7种模式逐一打开/提交验证
|