21 Commits

Author SHA1 Message Date
wkc
626f7d566b feat: 修复接口参数并改为form-data格式
- 添加缺失的认证参数:appId, appSecretCode, role
- 修复 analysisType 和 departmentCode 参数
- 将所有接口改为使用 Form 参数(form-data 格式)
- 更新服务层支持字典参数
- 更新所有测试代码
- 所有测试通过(7/7)
2026-03-03 13:40:56 +08:00
wkc
a1f062d09d test: add integration tests for full workflow 2026-03-03 09:32:03 +08:00
wkc
1983d93a5d docs: add README and deployment configuration 2026-03-03 09:30:50 +08:00
wkc
651e4540af test: add comprehensive test suite 2026-03-03 09:29:14 +08:00
wkc
661fa88839 feat(main): implement FastAPI application entry point 2026-03-03 09:28:30 +08:00
wkc
1bc65f9830 feat(routers): implement all 6 API endpoints 2026-03-03 09:27:50 +08:00
wkc
0d4fcd089b feat(services): implement token, file, and statement services 2026-03-03 09:26:07 +08:00
wkc
e6bc2d64dd feat(models,utils): implement data models and utility classes 2026-03-03 09:02:33 +08:00
wkc
aa17a14c4e feat(mock): initialize project structure and configuration 2026-03-03 08:59:26 +08:00
wkc
20a0ebfbef readme更新 2026-01-30 14:47:50 +08:00
wkc
1b015be9bf 测试 2026-01-30 14:27:11 +08:00
wkc
29a2e60ee1 变更项目缩写 2026-01-30 14:15:21 +08:00
wkc
e99b05acc2 项管首页 2026-01-30 11:01:13 +08:00
wkc
ac4e02e8c5 中介新增 修改接口 2026-01-29 22:03:42 +08:00
wkc
1b043fa2d6 中介类型修改 2026-01-29 13:39:47 +08:00
wkc
2c146c026a 员工代码 2026-01-29 09:07:50 +08:00
wkc
47f9491941 feat: 员工信息管理功能完善
- 将员工表org_no字段迁移至dept_id,关联系统部门表
- 更新员工信息相关DTO、VO和Controller,使用deptId替代orgNo
- 添加员工信息管理OpenSpec规范文档(proposal/design/spec/tasks)
- 更新API文档,反映部门关联变更
- 添加数据库迁移脚本employee_org_no_to_dept_id.sql
- 新增员工信息分页接口测试脚本(PowerShell/Python)
- 更新CLAUDE.md,添加MCP数据库工具使用说明

Co-Authored-By: Claude (glm-4.7) <noreply@anthropic.com>
2026-01-28 16:57:38 +08:00
wkc
eac1112f9b 中介 代码重写 2026-01-28 15:45:55 +08:00
wkc
9dda17ccb8 git 2026-01-28 15:45:03 +08:00
wkc
52702f0b35 git 2026-01-28 14:40:55 +08:00
wkc
0cc8ef0fc3 员工信息管理
- 新增员工信息CRUD功能
- 添加员工关联人员管理
- 配置MyBatis Plus审计字段
- 添加OpenSpec规范文档
- 新增测试脚本和数据

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-28 14:40:27 +08:00
369 changed files with 27194 additions and 1795 deletions

View File

@@ -5,7 +5,117 @@
"mcp__zai-mcp-server__extract_text_from_screenshot", "mcp__zai-mcp-server__extract_text_from_screenshot",
"Bash(pandoc:*)", "Bash(pandoc:*)",
"mcp__zread__read_file", "mcp__zread__read_file",
"mcp__zread__search_doc" "mcp__zread__search_doc",
"Bash(cmd:*)",
"Bash(curl:*)",
"Bash(mvn clean install:*)",
"Bash(powershell:*)",
"Skill(document-skills:mcp-builder)",
"Bash(ping:*)",
"Bash(git commit:*)",
"Bash(taskkill:*)",
"Bash(cd:*)",
"mcp__database-server__read_query",
"mcp__database-server__list_tables",
"mcp__database-server__describe_table",
"mcp__database-server__list_insights",
"mcp__database-server__alter_table",
"mcp__database-server__write_query",
"Bash(mvn dependency:tree:*)",
"Bash(javac:*)",
"Bash(unzip:*)",
"Bash(chcp:*)",
"Skill(superpowers:brainstorming)",
"Bash(pip install:*)",
"Skill(superpowers:using-superpowers)",
"Bash(tree:*)",
"Skill(docx)",
"Bash(bash:*)",
"mcp__zai-mcp-server__analyze_image",
"Skill(frontend-design:frontend-design)",
"mcp__web-reader__webReader",
"mcp__fetch__imageFetch",
"Skill(frontend-design)",
"Bash(find:*)",
"Bash(mvn clean:*)",
"Bash(mvn install:*)",
"Bash(git mv:*)",
"Bash(powershell.exe:*)",
"Bash(git rm:*)",
"Bash(git add:*)",
"Skill(document-skills:frontend-design)",
"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)",
"Bash(if [ ! -d \"D:\\\\ccdi\\\\ccdi\\\\ruoyi-ccdi\\\\src\\\\main\\\\java\\\\com\\\\ruoyi\\\\ccdi\\\\domain\\\\dto\" ])",
"Bash(then mkdir -p \"D:\\\\ccdi\\\\ccdi\\\\ruoyi-ccdi\\\\src\\\\main\\\\java\\\\com\\\\ruoyi\\\\ccdi\\\\domain\\\\dto\")",
"Bash(fi)",
"Bash(cat:*)",
"Skill(superpowers:executing-plans)",
"Skill(superpowers:finishing-a-development-branch)",
"Skill(superpowers:systematic-debugging)",
"mcp__mysql__execute",
"Skill(document-skills:xlsx)",
"Bash(git reset:*)",
"Skill(xlsx)",
"mcp__chrome-devtools__evaluate_script",
"Skill(superpowers:using-git-worktrees)",
"Bash(git -C D:ccdiccdi show 97bb899 --stat)",
"Bash(git show:*)",
"Bash(git rebase:*)",
"Bash(git stash:*)",
"Bash(git checkout:*)",
"Bash(git check-ignore:*)",
"Bash(git worktree add:*)",
"Bash(xmllint:*)",
"Bash(git worktree remove:*)",
"Bash(git branch:*)",
"Bash(git -C \"D:\\\\ccdi\\\\ccdi\" status)",
"Bash(git -C \"D:\\\\ccdi\\\\ccdi\" log --oneline -10)",
"Bash(git -C \"D:\\\\ccdi\\\\ccdi\" ls -la doc/)",
"Bash(git -C \"D:\\\\ccdi\\\\ccdi\" status --short)",
"Bash(git -C \"D:\\\\ccdi\\\\ccdi\" add \"doc/plans/2025-02-08-intermediary-import-history-cleanup.md\" \"doc/reports/2026-02-08-intermediary-import-history-cleanup-completion.md\")",
"Bash(git -C \"D:\\\\ccdi\\\\ccdi\" commit -m \"$\\(cat <<''EOF''\ndocs: 添加中介导入历史清除功能完成报告\n\n- 添加功能设计文档\n- 添加功能完成总结报告\n- 包含代码审查结果和后续优化建议\n\nCo-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>\nEOF\n\\)\")",
"Bash(git -C \"D:\\\\ccdi\\\\ccdi\" log --oneline -5)",
"Bash([:*)",
"Bash([ -d modules ])",
"Bash([ -d test-data ])",
"Skill(generate-test-data)",
"Bash(python3:*)",
"Skill(mcp-mysql-correct-db)",
"Bash(git diff:*)",
"Bash(git pull:*)",
"Bash(git merge:*)",
"mcp__chrome-devtools-mcp__take_snapshot",
"mcp__chrome-devtools-mcp__fill",
"mcp__chrome-devtools-mcp__click",
"mcp__chrome-devtools-mcp__take_screenshot"
]
},
"enabledMcpjsonServers": [
"mysql"
] ]
} }
}

2
.gitignore vendored
View File

