# 中介黑名单前端适配API v2.0重构设计文档

**文档版本**: v1.0
**创建日期**: 2026-02-05
**设计目标**: 将前端字段完全对齐API v2.0规范,实现前后端字段名一致

---

## 一、变更背景

### 1.1 API v2.0核心变更

后端API已升级至v2.0版本,主要变更包括:

- **统一业务ID**: 使用`bizId`替代`intermediaryId`作为主键
- **接口分离**: 个人和实体中介使用独立的详情查询接口
- **字段规范化**: 统一字段命名规范,消除歧义
- **DTO/VO分离**: 请求和响应对象完全分离

### 1.2 重构目标

1. **字段名对齐**: 前端表单字段与API请求字段完全一致
2. **消除映射**: 移除前后端字段名转换逻辑
3. **代码简化**: 降低维护成本,提升可读性
4. **类型安全**: 确保个人和实体中介字段正确隔离

---

## 二、字段映射方案

### 2.1 个人中介字段映射

| 旧前端字段          | API v2.0字段     | 说明     |
|----------------|----------------|--------|
| intermediaryId | bizId          | 主键ID   |
| certificateNo  | personId       | 证件号码   |
| indivType      | personType     | 人员类型   |
| indivSubType   | personSubType  | 人员子类型  |
| indivGender    | gender         | 性别     |
| indivCertType  | idType         | 证件类型   |
| indivPhone     | mobile         | 手机号码   |
| indivWechat    | wechatNo       | 微信号    |
| indivAddress   | contactAddress | 联系地址   |
| indivCompany   | company        | 所在公司   |
| indivPosition  | position       | 职位     |
| indivRelatedId | relatedNumId   | 关联人员ID |
| indivRelation  | relationType   | 关系类型   |

**保持不变的字段:**

- name (姓名)
- remark (备注)
- intermediaryType (中介类型)
- status (状态)

### 2.2 实体中介字段映射

| 旧前端字段                          | API v2.0字段          | 说明        |
|--------------------------------|---------------------|-----------|
| intermediaryId                 | bizId               | 主键ID      |
| name                           | enterpriseName      | 机构名称      |
| certificateNo / corpCreditCode | socialCreditCode    | 统一社会信用代码  |
| corpType                       | enterpriseType      | 主体类型      |
| corpNature                     | enterpriseNature    | 企业性质      |
| corpIndustryCategory           | industryClass       | 行业分类      |
| corpIndustry                   | industryName        | 所属行业      |
| corpEstablishDate              | establishDate       | 成立日期      |
| corpAddress                    | registerAddress     | 注册地址      |
| corpLegalRep                   | legalRepresentative | 法定代表人     |
| corpLegalCertType              | legalCertType       | 法定代表人证件类型 |
| corpLegalCertNo                | legalCertNo         | 法定代表人证件号码 |
| corpShareholder1-5             | shareholder1-5      | 股东信息(1-5) |

**保持不变的字段:**

- remark (备注)
- intermediaryType (中介类型)
- status (状态)

---

## 三、文件修改清单

### 3.1 需要修改的文件

| 序号 | 文件路径                                                              | 修改类型 | 优先级 |
|----|-------------------------------------------------------------------|------|-----|
| 1  | `ruoyi-ui/src/api/ccdiIntermediary.js`                            | API层 | P0  |
| 2  | `ruoyi-ui/src/views/ccdiIntermediary/index.vue`                   | 主页面  | P0  |
| 3  | `ruoyi-ui/src/views/ccdiIntermediary/components/EditDialog.vue`   | 编辑组件 | P0  |
| 4  | `ruoyi-ui/src/views/ccdiIntermediary/components/DetailDialog.vue` | 详情组件 | P1  |
| 5  | `ruoyi-ui/src/views/ccdiIntermediary/components/ImportDialog.vue` | 导入组件 | P1  |

### 3.2 无需修改的文件

| 序号 | 文件路径             | 原因         |
|----|------------------|------------|
| 1  | `SearchForm.vue` | 查询参数与API兼容 |
| 2  | `DataTable.vue`  | 已使用友好名称字段  |

