|
|
# 间接支付页面 - 第三步"选择事前流程"按钮逻辑说明
|
|
|
|
|
|
## 页面信息
|
|
|
|
|
|
- **页面路径**: `http://localhost:3000/#/payment/indirect-payment`
|
|
|
- **页面组件**: `czemc-budget-execution-frontend/src/views/payment/IndirectPayment.vue`
|
|
|
- **步骤**: 第三步 - 填写信息
|
|
|
- **相关组件**: `czemc-budget-execution-frontend/src/components/PreApprovalFlowPicker.vue`
|
|
|
|
|
|
## 一、按钮出现逻辑
|
|
|
|
|
|
### 1.1 渲染条件
|
|
|
|
|
|
**位置**: `IndirectPayment.vue` 第296-301行
|
|
|
|
|
|
```296:301:czemc-budget-execution-frontend/src/views/payment/IndirectPayment.vue
|
|
|
<!-- 事前流程实例 -->
|
|
|
<PreApprovalFlowPicker
|
|
|
v-else-if="field.element_type === 'oa_custom_model'"
|
|
|
v-model="formData[field.key]"
|
|
|
:model-id="field.model_id"
|
|
|
:placeholder="`请选择${field.label}`"
|
|
|
/>
|
|
|
```
|
|
|
|
|
|
**触发条件**:
|
|
|
1. 当前字段的 `element_type === 'oa_custom_model'`(事前流程类型)
|
|
|
2. 字段必须存在于模板配置中(从 `templateConfig` 中获取)
|
|
|
3. 字段的 `visible !== false`(字段可见)
|
|
|
4. 字段通过显示条件检查(`checkFieldDisplayConditions(f)`)
|
|
|
|
|
|
### 1.2 按钮显示/隐藏逻辑
|
|
|
|
|
|
**位置**: `PreApprovalFlowPicker.vue` 第4-40行
|
|
|
|
|
|
```4:40:czemc-budget-execution-frontend/src/components/PreApprovalFlowPicker.vue
|
|
|
<!-- 录入态 -->
|
|
|
<div v-if="!readonly" class="input-container">
|
|
|
<!-- 已选择流程的展示区域 -->
|
|
|
<div v-if="selectedFlow" class="selected-display">
|
|
|
<div class="selected-item">
|
|
|
<el-icon class="item-icon"><DocumentChecked /></el-icon>
|
|
|
<div class="item-content">
|
|
|
<div class="item-title">{{ getFlowDisplayName(selectedFlow) }}</div>
|
|
|
<div v-if="selectedFlow.status" class="item-meta">
|
|
|
<el-tag :type="getStatusType(selectedFlow.status)" size="small">
|
|
|
{{ getStatusText(selectedFlow.status) }}
|
|
|
</el-tag>
|
|
|
</div>
|
|
|
</div>
|
|
|
<el-button
|
|
|
type="danger"
|
|
|
link
|
|
|
size="small"
|
|
|
@click="clearSelection"
|
|
|
class="item-remove"
|
|
|
>
|
|
|
<el-icon><Close /></el-icon>
|
|
|
</el-button>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<!-- 未选择时的操作区域 -->
|
|
|
<div v-else class="action-container">
|
|
|
<el-button
|
|
|
type="primary"
|
|
|
size="small"
|
|
|
@click="showSelectDialog = true"
|
|
|
:disabled="disabled"
|
|
|
>
|
|
|
<el-icon><Document /></el-icon>
|
|
|
选择事前流程
|
|
|
</el-button>
|
|
|
</div>
|
|
|
</div>
|
|
|
```
|
|
|
|
|
|
**显示逻辑**:
|
|
|
- **显示"选择事前流程"按钮**的条件:
|
|
|
1. `readonly === false`(非只读模式)
|
|
|
2. `selectedFlow === null` 或 `selectedFlow === undefined`(未选择流程)
|
|
|
3. `disabled === false`(按钮未禁用)
|
|
|
|
|
|
- **显示已选择流程卡片**的条件:
|
|
|
1. `readonly === false`(非只读模式)
|
|
|
2. `selectedFlow !== null` 且 `selectedFlow !== undefined`(已选择流程)
|
|
|
|
|
|
### 1.3 状态判断流程
|
|
|
|
|
|
```mermaid
|
|
|
flowchart TD
|
|
|
A[字段类型检查] --> B{是否为 oa_custom_model?}
|
|
|
B -->|否| C[不渲染组件]
|
|
|
B -->|是| D{字段是否可见?}
|
|
|
D -->|否| C
|
|
|
D -->|是| E{是否通过显示条件?}
|
|
|
E -->|否| C
|
|
|
E -->|是| F[渲染 PreApprovalFlowPicker]
|
|
|
F --> G{readonly?}
|
|
|
G -->|是| H[显示只读状态]
|
|
|
G -->|否| I{selectedFlow?}
|
|
|
I -->|有值| J[显示已选择流程卡片]
|
|
|
I -->|无值| K[显示"选择事前流程"按钮]
|
|
|
K --> L{disabled?}
|
|
|
L -->|是| M[按钮禁用状态]
|
|
|
L -->|否| N[按钮可点击]
|
|
|
```
|
|
|
|
|
|
## 二、点击按钮后的操作步骤
|
|
|
|
|
|
### 2.1 打开选择对话框
|
|
|
|
|
|
**触发**: 点击"选择事前流程"按钮
|
|
|
|
|
|
**操作**: 设置 `showSelectDialog.value = true`
|
|
|
|
|
|
**位置**: `PreApprovalFlowPicker.vue` 第34行
|
|
|
|
|
|
```34:34:czemc-budget-execution-frontend/src/components/PreApprovalFlowPicker.vue
|
|
|
@click="showSelectDialog = true"
|
|
|
```
|
|
|
|
|
|
### 2.2 对话框打开事件处理
|
|
|
|
|
|
**函数**: `handleDialogOpened()`(第623-631行)
|
|
|
|
|
|
```623:631:czemc-budget-execution-frontend/src/components/PreApprovalFlowPicker.vue
|
|
|
// 对话框打开时先加载年份列表,然后加载流程列表
|
|
|
const handleDialogOpened = async () => {
|
|
|
// 先加载年份列表
|
|
|
await loadAvailableYears()
|
|
|
|
|
|
// 年份加载完成后,如果有选中的年份,再加载流程列表
|
|
|
if (selectedYear.value) {
|
|
|
loadFlowInstances()
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
**执行顺序**:
|
|
|
1. 调用 `loadAvailableYears()` 加载可用年份列表
|
|
|
2. 自动选定年份(优先当年,否则最新年份)
|
|
|
3. 如果有选中的年份,调用 `loadFlowInstances()` 加载流程列表
|
|
|
|
|
|
### 2.3 加载年份列表
|
|
|
|
|
|
**函数**: `loadAvailableYears()`(第416-453行)
|
|
|
|
|
|
**API调用**: `GET /api/budget/planned-expenditures/oa-flow-years`
|
|
|
|
|
|
**请求参数**:
|
|
|
```javascript
|
|
|
{
|
|
|
custom_model_id: props.modelId // 流程模型ID
|
|
|
}
|
|
|
```
|
|
|
|
|
|
**响应处理**:
|
|
|
- 如果返回年份数组,设置 `availableYears.value`
|
|
|
- 自动选定年份:
|
|
|
- 优先选择当前年份(如果存在)
|
|
|
- 否则选择数组中的第一个年份(最新年份)
|
|
|
- 如果无数据或出错,默认使用当前年份
|
|
|
|
|
|
**关键代码**:
|
|
|
```432:444:czemc-budget-execution-frontend/src/components/PreApprovalFlowPicker.vue
|
|
|
// 自动选定当年
|
|
|
const currentYear = new Date().getFullYear()
|
|
|
if (availableYears.value.includes(currentYear)) {
|
|
|
selectedYear.value = currentYear
|
|
|
} else if (availableYears.value.length > 0) {
|
|
|
// 如果没有当年,选择最新的年份
|
|
|
selectedYear.value = availableYears.value[0]
|
|
|
}
|
|
|
```
|
|
|
|
|
|
### 2.4 加载流程实例列表
|
|
|
|
|
|
**函数**: `loadFlowInstances()`(第456-522行)
|
|
|
|
|
|
**触发时机**:
|
|
|
1. 对话框打开后,年份加载完成且有选中年份
|
|
|
2. 年份切换时
|
|
|
3. 搜索关键词变化时
|
|
|
4. 分页参数变化时
|
|
|
|
|
|
**API调用**: `GET /api/budget/planned-expenditures/oa-flow-instances`
|
|
|
|
|
|
**请求参数**:
|
|
|
```javascript
|
|
|
{
|
|
|
custom_model_id: props.modelId, // 流程模型ID(必填)
|
|
|
year: selectedYear.value, // 年份(必填)
|
|
|
page: pagination.value.currentPage, // 当前页码
|
|
|
page_size: pagination.value.pageSize, // 每页数量
|
|
|
keyword: searchKeyword.value // 搜索关键词(可选)
|
|
|
}
|
|
|
```
|
|
|
|
|
|
**响应数据结构**:
|
|
|
```javascript
|
|
|
{
|
|
|
code: 0,
|
|
|
data: {
|
|
|
data: [ // 流程实例列表
|
|
|
{
|
|
|
id: 1,
|
|
|
no: 'FLOW-20250101-001',
|
|
|
title: '流程标题',
|
|
|
status: 'approved',
|
|
|
status_text: '已通过',
|
|
|
created_at: '2025-01-01 10:00:00',
|
|
|
related_count: 2, // 已关联数量
|
|
|
list_field_values: {}, // 列表字段值
|
|
|
list_fields: [] // 列表字段定义
|
|
|
}
|
|
|
],
|
|
|
total: 100, // 总记录数
|
|
|
list_columns: [ // 动态列定义(show_in_list=1的字段)
|
|
|
{
|
|
|
label: '字段标签',
|
|
|
name: 'field_name',
|
|
|
type: 'text'
|
|
|
}
|
|
|
]
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
**处理逻辑**:
|
|
|
1. 提取 `list_columns` 作为动态表格列
|
|
|
2. 提取 `data` 作为流程列表数据
|
|
|
3. 更新分页信息(`total`)
|
|
|
4. 设置加载状态
|
|
|
|
|
|
### 2.5 流程列表展示
|
|
|
|
|
|
**位置**: 对话框中的表格(第107-166行)
|
|
|
|
|
|
**表格列结构**:
|
|
|
1. **序号列** (#) - 宽度 60px
|
|
|
2. **流程编号** (no) - 宽度 150px,支持溢出提示
|
|
|
3. **流程标题** (title) - 最小宽度 250px,支持溢出提示
|
|
|
4. **动态列** - 根据 `list_columns` 动态生成,显示 `show_in_list=1` 的字段
|
|
|
5. **流程状态** - 宽度 120px,显示状态标签(带颜色)
|
|
|
6. **创建时间** - 宽度 180px
|
|
|
7. **关联信息** - 宽度 200px,显示已关联数量
|
|
|
8. **操作** - 宽度 120px,固定右侧,包含"查看详情"按钮
|
|
|
|
|
|
**交互特性**:
|
|
|
- 支持行点击选择(高亮当前行)
|
|
|
- 支持搜索功能(搜索流程编号、标题、列表字段)
|
|
|
- 支持分页(15/30/50/100 条每页)
|
|
|
- 支持查看详情(打开详情对话框)
|
|
|
|
|
|
### 2.6 年份切换
|
|
|
|
|
|
**函数**: `handleYearChange()`(第608-614行)
|
|
|
|
|
|
**触发**: 用户切换年份单选按钮
|
|
|
|
|
|
**操作**:
|
|
|
1. 重置分页到第一页
|
|
|
2. 清空搜索关键词
|
|
|
3. 清空已选中的行
|
|
|
4. 重新加载流程列表
|
|
|
|
|
|
```608:614:czemc-budget-execution-frontend/src/components/PreApprovalFlowPicker.vue
|
|
|
// 年份切换
|
|
|
const handleYearChange = () => {
|
|
|
pagination.value.currentPage = 1
|
|
|
searchKeyword.value = ''
|
|
|
selectedRow.value = null
|
|
|
loadFlowInstances()
|
|
|
}
|
|
|
```
|
|
|
|
|
|
### 2.7 搜索功能
|
|
|
|
|
|
**函数**: `handleSearch()`(第616-620行)
|
|
|
|
|
|
**触发**: 搜索输入框内容变化(`@input` 事件)
|
|
|
|
|
|
**操作**:
|
|
|
1. 重置分页到第一页
|
|
|
2. 重新加载流程列表(带搜索关键词)
|
|
|
|
|
|
```616:620:czemc-budget-execution-frontend/src/components/PreApprovalFlowPicker.vue
|
|
|
// 搜索
|
|
|
const handleSearch = () => {
|
|
|
pagination.value.currentPage = 1
|
|
|
loadFlowInstances()
|
|
|
}
|
|
|
```
|
|
|
|
|
|
### 2.8 选择流程
|
|
|
|
|
|
**函数**: `handleSelectFlow(row)`(第572-575行)
|
|
|
|
|
|
**触发**: 点击表格行
|
|
|
|
|
|
**操作**: 设置 `selectedRow.value = row`(高亮当前行)
|
|
|
|
|
|
```572:575:czemc-budget-execution-frontend/src/components/PreApprovalFlowPicker.vue
|
|
|
// 处理选择行
|
|
|
const handleSelectFlow = (row) => {
|
|
|
selectedRow.value = row
|
|
|
}
|
|
|
```
|
|
|
|
|
|
### 2.9 确认选择
|
|
|
|
|
|
**函数**: `confirmSelect()`(第577-592行)
|
|
|
|
|
|
**触发**: 点击对话框底部的"确定"按钮
|
|
|
|
|
|
**前置条件**: `selectedRow.value !== null`(必须已选择一行)
|
|
|
|
|
|
**操作步骤**:
|
|
|
1. 验证是否已选择流程
|
|
|
2. 设置 `selectedFlow.value = selectedRow.value`
|
|
|
3. 触发 `update:modelValue` 事件,传递流程ID
|
|
|
4. 触发 `change` 事件,传递流程ID
|
|
|
5. 加载流程详情用于展示
|
|
|
6. 关闭对话框
|
|
|
|
|
|
```577:592:czemc-budget-execution-frontend/src/components/PreApprovalFlowPicker.vue
|
|
|
// 确认选择
|
|
|
const confirmSelect = () => {
|
|
|
if (!selectedRow.value) {
|
|
|
ElMessage.warning('请选择一条流程')
|
|
|
return
|
|
|
}
|
|
|
|
|
|
selectedFlow.value = selectedRow.value
|
|
|
emit('update:modelValue', selectedRow.value.id)
|
|
|
emit('change', selectedRow.value.id)
|
|
|
|
|
|
// 加载详情用于展示
|
|
|
loadFlowDetail(selectedRow.value.id)
|
|
|
|
|
|
showSelectDialog.value = false
|
|
|
}
|
|
|
```
|
|
|
|
|
|
### 2.10 加载流程详情
|
|
|
|
|
|
**函数**: `loadFlowDetail(flowId)`(第524-570行)
|
|
|
|
|
|
**触发时机**:
|
|
|
1. 确认选择后,加载选中流程的详情
|
|
|
2. 查看详情时,加载指定流程的详情
|
|
|
3. 组件初始化时,如果有初始值,加载详情
|
|
|
|
|
|
**缓存机制**:
|
|
|
1. 先检查缓存 `flowDetailsCache.value[flowId]`
|
|
|
2. 如果缓存存在,直接使用
|
|
|
3. 否则从列表数据中查找
|
|
|
4. 如果列表中没有,调用API加载
|
|
|
|
|
|
**API调用**: `GET /api/budget/planned-expenditures/oa-flow-details`
|
|
|
|
|
|
**请求参数**:
|
|
|
```javascript
|
|
|
{
|
|
|
flow_ids: [flowId] // 流程ID数组
|
|
|
}
|
|
|
```
|
|
|
|
|
|
**响应数据**:
|
|
|
```javascript
|
|
|
{
|
|
|
code: 0,
|
|
|
data: {
|
|
|
'flowId': { // key为流程ID
|
|
|
id: 1,
|
|
|
no: 'FLOW-001',
|
|
|
title: '流程标题',
|
|
|
display_name: 'FLOW-001 - 流程标题',
|
|
|
status: 'approved',
|
|
|
list_fields: [], // 列表字段
|
|
|
all_fields: [] // 全部字段(用于详情)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
### 2.11 更新显示状态
|
|
|
|
|
|
**位置**: 组件模板第6-27行
|
|
|
|
|
|
**显示内容**:
|
|
|
- 流程图标(DocumentChecked)
|
|
|
- 流程显示名称(编号 - 标题)
|
|
|
- 流程状态标签(带颜色)
|
|
|
- 清除按钮(右上角)
|
|
|
|
|
|
**样式**: 绿色背景卡片,带边框
|
|
|
|
|
|
### 2.12 清除选择
|
|
|
|
|
|
**函数**: `clearSelection()`(第594-600行)
|
|
|
|
|
|
**触发**: 点击已选择流程卡片右上角的清除按钮
|
|
|
|
|
|
**操作**:
|
|
|
1. 清空 `selectedFlow.value`
|
|
|
2. 清空 `selectedRow.value`
|
|
|
3. 触发 `update:modelValue` 事件,传递 `null`
|
|
|
4. 触发 `change` 事件,传递 `null`
|
|
|
|
|
|
**结果**: 恢复显示"选择事前流程"按钮
|
|
|
|
|
|
```594:600:czemc-budget-execution-frontend/src/components/PreApprovalFlowPicker.vue
|
|
|
// 清除选择
|
|
|
const clearSelection = () => {
|
|
|
selectedFlow.value = null
|
|
|
selectedRow.value = null
|
|
|
emit('update:modelValue', null)
|
|
|
emit('change', null)
|
|
|
}
|
|
|
```
|
|
|
|
|
|
## 三、完整操作流程图
|
|
|
|
|
|
```mermaid
|
|
|
sequenceDiagram
|
|
|
participant U as 用户
|
|
|
participant C as PreApprovalFlowPicker组件
|
|
|
participant API as 后端API
|
|
|
|
|
|
U->>C: 点击"选择事前流程"按钮
|
|
|
C->>C: showSelectDialog = true
|
|
|
C->>C: handleDialogOpened()
|
|
|
C->>API: GET /oa-flow-years (加载年份列表)
|
|
|
API-->>C: 返回年份数组
|
|
|
C->>C: 自动选定年份(优先当年)
|
|
|
C->>API: GET /oa-flow-instances (加载流程列表)
|
|
|
API-->>C: 返回流程列表和动态列
|
|
|
C->>U: 显示流程列表对话框
|
|
|
|
|
|
alt 用户切换年份
|
|
|
U->>C: 切换年份
|
|
|
C->>C: handleYearChange()
|
|
|
C->>C: 重置分页和搜索
|
|
|
C->>API: GET /oa-flow-instances (重新加载)
|
|
|
API-->>C: 返回新年份的流程列表
|
|
|
end
|
|
|
|
|
|
alt 用户搜索
|
|
|
U->>C: 输入搜索关键词
|
|
|
C->>C: handleSearch()
|
|
|
C->>API: GET /oa-flow-instances (带关键词)
|
|
|
API-->>C: 返回搜索结果
|
|
|
end
|
|
|
|
|
|
U->>C: 点击表格行选择流程
|
|
|
C->>C: handleSelectFlow(row)
|
|
|
C->>C: selectedRow = row (高亮行)
|
|
|
|
|
|
U->>C: 点击"确定"按钮
|
|
|
C->>C: confirmSelect()
|
|
|
C->>C: selectedFlow = selectedRow
|
|
|
C->>C: emit('update:modelValue', flowId)
|
|
|
C->>API: GET /oa-flow-details (加载详情)
|
|
|
API-->>C: 返回流程详情
|
|
|
C->>C: 缓存详情数据
|
|
|
C->>C: showSelectDialog = false
|
|
|
C->>U: 显示已选择流程卡片
|
|
|
|
|
|
alt 用户清除选择
|
|
|
U->>C: 点击清除按钮
|
|
|
C->>C: clearSelection()
|
|
|
C->>C: emit('update:modelValue', null)
|
|
|
C->>U: 恢复显示"选择事前流程"按钮
|
|
|
end
|
|
|
```
|
|
|
|
|
|
## 四、数据流
|
|
|
|
|
|
### 4.1 数据绑定
|
|
|
|
|
|
**父组件** (`IndirectPayment.vue`):
|
|
|
- `v-model="formData[field.key]"` - 双向绑定流程ID
|
|
|
- `:model-id="field.model_id"` - 传递流程模型ID
|
|
|
|
|
|
**子组件** (`PreApprovalFlowPicker.vue`):
|
|
|
- `props.modelValue` - 接收流程ID
|
|
|
- `props.modelId` - 接收流程模型ID
|
|
|
- `emit('update:modelValue', flowId)` - 更新流程ID
|
|
|
|
|
|
### 4.2 数据存储
|
|
|
|
|
|
**表单数据**:
|
|
|
```javascript
|
|
|
formData = {
|
|
|
'element_123': 456, // 字段key: 流程ID
|
|
|
// ... 其他字段
|
|
|
}
|
|
|
```
|
|
|
|
|
|
**组件内部状态**:
|
|
|
```javascript
|
|
|
selectedFlow.value = {
|
|
|
id: 456,
|
|
|
no: 'FLOW-001',
|
|
|
title: '流程标题',
|
|
|
status: 'approved',
|
|
|
// ... 其他字段
|
|
|
}
|
|
|
```
|
|
|
|
|
|
### 4.3 监听数据变化
|
|
|
|
|
|
**监听 modelValue 变化**(第634-647行):
|
|
|
- 当外部传入的 `modelValue` 变化时
|
|
|
- 如果有值且与当前选中的流程ID不同,重新加载详情
|
|
|
- 如果值为空,清空选中状态
|
|
|
|
|
|
```634:647:czemc-budget-execution-frontend/src/components/PreApprovalFlowPicker.vue
|
|
|
// 监听 modelValue 变化,加载详情
|
|
|
watch(() => props.modelValue, (newValue) => {
|
|
|
if (newValue) {
|
|
|
// 如果有值但没有选中流程,需要加载
|
|
|
if (!selectedFlow.value || selectedFlow.value.id !== newValue) {
|
|
|
loadFlowDetail(newValue).then(() => {
|
|
|
if (detailFlow.value) {
|
|
|
selectedFlow.value = detailFlow.value
|
|
|
}
|
|
|
})
|
|
|
}
|
|
|
} else {
|
|
|
selectedFlow.value = null
|
|
|
}
|
|
|
}, { immediate: true })
|
|
|
```
|
|
|
|
|
|
## 五、关键配置和参数
|
|
|
|
|
|
### 5.1 组件属性
|
|
|
|
|
|
| 属性 | 类型 | 必填 | 默认值 | 说明 |
|
|
|
|------|------|------|--------|------|
|
|
|
| `modelValue` | Number/String/null | 否 | null | 双向绑定,流程ID |
|
|
|
| `modelId` | Number/String | 是 | - | 流程模型ID |
|
|
|
| `placeholder` | String | 否 | '请选择事前流程实例' | 占位符文本 |
|
|
|
| `disabled` | Boolean | 否 | false | 是否禁用 |
|
|
|
| `readonly` | Boolean | 否 | false | 是否只读 |
|
|
|
| `autoLoad` | Boolean | 否 | false | 是否自动加载 |
|
|
|
|
|
|
### 5.2 对话框配置
|
|
|
|
|
|
- **宽度**: 80%
|
|
|
- **标题**: "选择事前流程实例"
|
|
|
- **关闭方式**: 点击遮罩不关闭(`:close-on-click-modal="false"`)
|
|
|
|
|
|
### 5.3 分页配置
|
|
|
|
|
|
- **默认每页**: 15条
|
|
|
- **可选每页**: 15/30/50/100条
|
|
|
- **布局**: total, sizes, prev, pager, next
|
|
|
|
|
|
## 六、注意事项
|
|
|
|
|
|
### 6.1 必填参数
|
|
|
|
|
|
- `modelId` 必须提供,否则无法加载流程列表
|
|
|
- 年份必须选择,否则不加载流程列表
|
|
|
|
|
|
### 6.2 数据一致性
|
|
|
|
|
|
- 流程ID必须与 `modelId` 对应的流程模型匹配
|
|
|
- 选择流程后,流程详情会在确认时加载并缓存
|
|
|
- 如果流程不存在,会显示友好的错误信息
|
|
|
|
|
|
### 6.3 性能优化
|
|
|
|
|
|
- 流程列表支持分页,避免一次性加载过多数据
|
|
|
- 流程详情使用缓存机制,避免重复请求
|
|
|
- 年份列表只在对话框打开时加载一次
|
|
|
|
|
|
### 6.4 错误处理
|
|
|
|
|
|
- API 请求失败时显示错误提示
|
|
|
- 流程不存在时显示友好的提示信息
|
|
|
- 网络错误时不影响其他功能
|
|
|
- 年份加载失败时默认使用当前年份
|
|
|
|
|
|
### 6.5 用户体验
|
|
|
|
|
|
- 自动选定当前年份,减少用户操作
|
|
|
- 支持搜索,快速定位流程
|
|
|
- 支持查看详情,了解流程完整信息
|
|
|
- 已选择状态清晰展示,带状态标签
|
|
|
- 支持清除选择,方便重新选择
|
|
|
|
|
|
## 七、相关文件
|
|
|
|
|
|
### 7.1 组件文件
|
|
|
- `czemc-budget-execution-frontend/src/components/PreApprovalFlowPicker.vue`
|
|
|
|
|
|
### 7.2 页面文件
|
|
|
- `czemc-budget-execution-frontend/src/views/payment/IndirectPayment.vue`
|
|
|
|
|
|
### 7.3 API 文件
|
|
|
- `czemc-budget-execution-frontend/src/utils/api.js`
|
|
|
- `plannedExpenditureAPI.getOaFlowYears()` - 获取可用年份列表
|
|
|
- `plannedExpenditureAPI.getOaFlowInstances()` - 获取流程实例列表
|
|
|
- `plannedExpenditureAPI.getOaFlowDetails()` - 批量获取流程详情
|
|
|
|
|
|
### 7.4 后端接口
|
|
|
- `GET /api/budget/planned-expenditures/oa-flow-years` - 获取可用年份列表
|
|
|
- `GET /api/budget/planned-expenditures/oa-flow-instances` - 获取流程实例列表
|
|
|
- `GET /api/budget/planned-expenditures/oa-flow-details` - 批量获取流程详情
|
|
|
|