# 承销商管理 — 前端技术方案

> 依据：`承销商管理功能需求.md`、`承销商管理技术方案.md`（后端 v1.3）；布局对齐 `tradeMarket/supplier/index.vue`（双 `el-card`）；字段 **小驼峰**。

---

## 1. 页面与路由

| 项 | 说明 |
| --- | --- |
| **Vue 路径** | `ruoyi-ui/src/views/tradeMarket/distributor/index.vue` |
| **组件名** | `TradeMarketDistributor` |
| **菜单配置** | 组件路径：`tradeMarket/distributor/index`（「交易市场平台」目录下，手工配置） |
| **权限前缀** | `tradeMarket:distributor:list\|query\|add\|edit\|remove\|assignAccount` |

---

## 2. API 模块

| 项 | 说明 |
| --- | --- |
| **文件** | `ruoyi-ui/src/api/tradeMarket/distributor.js` |
| **Base** | `/tradeMarket/distributor` |

| 方法 | HTTP | 说明 |
| --- | --- | --- |
| `listDistributor` | GET | `/list`，Query：`pageNum`、`pageSize`、`distributorCode`、`distributorName` |
| `getDistributor` | GET | `/{id}` |
| `addDistributor` | POST | `/`，Body 不含 `distributorCode` |
| `updateDistributor` | PUT | `/`，Body 含 `id`，不含 `distributorCode` |
| `delDistributor` | DELETE | `/{ids}`，单条传一个 id |
| `assignAccountDistributor` | POST | `/assignAccount/{id}`，无 Body |

---

## 3. 页面结构

1. **筛选区**：承销商编号、承销商名称（**模糊**，原样提交由后端 `LIKE %keyword%`）；搜索、重置、新增。  
2. **列表区**：编号、名称、类型、身份识别号、联系方式、经营地点、销售去向、**账号分配**、操作（查看 / 编辑 / **分配账号** / 删除）。  
3. **新增/编辑弹窗**（720px）：编号只读（新增占位「保存后自动生成」）；类型切换身份字段标签与校验；销售去向三选一下拉；备注 ≤500 字。  
4. **查看弹窗**（720px）：全部业务字段、销售去向、**账号分配状态**、**已分配登录名**、审计信息；底部：**分配账号**（未分配时）、编辑、删除、关闭。

---

## 4. 业务规则（前端）

| 规则 | 实现 |
| --- | --- |
| 承销商编号 | 新增 `buildPayload` **不传** `distributorCode`；编辑弹窗只读展示；保存后列表/详情由后端返回 2 位编号 |
| 承销商类型 | `1` 个体户 → 标签「身份证号」、`ID_CARD_REG`；`2` 企业 → 标签「主体识别号」、`USCC_REG`（18 位大写） |
| 类型切换 | `onDistributorTypeChange` 后 `$nextTick` 重校验 `identityNo` |
| 销售去向 | `1` 本市、`2` 本省、`3` 外省；必选；列表/详情优先 `salesDestinationName` |
| 名称/手机 | 名称 trim 后 1～20 字；`PHONE_REG`；身份号提交前 `trim().toUpperCase()` |
| 经营地点/备注 | 选填；前端长度 ≤50 / ≤500 |
| 列表筛选 | `queryParams.distributorCode`、`distributorName` 模糊（与供应商**精确**筛选不同） |
| 列表展示 | 类型优先 `distributorTypeName`；销售去向优先 `salesDestinationName` |
| 删除 | 确认框展示编号、名称；后端存在未支付订单时返回 msg「存在未支付订单，无法删除」，由 `request` 拦截器 toast |
| 分配账号 | `canAssignAccount(row)`：`Number(row.accountAssigned) === 0` 且有 `assignAccount` 权限；确认文案 `confirmAssign`；调 `assignAccountDistributor`；成功 toast `msgAssignOk` 并刷新列表；若详情弹窗打开则重新 `getDistributor` 刷新 `viewRow` |
| 账号列 | `accountAssigned === 1` 显示「是」+ 括号内 `assignedLoginName`；否则「否」（文案 `tradeMarket.status.yes/no`） |
| 与供应商差异 | 无收费方式/费率、**无车辆号牌**；筛选为**模糊**非精确；分配账号角色后端绑定 **104**（供应商为 103） |

**枚举常量（页面内）**

| 常量 | 值 |
| --- | --- |
| 个体户 | `distributorType = 1` |
| 企业 | `distributorType = 2` |
| 本市 | `salesDestination = 1` |
| 本省 | `salesDestination = 2` |
| 外省 | `salesDestination = 3` |