---

## 四、API层修改详情

### 4.1 ccdiIntermediary.js

#### 新增接口

```javascript
// 查询个人中介详情
export function getPersonIntermediary(bizId) {
  return request({
    url: '/ccdi/intermediary/person/' + bizId,
    method: 'get'
  })
}

// 查询实体中介详情
export function getEntityIntermediary(socialCreditCode) {
  return request({
    url: '/ccdi/intermediary/entity/' + socialCreditCode,
    method: 'get'
  })
}
```

#### 删除接口

```javascript
// 删除以下旧版统一接口
// getIntermediary(intermediaryId)
// addIntermediary(data)
// updateIntermediary(data)
```

---

## 五、主页面修改详情

### 5.1 index.vue - 数据模型

#### queryParams修改

```javascript
queryParams: {
  pageNum: 1,
  pageSize: 10,
  name: null,
  certificateNo: null,  // 保持不变(API查询参数兼容)
  intermediaryType: null,
  status: null
}
```

#### form数据模型

```javascript
form: {
  // 通用字段
  bizId: null,  // 原 intermediaryId
  intermediaryType: '1',
  status: '0',
  remark: null,

  // 个人中介字段
  name: null,
  personId: null,  // 原 certificateNo
  personType: null,  // 原 indivType
  personSubType: null,  // 原 indivSubType
  relationType: null,  // 原 indivRelation
  gender: null,  // 原 indivGender
  idType: null,  // 原 indivCertType
  mobile: null,  // 原 indivPhone
  wechatNo: null,  // 原 indivWechat
  contactAddress: null,  // 原 indivAddress
  company: null,  // 原 indivCompany
  socialCreditCode: null,  // 新增
  position: null,  // 原 indivPosition
  relatedNumId: null,  // 原 indivRelatedId

  // 实体中介字段
  enterpriseName: null,  // 原 name
  socialCreditCode: null,  // 原 certificateNo/corpCreditCode
  enterpriseType: null,  // 原 corpType
  enterpriseNature: null,  // 原 corpNature
  industryClass: null,  // 原 corpIndustryCategory
  industryName: null,  // 原 corpIndustry
  establishDate: null,  // 原 corpEstablishDate
  registerAddress: null,  // 原 corpAddress
  legalRepresentative: null,  // 原 corpLegalRep
  legalCertType: null,  // 原 corpLegalCertType
  legalCertNo: null,  // 原 corpLegalCertNo
  shareholder1: null,  // 原 corpShareholder1
  shareholder2: null,  // 原 corpShareholder2
  shareholder3: null,  // 原 corpShareholder3
  shareholder4: null,  // 原 corpShareholder4
  shareholder5: null   // 原 corpShareholder5
}
```

### 5.2 核心方法修改

#### handleSelectionChange

```javascript
handleSelectionChange(selection) {
  this.ids = selection.map(item => item.bizId);  // 原 intermediaryId
  this.single = selection.length !== 1;
  this.multiple = !selection.length;
}
```

#### handleDetail

```javascript
handleDetail(row) {
  if (row.intermediaryType === '1') {
    // 个人中介
    getPersonIntermediary(row.bizId).then(response => {
      this.detailData = response.data;
      this.detailOpen = true;
    });
  } else {
    // 实体中介
    getEntityIntermediary(row.socialCreditCode).then(response => {
      this.detailData = response.data;
      this.detailOpen = true;
    });
  }
}
```

#### handleUpdate

```javascript
handleUpdate(row) {
  this.reset();
  if (row.intermediaryType === '1') {
    getPersonIntermediary(row.bizId).then(response => {
      this.form = response.data;
      this.open = true;
      this.title = "修改中介黑名单";
    });
  } else {
    getEntityIntermediary(row.socialCreditCode).then(response => {
      this.form = response.data;
      this.open = true;
      this.title = "修改中介黑名单";
    });
  }
}
```

#### submitForm

