187 lines
4.6 KiB
Markdown
187 lines
4.6 KiB
Markdown
|
|
# Design: 议价池显示组件
|
|||
|
|
|
|||
|
|
## Overview
|
|||
|
|
|
|||
|
|
本文档描述议价池显示组件的详细设计,包括组件结构、数据流、样式规范和实现细节。
|
|||
|
|
|
|||
|
|
## Component Architecture
|
|||
|
|
|
|||
|
|
### 组件层次结构
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
detail.vue (流程详情页面)
|
|||
|
|
├── left-panel (左侧关键信息卡片)
|
|||
|
|
└── right-panel (右侧面板)
|
|||
|
|
├── detail-card (流程详情卡片)
|
|||
|
|
├── ModelOutputDisplay (模型输出组件) [已存在]
|
|||
|
|
└── BargainingPoolDisplay (议价池显示组件) [新增]
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 组件职责
|
|||
|
|
|
|||
|
|
| 组件 | 职责 |
|
|||
|
|
|------|------|
|
|||
|
|
| `detail.vue` | 流程详情页面容器,负责数据获取和子组件协调 |
|
|||
|
|
| `BargainingPoolDisplay.vue` | 议价池数据展示,独立封装议价池相关的 UI 和逻辑 |
|
|||
|
|
|
|||
|
|
## Component Specification
|
|||
|
|
|
|||
|
|
### BargainingPoolDisplay.vue
|
|||
|
|
|
|||
|
|
#### Props
|
|||
|
|
|
|||
|
|
| 属性名 | 类型 | 默认值 | 说明 |
|
|||
|
|
|--------|------|--------|------|
|
|||
|
|
| `branchPool` | Number/String | 0 | 网点议价池 |
|
|||
|
|
| `subBranchPool` | Number/String | 0 | 支行议价池 |
|
|||
|
|
| `privateDomainPool` | Number/String | 0 | 私域池 |
|
|||
|
|
|
|||
|
|
#### Template Structure
|
|||
|
|
|
|||
|
|
```vue
|
|||
|
|
<template>
|
|||
|
|
<el-card class="bargaining-pool-card">
|
|||
|
|
<div slot="header" class="card-header">
|
|||
|
|
<span class="card-title">议价池</span>
|
|||
|
|
</div>
|
|||
|
|
<el-descriptions :column="3" border size="small">
|
|||
|
|
<el-descriptions-item label="网点议价池">
|
|||
|
|
{{ displayBranchPool }}
|
|||
|
|
</el-descriptions-item>
|
|||
|
|
<el-descriptions-item label="支行议价池">
|
|||
|
|
{{ displaySubBranchPool }}
|
|||
|
|
</el-descriptions-item>
|
|||
|
|
<el-descriptions-item label="私域池">
|
|||
|
|
{{ displayPrivateDomainPool }}
|
|||
|
|
</el-descriptions-item>
|
|||
|
|
</el-descriptions>
|
|||
|
|
</el-card>
|
|||
|
|
</template>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### Computed Properties
|
|||
|
|
|
|||
|
|
| 属性名 | 说明 |
|
|||
|
|
|--------|------|
|
|||
|
|
| `displayBranchPool` | 返回网点议价池的显示值,处理 null/undefined/空字符串为 '0' |
|
|||
|
|
| `displaySubBranchPool` | 返回支行议价池的显示值,处理 null/undefined/空字符串为 '0' |
|
|||
|
|
| `displayPrivateDomainPool` | 返回私域池的显示值,处理 null/undefined/空字符串为 '0' |
|
|||
|
|
|
|||
|
|
#### Style Specification
|
|||
|
|
|
|||
|
|
议价池卡片样式将与 `ModelOutputDisplay` 保持一致:
|
|||
|
|
|
|||
|
|
```scss
|
|||
|
|
.bargaining-pool-card {
|
|||
|
|
// 与 model-output-card 相同的样式
|
|||
|
|
::v-deep .el-card__header {
|
|||
|
|
padding: 16px 20px;
|
|||
|
|
background-color: #fafafa;
|
|||
|
|
border-bottom: 1px solid #ebeef5;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.card-header {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
|
|||
|
|
.card-title {
|
|||
|
|
font-size: 16px;
|
|||
|
|
font-weight: 500;
|
|||
|
|
color: #303133;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
::v-deep .el-card__body {
|
|||
|
|
padding: 20px;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Data Flow
|
|||
|
|
|
|||
|
|
### API 响应结构(预期)
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
{
|
|||
|
|
"data": {
|
|||
|
|
"loanPricingWorkflow": { ... },
|
|||
|
|
"modelRetailOutputFields": { ... },
|
|||
|
|
"modelCorpOutputFields": { ... },
|
|||
|
|
"bargainingPool": { // 新增字段
|
|||
|
|
"branchPool": 10, // 网点议价池
|
|||
|
|
"subBranchPool": 5, // 支行议价池
|
|||
|
|
"privateDomainPool": 3 // 私域池
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 组件集成
|
|||
|
|
|
|||
|
|
在 `detail.vue` 中:
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
// data
|
|||
|
|
bargainingPool: null,
|
|||
|
|
|
|||
|
|
// created() 中获取数据
|
|||
|
|
getWorkflow(serialNum).then(response => {
|
|||
|
|
this.workflowDetail = response.data.loanPricingWorkflow
|
|||
|
|
this.retailOutput = response.data.modelRetailOutputFields
|
|||
|
|
this.corpOutput = response.data.modelCorpOutputFields
|
|||
|
|
this.bargainingPool = response.data.bargainingPool // 新增
|
|||
|
|
this.loading = false
|
|||
|
|
})
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
```vue
|
|||
|
|
<!-- template 中使用组件 -->
|
|||
|
|
<BargainingPoolDisplay
|
|||
|
|
:branch-pool="bargainingPool?.branchPool"
|
|||
|
|
:sub-branch-pool="bargainingPool?.subBranchPool"
|
|||
|
|
:private-domain-pool="bargainingPool?.privateDomainPool"
|
|||
|
|
/>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Error Handling
|
|||
|
|
|
|||
|
|
### 数据缺失处理
|
|||
|
|
|
|||
|
|
当 API 响应中没有议价池数据时:
|
|||
|
|
- 组件使用默认值 0 显示
|
|||
|
|
- 不显示错误提示
|
|||
|
|
- 保证页面正常展示
|
|||
|
|
|
|||
|
|
### 值格式化
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
computed: {
|
|||
|
|
displayBranchPool() {
|
|||
|
|
const value = this.branchPool
|
|||
|
|
if (value === null || value === undefined || value === '') {
|
|||
|
|
return '0'
|
|||
|
|
}
|
|||
|
|
return value
|
|||
|
|
},
|
|||
|
|
// ... 其他字段类似
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Testing Considerations
|
|||
|
|
|
|||
|
|
### 单元测试场景
|
|||
|
|
1. 组件渲染时显示默认值 0
|
|||
|
|
2. 传入正确的议价池数据时正确显示
|
|||
|
|
3. 处理 null/undefined 值时显示 0
|
|||
|
|
|
|||
|
|
### 集成测试场景
|
|||
|
|
1. 流程详情页面加载时议价池卡片正确显示
|
|||
|
|
2. 议价池卡片位置在模型输出卡片下方
|
|||
|
|
3. 样式与模型输出卡片保持一致
|
|||
|
|
|
|||
|
|
## Future Enhancements
|
|||
|
|
|
|||
|
|
1. **后端数据对接**:当后端提供议价池 API 时,移除默认值逻辑
|
|||
|
|
2. **单位显示**:确认议价池数值单位(BP 或金额)后添加单位标签
|
|||
|
|
3. **交互功能**:可能需要添加议价池的编辑或调整功能
|