You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
cz-hjjc-budget/docs/直接支付页面功能说明.md

428 lines
11 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 直接支付页面功能说明
## 页面概述
**页面路径**: `/payment/direct-payment?payment_type=direct`
**组件文件**: `src/views/payment/DirectPayment.vue` (包装组件)
**实际组件**: `src/views/payment/CreatePayment.vue` (核心组件)
直接支付页面用于创建无需审批流程的支付申请,适用于水电费、工会经费、人员工资等常规支付场景。
---
## 功能流程
### 步骤概览
直接支付页面采用**三步向导式**流程:
1. **步骤0选择支付分类** - 通过思维导图选择支付分类
2. **步骤1填写表单信息** - 填写金额和模板配置的字段
3. **步骤2发起主流程** - 发起主审批流程(如果有配置)或确认提交
---
## 详细功能说明
### 步骤0选择支付分类
#### 功能描述
- 使用 D3.js 渲染思维导图(树状图)展示支付分类层级结构
- 用户点击叶子节点选择支付分类
- 选择后自动进入下一步
#### 数据加载
- **API**: `GET /budget/payment-categories` (树形结构)
- **参数**: `payment_type=direct` (筛选直接支付分类)
#### 关键逻辑
```javascript
// 判断是否为直接支付
const isDirectPayment = computed(() => {
return route.path === '/payment/direct-payment' ||
paymentType.value === 'direct'
})
```
---
### 步骤1填写表单信息
#### 1.1 支付金额
**功能特性**:
- 必填字段支持小数点后2位
- 直接支付模式下显示**金额大写**(如:壹万贰仟叁佰元整)
- 支持金额限制条件验证(`amount_limit_conditions`
- 直接支付模式下隐藏数字输入框的增减按钮
**金额限制条件**:
- 支持多种比较操作:`lt`(小于)、`lte`(小于等于)、`gt`(大于)、`gte`(大于等于)
- 可配置多个条件所有条件需同时满足AND逻辑
- 实时验证并显示提示信息
**数据字段**:
```javascript
formData.amount // 支付金额Number类型
```
#### 1.2 合同关联(可选)
**触发条件**:
- 支付分类配置了 `need_contract: true`
- 仅直接支付模式显示
**功能特性**:
- 点击"选择合同"按钮打开合同选择器
- 显示已选择合同的详细信息:
- 合同名称
- 合同总额
- 已支付次数
- 已支付金额
- 剩余金额(闭口合同显示)
- 支持重新选择和清除
**合同验证**:
- **开口合同**:不允许用于直接支付,提示用户使用非直接支付
- **闭口合同**:验证本次支付金额不能超过合同剩余金额
**数据字段**:
```javascript
selectedContract.value // 选中的合同对象
contractRemainingAmount // 合同剩余金额(计算属性)
```
#### 1.3 动态模板字段
根据支付分类配置的模板元素动态渲染表单字段。
**支持的字段类型**:
1. **审批流程** (`approval_flow`)
- 非主审批流程下拉选择OA模型
- 主审批流程在步骤2中通过iframe处理
2. **会议纪要** (`meeting_minutes`)
- 使用专用组件 `MeetingMinutesField`
- 支持会议信息录入
3. **勾选清单** (`checklist`)
- 多选复选框
- 未勾选项需填写备注说明
- 支持自定义选项和备注验证
4. **明细表格** (`detail_table`)
- 动态添加/删除行
- 支持多种字段类型:
- 文本 (`text`)
- 数字 (`number`)
- 日期 (`date`)
- 多行文本 (`textarea`)
- 部门选择 (`department`)
- 用户选择 (`user`)
5. **表单元素** (`form_element`)
- 单行文本 (`single_line_text`)
- 多行文本 (`multi_line_text`)
- 附件上传 (`attachment`)
- 支持多文件上传最多10个
- 文件大小限制10MB
- 支持格式JPG/PNG/PDF/DOC/DOCX/XLS/XLSX
**字段显示条件**:
- 支持基于金额的显示条件(`display_conditions`
- 可配置基于 `contract_total_amount`(合同总金额)或 `current_payment_amount`(本次支付金额)的条件
- 支持比较操作:`lt`、`lte`、`gt`、`gte`、`eq`
**数据字段**:
```javascript
formData.fields = {
[elementId]: value, // 字段值
[elementId]: [file1, file2], // 附件类型为数组
[elementId]: [{field1: value1, field2: value2}], // 明细表格为对象数组
}
```
#### 1.4 文件上传
**上传配置**:
- **接口**: `POST /api/upload-file`
- **请求头**: `Authorization: Bearer {token}`
- **文件限制**:
- 大小:≤ 10MB
- 格式JPG/PNG/PDF/DOC/DOCX/XLS/XLSX
**上传成功处理**:
```javascript
{
name: "文件名",
url: "文件URL",
uid: "唯一标识"
}
```
---
### 步骤2发起主流程
#### 功能描述
- 所有支付类型(包括直接支付)都会进入此步骤
- 如果支付分类配置了主审批流程显示OA流程创建iframe
- 如果未配置主审批流程,显示提示信息,用户可直接提交
#### 主审批流程处理
**情况1配置了主审批流程**
- 显示主审批流程信息
- 加载OA流程创建iframe
- 用户需要在OA页面完成流程创建
- 流程创建成功后通过postMessage返回flow_id
- 提交时会验证是否已创建流程
**情况2未配置主审批流程**
- 显示提示:"当前分类未配置主审批流程"
- 用户可以直接点击"提交"按钮完成提交
- 提交时`oa_flow_id`为`null`
#### 数据字段
```javascript
mainApprovalFlow.value // 主审批流程配置对象
oaFlowId.value // OA流程ID从postMessage接收
```
---
## 数据提交流程
### 提交前验证
1. **表单验证**
- 必填字段检查
- 金额格式验证
- 明细表格行数据验证
- 勾选清单备注验证
2. **金额限制条件验证**
- 检查是否满足分类配置的金额限制条件
3. **合同验证**(如需要)
- 合同类型验证(开口合同不允许)
- 支付金额不能超过合同剩余金额
4. **主审批流程验证**
- 如果配置了主审批流程检查是否已创建OA流程
- 如果未配置主审批流程,允许直接提交
### 提交数据构建
#### 直接支付数据结构
```javascript
{
payment_category_id: Number, // 支付分类ID
amount: Number, // 支付金额
fields: Object, // 模板字段数据
oa_flow_id: Number | null, // OA流程ID直接支付通常为null
// Step2后端已切换 1 Payment = 1 明细,直接写 Payment 级字段(不再传 details
contract_id: Number | null, // 关联合同IDneed_contract=true时必填
}
```
#### 完整提交示例
```javascript
// 直接支付 + 关联合同
{
payment_category_id: 123,
amount: 50000.00,
fields: {
456: "备注信息",
789: [
{name: "文件1.pdf", url: "/uploads/xxx.pdf", uid: "xxx"}
],
101: [
{field1: "值1", field2: "值2"}
]
},
oa_flow_id: null,
contract_id: 999
}
// 直接支付 + 未关联合同
{
payment_category_id: 123,
amount: 50000.00,
fields: {
456: "备注信息"
},
oa_flow_id: null,
contract_id: null
}
```
### API调用
**接口**: `POST /budget/payments`
**API方法**: `paymentAPI.create(paymentData)`
### 提交后处理
1. **成功响应**
- 显示成功提示:"申请付款提交成功"
- 跳转到支付查询页面:`/payment/payment-query`
2. **失败处理**
- 显示错误提示
- 保持当前页面,允许用户修改后重新提交
---
## 关键计算属性和方法
### 金额大写转换
```javascript
const amountUppercase = computed(() => {
if (!isDirectPayment.value) return ''
const n = Number(formData.amount)
if (!Number.isFinite(n) || n <= 0) return ''
return toChineseMoneyUppercase(n) // 转换为中文大写
})
```
### 合同剩余金额
```javascript
const contractRemainingAmount = computed(() => {
if (!selectedContract.value || selectedContract.value.amount_type !== 'fixed') {
return 0
}
const total = Number(selectedContract.value.amount_total) || 0
const paid = Number(selectedContract.value.payment_stats?.paid_amount) || 0
return total - paid
})
```
### 金额限制条件验证
```javascript
const amountLimitValidation = computed(() => {
// 验证逻辑
// 返回 { valid: boolean, message: string }
})
```
---
## 路由参数
### 支持的查询参数
- `payment_type=direct` - 支付类型(必填,用于区分直接/非直接支付)
- `category_id` - 预选分类ID可选直接进入指定分类
- `step` - 步骤编号(可选,直接进入指定步骤)
### 路由监听
页面会监听路由参数变化,自动:
- 确保 `payment_type=direct` 参数存在
- 根据 `category_id` 预选分类
- 根据 `step` 跳转到指定步骤
---
## 数据流图
```
用户访问页面
加载支付分类树payment_type=direct
步骤0选择支付分类
加载分类详情和模板元素
步骤1填写表单信息
├─ 填写支付金额
├─ 选择合同(如需要)
└─ 填写模板字段
验证表单数据
步骤2发起主流程
├─ 如果配置了主审批流程
│ ├─ 显示OA流程创建iframe
│ └─ 等待用户创建流程
└─ 如果未配置主审批流程
└─ 显示提示信息
验证主审批流程(如需要)
构建提交数据
调用 API: POST /budget/payments
提交成功 → 跳转到支付查询页面
```
---
## 注意事项
1. **直接支付 vs 非直接支付**
- 直接支付和非直接支付都支持主审批流程
- 如果分类配置了主审批流程两种类型都需要在步骤2中创建OA流程
- 如果分类未配置主审批流程,`oa_flow_id` 为 `null`,可直接提交
2. **合同关联**
- 只有分类配置了 `need_contract: true` 才显示合同选择
- 开口合同不能用于直接支付
- 闭口合同的支付金额不能超过剩余金额
3. **字段显示条件**
- 字段的显示/隐藏基于金额条件动态控制
- 条件支持合同总金额和本次支付金额两种比较
4. **文件上传**
- 文件上传是异步的,上传成功后才会保存到 `formData.fields`
- 支持多文件上传但单个文件大小不能超过10MB
5. **明细表格**
- 支持动态添加/删除行
- 每行的字段类型可以不同
- 支持部门、用户等关联字段
---
## 相关API接口
| 接口 | 方法 | 说明 |
|------|------|------|
| `/budget/payment-categories` | GET | 获取支付分类树 |
| `/budget/payment-categories/{id}` | GET | 获取分类详情 |
| `/budget/payment-template-elements` | GET | 获取模板元素列表 |
| `/budget/payment-template-elements/oa-models` | GET | 获取OA模型列表 |
| `/api/upload-file` | POST | 文件上传 |
| `/budget/payments` | POST | 创建支付流程 |
| `/budget/contracts` | GET | 获取合同列表(合同选择器) |
---
## 相关文件
- **组件文件**: `src/views/payment/CreatePayment.vue`
- **包装组件**: `src/views/payment/DirectPayment.vue`
- **API定义**: `src/utils/api.js`
- **路由配置**: `src/router/index.js`
---
## 更新日志
- 支持直接支付模式
- 支持合同关联
- 支持金额限制条件
- 支持字段显示条件
- 支持多种模板字段类型
- 支持文件上传
- 支持明细表格
- 支持勾选清单