```javascript
submitForm() {
  if (this.form.bizId != null) {  // 原 intermediaryId
    // 修改模式
    if (this.form.intermediaryType === '1') {
      updatePersonIntermediary(this.form).then(response => {
        this.$modal.msgSuccess("修改成功");
        this.open = false;
        this.getList();
      });
    } else {
      updateEntityIntermediary(this.form).then(response => {
        this.$modal.msgSuccess("修改成功");
        this.open = false;
        this.getList();
      });
    }
  } else {
    // 新增模式
    if (this.form.intermediaryType === '1') {
      addPersonIntermediary(this.form).then(response => {
        this.$modal.msgSuccess("新增成功");
        this.open = false;
        this.getList();
      });
    } else {
      addEntityIntermediary(this.form).then(response => {
        this.$modal.msgSuccess("新增成功");
        this.open = false;
        this.getList();
      });
    }
  }
}
```

#### handleDelete

```javascript
handleDelete(row) {
  const bizIds = row.bizId || this.ids.join(',');  // 原 intermediaryIds
  this.$modal.confirm('是否确认删除中介黑名单编号为"' + bizIds + '"的数据项？')
    .then(function() {
      return delIntermediary(bizIds);
    }).then(() => {
      this.getList();
      this.$modal.msgSuccess("删除成功");
    }).catch(() => {});
}
```

---

## 六、EditDialog组件修改详情

### 6.1 个人中介表单字段修改

| 行号  | 修改内容                                        |
|-----|---------------------------------------------|
| 46  | `form.certificateNo` → `form.personId`      |
| 54  | `form.indivType` → `form.personType`        |
| 66  | `form.indivSubType` → `form.personSubType`  |
| 80  | `form.indivGender` → `form.gender`          |
| 92  | `form.indivCertType` → `form.idType`        |
| 106 | `form.indivPhone` → `form.mobile`           |
| 110 | `form.indivWechat` → `form.wechatNo`        |
| 116 | `form.indivAddress` → `form.contactAddress` |
| 121 | `form.indivCompany` → `form.company`        |
| 126 | `form.indivPosition` → `form.position`      |
| 133 | `form.indivRelatedId` → `form.relatedNumId` |
| 138 | `form.indivRelation` → `form.relationType`  |

### 6.2 实体中介表单字段修改

| 行号      | 修改内容                                               |
|---------|----------------------------------------------------|
| 172     | `form.name` → `form.enterpriseName`                |
| 179     | `form.certificateNo` → `form.socialCreditCode`     |
| 190     | `form.corpType` → `form.enterpriseType`            |
| 202     | `form.corpNature` → `form.enterpriseNature`        |
| 227     | `form.corpIndustryCategory` → `form.industryClass` |
| 234     | `form.corpIndustry` → `form.industryName`          |
| 217     | `form.corpEstablishDate` → `form.establishDate`    |
| 239     | `form.corpAddress` → `form.registerAddress`        |
| 244     | `form.corpLegalRep` → `form.legalRepresentative`   |
| 249-251 | 添加下拉框:`form.legalCertType` (证件类型)                  |
| 254     | `form.corpLegalCertNo` → `form.legalCertNo`        |
| 260-284 | `form.corpShareholder1-5` → `form.shareholder1-5`  |

### 6.3 Script部分修改

#### computed属性

```javascript
isAddMode() {
  return !this.form || !this.form.bizId;  // 原 intermediaryId
}
```

#### initDialogState方法

```javascript
const isAdd = !this.form || !this.form.bizId;  // 原 intermediaryId
```

#### 删除方法

删除`handleCertificateNoChange`方法(v2.0无需字段同步)

#### 验证规则修改

**个人中介:**

```javascript
indivRules: {
  name: [
    { required: true, message: "姓名不能为空", trigger: "blur" },
    { max: 100, message: "姓名长度不能超过100个字符", trigger: "blur" }
  ],
  personId: [  // 原 certificateNo
    { required: true, message: "证件号不能为空", trigger: "blur" },
    { max: 50, message: "证件号长度不能超过50个字符", trigger: "blur" }
  ],
  remark: [
    { max: 500, message: "备注长度不能超过500个字符", trigger: "blur" }
  ]
}
```

**实体中介:**