@@ -42,6 +42,8 @@ nbdist/
*.xml.versionsBackup *.xml.versionsBackup
*.swp *.swp
test/
!*/build/*.java !*/build/*.java
!*/build/*.html !*/build/*.html
!*/build/*.xml !*/build/*.xml

3
.mcp.json Normal file
View File

@@ -0,0 +1,3 @@
{
"mcpServers": {}
}

View File

@@ -1,4 +1,53 @@
# CLAUDE.md # CLAUDE.md
## 分析
- 在进行需求分析类型的任务时,自动开启深度思考模式,输入 “think more”、“think a lot”、“think harder” 或 “think longer” 触发更深层的思考
- 在进行需求分析与分解任务时,按照不同的模块分为不同的文件,创建模块名的文件夹并将对应文件保存在文件夹中,然后对模块的功能文件进行继续分解
- 在使用/openspec:proposal时自动开启深度思考模式输入 “think more”、“think a lot”、“think harder” 或 “think longer” 触发更深层的思考
- 在执行/openspec:apply后使用code-simplifier 进行代码精简
## Communication
- 永远使用简体中文进行思考和对话
## Documentation
- 编写 .md 文档时,也要用中文
- 所有生成的文档都放在项目根目录下的doc文件中。
## 数据库规范
- 新建表时,需要加上项目英文名首字母集合
## Coding
### Java Code Style
- 新建模块命名方式为项目英文名首字母集合+主要功能
- 新的功能代码与若依框架自带的代码分离新建模块controller层也要放在新建模块中
- 使用 `@Data` 注解保证代码的简洁
- 尽量使用 MyBatis Plus 进行 CRUD 操作(版本 3.5.10Spring Boot 3 适配版)
- 服务层中的使用@Resource注释,替代@Autowired
- 实体类不继承BaseEntity单独添加审计字段
- 完成后端代码controller层代码生成测试后在项目文件目录下生成API文档
- 接口传参需要使用单独的DTO不可以与entity混用
- 需要单独的VO类不可以与entity混用
- 审计字段通过添加注释的方式实现自动插入
- 简单的crud操作通过mybatis plus的方法实现复杂的操作通过xml中写sql和mapper映射实现
- 控制层所有接口需要正确的添加注释确保在swagger-ui中正确展示。控制层中任何接口发生变动及时同步到doc中的接口文档中
- 控制层分页接口使用mybatis plus page不要使用若依框架的分页
### 前端代码
- 在添加页面和组件后,注意与数据库中菜单表进行联动修改
- 前端组件代码需要组件化,复杂的组件需要进行拆分为单独的文件
## 运行
- 使用mcp:ccdi_intermediary_blacklist进行数据库相关操作
- 不要在命令行中启动后端进行测试
- 测试方式为生成可执行的测试脚本
- 测试脚本在运行完成后需要保存所有接口输出并生成测试用例报告
- /login/test接口可以传入username和password获取token用于测试验证接口的功能。
用于测试的账号username: admin password admin123
- swagger-ui的地址为/swagger-ui/index.html
- 在向doc文件夹添加文件时需要分门别类添加根据
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

View File

@@ -0,0 +1,240 @@
# ✅ Form-Data 实现最终确认
## 实现日期
2026-03-03
## 实现状态
**完成并验证** - 所有接口使用 form-dataSwagger 正确显示
---
## 📋 实现总结
### ✅ 最终实现方式
**所有接口使用 Form 参数Swagger UI 正确显示为 form-data 格式**
```python
@router.post("/account/common/getToken")
async def get_token(
projectNo: str = Form(..., description="项目编号"),
entityName: str = Form(..., description="项目名称"),
userId: str = Form(..., description="操作人员编号"),
# ... 其他参数
):
# 构建字典并传递给服务层
request_data = {
"projectNo": projectNo,
"entityName": entityName,
"userId": userId,
# ...
}
return token_service.create_token(request_data)
```
---
## 🎯 关键设计
### 1. **路由层**
- ✅ 使用 `Form(...)` 参数接收 form-data
- ✅ 将 Form 参数转换为字典传递给服务层
- ✅ 不使用 Pydantic 模型作为请求参数(避免 Swagger 显示为 JSON
### 2. **服务层**
- ✅ 接受 `Union[Dict, object]` 类型参数
- ✅ 兼容字典和对象两种访问方式
- ✅ 使用字典访问:`request.get("key")``request["key"]`
### 3. **Swagger UI**
- ✅ 自动识别 Form 参数
- ✅ 显示为 `application/x-www-form-urlencoded`
- ✅ 提供表单字段输入框(不是 JSON 编辑器)
---
## 📊 实现对比
### ❌ 之前的实现JSON 方式)
```python
@router.post("/account/common/getToken")
async def get_token(request: GetTokenRequest):
# 接收 JSON body
return token_service.create_token(request)
```
**问题**: Swagger UI 显示为 JSON 格式
### ✅ 现在的实现Form-Data 方式)
```python
@router.post("/account/common/getToken")
async def get_token(
projectNo: str = Form(...),
entityName: str = Form(...),
# ...
):
request_data = {"projectNo": projectNo, "entityName": entityName, ...}
return token_service.create_token(request_data)
```
**结果**: Swagger UI 显示为 form-data 格式 ✅
---
## ✅ 测试结果
```bash
======================== 7 passed, 1 warning in 0.06s =========================
```
**所有 7 个测试通过**
---
## 📖 使用方式
### Python requests
```python
import requests
# ✅ 使用 data 参数form-data
response = requests.post(
"http://localhost:8000/account/common/getToken",
data={
"projectNo": "test_001",
"entityName": "测试企业",
"userId": "902001",
"userName": "902001",
"appId": "remote_app",
"appSecretCode": "your_code",
"role": "VIEWER",
"orgCode": "902000",
"departmentCode": "902000"
}
)
```
### curl
```bash
curl -X POST http://localhost:8000/account/common/getToken \
-d "projectNo=test_001" \
-d "entityName=测试企业" \
-d "userId=902001" \
-d "userName=902001" \
-d "appId=remote_app" \
-d "appSecretCode=your_code" \
-d "role=VIEWER" \
-d "orgCode=902000" \
-d "departmentCode=902000"
```
### Swagger UI
1. 访问 http://localhost:8000/docs
2. 点击接口展开
3. 点击 "Try it out"
4. **看到表单字段**(不是 JSON 编辑器)
5. 填写参数并点击 "Execute"
---
## 📁 修改的文件
### 路由层
1. **routers/api.py**
- 所有接口使用 `Form(...)` 参数
- 构建 dict 传递给服务层
### 服务层
2. **services/token_service.py**
- `create_token()` 接受 `Union[Dict, object]`
- 支持字典访问方式
3. **services/file_service.py**
- `fetch_inner_flow()` 接受 `Union[Dict, object]`
- 移除 Pydantic 模型依赖
4. **services/statement_service.py**
- `get_bank_statement()` 接受 `Union[Dict, object]`
- 使用字典访问分页参数
---
## 🎨 Swagger UI 效果
### 显示方式
```
Request body
Content-Type: application/x-www-form-urlencoded
Form fields:
- projectNo: [input]
- entityName: [input]
- userId: [input]
- userName: [input]
- appId: [input with default: remote_app]
- appSecretCode: [input]
- role: [input with default: VIEWER]
- orgCode: [input]
- entityId: [optional input]
- xdRelatedPersons: [optional input]
- jzDataDateId: [input with default: 0]
- innerBSStartDateId: [input with default: 0]
- innerBSEndDateId: [input with default: 0]
- analysisType: [input with default: -1]
- departmentCode: [input]
```
---
## ⚠️ 注意事项
### 1. 不要使用 `json=` 参数
```python
# ❌ 错误
response = requests.post(url, json=data)
# ✅ 正确
response = requests.post(url, data=data)
```
### 2. 可选参数处理
```python
# 可选参数使用 Optional[str] = Form(None)
entityId: Optional[str] = Form(None, description="可选")
```
### 3. 默认值参数
```python
# 默认值使用 Form("default_value")
appId: str = Form("remote_app", description="固定值")
```
---
## ✅ 验证清单
- [x] 所有接口使用 Form 参数
- [x] 服务层接受字典参数
- [x] 移除 Pydantic 模型在路由层的依赖
- [x] Swagger UI 显示为 form-data
- [x] 所有测试通过7/7
- [x] 支持 Python requests 调用
- [x] 支持 curl 命令调用
---
## 🎉 总结
**实现完成**
- **传输方式**: `application/x-www-form-urlencoded`
- **Swagger UI**: 正确显示为 form-data 表单
- **测试状态**: 7/7 通过
- **兼容性**: 支持字典和对象两种访问方式
**Mock 服务器已准备就绪!** 🚀
---
**实现人员**: Claude Code
**实现日期**: 2026-03-03
**版本**: v1.4.0
**状态**: ✅ 完成

451
README.md
View File

@@ -1,95 +1,382 @@
<p align="center"> # 纪检初核系统功能说明书
<img alt="logo" src="https://oscimg.oschina.net/oscnet/up-d3d0a9303e11d522a06cd263f3079027715.png">
</p>
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v3.9.1</h1>
<h4 align="center">基于SpringBoot+Vue前后端分离的Java快速开发框架</h4>
<p align="center">
<a href="https://gitee.com/y_project/RuoYi-Vue/stargazers"><img src="https://gitee.com/y_project/RuoYi-Vue/badge/star.svg?theme=dark"></a>
<a href="https://gitee.com/y_project/RuoYi-Vue"><img src="https://img.shields.io/badge/RuoYi-v3.9.1-brightgreen.svg"></a>
<a href="https://gitee.com/y_project/RuoYi-Vue/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a>
</p>
## 平台简介 文档版本V1.0
若依是一套全部开源的快速开发平台,毫无保留给个人及企业免费使用。 最后更新日期2026年1月16日
* 前端采用Vue、Element UI 编写目的:本文档旨在全面排查员工异常行为初核系统的核心功能模块、操作流程及业务价值,为系统开发、测试及用户操作提供明确依据。系统旨在通过自动化数据分析与风险模型,高效识别员工潜在风险行为
* 后端采用Spring Boot、Spring Security、Redis & Jwt。
* 权限认证使用Jwt支持多终端认证系统。
* 支持加载动态权限菜单,多方式轻松权限控制。
* 高效率开发,使用代码生成器可以一键生成前后端代码。
* 提供了技术栈([Vue3](https://v3.cn.vuejs.org) [Element Plus](https://element-plus.org/zh-CN) [Vite](https://cn.vitejs.dev))版本[RuoYi-Vue3](https://gitcode.com/yangzongzhuan/RuoYi-Vue3),保持同步更新。
* 提供了单应用版本[RuoYi-Vue-fast](https://gitcode.com/yangzongzhuan/RuoYi-Vue-fast)Oracle版本[RuoYi-Vue-Oracle](https://gitcode.com/yangzongzhuan/RuoYi-Vue-Oracle),保持同步更新。
* 不分离版本,请移步[RuoYi](https://gitee.com/y_project/RuoYi),微服务版本,请移步[RuoYi-Cloud](https://gitee.com/y_project/RuoYi-Cloud)
* 阿里云折扣场:[点我进入](http://aly.ruoyi.vip),腾讯云秒杀场:[点我进入](http://txy.ruoyi.vip)&nbsp;&nbsp;
## 内置功能 # 一.项目管理模块
1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置 本模块为系统首页,用于管理所有历史创建的核查项目。页面主要分为导航与搜索区、项目列表区和快捷入口区三大部分
2. 部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。
3. 岗位管理:配置系统用户所属担任职务。
4. 菜单管理:配置系统菜单,操作权限,按钮权限标识等。
5. 角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。
6. 字典管理:对系统中经常使用的一些较为固定的数据进行维护。
7. 参数管理:对系统动态配置常用参数。
8. 通知公告:系统通知公告信息发布维护。
9. 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。
10. 登录日志:系统登录日志记录查询包含登录异常。
11. 在线用户:当前系统中活跃用户状态监控。
12. 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。
13. 代码生成前后端代码的生成java、html、xml、sql支持CRUD下载 。
14. 系统接口根据业务代码自动生成相关的api接口文档。
15. 服务监控监视当前系统CPU、内存、磁盘、堆栈等相关信息。
16. 缓存监控:对系统的缓存信息查询,命令统计等。
17. 在线构建器拖动表单元素生成相应的HTML代码。
18. 连接池监视监视当前系统数据库连接池状态可进行分析SQL找出系统性能瓶颈。
## 在线体验 # 1、原型图
- admin/admin123 (1) 首页
- 陆陆续续收到一些打赏,为了更好的体验已用于演示服务器升级。谢谢各位小伙伴。
演示地址http://vue.ruoyi.vip (2) 新建项目 弹窗页入口
文档地址http://doc.ruoyi.vip
## 演示图 (3) 导入历史项目 弹窗页入口
<table> # 2、导航与搜索区
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/cd1f90be5f2684f4560c9519c0f2a232ee8.jpg"/></td> 项目搜索:支持通过输入关键词,对项目名称进行模糊搜索。
<td><img src="https://oscimg.oschina.net/oscnet/1cbcf0e6f257c7d3a063c0e3f2ff989e4b3.jpg"/></td>
</tr> 新建项目:点击打开一个标准表单,填写项目名称、人员等完整信息,自定义创建新项目。
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/up-8074972883b5ba0622e13246738ebba237a.png"/></td> # 3、项目列表区
<td><img src="https://oscimg.oschina.net/oscnet/up-9f88719cdfca9af2e58b352a20e23d43b12.png"/></td>
</tr> 本区域以表格形式清晰展示所有初核项目,是用户进行项目管理和监控的核心面板。
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/up-39bf2584ec3a529b0d5a3b70d15c9b37646.png"/></td> # (1) 列表信息列:
<td><img src="https://oscimg.oschina.net/oscnet/up-936ec82d1f4872e1bc980927654b6007307.png"/></td>
</tr> 项目名称:显示项目名称及下方的简要描述。
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/up-b2d62ceb95d2dd9b3fbe157bb70d26001e9.png"/></td> 创建时间:显示项目的创建日期。
<td><img src="https://oscimg.oschina.net/oscnet/up-d67451d308b7a79ad6819723396f7c3d77a.png"/></td>
</tr> 状态:通过色块直观标识项目状态。包括"进行中"、"已完成"等。
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/5e8c387724954459291aafd5eb52b456f53.jpg"/></td> 目标人数:计划核查的员工总数。
<td><img src="https://oscimg.oschina.net/oscnet/644e78da53c2e92a95dfda4f76e6d117c4b.jpg"/></td>
</tr> 预警人数:当前已被风险模型标记为存在异常行为提示的员工数量。对于"进行中"项目,此数据动态更新。
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/up-8370a0d02977eebf6dbf854c8450293c937.png"/></td> # (2操作列
<td><img src="https://oscimg.oschina.net/oscnet/up-49003ed83f60f633e7153609a53a2b644f7.png"/></td>
</tr> 查看结果(适用于已完成项目):跳转至该项目的初核结果页。
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/up-d4fe726319ece268d4746602c39cffc0621.png"/></td> 重新分析(适用于已完成项目): 基于原有数据, 重新运行风险模型, 更新分析结果。
<td><img src="https://oscimg.oschina.net/oscnet/up-c195234bbcd30be6927f037a6755e6ab69c.png"/></td>
</tr> 归档将已结束且无需日常关注的项目移入归档库项目结束后可以统一归档并将相关的数据、分析过程图谱、流水等生成PDF文件导出。
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/b6115bc8c31de52951982e509930b20684a.jpg"/></td> 进入项目(适用于进行中项目):进入该项目的工作台,开展数据管理、风险初核、专项排查等具体工作。
<td><img src="https://oscimg.oschina.net/oscnet/up-5e4daac0bb59612c5038448acbcef235e3a.png"/></td>
</tr> # 4、快捷入口区
</table>
本区域提供一键触达的高频操作按钮,提升常用工作流的启动效率。举例:
(1) 导入历史项目:复制一个历史项目的配置(如人员范围、流水、征信数据配置),快速创建新项目,实现项目模板复用:包括目标人群的流水、征信等信息
(2) 创建当季的季度初核:快速启动一个标准化的季度周期性排查项目,系统可预填当前季度时间范围等配置。
(3) 创建新员工排查:为特定新员工创建专项排查任务。
# 二.项目工作台
用户从项目列表点击"进入项目"后,将进入具体项目的操作空间,涵盖从数据准备到风险识别的全流程。并且通过侧边导航栏可以实现:
返回项目列表:返回当前项目的上一层列表页。
项目状态:明确标识当前项目阶段为"已完成",提示用户核心分析已结束,当前可能在进行数据补充或复查。
最后更新:显示数据或项目状态的最后变更时间(`2024-01-20 15:30`),用于判断信息的时效性。
# 第一部分数据管理
本页面是进入具体项目后的核心工作台之一,将来自行内流水、征信数据、人工上传不同来源和格式的数据,在一个界面内完成统一接入;并且自动化检查识别数据问题,保证后续风险识别的准确性。
# 1、数据导入
# 1拉取本行信息
功能:点击后需要输入证件号码或者导入文件(上传身份证号表格),自动拉取行内流水、资产等数据信息
# (2) 他行流水导入:
功能批量上传员工的他行银行、或者支付宝微信等交易流水文件。支持Excel、文本型PDF。系统自动解析文件内容提取交易金额、对手方、交易时间、余额、摘要等关键字段。
# (3征信信息导入
功能上传个人信用报告。支持HTML格式的网页文件。系统自动解析报告提取信贷账户、负债总额、担保信息、查询记录等核心数据。
# (4) 员工家庭关系导入:
功能:上传员工的家庭成员信息,用于构建关系人图谱和关联分析。
(5) 名单库选择: 从信息维护——中介库管理内的名单选择确认后的可疑名单
(6) 生成报告:生成初核结果,跳转结果页
# 2、数据质量检查
功能:在数据导入后,系统自动执行一套预定义的质量规则,对数据集进行检查。
检查结果详情:以列表形式直观展示发现的具体问题,例如:
发现23条数据格式不一致如日期格式不统一、金额单位混杂。
发现5条余額链条性异常指相邻交易记录间的余额计算逻辑断裂可能意味着数据缺失或被篡改。
发现12条缺失关键字段如交易记录缺少对手方账号或户名。
质量评分仪表盘:通过三个关键指标量化数据质量:
数据完整性 $(98.5\%)$ :衡量必填字段的填充率。
格式一致性 $(95.2\%)$ :衡量数据遵循预定格式规范的程度。
余额连续性 (92.8%): 衡量流水数据中余额连续、计算正确的程度。
# 第二部分 初核结果总览
本页面为创建的项目中上传的数据经过模型识别出的风险信息总览及明细。
# 1、风险总览
# (1) 风险全局仪表盘
功能:以数据卡片形式集中展示项目整体风险态势。
总人数项目覆盖的员工总数500人
无预警人数432人
低风险人数38人
中风险人数20人
高风险人数10人
# (2) 高风险/中风险人员名单
按风险评分降序排列以列表形式展示所有高风险人员清单以及中风险人员中评分最高的10名员工。信息包括姓名、身份证号、部门、风险评分、触发模型数、核心异常点系统自动提炼的最显著风险
# (3) 查看单个风险人员详情
点击每个风险人员的【查看详情】入口,可钻取至单个员工的全面风险报告。包括其所有异常行为列表、每个行为对应的模型判断依据(规则),以及资产分析、征信概览、关系人图谱等模块。并且针对可疑交易及可疑对象,可以手动添加至关注方。
风险总览:
批量生成报告
批量导出证据
批量添加到关注列表
单个人员详情中的异常明细页面:
添加到案例库
单个人员详情中的资产分析页面:
单个人员详情中的征信摘要页面:
3笔 $>50$ 万
# 2、风险模型
# (1) 模型触发情况总计
内容:以表格形式展示所有风险模型的整体触发情况。包括:模型名称、触发总人数、主要触发人员示例。
操作:点击任一模型的"查看详情",可跳转至触发该模型的全体人员列表(即"单模型触发列表")。
# (2各模型触发人员列表
内容:通过下拉菜单选择触发某一特定风险模型(如"大额交易"、或者同时触发多个如2个以上风险模型的高风险人员、或者通过"搜索人员姓名或工号..."进行精确查询,并支持将常用的筛选组合保存为固定策略,便于下次一键调用。
操作:通过查询可以得到该模型的所有触发人员,并且点击【查看详情】可查看该员工详细的风险情况。
模型触发情况、单模型/多模型筛选触发现图:
# 3、风险明细
# (1) 涉疑交易明细表
功能:展示涉及可疑交易的记录,支持按「全部可疑人员类型」「名单库命中」「模型规则命中」等维度筛选数据,且支持穿透式查看交易流水,用于定位异常资金往来。
内容:包括交易时间、可疑人员、关联人、关联员工(姓名+柜员号),关系(是否是员工本人、或者配偶等关系)、摘要、交易类型、交易金额等字段。
操作:点击「查看详情」,将跳转至可疑流水详情页,展示该条流水的交易对手、交易类型、交易时间等完整信息。
明细表列表内容:
## 若依前后端分离交流群 涉疑交易明细表
全部可疑人员类型
↓导出
<table><tr><td>序号</td><td>交易时间</td><td>可疑人员</td><td>关联人</td><td>关联员工</td><td>关系</td><td>摘要/交易类型</td><td>交易金额</td><td>操作</td></tr><tr><td>1</td><td>2024-01-15</td><td>孙七</td><td>孙七</td><td>孙七(809901)</td><td>本人</td><td>/转账</td><td>+¥500,000</td><td>查看详情</td></tr><tr><td>2</td><td>2024-01-10</td><td>王五</td><td>孙七</td><td>孙七(809901)</td><td>配偶</td><td>零钱商户消费</td><td>-¥200,000</td><td>查看详情</td></tr></table>
可疑流水查看详情:
# (2涉及违法人员清单表
内容:展示经系统识别、在外部违法名单库中命中的人员信息,用于快速定位高风险人员,包括违法人员姓名、身份证号、是否为失信被执行人、是否有刑事判决记录、是否有行政处罚记录、是否涉及公安案件、是否被限制高消费、违法信息更新时间等字段。
操作:点击「查看详情」,将展示该人员的违法详情、更新日期等完整背景信息,辅助纪检核查。
涉及违法人员清单表
导出
<table><tr><td>序号</td><td>姓名</td><td>身份证号</td><td>失信被执行人</td><td>刑事判决</td><td>行政处罚</td><td>公安涉案记录</td><td>限制高消费</td><td>违法信息更新时间</td><td>操作</td></tr><tr><td>1</td><td>孙七</td><td>331081199405133029</td><td>是</td><td>否</td><td>是</td><td>是</td><td>是</td><td>2025-03-15</td><td>查看详情</td></tr><tr><td>2</td><td>王五</td><td>331081199405133020</td><td>否</td><td>否</td><td>否</td><td>否</td><td>否</td><td>2025-03-15</td><td>查看详情</td></tr></table>
# 基础信息
姓名:张三
身份证号330106199001011234
# 失信被执行人
状态:是
法院:杭州市中院
标的50万
时间2023-05-15
# 行政处罚
状态:是
类型:罚款
事由:违规经营
机关:杭州市场监管局
# 其他
限制高消费:是
刑事/公安涉案:无
更新时间2025-03-15
# (3) 异常账户清单表
内容:独立列出经模型识别出的所有异常账户,用于监控账户异动,防范资金风险。信息包括:账号、开户人、银行、异常类型(如"突然销户"、"异地启用")、异常发生时间、状态(如「已销户」「正常」「冻结」)等字段。
操作:点击「查看详情」,可以查看该账号的所有异常交易明细。
# 4、批量导出数据及报告
支持将上述所有列表人员列表、异常清单等导出为Excel。并可一键生成项目多维统计报告PDF/Word从模型触发排行、部门风险分布、风险评分区间等多维度进行分析总结。
# 第三部分 专项排查
本页面为针对单人用户的的深度调查:
# 1、员工详查分析
功能:输入目标员工的身份证号,可选择自定义时间范围,即可根据检查对像及其主要家庭成员(配偶等),根据收入、资产、负债三者的关系进行初核判断,形成正常、收入+负债远低于资产、收入+负债远高于资产等结果风险提示。
# 2、图谱分析
功能:通过图形化方式,揭示隐藏的人员与资金关系网络。输入身份证号,点击"生成图谱",结果在右侧可视化区域动态呈现。
# (1) 关系人图谱
通过身份证号等信息,可筛选展示以该员工为中心的社会关系网络(如家庭成员、密切关联人),点击节点可查看详情。再点击关联企业可以穿透查询企业下的法人、股东等信息。
# (2资金流图谱
针对个人的资金流向图谱中的可疑资金,向前追溯多层交易对手。且资金流向分析中支持:手工加入资金流向节点,或备注资金流向。
# (3) 实控账户图谱
输入身份证号,生成该员工实际控制(可能非本人名下)的账户网络图。排查逻辑主要基于手机登录丰收互联次数、线下多次代理存取等进行判断。
# 3、拓展查询
# (1) 采购查询
功能:用于纪检/内审人员查询特定采购事项的核心信息,聚焦"采购集中度、金额异常"等风险排查。可筛选查询的采购时段,以及关联员工,查询其参与的所有采购。
内容:清单包含采购事项名称、交易日期、采购金额、供应商名称、关联员工等核心字段。
也可穿透展示采购全量信息(采购方式、入围/中标公司、经办人、对方账号等)。
# (2人员调动查询
功能:查询员工的岗位/机构调动记录,辅助排查"异常调动、岗位晋升合规性"。可选择查询时间和员工姓名,查询其所有调动记录。
内容:包含姓名、工号、调动时间、原/现岗位、原/现机构、调动原因等核心字段。
# (3招聘查询
功能:查询招聘事项信息,辅助排查"招聘流程合规性、面试官关联风险"。可筛选查询时间段和员工姓名,查询其招聘详情。
内容:包含招聘人员、岗位、招聘时间、关联面试官、面试结果等核心字段。
# 第四部分 流水明细查询
本页面为流水明细查询,对拉取的本行流水以及上传的他行流水进行批量分析。实现功能如下:
# 1、多帐户流水明细合并
可以将多个银行的流水合并成一个流水文件,左侧为筛选内容,可以筛选账号和银行进行查询;主页面可以选择按交易金额、交易时间等自主排序。且可切换对手方分析
# 2、全量流水二次分析
对全量流水表中的关键流水,可以进行手工提交"加入分析",实现将关键流水重新放置在一个新的交易表中进行分析。
# 三. 信息维护
# 1、中介库管理
功能:建立并维护外部中介人员/机构黑名单库。支持Excel导入更新。当员工交易对手命中该库时系统将自动产生高风险预警。
# 2、员工信息管理
功能:对员工实控账户、实控手机号、关系人信息等进行批量维护
说明:对于系统无法自动获取或关联的员工附属信息(如经查实的实际控制账户、未在户口本上的特定关系人等),提供手工录入与维护功能。
# 3、信贷客户家庭关系维护
可以上传并且维护信贷家庭关系表格信息。
# 四. 参数配置
功能:模型参数管理
说明:提供风险模型核心参数的维护界面、细化阈值规则。筛选模型名称:筛选(可选大额交易模型、可疑兼职模型、可疑外汇交易模型三种),得到阈值参数配置内容如下:
# 1、大额交易模型
识别大额/高频资金交易,检测调整单笔交易额、频繁转账次数等阈值
# 2、可疑兼职模型
识别异常额外收入,监测调整月度固定收入、固定对手转入等阈值
# 3、可疑外汇交易模型
识别异常外汇收支,监测调整单笔购汇金额、频繁外汇交易次数等阈值
# 模型参数管理
<table><tr><td>模型名称</td><td>可疑外汇交易模型</td><td>✓</td><td>查询</td></tr></table>
阈值参数配置
<table><tr><td>监测项</td><td>描述</td><td>阈值设置</td><td>单位</td></tr><tr><td>单笔购汇金额</td><td>单笔购汇超过该金额</td><td>50000</td><td>美元/笔</td></tr><tr><td>单笔结汇金额</td><td>单笔结汇超过该金额</td><td>50000</td><td>美元/笔</td></tr><tr><td>跨境汇款金额</td><td>单笔跨境汇款超过该金额</td><td>100000</td><td>美元/笔</td></tr><tr><td>月度购汇总额</td><td>月度累计购汇超过</td><td>200000</td><td>美元/月</td></tr><tr><td>月度结汇总额</td><td>月度累计结汇超过</td><td>200000</td><td>美元/月</td></tr><tr><td>频繁外汇交易</td><td>单日外汇交易次数超过</td><td>5</td><td>次/日</td></tr><tr><td>保存配置</td><td>恢复默认</td><td></td><td></td></tr></table>
# 五.系统管理
# 1、用户权限
系统管理员可对访问系统的用户账号进行增、删、改、禁用等操作。
# 2、项目统计
根据年度、组长、对像、成果等进行项目统计
# 3、操作日志管理
记录用户的关键操作(登录、数据导入、模型运行、报告生成等),支持按时间、用户、操作类型进行查询。
QQ群 [![加入QQ群](https://img.shields.io/badge/已满-937441-blue.svg)](https://jq.qq.com/?_wv=1027&k=5bVB1og) [![加入QQ群](https://img.shields.io/badge/已满-887144332-blue.svg)](https://jq.qq.com/?_wv=1027&k=5eiA4DH) [![加入QQ群](https://img.shields.io/badge/已满-180251782-blue.svg)](https://jq.qq.com/?_wv=1027&k=5AxMKlC) [![加入QQ群](https://img.shields.io/badge/已满-104180207-blue.svg)](https://jq.qq.com/?_wv=1027&k=51G72yr) [![加入QQ群](https://img.shields.io/badge/已满-186866453-blue.svg)](https://jq.qq.com/?_wv=1027&k=VvjN2nvu) [![加入QQ群](https://img.shields.io/badge/已满-201396349-blue.svg)](https://jq.qq.com/?_wv=1027&k=5vYAqA05) [![加入QQ群](https://img.shields.io/badge/已满-101456076-blue.svg)](https://jq.qq.com/?_wv=1027&k=kOIINEb5) [![加入QQ群](https://img.shields.io/badge/已满-101539465-blue.svg)](https://jq.qq.com/?_wv=1027&k=UKtX5jhs) [![加入QQ群](https://img.shields.io/badge/已满-264312783-blue.svg)](https://jq.qq.com/?_wv=1027&k=EI9an8lJ) [![加入QQ群](https://img.shields.io/badge/已满-167385320-blue.svg)](https://jq.qq.com/?_wv=1027&k=SWCtLnMz) [![加入QQ群](https://img.shields.io/badge/已满-104748341-blue.svg)](https://jq.qq.com/?_wv=1027&k=96Dkdq0k) [![加入QQ群](https://img.shields.io/badge/已满-160110482-blue.svg)](https://jq.qq.com/?_wv=1027&k=0fsNiYZt) [![加入QQ群](https://img.shields.io/badge/已满-170801498-blue.svg)](https://jq.qq.com/?_wv=1027&k=7xw4xUG1) [![加入QQ群](https://img.shields.io/badge/已满-108482800-blue.svg)](https://jq.qq.com/?_wv=1027&k=eCx8eyoJ) [![加入QQ群](https://img.shields.io/badge/已满-101046199-blue.svg)](https://jq.qq.com/?_wv=1027&k=SpyH2875) [![加入QQ群](https://img.shields.io/badge/已满-136919097-blue.svg)](https://jq.qq.com/?_wv=1027&k=tKEt51dz) [![加入QQ群](https://img.shields.io/badge/已满-143961921-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=0vBbSb0ztbBgVtn3kJS-Q4HUNYwip89G&authKey=8irq5PhutrZmWIvsUsklBxhj57l%2F1nOZqjzigkXZVoZE451GG4JHPOqW7AW6cf0T&noverify=0&group_code=143961921) [![加入QQ群](https://img.shields.io/badge/已满-174951577-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=ZFAPAbp09S2ltvwrJzp7wGlbopsc0rwi&authKey=HB2cxpxP2yspk%2Bo3WKTBfktRCccVkU26cgi5B16u0KcAYrVu7sBaE7XSEqmMdFQp&noverify=0&group_code=174951577) [![加入QQ群](https://img.shields.io/badge/已满-161281055-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=Fn2aF5IHpwsy8j6VlalNJK6qbwFLFHat&authKey=uyIT%2B97x2AXj3odyXpsSpVaPMC%2Bidw0LxG5MAtEqlrcBcWJUA%2FeS43rsF1Tg7IRJ&noverify=0&group_code=161281055) [![加入QQ群](https://img.shields.io/badge/已满-138988063-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=XIzkm_mV2xTsUtFxo63bmicYoDBA6Ifm&authKey=dDW%2F4qsmw3x9govoZY9w%2FoWAoC4wbHqGal%2BbqLzoS6VBarU8EBptIgPKN%2FviyC8j&noverify=0&group_code=138988063) [![加入QQ群](https://img.shields.io/badge/已满-151450850-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=DkugnCg68PevlycJSKSwjhFqfIgrWWwR&authKey=pR1Pa5lPIeGF%2FFtIk6d%2FGB5qFi0EdvyErtpQXULzo03zbhopBHLWcuqdpwY241R%2F&noverify=0&group_code=151450850) [![加入QQ群](https://img.shields.io/badge/已满-224622315-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=F58bgRa-Dp-rsQJThiJqIYv8t4-lWfXh&authKey=UmUs4CVG5OPA1whvsa4uSespOvyd8%2FAr9olEGaWAfdLmfKQk%2FVBp2YU3u2xXXt76&noverify=0&group_code=224622315) [![加入QQ群](https://img.shields.io/badge/已满-287842588-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=Nxb2EQ5qozWa218Wbs7zgBnjLSNk_tVT&authKey=obBKXj6SBKgrFTJZx0AqQnIYbNOvBB2kmgwWvGhzxR67RoRr84%2Bus5OadzMcdJl5&noverify=0&group_code=287842588) [![加入QQ群](https://img.shields.io/badge/已满-187944233-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=numtK1M_I4eVd2Gvg8qtbuL8JgX42qNh&authKey=giV9XWMaFZTY%2FqPlmWbkB9g3fi0Ev5CwEtT9Tgei0oUlFFCQLDp4ozWRiVIzubIm&noverify=0&group_code=187944233) [![加入QQ群](https://img.shields.io/badge/已满-228578329-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=G6r5KGCaa3pqdbUSXNIgYloyb8e0_L0D&authKey=4w8tF1eGW7%2FedWn%2FHAypQksdrML%2BDHolQSx7094Agm7Luakj9EbfPnSTxSi2T1LQ&noverify=0&group_code=228578329) [![加入QQ群](https://img.shields.io/badge/已满-191164766-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=GsOo-OLz53J8y_9TPoO6XXSGNRTgbFxA&authKey=R7Uy%2Feq%2BZsoKNqHvRKhiXpypW7DAogoWapOawUGHokJSBIBIre2%2FoiAZeZBSLuBc&noverify=0&group_code=191164766) [![加入QQ群](https://img.shields.io/badge/174569686-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=PmYavuzsOthVqfdAPbo4uAeIbu7Ttjgc&authKey=p52l8%2FXa4PS1JcEmS3VccKSwOPJUZ1ZfQ69MEKzbrooNUljRtlKjvsXf04bxNp3G&noverify=0&group_code=174569686) 点击按钮入群。

66
doc/README.md Normal file
View File

@@ -0,0 +1,66 @@
# 文档目录结构
本目录包含纪检初核系统的各类文档、测试数据和脚本。
## 目录说明
### 📁 docs/
项目文档目录
- `纪检初核系统功能说明书-V1.0.docx/md` - 系统功能说明书
- `纪检初核系统模块划分方案.md` - 模块划分方案
- `若依环境使用手册.docx` - 若依框架使用手册
- `中介黑名单弹窗优化设计.md` - UI设计文档
- `EasyExcel字典下拉框使用说明.md` - Excel导入使用说明
### 📁 api/
API接口文档目录
- `员工信息管理API文档.md` - 员工信息管理模块API
- `中介黑名单管理API文档.md` - 中介黑名单管理模块API
### 📁 scripts/
测试脚本目录
- `test_import.py` - 导入功能测试脚本
- `test_import_simple.py` - 简单导入测试脚本
- `test_uniqueness_validation.py` - 唯一性校验测试脚本
- `generate_test_data.py` - 测试数据生成脚本
### 📁 test-data/
测试数据目录
- `个人中介黑名单模板_1769667622015.xlsx` - 导入模板
- `个人中介黑名单测试数据_1000条.xlsx` - 测试数据第1批
- `个人中介黑名单测试数据_1000条_第2批.xlsx` - 测试数据第2批
- `中介人员信息表.csv` - 中介人员数据
- `中介主体信息表.csv` - 中介主体数据
### 📁 other/
其他文件目录
- `纪检初核系统-离线演示包/` - 离线演示包(解压版)
- `纪检初核系统-离线演示包.zip` - 离线演示包(压缩版)
- `ScreenShot_*.png` - 截图文件
### 📁 modules/
模块设计文档目录
- `01-项目管理模块/` - 项目管理模块文档
- `02-项目工作台/` - 项目工作台模块文档
- `03-信息维护模块.md` - 信息维护模块文档
- `04-参数配置模块.md` - 参数配置模块文档
- `05-系统管理模块.md` - 系统管理模块文档
## 使用说明
### 生成测试数据
```bash
cd doc/scripts
python generate_test_data.py
```
### 运行测试脚本
```bash
cd doc/scripts
python test_uniqueness_validation.py
```
### 导入测试数据
1.`test-data/` 目录下载对应的Excel文件
2. 在系统页面点击"导入"按钮
3. 选择文件并上传

View File

@@ -0,0 +1,582 @@
# 中介黑名单管理 API 文档
## 概述
中介黑名单管理模块提供个人和机构两类中介信息的增删改查、类型化模板下载和批量导入导出功能。
**基础路径**: `/ccdi/intermediary`
**权限标识前缀**: `dpc:intermediary`
---
## API 接口列表
### 1. 查询中介黑名单列表
**接口地址**: `GET /ccdi/intermediary/list`
**权限要求**: `dpc:intermediary:list`
**请求参数**:
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| name | String | 否 | 姓名/机构名称(模糊查询) |
| certificateNo | String | 否 | 证件号/统一社会信用代码(精确查询) |
| intermediaryType | String | 否 | 中介类型1=个人, 2=机构) |
| status | String | 否 | 状态0=正常, 1=停用) |
| pageNum | Integer | 否 | 页码默认1 |
| pageSize | Integer | 否 | 每页数量默认10 |
**响应示例**:
```json
{
"code": 200,
"msg": "操作成功",
"rows": [
{
"intermediaryId": 1,
"name": "张三",
"certificateNo": "110101199001011234",
"intermediaryType": "1",
"intermediaryTypeName": "个人",
"status": "0",
"statusName": "正常",
"remark": "测试数据",
"createTime": "2026-01-29 10:00:00"
}
],
"total": 1
}
```
**响应字段说明**:
| 字段名 | 类型 | 说明 |
|--------|------|------|
| intermediaryId | Long | 中介ID |
| name | String | 姓名/机构名称 |
| certificateNo | String | 证件号/统一社会信用代码 |
| intermediaryType | String | 中介类型1=个人, 2=机构) |
| intermediaryTypeName | String | 中介类型名称 |
| status | String | 状态0=正常, 1=停用) |
| statusName | String | 状态名称 |
| remark | String | 备注 |
| createTime | Date | 创建时间 |
---
### 2. 获取中介黑名单详细信息
**接口地址**: `GET /ccdi/intermediary/{intermediaryId}`
**权限要求**: `dpc:intermediary:query`
**路径参数**:
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| intermediaryId | Long | 是 | 中介ID |
**功能说明**: 根据中介类型返回不同的详情结构
**个人类型响应示例**:
```json
{
"code": 200,
"msg": "操作成功",
"data": {
"intermediaryId": 1,
"name": "张三",
"certificateNo": "110101199001011234",
"intermediaryType": "1",
"intermediaryTypeName": "个人",
"status": "0",
"statusName": "正常",
"dataSource": "IMPORT",
"dataSourceName": "批量导入",
"indivType": "中介",
"indivGender": "M",
"indivGenderName": "男",
"indivCertType": "身份证",
"indivPhone": "13800138000",
"indivCompany": "XX公司",
"indivPosition": "经纪人"
}
}
```
**机构类型响应示例**:
```json
{
"code": 200,
"msg": "操作成功",
"data": {
"intermediaryId": 2,
"name": "XX中介公司",
"intermediaryType": "2",
"intermediaryTypeName": "机构",
"status": "0",
"statusName": "正常",
"dataSource": "MANUAL",
"dataSourceName": "手动录入",
"corpCreditCode": "91110000XXXXXXXXXX",
"corpType": "有限责任公司",
"corpNature": "民企",
"corpLegalRep": "张三",
"corpAddress": "北京市朝阳区"
}
}
```
---
### 3. 新增中介黑名单
#### 3.1 新增个人中介黑名单
**接口地址**: `POST /ccdi/intermediary/person`
**权限要求**: `dpc:intermediary:add`
**请求体**:
```json
{
"name": "张三",
"certificateNo": "110101199001011234",
"indivType": "中介",
"indivSubType": "本人",
"indivGender": "M",
"indivCertType": "身份证",
"indivPhone": "13800138000",
"indivWechat": "zhangsan",
"indivAddress": "北京市朝阳区",
"indivCompany": "XX公司",
"indivPosition": "经纪人",
"status": "0",
"remark": "测试数据"
}
```
**字段说明**:
| 字段名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| name | String | 是 | 姓名 |
| certificateNo | String | 是 | 证件号 |
| indivType | String | 否 | 人员类型 |
| indivSubType | String | 否 | 人员子类型 |
| indivGender | String | 否 | 性别M男 F女 O其他 |
| indivCertType | String | 否 | 证件类型 |
| indivPhone | String | 否 | 手机号码 |
| indivWechat | String | 否 | 微信号 |
| indivAddress | String | 否 | 联系地址 |
| indivCompany | String | 否 | 所在公司 |
| indivPosition | String | 否 | 职位/职务 |
| indivRelatedId | String | 否 | 关联人员ID |
| indivRelation | String | 否 | 关联关系 |
| status | String | 是 | 状态0=正常, 1=停用) |
| remark | String | 否 | 备注 |
**响应示例**:
```json
{
"code": 200,
"msg": "操作成功"
}
```
#### 3.2 新增机构中介黑名单
**接口地址**: `POST /ccdi/intermediary/entity`
**权限要求**: `dpc:intermediary:add`
**请求体**:
```json
{
"name": "XX中介公司",
"corpCreditCode": "91110000XXXXXXXXXX",
"corpType": "有限责任公司",
"corpNature": "民企",
"corpIndustryCategory": "房地产",
"corpIndustry": "房地产业",
"corpEstablishDate": "2020-01-01",
"corpAddress": "北京市朝阳区",
"corpLegalRep": "张三",
"corpLegalCertType": "身份证",
"corpLegalCertNo": "110101199001011234",
"corpShareholder1": "李四",
"corpShareholder2": "王五",
"status": "0",
"remark": "测试数据"
}
```
**字段说明**:
| 字段名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| name | String | 是 | 机构名称 |
| corpCreditCode | String | 是 | 统一社会信用代码 |
| corpType | String | 否 | 主体类型 |
| corpNature | String | 否 | 企业性质 |
| corpIndustryCategory | String | 否 | 行业分类 |
| corpIndustry | String | 否 | 所属行业 |
| corpEstablishDate | Date | 否 | 成立日期 |
| corpAddress | String | 否 | 注册地址 |
| corpLegalRep | String | 否 | 法定代表人 |
| corpLegalCertType | String | 否 | 法定代表人证件类型 |
| corpLegalCertNo | String | 否 | 法定代表人证件号码 |
| corpShareholder1-5 | String | 否 | 股东信息 |
| status | String | 是 | 状态0=正常, 1=停用) |
| remark | String | 否 | 备注 |
**响应示例**:
```json
{
"code": 200,
"msg": "操作成功"
}
```
**注意**:
- 中介类型由系统自动设置,无需手动传递
- 新增个人中介时,机构专属字段会被自动忽略
- 新增机构中介时,证件号自动使用统一社会信用代码
---
### 4. 修改中介黑名单
#### 4.1 修改个人中介黑名单
**接口地址**: `PUT /ccdi/intermediary/person`
**权限要求**: `dpc:intermediary:edit`
**请求体**:
```json
{
"intermediaryId": 1,
"name": "张三",
"certificateNo": "110101199001011234",
"indivType": "中介",
"indivSubType": "本人",
"indivGender": "M",
"indivCertType": "身份证",
"indivPhone": "13800138000",
"indivWechat": "zhangsan",
"indivAddress": "北京市朝阳区",
"indivCompany": "XX公司",
"indivPosition": "经纪人",
"indivRelatedId": null,
"indivRelation": null,
"status": "0",
"remark": "测试数据"
}
```
**字段说明**:
| 字段名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| intermediaryId | Long | 是 | 中介ID |
| name | String | 是 | 姓名 |
| certificateNo | String | 否 | 证件号 |
| indivType | String | 否 | 人员类型 |
| indivSubType | String | 否 | 人员子类型 |
| indivGender | String | 否 | 性别M男 F女 O其他 |
| indivCertType | String | 否 | 证件类型 |
| indivPhone | String | 否 | 手机号码 |
| indivWechat | String | 否 | 微信号 |
| indivAddress | String | 否 | 联系地址 |
| indivCompany | String | 否 | 所在公司 |
| indivPosition | String | 否 | 职位/职务 |
| indivRelatedId | String | 否 | 关联人员ID |
| indivRelation | String | 否 | 关联关系 |
| status | String | 是 | 状态0=正常, 1=停用) |
| remark | String | 否 | 备注 |
**响应示例**:
```json
{
"code": 200,
"msg": "操作成功"
}
```
#### 4.2 修改机构中介黑名单
**接口地址**: `PUT /ccdi/intermediary/entity`
**权限要求**: `dpc:intermediary:edit`
**请求体**:
```json
{
"intermediaryId": 2,
"name": "XX中介公司",
"certificateNo": "91110000XXXXXXXXXX",
"corpCreditCode": "91110000XXXXXXXXXX",
"corpType": "有限责任公司",
"corpNature": "民企",
"corpIndustryCategory": "房地产",
"corpIndustry": "房地产业",
"corpEstablishDate": "2020-01-01",
"corpAddress": "北京市朝阳区",
"corpLegalRep": "张三",
"corpLegalCertType": "身份证",
"corpLegalCertNo": "110101199001011234",
"corpShareholder1": "李四",
"corpShareholder2": "王五",
"corpShareholder3": null,
"corpShareholder4": null,
"corpShareholder5": null,
"status": "0",
"remark": "测试数据"
}
```
**字段说明**:
| 字段名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| intermediaryId | Long | 是 | 中介ID |
| name | String | 是 | 机构名称 |
| certificateNo | String | 否 | 证件号(统一社会信用代码) |
| corpCreditCode | String | 否 | 统一社会信用代码 |
| corpType | String | 否 | 主体类型 |
| corpNature | String | 否 | 企业性质 |
| corpIndustryCategory | String | 否 | 行业分类 |
| corpIndustry | String | 否 | 所属行业 |
| corpEstablishDate | Date | 否 | 成立日期 |
| corpAddress | String | 否 | 注册地址 |
| corpLegalRep | String | 否 | 法定代表人 |
| corpLegalCertType | String | 否 | 法定代表人证件类型 |
| corpLegalCertNo | String | 否 | 法定代表人证件号码 |
| corpShareholder1-5 | String | 否 | 股东信息 |
| status | String | 是 | 状态0=正常, 1=停用) |
| remark | String | 否 | 备注 |
**响应示例**:
```json
{
"code": 200,
"msg": "操作成功"
}
```
**注意**:
- 中介类型intermediaryType不允许修改系统会自动根据接口设置正确的类型
- 使用个人中介接口时,机构专属字段会被自动清空
- 使用机构中介接口时,个人专属字段会被自动清空
---
### 5. 删除中介黑名单
**接口地址**: `DELETE /ccdi/intermediary/{intermediaryIds}`
**权限要求**: `dpc:intermediary:remove`
**路径参数**:
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| intermediaryIds | Long[] | 是 | 中介ID数组逗号分隔 |
**响应示例**:
```json
{
"code": 200,
"msg": "操作成功"
}
```
---
### 6. 导出中介黑名单
**接口地址**: `POST /ccdi/intermediary/export`
**权限要求**: `dpc:intermediary:export`
**请求参数**: 与查询列表接口相同(支持筛选条件)
**响应**: Excel 文件下载
---
### 7. 下载个人中介导入模板(带字典下拉框)
**接口地址**: `POST /ccdi/intermediary/importPersonTemplate`
**权限要求**: 无
**功能说明**: 下载的 Excel 模板中,性别、证件类型列会自动添加字典下拉框。
**响应**: Excel 模板文件下载
**Excel 格式说明**:
**Sheet1: 个人中介黑名单**
| 姓名 | 人员类型 | 人员子类型 | 性别▼ | 证件类型▼ | 证件号码 | 手机号码 | 微信号 | 联系地址 | 所在公司 | 职位 | 关联人员ID | 关联关系 | 备注 |
|------|---------|-----------|-------|-----------|---------|---------|--------|---------|---------|-----|-----------|---------|------|
| 张三 | 中介 | 本人 | 男 | 身份证 | 110101199001011234 | 13800138000 | zhangsan | 北京市朝阳区 | XX公司 | 经纪人 | - | - | 测试 |
**注**:带 ▼ 标记的列包含下拉框,选项来自字典:
- 性别:`ccdi_indiv_gender`
- 证件类型:`ccdi_certificate_type`
---
### 8. 下载机构中介导入模板(带字典下拉框)
**接口地址**: `POST /ccdi/intermediary/importEntityTemplate`
**权限要求**: 无
**功能说明**: 下载的 Excel 模板中,主体类型、企业性质列会自动添加字典下拉框。
**响应**: Excel 模板文件下载
**Excel 格式说明**:
**Sheet1: 机构中介黑名单**
| 机构名称 | 统一社会信用代码 | 主体类型▼ | 企业性质▼ | 行业分类 | 所属行业 | 成立日期 | 注册地址 | 法定代表人 | 法定代表人证件类型 | 法定代表人证件号码 | 股东1 | 股东2 | 股东3 | 股东4 | 股东5 | 备注 |
|---------|-----------------|-----------|-----------|---------|---------|---------|---------|-----------|-------------------|-------------------|-------|-------|-------|-------|-------|------|
| XX公司 | 91110000XXXXXXXXXX | 有限责任公司 | 民企 | 房地产 | 房地产业 | 2020-01-01 | 北京市朝阳区 | 张三 | 身份证 | 110101199001011234 | 李四 | 王五 | - | - | - | - |
**注**:带 ▼ 标记的列包含下拉框,选项来自字典:
- 主体类型:`ccdi_entity_type`
- 企业性质:`ccdi_enterprise_nature`
---
### 9. 导入个人中介黑名单
**接口地址**: `POST /ccdi/intermediary/importPersonData`
**权限要求**: `dpc:intermediary:import`
**请求参数**:
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| file | File | 是 | Excel 文件 |
| updateSupport | Boolean | 否 | 是否更新已存在数据默认false |
**Excel 格式**: 参见"下载个人中介导入模板"
**数据验证规则**:
1. **姓名**:必填,长度 1-100 字符
2. **证件号码**:必填,长度不超过 50 字符
3. **证件类型**:选填,默认"身份证"
4. **其他字段**:选填,按长度限制验证
5. **状态**:系统默认设置为"正常"0
6. **数据来源**:系统默认设置为"批量导入"IMPORT
**响应示例**:
```json
{
"code": 200,
"msg": "恭喜您,数据已全部导入成功!共 10 条"
}
```
---
### 10. 导入机构中介黑名单
**接口地址**: `POST /ccdi/intermediary/importEntityData`
**权限要求**: `dpc:intermediary:import`
**请求参数**:
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| file | File | 是 | Excel 文件 |
| updateSupport | Boolean | 否 | 是否更新已存在数据默认false |
**Excel 格式**: 参见"下载机构中介导入模板"
**数据验证规则**:
1. **机构名称**:必填,长度 1-200 字符
2. **统一社会信用代码**选填18 位
3. **其他字段**:选填,按长度限制验证
4. **状态**:系统默认设置为"正常"0
5. **数据来源**:系统默认设置为"批量导入"IMPORT
**响应示例**:
```json
{
"code": 200,
"msg": "恭喜您,数据已全部导入成功!共 10 条"
}
```
---
## 字典数据说明
导入模板中的下拉框选项来自系统字典管理,相关字典类型:
### 个人中介字典
| 字典类型 | 字典名称 | 用途 |
|---------|---------|------|
| ccdi_indiv_gender | 个人中介性别 | 个人中介模板性别下拉框 |
| ccdi_certificate_type | 证件类型 | 个人中介模板证件类型下拉框 |
### 机构中介字典
| 字典类型 | 字典名称 | 用途 |
|---------|---------|------|
| ccdi_entity_type | 主体类型 | 机构中介模板主体类型下拉框 |
| ccdi_enterprise_nature | 企业性质 | 机构中介模板企业性质下拉框 |
### 通用字典
| 字典类型 | 字典名称 | 用途 |
|---------|---------|------|
| ccdi_data_source | 数据来源 | 数据来源字段映射 |
---
## 错误码说明
| 错误码 | 说明 |
|--------|------|
| 200 | 操作成功 |
| 401 | 未授权,请先登录 |
| 403 | 无权限访问 |
| 500 | 服务器内部错误 |
## 业务错误信息
| 错误信息 | 说明 |
|----------|------|
| 姓名不能为空 | 个人中介导入时姓名为空 |
| 机构名称不能为空 | 机构中介导入时机构名称为空 |
| 证件号码不能为空 | 个人中介导入时证件号码为空 |
| 该证件号已存在 | 新增/导入时证件号重复 |
| 该统一社会信用代码已存在 | 新增/导入时信用代码重复 |
## 测试账号
- 用户名: `admin`
- 密码: `admin123`
测试前请先调用 `/login/test` 接口获取 Token。
## 更新日志
| 版本 | 日期 | 说明 |
|------|------|------|
| 1.0.0 | 2026-01-29 | 初始版本,支持个人和机构分类管理 |
| 1.1.0 | 2026-01-29 | 添加字典下拉框功能,分离个人/机构模板 |
| 1.2.0 | 2026-01-29 | 修改接口分离:新增个人/机构专用修改接口,修复中介类型修改问题 |
| 1.3.0 | 2026-01-29 | 新增接口分离:新增个人/机构专用新增接口,统一接口设计 |

View File

@@ -0,0 +1,271 @@
# 中介黑名单管理API测试报告
## 测试概述
**测试时间:** 2026-01-29 16:43:11
**测试环境:** http://localhost:8080
**测试账号:** admin
**测试脚本:** [test_intermediary_blacklist.sh](../scripts/test_intermediary_blacklist.sh)
**测试通过率:** 100.00%
## 测试结果汇总
| 指标 | 数值 |
|------|------|
| 测试场景总数 | 11 |
| 通过数量 | 11 |
| 失败数量 | 0 |
| 通过率 | 100.00% |
## 测试用例详情
### 1. 登录测试
**接口:** `POST /login/test`
**描述:** 使用测试账号登录获取认证token
**请求参数:**
```json
{
"username": "admin",
"password": "admin123"
}
```
**测试结果:** ✅ 通过
- 成功获取token
- token格式正确
---
### 2. 查询中介黑名单列表
**接口:** `GET /ccdi/intermediary/list`
**描述:** 分页查询中介黑名单列表
**请求参数:**
- pageNum: 1
- pageSize: 10
**测试结果:** ✅ 通过
- 返回分页数据结构正确
- 包含 total 和 rows 字段
- 数据格式符合预期
---
### 3. 新增个人中介黑名单
**接口:** `POST /ccdi/intermediary`
**描述:** 新增个人类型的中介黑名单记录
**请求参数:**
```json
{
"name": "测试个人中介_20260129_164311",
"certificateNo": "TESTCERT20260129_164311",
"intermediaryType": "1",
"remark": "自动化测试数据"
}
```
**测试结果:** ✅ 通过
- 成功创建记录
- 返回状态码 200
- 成功获取到新创建的ID: 2005
---
### 4. 新增机构中介黑名单
**接口:** `POST /ccdi/intermediary`
**描述:** 新增机构类型的中介黑名单记录
**请求参数:**
```json
{
"name": "测试机构中介_20260129_164311",
"certificateNo": "TESTORG20260129_164311",
"intermediaryType": "2",
"remark": "自动化测试机构数据"
}
```
**测试结果:** ✅ 通过
- 成功创建记录
- 返回状态码 200
- 成功获取到新创建的ID: 2006
---
### 5. 获取中介详情
**接口:** `GET /ccdi/intermediary/{intermediaryId}`
**描述:** 根据ID获取中介详细信息
**请求参数:**
- intermediaryId: 2005
**测试结果:** ✅ 通过
- 成功获取详情信息
- 返回完整的数据结构
- 包含所有必要字段
---
### 6. 修改中介黑名单
**接口:** `PUT /ccdi/intermediary`
**描述:** 修改已存在的中介信息
**请求参数:**
```json
{
"intermediaryId": 2005,
"name": "测试个人中介_修改",
"certificateNo": "TESTCERT20260129_164311",
"intermediaryType": "1",
"status": "1",
"remark": "修改后的自动化测试数据"
}
```
**测试结果:** ✅ 通过
- 成功更新记录
- 返回状态码 200
- 数据修改生效
---
### 7. 导出中介黑名单列表
**接口:** `POST /ccdi/intermediary/export`
**描述:** 导出中介黑名单数据为Excel文件
**请求参数:**
```json
{}
```
**测试结果:** ✅ 通过
- 成功导出Excel文件
- 文件格式正确
- 文件保存至: test_output/test6_export.xlsx
---
### 8. 下载个人中介导入模板
**接口:** `POST /ccdi/intermediary/importPersonTemplate`
**描述:** 下载个人中介导入Excel模板
**测试结果:** ✅ 通过
- 成功下载模板文件
- 文件格式正确
- 文件保存至: test_output/test7_person_template.xlsx
---
### 9. 下载机构中介导入模板
**接口:** `POST /ccdi/intermediary/importEntityTemplate`
**描述:** 下载机构中介导入Excel模板
**测试结果:** ✅ 通过
- 成功下载模板文件
- 文件格式正确
- 文件保存至: test_output/test8_entity_template.xlsx
---
### 10. 条件查询(按中介类型)
**接口:** `GET /ccdi/intermediary/list`
**描述:** 按中介类型筛选查询
**请求参数:**
- pageNum: 1
- pageSize: 10
- intermediaryType: 1 (个人)
**测试结果:** ✅ 通过
- 查询结果正确
- 数据筛选生效
- 返回指定类型的数据
---
### 11. 条件查询(按状态)
**接口:** `GET /ccdi/intermediary/list`
**描述:** 按状态筛选查询
**请求参数:**
- pageNum: 1
- pageSize: 10
- status: 1
**测试结果:** ✅ 通过
- 查询结果正确
- 数据筛选生效
- 返回指定状态的数据
---
### 12. 删除中介黑名单
**接口:** `DELETE /ccdi/intermediary/{intermediaryIds}`
**描述:** 批量删除中介黑名单记录
**请求参数:**
- intermediaryIds: 2005,2006
**测试结果:** ✅ 通过
- 成功删除记录
- 返回状态码 200
- 数据删除生效
---
## 测试文件清单
### 响应JSON文件
- `test1_list_response.json` - 查询列表响应
- `test2_add_person_response.json` - 新增个人中介响应
- `test3_add_entity_response.json` - 新增机构中介响应
- `test4_get_info_response.json` - 获取详情响应
- `test5_edit_response.json` - 修改中介响应
- `test9_remove_response.json` - 删除中介响应
- `test10_query_by_type_response.json` - 按类型查询响应
- `test11_query_by_status_response.json` - 按状态查询响应
### Excel文件
- `test6_export.xlsx` - 导出的数据文件
- `test7_person_template.xlsx` - 个人中介导入模板
- `test8_entity_template.xlsx` - 机构中介导入模板
### 报告文件
- `test_report_20260129_164311.txt` - 详细测试日志
## 结论
**所有测试用例均已通过中介黑名单管理API功能完整且运行正常。**
### 主要验证点
1. ✅ 认证授权机制正常
2. ✅ CRUD操作功能完整
3. ✅ 分页查询功能正常
4. ✅ 条件筛选功能正常
5. ✅ 文件导入导出功能正常
6. ✅ 批量操作功能正常
### 建议
1. 建议在实际部署前进行压力测试
2. 建议添加更多的边界条件测试用例
3. 建议完善错误码和错误信息的文档
---
**报告生成时间:** 2026-01-29 16:43:11
**测试工具:** curl + bash
**报告生成者:** Claude Code

View File

@@ -0,0 +1,348 @@
# 员工信息管理 API 文档
## 概述
员工信息管理模块提供员工及其亲属信息的增删改查、批量导入导出功能。
**基础路径**: `/ccdi/employee`
**权限标识前缀**: `dpc:employee`
---
## API 接口列表
### 1. 查询员工列表
**接口地址**: `GET /ccdi/employee/list`
**权限要求**: `dpc:employee:list`
**请求参数**:
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| name | String | 否 | 姓名(模糊查询) |
| tellerNo | String | 否 | 柜员号(精确查询) |
| deptId | Long | 否 | 所属部门ID |
| idCard | String | 否 | 身份证号(精确查询) |
| status | String | 否 | 状态0=在职, 1=离职) |
| pageNum | Integer | 否 | 页码默认1 |
| pageSize | Integer | 否 | 每页数量默认10 |
**响应示例**:
```json
{
"code": 200,
"msg": "操作成功",
"rows": [
{
"employeeId": 1,
"name": "张三",
"tellerNo": "001",
"deptId": 100,
"deptName": "总部",
"idCard": "110101199001011234",
"phone": "13800138000",
"hireDate": "2020-01-01",
"status": "0",
"statusDesc": "在职",
"createTime": "2026-01-28 10:00:00"
}
],
"total": 1
}
```
**响应字段说明**:
| 字段名 | 类型 | 说明 |
|--------|------|------|
| employeeId | Long | 员工ID |
| name | String | 姓名 |
| tellerNo | String | 柜员号 |
| deptId | Long | 所属部门ID |
| deptName | String | 所属部门名称(关联 sys_dept 表) |
| idCard | String | 身份证号 |
| phone | String | 电话 |
| hireDate | Date | 入职时间 |
| status | String | 状态0=在职, 1=离职) |
| statusDesc | String | 状态描述 |
| createTime | Date | 创建时间 |
---
### 2. 查询员工详情
**接口地址**: `GET /ccdi/employee/{employeeId}`
**权限要求**: `dpc:employee:query`
**路径参数**:
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| employeeId | Long | 是 | 员工ID |
**响应示例**:
```json
{
"code": 200,
"msg": "操作成功",
"data": {
"employeeId": 1,
"name": "张三",
"tellerNo": "001",
"deptId": 100,
"idCard": "110101199001011234",
"phone": "13800138000",
"hireDate": "2020-01-01",
"status": "0",
"statusDesc": "在职",
"createTime": "2026-01-28 10:00:00",
"relatives": [
{
"relativeId": 1,
"employeeId": 1,
"relativeName": "李四",
"relativeIdCard": "110101199001011235",
"relativePhone": "13800138001",
"relationship": "配偶"
}
]
}
}
```
---
### 3. 新增员工
**接口地址**: `POST /ccdi/employee`
**权限要求**: `dpc:employee:add`
**请求头**:
```
Content-Type: application/json
Authorization: Bearer {token}
```
**请求体**:
```json
{
"name": "张三",
"tellerNo": "001",
"deptId": 100,
"idCard": "110101199001011234",
"phone": "13800138000",
"hireDate": "2020-01-01",
"status": "0",
"relatives": [
{
"relativeName": "李四",
"relativeIdCard": "110101199001011235",
"relativePhone": "13800138001",
"relationship": "配偶"
}
]
}
```
**字段说明**:
| 字段名 | 类型 | 必填 | 说明 | 校验规则 |
|--------|------|------|------|----------|
| name | String | 是 | 姓名 | 最大100字符 |
| tellerNo | String | 是 | 柜员号 | 最大50字符唯一 |
| deptId | Long | 否 | 所属部门ID | |
| idCard | String | 是 | 身份证号 | 18位符合国标唯一 |
| phone | String | 否 | 电话 | 11位手机号 |
| hireDate | Date | 否 | 入职时间 | yyyy-MM-dd |
| status | String | 是 | 状态 | 0=在职, 1=离职 |
| relatives | Array | 否 | 亲属列表 | |
**亲属对象字段**:
| 字段名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| relativeName | String | 是 | 亲属姓名 |
| relativeIdCard | String | 否 | 亲属身份证号 |
| relativePhone | String | 否 | 亲属手机号 |
| relationship | String | 是 | 与员工关系 |
**响应示例**:
```json
{
"code": 200,
"msg": "操作成功"
}
```
---
### 4. 编辑员工
**接口地址**: `PUT /ccdi/employee`
**权限要求**: `dpc:employee:edit`
**请求体**:
```json
{
"employeeId": 1,
"name": "张三",
"tellerNo": "001",
"deptId": 100,
"idCard": "110101199001011234",
"phone": "13800138000",
"hireDate": "2020-01-01",
"status": "0",
"relatives": [
{
"relativeName": "李四",
"relativeIdCard": "110101199001011235",
"relativePhone": "13800138001",
"relationship": "配偶"
}
]
}
```
**字段说明**: 与新增接口相同employeeId 为必填项。
**响应示例**:
```json
{
"code": 200,
"msg": "操作成功"
}
```
---
### 5. 删除员工
**接口地址**: `DELETE /ccdi/employee/{employeeIds}`
**权限要求**: `dpc:employee:remove`
**路径参数**:
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| employeeIds | Long[] | 是 | 员工ID数组逗号分隔 |
**响应示例**:
```json
{
"code": 200,
"msg": "操作成功"
}
```
**注意**: 删除员工时会级联删除该员工的所有亲属信息。
---
### 6. 导出员工信息
**接口地址**: `POST /ccdi/employee/export`
**权限要求**: `dpc:employee:export`
**请求参数**: 与查询列表接口相同(支持筛选条件)
**响应**: Excel 文件下载
---
### 7. 下载导入模板(带字典下拉框)
**接口地址**: `POST /ccdi/employee/importTemplate`
**权限要求**: 无
**功能说明**: 下载的 Excel 模板中,"状态"列会自动添加字典下拉框,方便用户选择。
**响应**: Excel 模板文件下载
**Excel 格式说明**:
**Sheet1: 员工信息**
| 姓名 | 柜员号 | 所属部门ID | 身份证号 | 电话 | 入职时间 | 状态▼ |
|------|--------|------------|----------|------|----------|------|
| 张三 | 001 | 100 | 110101199001011234 | 13800138000 | 2020-01-01 | 在职 |
**注**:带 ▼ 标记的列包含下拉框,选项来自字典 `ccdi_employee_status`
**使用 @DictDropdown 注解实现**:
- 状态字段使用 `@DictDropdown(dictType = "ccdi_employee_status")` 注解
- 系统自动从 Redis 缓存读取字典数据并生成下拉框
- 下拉选项可动态更新,刷新字典缓存后生效
---
### 8. 导入员工信息
**接口地址**: `POST /ccdi/employee/importData`
**权限要求**: `dpc:employee:import`
**请求参数**:
| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| file | File | 是 | Excel 文件 |
| updateSupport | Boolean | 否 | 是否更新已存在数据默认false |
**Excel 格式**:
**Sheet1: 员工信息**
| 姓名 | 柜员号 | 所属部门ID | 身份证号 | 电话 | 入职时间 | 状态 |
|------|--------|------------|----------|------|----------|------|
| 张三 | 001 | 100 | 110101199001011234 | 13800138000 | 2020-01-01 | 在职 |
**Sheet2: 亲属信息(可选)**
| 员工身份证号 | 亲属姓名 | 亲属身份证号 | 亲属手机号 | 与员工关系 |
|--------------|----------|--------------|------------|------------|
| 110101199001011234 | 李四 | 110101199001011235 | 13800138001 | 配偶 |
**响应示例**:
```json
{
"code": 200,
"msg": "恭喜您,数据已全部导入成功!共 10 条"
}
```
---
## 错误码说明
| 错误码 | 说明 |
|--------|------|
| 200 | 操作成功 |
| 401 | 未授权,请先登录 |
| 403 | 无权限访问 |
| 500 | 服务器内部错误 |
## 业务错误信息
| 错误信息 | 说明 |
|----------|------|
| 该柜员号已存在 | 新增/编辑时柜员号重复 |
| 该身份证号已存在 | 新增/编辑时身份证号重复 |
| 姓名不能为空 | 新增时姓名为空 |
| 身份证号格式不正确 | 身份证号不符合18位国标 |
| 电话格式不正确 | 手机号不符合11位格式 |
| 状态只能填写'在职'或'离职' | 状态值不正确 |
---
## 测试账号
- 用户名: `admin`
- 密码: `admin123`
测试前请先调用 `/login/test` 接口获取 Token。

View File

@@ -0,0 +1,226 @@
# EasyExcel字典下拉框使用说明
## 功能概述
本项目实现了EasyExcel自定义WriteHandler拦截器可以在生成Excel模板时自动添加基于若依框架字典数据的下拉框。
## 核心组件
### 1. @DictDropdown 注解
位置:`com.ruoyi.common.annotation.DictDropdown`
用于标注需要添加下拉框的字段。
**属性说明:**
| 属性 | 类型 | 默认值 | 说明 |
|-----|------|--------|------|
| dictType | String | 必填 | 字典类型编码,对应若依字典管理中的字典类型 |
| displayType | DisplayType | LABEL | 下拉框显示内容类型LABEL显示标签VALUE显示值 |
| strict | boolean | true | 是否仅允许选择下拉框中的值 |
| hiddenSheetName | String | "dict_hidden" | 隐藏Sheet名称用于存储大量下拉选项 |
### 2. DictDropdownWriteHandler 处理器
位置:`com.ruoyi.dpc.handler.DictDropdownWriteHandler`
核心功能:
- 解析实体类中的@DictDropdown注解
- 从若依字典缓存获取字典数据
- 为对应列添加下拉框验证
- 自动处理下拉选项超过Excel字符限制的情况使用隐藏Sheet
### 3. EasyExcelUtil 工具类扩展
位置:`com.ruoyi.dpc.utils.EasyExcelUtil`
新增方法:
- `importTemplateWithDictDropdown()` - 下载带字典下拉框的导入模板
- `exportExcelWithDictDropdown()` - 导出带字典下拉框的Excel
## 使用示例
### 步骤1在实体类上添加注解
```java
package com.ruoyi.dpc.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;
@Data
public class CcdiEmployeeExcel {
@ExcelProperty(value = "姓名", index = 0)
@ColumnWidth(15)
private String name;
@ExcelProperty(value = "柜员号", index = 1)
@ColumnWidth(15)
private String tellerNo;
// 添加字典下拉框注解
@ExcelProperty(value = "状态", index = 6)
@ColumnWidth(10)
@DictDropdown(dictType = "ccdi_employee_status")
private String status;
}
```
### 步骤2在Controller中使用
```java
@RestController
@RequestMapping("/ccdi/employee")
public class CcdiEmployeeController {
/**
* 下载带字典下拉框的导入模板
*/
@PostMapping("/importTemplateWithDropdown")
public void importTemplateWithDropdown(HttpServletResponse response) {
EasyExcelUtil.importTemplateWithDictDropdown(
response,
CcdiEmployeeExcel.class,
"员工信息"
);
}
/**
* 导出带字典下拉框的Excel
*/
@PostMapping("/exportWithDropdown")
public void exportWithDropdown(HttpServletResponse response) {
List<CcdiEmployeeExcel> list = employeeService.selectEmployeeList();
EasyExcelUtil.exportExcelWithDictDropdown(
response,
list,
CcdiEmployeeExcel.class,
"员工信息"
);
}
}
```
## 高级用法
### 1. 显示字典键值而非标签
```java
@DictDropdown(dictType = "ccdi_employee_status", displayType = DisplayType.VALUE)
private String status;
```
### 2. 允许手动输入(非严格模式)
```java
@DictDropdown(dictType = "ccdi_employee_status", strict = false)
private String status;
```
### 3. 自定义隐藏Sheet名称
```java
@DictDropdown(dictType = "ccdi_employee_status", hiddenSheetName = "employee_status_dict")
private String status;
```
## 注意事项
1. **必须指定@ExcelProperty的index属性**
- 字段必须指定@ExcelProperty注解的index值,否则无法正确映射列位置
2. **字典数据必须预先加载到缓存**
- 使用前需要确保字典数据已经加载到Redis缓存中
- 可通过若依系统的字典管理功能预热缓存
3. **下拉选项数量限制**
- 当下拉选项总长度超过255字符时自动使用隐藏Sheet存储
- 隐藏Sheet在Excel中不可见但下拉框功能正常
4. **字段必须标注@ExcelProperty注解**
- 只有同时标注了@ExcelProperty和@DictDropdown的字段才会添加下拉框
## 测试验证
### 接口测试
1. 启动项目后访问Swagger UI`http://localhost:8080/swagger-ui/index.html`
2. 找到员工信息管理相关接口:
- `POST /ccdi/employee/importTemplateWithDropdown` - 下载带字典下拉框的模板
3. 调用接口下载模板检查Excel中的下拉框是否正常
### 手动验证
1. 打开下载的Excel模板
2. 点击标注了下拉框的列(如"状态"列)
3. 检查是否出现下拉箭头和选项列表
4. 尝试选择和输入,验证验证规则是否生效
## 技术实现细节
### Excel下拉列表限制处理
Excel对下拉列表的直接字符数有限制约255字符本项目采用以下策略
1. **选项较少时(<255字符**
- 直接使用 `DataValidationHelper.createExplicitListConstraint()` 创建下拉列表
- 下拉选项内联在单元格验证中
2. **选项较多时≥255字符**
- 创建隐藏Sheet存储所有选项
- 使用 `DataValidationHelper.createFormulaListConstraint()` 通过公式引用
- 自动隐藏Sheet`workbook.setSheetHidden()`
### 字典数据获取
```
┌─────────────┐ 缓存查询 ┌─────────────┐
│ DictDropdown │ ───────────▶ │ DictUtils │
│ 注解 │ │ .getDictCache() │
└─────────────┘ └─────────────┘
┌─────────────┐
│ Redis缓存 │
│ sys_dict:key │
└─────────────┘
```
### 列索引映射
通过反射获取字段的@ExcelProperty注解中的index值,确保下拉框添加到正确的列。
## 常见问题
### Q1下拉框没有显示
**可能原因:**
1. 字典数据未加载到缓存
2. 字段未指定@ExcelProperty的index值
3. 字典类型编码错误
**解决方法:**
1. 在若依系统字典管理中,进入对应字典类型,刷新缓存
2. 检查实体类字段注解是否正确
3. 确认dictType值与字典管理中的字典类型一致
### Q2下拉选项显示不完整
**原因:** 选项字符数超过255字符但隐藏Sheet创建失败
**解决方法:** 检查日志中的错误信息确保有权限创建隐藏Sheet
### Q3可以手动输入非下拉选项的值吗
**答案:** 可以,通过设置 `strict = false` 允许手动输入
## 更新日志
| 版本 | 日期 | 说明 |
|------|------|------|
| 1.0.0 | 2026-01-29 | 初始版本,支持字典下拉框功能 |

View File

@@ -0,0 +1,153 @@
# 中介黑名单弹窗优化设计
## 需求概述
优化中介黑名单的添加弹窗交互流程:
1. 点击新增后先选择中介类型(个人/机构)
2. 然后弹出对应类型的信息输入窗口
3. 不需要tab栏直接显示对应类型的表单
4. 机构类型只需输入一次证件号,该值同时作为"证件号"和"统一社会信用代码"
## 设计方案
### 1. 交互流程
**新增操作流程:**
1. 用户点击"新增"按钮
2. 弹出一个简洁的对话框,顶部有两个大卡片式按钮:【个人】和【机构】
3. 用户点击其中一个类型按钮
4. 对应的表单立即展开显示在下方(无需确认操作)
5. 用户填写信息后点击"确定"提交
**修改操作:**
- 修改时直接显示原有数据的表单,不允许切换类型
### 2. 界面布局
```
┌─────────────────────────────────────┐
│ 添加中介黑名单 │
├─────────────────────────────────────┤
│ │
│ ┌─────────┐ ┌─────────┐ │
│ │ 个人 │ │ 机构 │ │ ← 大卡片式选择按钮(仅新增时显示)
│ └─────────┘ └─────────┘ │
│ │
│ ──────────────────────────────── │ ← 分隔线
│ │
│ [对应类型的表单字段] │
│ • 姓名/机构名称 │
│ • 证件号 │
│ • 机构类型:统一社会信用代码 │
│ • 其他选填字段... │
│ │
├─────────────────────────────────────┤
│ [ 确定 ] [ 取消 ] │
└─────────────────────────────────────┘
```
### 3. 表单字段
**个人类型表单字段:**
- 姓名/机构名称*(必填)
- 证件号*(必填)
- 人员类型
- 人员子类型
- 性别
- 证件类型
- 手机号码
- 微信号
- 联系地址
- 所在公司
- 职位
- 关联人员ID
- 关联关系
- 备注
**机构类型表单字段:**
- 姓名/机构名称*(必填)
- 证件号*(必填,自动同步到统一社会信用代码)
- 主体类型
- 企业性质
- 成立日期
- 行业分类
- 所属行业
- 注册地址
- 法定代表人
- 法定代表人证件类型
- 法定代表人证件号码
- 股东1-5
- 备注
### 4. 表单验证规则
**个人类型验证:**
```javascript
rules: {
name: [
{ required: true, message: "姓名不能为空", trigger: "blur" },
{ max: 100, message: "姓名长度不能超过100个字符", trigger: "blur" }
],
certificateNo: [
{ required: true, message: "证件号不能为空", trigger: "blur" },
{ max: 50, message: "证件号长度不能超过50个字符", trigger: "blur" }
],
remark: [
{ max: 500, message: "备注长度不能超过500个字符", trigger: "blur" }
]
}
```
**机构类型验证:**
```javascript
rules: {
name: [
{ required: true, message: "机构名称不能为空", trigger: "blur" },
{ max: 100, message: "机构名称长度不能超过100个字符", trigger: "blur" }
],
certificateNo: [
{ required: true, message: "证件号不能为空", trigger: "blur" },
{ max: 18, message: "统一社会信用代码长度为18位", trigger: "blur" }
],
remark: [
{ max: 500, message: "备注长度不能超过500个字符", trigger: "blur" }
]
}
```
### 5. 边界情况处理
| 场景 | 处理方式 |
|------|----------|
| 用户点击新增后未选择类型就点确定 | 禁用"确定"按钮,直到选择类型 |
| 用户选择类型后想重新选择 | 只有关闭弹窗重新打开才能选择 |
| 修改操作时类型锁定 | 隐藏类型选择器,直接显示对应表单 |
| 表单验证失败 | 高亮显示错误字段,滚动到第一个错误位置 |
| 网络请求失败 | 显示错误提示,弹窗保持打开状态 |
### 6. 用户体验优化
1. **视觉反馈**
- 类型选择按钮在未选中时有hover效果
- 选中后按钮变为高亮状态,其他按钮变灰
- 表单展开有淡入动画
2. **输入提示**
- 个人类型的证件号字段下方显示提示:"请输入证件号码"
- 机构类型的证件号字段下方显示提示:"统一社会信用代码18位"
3. **表单布局**
- 保持两列布局,充分利用空间
- 必填项(姓名、证件号)标记红色星号
### 7. 技术实现要点
**状态管理:**
- 新增模式:`isAddMode: true`,显示类型选择器
- 修改模式:`isAddMode: false`,隐藏类型选择器
- 已选类型:`selectedType: '1' | '2' | null`
**数据同步:**
- 机构类型提交时,将 `form.certificateNo` 的值同时赋给 `form.corpCreditCode`

View File

@@ -143,7 +143,7 @@ project_status项目状态:
```sql ```sql
-- 项目信息表 -- 项目信息表
CREATE TABLE dpc_project ( CREATE TABLE ccdi_project (
project_id bigint(20) not null auto_increment comment '项目ID', project_id bigint(20) not null auto_increment comment '项目ID',
project_name varchar(100) not null comment '项目名称', project_name varchar(100) not null comment '项目名称',
project_desc varchar(500) default null comment '项目描述', project_desc varchar(500) default null comment '项目描述',
@@ -182,7 +182,7 @@ CREATE TABLE dpc_project (
示例: 示例:
``` ```
POST /dpc/project/list POST /ccdi/project/list
功能: 查询项目列表 功能: 查询项目列表
请求参数: 请求参数:
{ {

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 KiB

View File

@@ -0,0 +1,162 @@
# 中介黑名单导入功能修复说明
## 问题描述
在导入机构中介黑名单数据时,出现以下错误:
```
Error updating database. Cause: java.sql.SQLIntegrityConstraintViolationException: Column 'certificate_no' cannot be null
```
## 问题原因
1. **数据库约束**`ccdi_intermediary_blacklist` 表的 `certificate_no` 字段设置为 `NOT NULL`,不允许存储 null 值。
2. **代码缺陷**:在 `CcdiIntermediaryBlacklistServiceImpl.java``importEntityIntermediary` 方法中,导入机构中介时只设置了 `corpCreditCode`(统一社会信用代码),但没有设置 `certificateNo` 字段,导致该字段为 null。
3. **批量插入失败**`batchInsert` 方法明确插入 `certificate_no` 字段,当值为 null 时违反数据库约束。
## 解决方案
### 1. 代码修改
**文件**[CcdiIntermediaryBlacklistServiceImpl.java](d:\discipline-prelim-check\discipline-prelim-check\ruoyi-ccdi\src\main\java\com\ruoyi\dpc\service\impl\CcdiIntermediaryBlacklistServiceImpl.java)
**修改位置**:第 390-394 行
**修改前**
```java
// 转换为实体
CcdiIntermediaryBlacklist intermediary = new CcdiIntermediaryBlacklist();
intermediary.setName(excel.getName());
intermediary.setIntermediaryType("2");
```
**修改后**
```java
// 转换为实体
CcdiIntermediaryBlacklist intermediary = new CcdiIntermediaryBlacklist();
intermediary.setName(excel.getName());
// 对于机构中介,使用统一社会信用代码作为证件号
intermediary.setCertificateNo(excel.getCorpCreditCode());
intermediary.setIntermediaryType("2");
```
### 2. 验证逻辑增强
**文件**[CcdiIntermediaryBlacklistServiceImpl.java](d:\discipline-prelim-check\discipline-prelim-check\ruoyi-ccdi\src\main\java\com\ruoyi\dpc\service\impl\CcdiIntermediaryBlacklistServiceImpl.java)
**修改位置**:第 484-488 行
**修改前**
```java
private void validateEntityIntermediaryData(CcdiIntermediaryEntityExcel excel) {
if (StringUtils.isEmpty(excel.getName())) {
throw new RuntimeException("机构名称不能为空");
}
}
```
**修改后**
```java
private void validateEntityIntermediaryData(CcdiIntermediaryEntityExcel excel) {
if (StringUtils.isEmpty(excel.getName())) {
throw new RuntimeException("机构名称不能为空");
}
// 验证统一社会信用代码不能为空(因为会用作 certificate_no 字段)
if (StringUtils.isEmpty(excel.getCorpCreditCode())) {
throw new RuntimeException("统一社会信用代码不能为空");
}
}
```
### 3. 批量更新 XML 配置优化
**文件**[CcdiIntermediaryBlacklistMapper.xml](d:\discipline-prelim-check\discipline-prelim-check\ruoyi-ccdi\src\main\resources\mapper\dpc\CcdiIntermediaryBlacklistMapper.xml)
**修改位置**:第 125-127 行
**修改前**
```xml
<if test="item.dataSource != null">data_source = #{item.dataSource},</if>
update_by = #{item.updateBy},
update_time = #{item.updateTime}
```
**修改后**
```xml
<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}
```
## 设计说明
### 为什么使用统一社会信用代码作为证件号?
1. **数据一致性**:统一社会信用代码本身就是机构的法定证件号,将其同时存储在 `certificate_no` 字段中可以保持数据的一致性。
2. **查询便利**`certificate_no` 字段有索引,设置后可以快速查询机构中介。
3. **兼容性好**:个人中介和机构中介都使用 `certificate_no` 字段,查询逻辑更统一。
4. **不破坏现有结构**:不需要修改数据库表结构,只修改代码逻辑。
## 测试验证
### 测试用例
1. **个人中介导入**:正常导入个人中介数据,验证 `certificate_no` 字段正确存储身份证号。
2. **机构中介导入**:导入机构中介数据,验证 `certificate_no` 字段正确存储统一社会信用代码。
3. **统一社会信用代码为空**:验证当统一社会信用代码为空时,导入被正确拒绝并给出错误提示。
4. **批量更新**:验证批量更新时 `certificate_no` 字段能够正确更新。
### 测试脚本
测试脚本位于:[doc/test-data/test_import_fix.py](d:\discipline-prelim-check\discipline-prelim-check\doc\test-data\test_import_fix.py)
运行测试:
```bash
python doc/test-data/test_import_fix.py
```
## 影响范围
### 已影响的功能
- 机构中介批量导入功能
### 不影响的功能
- 个人中介导入功能
- 手动新增中介功能
- 中介查询功能
- 中介导出功能
## 注意事项
1. **数据迁移**:如果数据库中已存在机构中介数据且 `certificate_no` 为 null需要执行以下 SQL 进行数据修复:
```sql
UPDATE ccdi_intermediary_blacklist
SET certificate_no = corp_credit_code
WHERE intermediary_type = '2' AND certificate_no IS NULL AND corp_credit_code IS NOT NULL;
```
2. **Excel 模板**:确保导入模板中统一社会信用代码字段设置为必填项。
3. **前端验证**:建议在前端表单中也添加统一社会信用代码的必填验证。
## 修改文件列表
1. [CcdiIntermediaryBlacklistServiceImpl.java](d:\discipline-prelim-check\discipline-prelim-check\ruoyi-ccdi\src\main\java\com\ruoyi\dpc\service\impl\CcdiIntermediaryBlacklistServiceImpl.java) - 服务层实现
2. [CcdiIntermediaryBlacklistMapper.xml](d:\discipline-prelim-check\discipline-prelim-check\ruoyi-ccdi\src\main\resources\mapper\dpc\CcdiIntermediaryBlacklistMapper.xml) - MyBatis 映射文件
3. [test_import_fix.py](d:\discipline-prelim-check\discipline-prelim-check\doc\test-data\test_import_fix.py) - 测试脚本
## 版本历史
| 版本 | 日期 | 作者 | 说明 |
|------|------|------|------|
| 1.0 | 2026-01-29 | ruoyi | 初始版本,修复机构中介导入时 certificate_no 为 null 的问题 |

Some files were not shown because too many files have changed in this diff Show More