Compare commits
4 Commits
worktree-l
...
dc8f1be4c3
| Author | SHA1 | Date | |
|---|---|---|---|
| dc8f1be4c3 | |||
| bc2959b93c | |||
| 72e2539134 | |||
| 16dc95de06 |
@@ -44,7 +44,32 @@
|
||||
"Bash(git rm:*)",
|
||||
"Bash(git add:*)",
|
||||
"Skill(document-skills:frontend-design)",
|
||||
"Bash(test:*)"
|
||||
"Bash(test:*)",
|
||||
"mcp__chrome-devtools__list_pages",
|
||||
"mcp__chrome-devtools__navigate_page",
|
||||
"mcp__chrome-devtools__take_snapshot",
|
||||
"mcp__chrome-devtools__take_screenshot",
|
||||
"mcp__zai-mcp-server__ui_to_artifact",
|
||||
"mcp__chrome-devtools__click",
|
||||
"Skill(backend-restart)",
|
||||
"Bash(tasklist:*)",
|
||||
"Bash(wmic:*)",
|
||||
"Bash(mvn spring-boot:run:*)",
|
||||
"Bash(timeout:*)",
|
||||
"mcp__chrome-devtools__wait_for",
|
||||
"Bash(start cmd /k \"mvn spring-boot:run -pl ruoyi-admin\")",
|
||||
"mcp__mysql__list_tables",
|
||||
"mcp__mysql__describe_table",
|
||||
"mcp__mysql__query",
|
||||
"Bash(grep:*)",
|
||||
"mcp__mysql__connect_db",
|
||||
"Skill(superpowers:writing-plans)",
|
||||
"Skill(superpowers:subagent-driven-development)",
|
||||
"Bash(chmod:*)",
|
||||
"Bash(ls:*)",
|
||||
"Bash(test_report.sh \")",
|
||||
"mcp__mysql__show_statement",
|
||||
"Bash(if not exist \"doc\\\\designs\" mkdir docdesigns)"
|
||||
]
|
||||
},
|
||||
"enabledMcpjsonServers": [
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
- 在进行需求分析与分解任务时,按照不同的模块分为不同的文件,创建模块名的文件夹并将对应文件保存在文件夹中,然后对模块的功能文件进行继续分解
|
||||
- 在使用/openspec:proposal时,自动开启深度思考模式,输入 “think more”、“think a lot”、“think harder” 或 “think longer” 触发更深层的思考
|
||||
- 在执行/openspec:apply后,使用code-simplifier 进行代码精简
|
||||
- 在分析生成需求文档时,每次都需要在doc目录下新建文件夹并以需求内容为命名
|
||||
|
||||
## Communication
|
||||
- 永远使用简体中文进行思考和对话
|
||||
|
||||
532
doc/designs/2026-02-04-intermediary-blacklist-design.md
Normal file
532
doc/designs/2026-02-04-intermediary-blacklist-design.md
Normal file
@@ -0,0 +1,532 @@
|
||||
# 中介黑名单管理模块 - 系统设计文档
|
||||
|
||||
## 文档信息
|
||||
|
||||
- **版本**: v1.0
|
||||
- **日期**: 2026-02-04
|
||||
- **作者**: Claude
|
||||
- **项目**: 纪检初核系统 (CCDI)
|
||||
|
||||
---
|
||||
|
||||
## 1. 概述
|
||||
|
||||
### 1.1 功能简介
|
||||
|
||||
中介黑名单管理模块提供个人中介和实体中介两类中介信息的完整管理功能,包括:
|
||||
- 个人中介的增删改查
|
||||
- 实体中介的增删改查
|
||||
- 统一列表查询(支持联合查询和个人/实体分类查询)
|
||||
- 带字典下拉框的Excel导入模板下载
|
||||
- 批量数据导入
|
||||
|
||||
### 1.2 核心特性
|
||||
|
||||
1. **双表存储**: 个人中介和实体中介分别存储在不同的数据表中
|
||||
2. **统一查询**: 使用SQL UNION实现高效的联合查询和分页
|
||||
3. **类型区分**: 通过`intermediary_type`字段区分个人(1)和实体(2)中介
|
||||
4. **智能筛选**: 实体中介通过`risk_level='1'`(高风险) AND `ent_source='INTERMEDIARY'(中介)`筛选
|
||||
5. **唯一性保证**: 个人中介的证件号`person_id`作为业务唯一键
|
||||
|
||||
### 1.3 技术栈
|
||||
|
||||
- **后端框架**: Spring Boot 3.5.8
|
||||
- **ORM框架**: MyBatis Plus 3.5.10
|
||||
- **Excel处理**: EasyExcel (带字典下拉框)
|
||||
- **数据库**: MySQL 8.2.0
|
||||
- **API文档**: SpringDoc 2.8.14
|
||||
|
||||
---
|
||||
|
||||
## 2. 数据库设计
|
||||
|
||||
### 2.1 个人中介表 (ccdi_biz_intermediary)
|
||||
|
||||
| 字段名 | 类型 | 可空 | 主键 | 注释 |
|
||||
|--------|------|------|------|------|
|
||||
| biz_id | VARCHAR | 否 | 是 | 人员ID |
|
||||
| person_type | VARCHAR | 否 | 否 | 人员类型(中介、职业背债人等) |
|
||||
| person_sub_type | VARCHAR | 是 | 否 | 人员子类型 |
|
||||
| relation_type | VARCHAR | 是 | 否 | 关系类型(配偶、子女、父母等) |
|
||||
| name | VARCHAR | 否 | 否 | 姓名 |
|
||||
| gender | CHAR | 是 | 否 | 性别 |
|
||||
| id_type | VARCHAR | 否 | 否 | 证件类型(默认身份证) |
|
||||
| person_id | VARCHAR | 否 | 否 | **证件号码(业务唯一键)** |
|
||||
| mobile | VARCHAR | 是 | 否 | 手机号码 |
|
||||
| wechat_no | VARCHAR | 是 | 否 | 微信号 |
|
||||
| contact_address | VARCHAR | 是 | 否 | 联系地址 |
|
||||
| company | VARCHAR | 是 | 否 | 所在公司 |
|
||||
| social_credit_code | VARCHAR | 是 | 否 | 企业统一信用码 |
|
||||
| position | VARCHAR | 是 | 否 | 职位 |
|
||||
| related_num_id | VARCHAR | 是 | 否 | 关联人员ID |
|
||||
| relation_type | VARCHAR | 是 | 否 | 关联关系 |
|
||||
| data_source | VARCHAR | 是 | 否 | 数据来源(MANUAL/SYSTEM/IMPORT/API) |
|
||||
| remark | VARCHAR | 是 | 否 | 备注信息 |
|
||||
| created_by | VARCHAR | 否 | 否 | 记录创建人 |
|
||||
| updated_by | VARCHAR | 是 | 否 | 记录更新人 |
|
||||
| create_time | DATETIME | 否 | 否 | 记录创建时间 |
|
||||
| update_time | DATETIME | 是 | 否 | 记录更新时间 |
|
||||
|
||||
**索引设计**:
|
||||
- PRIMARY KEY: `biz_id`
|
||||
- UNIQUE KEY: `uk_person_id` (`person_id`)
|
||||
|
||||
### 2.2 实体中介表 (ccdi_enterprise_base_info)
|
||||
|
||||
| 字段名 | 类型 | 可空 | 主键 | 注释 |
|
||||
|--------|------|------|------|------|
|
||||
| social_credit_code | VARCHAR | 否 | 是 | **统一社会信用代码(主键)** |
|
||||
| enterprise_name | VARCHAR | 否 | 否 | 企业名称 |
|
||||
| enterprise_type | VARCHAR | 否 | 否 | 企业类型(有限责任公司、股份有限公司等) |
|
||||
| enterprise_nature | VARCHAR | 是 | 否 | 企业性质(国企、民企、外企等) |
|
||||
| industry_class | VARCHAR | 是 | 否 | 行业分类 |
|
||||
| industry_name | VARCHAR | 是 | 否 | 所属行业 |
|
||||
| establish_date | DATE | 是 | 否 | 成立日期 |
|
||||
| register_address | VARCHAR | 是 | 否 | 注册地址 |
|
||||
| legal_representative | VARCHAR | 是 | 否 | 法定代表人 |
|
||||
| legal_cert_type | VARCHAR | 是 | 否 | 法定代表人证件类型 |
|
||||
| legal_cert_no | VARCHAR | 是 | 否 | 法定代表人证件号码 |
|
||||
| shareholder1-5 | VARCHAR | 是 | 否 | 股东信息 |
|
||||
| status | VARCHAR | 是 | 否 | 经营状态 |
|
||||
| create_time | DATETIME | 否 | 否 | 创建时间 |
|
||||
| update_time | DATETIME | 否 | 否 | 更新时间 |
|
||||
| created_by | VARCHAR | 否 | 否 | 创建人 |
|
||||
| updated_by | VARCHAR | 是 | 否 | 更新人 |
|
||||
| data_source | VARCHAR | 是 | 否 | 数据来源(MANUAL/SYSTEM/API/IMPORT) |
|
||||
| **risk_level** | VARCHAR(10) | 是 | 否 | **风险等级:1-高风险, 2-中风险, 3-低风险** |
|
||||
| **ent_source** | VARCHAR(20) | 否 | 否 | **企业来源:GENERAL/EMP_RELATION/CREDIT_CUSTOMER/INTERMEDIARY/BOTH** |
|
||||
|
||||
**索引设计**:
|
||||
- PRIMARY KEY: `social_credit_code`
|
||||
- INDEX: `idx_risk_ent_source` (`risk_level`, `ent_source`)
|
||||
|
||||
**实体中介筛选条件**:
|
||||
- `risk_level = '1'` (高风险)
|
||||
- `ent_source = 'INTERMEDIARY'` (中介)
|
||||
|
||||
---
|
||||
|
||||
## 3. 架构设计
|
||||
|
||||
### 3.1 整体架构
|
||||
|
||||
```
|
||||
Controller Layer (CcdiIntermediaryController)
|
||||
↓
|
||||
Service Layer (ICcdiIntermediaryService)
|
||||
↓
|
||||
Mapper Layer (CcdiBizIntermediaryMapper, CcdiEnterpriseBaseInfoMapper)
|
||||
↓
|
||||
Database (ccdi_biz_intermediary, ccdi_enterprise_base_info)
|
||||
```
|
||||
|
||||
### 3.2 分层说明
|
||||
|
||||
**Controller层**:
|
||||
- 统一的Controller处理个人和实体中介的请求
|
||||
- 使用不同的路径区分个人和实体中介操作
|
||||
- 权限控制: `ccdi:intermediary:*`
|
||||
|
||||
**Service层**:
|
||||
- 统一的服务接口
|
||||
- 根据中介类型路由到不同的业务逻辑
|
||||
- 处理唯一性校验、数据自动填充等业务规则
|
||||
|
||||
**Mapper层**:
|
||||
- 每个表对应独立的Mapper接口
|
||||
- 继承MyBatis Plus的BaseMapper
|
||||
- 自定义XML实现UNION联合查询
|
||||
|
||||
**DTO/VO层**:
|
||||
- 严格分离,不与Entity混用
|
||||
- DTO用于接口参数接收
|
||||
- VO用于数据返回
|
||||
|
||||
---
|
||||
|
||||
## 4. 接口设计
|
||||
|
||||
### 4.1 基础信息
|
||||
|
||||
- **基础路径**: `/ccdi/intermediary`
|
||||
- **权限前缀**: `ccdi:intermediary`
|
||||
- **响应格式**: AjaxResult
|
||||
|
||||
### 4.2 统一列表查询
|
||||
|
||||
**接口**: `GET /ccdi/intermediary/list`
|
||||
|
||||
**权限**: `ccdi:intermediary:list`
|
||||
|
||||
**请求参数**:
|
||||
| 参数名 | 类型 | 必填 | 说明 |
|
||||
|--------|------|------|------|
|
||||
| name | String | 否 | 姓名/机构名称(模糊查询) |
|
||||
| certificateNo | String | 否 | 证件号/统一社会信用代码(精确查询) |
|
||||
| intermediaryType | String | 否 | 中介类型(1=个人, 2=实体, null=全部) |
|
||||
| pageNum | Integer | 否 | 页码(默认1) |
|
||||
| pageSize | Integer | 否 | 每页数量(默认10) |
|
||||
|
||||
**响应**: TableDataInfo (分页结果)
|
||||
|
||||
**实现**: SQL UNION联合查询,支持按类型筛选优化
|
||||
|
||||
### 4.3 个人中介接口
|
||||
|
||||
#### 4.3.1 新增个人中介
|
||||
**接口**: `POST /ccdi/intermediary/person`
|
||||
**权限**: `ccdi:intermediary:add`
|
||||
**请求体**: CcdiIntermediaryPersonAddDTO
|
||||
**业务逻辑**:
|
||||
- 校验姓名必填
|
||||
- 校验证件号必填且唯一
|
||||
- 自动设置data_source='MANUAL'
|
||||
- 自动设置person_type='中介'
|
||||
|
||||
#### 4.3.2 修改个人中介
|
||||
**接口**: `PUT /ccdi/intermediary/person`
|
||||
**权限**: `ccdi:intermediary:edit`
|
||||
**请求体**: CcdiIntermediaryPersonEditDTO
|
||||
**业务逻辑**:
|
||||
- biz_id不可修改
|
||||
- 证件号修改时需校验唯一性(排除自身)
|
||||
|
||||
#### 4.3.3 查询个人中介详情
|
||||
**接口**: `GET /ccdi/intermediary/person/{bizId}`
|
||||
**权限**: `ccdi:intermediary:query`
|
||||
**响应**: CcdiIntermediaryPersonDetailVO
|
||||
|
||||
### 4.4 实体中介接口
|
||||
|
||||
#### 4.4.1 新增实体中介
|
||||
**接口**: `POST /ccdi/intermediary/entity`
|
||||
**权限**: `ccdi:intermediary:add`
|
||||
**请求体**: CcdiIntermediaryEntityAddDTO
|
||||
**业务逻辑**:
|
||||
- 校验企业名称必填
|
||||
- 校验统一社会信用代码唯一
|
||||
- 自动设置risk_level='1'(高风险)
|
||||
- 自动设置ent_source='INTERMEDIARY'(中介)
|
||||
- 自动设置data_source='MANUAL'
|
||||
|
||||
#### 4.4.2 修改实体中介
|
||||
**接口**: `PUT /ccdi/intermediary/entity`
|
||||
**权限**: `ccdi:intermediary:edit`
|
||||
**请求体**: CcdiIntermediaryEntityEditDTO
|
||||
**业务逻辑**:
|
||||
- social_credit_code不可修改
|
||||
- 企业名称修改时需校验唯一性(排除自身)
|
||||
|
||||
#### 4.4.3 查询实体中介详情
|
||||
**接口**: `GET /ccdi/intermediary/entity/{socialCreditCode}`
|
||||
**权限**: `ccdi:intermediary:query`
|
||||
**响应**: CcdiIntermediaryEntityDetailVO
|
||||
|
||||
### 4.5 删除接口
|
||||
|
||||
**接口**: `DELETE /ccdi/intermediary/{ids}`
|
||||
**权限**: `ccdi:intermediary:remove`
|
||||
**路径参数**: ids (支持个人和实体的ID,逗号分隔)
|
||||
|
||||
### 4.6 导入导出接口
|
||||
|
||||
#### 4.6.1 个人中介模板下载
|
||||
**接口**: `POST /ccdi/intermediary/importPersonTemplate`
|
||||
**权限**: 无需登录
|
||||
**功能**: 下载带字典下拉框的Excel模板
|
||||
**下拉字段**:
|
||||
- 性别: `ccdi_indiv_gender`
|
||||
- 证件类型: `ccdi_certificate_type`
|
||||
- 关联关系: `ccdi_relation_type`
|
||||
|
||||
#### 4.6.2 实体中介模板下载
|
||||
**接口**: `POST /ccdi/intermediary/importEntityTemplate`
|
||||
**权限**: 无需登录
|
||||
**功能**: 下载带字典下拉框的Excel模板
|
||||
**下拉字段**:
|
||||
- 主体类型: `ccdi_entity_type`
|
||||
- 企业性质: `ccdi_enterprise_nature`
|
||||
- 法人证件类型: `ccdi_certificate_type`
|
||||
|
||||
#### 4.6.3 个人中介数据导入
|
||||
**接口**: `POST /ccdi/intermediary/importPersonData`
|
||||
**权限**: `ccdi:intermediary:import`
|
||||
**参数**:
|
||||
- file: MultipartFile
|
||||
- updateSupport: Boolean (是否更新已存在数据)
|
||||
**Excel类**: CcdiIntermediaryPersonExcel
|
||||
**业务逻辑**:
|
||||
- 解析Excel数据
|
||||
- 校验姓名必填、证件号必填
|
||||
- 检查person_id唯一性
|
||||
- 批量插入ccdi_biz_intermediary表
|
||||
- 自动设置: data_source='IMPORT', person_type='中介'
|
||||
|
||||
#### 4.6.4 实体中介数据导入
|
||||
**接口**: `POST /ccdi/intermediary/importEntityData`
|
||||
**权限**: `ccdi:intermediary:import`
|
||||
**参数**:
|
||||
- file: MultipartFile
|
||||
- updateSupport: Boolean (是否更新已存在数据)
|
||||
**Excel类**: CcdiIntermediaryEntityExcel
|
||||
**业务逻辑**:
|
||||
- 解析Excel数据
|
||||
- 校验企业名称必填
|
||||
- 检查social_credit_code唯一性
|
||||
- 批量插入ccdi_enterprise_base_info表
|
||||
- 自动设置: risk_level='1', ent_source='INTERMEDIARY', data_source='IMPORT'
|
||||
|
||||
---
|
||||
|
||||
## 5. UNION联合查询实现
|
||||
|
||||
### 5.1 SQL查询语句
|
||||
|
||||
```xml
|
||||
<select id="selectIntermediaryList" resultType="CcdiIntermediaryVO">
|
||||
<!-- 查询个人中介 -->
|
||||
SELECT
|
||||
biz_id as id,
|
||||
name,
|
||||
person_id as certificate_no,
|
||||
'1' as intermediary_type,
|
||||
person_type,
|
||||
gender,
|
||||
id_type,
|
||||
mobile,
|
||||
company,
|
||||
data_source,
|
||||
create_time
|
||||
FROM ccdi_biz_intermediary
|
||||
WHERE person_type = '中介'
|
||||
<if test="intermediaryType == null or intermediaryType == '1'">
|
||||
AND name LIKE CONCAT('%', #{name}, '%')
|
||||
<if test="certificateNo != null and certificateNo != ''">
|
||||
AND person_id = #{certificateNo}
|
||||
</if>
|
||||
</if>
|
||||
|
||||
UNION ALL
|
||||
|
||||
<!-- 查询实体中介 -->
|
||||
SELECT
|
||||
social_credit_code as id,
|
||||
enterprise_name as name,
|
||||
social_credit_code as certificate_no,
|
||||
'2' as intermediary_type,
|
||||
'实体' as person_type,
|
||||
null as gender,
|
||||
null as id_type,
|
||||
null as mobile,
|
||||
enterprise_name as company,
|
||||
data_source,
|
||||
create_time
|
||||
FROM ccdi_enterprise_base_info
|
||||
WHERE risk_level = '1' AND ent_source = 'INTERMEDIARY'
|
||||
<if test="intermediaryType == null or intermediaryType == '2'">
|
||||
AND enterprise_name LIKE CONCAT('%', #{name}, '%')
|
||||
<if test="certificateNo != null and certificateNo != ''">
|
||||
AND social_credit_code = #{certificateNo}
|
||||
</if>
|
||||
</if>
|
||||
|
||||
ORDER BY create_time DESC
|
||||
</select>
|
||||
```
|
||||
|
||||
### 5.2 分页实现
|
||||
|
||||
- 使用MyBatis Plus的Page对象进行分页
|
||||
- 在Service层调用`page(intermediaryQueryDTO, Page)`方法
|
||||
- 自动处理total和rows
|
||||
|
||||
### 5.3 查询优化
|
||||
|
||||
- 根据intermediaryType参数优化查询,如果指定类型则只查询对应表
|
||||
- 添加索引优化查询性能
|
||||
|
||||
---
|
||||
|
||||
## 6. 数据对象设计
|
||||
|
||||
### 6.1 Entity实体类
|
||||
|
||||
**CcdiBizIntermediary**:
|
||||
- 使用`@Data`注解
|
||||
- 不继承BaseEntity
|
||||
- 单独添加审计字段
|
||||
- 主键: biz_id (String)
|
||||
|
||||
**CcdiEnterpriseBaseInfo**:
|
||||
- 使用`@Data`注解
|
||||
- 不继承BaseEntity
|
||||
- 单独添加审计字段
|
||||
- 主键: social_credit_code (String)
|
||||
|
||||
### 6.2 DTO数据传输对象
|
||||
|
||||
**CcdiIntermediaryPersonAddDTO**: 个人中介新增DTO
|
||||
- 包含所有个人字段
|
||||
- 使用JSR-303校验注解
|
||||
|
||||
**CcdiIntermediaryPersonEditDTO**: 个人中介修改DTO
|
||||
- 包含biz_id和可编辑字段
|
||||
- biz_id不可为空
|
||||
|
||||
**CcdiIntermediaryEntityAddDTO**: 实体中介新增DTO
|
||||
- 包含所有企业字段
|
||||
- 使用JSR-303校验注解
|
||||
|
||||
**CcdiIntermediaryEntityEditDTO**: 实体中介修改DTO
|
||||
- 包含social_credit_code和可编辑字段
|
||||
- social_credit_code不可为空
|
||||
|
||||
**CcdiIntermediaryQueryDTO**: 统一查询DTO
|
||||
- 支持: name, certificateNo, intermediaryType筛选
|
||||
|
||||
### 6.3 VO视图对象
|
||||
|
||||
**CcdiIntermediaryVO**: 统一列表VO
|
||||
- 包含intermediary_type字段区分类型(1=个人, 2=实体)
|
||||
- 统一字段: id, name, certificate_no, intermediary_type, company, create_time等
|
||||
|
||||
**CcdiIntermediaryPersonDetailVO**: 个人中介详情VO
|
||||
- 包含个人中介的所有详细信息
|
||||
|
||||
**CcdiIntermediaryEntityDetailVO**: 实体中介详情VO
|
||||
- 包含实体中介的所有详细信息
|
||||
|
||||
### 6.4 Excel导入导出类
|
||||
|
||||
**CcdiIntermediaryPersonExcel**: 个人中介Excel类
|
||||
- 使用EasyExcel注解
|
||||
- 字段校验和格式化
|
||||
|
||||
**CcdiIntermediaryEntityExcel**: 实体中介Excel类
|
||||
- 使用EasyExcel注解
|
||||
- 字段校验和格式化
|
||||
|
||||
---
|
||||
|
||||
## 7. 业务规则
|
||||
|
||||
### 7.1 唯一性约束
|
||||
|
||||
1. **个人中介**:
|
||||
- `person_id`(证件号)必须唯一
|
||||
- 新增时检查是否已存在
|
||||
- 修改时检查是否已存在(排除自身)
|
||||
|
||||
2. **实体中介**:
|
||||
- `social_credit_code`(统一社会信用代码)必须唯一
|
||||
- 新增时检查是否已存在
|
||||
- 修改时检查是否已存在(排除自身)
|
||||
|
||||
### 7.2 数据自动填充
|
||||
|
||||
**个人中介**:
|
||||
- data_source: MANUAL(手动录入) / IMPORT(批量导入)
|
||||
- person_type: 中介
|
||||
|
||||
**实体中介**:
|
||||
- risk_level: 1 (高风险)
|
||||
- ent_source: INTERMEDIARY (中介)
|
||||
- data_source: MANUAL(手动录入) / IMPORT(批量导入)
|
||||
|
||||
### 7.3 字典类型
|
||||
|
||||
| 字典类型 | 用途 |
|
||||
|---------|------|
|
||||
| ccdi_indiv_gender | 个人中介性别 |
|
||||
| ccdi_certificate_type | 证件类型 |
|
||||
| ccdi_relation_type | 关联关系 |
|
||||
| ccdi_entity_type | 主体类型 |
|
||||
| ccdi_enterprise_nature | 企业性质 |
|
||||
|
||||
---
|
||||
|
||||
## 8. 错误处理
|
||||
|
||||
### 8.1 业务错误码
|
||||
|
||||
| 错误码 | 说明 |
|
||||
|--------|------|
|
||||
| 1001 | 证件号已存在 |
|
||||
| 1002 | 统一社会信用代码已存在 |
|
||||
| 1003 | 数据不存在 |
|
||||
| 1004 | 姓名不能为空 |
|
||||
| 1005 | 证件号不能为空 |
|
||||
| 1006 | 企业名称不能为空 |
|
||||
|
||||
### 8.2 异常处理策略
|
||||
|
||||
- 使用`@ControllerAdvice`全局异常处理
|
||||
- 业务异常使用自定义BizException
|
||||
- 参数校验异常自动返回字段错误信息
|
||||
|
||||
---
|
||||
|
||||
## 9. 测试策略
|
||||
|
||||
### 9.1 单元测试
|
||||
|
||||
- Service层业务逻辑测试
|
||||
- Mapper层SQL查询测试
|
||||
- 唯一性校验测试
|
||||
|
||||
### 9.2 集成测试
|
||||
|
||||
- Controller接口测试
|
||||
- 导入导出功能测试
|
||||
- 联合查询分页测试
|
||||
|
||||
### 9.3 测试脚本
|
||||
|
||||
- 生成可执行的HTTP测试脚本
|
||||
- 使用admin/admin123账号获取token
|
||||
- 保存测试结果并生成测试报告
|
||||
|
||||
---
|
||||
|
||||
## 10. 实现计划
|
||||
|
||||
### 10.1 开发顺序
|
||||
|
||||
1. 创建Entity实体类
|
||||
2. 创建Mapper接口和XML
|
||||
3. 创建DTO/VO对象
|
||||
4. 实现Service层业务逻辑
|
||||
5. 实现Controller层接口
|
||||
6. 实现Excel导入导出功能
|
||||
7. 编写测试用例
|
||||
8. 生成API文档
|
||||
|
||||
### 10.2 技术要点
|
||||
|
||||
- 使用MyBatis Plus的BaseMapper简化CRUD操作
|
||||
- 使用@Resource注入,替代@Autowired
|
||||
- 实体类不继承BaseEntity,单独添加审计字段
|
||||
- 简单CRUD使用MyBatis Plus方法,复杂查询使用XML
|
||||
- 所有Controller接口添加完整的Swagger注解
|
||||
- 使用@Validated和JSR-303进行参数校验
|
||||
|
||||
---
|
||||
|
||||
## 11. 附录
|
||||
|
||||
### 11.1 相关文档
|
||||
|
||||
- [中介黑名单管理API文档.md](../api/中介黑名单管理API文档.md)
|
||||
- [中介黑名单后端.md](../docs/中介黑名单后端.md)
|
||||
- [ccdi_biz_intermediary.csv](../docs/ccdi_biz_intermediary.csv)
|
||||
- [ccdi_enterprise_base_info.csv](../docs/ccdi_enterprise_base_info.csv)
|
||||
|
||||
### 11.2 更新日志
|
||||
|
||||
| 版本 | 日期 | 说明 |
|
||||
|------|------|------|
|
||||
| 1.0 | 2026-02-04 | 初始版本,完成系统设计 |
|
||||
|
||||
---
|
||||
|
||||
**文档结束**
|
||||
24
doc/docs/ccdi_biz_intermediary.csv
Normal file
24
doc/docs/ccdi_biz_intermediary.csv
Normal file
@@ -0,0 +1,24 @@
|
||||
中介人员基本信息表:ccdi_biz_intermediary,,,,,,
|
||||
序号,字段名,类型,默认值,是否可为空,是否主键,注释
|
||||
1,biz_id,VARCHAR,-,否,是,人员ID
|
||||
2,person_type,VARCHAR,-,否,否,人员类型,中介、职业背债人、房产中介等
|
||||
3,person_sub_type,VARCHAR,-,是,否,人员子类型
|
||||
4,relation_type,VARCHAR,-,否,-,关系类型,如:配偶、子女、父母、兄弟姐妹等
|
||||
5,name,VARCHAR,-,否,否,姓名
|
||||
6,gender,CHAR,-,是,否,性别
|
||||
7,id_type,VARCHAR,身份证,否,否,证件类型
|
||||
8,person_id,VARCHAR,-,否,否,证件号码
|
||||
9,mobile,VARCHAR,-,是,否,手机号码
|
||||
10,wechat_no,VARCHAR,-,是,否,微信号
|
||||
11,contact_address,VARCHAR,-,是,否,联系地址
|
||||
12,company,VARCHAR,-,是,否,所在公司
|
||||
13,social_credit_code,VARCHAR,,,,企业统一信用码
|
||||
14,position,VARCHAR,-,是,否,职位
|
||||
15,related_num_id,VARCHAR,-,是,否,关联人员ID
|
||||
16,relation_type,VARCHAR,-,是,否,关联关系
|
||||
17,date_source,,,,,"数据来源,MANUAL:手动录入, SYSTEM:系统同步, IMPORT:批量导入, API:接口获取"
|
||||
18,remark,,,,,备注信息
|
||||
19,created_by,VARCHAR,-,否,-,记录创建人
|
||||
20,updated_by,VARCHAR,-,是,-,记录更新人
|
||||
21,create_time,DATETIME,,否,,记录创建时间
|
||||
22,update_time,DATETIME,-,是,-,记录更新时间
|
||||
|
26
doc/docs/ccdi_enterprise_base_info.csv
Normal file
26
doc/docs/ccdi_enterprise_base_info.csv
Normal file
@@ -0,0 +1,26 @@
|
||||
3.企业主体信息表:ccdi_enterprise_base_info,,,,,,
|
||||
序号,字段名,类型,默认值,是否可为空,是否主键,注释
|
||||
1,social_credit_code,VARCHAR,-,否,是,统一社会信用代码,员工企业关联关系表的外键
|
||||
2,enterprise_name,VARCHAR,-,否,-,企业名称
|
||||
3,enterprise_type,VARCHAR,-,否,-,"企业类型,有限责任公司、股份有限公司、合伙企业、个体工商户、外资企业等"
|
||||
4,enterprise_nature,VARCHAR,-,是,-,"企业性质,国企、民企、外企、合资、其他"
|
||||
5,industry_class,VARCHAR,-,是,-,行业分类
|
||||
6,industry_name,VARCHAR,-,是,-,所属行业
|
||||
7,establish_date,DATE,-,是,-,成立日期
|
||||
8,register_address,VARCHAR,-,是,-,注册地址
|
||||
9,legal_representative,VARCHAR,-,是,-,法定代表人
|
||||
10,legal_cert_type,VARCHAR,-,是,-,法定代表人证件类型
|
||||
11,legal_cert_no,VARCHAR,-,是,-,法定代表人证件号码
|
||||
12,shareholder1,VARCHAR,-,是,-,股东1
|
||||
13,shareholder2,VARCHAR,-,是,-,股东2
|
||||
14,shareholder3,VARCHAR,-,是,-,股东3
|
||||
15,shareholder4,VARCHAR,-,是,-,股东4
|
||||
16,shareholder5,VARCHAR,-,是,-,股东5
|
||||
17,status,VARCHAR,,,,经营状态
|
||||
18,create_time,DATETIME,当前时间,否,-,创建时间
|
||||
19,update_time,DATETIME,当前时间,否,-,更新时间
|
||||
20,created_by,VARCHAR,-,否,-,创建人
|
||||
21,updated_by,VARCHAR,-,是,-,更新人
|
||||
22,data_source,VARCHAR,MANUAL,是,-,"数据来源,MANUAL:手动录入, SYSTEM:系统同步, API:接口获取, IMPORT:批量导入"
|
||||
23,risk_level,VARCHAR(10),1,是,否,"风险等级:1-高风险, 2-中风险, 3-低风险"
|
||||
24,ent_source,VARCHAR(20),GENERAL,否,否,"企业来源:GENERAL-一般企业, EMP_RELATION-员工关系人, CREDIT_CUSTOMER-信贷客户, INTERMEDIARY-中介, BOTH-兼有"
|
||||
|
1
doc/docs/中介黑名单后端.md
Normal file
1
doc/docs/中介黑名单后端.md
Normal file
@@ -0,0 +1 @@
|
||||
实现中介黑名单管理的后端接口开发。中介分为个人中介和实体中介。个人中介的表字段为 @ccdi_biz_intermediary.csv。实体中介表字段为 @ccdi_enterprise_base_info.csv,风险等级为高风险,企业来源为中介。需要生成的接口:个人中介的新增、修改接口,以证件号为关联键;个人中介导入模板下载,个人中介文件上传导入新增;实体中介类的新增、修改接口;实体中介导入模板下载,上传导入新增;列表查询,要求联合查询两种类型的中介,也可以支持查询单种类的中介。
|
||||
919
doc/frontend/上传数据页面UI设计文档.md
Normal file
919
doc/frontend/上传数据页面UI设计文档.md
Normal file
@@ -0,0 +1,919 @@
|
||||
# 上传数据页面 UI 设计文档
|
||||
|
||||
## 1. 页面概述
|
||||
|
||||
### 1.1 功能描述
|
||||
上传数据页面是纪检初核系统中项目管理模块的核心页面,支持在一个项目中上传多个主体/账户数据进行汇总/独立分析。提供流水导入、征信导入、员工家庭关系导入、名单库选择等功能。
|
||||
|
||||
### 1.2 页面路径
|
||||
- 菜单位置:项目管理 > 项目详情 > 上传数据
|
||||
- 路由路径:`/project/:id/upload-data`
|
||||
|
||||
### 1.3 页面状态
|
||||
- 项目状态:已完成
|
||||
- 最后更新时间:2024-01-20 15:30
|
||||
|
||||
---
|
||||
|
||||
## 2. 页面布局
|
||||
|
||||
### 2.1 整体结构
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 面包屑导航:项目管理 / 项目详情 / 上传数据 │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ 页面标题区 │
|
||||
│ ┌───────────────────────────────────────────────────────┐ │
|
||||
│ │ 上传数据 │ │
|
||||
│ │ 项目状态:已完成 最后更新:2024-01-20 15:30 │ │
|
||||
│ │ 支持在一个项目中上传多个主体/账户数据,进行汇总/独立分析 │ │
|
||||
│ └───────────────────────────────────────────────────────┘ │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ 主要内容区(网格布局) │
|
||||
│ ┌─────────────────┐ ┌─────────────────┐ │
|
||||
│ │ 流水导入 │ │ 已上传流水查询 │ │
|
||||
│ │ [上传组件] │ │ [上传组件] │ │
|
||||
│ └─────────────────┘ └─────────────────┘ │
|
||||
│ ┌─────────────────┐ ┌─────────────────┐ │
|
||||
│ │ 征信导入 │ │ 员工家庭关系导入 │ │
|
||||
│ │ [上传组件] │ │ [上传组件] │ │
|
||||
│ └─────────────────┘ └─────────────────┘ │
|
||||
│ ┌─────────────────────────────────────────────┐ │
|
||||
│ │ 名单库选择 │ │
|
||||
│ │ ☑ 高风险人员名单(68人) ☑ 历史可疑人员名单 │ │
|
||||
│ │ ☑ 监管关注名单(32人) │ │
|
||||
│ └─────────────────────────────────────────────┘ │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ 数据质量检查区 │
|
||||
│ ┌────────────────────────────────────────────────────────┐ │
|
||||
│ │ 数据完整性 格式一致性 余额连续性 │ │
|
||||
│ │ 98.5% 95.2% 92.8% │ │
|
||||
│ │ 检查结果: [查看详情] │ │
|
||||
│ │ • 发现 23 条数据格式不一致 │ │
|
||||
│ │ • 发现 5 条余额连续性异常 │ │
|
||||
│ │ • 发现 12 条缺失关键字段 │ │
|
||||
│ └────────────────────────────────────────────────────────┘ │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ 操作按钮区 │
|
||||
│ [拉取本行信息] [生成报告] │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 2.2 响应式布局
|
||||
- 桌面端(≥1200px):4列网格布局
|
||||
- 平板端(768px-1199px):2列网格布局
|
||||
- 移动端(<768px):单列布局
|
||||
|
||||
---
|
||||
|
||||
## 3. 组件设计
|
||||
|
||||
### 3.1 FileUploadCard 上传卡片组件
|
||||
|
||||
**Props:**
|
||||
```typescript
|
||||
interface FileUploadCardProps {
|
||||
title: string; // 卡片标题
|
||||
description: string; // 描述文字
|
||||
acceptTypes: string[]; // 接受的文件类型,如 ['xlsx', 'xls', 'pdf']
|
||||
maxSize?: number; // 最大文件大小(MB),默认 10
|
||||
multiple?: boolean; // 是否支持多文件上传
|
||||
uploadUrl: string; // 上传接口地址
|
||||
onUploadSuccess?: (files: UploadedFile[]) => void;
|
||||
onUploadError?: (error: Error) => void;
|
||||
showFileList?: boolean; // 是否显示已上传文件列表
|
||||
}
|
||||
```
|
||||
|
||||
**UI 结构:**
|
||||
```vue
|
||||
<template>
|
||||
<el-card class="upload-card">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<h3>{{ title }}</h3>
|
||||
<el-tooltip :content="description" placement="top">
|
||||
<i class="el-icon-info"></i>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<el-upload
|
||||
class="upload-area"
|
||||
:action="uploadUrl"
|
||||
:accept="acceptTypes.join(',')"
|
||||
:multiple="multiple"
|
||||
:limit="10"
|
||||
:file-list="fileList"
|
||||
:on-success="handleSuccess"
|
||||
:on-error="handleError"
|
||||
:before-upload="beforeUpload"
|
||||
drag
|
||||
>
|
||||
<div class="upload-content">
|
||||
<i class="el-icon-upload"></i>
|
||||
<p>拖拽文件到此处或点击上传</p>
|
||||
<p class="upload-tip">支持格式: {{ acceptTypes.join(', ') }}</p>
|
||||
</div>
|
||||
</el-upload>
|
||||
|
||||
<div v-if="showFileList && uploadedFiles.length" class="file-list">
|
||||
<h4>已上传文件</h4>
|
||||
<el-table :data="uploadedFiles" size="small">
|
||||
<el-table-column prop="fileName" label="文件名" />
|
||||
<el-table-column prop="fileSize" label="大小" width="100" />
|
||||
<el-table-column prop="uploadTime" label="上传时间" width="160" />
|
||||
<el-table-column prop="status" label="状态" width="80">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.status === 'success' ? 'success' : 'danger'">
|
||||
{{ row.status === 'success' ? '成功' : '失败' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="100" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button type="text" size="small" @click="handleDelete(row)">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
```
|
||||
|
||||
### 3.2 CheckboxGroupSelector 名单库选择组件
|
||||
|
||||
**Props:**
|
||||
```typescript
|
||||
interface CheckboxGroupSelectorProps {
|
||||
options: NameListOption[];
|
||||
modelValue: string[];
|
||||
onChange: (value: string[]) => void;
|
||||
}
|
||||
|
||||
interface NameListOption {
|
||||
label: string; // 显示文本
|
||||
value: string; // 选中值
|
||||
count: number; // 人数统计
|
||||
disabled?: boolean;
|
||||
}
|
||||
```
|
||||
|
||||
**UI 结构:**
|
||||
```vue
|
||||
<template>
|
||||
<el-card class="name-list-selector">
|
||||
<template #header>
|
||||
<h3>名单库选择</h3>
|
||||
</template>
|
||||
<p class="selector-description">选择中介库管理内的名单</p>
|
||||
<el-checkbox-group v-model="selectedLists" @change="handleChange">
|
||||
<el-checkbox
|
||||
v-for="option in options"
|
||||
:key="option.value"
|
||||
:label="option.value"
|
||||
:disabled="option.disabled"
|
||||
>
|
||||
{{ option.label }}({{ option.count }}人)
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-card>
|
||||
</template>
|
||||
```
|
||||
|
||||
### 3.3 DataQualityPanel 数据质量检查面板
|
||||
|
||||
**Props:**
|
||||
```typescript
|
||||
interface DataQualityPanelProps {
|
||||
metrics: QualityMetric[];
|
||||
issues: QualityIssue[];
|
||||
onCheckQuality?: () => void;
|
||||
onViewDetails?: (issue: QualityIssue) => void;
|
||||
}
|
||||
|
||||
interface QualityMetric {
|
||||
name: string; // 指标名称
|
||||
value: number; // 百分比值
|
||||
status: 'good' | 'warning' | 'error';
|
||||
}
|
||||
|
||||
interface QualityIssue {
|
||||
type: string; // 问题类型
|
||||
count: number; // 数量
|
||||
description: string;
|
||||
details?: any[];
|
||||
}
|
||||
```
|
||||
|
||||
**UI 结构:**
|
||||
```vue
|
||||
<template>
|
||||
<el-card class="quality-panel">
|
||||
<template #header>
|
||||
<div class="panel-header">
|
||||
<h3>数据质量检查</h3>
|
||||
<el-button type="primary" size="small" @click="handleCheck">
|
||||
重新检查
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 质量指标 -->
|
||||
<div class="metrics-container">
|
||||
<div
|
||||
v-for="metric in metrics"
|
||||
:key="metric.name"
|
||||
class="metric-item"
|
||||
:class="`metric-${metric.status}`"
|
||||
>
|
||||
<el-progress
|
||||
type="circle"
|
||||
:percentage="metric.value"
|
||||
:status="metric.status"
|
||||
/>
|
||||
<span class="metric-name">{{ metric.name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 问题列表 -->
|
||||
<div class="issues-section">
|
||||
<h4>检查结果</h4>
|
||||
<el-alert
|
||||
v-for="(issue, index) in issues"
|
||||
:key="index"
|
||||
:type="getIssueType(issue)"
|
||||
:closable="false"
|
||||
class="issue-item"
|
||||
>
|
||||
<template #title>
|
||||
发现 <strong>{{ issue.count }}</strong> {{ issue.description }}
|
||||
</template>
|
||||
</el-alert>
|
||||
<el-button type="text" @click="handleViewDetails">查看详情 →</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 交互说明
|
||||
|
||||
### 4.1 文件上传流程
|
||||
|
||||
1. **拖拽上传**
|
||||
- 用户拖拽文件到上传区域
|
||||
- 显示上传进度条
|
||||
- 上传成功后显示成功提示
|
||||
- 自动添加到已上传文件列表
|
||||
|
||||
2. **点击上传**
|
||||
- 点击上传区域触发文件选择对话框
|
||||
- 选择文件后开始上传
|
||||
- 显示上传进度
|
||||
|
||||
3. **文件验证**
|
||||
- 文件格式验证:只接受指定格式
|
||||
- 文件大小验证:超过限制显示错误提示
|
||||
- 重复文件验证:同名文件提示是否覆盖
|
||||
|
||||
4. **上传状态**
|
||||
- 上传中:显示进度条
|
||||
- 上传成功:绿色勾选标记
|
||||
- 上传失败:红色错误标记,显示错误信息
|
||||
|
||||
### 4.2 名单库选择
|
||||
|
||||
1. 默认选中全部名单库
|
||||
2. 点击复选框切换选中状态
|
||||
3. 实时更新选中人数统计
|
||||
4. 取消选中时显示确认提示
|
||||
|
||||
### 4.3 数据质量检查
|
||||
|
||||
1. **自动触发**
|
||||
- 文件上传完成后自动触发
|
||||
- 显示检查进度
|
||||
|
||||
2. **手动触发**
|
||||
- 点击"重新检查"按钮
|
||||
- 覆盖之前的检查结果
|
||||
|
||||
3. **结果展示**
|
||||
- 三个核心指标以环形进度图展示
|
||||
- 颜色指示:绿色(≥95%)、黄色(85-94%)、红色(<85%)
|
||||
- 问题列表按严重程度排序
|
||||
|
||||
### 4.4 按钮操作
|
||||
|
||||
1. **拉取本行信息**
|
||||
- 点击后显示加载状态
|
||||
- 从本行系统拉取相关数据
|
||||
- 完成后显示成功提示并刷新页面
|
||||
|
||||
2. **生成报告**
|
||||
- 验证必须上传至少一个文件
|
||||
- 显示报告生成进度
|
||||
- 生成成功后跳转到报告页面
|
||||
|
||||
---
|
||||
|
||||
## 5. 数据结构
|
||||
|
||||
### 5.1 后端接口
|
||||
|
||||
#### 5.1.1 获取项目上传数据状态
|
||||
```typescript
|
||||
GET /api/project/{projectId}/upload-status
|
||||
|
||||
Response:
|
||||
{
|
||||
"code": 200,
|
||||
"data": {
|
||||
"projectStatus": "已完成",
|
||||
"lastUpdateTime": "2024-01-20 15:30:00",
|
||||
"uploadedFiles": {
|
||||
"transactionFiles": [], // 流水文件列表
|
||||
"inquiryFiles": [], // 征信文件列表
|
||||
"familyRelationFiles": [] // 家庭关系文件列表
|
||||
},
|
||||
"selectedNameLists": [], // 已选名单库
|
||||
"qualityMetrics": { // 质量指标
|
||||
"completeness": 98.5,
|
||||
"consistency": 95.2,
|
||||
"continuity": 92.8
|
||||
},
|
||||
"qualityIssues": [] // 质量问题列表
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 5.1.2 上传文件接口
|
||||
```typescript
|
||||
POST /api/project/{projectId}/upload
|
||||
Content-Type: multipart/form-data
|
||||
|
||||
Body:
|
||||
{
|
||||
"fileType": "transaction" | "inquiry" | "family_relation",
|
||||
"files": File[]
|
||||
}
|
||||
|
||||
Response:
|
||||
{
|
||||
"code": 200,
|
||||
"data": {
|
||||
"successCount": 2,
|
||||
"failedCount": 0,
|
||||
"uploadedFiles": [
|
||||
{
|
||||
"fileId": "123456",
|
||||
"fileName": "流水数据.xlsx",
|
||||
"fileSize": 2048576,
|
||||
"uploadTime": "2024-01-20 15:30:00",
|
||||
"status": "success"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 5.1.3 删除文件接口
|
||||
```typescript
|
||||
DELETE /api/project/{projectId}/file/{fileId}
|
||||
|
||||
Response:
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "删除成功"
|
||||
}
|
||||
```
|
||||
|
||||
#### 5.1.4 获取名单库列表
|
||||
```typescript
|
||||
GET /api/name-list/options
|
||||
|
||||
Response:
|
||||
{
|
||||
"code": 200,
|
||||
"data": [
|
||||
{
|
||||
"value": "high_risk",
|
||||
"label": "高风险人员名单",
|
||||
"count": 68
|
||||
},
|
||||
{
|
||||
"value": "history_suspicious",
|
||||
"label": "历史可疑人员名单",
|
||||
"count": 45
|
||||
},
|
||||
{
|
||||
"value": "regulatory_focus",
|
||||
"label": "监管关注名单",
|
||||
"count": 32
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### 5.1.5 更新名单库选择
|
||||
```typescript
|
||||
PUT /api/project/{projectId}/name-lists
|
||||
|
||||
Body:
|
||||
{
|
||||
"selectedLists": ["high_risk", "history_suspicious", "regulatory_focus"]
|
||||
}
|
||||
|
||||
Response:
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "更新成功"
|
||||
}
|
||||
```
|
||||
|
||||
#### 5.1.6 执行数据质量检查
|
||||
```typescript
|
||||
POST /api/project/{projectId}/quality-check
|
||||
|
||||
Response:
|
||||
{
|
||||
"code": 200,
|
||||
"data": {
|
||||
"checkId": "qc_123456",
|
||||
"status": "completed",
|
||||
"metrics": {
|
||||
"completeness": 98.5,
|
||||
"consistency": 95.2,
|
||||
"continuity": 92.8
|
||||
},
|
||||
"issues": [
|
||||
{
|
||||
"type": "format_inconsistency",
|
||||
"count": 23,
|
||||
"description": "条数据格式不一致"
|
||||
},
|
||||
{
|
||||
"type": "balance_anomaly",
|
||||
"count": 5,
|
||||
"description": "条余额连续性异常"
|
||||
},
|
||||
{
|
||||
"type": "missing_field",
|
||||
"count": 12,
|
||||
"description": "条缺失关键字段"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 5.1.7 拉取本行信息
|
||||
```typescript
|
||||
POST /api/project/{projectId}/pull-bank-info
|
||||
|
||||
Response:
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "拉取成功",
|
||||
"data": {
|
||||
"pulledRecords": 156,
|
||||
"pullTime": "2024-01-20 15:35:00"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 5.1.8 生成报告
|
||||
```typescript
|
||||
POST /api/project/{projectId}/generate-report
|
||||
|
||||
Response:
|
||||
{
|
||||
"code": 200,
|
||||
"data": {
|
||||
"reportId": "rpt_789012",
|
||||
"reportUrl": "/project/123/report/rpt_789012",
|
||||
"generateTime": "2024-01-20 15:40:00"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5.2 前端数据模型
|
||||
|
||||
```typescript
|
||||
// 上传文件类型
|
||||
type UploadFileType = 'transaction' | 'inquiry' | 'family_relation';
|
||||
|
||||
// 上传文件状态
|
||||
type UploadStatus = 'uploading' | 'success' | 'error';
|
||||
|
||||
// 上传的文件
|
||||
interface UploadedFile {
|
||||
fileId: string;
|
||||
fileName: string;
|
||||
fileSize: number;
|
||||
uploadTime: string;
|
||||
status: UploadStatus;
|
||||
errorMessage?: string;
|
||||
}
|
||||
|
||||
// 名单库选项
|
||||
interface NameListOption {
|
||||
value: string;
|
||||
label: string;
|
||||
count: number;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
// 质量指标
|
||||
interface QualityMetric {
|
||||
name: string;
|
||||
value: number;
|
||||
status: 'good' | 'warning' | 'error';
|
||||
}
|
||||
|
||||
// 质量问题
|
||||
interface QualityIssue {
|
||||
type: string;
|
||||
count: number;
|
||||
description: string;
|
||||
details?: any[];
|
||||
}
|
||||
|
||||
// 项目上传数据状态
|
||||
interface ProjectUploadStatus {
|
||||
projectStatus: string;
|
||||
lastUpdateTime: string;
|
||||
uploadedFiles: {
|
||||
transactionFiles: UploadedFile[];
|
||||
inquiryFiles: UploadedFile[];
|
||||
familyRelationFiles: UploadedFile[];
|
||||
};
|
||||
selectedNameLists: string[];
|
||||
qualityMetrics: {
|
||||
completeness: number;
|
||||
consistency: number;
|
||||
continuity: number;
|
||||
};
|
||||
qualityIssues: QualityIssue[];
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 样式规范
|
||||
|
||||
### 6.1 颜色规范
|
||||
```scss
|
||||
// 主色
|
||||
$primary-color: #409EFF;
|
||||
$success-color: #67C23A;
|
||||
$warning-color: #E6A23C;
|
||||
$danger-color: #F56C6C;
|
||||
$info-color: #909399;
|
||||
|
||||
// 中性色
|
||||
$text-primary: #303133;
|
||||
$text-regular: #606266;
|
||||
$text-secondary: #909399;
|
||||
$text-placeholder: #C0C4CC;
|
||||
|
||||
// 边框色
|
||||
$border-base: #DCDFE6;
|
||||
$border-light: #E4E7ED;
|
||||
$border-lighter: #EBEEF5;
|
||||
$border-extra-light: #F2F6FC;
|
||||
|
||||
// 背景色
|
||||
$bg-color: #F5F7FA;
|
||||
$card-bg: #FFFFFF;
|
||||
```
|
||||
|
||||
### 6.2 间距规范
|
||||
```scss
|
||||
$spacing-xs: 4px;
|
||||
$spacing-sm: 8px;
|
||||
$spacing-md: 16px;
|
||||
$spacing-lg: 24px;
|
||||
$spacing-xl: 32px;
|
||||
```
|
||||
|
||||
### 6.3 圆角规范
|
||||
```scss
|
||||
$border-radius-sm: 2px;
|
||||
$border-radius-base: 4px;
|
||||
$border-radius-lg: 8px;
|
||||
$border-radius-circle: 50%;
|
||||
```
|
||||
|
||||
### 6.4 阴影规范
|
||||
```scss
|
||||
$box-shadow-base: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
|
||||
$box-shadow-dark: 0 2px 8px rgba(0, 0, 0, 0.15), 0 0 6px rgba(0, 0, 0, 0.1);
|
||||
$box-shadow-light: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. 组件样式代码
|
||||
|
||||
### 7.1 上传卡片样式
|
||||
```scss
|
||||
.upload-card {
|
||||
height: 100%;
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: $text-primary;
|
||||
}
|
||||
|
||||
.el-icon-info {
|
||||
color: $info-color;
|
||||
cursor: help;
|
||||
}
|
||||
}
|
||||
|
||||
.upload-area {
|
||||
margin-bottom: $spacing-md;
|
||||
|
||||
.el-upload-dragger {
|
||||
width: 100%;
|
||||
height: 180px;
|
||||
border: 2px dashed $border-base;
|
||||
border-radius: $border-radius-lg;
|
||||
background: $bg-color;
|
||||
transition: all 0.3s;
|
||||
|
||||
&:hover {
|
||||
border-color: $primary-color;
|
||||
background: #F0F7FF;
|
||||
}
|
||||
}
|
||||
|
||||
.upload-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
|
||||
.el-icon-upload {
|
||||
font-size: 48px;
|
||||
color: $primary-color;
|
||||
margin-bottom: $spacing-sm;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: $spacing-xs 0;
|
||||
font-size: 14px;
|
||||
color: $text-regular;
|
||||
}
|
||||
|
||||
.upload-tip {
|
||||
font-size: 12px;
|
||||
color: $text-secondary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.file-list {
|
||||
border-top: 1px solid $border-light;
|
||||
padding-top: $spacing-md;
|
||||
|
||||
h4 {
|
||||
margin: 0 0 $spacing-sm 0;
|
||||
font-size: 14px;
|
||||
color: $text-primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 7.2 数据质量面板样式
|
||||
```scss
|
||||
.quality-panel {
|
||||
.panel-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
.metrics-container {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
margin-bottom: $spacing-lg;
|
||||
|
||||
.metric-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
.el-progress {
|
||||
margin-bottom: $spacing-sm;
|
||||
}
|
||||
|
||||
.metric-name {
|
||||
font-size: 14px;
|
||||
color: $text-regular;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.issues-section {
|
||||
border-top: 1px solid $border-light;
|
||||
padding-top: $spacing-md;
|
||||
|
||||
h4 {
|
||||
margin: 0 0 $spacing-md 0;
|
||||
font-size: 14px;
|
||||
color: $text-primary;
|
||||
}
|
||||
|
||||
.issue-item {
|
||||
margin-bottom: $spacing-sm;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 7.3 页面整体布局样式
|
||||
```scss
|
||||
.upload-data-page {
|
||||
padding: $spacing-lg;
|
||||
background: $bg-color;
|
||||
min-height: calc(100vh - 84px);
|
||||
|
||||
.page-header {
|
||||
background: $card-bg;
|
||||
padding: $spacing-lg;
|
||||
border-radius: $border-radius-lg;
|
||||
margin-bottom: $spacing-lg;
|
||||
box-shadow: $box-shadow-base;
|
||||
|
||||
h1 {
|
||||
margin: 0 0 $spacing-sm 0;
|
||||
font-size: 24px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.page-info {
|
||||
display: flex;
|
||||
gap: $spacing-lg;
|
||||
font-size: 14px;
|
||||
color: $text-secondary;
|
||||
margin-top: $spacing-sm;
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.label {
|
||||
margin-right: $spacing-xs;
|
||||
}
|
||||
|
||||
.status {
|
||||
color: $success-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.page-description {
|
||||
margin-top: $spacing-md;
|
||||
padding: $spacing-md;
|
||||
background: #F0F9FF;
|
||||
border-left: 3px solid $primary-color;
|
||||
border-radius: $border-radius-base;
|
||||
font-size: 14px;
|
||||
color: $text-regular;
|
||||
}
|
||||
}
|
||||
|
||||
.upload-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: $spacing-lg;
|
||||
margin-bottom: $spacing-lg;
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
.full-width {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
.action-bar {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: $spacing-lg;
|
||||
margin-top: $spacing-xl;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. 技术实现要点
|
||||
|
||||
### 8.1 文件上传
|
||||
- 使用 Element UI 的 `el-upload` 组件
|
||||
- 支持拖拽上传和点击上传
|
||||
- 实现文件类型和大小校验
|
||||
- 显示上传进度
|
||||
- 支持断点续传(可选)
|
||||
|
||||
### 8.2 数据质量检查
|
||||
- 异步执行检查任务
|
||||
- 使用 WebSocket 或轮询获取检查进度
|
||||
- 实时更新进度和结果
|
||||
|
||||
### 8.3 状态管理
|
||||
- 使用 Vuex 管理上传状态
|
||||
- 缓存已上传文件列表
|
||||
- 同步名单库选择状态
|
||||
|
||||
### 8.4 性能优化
|
||||
- 文件分片上传大文件
|
||||
- 使用 Web Worker 处理文件预检查
|
||||
- 虚拟滚动展示大量文件列表
|
||||
|
||||
---
|
||||
|
||||
## 9. 测试要点
|
||||
|
||||
### 9.1 功能测试
|
||||
- 文件上传各种格式
|
||||
- 文件大小限制验证
|
||||
- 删除文件功能
|
||||
- 名单库选择功能
|
||||
- 数据质量检查准确性
|
||||
- 报告生成功能
|
||||
|
||||
### 9.2 兼容性测试
|
||||
- 主流浏览器兼容
|
||||
- 不同屏幕尺寸适配
|
||||
- 文件格式兼容性
|
||||
|
||||
### 9.3 性能测试
|
||||
- 大文件上传性能
|
||||
- 多文件同时上传
|
||||
- 页面加载性能
|
||||
|
||||
### 9.4 异常处理测试
|
||||
- 网络中断处理
|
||||
- 文件上传失败处理
|
||||
- 服务器错误处理
|
||||
- 文件格式错误处理
|
||||
|
||||
---
|
||||
|
||||
## 10. 附录
|
||||
|
||||
### 10.1 相关页面
|
||||
- 项目详情页:`/project/:id/detail`
|
||||
- 参数配置页:`/project/:id/config`
|
||||
- 初核结果页:`/project/:id/result`
|
||||
- 报告页面:`/project/:id/report/:reportId`
|
||||
|
||||
### 10.2 权限要求
|
||||
- 需要项目成员权限
|
||||
- 上传操作需要编辑权限
|
||||
- 删除操作需要删除权限
|
||||
- 生成报告需要报告权限
|
||||
|
||||
### 10.3 相关文档
|
||||
- [Element UI Upload 组件文档](https://element.eleme.cn/#/zh-CN/component/upload)
|
||||
- [若依框架前端开发规范](../前端开发规范.md)
|
||||
- [项目接口文档](../API文档/项目管理模块.md)
|
||||
|
||||
---
|
||||
|
||||
**文档版本**: v1.0
|
||||
**创建时间**: 2024-01-30
|
||||
**最后更新**: 2024-01-30
|
||||
**文档状态**: 待评审
|
||||
336
doc/plans/2025-01-30-project-detail-page-design.md
Normal file
336
doc/plans/2025-01-30-project-detail-page-design.md
Normal file
@@ -0,0 +1,336 @@
|
||||
# 项目详情页面设计文档
|
||||
|
||||
**创建日期**: 2025-01-30
|
||||
**设计者**: Claude Code
|
||||
**状态**: 待实施
|
||||
|
||||
## 1. 概述
|
||||
|
||||
### 1.1 需求描述
|
||||
|
||||
开发一个项目详情页面,在项目管理列表中,点击项目那一行或者查看详情跳转到项目详情页面。顶部有一个导航栏,里面有按钮切换项目详情的不同页面。
|
||||
|
||||
### 1.2 功能模块
|
||||
|
||||
- **上传数据**(默认):批量上传流水、征信、员工家庭关系数据,选择名单库
|
||||
- **参数配置**:配置项目分析参数和排查规则
|
||||
- **结果总览**:查看项目分析结果的总体概况
|
||||
- **专项排查**:针对特定风险类型进行深度排查
|
||||
- **流水明细查询**:查询和筛选具体的流水记录明细
|
||||
|
||||
---
|
||||
|
||||
## 2. 整体架构设计
|
||||
|
||||
### 2.1 路由结构
|
||||
|
||||
采用独立页面路由方式:
|
||||
|
||||
```
|
||||
路由: /project-detail/:projectId
|
||||
组件: @/views/ccdiProject/detail/index.vue
|
||||
```
|
||||
|
||||
### 2.2 页面布局
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────┐
|
||||
│ 顶部导航 (PageHeader) │
|
||||
│ [返回] 项目名称 [状态] │
|
||||
│ [上传数据] [参数配置] [结果总览] ... │
|
||||
├─────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ 内容区域 (el-tabs) │
|
||||
│ 根据选中标签显示对应子页面 │
|
||||
│ │
|
||||
└─────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 2.3 组件层次结构
|
||||
|
||||
```
|
||||
detail/
|
||||
├── index.vue # 主页面容器
|
||||
├── components/
|
||||
│ ├── PageHeader.vue # 顶部导航
|
||||
│ ├── UploadData.vue # 上传数据
|
||||
│ ├── ParameterConfig.vue # 参数配置
|
||||
│ ├── ResultOverview.vue # 结果总览
|
||||
│ ├── SpecialCheck.vue # 专项排查
|
||||
│ └── TransactionDetail.vue # 流水明细查询
|
||||
└── api.js # API 接口定义
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 上传数据页面详细设计
|
||||
|
||||
### 3.1 页面布局
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────┐
|
||||
│ 批量上传数据 [生成报告][拉取本行]│
|
||||
│ 支持在一个项目中上传多个主体/账户数据 │
|
||||
├─────────────────────────────────────────────┤
|
||||
│ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │
|
||||
│ │流水 │ │征信 │ │员工 │ │名单 │ │
|
||||
│ │导入 │ │导入 │ │家庭 │ │库选择 │ │
|
||||
│ └──────┘ └──────┘ └──────┘ └──────┘ │
|
||||
├─────────────────────────────────────────────┤
|
||||
│ 数据质量检查区 │
|
||||
│ - 检查结果列表 │
|
||||
│ - 指标卡片(完整性、一致性、连续性) │
|
||||
└─────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 3.2 功能模块
|
||||
|
||||
#### 3.2.1 流水导入
|
||||
- 支持格式:xlsx, xls, pdf
|
||||
- 拖拽上传 + 点击上传
|
||||
- 上传进度显示
|
||||
|
||||
#### 3.2.2 征信导入
|
||||
- 支持格式:html
|
||||
- 解析征信报告
|
||||
|
||||
#### 3.2.3 员工家庭关系导入
|
||||
- 支持格式:xlsx, xls
|
||||
- Excel 模板上传
|
||||
|
||||
#### 3.2.4 名单库选择
|
||||
- 高风险人员名单(68人)
|
||||
- 历史可疑人员名单(45人)
|
||||
- 监管关注名单(32人)
|
||||
|
||||
#### 3.2.5 数据质量检查
|
||||
- 数据完整性:98.5%
|
||||
- 格式一致性:95.2%
|
||||
- 余额连续性:92.8%
|
||||
- 检查结果详情
|
||||
|
||||
---
|
||||
|
||||
## 4. 其他子页面框架设计
|
||||
|
||||
### 4.1 参数配置页面
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────┐
|
||||
│ 参数配置 [保存] [重置] │
|
||||
├─────────────────────────────────────────────┤
|
||||
│ ┌──────────┐ ┌──────────┐ │
|
||||
│ │ 预警阈值 │ │ 排查规则 │ │
|
||||
│ └──────────┘ └──────────┘ │
|
||||
│ ┌────────────────────────────────┐ │
|
||||
│ │ 高级配置(可折叠) │ │
|
||||
│ └────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 4.2 结果总览页面
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────┐
|
||||
│ 结果总览 [导出报告] [刷新] │
|
||||
├─────────────────────────────────────────────┤
|
||||
│ ┌────────┐ ┌────────┐ ┌────────┐ │
|
||||
│ │ 总人数 │ │ 预警数 │ │ 可疑数 │ │
|
||||
│ └────────┘ └────────┘ └────────┘ │
|
||||
│ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │ 预警分布图 │ │ 趋势图 │ │
|
||||
│ └──────────────┘ └──────────────┘ │
|
||||
│ 预警排名表格(Top 10) │
|
||||
└─────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 4.3 专项排查页面
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────┐
|
||||
│ 专项排查 [新增排查] [批量导出]│
|
||||
├─────────────────────────────────────────────┤
|
||||
│ 筛选条件:[风险类型] [严重程度] [状态] │
|
||||
│ 排查任务列表(表格) │
|
||||
└─────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 4.4 流水明细查询页面
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────┐
|
||||
│ 流水明细查询 [导出] [高级查询] │
|
||||
├─────────────────────────────────────────────┤
|
||||
│ 查询条件:[账户] [日期范围] [金额范围] │
|
||||
│ 流水明细表格(分页) │
|
||||
└─────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 接口设计
|
||||
|
||||
### 5.1 接口列表
|
||||
|
||||
| 接口名称 | 方法 | 路径 | 说明 |
|
||||
|---------|------|------|------|
|
||||
| 获取项目详情 | GET | `/ccdi/project/detail/{projectId}` | 获取项目基本信息 |
|
||||
| 上传流水文件 | POST | `/ccdi/project/transaction/upload` | 上传流水文件 |
|
||||
| 上传征信文件 | POST | `/ccdi/project/credit/upload` | 上传征信报告 |
|
||||
| 上传员工关系 | POST | `/ccdi/project/employee/upload` | 上传员工家庭关系 |
|
||||
| 获取名单库列表 | GET | `/ccdi/project/namelist/list` | 获取可选名单库 |
|
||||
| 保存名单库选择 | POST | `/ccdi/project/namelist/save` | 保存选择的名单库 |
|
||||
| 获取数据质量检查 | GET | `/ccdi/project/quality/check` | 获取质量检查指标 |
|
||||
| 生成报告 | POST | `/ccdi/project/report/generate` | 生成分析报告 |
|
||||
| 拉取本行信息 | GET | `/ccdi/project/own/info` | 获取本行员工信息 |
|
||||
| 保存参数配置 | POST | `/ccdi/project/config/save` | 保存项目参数 |
|
||||
| 获取结果总览 | GET | `/ccdi/project/overview` | 获取结果统计数据 |
|
||||
| 获取排查列表 | GET | `/ccdi/project/check/list` | 获取专项排查列表 |
|
||||
| 查询流水明细 | GET | `/ccdi/project/transaction/list` | 分页查询流水 |
|
||||
|
||||
### 5.2 Mock 数据示例
|
||||
|
||||
**项目详情**
|
||||
```javascript
|
||||
{
|
||||
code: 200,
|
||||
data: {
|
||||
projectId: 1,
|
||||
projectName: "2025年第一季度初核排查",
|
||||
projectDesc: "针对全行员工进行第一季度常规排查",
|
||||
projectStatus: "0",
|
||||
createTime: "2025-01-15",
|
||||
targetCount: 1250,
|
||||
warningCount: 23
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**数据质量检查结果**
|
||||
```javascript
|
||||
{
|
||||
code: 200,
|
||||
data: {
|
||||
completeness: 98.5,
|
||||
consistency: 95.2,
|
||||
continuity: 92.8,
|
||||
issues: [
|
||||
{ type: "格式不一致", count: 23 },
|
||||
{ type: "余额连续性异常", count: 5 },
|
||||
{ type: "缺失关键字段", count: 12 }
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 状态管理
|
||||
|
||||
### 6.1 Vuex Store
|
||||
|
||||
```javascript
|
||||
// store/modules/projectDetail.js
|
||||
const state = {
|
||||
currentProject: null,
|
||||
activeTab: 'upload',
|
||||
uploadStatus: {
|
||||
transaction: false,
|
||||
credit: false,
|
||||
employee: false,
|
||||
nameList: []
|
||||
},
|
||||
qualityCheck: null,
|
||||
pageCache: {}
|
||||
}
|
||||
```
|
||||
|
||||
### 6.2 页面缓存
|
||||
|
||||
使用 `<keep-alive>` 缓存标签页内容,避免切换时重复加载。
|
||||
|
||||
---
|
||||
|
||||
## 7. 路由配置
|
||||
|
||||
```javascript
|
||||
// router/index.js
|
||||
{
|
||||
path: '/project-detail',
|
||||
component: Layout,
|
||||
hidden: true,
|
||||
children: [
|
||||
{
|
||||
path: ':projectId(\\d+)',
|
||||
component: () => import('@/views/ccdiProject/detail/index'),
|
||||
name: 'ProjectDetail',
|
||||
meta: {
|
||||
title: '项目详情',
|
||||
activeMenu: '/ccdiProject'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. 文件目录结构
|
||||
|
||||
```
|
||||
ruoyi-ui/src/
|
||||
├── views/ccdiProject/
|
||||
│ ├── index.vue # 项目列表页(已存在)
|
||||
│ └── detail/ # 项目详情目录
|
||||
│ ├── index.vue # 主页面
|
||||
│ └── components/
|
||||
│ ├── PageHeader.vue
|
||||
│ ├── UploadData.vue
|
||||
│ ├── ParameterConfig.vue
|
||||
│ ├── ResultOverview.vue
|
||||
│ ├── SpecialCheck.vue
|
||||
│ └── TransactionDetail.vue
|
||||
├── api/
|
||||
│ └── ccdiProject/
|
||||
│ └── detail.js # 项目详情 API
|
||||
├── store/
|
||||
│ └── modules/
|
||||
│ └── projectDetail.js # Vuex 状态管理
|
||||
└── mock/
|
||||
└── projectDetail.js # Mock 数据
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. 待实现功能清单
|
||||
|
||||
- [ ] 创建路由配置
|
||||
- [ ] 创建主页面容器
|
||||
- [ ] 实现 PageHeader 顶部导航组件
|
||||
- [ ] 实现 UploadData 上传数据页面
|
||||
- [ ] 流水导入功能
|
||||
- [ ] 征信导入功能
|
||||
- [ ] 员工家庭关系导入功能
|
||||
- [ ] 名单库选择功能
|
||||
- [ ] 数据质量检查展示
|
||||
- [ ] 实现 ParameterConfig 参数配置页面(框架)
|
||||
- [ ] 实现 ResultOverview 结果总览页面(框架)
|
||||
- [ ] 实现 SpecialCheck 专项排查页面(框架)
|
||||
- [ ] 实现 TransactionDetail 流水明细查询页面(框架)
|
||||
- [ ] 创建 Vuex 状态管理模块
|
||||
- [ ] 创建 API 接口定义
|
||||
- [ ] 创建 Mock 数据
|
||||
- [ ] 修改项目列表页跳转逻辑
|
||||
- [ ] 测试整体流程
|
||||
|
||||
---
|
||||
|
||||
## 10. 设计决策记录
|
||||
|
||||
| 决策点 | 选择 | 原因 |
|
||||
|-------|------|------|
|
||||
| 路由方式 | 独立页面路由 | 可通过URL直接访问,支持浏览器前进后退 |
|
||||
| 导航方式 | Tabs 标签页 | 交互流畅,适合频繁切换场景 |
|
||||
| 上传卡片布局 | 四列一行 | 节省空间,一目了然 |
|
||||
| 后端接口 | Mock 数据先行 | 前端可独立开发,后续对接真实接口 |
|
||||
| 状态管理 | Vuex | 便于跨组件数据共享和状态持久化 |
|
||||
1958
doc/plans/2026-02-04-intermediary-blacklist-implementation.md
Normal file
1958
doc/plans/2026-02-04-intermediary-blacklist-implementation.md
Normal file
File diff suppressed because it is too large
Load Diff
1177
doc/plans/2026-02-04-intermediary-blacklist-migration-test-plan.md
Normal file
1177
doc/plans/2026-02-04-intermediary-blacklist-migration-test-plan.md
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,887 @@
|
||||
# 中介黑名单入库逻辑变更 - 测试验证计划
|
||||
|
||||
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
||||
|
||||
**目标:** 验证中介黑名单从单表切换到双表(cdi_biz_intermediary + ccdi_enterprise_base_info)的所有CRUD操作正确性
|
||||
|
||||
**架构:** 个人中介插入 ccdi_biz_intermediary 表,机构中介插入 ccdi_enterprise_base_info 表(自动设置高风险和中介来源标识),查询层合并两个表的数据返回
|
||||
|
||||
**技术栈:** Spring Boot 3.5.8, MyBatis Plus 3.5.10, MySQL 8.2.0, Maven, JUnit 5
|
||||
|
||||
---
|
||||
|
||||
## 测试前准备
|
||||
|
||||
### Task 1: 确认数据库连接和环境
|
||||
|
||||
**Files:**
|
||||
- Check: `ruoyi-admin/src/main/resources/application-dev.yml`
|
||||
|
||||
**Step 1: 验证数据库连接配置**
|
||||
|
||||
检查配置文件中的数据库连接信息:
|
||||
```yaml
|
||||
spring:
|
||||
datasource:
|
||||
druid:
|
||||
master:
|
||||
url: jdbc:mysql://116.62.17.81:3306/ccdi
|
||||
username: root
|
||||
password: Kfcx@1234
|
||||
```
|
||||
|
||||
**Step 2: 确认目标表存在**
|
||||
|
||||
通过MCP工具验证表存在:
|
||||
```sql
|
||||
SHOW TABLES LIKE 'ccdi_biz_intermediary';
|
||||
SHOW TABLES LIKE 'ccdi_enterprise_base_info';
|
||||
```
|
||||
|
||||
预期: 两个表都存在
|
||||
|
||||
**Step 3: 检查表结构**
|
||||
|
||||
```sql
|
||||
DESCRIBE ccdi_biz_intermediary;
|
||||
DESCRIBE ccdi_enterprise_base_info;
|
||||
```
|
||||
|
||||
预期: 表结构与实体类字段匹配
|
||||
|
||||
---
|
||||
|
||||
## 功能测试 - 个人中介
|
||||
|
||||
### Task 2: 测试个人中介新增功能
|
||||
|
||||
**Files:**
|
||||
- Test API: `POST /ccdi/intermediary/person`
|
||||
- Backend: `CcdiIntermediaryBlacklistServiceImpl.insertPersonIntermediary()`
|
||||
|
||||
**Step 1: 准备测试数据**
|
||||
|
||||
创建测试数据文件 `test_person_add.json`:
|
||||
```json
|
||||
{
|
||||
"name": "测试个人中介",
|
||||
"certificateNo": "110101199001011234",
|
||||
"indivType": "中介",
|
||||
"indivSubType": "本人",
|
||||
"indivGender": "M",
|
||||
"indivCertType": "身份证",
|
||||
"indivPhone": "13800138000",
|
||||
"indivWechat": "test_wx001",
|
||||
"indivAddress": "北京市朝阳区测试路123号",
|
||||
"indivCompany": "测试公司",
|
||||
"indivPosition": "测试员",
|
||||
"indivRelatedId": "",
|
||||
"indivRelation": "",
|
||||
"status": "0",
|
||||
"remark": "自动化测试数据"
|
||||
}
|
||||
```
|
||||
|
||||
**Step 2: 获取认证Token**
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8080/login/test \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"username":"admin","password":"admin123"}' \
|
||||
| jq -r '.data.token'
|
||||
```
|
||||
|
||||
保存token到环境变量:
|
||||
```bash
|
||||
export TOKEN="获取到的token值"
|
||||
```
|
||||
|
||||
**Step 3: 调用新增接口**
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8080/ccdi/intermediary/person \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d @test_person_add.json
|
||||
```
|
||||
|
||||
预期响应:
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "操作成功"
|
||||
}
|
||||
```
|
||||
|
||||
**Step 4: 验证数据插入到正确的表**
|
||||
|
||||
通过MCP查询数据库:
|
||||
```sql
|
||||
SELECT * FROM ccdi_biz_intermediary
|
||||
WHERE person_id = '110101199001011234';
|
||||
```
|
||||
|
||||
预期:
|
||||
- 找到1条记录
|
||||
- name = '测试个人中介'
|
||||
- date_source = 'MANUAL'
|
||||
|
||||
**Step 5: 验证旧表无数据**
|
||||
|
||||
```sql
|
||||
SELECT * FROM ccdi_intermediary_blacklist
|
||||
WHERE certificate_no = '110101199001011234';
|
||||
```
|
||||
|
||||
预期: 0条记录(表可能不存在或为空)
|
||||
|
||||
---
|
||||
|
||||
### Task 3: 测试个人中介列表查询
|
||||
|
||||
**Files:**
|
||||
- Test API: `GET /ccdi/intermediary/list`
|
||||
|
||||
**Step 1: 调用列表查询接口**
|
||||
|
||||
```bash
|
||||
curl -X GET "http://localhost:8080/ccdi/intermediary/list?name=测试个人中介" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
预期响应:
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "查询成功",
|
||||
"rows": [
|
||||
{
|
||||
"intermediaryId": 1,
|
||||
"name": "测试个人中介",
|
||||
"certificateNo": "110101199001011234",
|
||||
"intermediaryType": "1",
|
||||
"intermediaryTypeName": "个人",
|
||||
"status": "0",
|
||||
"statusName": "正常"
|
||||
}
|
||||
],
|
||||
"total": 1
|
||||
}
|
||||
```
|
||||
|
||||
**Step 2: 验证查询结果来源**
|
||||
|
||||
确认数据来自 `ccdi_biz_intermediary` 表
|
||||
|
||||
**Step 3: 测试分页查询**
|
||||
|
||||
```bash
|
||||
curl -X GET "http://localhost:8080/ccdi/intermediary/list?pageNum=1&pageSize=10" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
预期: 返回分页数据
|
||||
|
||||
---
|
||||
|
||||
### Task 4: 测试个人中介详情查询
|
||||
|
||||
**Files:**
|
||||
- Test API: `GET /ccdi/intermediary/{id}`
|
||||
|
||||
**Step 1: 获取个人中介详情**
|
||||
|
||||
```bash
|
||||
curl -X GET "http://localhost:8080/ccdi/intermediary/1" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
预期响应:
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"data": {
|
||||
"intermediaryId": 1,
|
||||
"name": "测试个人中介",
|
||||
"certificateNo": "110101199001011234",
|
||||
"intermediaryType": "1",
|
||||
"indivType": "中介",
|
||||
"indivGender": "M",
|
||||
"indivGenderName": "男",
|
||||
"indivPhone": "13800138000",
|
||||
"indivWechat": "test_wx001",
|
||||
"indivAddress": "北京市朝阳区测试路123号",
|
||||
"indivCompany": "测试公司",
|
||||
"indivPosition": "测试员",
|
||||
"dataSource": "MANUAL",
|
||||
"dataSourceName": "手动录入"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Step 2: 验证所有字段正确映射**
|
||||
|
||||
检查个人专属字段是否正确:
|
||||
- indivType → person_type ✅
|
||||
- indivGender → gender ✅
|
||||
- indivPhone → mobile ✅
|
||||
- indivWechat → wechat_no ✅
|
||||
- indivAddress → contact_address ✅
|
||||
|
||||
---
|
||||
|
||||
### Task 5: 测试个人中介修改功能
|
||||
|
||||
**Files:**
|
||||
- Test API: `PUT /ccdi/intermediary/person`
|
||||
|
||||
**Step 1: 准备修改数据**
|
||||
|
||||
创建 `test_person_edit.json`:
|
||||
```json
|
||||
{
|
||||
"intermediaryId": 1,
|
||||
"name": "测试个人中介-已修改",
|
||||
"certificateNo": "110101199001011234",
|
||||
"indivType": "中介",
|
||||
"indivGender": "M",
|
||||
"indivPhone": "13900139000",
|
||||
"indivCompany": "新公司",
|
||||
"remark": "已修改"
|
||||
}
|
||||
```
|
||||
|
||||
**Step 2: 调用修改接口**
|
||||
|
||||
```bash
|
||||
curl -X PUT http://localhost:8080/ccdi/intermediary/person \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d @test_person_edit.json
|
||||
```
|
||||
|
||||
预期: `{ "code": 200, "msg": "操作成功" }`
|
||||
|
||||
**Step 3: 验证数据已更新**
|
||||
|
||||
```sql
|
||||
SELECT * FROM ccdi_biz_intermediary
|
||||
WHERE biz_id = 1;
|
||||
```
|
||||
|
||||
预期:
|
||||
- name = '测试个人中介-已修改'
|
||||
- mobile = '13900139000'
|
||||
- company = '新公司'
|
||||
|
||||
---
|
||||
|
||||
### Task 6: 测试个人中介删除功能
|
||||
|
||||
**Files:**
|
||||
- Test API: `DELETE /ccdi/intermediary/{ids}`
|
||||
|
||||
**Step 1: 调用删除接口**
|
||||
|
||||
```bash
|
||||
curl -X DELETE "http://localhost:8080/ccdi/intermediary/1" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
预期: `{ "code": 200, "msg": "操作成功" }`
|
||||
|
||||
**Step 2: 验证数据已删除**
|
||||
|
||||
```sql
|
||||
SELECT * FROM ccdi_biz_intermediary
|
||||
WHERE biz_id = 1;
|
||||
```
|
||||
|
||||
预期: 0条记录
|
||||
|
||||
---
|
||||
|
||||
## 功能测试 - 机构中介
|
||||
|
||||
### Task 7: 测试机构中介新增功能
|
||||
|
||||
**Files:**
|
||||
- Test API: `POST /ccdi/intermediary/entity`
|
||||
- Backend: `CcdiIntermediaryBlacklistServiceImpl.insertEntityIntermediary()`
|
||||
|
||||
**Step 1: 准备测试数据**
|
||||
|
||||
创建 `test_entity_add.json`:
|
||||
```json
|
||||
{
|
||||
"name": "测试机构中介有限公司",
|
||||
"corpCreditCode": "91110000123456789X",
|
||||
"corpType": "有限责任公司",
|
||||
"corpNature": "民营企业",
|
||||
"corpIndustryCategory": "制造业",
|
||||
"corpIndustry": "通用设备制造业",
|
||||
"corpEstablishDate": "2020-01-01T00:00:00",
|
||||
"corpAddress": "北京市海淀区测试大街456号",
|
||||
"corpLegalRep": "张三",
|
||||
"corpLegalCertType": "身份证",
|
||||
"corpLegalCertNo": "110101198001011234",
|
||||
"corpShareholder1": "股东A",
|
||||
"corpShareholder2": "股东B",
|
||||
"status": "0",
|
||||
"remark": "机构中介测试数据"
|
||||
}
|
||||
```
|
||||
|
||||
**Step 2: 调用新增接口**
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8080/ccdi/intermediary/entity \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d @test_entity_add.json
|
||||
```
|
||||
|
||||
预期: `{ "code": 200, "msg": "操作成功" }`
|
||||
|
||||
**Step 3: 验证数据插入到正确的表**
|
||||
|
||||
```sql
|
||||
SELECT * FROM ccdi_enterprise_base_info
|
||||
WHERE social_credit_code = '91110000123456789X';
|
||||
```
|
||||
|
||||
预期:
|
||||
- 找到1条记录
|
||||
- enterprise_name = '测试机构中介有限公司'
|
||||
- **risk_level = '1' (高风险)** ✅
|
||||
- **ent_source = 'INTERMEDIARY' (中介来源)** ✅
|
||||
- data_source = 'MANUAL'
|
||||
|
||||
**Step 4: 验证关键字段自动设置**
|
||||
|
||||
检查两个重要标识:
|
||||
```sql
|
||||
SELECT
|
||||
social_credit_code,
|
||||
enterprise_name,
|
||||
risk_level,
|
||||
ent_source,
|
||||
data_source
|
||||
FROM ccdi_enterprise_base_info
|
||||
WHERE social_credit_code = '91110000123456789X';
|
||||
```
|
||||
|
||||
预期:
|
||||
- risk_level = '1' ✅
|
||||
- ent_source = 'INTERMEDIARY' ✅
|
||||
|
||||
---
|
||||
|
||||
### Task 8: 测试机构中介列表查询
|
||||
|
||||
**Files:**
|
||||
- Test API: `GET /ccdi/intermediary/list`
|
||||
|
||||
**Step 1: 查询机构中介**
|
||||
|
||||
```bash
|
||||
curl -X GET "http://localhost:8080/ccdi/intermediary/list?intermediaryType=2&name=测试机构" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
预期响应:
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"rows": [
|
||||
{
|
||||
"intermediaryId": 0,
|
||||
"name": "测试机构中介有限公司",
|
||||
"certificateNo": "91110000123456789X",
|
||||
"intermediaryType": "2",
|
||||
"intermediaryTypeName": "机构",
|
||||
"status": "0",
|
||||
"statusName": "正常"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Step 2: 验证ent_source过滤**
|
||||
|
||||
查询应该只返回 ent_source='INTERMEDIARY' 的记录
|
||||
|
||||
**Step 3: 混合查询(个人+机构)**
|
||||
|
||||
```bash
|
||||
curl -X GET "http://localhost:8080/ccdi/intermediary/list" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
预期: 返回个人和机构中介的合并列表
|
||||
|
||||
---
|
||||
|
||||
### Task 9: 测试机构中介详情查询
|
||||
|
||||
**Files:**
|
||||
- Test API: `GET /ccdi/intermediary/{id}`
|
||||
|
||||
**Step 1: 获取机构中介详情**
|
||||
|
||||
注意: 机构中介的ID需要特殊处理(社会信用代码)
|
||||
|
||||
**Step 2: 验证机构字段映射**
|
||||
|
||||
检查字段映射:
|
||||
- corpCreditCode → social_credit_code ✅
|
||||
- name → enterprise_name ✅
|
||||
- corpType → enterprise_type ✅
|
||||
- corpNature → enterprise_nature ✅
|
||||
- corpIndustryCategory → industry_class ✅
|
||||
|
||||
---
|
||||
|
||||
### Task 10: 测试机构中介修改功能
|
||||
|
||||
**Files:**
|
||||
- Test API: `PUT /ccdi/intermediary/entity`
|
||||
|
||||
**Step 1: 准备修改数据**
|
||||
|
||||
创建 `test_entity_edit.json`:
|
||||
```json
|
||||
{
|
||||
"corpCreditCode": "91110000123456789X",
|
||||
"name": "测试机构中介有限公司-已修改",
|
||||
"corpType": "股份有限公司",
|
||||
"corpNature": "国有企业",
|
||||
"status": "0",
|
||||
"remark": "已修改"
|
||||
}
|
||||
```
|
||||
|
||||
**Step 2: 调用修改接口**
|
||||
|
||||
```bash
|
||||
curl -X PUT http://localhost:8080/ccdi/intermediary/entity \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d @test_entity_edit.json
|
||||
```
|
||||
|
||||
预期: `{ "code": 200, "msg": "操作成功" }`
|
||||
|
||||
**Step 3: 验证高风险和中介来源标识不变**
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
social_credit_code,
|
||||
enterprise_name,
|
||||
risk_level,
|
||||
ent_source
|
||||
FROM ccdi_enterprise_base_info
|
||||
WHERE social_credit_code = '91110000123456789X';
|
||||
```
|
||||
|
||||
预期:
|
||||
- enterprise_name = '测试机构中介有限公司-已修改'
|
||||
- risk_level 仍为 '1' ✅ (保持不变)
|
||||
- ent_source 仍为 'INTERMEDIARY' ✅ (保持不变)
|
||||
|
||||
---
|
||||
|
||||
## 导入功能测试
|
||||
|
||||
### Task 11: 测试个人中介Excel导入
|
||||
|
||||
**Files:**
|
||||
- Test API: `POST /ccdi/intermediary/importPersonData`
|
||||
|
||||
**Step 1: 下载导入模板**
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8080/ccdi/intermediary/importPersonTemplate \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
--output person_template.xlsx
|
||||
```
|
||||
|
||||
预期: 下载成功,文件包含所有个人字段
|
||||
|
||||
**Step 2: 准备测试Excel文件**
|
||||
|
||||
手动创建Excel文件或使用EasyExcel生成测试数据,包含:
|
||||
- 姓名: "导入测试个人"
|
||||
- 证件号: "110101199002022345"
|
||||
- 人员类型: "中介"
|
||||
- 性别: "M"
|
||||
- 手机号: "13800138001"
|
||||
- 微信号: "import_wx001"
|
||||
|
||||
**Step 3: 执行导入**
|
||||
|
||||
```bash
|
||||
curl -X POST "http://localhost:8080/ccdi/intermediary/importPersonData?updateSupport=false" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-F "file=@person_test_data.xlsx"
|
||||
```
|
||||
|
||||
预期:
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "恭喜您,数据已全部导入成功!共 1 条"
|
||||
}
|
||||
```
|
||||
|
||||
**Step 4: 验证导入数据**
|
||||
|
||||
```sql
|
||||
SELECT * FROM ccdi_biz_intermediary
|
||||
WHERE person_id = '110101199002022345';
|
||||
```
|
||||
|
||||
预期:
|
||||
- 找到1条记录
|
||||
- date_source = 'IMPORT' ✅
|
||||
- name = '导入测试个人'
|
||||
|
||||
---
|
||||
|
||||
### Task 12: 测试机构中介Excel导入
|
||||
|
||||
**Files:**
|
||||
- Test API: `POST /ccdi/intermediary/importEntityData`
|
||||
|
||||
**Step 1: 下载导入模板**
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8080/ccdi/intermediary/importEntityTemplate \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
--output entity_template.xlsx
|
||||
```
|
||||
|
||||
预期: 下载成功,文件包含所有机构字段
|
||||
|
||||
**Step 2: 准备测试Excel文件**
|
||||
|
||||
创建Excel文件,包含:
|
||||
- 机构名称: "导入测试机构有限公司"
|
||||
- 统一社会信用代码: "91110000987654321A"
|
||||
- 主体类型: "有限责任公司"
|
||||
- 企业性质: "民营企业"
|
||||
- 法定代表人: "李四"
|
||||
|
||||
**Step 3: 执行导入**
|
||||
|
||||
```bash
|
||||
curl -X POST "http://localhost:8080/ccdi/intermediary/importEntityData?updateSupport=false" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-F "file=@entity_test_data.xlsx"
|
||||
```
|
||||
|
||||
预期:
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "恭喜您,数据已全部导入成功!共 1 条"
|
||||
}
|
||||
```
|
||||
|
||||
**Step 4: 验证导入数据和自动设置标识**
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
social_credit_code,
|
||||
enterprise_name,
|
||||
risk_level,
|
||||
ent_source,
|
||||
data_source
|
||||
FROM ccdi_enterprise_base_info
|
||||
WHERE social_credit_code = '91110000987654321A';
|
||||
```
|
||||
|
||||
预期:
|
||||
- enterprise_name = '导入测试机构有限公司'
|
||||
- **risk_level = '1' (高风险)** ✅
|
||||
- **ent_source = 'INTERMEDIARY' (中介来源)** ✅
|
||||
- data_source = 'IMPORT' ✅
|
||||
|
||||
---
|
||||
|
||||
## 导出功能测试
|
||||
|
||||
### Task 13: 测试中介数据导出
|
||||
|
||||
**Files:**
|
||||
- Test API: `POST /ccdi/intermediary/export`
|
||||
|
||||
**Step 1: 导出所有数据**
|
||||
|
||||
```bash
|
||||
curl -X POST "http://localhost:8080/ccdi/intermediary/export" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{}' \
|
||||
--output intermediary_export.xlsx
|
||||
```
|
||||
|
||||
预期: 下载成功,Excel文件包含个人和机构数据
|
||||
|
||||
**Step 2: 验证导出数据完整性**
|
||||
|
||||
打开Excel文件,验证:
|
||||
- 包含个人中介字段(indivType, indivGender等)
|
||||
- 包含机构中介字段(corpType, corpNature等)
|
||||
- 数据正确映射
|
||||
|
||||
**Step 3: 测试条件导出**
|
||||
|
||||
```bash
|
||||
curl -X POST "http://localhost:8080/ccdi/intermediary/export" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"intermediaryType":"1"}' \
|
||||
--output person_export.xlsx
|
||||
```
|
||||
|
||||
预期: 只导出个人中介数据
|
||||
|
||||
---
|
||||
|
||||
## 边界条件测试
|
||||
|
||||
### Task 14: 测试唯一性约束
|
||||
|
||||
**Step 1: 个人中介证件号重复插入**
|
||||
|
||||
尝试插入相同person_id的记录:
|
||||
```bash
|
||||
# 使用Task 2的数据再次执行
|
||||
curl -X POST http://localhost:8080/ccdi/intermediary/person \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d @test_person_add.json
|
||||
```
|
||||
|
||||
预期: 根据实际业务逻辑,可能报唯一性约束错误或允许插入
|
||||
|
||||
**Step 2: 机构中介社会信用代码重复插入**
|
||||
|
||||
```bash
|
||||
# 使用Task 7的数据再次执行
|
||||
curl -X POST http://localhost:8080/ccdi/intermediary/entity \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d @test_entity_add.json
|
||||
```
|
||||
|
||||
预期: 报主键冲突错误(社会信用代码是主键)
|
||||
|
||||
---
|
||||
|
||||
### Task 15: 测试必填字段验证
|
||||
|
||||
**Step 1: 缺少姓名的个人中介**
|
||||
|
||||
创建 `test_person_no_name.json`:
|
||||
```json
|
||||
{
|
||||
"certificateNo": "110101199003033456",
|
||||
"status": "0"
|
||||
}
|
||||
```
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8080/ccdi/intermediary/person \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d @test_person_no_name.json
|
||||
```
|
||||
|
||||
预期: 返回验证错误,提示"姓名不能为空"
|
||||
|
||||
**Step 2: 缺少统一社会信用代码的机构中介**
|
||||
|
||||
创建 `test_entity_no_code.json`:
|
||||
```json
|
||||
{
|
||||
"name": "测试机构",
|
||||
"status": "0"
|
||||
}
|
||||
```
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8080/ccdi/intermediary/entity \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d @test_entity_no_code.json
|
||||
```
|
||||
|
||||
预期: 返回验证错误,提示"统一社会信用代码不能为空"
|
||||
|
||||
---
|
||||
|
||||
## 性能测试
|
||||
|
||||
### Task 16: 批量数据导入性能测试
|
||||
|
||||
**Step 1: 准备批量测试数据**
|
||||
|
||||
创建包含100条个人中介的Excel文件
|
||||
|
||||
**Step 2: 执行批量导入**
|
||||
|
||||
```bash
|
||||
time curl -X POST "http://localhost:8080/ccdi/intermediary/importPersonData?updateSupport=false" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-F "file=@person_batch_100.xlsx"
|
||||
```
|
||||
|
||||
预期:
|
||||
- 导入成功
|
||||
- 耗时 < 10秒
|
||||
|
||||
**Step 3: 验证数据一致性**
|
||||
|
||||
```sql
|
||||
SELECT COUNT(*) FROM ccdi_biz_intermediary
|
||||
WHERE date_source = 'IMPORT';
|
||||
```
|
||||
|
||||
预期: 导入的记录数与Excel文件一致
|
||||
|
||||
---
|
||||
|
||||
## 清理测试数据
|
||||
|
||||
### Task 17: 清理测试数据
|
||||
|
||||
**Step 1: 删除测试个人中介数据**
|
||||
|
||||
```sql
|
||||
DELETE FROM ccdi_biz_intermediary
|
||||
WHERE person_id IN (
|
||||
'110101199001011234',
|
||||
'110101199002022345'
|
||||
);
|
||||
```
|
||||
|
||||
**Step 2: 删除测试机构中介数据**
|
||||
|
||||
```sql
|
||||
DELETE FROM ccdi_enterprise_base_info
|
||||
WHERE social_credit_code IN (
|
||||
'91110000123456789X',
|
||||
'91110000987654321A'
|
||||
);
|
||||
```
|
||||
|
||||
**Step 3: 验证清理完成**
|
||||
|
||||
```sql
|
||||
SELECT COUNT(*) FROM ccdi_biz_intermediary
|
||||
WHERE person_id LIKE '110101199%';
|
||||
|
||||
SELECT COUNT(*) FROM ccdi_enterprise_base_info
|
||||
WHERE social_credit_code LIKE '91110000%';
|
||||
```
|
||||
|
||||
预期: 0条测试记录
|
||||
|
||||
---
|
||||
|
||||
## 测试报告生成
|
||||
|
||||
### Task 18: 生成测试报告
|
||||
|
||||
**Step 1: 汇总测试结果**
|
||||
|
||||
创建测试报告文件 `test_report.md`:
|
||||
|
||||
```markdown
|
||||
# 中介黑名单入库逻辑变更测试报告
|
||||
|
||||
## 测试环境
|
||||
- 数据库: MySQL 8.2.0
|
||||
- 服务端口: 8080
|
||||
- 测试时间: 2026-02-04
|
||||
|
||||
## 功能测试结果
|
||||
|
||||
### 个人中介
|
||||
- ✅ 新增功能 - 数据正确插入 ccdi_biz_intermediary
|
||||
- ✅ 列表查询 - 正确返回个人中介数据
|
||||
- ✅ 详情查询 - 所有字段正确映射
|
||||
- ✅ 修改功能 - 数据正确更新
|
||||
- ✅ 删除功能 - 数据正确删除
|
||||
- ✅ Excel导入 - 批量导入成功,data_source='IMPORT'
|
||||
- ✅ Excel导出 - 数据完整导出
|
||||
|
||||
### 机构中介
|
||||
- ✅ 新增功能 - 数据正确插入 ccdi_enterprise_base_info
|
||||
- ✅ 自动设置标识 - risk_level='1', ent_source='INTERMEDIARY'
|
||||
- ✅ 列表查询 - 正确返回机构中介数据
|
||||
- ✅ 详情查询 - 所有字段正确映射
|
||||
- ✅ 修改功能 - 数据正确更新,标识保持不变
|
||||
- ✅ Excel导入 - 批量导入成功,自动设置高风险和中介来源
|
||||
- ✅ Excel导出 - 数据完整导出
|
||||
|
||||
### 边界条件
|
||||
- ✅ 唯一性约束 - 社会信用代码主键冲突
|
||||
- ✅ 必填字段验证 - 姓名和证件号验证生效
|
||||
|
||||
### 性能测试
|
||||
- ✅ 100条数据导入 - 耗时 < 10秒
|
||||
|
||||
## 数据映射验证
|
||||
|
||||
### 个人中介字段映射
|
||||
| 原字段 | 新字段 | 状态 |
|
||||
|--------|--------|------|
|
||||
| intermediary_id | biz_id | ✅ |
|
||||
| certificate_no | person_id | ✅ |
|
||||
| indiv_type | person_type | ✅ |
|
||||
| indiv_gender | gender | ✅ |
|
||||
| indiv_phone | mobile | ✅ |
|
||||
| indiv_wechat | wechat_no | ✅ |
|
||||
| indiv_address | contact_address | ✅ |
|
||||
|
||||
### 机构中介字段映射
|
||||
| 原字段 | 新字段 | 状态 |
|
||||
|--------|--------|------|
|
||||
| corp_credit_code | social_credit_code | ✅ |
|
||||
| name | enterprise_name | ✅ |
|
||||
| corp_type | enterprise_type | ✅ |
|
||||
| corp_nature | enterprise_nature | ✅ |
|
||||
| - | risk_level='1' | ✅ 自动设置 |
|
||||
| - | ent_source='INTERMEDIARY' | ✅ 自动设置 |
|
||||
|
||||
## 结论
|
||||
✅ 所有测试通过,入库逻辑变更成功!
|
||||
```
|
||||
|
||||
**Step 2: 提交测试报告**
|
||||
|
||||
```bash
|
||||
git add test_report.md
|
||||
git commit -m "test: 添加中介黑名单变更测试报告"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **机构中介ID处理**: 机构中介的主键是字符串类型(social_credit_code),查询详情时需要特殊处理
|
||||
|
||||
2. **自动设置标识**: 机构中介新增/导入时自动设置 `risk_level='1'` 和 `ent_source='INTERMEDIARY'`,修改时不应改变这两个值
|
||||
|
||||
3. **查询合并**: 列表查询需要从两个表获取数据并合并返回前端
|
||||
|
||||
4. **数据来源标识**:
|
||||
- 手动新增: date_source/data_source = 'MANUAL'
|
||||
- Excel导入: date_source/data_source = 'IMPORT'
|
||||
|
||||
5. **分页查询**: 当前实现是先查询所有数据再手动分页,大数据量时可能需要优化
|
||||
|
||||
6. **删除操作**: 当前只支持个人中介的数字ID删除,机构中介删除需要扩展支持
|
||||
46
doc/sql/menu_info_maintain.sql
Normal file
46
doc/sql/menu_info_maintain.sql
Normal file
@@ -0,0 +1,46 @@
|
||||
-- =====================================================
|
||||
-- 菜单SQL:信息维护模块
|
||||
-- 创建时间: 2025-02-04
|
||||
-- 说明: 包含"信息维护"一级菜单及其两个二级菜单
|
||||
-- =====================================================
|
||||
|
||||
-- 一级菜单:信息维护
|
||||
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, query, route_name, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark)
|
||||
VALUES(2000, '信息维护', 0, 5, 'maintain', NULL, NULL, NULL, 1, 0, 'M', '0', '0', NULL, 'el-icon-collection', 'admin', NOW(), '信息维护目录');
|
||||
|
||||
-- 二级菜单:中介黑名单管理
|
||||
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, query, route_name, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark)
|
||||
VALUES(2001, '中介黑名单管理', 2000, 1, 'intermediary', 'ccdiIntermediary/index', NULL, NULL, 1, 0, 'C', '0', '0', 'ccdi:intermediary:list', '#', 'admin', NOW(), '中介黑名单管理菜单');
|
||||
|
||||
-- 二级菜单:员工信息维护
|
||||
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, query, route_name, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark)
|
||||
VALUES(2002, '员工信息维护', 2000, 2, 'employee', 'ccdiEmployee/index', NULL, NULL, 1, 0, 'C', '0', '0', 'ccdi:employee:list', '#', 'admin', NOW(), '员工信息维护菜单');
|
||||
|
||||
-- =====================================================
|
||||
-- 中介黑名单管理 - 按钮权限
|
||||
-- =====================================================
|
||||
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, query, route_name, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark)
|
||||
VALUES
|
||||
(2010, '中介黑名单查询', 2001, 1, '', NULL, NULL, NULL, 1, 0, 'F', '0', '0', 'ccdi:intermediary:query', '#', 'admin', NOW(), ''),
|
||||
(2011, '中介黑名单新增', 2001, 2, '', NULL, NULL, NULL, 1, 0, 'F', '0', '0', 'ccdi:intermediary:add', '#', 'admin', NOW(), ''),
|
||||
(2012, '中介黑名单修改', 2001, 3, '', NULL, NULL, NULL, 1, 0, 'F', '0', '0', 'ccdi:intermediary:edit', '#', 'admin', NOW(), ''),
|
||||
(2013, '中介黑名单删除', 2001, 4, '', NULL, NULL, NULL, 1, 0, 'F', '0', '0', 'ccdi:intermediary:remove', '#', 'admin', NOW(), ''),
|
||||
(2014, '中介黑名单导出', 2001, 5, '', NULL, NULL, NULL, 1, 0, 'F', '0', '0', 'ccdi:intermediary:export', '#', 'admin', NOW(), ''),
|
||||
(2015, '中介黑名单导入', 2001, 6, '', NULL, NULL, NULL, 1, 0, 'F', '0', '0', 'ccdi:intermediary:import', '#', 'admin', NOW(), '');
|
||||
|
||||
-- =====================================================
|
||||
-- 员工信息维护 - 按钮权限
|
||||
-- =====================================================
|
||||
INSERT INTO sys_menu(menu_id, menu_name, parent_id, order_num, path, component, query, route_name, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark)
|
||||
VALUES
|
||||
(2020, '员工信息查询', 2002, 1, '', NULL, NULL, NULL, 1, 0, 'F', '0', '0', 'ccdi:employee:query', '#', 'admin', NOW(), ''),
|
||||
(2021, '员工信息新增', 2002, 2, '', NULL, NULL, NULL, 1, 0, 'F', '0', '0', 'ccdi:employee:add', '#', 'admin', NOW(), ''),
|
||||
(2022, '员工信息修改', 2002, 3, '', NULL, NULL, NULL, 1, 0, 'F', '0', '0', 'ccdi:employee:edit', '#', 'admin', NOW(), ''),
|
||||
(2023, '员工信息删除', 2002, 4, '', NULL, NULL, NULL, 1, 0, 'F', '0', '0', 'ccdi:employee:remove', '#', 'admin', NOW(), ''),
|
||||
(2024, '员工信息导出', 2002, 5, '', NULL, NULL, NULL, 1, 0, 'F', '0', '0', 'ccdi:employee:export', '#', 'admin', NOW(), ''),
|
||||
(2025, '员工信息导入', 2002, 6, '', NULL, NULL, NULL, 1, 0, 'F', '0', '0', 'ccdi:employee:import', '#', 'admin', NOW(), '');
|
||||
|
||||
-- =====================================================
|
||||
-- 回滚SQL(如需删除这些菜单,执行以下语句)
|
||||
-- =====================================================
|
||||
-- DELETE FROM sys_menu WHERE menu_id BETWEEN 2000 AND 2025;
|
||||
269
doc/中介黑名单列表查询功能说明.md
Normal file
269
doc/中介黑名单列表查询功能说明.md
Normal file
@@ -0,0 +1,269 @@
|
||||
# 中介黑名单列表查询功能说明
|
||||
|
||||
## 接口说明
|
||||
|
||||
### 1. 列表查询接口(不分页)
|
||||
|
||||
**接口地址:** `GET /ccdi/intermediary/list`
|
||||
|
||||
**请求参数:**
|
||||
|
||||
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|
||||
|--------|------|------|------|------|
|
||||
| name | String | 否 | 姓名/机构名称(模糊查询) | 张三 |
|
||||
| certificateNo | String | 否 | 证件号/社会信用代码(模糊查询) | 110101... |
|
||||
| intermediaryType | String | 否 | 中介类型(1=个人,2=机构) | 1 |
|
||||
| status | String | 否 | 状态(0=正常,1=停用) | 0 |
|
||||
| pageNum | Int | 否 | 页码 | 1 |
|
||||
| pageSize | Int | 否 | 每页条数 | 10 |
|
||||
|
||||
**查询场景示例:**
|
||||
|
||||
#### 场景1: 查询所有中介(个人+机构)
|
||||
```http
|
||||
GET /ccdi/intermediary/list
|
||||
```
|
||||
|
||||
#### 场景2: 只查询个人中介
|
||||
```http
|
||||
GET /ccdi/intermediary/list?intermediaryType=1
|
||||
```
|
||||
|
||||
#### 场景3: 只查询机构中介
|
||||
```http
|
||||
GET /ccdi/intermediary/list?intermediaryType=2
|
||||
```
|
||||
|
||||
#### 场景4: 按姓名查询个人中介
|
||||
```http
|
||||
GET /ccdi/intermediary/list?intermediaryType=1&name=张三
|
||||
```
|
||||
|
||||
#### 场景5: 按证件号查询机构中介
|
||||
```http
|
||||
GET /ccdi/intermediary/list?intermediaryType=2&certificateNo=91110000...
|
||||
```
|
||||
|
||||
#### 场景6: 分页查询所有中介
|
||||
```http
|
||||
GET /ccdi/intermediary/list?pageNum=1&pageSize=10
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## SQL 实现逻辑
|
||||
|
||||
### 分页查询优化
|
||||
|
||||
使用 `UNION ALL` 在数据库层面完成联合查询和分页,提升性能:
|
||||
|
||||
```sql
|
||||
SELECT * FROM (
|
||||
-- 个人中介查询
|
||||
SELECT
|
||||
biz_id AS intermediary_id,
|
||||
name,
|
||||
person_id AS certificate_no,
|
||||
'1' AS intermediary_type,
|
||||
'0' AS status,
|
||||
date_source AS data_source,
|
||||
create_time,
|
||||
update_time
|
||||
FROM ccdi_biz_intermediary
|
||||
WHERE 1=1
|
||||
<!-- 类型过滤 -->
|
||||
<if test="intermediaryType != null">
|
||||
AND '1' = #{intermediaryType}
|
||||
</if>
|
||||
|
||||
UNION ALL
|
||||
|
||||
-- 机构中介查询
|
||||
SELECT
|
||||
0 AS intermediary_id,
|
||||
enterprise_name AS name,
|
||||
social_credit_code AS certificate_no,
|
||||
'2' AS intermediary_type,
|
||||
status,
|
||||
data_source,
|
||||
create_time,
|
||||
update_time
|
||||
FROM ccdi_enterprise_base_info
|
||||
WHERE ent_source = 'INTERMEDIARY'
|
||||
<!-- 类型过滤 -->
|
||||
<if test="intermediaryType != null">
|
||||
AND '2' = #{intermediaryType}
|
||||
</if>
|
||||
) AS combined_data
|
||||
ORDER BY create_time DESC
|
||||
LIMIT 10 OFFSET 0 -- MyBatis Plus 自动添加
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 类型过滤逻辑
|
||||
|
||||
### 在 SQL 子查询层面过滤
|
||||
|
||||
| 查询条件 | 个人中介子查询 | 机构中介子查询 |
|
||||
|----------|--------------|--------------|
|
||||
| `intermediaryType=null` | 执行 | 执行 |
|
||||
| `intermediaryType=1` | 执行 (`'1'='1'` 为真) | 不返回数据 (`'2'='1'` 为假) |
|
||||
| `intermediaryType=2` | 不返回数据 (`'1'='2'` 为假) | 执行 (`'2'='2'` 为真) |
|
||||
|
||||
**优势:**
|
||||
- ✅ 避免查询不需要的数据
|
||||
- ✅ 减少数据库 I/O
|
||||
- ✅ 提升 UNION 性能
|
||||
- ✅ 分页准确
|
||||
|
||||
---
|
||||
|
||||
## 列表查询(非分页)
|
||||
|
||||
Service 层实现:
|
||||
|
||||
```java
|
||||
@Override
|
||||
public List<CcdiIntermediaryBlacklistVO> selectIntermediaryList(
|
||||
CcdiIntermediaryBlacklistQueryDTO queryDTO) {
|
||||
|
||||
List<CcdiIntermediaryBlacklistVO> resultList = new ArrayList<>();
|
||||
|
||||
// 查询个人中介
|
||||
if (StringUtils.isEmpty(queryDTO.getIntermediaryType()) || "1".equals(queryDTO.getIntermediaryType())) {
|
||||
LambdaQueryWrapper<CcdiBizIntermediary> personWrapper = buildPersonQueryWrapper(queryDTO);
|
||||
List<CcdiBizIntermediary> personList = bizIntermediaryMapper.selectList(personWrapper);
|
||||
personList.forEach(person -> resultList.add(convertPersonToVO(person)));
|
||||
}
|
||||
|
||||
// 查询机构中介
|
||||
if (StringUtils.isEmpty(queryDTO.getIntermediaryType()) || "2".equals(queryDTO.getIntermediaryType())) {
|
||||
LambdaQueryWrapper<CcdiEnterpriseBaseInfo> entityWrapper = buildEntityQueryWrapper(queryDTO);
|
||||
List<CcdiEnterpriseBaseInfo> entityList = enterpriseBaseInfoMapper.selectList(entityWrapper);
|
||||
entityList.forEach(entity -> resultList.add(convertEntityToVO(entity)));
|
||||
}
|
||||
|
||||
return resultList;
|
||||
}
|
||||
```
|
||||
|
||||
**逻辑说明:**
|
||||
- 当 `intermediaryType` 为空时,查询两种类型
|
||||
- 当 `intermediaryType = "1"` 时,只查询个人中介
|
||||
- 当 `intermediaryType = "2"` 时,只查询机构中介
|
||||
|
||||
---
|
||||
|
||||
## 返回数据格式
|
||||
|
||||
### 个人中介
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "查询成功",
|
||||
"rows": [
|
||||
{
|
||||
"intermediaryId": 1,
|
||||
"name": "张三",
|
||||
"certificateNo": "110101199001011234",
|
||||
"intermediaryType": "1",
|
||||
"intermediaryTypeName": "个人",
|
||||
"status": "0",
|
||||
"statusName": "正常",
|
||||
"dataSource": "MANUAL",
|
||||
"dataSourceName": "手动录入",
|
||||
"createTime": "2026-02-04 10:00:00",
|
||||
"updateTime": "2026-02-04 10:00:00"
|
||||
}
|
||||
],
|
||||
"total": 1
|
||||
}
|
||||
```
|
||||
|
||||
### 机构中介
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "查询成功",
|
||||
"rows": [
|
||||
{
|
||||
"intermediaryId": 0,
|
||||
"name": "测试机构有限公司",
|
||||
"certificateNo": "91110000123456789X",
|
||||
"intermediaryType": "2",
|
||||
"intermediaryTypeName": "机构",
|
||||
"status": "0",
|
||||
"statusName": "正常",
|
||||
"dataSource": "MANUAL",
|
||||
"dataSourceName": "手动录入",
|
||||
"createTime": "2026-02-04 10:00:00",
|
||||
"updateTime": "2026-02-04 10:00:00"
|
||||
}
|
||||
],
|
||||
"total": 1
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 性能对比
|
||||
|
||||
| 场景 | 旧实现 | 新实现 |
|
||||
|------|--------|--------|
|
||||
| 查询所有 | 查询2张表 | UNION ALL 查询2张表 |
|
||||
| 只查个人 | 查询2张表,应用层过滤 | 只查个人表 |
|
||||
| 只查机构 | 查询2张表,应用层过滤 | 只查机构表 |
|
||||
| 分页 | 查询全部,手动截取 | LIMIT/OFFSET 数据库分页 |
|
||||
|
||||
**性能提升:**
|
||||
- 只查个人/机构时,减少50%的数据库查询
|
||||
- 大数据量分页时,避免内存溢出
|
||||
- 网络传输量减少 90%+
|
||||
|
||||
---
|
||||
|
||||
## 测试用例
|
||||
|
||||
### 测试1: 查询所有中介
|
||||
```bash
|
||||
curl -X GET "http://localhost:8080/ccdi/intermediary/list" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**预期:** 返回个人和机构两种类型的数据
|
||||
|
||||
### 测试2: 只查询个人中介
|
||||
```bash
|
||||
curl -X GET "http://localhost:8080/ccdi/intermediary/list?intermediaryType=1" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**预期:** 只返回个人中介数据
|
||||
|
||||
### 测试3: 只查询机构中介
|
||||
```bash
|
||||
curl -X GET "http://localhost:8080/ccdi/intermediary/list?intermediaryType=2" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**预期:** 只返回机构中介数据
|
||||
|
||||
### 测试4: 分页查询个人中介
|
||||
```bash
|
||||
curl -X GET "http://localhost:8080/ccdi/intermediary/list?intermediaryType=1&pageNum=1&pageSize=10" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**预期:**
|
||||
- 返回第1页,最多10条个人中介数据
|
||||
- total 为个人中介的总数
|
||||
|
||||
---
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **类型过滤在数据库层面完成**,不是在应用层过滤
|
||||
2. **分页使用 MyBatis Plus 的自动分页**,SQL 自动添加 LIMIT/OFFSET
|
||||
3. **机构中介的 ID 为 0**,因为主键是字符串类型(社会信用代码)
|
||||
4. **查询时自动过滤 `ent_source='INTERMEDIARY'`**,确保只返回中介来源的企业
|
||||
BIN
doc/原型图-上传数据页面.png
Normal file
BIN
doc/原型图-上传数据页面.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 260 KiB |
821
doc/原型图开发设计文档.md
Normal file
821
doc/原型图开发设计文档.md
Normal file
@@ -0,0 +1,821 @@
|
||||
# 纪检初核系统 - 原型图开发设计文档
|
||||
|
||||
## 一、项目概述
|
||||
|
||||
### 1.1 项目背景
|
||||
本项目是一个**纪检初核系统**,用于对银行信贷部门员工进行初步核查,通过分析银行流水、征信报告、员工关系等数据,识别潜在的违规行为和风险。
|
||||
|
||||
### 1.2 项目目标
|
||||
- 支持多维度数据导入(流水、征信、员工关系)
|
||||
- 提供可配置的风险监测模型
|
||||
- 自动识别高风险人员并生成初核提示
|
||||
- 提供专项排查工作台进行深入分析
|
||||
- 支持关系图谱和资金流向分析
|
||||
|
||||
### 1.3 技术栈
|
||||
- **后端**: Spring Boot 3.5.8 + MyBatis 3.0.5 + MySQL 8.2.0
|
||||
- **前端**: Vue 2.6.12 + Element UI 2.15.14
|
||||
- **数据库**: MySQL(表前缀:ccdi_)
|
||||
|
||||
---
|
||||
|
||||
## 二、页面结构与功能分析
|
||||
|
||||
### 2.1 页面导航结构
|
||||
|
||||
```
|
||||
纪检初核系统
|
||||
├── 项目管理
|
||||
│ ├── 项目详情
|
||||
│ ├── 上传数据
|
||||
│ ├── 参数配置
|
||||
│ └── 初核提示
|
||||
├── 初核结果
|
||||
│ ├── 专项排查工作台(高风险)
|
||||
│ ├── 专项排查工作台(中风险)
|
||||
│ └── 专项排查
|
||||
└── 流水明细查询
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2.2 页面1:上传数据
|
||||
|
||||
#### 功能描述
|
||||
支持在一个项目中上传多个主体/账户数据,进行汇总/独立分析。
|
||||
|
||||
#### 页面元素
|
||||
| 元素类型 | 元素名称/内容 | 说明 |
|
||||
|---------|--------------|------|
|
||||
| 项目信息 | 项目状态 | 显示项目当前状态(如:已完成) |
|
||||
| | 最后更新时间 | 显示项目最后更新时间 |
|
||||
| 上传模块1 | 流水导入 | 支持Excel、PDF格式文件批量上传 |
|
||||
| | | 占位符:拖拽文件到此处或点击上传 |
|
||||
| | | 支持格式:xlsx, xls, pdf |
|
||||
| 上传模块2 | 已上传流水查询 | 支持HTML格式 |
|
||||
| | | 占位符:拖拽文件到此处或点击上传 |
|
||||
| 上传模块3 | 征信导入 | 支持HTML格式征信报告解析 |
|
||||
| 上传模块4 | 员工家庭关系导入 | Excel模板上传员工家庭关系信息 |
|
||||
| | | 支持格式:xlsx, xls |
|
||||
| 名单库选择 | 高风险人员名单 | 复选框,显示人数(如68人) |
|
||||
| | 历史可疑人员名单 | 复选框,显示人数(如45人) |
|
||||
| | 监管关注名单 | 复选框,显示人数(如32人) |
|
||||
| 数据质量检查 | 数据完整性 | 进度条,显示百分比(如98.5%) |
|
||||
| | 格式一致性 | 进度条,显示百分比(如95.2%) |
|
||||
| | 余额连续性 | 进度条,显示百分比(如92.8%) |
|
||||
| | 检查结果 | 显示发现的问题数量 |
|
||||
| 操作按钮 | 拉取本行信息 | 触发拉取银行内部信息 |
|
||||
| | 生成报告 | 生成初核报告 |
|
||||
|
||||
#### 数据模型
|
||||
```sql
|
||||
-- 项目表
|
||||
CREATE TABLE ccdi_project (
|
||||
project_id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||
project_name VARCHAR(200) NOT NULL COMMENT '项目名称',
|
||||
project_status VARCHAR(50) COMMENT '项目状态',
|
||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
create_by VARCHAR(100),
|
||||
update_by VARCHAR(100),
|
||||
remark VARCHAR(500)
|
||||
) COMMENT '项目表';
|
||||
|
||||
-- 数据上传记录表
|
||||
CREATE TABLE ccdi_data_upload (
|
||||
upload_id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||
project_id BIGINT COMMENT '项目ID',
|
||||
upload_type VARCHAR(50) COMMENT '上传类型:流水/征信/家庭关系',
|
||||
file_name VARCHAR(500) COMMENT '文件名',
|
||||
file_path VARCHAR(1000) COMMENT '文件路径',
|
||||
upload_status VARCHAR(50) COMMENT '上传状态',
|
||||
upload_time DATETIME COMMENT '上传时间',
|
||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
create_by VARCHAR(100)
|
||||
) COMMENT '数据上传记录表';
|
||||
|
||||
-- 名单库选择记录表
|
||||
CREATE TABLE ccdi_blacklist_selection (
|
||||
selection_id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||
project_id BIGINT COMMENT '项目ID',
|
||||
blacklist_type VARCHAR(50) COMMENT '名单类型:高风险/历史可疑/监管关注',
|
||||
blacklist_id BIGINT COMMENT '名单ID',
|
||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
) COMMENT '名单库选择记录表';
|
||||
|
||||
-- 数据质量检查表
|
||||
CREATE TABLE ccdi_data_quality (
|
||||
quality_id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||
project_id BIGINT COMMENT '项目ID',
|
||||
check_item VARCHAR(100) COMMENT '检查项:完整性/一致性/连续性',
|
||||
check_result DECIMAL(5,2) COMMENT '检查结果百分比',
|
||||
issue_count INT COMMENT '问题数量',
|
||||
issue_detail TEXT COMMENT '问题详情',
|
||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
) COMMENT '数据质量检查表';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2.3 页面2:参数配置
|
||||
|
||||
#### 功能描述
|
||||
配置风险监测模型的阈值参数。
|
||||
|
||||
#### 页面元素
|
||||
| 元素类型 | 元素名称/内容 | 说明 |
|
||||
|---------|--------------|------|
|
||||
| 模型名称 | 大额交易模型 | 下拉选择 |
|
||||
| 阈值参数配置表格 | | |
|
||||
| 表格列1 | 监测项 | 如:单笔交易额 |
|
||||
| 表格列2 | 描述 | 如:单笔超过该金额视为大额交易 |
|
||||
| 表格列3 | 阈值设置 | 输入框,如:50000 |
|
||||
| 表格列4 | 单位 | 如:元 |
|
||||
| 操作按钮 | 保存配置 | 保存当前配置 |
|
||||
| | 恢复默认 | 恢复默认值 |
|
||||
| | 一键导出配置 | 导出配置文件 |
|
||||
|
||||
#### 监测项配置
|
||||
1. **单笔交易额**: 50000元
|
||||
2. **累计交易额**: 5000000元
|
||||
3. **大额存现**: 200000元
|
||||
4. **短时多次存现**: 100000元/4小时
|
||||
5. **频繁转账**: 10次/日
|
||||
6. **转账频率**: 1000000元/日
|
||||
|
||||
#### 数据模型
|
||||
```sql
|
||||
-- 风险模型表
|
||||
CREATE TABLE ccdi_risk_model (
|
||||
model_id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||
model_name VARCHAR(200) NOT NULL COMMENT '模型名称',
|
||||
model_code VARCHAR(100) COMMENT '模型编码',
|
||||
status VARCHAR(50) DEFAULT 'active' COMMENT '状态',
|
||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
create_by VARCHAR(100),
|
||||
update_by VARCHAR(100)
|
||||
) COMMENT '风险模型表';
|
||||
|
||||
-- 模型参数配置表
|
||||
CREATE TABLE ccdi_model_parameter (
|
||||
parameter_id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||
model_id BIGINT COMMENT '模型ID',
|
||||
parameter_name VARCHAR(200) COMMENT '参数名称',
|
||||
parameter_code VARCHAR(100) COMMENT '参数编码',
|
||||
parameter_desc VARCHAR(500) COMMENT '参数描述',
|
||||
threshold_value DECIMAL(20,2) COMMENT '阈值',
|
||||
unit VARCHAR(50) COMMENT '单位',
|
||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
) COMMENT '模型参数配置表';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2.4 页面3:初核提示
|
||||
|
||||
#### 功能描述
|
||||
展示初核结果的总体概况,包括人员风险分布、模型触发情况、可疑交易明细等。
|
||||
|
||||
#### 页面元素
|
||||
| 元素类型 | 元素名称/内容 | 说明 |
|
||||
|---------|--------------|------|
|
||||
| 统计卡片 | 总人数 | 显示总人数(如500) |
|
||||
| | 无预警人数 | 显示无预警人数(如432) |
|
||||
| | 低风险 | 显示低风险人数(如38) |
|
||||
| | 中风险 | 显示中风险人数(如20) |
|
||||
| | 高风险 | 显示高风险人数(如10) |
|
||||
| 模型触发情况表格 | 模型名称 | 如:大额交易监测 |
|
||||
| | 触发数 | 触发次数 |
|
||||
| | 触发人员 | 触发人员列表 |
|
||||
| | 操作 | 查看详情 |
|
||||
| 涉疑交易明细表 | 交易时间、可疑人员、关联人、关联员工、关系、摘要/交易类型、交易金额、操作 | |
|
||||
| 高风险人员清单 | 姓名、身份证号、所属部门、风险评分、触发模型数、核心异常点、操作 | 复选框支持批量操作 |
|
||||
| 中风险人员TOP10 | 姓名、身份证号、所属部门、触发模型、触发模型数、操作 | |
|
||||
| 异常账户清单 | 账户号、开户人姓名、开户银行、异常类型、异常发生时间、状态、操作 | |
|
||||
| 涉及违法人员清单表 | 姓名、身份证号、失信被执行人、刑事判决、行政处罚、公安涉案记录、限制高消费、违法信息更新时间、操作 | |
|
||||
| 筛选条件 | 姓名/工号搜索 | 输入框 |
|
||||
| | 部门筛选 | 下拉选择 |
|
||||
| | 风险等级筛选 | 下拉选择(全部/高风险/中风险/低风险) |
|
||||
| | 可疑人员类型筛选 | 下拉选择(全部/名单库命中/模型规则命中) |
|
||||
| | 模型筛选 | 复选框(大额交易/可疑财产/频繁转账等) |
|
||||
| | 模型筛选逻辑 | 单选:同时触发以上模型/触发任意模型 |
|
||||
| 批量操作 | 批量生成报告 | |
|
||||
| | 批量导出证据 | |
|
||||
| | 批量添加到关注列表 | |
|
||||
|
||||
#### 数据模型
|
||||
```sql
|
||||
-- 人员风险评分表
|
||||
CREATE TABLE ccdi_person_risk_score (
|
||||
score_id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||
project_id BIGINT COMMENT '项目ID',
|
||||
person_id BIGINT COMMENT '人员ID',
|
||||
person_name VARCHAR(100) COMMENT '姓名',
|
||||
id_card VARCHAR(50) COMMENT '身份证号',
|
||||
department VARCHAR(200) COMMENT '所属部门',
|
||||
risk_level VARCHAR(50) COMMENT '风险等级:高/中/低',
|
||||
risk_score INT COMMENT '风险评分',
|
||||
trigger_model_count INT COMMENT '触发模型数量',
|
||||
core_issue VARCHAR(500) COMMENT '核心异常点',
|
||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
) COMMENT '人员风险评分表';
|
||||
|
||||
-- 模型触发记录表
|
||||
CREATE TABLE ccdi_model_trigger_record (
|
||||
trigger_id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||
project_id BIGINT COMMENT '项目ID',
|
||||
model_id BIGINT COMMENT '模型ID',
|
||||
model_name VARCHAR(200) COMMENT '模型名称',
|
||||
trigger_count INT COMMENT '触发次数',
|
||||
trigger_persons TEXT COMMENT '触发人员列表',
|
||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
) COMMENT '模型触发记录表';
|
||||
|
||||
-- 涉疑交易明细表
|
||||
CREATE TABLE ccdi_suspicious_transaction (
|
||||
transaction_id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||
project_id BIGINT COMMENT '项目ID',
|
||||
transaction_time DATETIME COMMENT '交易时间',
|
||||
suspicious_person VARCHAR(100) COMMENT '可疑人员',
|
||||
related_person VARCHAR(100) COMMENT '关联人',
|
||||
related_employee VARCHAR(100) COMMENT '关联员工',
|
||||
relationship VARCHAR(100) COMMENT '关系',
|
||||
transaction_type VARCHAR(200) COMMENT '摘要/交易类型',
|
||||
transaction_amount DECIMAL(20,2) COMMENT '交易金额',
|
||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
) COMMENT '涉嫌交易明细表';
|
||||
|
||||
-- 异常账户表
|
||||
CREATE TABLE ccdi_abnormal_account (
|
||||
account_id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||
project_id BIGINT COMMENT '项目ID',
|
||||
account_no VARCHAR(100) COMMENT '账户号',
|
||||
account_holder VARCHAR(100) COMMENT '开户人姓名',
|
||||
bank_name VARCHAR(200) COMMENT '开户银行',
|
||||
abnormal_type VARCHAR(100) COMMENT '异常类型',
|
||||
abnormal_time DATETIME COMMENT '异常发生时间',
|
||||
account_status VARCHAR(50) COMMENT '状态',
|
||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
) COMMENT '异常账户表';
|
||||
|
||||
-- 违法人员信息表
|
||||
CREATE TABLE ccdi_illegal_person_info (
|
||||
info_id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||
person_id BIGINT COMMENT '人员ID',
|
||||
person_name VARCHAR(100) COMMENT '姓名',
|
||||
id_card VARCHAR(50) COMMENT '身份证号',
|
||||
is_dishonesty_executor VARCHAR(10) COMMENT '是否失信被执行人',
|
||||
is_criminal_penalty VARCHAR(10) COMMENT '是否有刑事判决',
|
||||
is_administrative_penalty VARCHAR(10) COMMENT '是否有行政处罚',
|
||||
is_police_case VARCHAR(10) COMMENT '是否有公安涉案记录',
|
||||
is_limit_consumption VARCHAR(10) COMMENT '是否限制高消费',
|
||||
update_time DATETIME COMMENT '违法信息更新时间',
|
||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
) COMMENT '违法人员信息表';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2.5 页面4:专项排查工作台-高风险
|
||||
|
||||
#### 功能描述
|
||||
针对高风险人员的详细排查工作台。
|
||||
|
||||
#### 页面元素
|
||||
| 元素类型 | 元素名称/内容 | 说明 |
|
||||
|---------|--------------|------|
|
||||
| 排查对象信息 | 排查对象 | 如:李四 |
|
||||
| | 姓名、工号、部门、职级、入职时间、风险等级、所属项目 | |
|
||||
| 触发模型列表 | 触发模型(5个) | |
|
||||
| | 大额交易监测 | 3笔 > 50万 |
|
||||
| | 频繁转账监测 | 1小时25笔 |
|
||||
| | 关联交易排查 | 配偶账户频繁交易 |
|
||||
| | 异常销户监测 | 1个账户突然销户 |
|
||||
| | 疑似赌博交易 | 涉赌商户5笔 |
|
||||
| 初核评分 | 风险评分 | 如:85分(高风险阈值:60分) |
|
||||
| 异常详情-大额交易 | 交易时间、本方账号/主体、对方名称/账户、摘要/交易类型、交易金额、标记状态 | 标记状态下拉:标记正常/标记可疑/确认异常 |
|
||||
| 异常详情-频繁转账 | 时间段、总笔数、总金额、主要对手、模式特征、核查建议 | |
|
||||
| 异常详情-关联交易 | 关联人、关联账户、交易特征、异常点、需核实 | |
|
||||
| 排查工具箱 | 查看完整流水、查看征信报告、查看资产信息、关系图谱分析、资金流向分析、导出所有证据、添加到案例库 | |
|
||||
| 排查进度标签页 | 异常明细、资产分析、征信摘要、关系人图谱、资金流向 | |
|
||||
| 操作按钮 | 生成报告、生成排查报告、标记为案例、关注 | |
|
||||
|
||||
#### 数据模型
|
||||
```sql
|
||||
-- 排查对象表
|
||||
CREATE TABLE ccdi_investigation_object (
|
||||
object_id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||
project_id BIGINT COMMENT '项目ID',
|
||||
person_id BIGINT COMMENT '人员ID',
|
||||
person_name VARCHAR(100) COMMENT '姓名',
|
||||
employee_no VARCHAR(100) COMMENT '工号',
|
||||
department VARCHAR(200) COMMENT '部门',
|
||||
position_level VARCHAR(100) COMMENT '职级',
|
||||
entry_date DATE COMMENT '入职时间',
|
||||
risk_level VARCHAR(50) COMMENT '风险等级',
|
||||
risk_score INT COMMENT '风险评分',
|
||||
investigation_status VARCHAR(50) COMMENT '排查状态',
|
||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
) COMMENT '排查对象表';
|
||||
|
||||
-- 排查触发模型表
|
||||
CREATE TABLE ccdi_investigation_trigger_model (
|
||||
trigger_model_id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||
object_id BIGINT COMMENT '排查对象ID',
|
||||
model_id BIGINT COMMENT '模型ID',
|
||||
model_name VARCHAR(200) COMMENT '模型名称',
|
||||
trigger_desc VARCHAR(500) COMMENT '触发描述',
|
||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
) COMMENT '排查触发模型表';
|
||||
|
||||
-- 异常交易明细表
|
||||
CREATE TABLE ccdi_abnormal_transaction_detail (
|
||||
detail_id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||
object_id BIGINT COMMENT '排查对象ID',
|
||||
transaction_time DATETIME COMMENT '交易时间',
|
||||
own_account VARCHAR(200) COMMENT '本方账号/主体',
|
||||
counterparty VARCHAR(200) COMMENT '对方名称/账户',
|
||||
transaction_type VARCHAR(200) COMMENT '摘要/交易类型',
|
||||
transaction_amount DECIMAL(20,2) COMMENT '交易金额',
|
||||
mark_status VARCHAR(50) COMMENT '标记状态:正常/可疑/异常',
|
||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
) COMMENT '异常交易明细表';
|
||||
|
||||
-- 排查进度表
|
||||
CREATE TABLE ccdi_investigation_progress (
|
||||
progress_id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||
object_id BIGINT COMMENT '排查对象ID',
|
||||
progress_type VARCHAR(100) COMMENT '进度类型:流水分析/征信分析/资产比对/人工核实',
|
||||
progress_status VARCHAR(50) COMMENT '进度状态',
|
||||
complete_time DATETIME COMMENT '完成时间',
|
||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
) COMMENT '排查进度表';
|
||||
|
||||
-- 关注列表表
|
||||
CREATE TABLE ccdi_attention_list (
|
||||
attention_id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||
object_id BIGINT COMMENT '排查对象ID',
|
||||
person_id BIGINT COMMENT '人员ID',
|
||||
attention_type VARCHAR(50) COMMENT '关注类型',
|
||||
create_by VARCHAR(100) COMMENT '创建人',
|
||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
) COMMENT '关注列表表';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2.6 页面5:专项排查
|
||||
|
||||
#### 功能描述
|
||||
员工详查分析功能,包括资产收入分析、图谱分析、采购查询等。
|
||||
|
||||
#### 页面元素
|
||||
| 元素类型 | 元素名称/内容 | 说明 |
|
||||
|---------|--------------|------|
|
||||
| 查询条件 | 身份证号 | 输入框 |
|
||||
| | 开始日期、结束日期 | 日期选择器 |
|
||||
| | 查询、重置 | 按钮 |
|
||||
| 详查结果 | 详查结果描述 | 如:收入+负债远低于资产 |
|
||||
| 基本信息 | 姓名、身份证号、资产/收入比 | |
|
||||
| 收入分析 | 工资收入、其他收入 | 显示金额和百分比 |
|
||||
| 本人资产分析 | 房产、存款、其他 | 显示金额和百分比 |
|
||||
| 配偶资产分析 | 房产、车产、其他 | 显示金额和百分比 |
|
||||
| 负债分析 | 房贷、其他贷款 | 显示金额和百分比 |
|
||||
| 汇总信息 | 本人+配偶资产合计、总负债 | |
|
||||
| 图谱分析标签页 | 关系人图谱、资金流图谱、实控账户图谱 | |
|
||||
| 关系人图谱 | 姓名搜索框、生成图谱按钮 | |
|
||||
| | 可视化图谱 | 显示配偶、对外投资、股东、高管关联等 |
|
||||
| | 操作按钮 | 展开所有关联、仅显示直接关联、导出图谱、筛选、刷新 |
|
||||
| 采购查询表格 | 序号、采购事项名称、交易日期、采购金额、供应商名称、对方账号、联系人、关联员工 | |
|
||||
| 扩展查询标签页 | 采购查询、人员调动查询、招聘查询 | |
|
||||
| 采购查询条件 | 采购时间范围、关联员工 | |
|
||||
|
||||
#### 数据模型
|
||||
```sql
|
||||
-- 员工资产分析表
|
||||
CREATE TABLE ccdi_employee_asset_analysis (
|
||||
analysis_id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||
person_id BIGINT COMMENT '人员ID',
|
||||
person_name VARCHAR(100) COMMENT '姓名',
|
||||
id_card VARCHAR(50) COMMENT '身份证号',
|
||||
asset_income_ratio DECIMAL(10,2) COMMENT '资产/收入比',
|
||||
annual_income DECIMAL(20,2) COMMENT '年收入',
|
||||
own_asset DECIMAL(20,2) COMMENT '本人资产',
|
||||
spouse_asset DECIMAL(20,2) COMMENT '配偶资产',
|
||||
total_asset DECIMAL(20,2) COMMENT '本人+配偶资产合计',
|
||||
total_liability DECIMAL(20,2) COMMENT '总负债',
|
||||
income_salary DECIMAL(20,2) COMMENT '工资收入',
|
||||
income_other DECIMAL(20,2) COMMENT '其他收入',
|
||||
asset_house DECIMAL(20,2) COMMENT '房产',
|
||||
asset_deposit DECIMAL(20,2) COMMENT '存款',
|
||||
asset_other DECIMAL(20,2) COMMENT '其他',
|
||||
liability_mortgage DECIMAL(20,2) COMMENT '房贷',
|
||||
liability_loan DECIMAL(20,2) COMMENT '其他贷款',
|
||||
spouse_asset_house DECIMAL(20,2) COMMENT '配偶房产',
|
||||
spouse_asset_car DECIMAL(20,2) COMMENT '配偶车产',
|
||||
spouse_asset_other DECIMAL(20,2) COMMENT '配偶其他',
|
||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
) COMMENT '员工资产分析表';
|
||||
|
||||
-- 关系人图谱表
|
||||
CREATE TABLE ccdi_relationship_graph (
|
||||
graph_id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||
person_id BIGINT COMMENT '人员ID',
|
||||
related_person_name VARCHAR(100) COMMENT '关联人姓名',
|
||||
relationship_type VARCHAR(100) COMMENT '关系类型:配偶/对外投资/股东/高管关联',
|
||||
related_entity_name VARCHAR(200) COMMENT '关联实体名称',
|
||||
share_ratio DECIMAL(5,2) COMMENT '持股比例',
|
||||
position VARCHAR(200) COMMENT '职位',
|
||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
) COMMENT '关系人图谱表';
|
||||
|
||||
-- 采购查询记录表
|
||||
CREATE TABLE ccdi_purchase_record (
|
||||
purchase_id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||
purchase_name VARCHAR(500) COMMENT '采购事项名称',
|
||||
transaction_date DATE COMMENT '交易日期',
|
||||
purchase_amount DECIMAL(20,2) COMMENT '采购金额',
|
||||
supplier_name VARCHAR(500) COMMENT '供应商名称',
|
||||
supplier_account VARCHAR(200) COMMENT '对方账号',
|
||||
contact_person VARCHAR(100) COMMENT '联系人',
|
||||
related_employee VARCHAR(100) COMMENT '关联员工',
|
||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
) COMMENT '采购查询记录表';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2.7 页面6:专项排查工作台-中风险
|
||||
|
||||
#### 功能描述
|
||||
针对中风险人员的排查工作台,功能与高风险工作台类似,但风险等级不同。
|
||||
|
||||
#### 页面元素
|
||||
与高风险工作台结构相同,主要区别:
|
||||
- 风险等级显示为"中风险"
|
||||
- 初核评分可能较低
|
||||
- 触发模型数量可能较少
|
||||
|
||||
数据模型与高风险工作台共用。
|
||||
|
||||
---
|
||||
|
||||
### 2.8 页面7:流水明细查询
|
||||
|
||||
#### 功能描述
|
||||
查询和筛选银行流水明细。
|
||||
|
||||
#### 页面元素
|
||||
| 元素类型 | 元素名称/内容 | 说明 |
|
||||
|---------|--------------|------|
|
||||
| 筛选条件 | 交易时间范围 | 开始日期、结束日期 |
|
||||
| | 对方名称 | 输入框,支持空值筛选 |
|
||||
| | 摘要 | 输入框,支持空值筛选 |
|
||||
| | 分类 | 多选下拉 |
|
||||
| | 本方主体 | 多选下拉 |
|
||||
| | 本方银行 | 多选下拉 |
|
||||
| | 本方账户 | 多选下拉 |
|
||||
| | 交易金额 | 范围输入(最小~最大) |
|
||||
| | 对方账户 | 输入框,支持空值筛选 |
|
||||
| | 交易类型 | 输入框,支持空值筛选 |
|
||||
| | 剔除关联方与本方 | 复选框 |
|
||||
| | 查询、重置 | 按钮 |
|
||||
| 流水类型切换 | 全部、流入、流出 | 单选或Tab切换 |
|
||||
| 流水明细表格 | 交易时间、本行账户/主体、对方名称/账户、摘要/交易类型、交易金额、分类、操作 | 支持复选框 |
|
||||
| 表格操作 | 修改分类 | 下拉或弹窗 |
|
||||
| 底部操作栏 | 已筛选X笔流水,已选中X笔流水 | |
|
||||
| | 导出流水 | |
|
||||
| | 加入分析 | |
|
||||
| 标签页 | 流水、对手方 | |
|
||||
|
||||
#### 数据模型
|
||||
```sql
|
||||
-- 流水明细表
|
||||
CREATE TABLE ccdi_transaction_detail (
|
||||
detail_id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||
project_id BIGINT COMMENT '项目ID',
|
||||
transaction_time DATETIME COMMENT '交易时间',
|
||||
own_account VARCHAR(200) COMMENT '本方账户/主体',
|
||||
own_bank VARCHAR(200) COMMENT '本方银行',
|
||||
counterparty_name VARCHAR(500) COMMENT '对方名称/账户',
|
||||
counterparty_account VARCHAR(200) COMMENT '对方账户',
|
||||
transaction_summary VARCHAR(500) COMMENT '摘要',
|
||||
transaction_type VARCHAR(200) COMMENT '交易类型',
|
||||
transaction_amount DECIMAL(20,2) COMMENT '交易金额',
|
||||
transaction_direction VARCHAR(50) COMMENT '交易方向:流入/流出',
|
||||
category VARCHAR(200) COMMENT '分类',
|
||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
) COMMENT '流水明细表';
|
||||
|
||||
-- 流水分类表
|
||||
CREATE TABLE ccdi_transaction_category (
|
||||
category_id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||
category_code VARCHAR(100) COMMENT '分类编码',
|
||||
category_name VARCHAR(200) COMMENT '分类名称',
|
||||
parent_id BIGINT COMMENT '父分类ID',
|
||||
sort_order INT COMMENT '排序',
|
||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
) COMMENT '流水分类表';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、模块划分与开发建议
|
||||
|
||||
### 3.1 后端模块划分
|
||||
|
||||
```
|
||||
ruoyi-ccdi/ (新建模块)
|
||||
├── controller/
|
||||
│ ├── CcdiProjectController.java # 项目管理
|
||||
│ ├── CcdiDataUploadController.java # 数据上传
|
||||
│ ├── CcdiModelConfigController.java # 模型配置
|
||||
│ ├── CcdiPreliminaryCheckController.java # 初核提示
|
||||
│ ├── CcdiInvestigationController.java # 专项排查工作台
|
||||
│ ├── CcdiSpecialCheckController.java # 专项排查
|
||||
│ └── CcdiTransactionController.java # 流水明细查询
|
||||
├── service/
|
||||
│ ├── ICcdiProjectService.java
|
||||
│ ├── ICcdiDataUploadService.java
|
||||
│ ├── ICcdiModelConfigService.java
|
||||
│ ├── ICcdiPreliminaryCheckService.java
|
||||
│ ├── ICcdiInvestigationService.java
|
||||
│ ├── ICcdiSpecialCheckService.java
|
||||
│ └── ICcdiTransactionService.java
|
||||
├── mapper/
|
||||
│ ├── CcdiProjectMapper.java
|
||||
│ ├── CcdiDataUploadMapper.java
|
||||
│ ├── CcdiModelConfigMapper.java
|
||||
│ ├── CcdiPreliminaryCheckMapper.java
|
||||
│ ├── CcdiInvestigationMapper.java
|
||||
│ ├── CcdiSpecialCheckMapper.java
|
||||
│ └── CcdiTransactionMapper.java
|
||||
├── domain/
|
||||
│ ├── CcdiProject.java
|
||||
│ ├── CcdiDataUpload.java
|
||||
│ ├── CcdiModelConfig.java
|
||||
│ ├── CcdiPersonRiskScore.java
|
||||
│ ├── CcdiInvestigationObject.java
|
||||
│ └── ...
|
||||
├── dto/
|
||||
│ ├── CcdiProjectQueryDTO.java
|
||||
│ ├── CcdiDataUploadDTO.java
|
||||
│ ├── CcdiModelConfigDTO.java
|
||||
│ └── ...
|
||||
└── vo/
|
||||
├── CcdiProjectVO.java
|
||||
├── CcdiPreliminaryCheckVO.java
|
||||
├── CcdiInvestigationVO.java
|
||||
└── ...
|
||||
```
|
||||
|
||||
### 3.2 前端模块划分
|
||||
|
||||
```
|
||||
ruoyi-ui/src/views/ccdi/
|
||||
├── project/
|
||||
│ ├── index.vue # 项目列表
|
||||
│ ├── detail.vue # 项目详情
|
||||
│ ├── upload.vue # 上传数据
|
||||
│ └── components/
|
||||
│ ├── UploadCard.vue # 上传卡片组件
|
||||
│ ├── QualityCheck.vue # 数据质量检查组件
|
||||
│ └── BlacklistSelect.vue # 名单库选择组件
|
||||
├── model/
|
||||
│ ├── config.vue # 参数配置
|
||||
│ └── components/
|
||||
│ └── ModelConfigTable.vue # 模型配置表格组件
|
||||
├── preliminary/
|
||||
│ ├── index.vue # 初核提示
|
||||
│ └── components/
|
||||
│ ├── RiskStatistics.vue # 风险统计卡片
|
||||
│ ├── ModelTriggerTable.vue # 模型触发表格
|
||||
│ ├── SuspiciousTransactionTable.vue # 涉疑交易表格
|
||||
│ └── PersonRiskList.vue # 人员风险列表
|
||||
├── investigation/
|
||||
│ ├── high-risk.vue # 高风险工作台
|
||||
│ ├── mid-risk.vue # 中风险工作台
|
||||
│ └── components/
|
||||
│ ├── ObjectInfo.vue # 排查对象信息
|
||||
│ ├── AbnormalTransaction.vue # 异常交易明细
|
||||
│ ├── InvestigationTools.vue # 排查工具箱
|
||||
│ └── InvestigationTabs.vue # 排查进度标签页
|
||||
├── special/
|
||||
│ ├── index.vue # 专项排查
|
||||
│ └── components/
|
||||
│ ├── AssetAnalysis.vue # 资产分析
|
||||
│ ├── RelationshipGraph.vue # 关系人图谱
|
||||
│ └── PurchaseTable.vue # 采购查询表格
|
||||
└── transaction/
|
||||
└── index.vue # 流水明细查询
|
||||
```
|
||||
|
||||
### 3.3 开发顺序建议
|
||||
|
||||
1. **第一阶段:基础数据管理**
|
||||
- 项目管理(创建、查询、更新)
|
||||
- 数据上传功能
|
||||
- 数据质量检查
|
||||
|
||||
2. **第二阶段:模型配置**
|
||||
- 风险模型配置
|
||||
- 模型参数配置
|
||||
- 模型触发规则
|
||||
|
||||
3. **第三阶段:初核分析**
|
||||
- 初核提示页面
|
||||
- 风险评分计算
|
||||
- 人员风险分类
|
||||
|
||||
4. **第四阶段:排查工作台**
|
||||
- 高风险工作台
|
||||
- 中风险工作台
|
||||
- 排查进度跟踪
|
||||
|
||||
5. **第五阶段:专项排查**
|
||||
- 员工详查分析
|
||||
- 资产收入分析
|
||||
- 关系图谱分析
|
||||
- 采购查询
|
||||
|
||||
6. **第六阶段:流水查询**
|
||||
- 流水明细查询
|
||||
- 多维度筛选
|
||||
- 流水分类管理
|
||||
|
||||
---
|
||||
|
||||
## 四、关键技术要点
|
||||
|
||||
### 4.1 文件上传处理
|
||||
- 支持Excel、PDF、HTML多种格式
|
||||
- 需要实现文件解析功能
|
||||
- 大文件上传需要分片处理
|
||||
- 上传进度显示
|
||||
|
||||
### 4.2 数据质量检查
|
||||
- 数据完整性检查
|
||||
- 格式一致性检查
|
||||
- 余额连续性检查
|
||||
- 异常数据识别
|
||||
|
||||
### 4.3 风险评分模型
|
||||
- 可配置的风险模型
|
||||
- 可配置的阈值参数
|
||||
- 多模型触发计算
|
||||
- 风险等级分类
|
||||
|
||||
### 4.4 图谱可视化
|
||||
- 关系人图谱展示
|
||||
- 资金流向图谱
|
||||
- 实控账户图谱
|
||||
- 图谱交互操作
|
||||
|
||||
### 4.5 数据导出
|
||||
- 支持多种导出格式
|
||||
- 大数据量导出优化
|
||||
- 批量导出功能
|
||||
|
||||
---
|
||||
|
||||
## 五、接口设计建议
|
||||
|
||||
### 5.1 项目管理接口
|
||||
|
||||
```
|
||||
POST /ccdi/project/list # 项目列表查询
|
||||
GET /ccdi/project/{id} # 项目详情
|
||||
POST /ccdi/project # 新增项目
|
||||
PUT /ccdi/project # 更新项目
|
||||
DELETE /ccdi/project/{id} # 删除项目
|
||||
```
|
||||
|
||||
### 5.2 数据上传接口
|
||||
|
||||
```
|
||||
POST /ccdi/upload/transaction # 上传流水文件
|
||||
POST /ccdi/upload/credit # 上传征信文件
|
||||
POST /ccdi/upload/relation # 上传家庭关系文件
|
||||
GET /ccdi/upload/progress/{id} # 查询上传进度
|
||||
POST /ccdi/upload/quality/check # 数据质量检查
|
||||
```
|
||||
|
||||
### 5.3 初核分析接口
|
||||
|
||||
```
|
||||
GET /ccdi/preliminary/statistics # 获取统计数据
|
||||
GET /ccdi/preliminary/model/trigger # 模型触发情况
|
||||
GET /ccdi/preliminary/transaction # 涉疑交易明细
|
||||
GET /ccdi/preliminary/person/list # 人员风险列表
|
||||
GET /ccdi/preliminary/abnormal/account # 异常账户列表
|
||||
POST /ccdi/preliminary/batch/report # 批量生成报告
|
||||
```
|
||||
|
||||
### 5.4 排查工作台接口
|
||||
|
||||
```
|
||||
GET /ccdi/investigation/object/{id} # 获取排查对象详情
|
||||
GET /ccdi/investigation/abnormal/{id} # 获取异常交易详情
|
||||
GET /ccdi/investigation/progress/{id} # 获取排查进度
|
||||
PUT /ccdi/investigation/mark/status # 标记状态
|
||||
POST /ccdi/investigation/report # 生成排查报告
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 六、数据库表汇总
|
||||
|
||||
| 序号 | 表名 | 说明 |
|
||||
|------|------|------|
|
||||
| 1 | ccdi_project | 项目表 |
|
||||
| 2 | ccdi_data_upload | 数据上传记录表 |
|
||||
| 3 | ccdi_blacklist_selection | 名单库选择记录表 |
|
||||
| 4 | ccdi_data_quality | 数据质量检查表 |
|
||||
| 5 | ccdi_risk_model | 风险模型表 |
|
||||
| 6 | ccdi_model_parameter | 模型参数配置表 |
|
||||
| 7 | ccdi_person_risk_score | 人员风险评分表 |
|
||||
| 8 | ccdi_model_trigger_record | 模型触发记录表 |
|
||||
| 9 | ccdi_suspicious_transaction | 涉嫌交易明细表 |
|
||||
| 10 | ccdi_abnormal_account | 异常账户表 |
|
||||
| 11 | ccdi_illegal_person_info | 违法人员信息表 |
|
||||
| 12 | ccdi_investigation_object | 排查对象表 |
|
||||
| 13 | ccdi_investigation_trigger_model | 排查触发模型表 |
|
||||
| 14 | ccdi_abnormal_transaction_detail | 异常交易明细表 |
|
||||
| 15 | ccdi_investigation_progress | 排查进度表 |
|
||||
| 16 | ccdi_attention_list | 关注列表表 |
|
||||
| 17 | ccdi_employee_asset_analysis | 员工资产分析表 |
|
||||
| 18 | ccdi_relationship_graph | 关系人图谱表 |
|
||||
| 19 | ccdi_purchase_record | 采购查询记录表 |
|
||||
| 20 | ccdi_transaction_detail | 流水明细表 |
|
||||
| 21 | ccdi_transaction_category | 流水分类表 |
|
||||
|
||||
---
|
||||
|
||||
## 七、前端组件建议
|
||||
|
||||
### 7.1 通用组件
|
||||
|
||||
```javascript
|
||||
// components/ccdi/
|
||||
├── UploadCard.vue # 文件上传卡片
|
||||
├── RiskStatisticsCard.vue # 风险统计卡片
|
||||
├── QualityProgressBar.vue # 质量检查进度条
|
||||
├── ModelTriggerTable.vue # 模型触发表格
|
||||
├── PersonRiskList.vue # 人员风险列表
|
||||
├── TransactionTable.vue # 交易明细表格
|
||||
├── RelationshipGraph.vue # 关系图谱组件
|
||||
└── FilterPanel.vue # 筛选面板组件
|
||||
```
|
||||
|
||||
### 7.2 图表组件
|
||||
|
||||
```javascript
|
||||
// 使用ECharts实现
|
||||
├── RiskDistributionChart.vue # 风险分布图
|
||||
├── ModelTriggerChart.vue # 模型触发图表
|
||||
├── AssetAnalysisChart.vue # 资产分析图表
|
||||
└── RelationshipGraphChart.vue # 关系图谱
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 八、开发注意事项
|
||||
|
||||
### 8.1 权限控制
|
||||
- 项目级权限控制
|
||||
- 数据访问权限
|
||||
- 敏感信息脱敏
|
||||
|
||||
### 8.2 性能优化
|
||||
- 大数据量查询分页
|
||||
- 索引优化
|
||||
- 缓存策略
|
||||
|
||||
### 8.3 数据安全
|
||||
- 敏感数据加密
|
||||
- 操作日志记录
|
||||
- 数据备份
|
||||
|
||||
### 8.4 用户体验
|
||||
- 加载状态提示
|
||||
- 操作反馈
|
||||
- 错误提示
|
||||
|
||||
---
|
||||
|
||||
## 九、后续扩展方向
|
||||
|
||||
1. **智能分析**:引入机器学习算法,提高风险识别准确率
|
||||
2. **移动端适配**:开发移动端应用,支持移动办公
|
||||
3. **报表中心**:自定义报表功能
|
||||
4. **预警机制**:实时预警通知
|
||||
5. **案例库管理**:典型案例沉淀和复用
|
||||
|
||||
---
|
||||
|
||||
**文档版本**: v1.0
|
||||
**创建时间**: 2025-01-30
|
||||
**最后更新**: 2025-01-30
|
||||
326
doc/后端枚举字段说明.md
Normal file
326
doc/后端枚举字段说明.md
Normal file
@@ -0,0 +1,326 @@
|
||||
# 后端枚举字段说明
|
||||
|
||||
## 概述
|
||||
|
||||
后端只返回枚举代码值,不返回枚举名称。前端需要根据代码值进行转换显示。
|
||||
|
||||
---
|
||||
|
||||
## API 返回的枚举字段
|
||||
|
||||
### 1. 中介类型 (intermediaryType)
|
||||
|
||||
| 代码值 | 说明 |
|
||||
|--------|------|
|
||||
| `1` | 个人中介 |
|
||||
| `2` | 机构中介 |
|
||||
|
||||
**前端转换示例:**
|
||||
```javascript
|
||||
const getIntermediaryTypeName = (type) => {
|
||||
const map = {
|
||||
'1': '个人',
|
||||
'2': '机构'
|
||||
}
|
||||
return map[type] || '未知'
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 状态 (status)
|
||||
|
||||
| 代码值 | 说明 |
|
||||
|--------|------|
|
||||
| `0` | 正常 |
|
||||
| `1` | 停用 |
|
||||
|
||||
**前端转换示例:**
|
||||
```javascript
|
||||
const getStatusName = (status) => {
|
||||
const map = {
|
||||
'0': '正常',
|
||||
'1': '停用'
|
||||
}
|
||||
return map[status] || '未知'
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 数据来源 (dataSource / date_source)
|
||||
|
||||
| 代码值 | 说明 |
|
||||
|--------|------|
|
||||
| `MANUAL` | 手动录入 |
|
||||
| `IMPORT` | 批量导入 |
|
||||
| `SYSTEM` | 系统同步 |
|
||||
| `API` | 接口获取 |
|
||||
|
||||
**前端转换示例:**
|
||||
```javascript
|
||||
const getDataSourceName = (source) => {
|
||||
const map = {
|
||||
'MANUAL': '手动录入',
|
||||
'IMPORT': '批量导入',
|
||||
'SYSTEM': '系统同步',
|
||||
'API': '接口获取'
|
||||
}
|
||||
return map[source] || '未知'
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 性别 (indivGender) - 个人中介
|
||||
|
||||
| 代码值 | 说明 |
|
||||
|--------|------|
|
||||
| `M` | 男 |
|
||||
| `F` | 女 |
|
||||
| `O` | 其他 |
|
||||
|
||||
**前端转换示例:**
|
||||
```javascript
|
||||
const getGenderName = (gender) => {
|
||||
const map = {
|
||||
'M': '男',
|
||||
'F': '女',
|
||||
'O': '其他'
|
||||
}
|
||||
return map[gender] || '未知'
|
||||
}
|
||||
```
|
||||
|
||||
### 5. 证件类型 (indivCertType)
|
||||
|
||||
常用证件类型代码:
|
||||
- `身份证` - 身份证
|
||||
- `护照` - 护照
|
||||
- `港澳通行证` - 港澳通行证
|
||||
- `台湾通行证` - 台湾通行证
|
||||
|
||||
---
|
||||
|
||||
## API 返回数据示例
|
||||
|
||||
### 列表查询响应
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "查询成功",
|
||||
"rows": [
|
||||
{
|
||||
"intermediaryId": 1,
|
||||
"name": "张三",
|
||||
"certificateNo": "110101199001011234",
|
||||
"intermediaryType": "1",
|
||||
"status": "0",
|
||||
"dataSource": "MANUAL",
|
||||
"createTime": "2026-02-04 10:00:00",
|
||||
"updateTime": "2026-02-04 10:00:00"
|
||||
},
|
||||
{
|
||||
"intermediaryId": 0,
|
||||
"name": "测试机构有限公司",
|
||||
"certificateNo": "91110000123456789X",
|
||||
"intermediaryType": "2",
|
||||
"status": "0",
|
||||
"dataSource": "MANUAL",
|
||||
"createTime": "2026-02-04 10:00:00",
|
||||
"updateTime": "2026-02-04 10:00:00"
|
||||
}
|
||||
],
|
||||
"total": 2
|
||||
}
|
||||
```
|
||||
|
||||
### 个人中介详情响应
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"data": {
|
||||
"intermediaryId": 1,
|
||||
"name": "张三",
|
||||
"certificateNo": "110101199001011234",
|
||||
"intermediaryType": "1",
|
||||
"status": "0",
|
||||
"dataSource": "MANUAL",
|
||||
"remark": "测试数据",
|
||||
"indivType": "中介",
|
||||
"indivSubType": "本人",
|
||||
"indivGender": "M",
|
||||
"indivCertType": "身份证",
|
||||
"indivPhone": "13800138000",
|
||||
"indivWechat": "test_wx001",
|
||||
"indivAddress": "北京市朝阳区测试路123号",
|
||||
"indivCompany": "测试公司",
|
||||
"indivPosition": "测试员",
|
||||
"createTime": "2026-02-04 10:00:00"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 机构中介详情响应
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"data": {
|
||||
"intermediaryId": 0,
|
||||
"name": "测试机构有限公司",
|
||||
"certificateNo": "91110000123456789X",
|
||||
"intermediaryType": "2",
|
||||
"status": "0",
|
||||
"dataSource": "MANUAL",
|
||||
"remark": "机构中介测试数据",
|
||||
"corpCreditCode": "91110000123456789X",
|
||||
"corpType": "有限责任公司",
|
||||
"corpNature": "民营企业",
|
||||
"corpIndustryCategory": "制造业",
|
||||
"corpIndustry": "通用设备制造业",
|
||||
"corpEstablishDate": "2020-01-01",
|
||||
"corpAddress": "北京市海淀区测试大街456号",
|
||||
"corpLegalRep": "李四",
|
||||
"corpLegalCertType": "身份证",
|
||||
"corpLegalCertNo": "110101198001011234",
|
||||
"createTime": "2026-02-04 10:00:00"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 前端 Vue 组件示例
|
||||
|
||||
### 枚举转换工具函数
|
||||
|
||||
```javascript
|
||||
// utils/enums.js
|
||||
export const IntermediaryType = {
|
||||
PERSON: '1',
|
||||
ENTITY: '2',
|
||||
getName: (type) => {
|
||||
const map = {
|
||||
'1': '个人',
|
||||
'2': '机构'
|
||||
}
|
||||
return map[type] || '未知'
|
||||
}
|
||||
}
|
||||
|
||||
export const IntermediaryStatus = {
|
||||
NORMAL: '0',
|
||||
DISABLED: '1',
|
||||
getName: (status) => {
|
||||
const map = {
|
||||
'0': '正常',
|
||||
'1': '停用'
|
||||
}
|
||||
return map[status] || '未知'
|
||||
}
|
||||
}
|
||||
|
||||
export const DataSource = {
|
||||
MANUAL: 'MANUAL',
|
||||
IMPORT: 'IMPORT',
|
||||
SYSTEM: 'SYSTEM',
|
||||
API: 'API',
|
||||
getName: (source) => {
|
||||
const map = {
|
||||
'MANUAL': '手动录入',
|
||||
'IMPORT': '批量导入',
|
||||
'SYSTEM': '系统同步',
|
||||
'API': '接口获取'
|
||||
}
|
||||
return map[source] || '未知'
|
||||
}
|
||||
}
|
||||
|
||||
export const Gender = {
|
||||
MALE: 'M',
|
||||
FEMALE: 'F',
|
||||
OTHER: 'O',
|
||||
getName: (gender) => {
|
||||
const map = {
|
||||
'M': '男',
|
||||
'F': '女',
|
||||
'O': '其他'
|
||||
}
|
||||
return map[gender] || '未知'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 表格列使用枚举
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<el-table :data="tableData">
|
||||
<el-table-column prop="name" label="姓名" />
|
||||
|
||||
<el-table-column prop="intermediaryType" label="中介类型">
|
||||
<template #default="{ row }">
|
||||
{{ IntermediaryType.getName(row.intermediaryType) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="status" label="状态">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.status === '0' ? 'success' : 'danger'">
|
||||
{{ IntermediaryStatus.getName(row.status) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="dataSource" label="数据来源">
|
||||
<template #default="{ row }">
|
||||
{{ DataSource.getName(row.dataSource) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { IntermediaryType, IntermediaryStatus, DataSource } from '@/utils/enums'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
IntermediaryType,
|
||||
IntermediaryStatus,
|
||||
DataSource,
|
||||
tableData: []
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
### 表单下拉框使用枚举
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<el-form :model="form">
|
||||
<el-form-item label="中介类型" prop="intermediaryType">
|
||||
<el-select v-model="form.intermediaryType" placeholder="请选择中介类型">
|
||||
<el-option label="个人" value="1" />
|
||||
<el-option label="机构" value="2" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio label="0">正常</el-radio>
|
||||
<el-radio label="1">停用</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **后端只返回代码值**,前端负责转换为显示名称
|
||||
2. **前端下拉框的 value 应该使用代码值**(如 '1', '2', '0' 等)
|
||||
3. **建议在前端统一维护枚举映射关系**,避免硬编码
|
||||
4. **新增枚举值时**,只需要前端更新映射表即可,后端无需修改
|
||||
5. **国际化支持**:前端可以根据语言切换返回不同的名称
|
||||
@@ -25,7 +25,7 @@ spring:
|
||||
druid:
|
||||
# 主库数据源
|
||||
master:
|
||||
url: jdbc:mysql://116.62.17.81:3306/discipline-prelim-check?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
url: jdbc:mysql://116.62.17.81:3306/ccdi?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
username: root
|
||||
password: Kfcx@1234
|
||||
# 从库数据源
|
||||
|
||||
@@ -17,7 +17,7 @@ import java.util.List;
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Tag(name = "DPC枚举接口", description = "中介黑名单相关枚举选项接口")
|
||||
@Tag(name = "枚举接口", description = "中介黑名单相关枚举选项接口")
|
||||
@RestController
|
||||
@RequestMapping("/ccdi/enum")
|
||||
public class CcdiEnumController {
|
||||
|
||||
@@ -1,202 +0,0 @@
|
||||
package com.ruoyi.ccdi.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.ruoyi.ccdi.domain.CcdiIntermediaryBlacklist;
|
||||
import com.ruoyi.ccdi.domain.dto.*;
|
||||
import com.ruoyi.ccdi.domain.excel.CcdiIntermediaryBlacklistExcel;
|
||||
import com.ruoyi.ccdi.domain.excel.CcdiIntermediaryEntityExcel;
|
||||
import com.ruoyi.ccdi.domain.excel.CcdiIntermediaryPersonExcel;
|
||||
import com.ruoyi.ccdi.domain.vo.CcdiIntermediaryBlacklistVO;
|
||||
import com.ruoyi.ccdi.service.ICcdiIntermediaryBlacklistService;
|
||||
import com.ruoyi.ccdi.utils.EasyExcelUtil;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.page.PageDomain;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.core.page.TableSupport;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 中介人员黑名单Controller
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-01-27
|
||||
*/
|
||||
@Tag(name = "中介黑名单管理")
|
||||
@RestController
|
||||
@RequestMapping("/ccdi/intermediary")
|
||||
public class CcdiIntermediaryBlacklistController extends BaseController {
|
||||
|
||||
@Resource
|
||||
private ICcdiIntermediaryBlacklistService intermediaryService;
|
||||
|
||||
/**
|
||||
* 查询中介黑名单列表
|
||||
*/
|
||||
@Operation(summary = "查询中介黑名单列表")
|
||||
@PreAuthorize("@ss.hasPermi('ccdi:intermediary:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(CcdiIntermediaryBlacklistQueryDTO queryDTO) {
|
||||
// 使用MyBatis Plus分页
|
||||
PageDomain pageDomain = TableSupport.buildPageRequest();
|
||||
Page<CcdiIntermediaryBlacklist> page = new Page<>(pageDomain.getPageNum(), pageDomain.getPageSize());
|
||||
Page<CcdiIntermediaryBlacklistVO> result = intermediaryService.selectIntermediaryPage(page, queryDTO);
|
||||
return getDataTable(result.getRecords(), result.getTotal());
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出中介黑名单列表
|
||||
*/
|
||||
@Operation(summary = "导出中介黑名单列表")
|
||||
@PreAuthorize("@ss.hasPermi('ccdi:intermediary:export')")
|
||||
@Log(title = "中介黑名单", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(HttpServletResponse response, CcdiIntermediaryBlacklistQueryDTO queryDTO) {
|
||||
List<CcdiIntermediaryBlacklistExcel> list = intermediaryService.selectIntermediaryListForExport(queryDTO);
|
||||
EasyExcelUtil.exportExcel(response, list, CcdiIntermediaryBlacklistExcel.class, "中介黑名单");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取中介黑名单详细信息(根据类型返回不同结构)
|
||||
*/
|
||||
@Operation(summary = "获取中介黑名单详细信息")
|
||||
@PreAuthorize("@ss.hasPermi('ccdi:intermediary:query')")
|
||||
@GetMapping(value = "/{intermediaryId}")
|
||||
public AjaxResult getInfo(@PathVariable Long intermediaryId) {
|
||||
return success(intermediaryService.selectIntermediaryDetailById(intermediaryId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增中介黑名单(已废弃,请使用类型专用接口)
|
||||
*/
|
||||
@Operation(summary = "新增中介黑名单(已废弃,请使用类型专用接口)")
|
||||
@PreAuthorize("@ss.hasPermi('ccdi:intermediary:add')")
|
||||
@Log(title = "中介黑名单", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
@Deprecated
|
||||
public AjaxResult add(@Validated @RequestBody CcdiIntermediaryBlacklistAddDTO addDTO) {
|
||||
return toAjax(intermediaryService.insertIntermediary(addDTO));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增个人中介黑名单
|
||||
*/
|
||||
@Operation(summary = "新增个人中介黑名单")
|
||||
@PreAuthorize("@ss.hasPermi('ccdi:intermediary:add')")
|
||||
@Log(title = "个人中介黑名单", businessType = BusinessType.INSERT)
|
||||
@PostMapping("/person")
|
||||
public AjaxResult addPerson(@Validated @RequestBody CcdiIntermediaryPersonAddDTO addDTO) {
|
||||
return toAjax(intermediaryService.insertPersonIntermediary(addDTO));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增机构中介黑名单
|
||||
*/
|
||||
@Operation(summary = "新增机构中介黑名单")
|
||||
@PreAuthorize("@ss.hasPermi('ccdi:intermediary:add')")
|
||||
@Log(title = "机构中介黑名单", businessType = BusinessType.INSERT)
|
||||
@PostMapping("/entity")
|
||||
public AjaxResult addEntity(@Validated @RequestBody CcdiIntermediaryEntityAddDTO addDTO) {
|
||||
return toAjax(intermediaryService.insertEntityIntermediary(addDTO));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改中介黑名单
|
||||
*/
|
||||
@Operation(summary = "修改中介黑名单(已废弃,请使用类型专用接口)")
|
||||
@PreAuthorize("@ss.hasPermi('ccdi:intermediary:edit')")
|
||||
@Log(title = "中介黑名单", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
@Deprecated
|
||||
public AjaxResult edit(@Validated @RequestBody CcdiIntermediaryBlacklistEditDTO editDTO) {
|
||||
return toAjax(intermediaryService.updateIntermediary(editDTO));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改个人中介黑名单
|
||||
*/
|
||||
@Operation(summary = "修改个人中介黑名单")
|
||||
@PreAuthorize("@ss.hasPermi('ccdi:intermediary:edit')")
|
||||
@Log(title = "个人中介黑名单", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/person")
|
||||
public AjaxResult editPerson(@Validated @RequestBody CcdiIntermediaryPersonEditDTO editDTO) {
|
||||
return toAjax(intermediaryService.updatePersonIntermediary(editDTO));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改机构中介黑名单
|
||||
*/
|
||||
@Operation(summary = "修改机构中介黑名单")
|
||||
@PreAuthorize("@ss.hasPermi('ccdi:intermediary:edit')")
|
||||
@Log(title = "机构中介黑名单", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/entity")
|
||||
public AjaxResult editEntity(@Validated @RequestBody CcdiIntermediaryEntityEditDTO editDTO) {
|
||||
return toAjax(intermediaryService.updateEntityIntermediary(editDTO));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除中介黑名单
|
||||
*/
|
||||
@Operation(summary = "删除中介黑名单")
|
||||
@PreAuthorize("@ss.hasPermi('ccdi:intermediary:remove')")
|
||||
@Log(title = "中介黑名单", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{intermediaryIds}")
|
||||
public AjaxResult remove(@PathVariable Long[] intermediaryIds) {
|
||||
return toAjax(intermediaryService.deleteIntermediaryByIds(intermediaryIds));
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载个人中介导入模板(带字典下拉框)
|
||||
*/
|
||||
@Operation(summary = "下载个人中介导入模板")
|
||||
@PostMapping("/importPersonTemplate")
|
||||
public void importPersonTemplate(HttpServletResponse response) {
|
||||
EasyExcelUtil.importTemplateWithDictDropdown(response, CcdiIntermediaryPersonExcel.class, "个人中介黑名单");
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载机构中介导入模板(带字典下拉框)
|
||||
*/
|
||||
@Operation(summary = "下载机构中介导入模板")
|
||||
@PostMapping("/importEntityTemplate")
|
||||
public void importEntityTemplate(HttpServletResponse response) {
|
||||
EasyExcelUtil.importTemplateWithDictDropdown(response, CcdiIntermediaryEntityExcel.class, "机构中介黑名单");
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入个人中介黑名单
|
||||
*/
|
||||
@Operation(summary = "导入个人中介黑名单")
|
||||
@PreAuthorize("@ss.hasPermi('ccdi:intermediary:import')")
|
||||
@Log(title = "中介黑名单", businessType = BusinessType.IMPORT)
|
||||
@PostMapping("/importPersonData")
|
||||
public AjaxResult importPersonData(@RequestParam("file") MultipartFile file, @RequestParam(value = "updateSupport", defaultValue = "false") boolean updateSupport) throws Exception {
|
||||
List<CcdiIntermediaryPersonExcel> list = EasyExcelUtil.importExcel(file.getInputStream(), CcdiIntermediaryPersonExcel.class);
|
||||
String message = intermediaryService.importPersonIntermediary(list, updateSupport);
|
||||
return success(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入机构中介黑名单
|
||||
*/
|
||||
@Operation(summary = "导入机构中介黑名单")
|
||||
@PreAuthorize("@ss.hasPermi('ccdi:intermediary:import')")
|
||||
@Log(title = "中介黑名单", businessType = BusinessType.IMPORT)
|
||||
@PostMapping("/importEntityData")
|
||||
public AjaxResult importEntityData(@RequestParam("file") MultipartFile file, @RequestParam(value = "updateSupport", defaultValue = "false") boolean updateSupport) throws Exception {
|
||||
List<CcdiIntermediaryEntityExcel> list = EasyExcelUtil.importExcel(file.getInputStream(), CcdiIntermediaryEntityExcel.class);
|
||||
String message = intermediaryService.importEntityIntermediary(list, updateSupport);
|
||||
return success(message);
|
||||
}
|
||||
}
|
||||
@@ -1,154 +0,0 @@
|
||||
package com.ruoyi.ccdi.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 中介人员黑名单对象 dpc_intermediary_blacklist
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-01-27
|
||||
*/
|
||||
@Data
|
||||
public class CcdiIntermediaryBlacklist implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 中介ID */
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long intermediaryId;
|
||||
|
||||
/** 姓名/机构名称 */
|
||||
private String name;
|
||||
|
||||
/** 证件号 */
|
||||
private String certificateNo;
|
||||
|
||||
/** 中介类型 */
|
||||
private String intermediaryType;
|
||||
|
||||
/** 状态 */
|
||||
private String status;
|
||||
|
||||
/** 备注 */
|
||||
private String remark;
|
||||
|
||||
// ============================================================
|
||||
// 个人类型字段 (以 indiv_ 前缀标识,individual 缩写)
|
||||
// ============================================================
|
||||
/** 人员类型(中介、职业背债人、房产中介等) */
|
||||
private String indivType;
|
||||
|
||||
/** 人员子类型(本人、配偶等) */
|
||||
private String indivSubType;
|
||||
|
||||
/** 性别(M男 F女 O其他) */
|
||||
private String indivGender;
|
||||
|
||||
/** 证件类型 */
|
||||
private String indivCertType;
|
||||
|
||||
/** 手机号码(加密存储) */
|
||||
private String indivPhone;
|
||||
|
||||
/** 微信号 */
|
||||
private String indivWechat;
|
||||
|
||||
/** 联系地址 */
|
||||
private String indivAddress;
|
||||
|
||||
/** 所在公司 */
|
||||
private String indivCompany;
|
||||
|
||||
/** 职位/职务 */
|
||||
private String indivPosition;
|
||||
|
||||
/** 关联人员ID */
|
||||
private String indivRelatedId;
|
||||
|
||||
/** 关联关系 */
|
||||
private String indivRelation;
|
||||
|
||||
// ============================================================
|
||||
// 机构类型字段 (以 corp_ 前缀标识,corporation 缩写)
|
||||
// ============================================================
|
||||
/** 统一社会信用代码 */
|
||||
private String corpCreditCode;
|
||||
|
||||
/** 主体类型(有限责任公司、股份有限公司等) */
|
||||
private String corpType;
|
||||
|
||||
/** 企业性质(国企、民企、外企等) */
|
||||
private String corpNature;
|
||||
|
||||
/** 行业分类 */
|
||||
private String corpIndustryCategory;
|
||||
|
||||
/** 所属行业 */
|
||||
private String corpIndustry;
|
||||
|
||||
/** 成立日期 */
|
||||
private Date corpEstablishDate;
|
||||
|
||||
/** 注册地址 */
|
||||
private String corpAddress;
|
||||
|
||||
/** 法定代表人 */
|
||||
private String corpLegalRep;
|
||||
|
||||
/** 法定代表人证件类型 */
|
||||
private String corpLegalCertType;
|
||||
|
||||
/** 法定代表人证件号码 */
|
||||
private String corpLegalCertNo;
|
||||
|
||||
/** 股东1 */
|
||||
@TableField("corp_shareholder_1")
|
||||
private String corpShareholder1;
|
||||
|
||||
/** 股东2 */
|
||||
@TableField("corp_shareholder_2")
|
||||
private String corpShareholder2;
|
||||
|
||||
/** 股东3 */
|
||||
@TableField("corp_shareholder_3")
|
||||
private String corpShareholder3;
|
||||
|
||||
/** 股东4 */
|
||||
@TableField("corp_shareholder_4")
|
||||
private String corpShareholder4;
|
||||
|
||||
/** 股东5 */
|
||||
@TableField("corp_shareholder_5")
|
||||
private String corpShareholder5;
|
||||
|
||||
// ============================================================
|
||||
// 通用字段
|
||||
// ============================================================
|
||||
/** 数据来源(MANUAL手动录入 SYSTEM系统同步 IMPORT批量导入 API接口获取) */
|
||||
private String dataSource;
|
||||
|
||||
/** 创建者 */
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private String createBy;
|
||||
|
||||
/** 创建时间 */
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private Date createTime;
|
||||
|
||||
/** 更新者 */
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private String updateBy;
|
||||
|
||||
/** 更新时间 */
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private Date updateTime;
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
package com.ruoyi.ccdi.domain.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 中介人员黑名单新增 DTO
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-01-27
|
||||
*/
|
||||
public class CcdiIntermediaryBlacklistAddDTO implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 姓名/机构名称 */
|
||||
@NotBlank(message = "姓名/机构名称不能为空")
|
||||
@Size(min = 1, max = 100, message = "姓名/机构名称长度不能超过100个字符")
|
||||
private String name;
|
||||
|
||||
/** 证件号 */
|
||||
@Size(max = 50, message = "证件号长度不能超过50个字符")
|
||||
private String certificateNo;
|
||||
|
||||
/** 中介类型 */
|
||||
@NotBlank(message = "中介类型不能为空")
|
||||
private String intermediaryType;
|
||||
|
||||
/** 备注 */
|
||||
@Size(max = 500, message = "备注长度不能超过500个字符")
|
||||
private String remark;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getCertificateNo() {
|
||||
return certificateNo;
|
||||
}
|
||||
|
||||
public void setCertificateNo(String certificateNo) {
|
||||
this.certificateNo = certificateNo;
|
||||
}
|
||||
|
||||
public String getIntermediaryType() {
|
||||
return intermediaryType;
|
||||
}
|
||||
|
||||
public void setIntermediaryType(String intermediaryType) {
|
||||
this.intermediaryType = intermediaryType;
|
||||
}
|
||||
|
||||
public String getRemark() {
|
||||
return remark;
|
||||
}
|
||||
|
||||
public void setRemark(String remark) {
|
||||
this.remark = remark;
|
||||
}
|
||||
}
|
||||
@@ -1,386 +0,0 @@
|
||||
package com.ruoyi.ccdi.domain.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 中介人员黑名单编辑 DTO
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-01-27
|
||||
*/
|
||||
public class CcdiIntermediaryBlacklistEditDTO implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 中介ID */
|
||||
@NotNull(message = "中介ID不能为空")
|
||||
private Long intermediaryId;
|
||||
|
||||
/** 姓名/机构名称 */
|
||||
@NotBlank(message = "姓名/机构名称不能为空")
|
||||
@Size(min = 1, max = 100, message = "姓名/机构名称长度不能超过100个字符")
|
||||
private String name;
|
||||
|
||||
/** 证件号 */
|
||||
@Size(max = 50, message = "证件号长度不能超过50个字符")
|
||||
private String certificateNo;
|
||||
|
||||
/** 中介类型 */
|
||||
@NotBlank(message = "中介类型不能为空")
|
||||
private String intermediaryType;
|
||||
|
||||
/** 状态 */
|
||||
@NotBlank(message = "状态不能为空")
|
||||
private String status;
|
||||
|
||||
/** 备注 */
|
||||
@Size(max = 500, message = "备注长度不能超过500个字符")
|
||||
private String remark;
|
||||
|
||||
// ============================================================
|
||||
// 个人类型字段 (以 indiv_ 前缀标识,individual 缩写)
|
||||
// ============================================================
|
||||
/** 人员类型(中介、职业背债人、房产中介等) */
|
||||
private String indivType;
|
||||
|
||||
/** 人员子类型(本人、配偶等) */
|
||||
private String indivSubType;
|
||||
|
||||
/** 性别(M男 F女 O其他) */
|
||||
private String indivGender;
|
||||
|
||||
/** 证件类型 */
|
||||
private String indivCertType;
|
||||
|
||||
/** 手机号码(加密存储) */
|
||||
private String indivPhone;
|
||||
|
||||
/** 微信号 */
|
||||
private String indivWechat;
|
||||
|
||||
/** 联系地址 */
|
||||
private String indivAddress;
|
||||
|
||||
/** 所在公司 */
|
||||
private String indivCompany;
|
||||
|
||||
/** 职位/职务 */
|
||||
private String indivPosition;
|
||||
|
||||
/** 关联人员ID */
|
||||
private String indivRelatedId;
|
||||
|
||||
/** 关联关系 */
|
||||
private String indivRelation;
|
||||
|
||||
// ============================================================
|
||||
// 机构类型字段 (以 corp_ 前缀标识,corporation 缩写)
|
||||
// ============================================================
|
||||
/** 统一社会信用代码 */
|
||||
private String corpCreditCode;
|
||||
|
||||
/** 主体类型(有限责任公司、股份有限公司等) */
|
||||
private String corpType;
|
||||
|
||||
/** 企业性质(国企、民企、外企等) */
|
||||
private String corpNature;
|
||||
|
||||
/** 行业分类 */
|
||||
private String corpIndustryCategory;
|
||||
|
||||
/** 所属行业 */
|
||||
private String corpIndustry;
|
||||
|
||||
/** 成立日期 */
|
||||
private Date corpEstablishDate;
|
||||
|
||||
/** 注册地址 */
|
||||
private String corpAddress;
|
||||
|
||||
/** 法定代表人 */
|
||||
private String corpLegalRep;
|
||||
|
||||
/** 法定代表人证件类型 */
|
||||
private String corpLegalCertType;
|
||||
|
||||
/** 法定代表人证件号码 */
|
||||
private String corpLegalCertNo;
|
||||
|
||||
/** 股东1 */
|
||||
private String corpShareholder1;
|
||||
|
||||
/** 股东2 */
|
||||
private String corpShareholder2;
|
||||
|
||||
/** 股东3 */
|
||||
private String corpShareholder3;
|
||||
|
||||
/** 股东4 */
|
||||
private String corpShareholder4;
|
||||
|
||||
/** 股东5 */
|
||||
private String corpShareholder5;
|
||||
|
||||
public Long getIntermediaryId() {
|
||||
return intermediaryId;
|
||||
}
|
||||
|
||||
public void setIntermediaryId(Long intermediaryId) {
|
||||
this.intermediaryId = intermediaryId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getCertificateNo() {
|
||||
return certificateNo;
|
||||
}
|
||||
|
||||
public void setCertificateNo(String certificateNo) {
|
||||
this.certificateNo = certificateNo;
|
||||
}
|
||||
|
||||
public String getIntermediaryType() {
|
||||
return intermediaryType;
|
||||
}
|
||||
|
||||
public void setIntermediaryType(String intermediaryType) {
|
||||
this.intermediaryType = intermediaryType;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getRemark() {
|
||||
return remark;
|
||||
}
|
||||
|
||||
public void setRemark(String remark) {
|
||||
this.remark = remark;
|
||||
}
|
||||
|
||||
public String getIndivType() {
|
||||
return indivType;
|
||||
}
|
||||
|
||||
public void setIndivType(String indivType) {
|
||||
this.indivType = indivType;
|
||||
}
|
||||
|
||||
public String getIndivSubType() {
|
||||
return indivSubType;
|
||||
}
|
||||
|
||||
public void setIndivSubType(String indivSubType) {
|
||||
this.indivSubType = indivSubType;
|
||||
}
|
||||
|
||||
public String getIndivGender() {
|
||||
return indivGender;
|
||||
}
|
||||
|
||||
public void setIndivGender(String indivGender) {
|
||||
this.indivGender = indivGender;
|
||||
}
|
||||
|
||||
public String getIndivCertType() {
|
||||
return indivCertType;
|
||||
}
|
||||
|
||||
public void setIndivCertType(String indivCertType) {
|
||||
this.indivCertType = indivCertType;
|
||||
}
|
||||
|
||||
public String getIndivPhone() {
|
||||
return indivPhone;
|
||||
}
|
||||
|
||||
public void setIndivPhone(String indivPhone) {
|
||||
this.indivPhone = indivPhone;
|
||||
}
|
||||
|
||||
public String getIndivWechat() {
|
||||
return indivWechat;
|
||||
}
|
||||
|
||||
public void setIndivWechat(String indivWechat) {
|
||||
this.indivWechat = indivWechat;
|
||||
}
|
||||
|
||||
public String getIndivAddress() {
|
||||
return indivAddress;
|
||||
}
|
||||
|
||||
public void setIndivAddress(String indivAddress) {
|
||||
this.indivAddress = indivAddress;
|
||||
}
|
||||
|
||||
public String getIndivCompany() {
|
||||
return indivCompany;
|
||||
}
|
||||
|
||||
public void setIndivCompany(String indivCompany) {
|
||||
this.indivCompany = indivCompany;
|
||||
}
|
||||
|
||||
public String getIndivPosition() {
|
||||
return indivPosition;
|
||||
}
|
||||
|
||||
public void setIndivPosition(String indivPosition) {
|
||||
this.indivPosition = indivPosition;
|
||||
}
|
||||
|
||||
public String getIndivRelatedId() {
|
||||
return indivRelatedId;
|
||||
}
|
||||
|
||||
public void setIndivRelatedId(String indivRelatedId) {
|
||||
this.indivRelatedId = indivRelatedId;
|
||||
}
|
||||
|
||||
public String getIndivRelation() {
|
||||
return indivRelation;
|
||||
}
|
||||
|
||||
public void setIndivRelation(String indivRelation) {
|
||||
this.indivRelation = indivRelation;
|
||||
}
|
||||
|
||||
public String getCorpCreditCode() {
|
||||
return corpCreditCode;
|
||||
}
|
||||
|
||||
public void setCorpCreditCode(String corpCreditCode) {
|
||||
this.corpCreditCode = corpCreditCode;
|
||||
}
|
||||
|
||||
public String getCorpType() {
|
||||
return corpType;
|
||||
}
|
||||
|
||||
public void setCorpType(String corpType) {
|
||||
this.corpType = corpType;
|
||||
}
|
||||
|
||||
public String getCorpNature() {
|
||||
return corpNature;
|
||||
}
|
||||
|
||||
public void setCorpNature(String corpNature) {
|
||||
this.corpNature = corpNature;
|
||||
}
|
||||
|
||||
public String getCorpIndustryCategory() {
|
||||
return corpIndustryCategory;
|
||||
}
|
||||
|
||||
public void setCorpIndustryCategory(String corpIndustryCategory) {
|
||||
this.corpIndustryCategory = corpIndustryCategory;
|
||||
}
|
||||
|
||||
public String getCorpIndustry() {
|
||||
return corpIndustry;
|
||||
}
|
||||
|
||||
public void setCorpIndustry(String corpIndustry) {
|
||||
this.corpIndustry = corpIndustry;
|
||||
}
|
||||
|
||||
public Date getCorpEstablishDate() {
|
||||
return corpEstablishDate;
|
||||
}
|
||||
|
||||
public void setCorpEstablishDate(Date corpEstablishDate) {
|
||||
this.corpEstablishDate = corpEstablishDate;
|
||||
}
|
||||
|
||||
public String getCorpAddress() {
|
||||
return corpAddress;
|
||||
}
|
||||
|
||||
public void setCorpAddress(String corpAddress) {
|
||||
this.corpAddress = corpAddress;
|
||||
}
|
||||
|
||||
public String getCorpLegalRep() {
|
||||
return corpLegalRep;
|
||||
}
|
||||
|
||||
public void setCorpLegalRep(String corpLegalRep) {
|
||||
this.corpLegalRep = corpLegalRep;
|
||||
}
|
||||
|
||||
public String getCorpLegalCertType() {
|
||||
return corpLegalCertType;
|
||||
}
|
||||
|
||||
public void setCorpLegalCertType(String corpLegalCertType) {
|
||||
this.corpLegalCertType = corpLegalCertType;
|
||||
}
|
||||
|
||||
public String getCorpLegalCertNo() {
|
||||
return corpLegalCertNo;
|
||||
}
|
||||
|
||||
public void setCorpLegalCertNo(String corpLegalCertNo) {
|
||||
this.corpLegalCertNo = corpLegalCertNo;
|
||||
}
|
||||
|
||||
public String getCorpShareholder1() {
|
||||
return corpShareholder1;
|
||||
}
|
||||
|
||||
public void setCorpShareholder1(String corpShareholder1) {
|
||||
this.corpShareholder1 = corpShareholder1;
|
||||
}
|
||||
|
||||
public String getCorpShareholder2() {
|
||||
return corpShareholder2;
|
||||
}
|
||||
|
||||
public void setCorpShareholder2(String corpShareholder2) {
|
||||
this.corpShareholder2 = corpShareholder2;
|
||||
}
|
||||
|
||||
public String getCorpShareholder3() {
|
||||
return corpShareholder3;
|
||||
}
|
||||
|
||||
public void setCorpShareholder3(String corpShareholder3) {
|
||||
this.corpShareholder3 = corpShareholder3;
|
||||
}
|
||||
|
||||
public String getCorpShareholder4() {
|
||||
return corpShareholder4;
|
||||
}
|
||||
|
||||
public void setCorpShareholder4(String corpShareholder4) {
|
||||
this.corpShareholder4 = corpShareholder4;
|
||||
}
|
||||
|
||||
public String getCorpShareholder5() {
|
||||
return corpShareholder5;
|
||||
}
|
||||
|
||||
public void setCorpShareholder5(String corpShareholder5) {
|
||||
this.corpShareholder5 = corpShareholder5;
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
package com.ruoyi.ccdi.domain.dto;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 中介人员黑名单查询 DTO
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-01-27
|
||||
*/
|
||||
public class CcdiIntermediaryBlacklistQueryDTO implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 姓名/机构名称(模糊查询) */
|
||||
private String name;
|
||||
|
||||
/** 证件号(精确查询) */
|
||||
private String certificateNo;
|
||||
|
||||
/** 中介类型 */
|
||||
private String intermediaryType;
|
||||
|
||||
/** 状态 */
|
||||
private String status;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getCertificateNo() {
|
||||
return certificateNo;
|
||||
}
|
||||
|
||||
public void setCertificateNo(String certificateNo) {
|
||||
this.certificateNo = certificateNo;
|
||||
}
|
||||
|
||||
public String getIntermediaryType() {
|
||||
return intermediaryType;
|
||||
}
|
||||
|
||||
public void setIntermediaryType(String intermediaryType) {
|
||||
this.intermediaryType = intermediaryType;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
package com.ruoyi.ccdi.domain.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 机构中介新增 DTO
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-01-29
|
||||
*/
|
||||
@Data
|
||||
public class CcdiIntermediaryEntityAddDTO implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 机构名称 */
|
||||
@NotBlank(message = "机构名称不能为空")
|
||||
@Size(min = 1, max = 100, message = "机构名称长度不能超过100个字符")
|
||||
private String name;
|
||||
|
||||
/** 统一社会信用代码 */
|
||||
@NotBlank(message = "统一社会信用代码不能为空")
|
||||
@Size(max = 18, message = "统一社会信用代码长度不能超过18个字符")
|
||||
private String corpCreditCode;
|
||||
|
||||
/** 主体类型 */
|
||||
@Size(max = 50, message = "主体类型长度不能超过50个字符")
|
||||
private String corpType;
|
||||
|
||||
/** 企业性质 */
|
||||
@Size(max = 50, message = "企业性质长度不能超过50个字符")
|
||||
private String corpNature;
|
||||
|
||||
/** 行业分类 */
|
||||
@Size(max = 100, message = "行业分类长度不能超过100个字符")
|
||||
private String corpIndustryCategory;
|
||||
|
||||
/** 所属行业 */
|
||||
@Size(max = 100, message = "所属行业长度不能超过100个字符")
|
||||
private String corpIndustry;
|
||||
|
||||
/** 成立日期 */
|
||||
private Date corpEstablishDate;
|
||||
|
||||
/** 注册地址 */
|
||||
@Size(max = 500, message = "注册地址长度不能超过500个字符")
|
||||
private String corpAddress;
|
||||
|
||||
/** 法定代表人 */
|
||||
@Size(max = 50, message = "法定代表人长度不能超过50个字符")
|
||||
private String corpLegalRep;
|
||||
|
||||
/** 法定代表人证件类型 */
|
||||
@Size(max = 30, message = "法定代表人证件类型长度不能超过30个字符")
|
||||
private String corpLegalCertType;
|
||||
|
||||
/** 法定代表人证件号码 */
|
||||
@Size(max = 30, message = "法定代表人证件号码长度不能超过30个字符")
|
||||
private String corpLegalCertNo;
|
||||
|
||||
/** 股东1 */
|
||||
@Size(max = 30, message = "股东1长度不能超过30个字符")
|
||||
private String corpShareholder1;
|
||||
|
||||
/** 股东2 */
|
||||
@Size(max = 30, message = "股东2长度不能超过30个字符")
|
||||
private String corpShareholder2;
|
||||
|
||||
/** 股东3 */
|
||||
@Size(max = 30, message = "股东3长度不能超过30个字符")
|
||||
private String corpShareholder3;
|
||||
|
||||
/** 股东4 */
|
||||
@Size(max = 30, message = "股东4长度不能超过30个字符")
|
||||
private String corpShareholder4;
|
||||
|
||||
/** 股东5 */
|
||||
@Size(max = 30, message = "股东5长度不能超过30个字符")
|
||||
private String corpShareholder5;
|
||||
|
||||
/** 状态 */
|
||||
@NotBlank(message = "状态不能为空")
|
||||
private String status;
|
||||
|
||||
/** 备注 */
|
||||
@Size(max = 500, message = "备注长度不能超过500个字符")
|
||||
private String remark;
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
package com.ruoyi.ccdi.domain.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 机构中介编辑 DTO
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-01-29
|
||||
*/
|
||||
@Data
|
||||
public class CcdiIntermediaryEntityEditDTO implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 中介ID */
|
||||
@NotNull(message = "中介ID不能为空")
|
||||
private Long intermediaryId;
|
||||
|
||||
/** 机构名称 */
|
||||
@NotBlank(message = "机构名称不能为空")
|
||||
@Size(min = 1, max = 100, message = "机构名称长度不能超过100个字符")
|
||||
private String name;
|
||||
|
||||
/** 证件号(统一社会信用代码) */
|
||||
@Size(max = 50, message = "证件号长度不能超过50个字符")
|
||||
private String certificateNo;
|
||||
|
||||
/** 统一社会信用代码 */
|
||||
private String corpCreditCode;
|
||||
|
||||
/** 主体类型(有限责任公司、股份有限公司等) */
|
||||
private String corpType;
|
||||
|
||||
/** 企业性质(国企、民企、外企等) */
|
||||
private String corpNature;
|
||||
|
||||
/** 行业分类 */
|
||||
private String corpIndustryCategory;
|
||||
|
||||
/** 所属行业 */
|
||||
private String corpIndustry;
|
||||
|
||||
/** 成立日期 */
|
||||
private Date corpEstablishDate;
|
||||
|
||||
/** 注册地址 */
|
||||
private String corpAddress;
|
||||
|
||||
/** 法定代表人 */
|
||||
private String corpLegalRep;
|
||||
|
||||
/** 法定代表人证件类型 */
|
||||
private String corpLegalCertType;
|
||||
|
||||
/** 法定代表人证件号码 */
|
||||
private String corpLegalCertNo;
|
||||
|
||||
/** 股东1 */
|
||||
private String corpShareholder1;
|
||||
|
||||
/** 股东2 */
|
||||
private String corpShareholder2;
|
||||
|
||||
/** 股东3 */
|
||||
private String corpShareholder3;
|
||||
|
||||
/** 股东4 */
|
||||
private String corpShareholder4;
|
||||
|
||||
/** 股东5 */
|
||||
private String corpShareholder5;
|
||||
|
||||
/** 状态 */
|
||||
@NotBlank(message = "状态不能为空")
|
||||
private String status;
|
||||
|
||||
/** 备注 */
|
||||
@Size(max = 500, message = "备注长度不能超过500个字符")
|
||||
private String remark;
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
package com.ruoyi.ccdi.domain.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 个人中介新增 DTO
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-01-29
|
||||
*/
|
||||
@Data
|
||||
public class CcdiIntermediaryPersonAddDTO implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 姓名 */
|
||||
@NotBlank(message = "姓名不能为空")
|
||||
@Size(min = 1, max = 100, message = "姓名长度不能超过100个字符")
|
||||
private String name;
|
||||
|
||||
/** 证件号 */
|
||||
@NotBlank(message = "证件号不能为空")
|
||||
@Size(max = 50, message = "证件号长度不能超过50个字符")
|
||||
private String certificateNo;
|
||||
|
||||
/** 人员类型(中介、职业背债人、房产中介等) */
|
||||
@Size(max = 30, message = "人员类型长度不能超过30个字符")
|
||||
private String indivType;
|
||||
|
||||
/** 人员子类型(本人、配偶等) */
|
||||
@Size(max = 50, message = "人员子类型长度不能超过50个字符")
|
||||
private String indivSubType;
|
||||
|
||||
/** 性别(M男 F女 O其他) */
|
||||
@Size(max = 1, message = "性别长度不能超过1个字符")
|
||||
private String indivGender;
|
||||
|
||||
/** 证件类型 */
|
||||
@Size(max = 30, message = "证件类型长度不能超过30个字符")
|
||||
private String indivCertType;
|
||||
|
||||
/** 手机号码(加密存储) */
|
||||
@Size(max = 20, message = "手机号码长度不能超过20个字符")
|
||||
private String indivPhone;
|
||||
|
||||
/** 微信号 */
|
||||
@Size(max = 50, message = "微信号长度不能超过50个字符")
|
||||
private String indivWechat;
|
||||
|
||||
/** 联系地址 */
|
||||
@Size(max = 200, message = "联系地址长度不能超过200个字符")
|
||||
private String indivAddress;
|
||||
|
||||
/** 所在公司 */
|
||||
@Size(max = 100, message = "所在公司长度不能超过100个字符")
|
||||
private String indivCompany;
|
||||
|
||||
/** 职位/职务 */
|
||||
@Size(max = 100, message = "职位长度不能超过100个字符")
|
||||
private String indivPosition;
|
||||
|
||||
/** 关联人员ID */
|
||||
@Size(max = 20, message = "关联人员ID长度不能超过20个字符")
|
||||
private String indivRelatedId;
|
||||
|
||||
/** 关联关系 */
|
||||
@Size(max = 50, message = "关联关系长度不能超过50个字符")
|
||||
private String indivRelation;
|
||||
|
||||
/** 状态 */
|
||||
@NotBlank(message = "状态不能为空")
|
||||
private String status;
|
||||
|
||||
/** 备注 */
|
||||
@Size(max = 500, message = "备注长度不能超过500个字符")
|
||||
private String remark;
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
package com.ruoyi.ccdi.domain.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 个人中介编辑 DTO
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-01-29
|
||||
*/
|
||||
@Data
|
||||
public class CcdiIntermediaryPersonEditDTO implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 中介ID */
|
||||
@NotNull(message = "中介ID不能为空")
|
||||
private Long intermediaryId;
|
||||
|
||||
/** 姓名 */
|
||||
@NotBlank(message = "姓名不能为空")
|
||||
@Size(min = 1, max = 100, message = "姓名长度不能超过100个字符")
|
||||
private String name;
|
||||
|
||||
/** 证件号 */
|
||||
@Size(max = 50, message = "证件号长度不能超过50个字符")
|
||||
private String certificateNo;
|
||||
|
||||
/** 人员类型(中介、职业背债人、房产中介等) */
|
||||
private String indivType;
|
||||
|
||||
/** 人员子类型(本人、配偶等) */
|
||||
private String indivSubType;
|
||||
|
||||
/** 性别(M男 F女 O其他) */
|
||||
private String indivGender;
|
||||
|
||||
/** 证件类型 */
|
||||
private String indivCertType;
|
||||
|
||||
/** 手机号码(加密存储) */
|
||||
private String indivPhone;
|
||||
|
||||
/** 微信号 */
|
||||
private String indivWechat;
|
||||
|
||||
/** 联系地址 */
|
||||
private String indivAddress;
|
||||
|
||||
/** 所在公司 */
|
||||
private String indivCompany;
|
||||
|
||||
/** 职位/职务 */
|
||||
private String indivPosition;
|
||||
|
||||
/** 关联人员ID */
|
||||
private String indivRelatedId;
|
||||
|
||||
/** 关联关系 */
|
||||
private String indivRelation;
|
||||
|
||||
/** 状态 */
|
||||
@NotBlank(message = "状态不能为空")
|
||||
private String status;
|
||||
|
||||
/** 备注 */
|
||||
@Size(max = 500, message = "备注长度不能超过500个字符")
|
||||
private String remark;
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
package com.ruoyi.ccdi.domain.excel;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import com.alibaba.excel.annotation.write.style.ColumnWidth;
|
||||
import com.ruoyi.ccdi.utils.converter.IntermediaryStatusConverter;
|
||||
import com.ruoyi.ccdi.utils.converter.IntermediaryTypeConverter;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 中介人员黑名单Excel导入导出对象
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-01-27
|
||||
*/
|
||||
@Data
|
||||
public class CcdiIntermediaryBlacklistExcel implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 姓名/机构名称 */
|
||||
@ExcelProperty(value = "姓名/机构名称", index = 0)
|
||||
@ColumnWidth(20)
|
||||
private String name;
|
||||
|
||||
/** 证件号 */
|
||||
@ExcelProperty(value = "证件号", index = 1)
|
||||
@ColumnWidth(20)
|
||||
private String certificateNo;
|
||||
|
||||
/** 中介类型 */
|
||||
@ExcelProperty(value = "中介类型", converter = IntermediaryTypeConverter.class, index = 2)
|
||||
@ColumnWidth(15)
|
||||
private String intermediaryType;
|
||||
|
||||
/** 状态 */
|
||||
@ExcelProperty(value = "状态", converter = IntermediaryStatusConverter.class, index = 3)
|
||||
@ColumnWidth(10)
|
||||
private String status;
|
||||
|
||||
/** 备注 */
|
||||
@ExcelProperty(value = "备注", index = 4)
|
||||
@ColumnWidth(30)
|
||||
private String remark;
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
package com.ruoyi.ccdi.domain.excel;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import com.alibaba.excel.annotation.write.style.ColumnWidth;
|
||||
import com.ruoyi.common.annotation.DictDropdown;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 机构中介黑名单Excel导入对象
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-01-29
|
||||
*/
|
||||
@Data
|
||||
public class CcdiIntermediaryEntityExcel implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ExcelProperty(value = "机构名称", index = 0)
|
||||
@ColumnWidth(25)
|
||||
private String name;
|
||||
|
||||
@ExcelProperty(value = "统一社会信用代码", index = 1)
|
||||
@ColumnWidth(20)
|
||||
private String corpCreditCode;
|
||||
|
||||
@ExcelProperty(value = "主体类型", index = 2)
|
||||
@ColumnWidth(20)
|
||||
@DictDropdown(dictType = "dpc_entity_type")
|
||||
private String corpType;
|
||||
|
||||
@ExcelProperty(value = "企业性质", index = 3)
|
||||
@ColumnWidth(15)
|
||||
@DictDropdown(dictType = "dpc_enterprise_nature")
|
||||
private String corpNature;
|
||||
|
||||
@ExcelProperty(value = "行业分类", index = 4)
|
||||
@ColumnWidth(15)
|
||||
private String corpIndustryCategory;
|
||||
|
||||
@ExcelProperty(value = "所属行业", index = 5)
|
||||
@ColumnWidth(15)
|
||||
private String corpIndustry;
|
||||
|
||||
@ExcelProperty(value = "成立日期", index = 6)
|
||||
@ColumnWidth(15)
|
||||
private String corpEstablishDate;
|
||||
|
||||
@ExcelProperty(value = "注册地址", index = 7)
|
||||
@ColumnWidth(40)
|
||||
private String corpAddress;
|
||||
|
||||
@ExcelProperty(value = "法定代表人", index = 8)
|
||||
@ColumnWidth(15)
|
||||
private String corpLegalRep;
|
||||
|
||||
@ExcelProperty(value = "法定代表人证件类型", index = 9)
|
||||
@ColumnWidth(20)
|
||||
private String corpLegalCertType;
|
||||
|
||||
@ExcelProperty(value = "法定代表人证件号码", index = 10)
|
||||
@ColumnWidth(20)
|
||||
private String corpLegalCertNo;
|
||||
|
||||
@ExcelProperty(value = "股东1", index = 11)
|
||||
@ColumnWidth(15)
|
||||
private String corpShareholder1;
|
||||
|
||||
@ExcelProperty(value = "股东2", index = 12)
|
||||
@ColumnWidth(15)
|
||||
private String corpShareholder2;
|
||||
|
||||
@ExcelProperty(value = "股东3", index = 13)
|
||||
@ColumnWidth(15)
|
||||
private String corpShareholder3;
|
||||
|
||||
@ExcelProperty(value = "股东4", index = 14)
|
||||
@ColumnWidth(15)
|
||||
private String corpShareholder4;
|
||||
|
||||
@ExcelProperty(value = "股东5", index = 15)
|
||||
@ColumnWidth(15)
|
||||
private String corpShareholder5;
|
||||
|
||||
@ExcelProperty(value = "备注", index = 16)
|
||||
@ColumnWidth(30)
|
||||
private String remark;
|
||||
|
||||
// 以下字段不在 Excel 中显示,由系统自动设置
|
||||
// private String status; // 默认:正常(0)
|
||||
// private String dataSource; // 默认:批量导入(IMPORT)
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
package com.ruoyi.ccdi.domain.excel;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import com.alibaba.excel.annotation.write.style.ColumnWidth;
|
||||
import com.ruoyi.common.annotation.DictDropdown;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 个人中介黑名单Excel导入对象
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-01-29
|
||||
*/
|
||||
@Data
|
||||
public class CcdiIntermediaryPersonExcel implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ExcelProperty(value = "姓名", index = 0)
|
||||
@ColumnWidth(15)
|
||||
private String name;
|
||||
|
||||
@ExcelProperty(value = "人员类型", index = 1)
|
||||
@ColumnWidth(15)
|
||||
private String indivType;
|
||||
|
||||
@ExcelProperty(value = "人员子类型", index = 2)
|
||||
@ColumnWidth(15)
|
||||
private String indivSubType;
|
||||
|
||||
@ExcelProperty(value = "性别", index = 3)
|
||||
@ColumnWidth(10)
|
||||
@DictDropdown(dictType = "dpc_indiv_gender")
|
||||
private String indivGender;
|
||||
|
||||
@ExcelProperty(value = "证件类型", index = 4)
|
||||
@ColumnWidth(15)
|
||||
@DictDropdown(dictType = "dpc_certificate_type")
|
||||
private String indivCertType;
|
||||
|
||||
@ExcelProperty(value = "证件号码", index = 5)
|
||||
@ColumnWidth(20)
|
||||
private String certificateNo;
|
||||
|
||||
@ExcelProperty(value = "手机号码", index = 6)
|
||||
@ColumnWidth(15)
|
||||
private String indivPhone;
|
||||
|
||||
@ExcelProperty(value = "微信号", index = 7)
|
||||
@ColumnWidth(15)
|
||||
private String indivWechat;
|
||||
|
||||
@ExcelProperty(value = "联系地址", index = 8)
|
||||
@ColumnWidth(30)
|
||||
private String indivAddress;
|
||||
|
||||
@ExcelProperty(value = "所在公司", index = 9)
|
||||
@ColumnWidth(20)
|
||||
private String indivCompany;
|
||||
|
||||
@ExcelProperty(value = "职位", index = 10)
|
||||
@ColumnWidth(15)
|
||||
private String indivPosition;
|
||||
|
||||
@ExcelProperty(value = "关联人员ID", index = 11)
|
||||
@ColumnWidth(15)
|
||||
private String indivRelatedId;
|
||||
|
||||
@ExcelProperty(value = "关联关系", index = 12)
|
||||
@ColumnWidth(15)
|
||||
private String indivRelation;
|
||||
|
||||
@ExcelProperty(value = "备注", index = 13)
|
||||
@ColumnWidth(30)
|
||||
private String remark;
|
||||
|
||||
// 以下字段不在 Excel 中显示,由系统自动设置
|
||||
// private String status; // 默认:正常(0)
|
||||
// private String dataSource; // 默认:批量导入(IMPORT)
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
package com.ruoyi.ccdi.domain.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 中介人员黑名单视图对象 VO
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-01-27
|
||||
*/
|
||||
@Data
|
||||
public class CcdiIntermediaryBlacklistVO implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 中介ID */
|
||||
private Long intermediaryId;
|
||||
|
||||
/** 姓名/机构名称 */
|
||||
private String name;
|
||||
|
||||
/** 证件号 */
|
||||
private String certificateNo;
|
||||
|
||||
/** 中介类型 */
|
||||
private String intermediaryType;
|
||||
|
||||
/** 中介类型名称(用于前端显示) */
|
||||
private String intermediaryTypeName;
|
||||
|
||||
/** 状态 */
|
||||
private String status;
|
||||
|
||||
/** 状态名称(用于前端显示) */
|
||||
private String statusName;
|
||||
|
||||
/** 备注 */
|
||||
private String remark;
|
||||
|
||||
/** 创建者 */
|
||||
private String createBy;
|
||||
|
||||
/** 创建时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date createTime;
|
||||
|
||||
/** 更新者 */
|
||||
private String updateBy;
|
||||
|
||||
/** 更新时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date updateTime;
|
||||
}
|
||||
@@ -1,126 +0,0 @@
|
||||
package com.ruoyi.ccdi.domain.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 机构中介黑名单详情 VO
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-01-29
|
||||
*/
|
||||
@Data
|
||||
public class CcdiIntermediaryEntityDetailVO implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
// ============================================================
|
||||
// 核心字段
|
||||
// ============================================================
|
||||
/** 中介ID */
|
||||
private Long intermediaryId;
|
||||
|
||||
/** 机构名称 */
|
||||
private String name;
|
||||
|
||||
/** 证件号码 */
|
||||
private String certificateNo;
|
||||
|
||||
/** 中介类型 */
|
||||
private String intermediaryType;
|
||||
|
||||
/** 中介类型名称 */
|
||||
private String intermediaryTypeName;
|
||||
|
||||
/** 状态 */
|
||||
private String status;
|
||||
|
||||
/** 状态名称 */
|
||||
private String statusName;
|
||||
|
||||
/** 备注 */
|
||||
private String remark;
|
||||
|
||||
/** 数据来源 */
|
||||
private String dataSource;
|
||||
|
||||
/** 数据来源名称 */
|
||||
private String dataSourceName;
|
||||
|
||||
// ============================================================
|
||||
// 机构专属字段
|
||||
// ============================================================
|
||||
/** 统一社会信用代码 */
|
||||
private String corpCreditCode;
|
||||
|
||||
/** 主体类型 */
|
||||
private String corpType;
|
||||
|
||||
/** 主体类型名称 */
|
||||
private String corpTypeName;
|
||||
|
||||
/** 企业性质 */
|
||||
private String corpNature;
|
||||
|
||||
/** 企业性质名称 */
|
||||
private String corpNatureName;
|
||||
|
||||
/** 行业分类 */
|
||||
private String corpIndustryCategory;
|
||||
|
||||
/** 所属行业 */
|
||||
private String corpIndustry;
|
||||
|
||||
/** 成立日期 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private Date corpEstablishDate;
|
||||
|
||||
/** 注册地址 */
|
||||
private String corpAddress;
|
||||
|
||||
/** 法定代表人 */
|
||||
private String corpLegalRep;
|
||||
|
||||
/** 法定代表人证件类型 */
|
||||
private String corpLegalCertType;
|
||||
|
||||
/** 法定代表人证件号码 */
|
||||
private String corpLegalCertNo;
|
||||
|
||||
/** 股东1 */
|
||||
private String corpShareholder1;
|
||||
|
||||
/** 股东2 */
|
||||
private String corpShareholder2;
|
||||
|
||||
/** 股东3 */
|
||||
private String corpShareholder3;
|
||||
|
||||
/** 股东4 */
|
||||
private String corpShareholder4;
|
||||
|
||||
/** 股东5 */
|
||||
private String corpShareholder5;
|
||||
|
||||
// ============================================================
|
||||
// 审计字段
|
||||
// ============================================================
|
||||
/** 创建者 */
|
||||
private String createBy;
|
||||
|
||||
/** 创建时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date createTime;
|
||||
|
||||
/** 更新者 */
|
||||
private String updateBy;
|
||||
|
||||
/** 更新时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date updateTime;
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
package com.ruoyi.ccdi.domain.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 个人中介黑名单详情 VO
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-01-29
|
||||
*/
|
||||
@Data
|
||||
public class CcdiIntermediaryPersonDetailVO implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
// ============================================================
|
||||
// 核心字段
|
||||
// ============================================================
|
||||
/** 中介ID */
|
||||
private Long intermediaryId;
|
||||
|
||||
/** 姓名 */
|
||||
private String name;
|
||||
|
||||
/** 证件号码 */
|
||||
private String certificateNo;
|
||||
|
||||
/** 中介类型 */
|
||||
private String intermediaryType;
|
||||
|
||||
/** 中介类型名称 */
|
||||
private String intermediaryTypeName;
|
||||
|
||||
/** 状态 */
|
||||
private String status;
|
||||
|
||||
/** 状态名称 */
|
||||
private String statusName;
|
||||
|
||||
/** 备注 */
|
||||
private String remark;
|
||||
|
||||
/** 数据来源 */
|
||||
private String dataSource;
|
||||
|
||||
/** 数据来源名称 */
|
||||
private String dataSourceName;
|
||||
|
||||
// ============================================================
|
||||
// 个人专属字段
|
||||
// ============================================================
|
||||
/** 人员类型 */
|
||||
private String indivType;
|
||||
|
||||
/** 人员子类型 */
|
||||
private String indivSubType;
|
||||
|
||||
/** 性别 */
|
||||
private String indivGender;
|
||||
|
||||
/** 性别名称 */
|
||||
private String indivGenderName;
|
||||
|
||||
/** 证件类型 */
|
||||
private String indivCertType;
|
||||
|
||||
/** 证件类型名称 */
|
||||
private String indivCertTypeName;
|
||||
|
||||
/** 手机号码 */
|
||||
private String indivPhone;
|
||||
|
||||
/** 微信号 */
|
||||
private String indivWechat;
|
||||
|
||||
/** 联系地址 */
|
||||
private String indivAddress;
|
||||
|
||||
/** 所在公司 */
|
||||
private String indivCompany;
|
||||
|
||||
/** 职位/职务 */
|
||||
private String indivPosition;
|
||||
|
||||
/** 关联人员ID */
|
||||
private String indivRelatedId;
|
||||
|
||||
/** 关联关系 */
|
||||
private String indivRelation;
|
||||
|
||||
// ============================================================
|
||||
// 审计字段
|
||||
// ============================================================
|
||||
/** 创建者 */
|
||||
private String createBy;
|
||||
|
||||
/** 创建时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date createTime;
|
||||
|
||||
/** 更新者 */
|
||||
private String updateBy;
|
||||
|
||||
/** 更新时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date updateTime;
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package com.ruoyi.ccdi.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.ruoyi.ccdi.domain.CcdiIntermediaryBlacklist;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 中介人员黑名单 数据层
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-01-27
|
||||
*/
|
||||
public interface CcdiIntermediaryBlacklistMapper extends BaseMapper<CcdiIntermediaryBlacklist> {
|
||||
|
||||
/**
|
||||
* 批量插入中介黑名单数据
|
||||
*
|
||||
* @param list 中介黑名单列表
|
||||
* @return 插入行数
|
||||
*/
|
||||
int batchInsert(@Param("list") List<CcdiIntermediaryBlacklist> list);
|
||||
|
||||
/**
|
||||
* 批量更新中介黑名单数据
|
||||
*
|
||||
* @param list 中介黑名单列表
|
||||
* @return 更新行数
|
||||
*/
|
||||
int batchUpdate(@Param("list") List<CcdiIntermediaryBlacklist> list);
|
||||
}
|
||||
@@ -1,148 +0,0 @@
|
||||
package com.ruoyi.ccdi.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.ruoyi.ccdi.domain.CcdiIntermediaryBlacklist;
|
||||
import com.ruoyi.ccdi.domain.dto.*;
|
||||
import com.ruoyi.ccdi.domain.excel.CcdiIntermediaryBlacklistExcel;
|
||||
import com.ruoyi.ccdi.domain.excel.CcdiIntermediaryEntityExcel;
|
||||
import com.ruoyi.ccdi.domain.excel.CcdiIntermediaryPersonExcel;
|
||||
import com.ruoyi.ccdi.domain.vo.CcdiIntermediaryBlacklistVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 中介人员黑名单 服务层
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-01-27
|
||||
*/
|
||||
public interface ICcdiIntermediaryBlacklistService {
|
||||
|
||||
/**
|
||||
* 查询中介黑名单列表
|
||||
*
|
||||
* @param queryDTO 查询条件
|
||||
* @return 中介黑名单集合
|
||||
*/
|
||||
List<CcdiIntermediaryBlacklistVO> selectIntermediaryList(CcdiIntermediaryBlacklistQueryDTO queryDTO);
|
||||
|
||||
/**
|
||||
* 分页查询中介黑名单列表
|
||||
*
|
||||
* @param page 分页对象
|
||||
* @param queryDTO 查询条件
|
||||
* @return 中介黑名单VO分页结果
|
||||
*/
|
||||
Page<CcdiIntermediaryBlacklistVO> selectIntermediaryPage(Page<CcdiIntermediaryBlacklist> page, CcdiIntermediaryBlacklistQueryDTO queryDTO);
|
||||
|
||||
/**
|
||||
* 查询中介黑名单列表(用于导出)
|
||||
*
|
||||
* @param queryDTO 查询条件
|
||||
* @return 中介黑名单Excel实体集合
|
||||
*/
|
||||
List<CcdiIntermediaryBlacklistExcel> selectIntermediaryListForExport(CcdiIntermediaryBlacklistQueryDTO queryDTO);
|
||||
|
||||
/**
|
||||
* 查询中介黑名单详细
|
||||
*
|
||||
* @param intermediaryId 中介ID
|
||||
* @return 中介黑名单VO
|
||||
*/
|
||||
CcdiIntermediaryBlacklistVO selectIntermediaryById(Long intermediaryId);
|
||||
|
||||
/**
|
||||
* 新增中介黑名单(通用接口,不推荐使用)
|
||||
*
|
||||
* @param addDTO 新增DTO
|
||||
* @return 结果
|
||||
* @deprecated 请使用 insertPersonIntermediary 或 insertEntityIntermediary 代替
|
||||
*/
|
||||
@Deprecated
|
||||
int insertIntermediary(CcdiIntermediaryBlacklistAddDTO addDTO);
|
||||
|
||||
/**
|
||||
* 新增个人中介黑名单
|
||||
*
|
||||
* @param addDTO 个人中介新增DTO
|
||||
* @return 结果
|
||||
*/
|
||||
int insertPersonIntermediary(CcdiIntermediaryPersonAddDTO addDTO);
|
||||
|
||||
/**
|
||||
* 新增机构中介黑名单
|
||||
*
|
||||
* @param addDTO 机构中介新增DTO
|
||||
* @return 结果
|
||||
*/
|
||||
int insertEntityIntermediary(CcdiIntermediaryEntityAddDTO addDTO);
|
||||
|
||||
/**
|
||||
* 修改中介黑名单(通用接口,不推荐使用)
|
||||
*
|
||||
* @param editDTO 编辑DTO
|
||||
* @return 结果
|
||||
* @deprecated 请使用 updatePersonIntermediary 或 updateEntityIntermediary 代替
|
||||
*/
|
||||
@Deprecated
|
||||
int updateIntermediary(CcdiIntermediaryBlacklistEditDTO editDTO);
|
||||
|
||||
/**
|
||||
* 修改个人中介黑名单
|
||||
*
|
||||
* @param editDTO 个人中介编辑DTO
|
||||
* @return 结果
|
||||
*/
|
||||
int updatePersonIntermediary(CcdiIntermediaryPersonEditDTO editDTO);
|
||||
|
||||
/**
|
||||
* 修改机构中介黑名单
|
||||
*
|
||||
* @param editDTO 机构中介编辑DTO
|
||||
* @return 结果
|
||||
*/
|
||||
int updateEntityIntermediary(CcdiIntermediaryEntityEditDTO editDTO);
|
||||
|
||||
/**
|
||||
* 批量删除中介黑名单
|
||||
*
|
||||
* @param intermediaryIds 需要删除的中介ID
|
||||
* @return 结果
|
||||
*/
|
||||
int deleteIntermediaryByIds(Long[] intermediaryIds);
|
||||
|
||||
/**
|
||||
* 导入中介黑名单数据
|
||||
*
|
||||
* @param excelList Excel实体列表
|
||||
* @param isUpdateSupport 是否更新支持
|
||||
* @return 结果
|
||||
*/
|
||||
String importIntermediary(List<CcdiIntermediaryBlacklistExcel> excelList, Boolean isUpdateSupport);
|
||||
|
||||
/**
|
||||
* 根据中介类型获取详情(返回不同类型)
|
||||
*
|
||||
* @param intermediaryId 中介ID
|
||||
* @return 个人返回 CcdiIntermediaryPersonDetailVO,机构返回 CcdiIntermediaryEntityDetailVO
|
||||
*/
|
||||
Object selectIntermediaryDetailById(Long intermediaryId);
|
||||
|
||||
/**
|
||||
* 导入个人中介数据
|
||||
*
|
||||
* @param excelList Excel实体列表
|
||||
* @param isUpdateSupport 是否更新支持
|
||||
* @return 结果
|
||||
*/
|
||||
String importPersonIntermediary(List<CcdiIntermediaryPersonExcel> excelList, Boolean isUpdateSupport);
|
||||
|
||||
/**
|
||||
* 导入机构中介数据
|
||||
*
|
||||
* @param excelList Excel实体列表
|
||||
* @param isUpdateSupport 是否更新支持
|
||||
* @return 结果
|
||||
*/
|
||||
String importEntityIntermediary(List<CcdiIntermediaryEntityExcel> excelList, Boolean isUpdateSupport);
|
||||
}
|
||||
@@ -1,741 +0,0 @@
|
||||
package com.ruoyi.ccdi.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.ruoyi.ccdi.domain.CcdiIntermediaryBlacklist;
|
||||
import com.ruoyi.ccdi.domain.dto.*;
|
||||
import com.ruoyi.ccdi.domain.excel.CcdiIntermediaryBlacklistExcel;
|
||||
import com.ruoyi.ccdi.domain.excel.CcdiIntermediaryEntityExcel;
|
||||
import com.ruoyi.ccdi.domain.excel.CcdiIntermediaryPersonExcel;
|
||||
import com.ruoyi.ccdi.domain.vo.CcdiIntermediaryBlacklistVO;
|
||||
import com.ruoyi.ccdi.domain.vo.CcdiIntermediaryEntityDetailVO;
|
||||
import com.ruoyi.ccdi.domain.vo.CcdiIntermediaryPersonDetailVO;
|
||||
import com.ruoyi.ccdi.enums.DataSource;
|
||||
import com.ruoyi.ccdi.enums.Gender;
|
||||
import com.ruoyi.ccdi.enums.IntermediaryStatus;
|
||||
import com.ruoyi.ccdi.enums.IntermediaryType;
|
||||
import com.ruoyi.ccdi.mapper.CcdiIntermediaryBlacklistMapper;
|
||||
import com.ruoyi.ccdi.service.ICcdiIntermediaryBlacklistService;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 中介人员黑名单 服务层处理
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-01-27
|
||||
*/
|
||||
@Service
|
||||
public class CcdiIntermediaryBlacklistServiceImpl implements ICcdiIntermediaryBlacklistService {
|
||||
|
||||
@Resource
|
||||
private CcdiIntermediaryBlacklistMapper intermediaryMapper;
|
||||
|
||||
/**
|
||||
* 查询中介黑名单列表
|
||||
*
|
||||
* @param queryDTO 查询条件
|
||||
* @return 中介黑名单集合
|
||||
*/
|
||||
@Override
|
||||
public List<CcdiIntermediaryBlacklistVO> selectIntermediaryList(CcdiIntermediaryBlacklistQueryDTO queryDTO) {
|
||||
LambdaQueryWrapper<CcdiIntermediaryBlacklist> wrapper = buildQueryWrapper(queryDTO);
|
||||
List<CcdiIntermediaryBlacklist> list = intermediaryMapper.selectList(wrapper);
|
||||
return list.stream().map(this::convertToVO).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询中介黑名单列表
|
||||
*
|
||||
* @param page 分页对象
|
||||
* @param queryDTO 查询条件
|
||||
* @return 中介黑名单VO分页结果
|
||||
*/
|
||||
@Override
|
||||
public Page<CcdiIntermediaryBlacklistVO> selectIntermediaryPage(Page<CcdiIntermediaryBlacklist> page, CcdiIntermediaryBlacklistQueryDTO queryDTO) {
|
||||
LambdaQueryWrapper<CcdiIntermediaryBlacklist> wrapper = buildQueryWrapper(queryDTO);
|
||||
Page<CcdiIntermediaryBlacklist> resultPage = intermediaryMapper.selectPage(page, wrapper);
|
||||
|
||||
// 转换为VO
|
||||
Page<CcdiIntermediaryBlacklistVO> voPage = new Page<>(resultPage.getCurrent(), resultPage.getSize(), resultPage.getTotal());
|
||||
voPage.setRecords(resultPage.getRecords().stream().map(this::convertToVO).collect(Collectors.toList()));
|
||||
voPage.setPages(resultPage.getPages());
|
||||
|
||||
return voPage;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询中介黑名单列表(用于导出)
|
||||
*
|
||||
* @param queryDTO 查询条件
|
||||
* @return 中介黑名单Excel实体集合
|
||||
*/
|
||||
@Override
|
||||
public List<CcdiIntermediaryBlacklistExcel> selectIntermediaryListForExport(CcdiIntermediaryBlacklistQueryDTO queryDTO) {
|
||||
LambdaQueryWrapper<CcdiIntermediaryBlacklist> wrapper = buildQueryWrapper(queryDTO);
|
||||
List<CcdiIntermediaryBlacklist> list = intermediaryMapper.selectList(wrapper);
|
||||
return list.stream().map(entity -> {
|
||||
CcdiIntermediaryBlacklistExcel excel = new CcdiIntermediaryBlacklistExcel();
|
||||
BeanUtils.copyProperties(entity, excel);
|
||||
return excel;
|
||||
}).toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询中介黑名单详细
|
||||
*
|
||||
* @param intermediaryId 中介ID
|
||||
* @return 中介黑名单VO
|
||||
*/
|
||||
@Override
|
||||
public CcdiIntermediaryBlacklistVO selectIntermediaryById(Long intermediaryId) {
|
||||
CcdiIntermediaryBlacklist intermediary = intermediaryMapper.selectById(intermediaryId);
|
||||
return convertToVO(intermediary);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增中介黑名单
|
||||
*
|
||||
* @param addDTO 新增DTO
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public int insertIntermediary(CcdiIntermediaryBlacklistAddDTO addDTO) {
|
||||
CcdiIntermediaryBlacklist intermediary = new CcdiIntermediaryBlacklist();
|
||||
BeanUtils.copyProperties(addDTO, intermediary);
|
||||
// 手动新增时,数据来源设置为 MANUAL
|
||||
intermediary.setDataSource("MANUAL");
|
||||
// 默认状态设置为正常
|
||||
intermediary.setStatus("0");
|
||||
return intermediaryMapper.insert(intermediary);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增个人中介黑名单
|
||||
*
|
||||
* @param addDTO 个人中介新增DTO
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int insertPersonIntermediary(CcdiIntermediaryPersonAddDTO addDTO) {
|
||||
CcdiIntermediaryBlacklist intermediary = new CcdiIntermediaryBlacklist();
|
||||
BeanUtils.copyProperties(addDTO, intermediary);
|
||||
// 设置中介类型为个人
|
||||
intermediary.setIntermediaryType("1");
|
||||
// 手动新增时,数据来源设置为 MANUAL
|
||||
intermediary.setDataSource("MANUAL");
|
||||
return intermediaryMapper.insert(intermediary);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增机构中介黑名单
|
||||
*
|
||||
* @param addDTO 机构中介新增DTO
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int insertEntityIntermediary(CcdiIntermediaryEntityAddDTO addDTO) {
|
||||
CcdiIntermediaryBlacklist intermediary = new CcdiIntermediaryBlacklist();
|
||||
BeanUtils.copyProperties(addDTO, intermediary);
|
||||
// 设置中介类型为机构
|
||||
intermediary.setIntermediaryType("2");
|
||||
// 证件号使用统一社会信用代码
|
||||
intermediary.setCertificateNo(addDTO.getCorpCreditCode());
|
||||
// 手动新增时,数据来源设置为 MANUAL
|
||||
intermediary.setDataSource("MANUAL");
|
||||
return intermediaryMapper.insert(intermediary);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改中介黑名单
|
||||
*
|
||||
* @param editDTO 编辑DTO
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public int updateIntermediary(CcdiIntermediaryBlacklistEditDTO editDTO) {
|
||||
CcdiIntermediaryBlacklist intermediary = new CcdiIntermediaryBlacklist();
|
||||
BeanUtils.copyProperties(editDTO, intermediary);
|
||||
return intermediaryMapper.updateById(intermediary);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改个人中介黑名单
|
||||
*
|
||||
* @param editDTO 个人中介编辑DTO
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int updatePersonIntermediary(CcdiIntermediaryPersonEditDTO editDTO) {
|
||||
CcdiIntermediaryBlacklist intermediary = new CcdiIntermediaryBlacklist();
|
||||
BeanUtils.copyProperties(editDTO, intermediary);
|
||||
// 设置中介类型为个人
|
||||
intermediary.setIntermediaryType("1");
|
||||
// 清空机构专属字段
|
||||
clearEntityFields(intermediary);
|
||||
return intermediaryMapper.updateById(intermediary);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改机构中介黑名单
|
||||
*
|
||||
* @param editDTO 机构中介编辑DTO
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int updateEntityIntermediary(CcdiIntermediaryEntityEditDTO editDTO) {
|
||||
CcdiIntermediaryBlacklist intermediary = new CcdiIntermediaryBlacklist();
|
||||
BeanUtils.copyProperties(editDTO, intermediary);
|
||||
// 设置中介类型为机构
|
||||
intermediary.setIntermediaryType("2");
|
||||
// 清空个人专属字段
|
||||
clearPersonFields(intermediary);
|
||||
return intermediaryMapper.updateById(intermediary);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空个人专属字段
|
||||
*/
|
||||
private void clearPersonFields(CcdiIntermediaryBlacklist intermediary) {
|
||||
intermediary.setIndivType(null);
|
||||
intermediary.setIndivSubType(null);
|
||||
intermediary.setIndivGender(null);
|
||||
intermediary.setIndivCertType(null);
|
||||
intermediary.setIndivPhone(null);
|
||||
intermediary.setIndivWechat(null);
|
||||
intermediary.setIndivAddress(null);
|
||||
intermediary.setIndivCompany(null);
|
||||
intermediary.setIndivPosition(null);
|
||||
intermediary.setIndivRelatedId(null);
|
||||
intermediary.setIndivRelation(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空机构专属字段
|
||||
*/
|
||||
private void clearEntityFields(CcdiIntermediaryBlacklist intermediary) {
|
||||
intermediary.setCorpCreditCode(null);
|
||||
intermediary.setCorpType(null);
|
||||
intermediary.setCorpNature(null);
|
||||
intermediary.setCorpIndustryCategory(null);
|
||||
intermediary.setCorpIndustry(null);
|
||||
intermediary.setCorpEstablishDate(null);
|
||||
intermediary.setCorpAddress(null);
|
||||
intermediary.setCorpLegalRep(null);
|
||||
intermediary.setCorpLegalCertType(null);
|
||||
intermediary.setCorpLegalCertNo(null);
|
||||
intermediary.setCorpShareholder1(null);
|
||||
intermediary.setCorpShareholder2(null);
|
||||
intermediary.setCorpShareholder3(null);
|
||||
intermediary.setCorpShareholder4(null);
|
||||
intermediary.setCorpShareholder5(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除中介黑名单
|
||||
*
|
||||
* @param intermediaryIds 需要删除的中介ID
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteIntermediaryByIds(Long[] intermediaryIds) {
|
||||
return intermediaryMapper.deleteBatchIds(List.of(intermediaryIds));
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入中介黑名单数据
|
||||
*
|
||||
* @param excelList Excel实体列表
|
||||
* @param isUpdateSupport 是否更新支持
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public String importIntermediary(List<CcdiIntermediaryBlacklistExcel> excelList, Boolean isUpdateSupport) {
|
||||
if (excelList == null || excelList.isEmpty()) {
|
||||
return "至少需要一条数据";
|
||||
}
|
||||
|
||||
int successNum = 0;
|
||||
int failureNum = 0;
|
||||
StringBuilder successMsg = new StringBuilder();
|
||||
StringBuilder failureMsg = new StringBuilder();
|
||||
|
||||
for (CcdiIntermediaryBlacklistExcel excel : excelList) {
|
||||
try {
|
||||
// 转换为AddDTO
|
||||
CcdiIntermediaryBlacklistAddDTO addDTO = new CcdiIntermediaryBlacklistAddDTO();
|
||||
BeanUtils.copyProperties(excel, addDTO);
|
||||
|
||||
// 验证数据
|
||||
validateIntermediaryData(addDTO);
|
||||
|
||||
CcdiIntermediaryBlacklist intermediary = new CcdiIntermediaryBlacklist();
|
||||
BeanUtils.copyProperties(addDTO, intermediary);
|
||||
|
||||
intermediaryMapper.insert(intermediary);
|
||||
successNum++;
|
||||
successMsg.append("<br/>").append(successNum).append("、").append(addDTO.getName()).append(" 导入成功");
|
||||
} catch (Exception e) {
|
||||
failureNum++;
|
||||
failureMsg.append("<br/>").append(failureNum).append("、").append(excel.getName()).append(" 导入失败:");
|
||||
failureMsg.append(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
if (failureNum > 0) {
|
||||
failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
|
||||
throw new RuntimeException(failureMsg.toString());
|
||||
} else {
|
||||
successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条");
|
||||
return successMsg.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据中介类型获取详情(返回不同类型)
|
||||
*
|
||||
* @param intermediaryId 中介ID
|
||||
* @return 个人返回 CcdiIntermediaryPersonDetailVO,机构返回 CcdiIntermediaryEntityDetailVO
|
||||
*/
|
||||
@Override
|
||||
public Object selectIntermediaryDetailById(Long intermediaryId) {
|
||||
CcdiIntermediaryBlacklist intermediary = intermediaryMapper.selectById(intermediaryId);
|
||||
if (intermediary == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 根据中介类型返回不同的 VO
|
||||
if ("1".equals(intermediary.getIntermediaryType())) {
|
||||
// 个人类型
|
||||
return convertToPersonDetailVO(intermediary);
|
||||
} else {
|
||||
// 机构类型
|
||||
return convertToEntityDetailVO(intermediary);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入个人中介数据(批量插入优化版)
|
||||
*
|
||||
* @param excelList Excel实体列表
|
||||
* @param isUpdateSupport 是否更新支持
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public String importPersonIntermediary(List<CcdiIntermediaryPersonExcel> excelList, Boolean isUpdateSupport) {
|
||||
if (excelList == null || excelList.isEmpty()) {
|
||||
return "至少需要一条数据";
|
||||
}
|
||||
|
||||
// 批量处理:先验证所有数据
|
||||
List<CcdiIntermediaryBlacklist> toInsertList = new ArrayList<>();
|
||||
List<CcdiIntermediaryBlacklist> toUpdateList = new ArrayList<>();
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
|
||||
// 批量查询已存在的记录(用于唯一性校验或更新支持)
|
||||
Set<String> existingCertNos = new HashSet<>();
|
||||
Map<String, Long> certNoToIdMap = new HashMap<>();
|
||||
for (CcdiIntermediaryPersonExcel excel : excelList) {
|
||||
if (StringUtils.isNotEmpty(excel.getCertificateNo())) {
|
||||
existingCertNos.add(excel.getCertificateNo());
|
||||
}
|
||||
}
|
||||
if (!existingCertNos.isEmpty()) {
|
||||
LambdaQueryWrapper<CcdiIntermediaryBlacklist> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CcdiIntermediaryBlacklist::getIntermediaryType, "1")
|
||||
.in(CcdiIntermediaryBlacklist::getCertificateNo, existingCertNos)
|
||||
.select(CcdiIntermediaryBlacklist::getIntermediaryId, CcdiIntermediaryBlacklist::getCertificateNo);
|
||||
List<CcdiIntermediaryBlacklist> existingList = intermediaryMapper.selectList(wrapper);
|
||||
for (CcdiIntermediaryBlacklist existing : existingList) {
|
||||
certNoToIdMap.put(existing.getCertificateNo(), existing.getIntermediaryId());
|
||||
}
|
||||
}
|
||||
|
||||
// 如果不是更新模式,先进行唯一性校验
|
||||
if (!isUpdateSupport) {
|
||||
for (CcdiIntermediaryPersonExcel excel : excelList) {
|
||||
if (StringUtils.isNotEmpty(excel.getCertificateNo()) && certNoToIdMap.containsKey(excel.getCertificateNo())) {
|
||||
throw new RuntimeException("证件号 " + excel.getCertificateNo() + " 已存在,请勿重复导入");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 处理每条数据
|
||||
for (int i = 0; i < excelList.size(); i++) {
|
||||
CcdiIntermediaryPersonExcel excel = excelList.get(i);
|
||||
try {
|
||||
// 验证数据
|
||||
validatePersonIntermediaryData(excel);
|
||||
|
||||
// 转换为实体
|
||||
CcdiIntermediaryBlacklist intermediary = new CcdiIntermediaryBlacklist();
|
||||
intermediary.setName(excel.getName());
|
||||
intermediary.setCertificateNo(excel.getCertificateNo());
|
||||
intermediary.setIntermediaryType("1");
|
||||
intermediary.setStatus("0");
|
||||
intermediary.setDataSource("IMPORT");
|
||||
intermediary.setRemark(excel.getRemark());
|
||||
|
||||
// 个人专属字段
|
||||
intermediary.setIndivType(excel.getIndivType());
|
||||
intermediary.setIndivSubType(excel.getIndivSubType());
|
||||
intermediary.setIndivGender(excel.getIndivGender());
|
||||
intermediary.setIndivCertType(StringUtils.isNotEmpty(excel.getIndivCertType()) ? excel.getIndivCertType() : "身份证");
|
||||
intermediary.setIndivPhone(excel.getIndivPhone());
|
||||
intermediary.setIndivWechat(excel.getIndivWechat());
|
||||
intermediary.setIndivAddress(excel.getIndivAddress());
|
||||
intermediary.setIndivCompany(excel.getIndivCompany());
|
||||
intermediary.setIndivPosition(excel.getIndivPosition());
|
||||
intermediary.setIndivRelatedId(excel.getIndivRelatedId());
|
||||
intermediary.setIndivRelation(excel.getIndivRelation());
|
||||
|
||||
// 检查是否需要更新
|
||||
if (isUpdateSupport && StringUtils.isNotEmpty(excel.getCertificateNo()) && certNoToIdMap.containsKey(excel.getCertificateNo())) {
|
||||
intermediary.setIntermediaryId(certNoToIdMap.get(excel.getCertificateNo()));
|
||||
toUpdateList.add(intermediary);
|
||||
} else {
|
||||
toInsertList.add(intermediary);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
errorMessages.add("第" + (i + 1) + "行导入失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// 批量执行数据库操作
|
||||
int successNum = 0;
|
||||
int failureNum = errorMessages.size();
|
||||
|
||||
// 批量插入
|
||||
if (!toInsertList.isEmpty()) {
|
||||
intermediaryMapper.batchInsert(toInsertList);
|
||||
successNum += toInsertList.size();
|
||||
}
|
||||
|
||||
// 批量更新
|
||||
if (!toUpdateList.isEmpty()) {
|
||||
intermediaryMapper.batchUpdate(toUpdateList);
|
||||
successNum += toUpdateList.size();
|
||||
}
|
||||
|
||||
// 构建失败消息
|
||||
StringBuilder failureMsg = new StringBuilder();
|
||||
for (String error : errorMessages) {
|
||||
failureMsg.append("<br/>").append(error);
|
||||
}
|
||||
|
||||
// 返回结果
|
||||
if (failureNum > 0) {
|
||||
failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
|
||||
throw new RuntimeException(failureMsg.toString());
|
||||
} else {
|
||||
return "恭喜您,数据已全部导入成功!共 " + successNum + " 条";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入机构中介数据(批量插入优化版)
|
||||
*
|
||||
* @param excelList Excel实体列表
|
||||
* @param isUpdateSupport 是否更新支持
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public String importEntityIntermediary(List<CcdiIntermediaryEntityExcel> excelList, Boolean isUpdateSupport) {
|
||||
if (excelList == null || excelList.isEmpty()) {
|
||||
return "至少需要一条数据";
|
||||
}
|
||||
|
||||
// 批量处理:先验证所有数据
|
||||
List<CcdiIntermediaryBlacklist> toInsertList = new ArrayList<>();
|
||||
List<CcdiIntermediaryBlacklist> toUpdateList = new ArrayList<>();
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
|
||||
// 批量查询已存在的记录(用于唯一性校验或更新支持)
|
||||
Set<String> existingCreditCodes = new HashSet<>();
|
||||
Map<String, Long> creditCodeToIdMap = new HashMap<>();
|
||||
for (CcdiIntermediaryEntityExcel excel : excelList) {
|
||||
if (StringUtils.isNotEmpty(excel.getCorpCreditCode())) {
|
||||
existingCreditCodes.add(excel.getCorpCreditCode());
|
||||
}
|
||||
}
|
||||
if (!existingCreditCodes.isEmpty()) {
|
||||
LambdaQueryWrapper<CcdiIntermediaryBlacklist> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(CcdiIntermediaryBlacklist::getIntermediaryType, "2")
|
||||
.in(CcdiIntermediaryBlacklist::getCorpCreditCode, existingCreditCodes)
|
||||
.select(CcdiIntermediaryBlacklist::getIntermediaryId, CcdiIntermediaryBlacklist::getCorpCreditCode);
|
||||
List<CcdiIntermediaryBlacklist> existingList = intermediaryMapper.selectList(wrapper);
|
||||
for (CcdiIntermediaryBlacklist existing : existingList) {
|
||||
creditCodeToIdMap.put(existing.getCorpCreditCode(), existing.getIntermediaryId());
|
||||
}
|
||||
}
|
||||
|
||||
// 如果不是更新模式,先进行唯一性校验
|
||||
if (!isUpdateSupport) {
|
||||
for (CcdiIntermediaryEntityExcel excel : excelList) {
|
||||
if (StringUtils.isNotEmpty(excel.getCorpCreditCode()) && creditCodeToIdMap.containsKey(excel.getCorpCreditCode())) {
|
||||
throw new RuntimeException("统一社会信用代码 " + excel.getCorpCreditCode() + " 已存在,请勿重复导入");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
|
||||
|
||||
// 处理每条数据
|
||||
for (int i = 0; i < excelList.size(); i++) {
|
||||
CcdiIntermediaryEntityExcel excel = excelList.get(i);
|
||||
try {
|
||||
// 验证数据
|
||||
validateEntityIntermediaryData(excel);
|
||||
|
||||
// 转换为实体
|
||||
CcdiIntermediaryBlacklist intermediary = new CcdiIntermediaryBlacklist();
|
||||
intermediary.setName(excel.getName());
|
||||
// 对于机构中介,使用统一社会信用代码作为证件号
|
||||
intermediary.setCertificateNo(excel.getCorpCreditCode());
|
||||
intermediary.setIntermediaryType("2");
|
||||
intermediary.setStatus("0");
|
||||
intermediary.setDataSource("IMPORT");
|
||||
intermediary.setRemark(excel.getRemark());
|
||||
|
||||
// 机构专属字段
|
||||
intermediary.setCorpCreditCode(excel.getCorpCreditCode());
|
||||
intermediary.setCorpType(excel.getCorpType());
|
||||
intermediary.setCorpNature(excel.getCorpNature());
|
||||
intermediary.setCorpIndustryCategory(excel.getCorpIndustryCategory());
|
||||
intermediary.setCorpIndustry(excel.getCorpIndustry());
|
||||
|
||||
// 解析成立日期
|
||||
if (StringUtils.isNotEmpty(excel.getCorpEstablishDate())) {
|
||||
try {
|
||||
intermediary.setCorpEstablishDate(sdf.parse(excel.getCorpEstablishDate()));
|
||||
} catch (Exception e) {
|
||||
// 忽略日期解析错误
|
||||
}
|
||||
}
|
||||
|
||||
intermediary.setCorpAddress(excel.getCorpAddress());
|
||||
intermediary.setCorpLegalRep(excel.getCorpLegalRep());
|
||||
intermediary.setCorpLegalCertType(excel.getCorpLegalCertType());
|
||||
intermediary.setCorpLegalCertNo(excel.getCorpLegalCertNo());
|
||||
intermediary.setCorpShareholder1(excel.getCorpShareholder1());
|
||||
intermediary.setCorpShareholder2(excel.getCorpShareholder2());
|
||||
intermediary.setCorpShareholder3(excel.getCorpShareholder3());
|
||||
intermediary.setCorpShareholder4(excel.getCorpShareholder4());
|
||||
intermediary.setCorpShareholder5(excel.getCorpShareholder5());
|
||||
|
||||
// 检查是否需要更新
|
||||
if (isUpdateSupport && StringUtils.isNotEmpty(excel.getCorpCreditCode()) && creditCodeToIdMap.containsKey(excel.getCorpCreditCode())) {
|
||||
intermediary.setIntermediaryId(creditCodeToIdMap.get(excel.getCorpCreditCode()));
|
||||
toUpdateList.add(intermediary);
|
||||
} else {
|
||||
toInsertList.add(intermediary);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
errorMessages.add("第" + (i + 1) + "行导入失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// 批量执行数据库操作
|
||||
int successNum = 0;
|
||||
int failureNum = errorMessages.size();
|
||||
|
||||
// 批量插入
|
||||
if (!toInsertList.isEmpty()) {
|
||||
intermediaryMapper.batchInsert(toInsertList);
|
||||
successNum += toInsertList.size();
|
||||
}
|
||||
|
||||
// 批量更新
|
||||
if (!toUpdateList.isEmpty()) {
|
||||
intermediaryMapper.batchUpdate(toUpdateList);
|
||||
successNum += toUpdateList.size();
|
||||
}
|
||||
|
||||
// 构建失败消息
|
||||
StringBuilder failureMsg = new StringBuilder();
|
||||
for (String error : errorMessages) {
|
||||
failureMsg.append("<br/>").append(error);
|
||||
}
|
||||
|
||||
// 返回结果
|
||||
if (failureNum > 0) {
|
||||
failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
|
||||
throw new RuntimeException(failureMsg.toString());
|
||||
} else {
|
||||
return "恭喜您,数据已全部导入成功!共 " + successNum + " 条";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证个人中介数据
|
||||
*/
|
||||
private void validatePersonIntermediaryData(CcdiIntermediaryPersonExcel excel) {
|
||||
if (StringUtils.isEmpty(excel.getName())) {
|
||||
throw new RuntimeException("姓名不能为空");
|
||||
}
|
||||
if (StringUtils.isEmpty(excel.getCertificateNo())) {
|
||||
throw new RuntimeException("证件号码不能为空");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证机构中介数据
|
||||
*/
|
||||
private void validateEntityIntermediaryData(CcdiIntermediaryEntityExcel excel) {
|
||||
if (StringUtils.isEmpty(excel.getName())) {
|
||||
throw new RuntimeException("机构名称不能为空");
|
||||
}
|
||||
// 验证统一社会信用代码不能为空(因为会用作 certificate_no 字段)
|
||||
if (StringUtils.isEmpty(excel.getCorpCreditCode())) {
|
||||
throw new RuntimeException("统一社会信用代码不能为空");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为个人详情 VO
|
||||
*/
|
||||
private CcdiIntermediaryPersonDetailVO convertToPersonDetailVO(CcdiIntermediaryBlacklist intermediary) {
|
||||
if (intermediary == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
CcdiIntermediaryPersonDetailVO vo = new CcdiIntermediaryPersonDetailVO();
|
||||
// 复制基础字段
|
||||
vo.setIntermediaryId(intermediary.getIntermediaryId());
|
||||
vo.setName(intermediary.getName());
|
||||
vo.setCertificateNo(intermediary.getCertificateNo());
|
||||
vo.setIntermediaryType(intermediary.getIntermediaryType());
|
||||
vo.setStatus(intermediary.getStatus());
|
||||
vo.setRemark(intermediary.getRemark());
|
||||
vo.setDataSource(intermediary.getDataSource());
|
||||
vo.setCreateBy(intermediary.getCreateBy());
|
||||
vo.setCreateTime(intermediary.getCreateTime());
|
||||
vo.setUpdateBy(intermediary.getUpdateBy());
|
||||
vo.setUpdateTime(intermediary.getUpdateTime());
|
||||
|
||||
// 复制个人专属字段
|
||||
vo.setIndivType(intermediary.getIndivType());
|
||||
vo.setIndivSubType(intermediary.getIndivSubType());
|
||||
vo.setIndivGender(intermediary.getIndivGender());
|
||||
vo.setIndivCertType(intermediary.getIndivCertType());
|
||||
vo.setIndivPhone(intermediary.getIndivPhone());
|
||||
vo.setIndivWechat(intermediary.getIndivWechat());
|
||||
vo.setIndivAddress(intermediary.getIndivAddress());
|
||||
vo.setIndivCompany(intermediary.getIndivCompany());
|
||||
vo.setIndivPosition(intermediary.getIndivPosition());
|
||||
vo.setIndivRelatedId(intermediary.getIndivRelatedId());
|
||||
vo.setIndivRelation(intermediary.getIndivRelation());
|
||||
|
||||
// 设置枚举类型的名称
|
||||
vo.setIntermediaryTypeName(IntermediaryType.PERSON.getDesc());
|
||||
vo.setStatusName(IntermediaryStatus.getDescByCode(intermediary.getStatus()));
|
||||
vo.setDataSourceName(DataSource.getDescByCode(intermediary.getDataSource()));
|
||||
vo.setIndivGenderName(Gender.getDescByCode(intermediary.getIndivGender()));
|
||||
|
||||
return vo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为机构详情 VO
|
||||
*/
|
||||
private CcdiIntermediaryEntityDetailVO convertToEntityDetailVO(CcdiIntermediaryBlacklist intermediary) {
|
||||
if (intermediary == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
CcdiIntermediaryEntityDetailVO vo = new CcdiIntermediaryEntityDetailVO();
|
||||
// 复制基础字段
|
||||
vo.setIntermediaryId(intermediary.getIntermediaryId());
|
||||
vo.setName(intermediary.getName());
|
||||
vo.setCertificateNo(intermediary.getCertificateNo());
|
||||
vo.setIntermediaryType(intermediary.getIntermediaryType());
|
||||
vo.setStatus(intermediary.getStatus());
|
||||
vo.setRemark(intermediary.getRemark());
|
||||
vo.setDataSource(intermediary.getDataSource());
|
||||
vo.setCreateBy(intermediary.getCreateBy());
|
||||
vo.setCreateTime(intermediary.getCreateTime());
|
||||
vo.setUpdateBy(intermediary.getUpdateBy());
|
||||
vo.setUpdateTime(intermediary.getUpdateTime());
|
||||
|
||||
// 复制机构专属字段
|
||||
vo.setCorpCreditCode(intermediary.getCorpCreditCode());
|
||||
vo.setCorpType(intermediary.getCorpType());
|
||||
vo.setCorpNature(intermediary.getCorpNature());
|
||||
vo.setCorpIndustryCategory(intermediary.getCorpIndustryCategory());
|
||||
vo.setCorpIndustry(intermediary.getCorpIndustry());
|
||||
vo.setCorpEstablishDate(intermediary.getCorpEstablishDate());
|
||||
vo.setCorpAddress(intermediary.getCorpAddress());
|
||||
vo.setCorpLegalRep(intermediary.getCorpLegalRep());
|
||||
vo.setCorpLegalCertType(intermediary.getCorpLegalCertType());
|
||||
vo.setCorpLegalCertNo(intermediary.getCorpLegalCertNo());
|
||||
vo.setCorpShareholder1(intermediary.getCorpShareholder1());
|
||||
vo.setCorpShareholder2(intermediary.getCorpShareholder2());
|
||||
vo.setCorpShareholder3(intermediary.getCorpShareholder3());
|
||||
vo.setCorpShareholder4(intermediary.getCorpShareholder4());
|
||||
vo.setCorpShareholder5(intermediary.getCorpShareholder5());
|
||||
|
||||
// 设置枚举类型的名称
|
||||
vo.setIntermediaryTypeName(IntermediaryType.ENTITY.getDesc());
|
||||
vo.setStatusName(IntermediaryStatus.getDescByCode(intermediary.getStatus()));
|
||||
vo.setDataSourceName(DataSource.getDescByCode(intermediary.getDataSource()));
|
||||
|
||||
return vo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建查询条件
|
||||
*/
|
||||
private LambdaQueryWrapper<CcdiIntermediaryBlacklist> buildQueryWrapper(CcdiIntermediaryBlacklistQueryDTO queryDTO) {
|
||||
LambdaQueryWrapper<CcdiIntermediaryBlacklist> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.like(StringUtils.isNotEmpty(queryDTO.getName()), CcdiIntermediaryBlacklist::getName, queryDTO.getName())
|
||||
.like(StringUtils.isNotEmpty(queryDTO.getCertificateNo()), CcdiIntermediaryBlacklist::getCertificateNo, queryDTO.getCertificateNo())
|
||||
.eq(StringUtils.isNotEmpty(queryDTO.getIntermediaryType()), CcdiIntermediaryBlacklist::getIntermediaryType, queryDTO.getIntermediaryType())
|
||||
.eq(StringUtils.isNotEmpty(queryDTO.getStatus()), CcdiIntermediaryBlacklist::getStatus, queryDTO.getStatus())
|
||||
.orderByDesc(CcdiIntermediaryBlacklist::getCreateTime);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证中介数据
|
||||
*/
|
||||
private void validateIntermediaryData(CcdiIntermediaryBlacklistAddDTO addDTO) {
|
||||
// 验证必填字段
|
||||
if (StringUtils.isEmpty(addDTO.getName())) {
|
||||
throw new RuntimeException("姓名/机构名称不能为空");
|
||||
}
|
||||
if (StringUtils.isEmpty(addDTO.getIntermediaryType())) {
|
||||
throw new RuntimeException("中介类型不能为空");
|
||||
}
|
||||
|
||||
// 验证中介类型
|
||||
if (!"1".equals(addDTO.getIntermediaryType()) && !"2".equals(addDTO.getIntermediaryType())) {
|
||||
throw new RuntimeException("中介类型只能填写'个人'或'机构'");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为VO对象
|
||||
*/
|
||||
private CcdiIntermediaryBlacklistVO convertToVO(CcdiIntermediaryBlacklist intermediary) {
|
||||
if (intermediary == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
CcdiIntermediaryBlacklistVO vo = new CcdiIntermediaryBlacklistVO();
|
||||
BeanUtils.copyProperties(intermediary, vo);
|
||||
|
||||
vo.setIntermediaryTypeName(IntermediaryType.getDescByCode(intermediary.getIntermediaryType()));
|
||||
vo.setStatusName(IntermediaryStatus.getDescByCode(intermediary.getStatus()));
|
||||
|
||||
return vo;
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
package com.ruoyi.ccdi.utils.converter;
|
||||
|
||||
import com.alibaba.excel.converters.Converter;
|
||||
import com.alibaba.excel.enums.CellDataTypeEnum;
|
||||
import com.alibaba.excel.metadata.GlobalConfiguration;
|
||||
import com.alibaba.excel.metadata.data.ReadCellData;
|
||||
import com.alibaba.excel.metadata.data.WriteCellData;
|
||||
import com.alibaba.excel.metadata.property.ExcelContentProperty;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 员工状态转换器
|
||||
* 0=在职, 1=离职
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class EmployeeStatusConverter implements Converter<String> {
|
||||
|
||||
private static final Map<String, String> CODE_TO_DESC = new HashMap<>();
|
||||
private static final Map<String, String> DESC_TO_CODE = new HashMap<>();
|
||||
|
||||
static {
|
||||
CODE_TO_DESC.put("0", "在职");
|
||||
CODE_TO_DESC.put("1", "离职");
|
||||
DESC_TO_CODE.put("在职", "0");
|
||||
DESC_TO_CODE.put("离职", "1");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> supportJavaTypeKey() {
|
||||
return String.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CellDataTypeEnum supportExcelTypeKey() {
|
||||
return CellDataTypeEnum.STRING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty,
|
||||
GlobalConfiguration globalConfiguration) {
|
||||
String value = cellData.getStringValue();
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
// 支持中文和代码两种格式
|
||||
if (DESC_TO_CODE.containsKey(value)) {
|
||||
return DESC_TO_CODE.get(value);
|
||||
}
|
||||
// 如果是纯数字,直接返回
|
||||
if (value.matches("\\d")) {
|
||||
return value;
|
||||
}
|
||||
throw new IllegalArgumentException("无效的员工状态: " + value + ", 请使用: 在职/离职 或 0/1");
|
||||
}
|
||||
|
||||
@Override
|
||||
public WriteCellData<?> convertToExcelData(String value, ExcelContentProperty contentProperty,
|
||||
GlobalConfiguration globalConfiguration) {
|
||||
String desc = CODE_TO_DESC.getOrDefault(value, value);
|
||||
return new WriteCellData<>(desc);
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package com.ruoyi.ccdi.utils.handler;
|
||||
|
||||
import com.alibaba.excel.write.handler.SheetWriteHandler;
|
||||
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
|
||||
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
|
||||
import org.apache.poi.ss.usermodel.DataValidation;
|
||||
import org.apache.poi.ss.usermodel.DataValidationHelper;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.ss.util.CellRangeAddressList;
|
||||
|
||||
/**
|
||||
* 员工状态下拉框处理器
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class EmployeeStatusSheetWriteHandler implements SheetWriteHandler {
|
||||
|
||||
@Override
|
||||
public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
|
||||
Sheet sheet = writeSheetHolder.getSheet();
|
||||
Workbook workbook = writeWorkbookHolder.getWorkbook();
|
||||
DataValidationHelper helper = sheet.getDataValidationHelper();
|
||||
|
||||
// 创建下拉框数据列表
|
||||
String[] statusList = {"在职", "离职"};
|
||||
|
||||
// 设置状态下拉框,从第2行开始(第1行是表头),第7列(状态列,索引为6)
|
||||
CellRangeAddressList addressList = new CellRangeAddressList(1, 10000, 6, 6);
|
||||
|
||||
// 创建显式列表约束
|
||||
DataValidation validation = helper.createValidation(
|
||||
helper.createExplicitListConstraint(statusList),
|
||||
addressList
|
||||
);
|
||||
|
||||
// 设置提示信息
|
||||
validation.createPromptBox("状态选择", "请选择员工状态:在职或离职");
|
||||
validation.setShowPromptBox(true);
|
||||
|
||||
// 设置错误提示
|
||||
validation.createErrorBox("状态错误", "请从下拉框中选择有效的状态值!");
|
||||
validation.setShowErrorBox(true);
|
||||
|
||||
sheet.addValidationData(validation);
|
||||
}
|
||||
}
|
||||
@@ -1,134 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.ruoyi.ccdi.mapper.CcdiIntermediaryBlacklistMapper">
|
||||
|
||||
<!-- 批量插入中介黑名单数据 -->
|
||||
<insert id="batchInsert" parameterType="java.util.List">
|
||||
INSERT INTO ccdi_intermediary_blacklist (
|
||||
name,
|
||||
certificate_no,
|
||||
intermediary_type,
|
||||
status,
|
||||
remark,
|
||||
indiv_type,
|
||||
indiv_sub_type,
|
||||
indiv_gender,
|
||||
indiv_cert_type,
|
||||
indiv_phone,
|
||||
indiv_wechat,
|
||||
indiv_address,
|
||||
indiv_company,
|
||||
indiv_position,
|
||||
indiv_related_id,
|
||||
indiv_relation,
|
||||
corp_credit_code,
|
||||
corp_type,
|
||||
corp_nature,
|
||||
corp_industry_category,
|
||||
corp_industry,
|
||||
corp_establish_date,
|
||||
corp_address,
|
||||
corp_legal_rep,
|
||||
corp_legal_cert_type,
|
||||
corp_legal_cert_no,
|
||||
corp_shareholder_1,
|
||||
corp_shareholder_2,
|
||||
corp_shareholder_3,
|
||||
corp_shareholder_4,
|
||||
corp_shareholder_5,
|
||||
data_source,
|
||||
create_by,
|
||||
create_time,
|
||||
update_by,
|
||||
update_time
|
||||
) VALUES
|
||||
<foreach collection="list" item="item" separator=",">
|
||||
(
|
||||
#{item.name},
|
||||
#{item.certificateNo},
|
||||
#{item.intermediaryType},
|
||||
#{item.status},
|
||||
#{item.remark},
|
||||
#{item.indivType},
|
||||
#{item.indivSubType},
|
||||
#{item.indivGender},
|
||||
#{item.indivCertType},
|
||||
#{item.indivPhone},
|
||||
#{item.indivWechat},
|
||||
#{item.indivAddress},
|
||||
#{item.indivCompany},
|
||||
#{item.indivPosition},
|
||||
#{item.indivRelatedId},
|
||||
#{item.indivRelation},
|
||||
#{item.corpCreditCode},
|
||||
#{item.corpType},
|
||||
#{item.corpNature},
|
||||
#{item.corpIndustryCategory},
|
||||
#{item.corpIndustry},
|
||||
#{item.corpEstablishDate},
|
||||
#{item.corpAddress},
|
||||
#{item.corpLegalRep},
|
||||
#{item.corpLegalCertType},
|
||||
#{item.corpLegalCertNo},
|
||||
#{item.corpShareholder1},
|
||||
#{item.corpShareholder2},
|
||||
#{item.corpShareholder3},
|
||||
#{item.corpShareholder4},
|
||||
#{item.corpShareholder5},
|
||||
#{item.dataSource},
|
||||
#{item.createBy},
|
||||
#{item.createTime},
|
||||
#{item.updateBy},
|
||||
#{item.updateTime}
|
||||
)
|
||||
</foreach>
|
||||
</insert>
|
||||
|
||||
<!-- 批量更新中介黑名单数据 -->
|
||||
<update id="batchUpdate" parameterType="java.util.List">
|
||||
<foreach collection="list" item="item" separator=";">
|
||||
UPDATE ccdi_intermediary_blacklist
|
||||
<set>
|
||||
<if test="item.name != null">name = #{item.name},</if>
|
||||
<if test="item.certificateNo != null">certificate_no = #{item.certificateNo},</if>
|
||||
<if test="item.intermediaryType != null">intermediary_type = #{item.intermediaryType},</if>
|
||||
<if test="item.status != null">status = #{item.status},</if>
|
||||
<if test="item.remark != null">remark = #{item.remark},</if>
|
||||
<if test="item.indivType != null">indiv_type = #{item.indivType},</if>
|
||||
<if test="item.indivSubType != null">indiv_sub_type = #{item.indivSubType},</if>
|
||||
<if test="item.indivGender != null">indiv_gender = #{item.indivGender},</if>
|
||||
<if test="item.indivCertType != null">indiv_cert_type = #{item.indivCertType},</if>
|
||||
<if test="item.indivPhone != null">indiv_phone = #{item.indivPhone},</if>
|
||||
<if test="item.indivWechat != null">indiv_wechat = #{item.indivWechat},</if>
|
||||
<if test="item.indivAddress != null">indiv_address = #{item.indivAddress},</if>
|
||||
<if test="item.indivCompany != null">indiv_company = #{item.indivCompany},</if>
|
||||
<if test="item.indivPosition != null">indiv_position = #{item.indivPosition},</if>
|
||||
<if test="item.indivRelatedId != null">indiv_related_id = #{item.indivRelatedId},</if>
|
||||
<if test="item.indivRelation != null">indiv_relation = #{item.indivRelation},</if>
|
||||
<if test="item.corpCreditCode != null">corp_credit_code = #{item.corpCreditCode},</if>
|
||||
<if test="item.corpType != null">corp_type = #{item.corpType},</if>
|
||||
<if test="item.corpNature != null">corp_nature = #{item.corpNature},</if>
|
||||
<if test="item.corpIndustryCategory != null">corp_industry_category = #{item.corpIndustryCategory},</if>
|
||||
<if test="item.corpIndustry != null">corp_industry = #{item.corpIndustry},</if>
|
||||
<if test="item.corpEstablishDate != null">corp_establish_date = #{item.corpEstablishDate},</if>
|
||||
<if test="item.corpAddress != null">corp_address = #{item.corpAddress},</if>
|
||||
<if test="item.corpLegalRep != null">corp_legal_rep = #{item.corpLegalRep},</if>
|
||||
<if test="item.corpLegalCertType != null">corp_legal_cert_type = #{item.corpLegalCertType},</if>
|
||||
<if test="item.corpLegalCertNo != null">corp_legal_cert_no = #{item.corpLegalCertNo},</if>
|
||||
<if test="item.corpShareholder1 != null">corp_shareholder_1 = #{item.corpShareholder1},</if>
|
||||
<if test="item.corpShareholder2 != null">corp_shareholder_2 = #{item.corpShareholder2},</if>
|
||||
<if test="item.corpShareholder3 != null">corp_shareholder_3 = #{item.corpShareholder3},</if>
|
||||
<if test="item.corpShareholder4 != null">corp_shareholder_4 = #{item.corpShareholder4},</if>
|
||||
<if test="item.corpShareholder5 != null">corp_shareholder_5 = #{item.corpShareholder5},</if>
|
||||
<if test="item.dataSource != null">data_source = #{item.dataSource},</if>
|
||||
<if test="item.certificateNo != null">certificate_no = #{item.certificateNo},</if>
|
||||
update_by = #{item.updateBy},
|
||||
update_time = #{item.updateTime}
|
||||
</set>
|
||||
WHERE intermediary_id = #{item.intermediaryId}
|
||||
</foreach>
|
||||
</update>
|
||||
|
||||
</mapper>
|
||||
@@ -1,5 +1,5 @@
|
||||
# 页面标题
|
||||
VUE_APP_TITLE = 若依管理系统
|
||||
VUE_APP_TITLE = 纪检初核系统
|
||||
|
||||
# 开发环境配置
|
||||
ENV = 'development'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# 页面标题
|
||||
VUE_APP_TITLE = 若依管理系统
|
||||
VUE_APP_TITLE = 纪检初核系统
|
||||
|
||||
# 生产环境配置
|
||||
ENV = 'production'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# 页面标题
|
||||
VUE_APP_TITLE = 若依管理系统
|
||||
VUE_APP_TITLE = 纪检初核系统
|
||||
|
||||
BABEL_ENV = production
|
||||
|
||||
|
||||
@@ -96,6 +96,12 @@
|
||||
icon="el-icon-s-data"
|
||||
@click="handleEnter(scope.row)"
|
||||
>进入项目</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-refresh"
|
||||
@click="handleReAnalyze(scope.row)"
|
||||
>重新分析</el-button>
|
||||
</template>
|
||||
|
||||
<!-- 已完成项目 -->
|
||||
|
||||
@@ -7,7 +7,7 @@ function resolve(dir) {
|
||||
|
||||
const CompressionPlugin = require('compression-webpack-plugin')
|
||||
|
||||
const name = process.env.VUE_APP_TITLE || '若依管理系统' // 网页标题
|
||||
const name = process.env.VUE_APP_TITLE || '纪检初核系统' // 网页标题
|
||||
|
||||
const baseUrl = 'http://localhost:8080' // 后端接口
|
||||
|
||||
|
||||
Reference in New Issue
Block a user