```javascript
corpRules: {
  enterpriseName: [  // 原 name
    { required: true, message: "机构名称不能为空", trigger: "blur" },
    { max: 200, message: "机构名称长度不能超过200个字符", trigger: "blur" }
  ],
  socialCreditCode: [  // 原 certificateNo
    { required: true, message: "统一社会信用代码不能为空", trigger: "blur" },
    { max: 50, message: "统一社会信用代码长度不能超过50个字符", trigger: "blur" }
  ],
  remark: [
    { max: 500, message: "备注长度不能超过500个字符", trigger: "blur" }
  ]
}
```

---

## 七、DetailDialog组件修改详情

### 7.1 核心字段修改

```vue
<!-- 业务ID -->
<el-descriptions-item label="业务ID">{{ detailData.bizId }}</el-descriptions-item>

<!-- 证件号/信用代码 -->
<el-descriptions-item label="证件号/信用代码">
  <span v-if="detailData.intermediaryType === '1'">{{ detailData.personId || '-' }}</span>
  <span v-else>{{ detailData.socialCreditCode || '-' }}</span>
</el-descriptions-item>
```

### 7.2 个人中介字段修改

| 旧字段                        | 新字段                       |
|----------------------------|---------------------------|
| detailData.indivType       | detailData.personType     |
| detailData.indivSubType    | detailData.personSubType  |
| detailData.indivGenderName | detailData.genderName     |
| detailData.indivCertType   | detailData.idType         |
| detailData.indivPhone      | detailData.mobile         |
| detailData.indivWechat     | detailData.wechatNo       |
| detailData.indivAddress    | detailData.contactAddress |
| detailData.indivCompany    | detailData.company        |
| detailData.indivPosition   | detailData.position       |
| detailData.indivRelatedId  | detailData.relatedNumId   |
| detailData.indivRelation   | detailData.relationType   |

**新增字段:**

- detailData.socialCreditCode (企业统一信用码)

### 7.3 实体中介字段修改

| 旧字段                             | 新字段                            |
|---------------------------------|--------------------------------|
| detailData.corpCreditCode       | detailData.socialCreditCode    |
| detailData.corpType             | detailData.enterpriseType      |
| detailData.corpNature           | detailData.enterpriseNature    |
| detailData.corpIndustryCategory | detailData.industryClass       |
| detailData.corpIndustry         | detailData.industryName        |
| detailData.corpEstablishDate    | detailData.establishDate       |
| detailData.corpAddress          | detailData.registerAddress     |
| detailData.corpLegalRep         | detailData.legalRepresentative |
| detailData.corpLegalCertType    | detailData.legalCertType       |
| detailData.corpLegalCertNo      | detailData.legalCertNo         |
| detailData.corpShareholder1-5   | detailData.shareholder1-5      |

---

## 八、ImportDialog组件修改详情

### 8.1 模板下载URL修正

**错误代码:**

```javascript
this.download('dpc/intermediary/importPersonTemplate', ...)
this.download('dpc/intermediary/importEntityTemplate', ...)
```

**修正为:**

```javascript
handleDownloadTemplate() {
  if (this.formData.importType === 'person') {
    this.download('ccdi/intermediary/importPersonTemplate', {}, `个人中介黑名单模板_${new Date().getTime()}.xlsx`);
  } else {
    this.download('ccdi/intermediary/importEntityTemplate', {}, `机构中介黑名单模板_${new Date().getTime()}.xlsx`);
  }
}
```

---

## 九、下拉框优化

### 9.1 新增下拉框

**法定代表人证件类型** (实体中介表单)

```vue
<el-form-item label="法定代表人证件类型">
  <el-select v-model="form.legalCertType" placeholder="请选择证件类型" clearable style="width: 100%">
    <el-option
      v-for="item in certTypeOptions"
      :key="item.value"
      :label="item.label"
      :value="item.value"
    />
  </el-select>
</el-form-item>
```

### 9.2 已有下拉框验证

- ✅ 性别 (genderOptions)
- ✅ 证件类型 (certTypeOptions)
- ✅ 主体类型 (corpTypeOptions)
- ✅ 企业性质 (corpNatureOptions)
- ✅ 人员类型 (indivTypeOptions)
- ✅ 人员子类型 (indivSubTypeOptions)
- ✅ 关联关系 (relationTypeOptions)