**正则（页面内）**

| 名称 | 用途 |
| --- | --- |
| `ID_CARD_REG` | 18 位居民身份证 |
| `USCC_REG` | 18 位统一社会信用代码 |
| `PHONE_REG` | 大陆手机号 |

**提交字段（`buildPayload`）**

| 字段 | 新增 | 修改 |
| --- | --- | --- |
| `distributorName` | Y | Y |
| `distributorType` | Y | Y |
| `identityNo` | Y | Y |
| `contactPhone` | Y | Y |
| `businessLocation` | N | N |
| `salesDestination` | Y | Y |
| `remark` | N | N |
| `id` | — | Y |
| `distributorCode` | **禁止** | **禁止** |

---

## 5. 国际化

| 项 | 说明 |
| --- | --- |
| **语言包** | `tradeMarket.distributor`（`lang/zh/tradeMarket.js`、`lang/bo/tradeMarket.js`） |
| **Mixin** | `tradeMarketLocaleMixin`，`tmNs = 'distributor'`，方法 `tmT` / `tmCommon` |
| **公共文案** | `tradeMarket.common.*`（含 `assignAccount`、`msgAssignOk`） |
| **状态文案** | `tradeMarket.status.yes` / `no` / `dash` |

**`distributor` 节点主要键**

| 键 | 用途 |
| --- | --- |
| `queryDistributorCode` / `queryDistributorName` | 筛选标签 |
| `queryDistributorCodePh` / `queryDistributorNamePh` | 模糊查询占位 |
| `colDistributorCode` … `colSalesDestination` | 列表列 |
| `colAccount` | 账号分配列 |
| `formDistributorCode` … `formSalesDestination` | 表单标签 |
| `distributorType1/2`、`salesDestination1/2/3` | 枚举展示 |
| `confirmDelete`、`confirmAssign` | 删除 / 分配账号确认 |
| `viewAssignedLogin` | 详情已分配登录名 |
| `rule*` | 表单校验提示 |

---

## 6. 联调说明

1. 部署 `BizDistributorController` 及 `biz_distributor` 表（见后端技术方案）。  
2. 菜单组件 `tradeMarket/distributor/index`，权限与后端 §4 一致（含 `assignAccount`）。  
3. 验证项：  
   - 编号/名称**模糊**筛选（如输入 `1` 可命中 `01`、`11`）  
   - 新增后 2 位编号自动生成；修改时编号不可变  
   - 个体户/企业证件切换与校验  
   - 销售去向三档保存与展示  
   - **分配账号仅一次**；列表与详情展示登录名  
   - 存在未支付订单时删除失败提示  
   - 逻辑删除后列表不可见  
   - 汉藏双语切换

---

## 7. 文件清单

| 类型 | 路径 |
| --- | --- |
| 页面 | `ruoyi-ui/src/views/tradeMarket/distributor/index.vue` |
| API | `ruoyi-ui/src/api/tradeMarket/distributor.js` |
| Mixin | `ruoyi-ui/src/mixins/tradeMarketLocaleMixin.js` |
| i18n | `ruoyi-ui/src/lang/zh/tradeMarket.js`、`lang/bo/tradeMarket.js`（`distributor` 节点及 `common`/`status` 扩展） |

---

## 8. 与供应商前端对照

| 项 | 供应商 | 承销商 |
| --- | --- | --- |
| 页面 | `tradeMarket/supplier/index.vue` | `tradeMarket/distributor/index.vue` |
| 筛选 | 编号/名称**精确** | **模糊** |
| 特色字段 | 车辆号牌、收费方式/费率 | **销售去向** |
| 分配账号 API | `assignAccountSupplier` | `assignAccountDistributor` |
| 后端角色 | 103 | 104 |
| 弹窗宽度 | 550px（表单字段多） | 720px |

---

## 9. 修订记录

| 版本 | 说明 |
| --- | --- |
| 1.0 | 初版：双卡片 CRUD；销售去向；模糊筛选；复用 tradeMarket 公共 i18n 与 mixin |
| 1.1 | 移除车辆号牌相关 UI、校验与 i18n（对齐修订草稿） |
| 1.2 | 分配账号 API/列表列/操作按钮（对齐功能需求 §5.6） |
| 1.3 | **与实现对齐**：补充 `assignAccountDistributor`、账号列/详情展示、`canAssignAccount`/`handleAssignAccount`、删除未支付订单联调说明、`buildPayload` 字段表、i18n 键清单、与供应商对照表；同步后端 v1.3 删除约束 |