---

## 十、测试计划

### 10.1 功能测试清单

**查询功能:**

- [ ] 列表查询正常显示
- [ ] 按姓名/机构名称模糊查询
- [ ] 按证件号精确查询
- [ ] 按中介类型筛选(个人/机构)
- [ ] 分页功能正常

**个人中介CRUD:**

- [ ] 新增个人中介 - 所有字段保存成功
- [ ] 查看个人中介详情 - 所有字段正确显示
- [ ] 修改个人中介 - 数据更新成功
- [ ] 删除个人中介 - 删除成功

**机构中介CRUD:**

- [ ] 新增机构中介 - 所有字段保存成功
- [ ] 查看机构中介详情 - 所有字段正确显示
- [ ] 修改机构中介 - 数据更新成功
- [ ] 删除机构中介 - 删除成功

**导入功能:**

- [ ] 下载个人中介导入模板成功
- [ ] 下载机构中介导入模板成功
- [ ] 个人中介数据导入成功
- [ ] 机构中介数据导入成功
- [ ] 导入时更新已存在数据功能正常

**下拉框验证:**

- [ ] 性别下拉框显示正确
- [ ] 证件类型下拉框显示正确
- [ ] 法定代表人证件类型下拉框显示正确
- [ ] 主体类型下拉框显示正确
- [ ] 企业性质下拉框显示正确

### 10.2 回归测试

- [ ] 权限控制正常
- [ ] 表单验证规则生效
- [ ] 错误提示信息正确
- [ ] 响应式布局正常
- [ ] 浏览器兼容性(Chrome/Firefox/Edge)

---

## 十一、风险与注意事项

### 11.1 兼容性风险

**影响范围**: 所有中介黑名单相关功能

**缓解措施**:

1. 完整的功能测试覆盖
2. 保留旧版代码备份
3. 分步骤部署,先测试环境验证

### 11.2 数据风险

**风险点**: 字段名变更可能导致数据丢失

**缓解措施**:

1. 确保后端已做好兼容处理
2. 导出测试数据进行对比验证
3. 增量导入测试

### 11.3 注意事项

1. **字段同步**: 确保前后端字段完全一致,不要遗留转换逻辑
2. **类型判断**: 所有详情查询必须根据`intermediaryType`调用不同接口
3. **验证规则**: 个人和实体中介的必填字段不同,需分别配置
4. **下拉框复用**: 法定代表人证件类型可复用`certTypeOptions`

---

## 十二、实施建议

### 12.1 实施步骤

1. **第一阶段**: API层修改
    - 新增详情查询接口
    - 删除旧版统一接口
    - 验证接口调用正常

2. **第二阶段**: 主页面修改
    - 修改数据模型
    - 修改核心方法
    - 测试查询和删除功能

3. **第三阶段**: 组件修改
    - EditDialog组件字段重命名
    - DetailDialog组件字段重命名
    - ImportDialog组件URL修正
    - 测试新增和修改功能

4. **第四阶段**: 全面测试
    - 功能测试
    - 回归测试
    - 兼容性测试

### 12.2 回滚方案

如发现问题严重,可按以下步骤回滚:

1. 恢复API层接口
2. 恢复前端文件备份
3. 重启前端服务
4. 清理浏览器缓存

---

## 附录

### 附录A: 相关文档

- [中介黑名单管理API文档-v2.0.md](../api/中介黑名单管理API文档-v2.0.md)
- [中介黑名单后端设计文档.md](../docs/中介黑名单后端.md)

### 附录B: 变更历史

| 版本   | 日期         | 作者     | 变更说明          |
|------|------------|--------|---------------|
| v1.0 | 2026-02-05 | Claude | 初始版本,完成前端适配设计 |

### 附录C: 审批记录

| 角色 | 姓名 | 审批状态 | 日期 |
|----|----|------|----|
| 开发 | -  | 待审批  | -  |
| 测试 | -  | 待审批  | -  |
| 产品 | -  | 待审批  | -  |
