中介库管理

This commit is contained in:
wkc
2026-01-28 09:58:31 +08:00
parent 5b0c338b5e
commit 6946744ab9
20 changed files with 2836 additions and 0 deletions

View File

@@ -0,0 +1,441 @@
# Design: 中介人员黑名单管理模块
## 数据库设计
### 表dpc_intermediary_blacklist
中介人员/机构黑名单主表。
```sql
CREATE TABLE `dpc_intermediary_blacklist` (
`intermediary_id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '中介ID',
`name` VARCHAR(100) NOT NULL COMMENT '姓名/机构名称',
`certificate_no` VARCHAR(50) DEFAULT NULL COMMENT '证件号',
`intermediary_type` CHAR(1) NOT NULL DEFAULT '1' COMMENT '中介类型1个人 2机构',
`status` CHAR(1) NOT NULL DEFAULT '0' COMMENT '状态0正常 1停用',
`remark` VARCHAR(500) DEFAULT NULL COMMENT '备注',
`create_by` VARCHAR(64) DEFAULT '' COMMENT '创建者',
`create_time` DATETIME DEFAULT NULL COMMENT '创建时间',
`update_by` VARCHAR(64) DEFAULT '' COMMENT '更新者',
`update_time` DATETIME DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`intermediary_id`),
KEY `idx_name` (`name`),
KEY `idx_certificate_no` (`certificate_no`),
KEY `idx_intermediary_type` (`intermediary_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='中介人员黑名单表';
```
### 字段说明
| 字段名 | 类型 | 说明 | 必填 | 默认值 |
|-------|------|------|-----|-------|
| intermediary_id | BIGINT | 中介ID主键 | 是 | 自增 |
| name | VARCHAR(100) | 姓名/机构名称 | 是 | - |
| certificate_no | VARCHAR(50) | 证件号 | 否 | NULL |
| intermediary_type | CHAR(1) | 中介类型1个人 2机构 | 是 | '1' |
| status | CHAR(1) | 状态0正常 1停用 | 是 | '0' |
| remark | VARCHAR(500) | 备注 | 否 | NULL |
| create_by | VARCHAR(64) | 创建者 | 是 | - |
| create_time | DATETIME | 创建时间 | 是 | - |
| update_by | VARCHAR(64) | 更新者 | 否 | '' |
| update_time | DATETIME | 更新时间 | 否 | NULL |
### 索引设计
- 主键索引:`intermediary_id`
- 普通索引:`name`(支持按名称搜索)
- 普通索引:`certificate_no`(支持按证件号精确匹配)
- 普通索引:`intermediary_type`(支持按类型筛选)
## 后端设计
### 模块结构
```
ruoyi-dpc/
├── src/main/java/com/ruoyi/dpc/
│ ├── controller/
│ │ └── DpcIntermediaryBlacklistController.java
│ ├── domain/
│ │ ├── DpcIntermediaryBlacklist.java
│ │ ├── dto/
│ │ │ ├── DpcIntermediaryBlacklistAddDTO.java
│ │ │ ├── DpcIntermediaryBlacklistEditDTO.java
│ │ │ └── DpcIntermediaryBlacklistQueryDTO.java
│ │ └── vo/
│ │ └── DpcIntermediaryBlacklistVO.java
│ ├── mapper/
│ │ └── DpcIntermediaryBlacklistMapper.java
│ └── service/
│ ├── IDpcIntermediaryBlacklistService.java
│ └── impl/
│ └── DpcIntermediaryBlacklistServiceImpl.java
└── src/main/resources/mapper/dpc/
└── DpcIntermediaryBlacklistMapper.xml
```
### Controller 层设计
**DpcIntermediaryBlacklistController**
```java
@RestController
@RequestMapping("/dpc/intermediary")
public class DpcIntermediaryBlacklistController extends BaseController {
/**
* 查询中介黑名单列表
*/
@PreAuthorize("@ss.hasPermi('dpc:intermediary:list')")
@GetMapping("/list")
public TableDataInfo list(DpcIntermediaryBlacklistQueryDTO queryDTO) {
// 分页查询逻辑
}
/**
* 导出中介黑名单列表
*/
@PreAuthorize("@ss.hasPermi('dpc:intermediary:export')")
@Log(title = "中介黑名单", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, DpcIntermediaryBlacklistQueryDTO queryDTO) {
// 导出逻辑
}
/**
* 获取中介黑名单详细信息
*/
@PreAuthorize("@ss.hasPermi('dpc:intermediary:query')")
@GetMapping(value = "/{intermediaryId}")
public AjaxResult getInfo(@PathVariable Long intermediaryId) {
// 查询详情逻辑
}
/**
* 新增中介黑名单
*/
@PreAuthorize("@ss.hasPermi('dpc:intermediary:add')")
@Log(title = "中介黑名单", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@Validated @RequestBody DpcIntermediaryBlacklistAddDTO addDTO) {
// 新增逻辑
}
/**
* 修改中介黑名单
*/
@PreAuthorize("@ss.hasPermi('dpc:intermediary:edit')")
@Log(title = "中介黑名单", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@Validated @RequestBody DpcIntermediaryBlacklistEditDTO editDTO) {
// 修改逻辑
}
/**
* 删除中介黑名单
*/
@PreAuthorize("@ss.hasPermi('dpc:intermediary:remove')")
@Log(title = "中介黑名单", businessType = BusinessType.DELETE)
@DeleteMapping("/{intermediaryIds}")
public AjaxResult remove(@PathVariable Long[] intermediaryIds) {
// 删除逻辑
}
/**
* 下载导入模板
*/
@PostMapping("/importTemplate")
public void importTemplate(HttpServletResponse response) {
// 生成 Excel 模板
}
/**
* 导入中介黑名单
*/
@PreAuthorize("@ss.hasPermi('dpc:intermediary:import')")
@Log(title = "中介黑名单", businessType = BusinessType.IMPORT)
@PostMapping("/importData")
public AjaxResult importData(MultipartFile file) {
// 导入逻辑
}
}
```
### Service 层设计
**IDpcIntermediaryBlacklistService**
```java
public interface IDpcIntermediaryBlacklistService {
/**
* 查询中介黑名单列表
*/
List<DpcIntermediaryBlacklistVO> selectIntermediaryList(DpcIntermediaryBlacklistQueryDTO queryDTO);
/**
* 查询中介黑名单详细信息
*/
DpcIntermediaryBlacklistVO selectIntermediaryById(Long intermediaryId);
/**
* 新增中介黑名单
*/
int insertIntermediary(DpcIntermediaryBlacklistAddDTO addDTO);
/**
* 修改中介黑名单
*/
int updateIntermediary(DpcIntermediaryBlacklistEditDTO editDTO);
/**
* 批量删除中介黑名单
*/
int deleteIntermediaryByIds(Long[] intermediaryIds);
/**
* 导入中介黑名单数据
*/
String importIntermediary(List<DpcIntermediaryBlacklistAddDTO> addDTOList, boolean isUpdateSupport);
}
```
### Domain 层设计
**实体类注解**
```java
public class DpcIntermediaryBlacklist {
/** 中介ID */
private Long intermediaryId;
/** 姓名/机构名称 */
@Excel(name = "姓名/机构名称")
private String name;
/** 证件号 */
@Excel(name = "证件号")
private String certificateNo;
/** 中介类型 */
@Excel(name = "中介类型", readConverterExp = "1=个人,2=机构")
private String intermediaryType;
/** 状态 */
@Excel(name = "状态", readConverterExp = "0=正常,1=停用")
private String status;
/** 备注 */
@Excel(name = "备注")
private String remark;
/** 创建者 */
private String createBy;
/** 创建时间 */
private Date createTime;
/** 更新者 */
private String updateBy;
/** 更新时间 */
private Date updateTime;
}
```
## 前端设计
### 页面结构
```
ruoyi-ui/src/views/dpcIntermediary/
├── index.vue # 主页面(列表 + 搜索)
└── components/
└── form-dialog.vue # 新增/编辑对话框
```
### 主要功能组件
**1. 搜索区**
- 按姓名/机构名称搜索(模糊)
- 按证件号搜索(精确)
- 按中介类型筛选(下拉:全部/个人/机构)
- 按状态筛选(下拉:全部/正常/停用)
**2. 操作按钮区**
- 新增按钮
- 导入按钮
- 导出按钮
- 下载模板按钮
**3. 数据表格**
- 列:姓名/机构名称、证件号、中介类型、状态、创建时间、操作
- 操作列:编辑、删除
**4. 新增/编辑对话框**
- 姓名/机构名称(必填)
- 证件号(选填)
- 中介类型(必填,单选:个人/机构)
- 状态(必填,单选:正常/停用)
- 备注(选填,文本域)
**5. 导入对话框**
- 上传 Excel 文件
- 显示导入结果(成功/失败数量)
- 显示错误详情(如有)
### API 设计
**dpcIntermediary.js**
```javascript
import request from '@/utils/request'
// 查询中介黑名单列表
export function listIntermediary(query) {
return request({
url: '/dpc/intermediary/list',
method: 'get',
params: query
})
}
// 查询中介黑名单详细
export function getIntermediary(intermediaryId) {
return request({
url: '/dpc/intermediary/' + intermediaryId,
method: 'get'
})
}
// 新增中介黑名单
export function addIntermediary(data) {
return request({
url: '/dpc/intermediary',
method: 'post',
data: data
})
}
// 修改中介黑名单
export function updateIntermediary(data) {
return request({
url: '/dpc/intermediary',
method: 'put',
data: data
})
}
// 删除中介黑名单
export function delIntermediary(intermediaryIds) {
return request({
url: '/dpc/intermediary/' + intermediaryIds,
method: 'delete'
})
}
// 导出中介黑名单
export function exportIntermediary(query) {
return request({
url: '/dpc/intermediary/export',
method: 'post',
params: query
})
}
// 下载导入模板
export function importTemplate() {
return request({
url: '/dpc/intermediary/importTemplate',
method: 'post'
})
}
// 导入中介黑名单
export function importData(data) {
return request({
url: '/dpc/intermediary/importData',
method: 'post',
data: data
})
}
```
## Excel 导入导出设计
### Excel 模板格式
| 姓名/机构名称 | 证件号 | 中介类型 | 状态 | 备注 |
|-------------|-------|---------|------|------|
| 张三 | 110101199001011234 | 个人 | 正常 | 测试数据 |
| XX中介公司 | 91110000XXXXXXXXXX | 机构 | 正常 | - |
### 导入数据验证规则
1. **姓名/机构名称**:必填,长度 1-100 字符
2. **证件号**:选填,长度不超过 50 字符
3. **中介类型**:必填,只能填"个人"或"机构"
4. **状态**:必填,只能填"正常"或"停用"
5. **备注**:选填,长度不超过 500 字符
### 导入错误处理
- 记录每一行的错误信息
- 返回导入结果统计(成功数、失败数)
- 失败数据不写入数据库
- 支持更新模式(可选)
## 权限设计
| 权限标识 | 说明 | 对应接口 |
|---------|------|---------|
| dpc:intermediary:list | 查询中介黑名单列表 | GET /dpc/intermediary/list |
| dpc:intermediary:query | 查询中介黑名单详情 | GET /dpc/intermediary/{id} |
| dpc:intermediary:add | 新增中介黑名单 | POST /dpc/intermediary |
| dpc:intermediary:edit | 修改中介黑名单 | PUT /dpc/intermediary |
| dpc:intermediary:remove | 删除中介黑名单 | DELETE /dpc/intermediary/{ids} |
| dpc:intermediary:export | 导出中介黑名单 | POST /dpc/intermediary/export |
| dpc:intermediary:import | 导入中介黑名单 | POST /dpc/intermediary/importData |
## 菜单设计
在系统菜单表中添加以下菜单记录:
```sql
-- 一级菜单:信息维护
INSERT INTO sys_menu VALUES (
2000, '信息维护', NULL, 1, 0, 'dpc', NULL, 1, 0, 'M', '0', '0', '', 'example', 'admin', NOW(), '', NULL, '信息维护目录'
);
-- 二级菜单:中介库管理
INSERT INTO sys_menu VALUES (
2001, '中介库管理', 2000, 1, 0, 'intermediary', 'dpcIntermediary/index', 1, 0, 'C', '0', '0', 'dpc:intermediary:list', 'user', 'admin', NOW(), '', NULL, '中介库管理菜单'
);
-- 中介库管理按钮权限
INSERT INTO sys_menu VALUES (2002, '中介查询', 2001, 1, 0, '', '', 1, 0, 'F', '0', '0', 'dpc:intermediary:query', '#', 'admin', NOW(), '', NULL, '');
INSERT INTO sys_menu VALUES (2003, '中介新增', 2001, 2, 0, '', '', 1, 0, 'F', '0', '0', 'dpc:intermediary:add', '#', 'admin', NOW(), '', NULL, '');
INSERT INTO sys_menu VALUES (2004, '中介修改', 2001, 3, 0, '', '', 1, 0, 'F', '0', '0', 'dpc:intermediary:edit', '#', 'admin', NOW(), '', NULL, '');
INSERT INTO sys_menu VALUES (2005, '中介删除', 2001, 4, 0, '', '', 1, 0, 'F', '0', '0', 'dpc:intermediary:remove', '#', 'admin', NOW(), '', NULL, '');
INSERT INTO sys_menu VALUES (2006, '中介导出', 2001, 5, 0, '', '', 1, 0, 'F', '0', '0', 'dpc:intermediary:export', '#', 'admin', NOW(), '', NULL, '');
INSERT INTO sys_menu VALUES (2007, '中介导入', 2001, 6, 0, '', '', 1, 0, 'F', '0', '0', 'dpc:intermediary:import', '#', 'admin', NOW(), '', NULL, '');
```
## 字典数据设计
### 中介类型dpc_intermediary_type
| 字典值 | 字典标签 | 排序 | 状态 |
|-------|---------|-----|------|
| 1 | 个人 | 1 | 正常 |
| 2 | 机构 | 2 | 正常 |
## 技术约束
1. **后端框架**Spring Boot 3.5.8
2. **ORM 框架**MyBatis 3.0.5
3. **Excel 处理**EasyExcel 3.3.4(依赖 `replace-poi-with-easyexcel` change
4. **前端框架**Vue 2.6.12 + Element UI 2.15.14
5. **数据库**MySQL 8.2.0
6. **字符编码**UTF-8utf8mb4

View File

@@ -0,0 +1,124 @@
# Proposal: 添加中介人员黑名单管理模块
## Change ID
`add-intermediary-blacklist`
## Summary
添加中介人员黑名单管理模块,实现外部中介人员/机构黑名单库的建立和维护。该模块支持 Excel 模板下载、批量导入、增删改查等功能,是系统中信息维护模块的核心子功能之一。
## Motivation
目前系统缺少中介人员黑名单管理功能。用户需要:
1. 建立并维护外部中介人员/机构黑名单库
2. 通过 Excel 批量导入中介名单数据
3. 对中介名单进行增、删、改、查操作
4. 支持按姓名、证件号、机构名称等条件查询
5. 在项目工作台中选择确认后的可疑名单
6. 当员工交易对手命中该库时,系统自动产生高风险预警
## Scope
本提案实现以下功能:
### 包含的功能
- **3.1.1 名单导入**
- Excel 模板下载(包含必填字段示例)
- Excel 批量导入中介名单
- 导入数据验证与错误提示
- **3.1.2 名单维护**
- 新增中介信息(个人/机构)
- 编辑中介信息
- 删除中介信息(带使用检查)
- 批量删除
- **3.1.3 名单查询**
- 按姓名/机构名称模糊搜索
- 按证件号精确搜索
- 按中介类型筛选(个人/机构)
- 按状态筛选(有效/失效)
- **3.1.4 名单导出**
- 导出当前查询结果为 Excel
### 明确排除
- **3.1.5 名单选择**(在项目工作台中选择名单的功能,属于项目工作台模块)
- **3.1.6 自动预警**(命中黑名单产生预警的功能,属于风险分析模块)
## Proposed Design
详见 [design.md](./design.md)
## Alternatives Considered
### 选项1使用若依代码生成器
**优点**
- 快速生成标准 CRUD 代码
- 自动生成前端页面和 API
- 符合项目基本规范
**缺点**
- 需要手动调整 Excel 导入导出逻辑
- 需要手动添加数据验证规则
- 需要手动处理个人/机构两种类型的差异显示
**决定**:部分采用。使用代码生成器生成基础 CRUD 代码,然后手动添加 Excel 导入导出和业务验证逻辑。
### 选项2完全自定义开发
**优点**
- 完全控制实现细节
- 可以根据业务需求灵活定制
**缺点**
- 开发周期较长
- 需要确保代码风格与若依框架一致
**决定**:不采用。中介黑名单管理是标准 CRUD 功能,使用代码生成器可提高开发效率。
## Impact
### 后端影响
- 新建 `ruoyi-dpc` 模块(如果不存在),与若依框架代码分离
- 新增表:`dpc_intermediary_blacklist`(中介黑名单主表)
- 新增权限:`dpc:intermediary:list`, `dpc:intermediary:query`, `dpc:intermediary:add`, `dpc:intermediary:edit`, `dpc:intermediary:remove`, `dpc:intermediary:export`, `dpc:intermediary:import`
- Controller 层:`ruoyi-dpc/src/main/java/com/ruoyi/dpc/controller/DpcIntermediaryBlacklistController.java`
### 前端影响
- 新增视图:`ruoyi-ui/src/views/dpcIntermediary/`
- 新增 API`ruoyi-ui/src/api/dpcIntermediary.js`
- 新增菜单:信息维护 > 中介库管理(注意与数据库中菜单表进行联动修改)
### 数据库影响
- 新增表:`dpc_intermediary_blacklist`
## Dependencies
- 依赖 EasyExcel 进行 Excel 导入导出(参考 `replace-poi-with-easyexcel` change
- 依赖若依框架的文件上传功能
- 依赖若依框架的权限系统
## Related Changes
- `replace-poi-with-easyexcel` - 依赖 EasyExcel 替换完成后的 Excel 工具
## Open Questions
1. **证件号校验**
- 是否需要添加格式校验?
- 建议:添加基本格式校验,但不强制要求(可能是历史数据)
2. **删除前的使用检查**
- 如何判断中介信息是否在项目中使用?
- 建议:暂时不实现使用检查,允许直接删除(可在后续版本中添加关联表)
3. **中介类型的数据结构**
- 个人和机构是否分开存储?
- 建议:使用同一张表,通过 `intermediary_type` 字段区分
## Success Criteria
- [ ] 用户可以下载 Excel 导入模板
- [ ] 用户可以通过 Excel 批量导入中介名单
- [ ] 用户可以新增中介信息(个人/机构)
- [ ] 用户可以编辑中介信息
- [ ] 用户可以删除中介信息
- [ ] 用户可以按多种条件查询中介名单
- [ ] 用户可以导出查询结果为 Excel
- [ ] 导入时进行数据验证并提示错误
## References
- [模块设计文档](../../../doc/modules/03-信息维护模块.md)
- [若依开发文档](https://doc.ruoyi.vip/)

View File

@@ -0,0 +1,388 @@
# Spec: 中介人员黑名单管理
## ADDED Requirements
### Requirement: 系统SHALL支持查询中介黑名单列表
系统MUST提供查询功能允许用户查询系统中已维护的中介人员/机构黑名单列表,以便了解当前黑名单库的内容。
#### Scenario: 分页查询中介黑名单列表
**Given** 用户已登录系统且具有 `dpc:intermediary:list` 权限
**When** 用户访问中介库管理页面
**Then** 系统应显示中介黑名单列表,支持分页展示
#### Scenario: 按名称模糊搜索中介黑名单
**Given** 用户已登录系统且具有 `dpc:intermediary:list` 权限
**And** 系统中存在姓名为"张三"的中介人员
**When** 用户在搜索框输入"张"并点击搜索
**Then** 系统应返回所有姓名中包含"张"的中介记录
#### Scenario: 按证件号精确搜索中介黑名单
**Given** 用户已登录系统且具有 `dpc:intermediary:list` 权限
**And** 系统中存在证件号为"110101199001011234"的中介人员
**When** 用户在搜索框输入"110101199001011234"并点击搜索
**Then** 系统应返回该证件号对应的中介记录
#### Scenario: 按中介类型筛选中介黑名单
**Given** 用户已登录系统且具有 `dpc:intermediary:list` 权限
**And** 系统中存在个人和机构两种类型的中介记录
**When** 用户选择中介类型为"个人"并点击搜索
**Then** 系统应仅返回中介类型为"个人"的记录
#### Scenario: 按状态筛选中介黑名单
**Given** 用户已登录系统且具有 `dpc:intermediary:list` 权限
**And** 系统中存在正常和停用两种状态的中介记录
**When** 用户选择状态为"正常"并点击搜索
**Then** 系统应仅返回状态为"正常"的记录
#### Scenario: 组合条件查询中介黑名单
**Given** 用户已登录系统且具有 `dpc:intermediary:list` 权限
**When** 用户同时输入名称"张"、选择中介类型为"个人"、选择状态为"正常"并点击搜索
**Then** 系统应返回同时满足所有条件的记录
---
### Requirement: 系统SHALL支持新增中介黑名单
系统MUST提供新增功能允许用户手动添加中介人员或机构到黑名单中以建立和维护黑名单库。
#### Scenario: 新增个人类型的中介黑名单
**Given** 用户已登录系统且具有 `dpc:intermediary:add` 权限
**When** 用户点击"新增"按钮
**And** 填写姓名为"张三"
**And** 填写证件号为"110101199001011234"
**And** 选择中介类型为"个人"
**And** 选择状态为"正常"
**And** 点击"确定"按钮
**Then** 系统应保存中介信息并提示"操作成功"
**And** 列表中应显示新增的记录
#### Scenario: 新增机构类型的中介黑名单
**Given** 用户已登录系统且具有 `dpc:intermediary:add` 权限
**When** 用户点击"新增"按钮
**And** 填写机构名称为"XX中介公司"
**And** 填写证件号为"91110000XXXXXXXXXX"
**And** 选择中介类型为"机构"
**And** 选择状态为"正常"
**And** 点击"确定"按钮
**Then** 系统应保存中介信息并提示"操作成功"
**And** 列表中应显示新增的记录
#### Scenario: 新增时不填写证件号
**Given** 用户已登录系统且具有 `dpc:intermediary:add` 权限
**When** 用户点击"新增"按钮
**And** 仅填写姓名为"张三"
**And** 不填写证件号
**And** 选择中介类型为"个人"
**And** 选择状态为"正常"
**And** 点击"确定"按钮
**Then** 系统应保存中介信息并提示"操作成功"
#### Scenario: 新增时姓名为空应校验失败
**Given** 用户已登录系统且具有 `dpc:intermediary:add` 权限
**When** 用户点击"新增"按钮
**And** 不填写姓名
**And** 点击"确定"按钮
**Then** 系统应提示"姓名/机构名称不能为空"
**And** 不保存数据
#### Scenario: 新增时姓名超过100字符应校验失败
**Given** 用户已登录系统且具有 `dpc:intermediary:add` 权限
**When** 用户点击"新增"按钮
**And** 填写姓名为101个字符的字符串
**And** 点击"确定"按钮
**Then** 系统应提示"姓名/机构名称长度不能超过100个字符"
**And** 不保存数据
#### Scenario: 新增时填写备注信息
**Given** 用户已登录系统且具有 `dpc:intermediary:add` 权限
**When** 用户点击"新增"按钮
**And** 填写必填信息
**And** 填写备注为"涉及多起违规交易"
**And** 点击"确定"按钮
**Then** 系统应保存中介信息及备注
**And** 列表中应显示新增的记录
---
### Requirement: 系统SHALL支持编辑中介黑名单
系统MUST提供编辑功能允许用户修改已存在的中介黑名单信息以更新或纠正数据。
#### Scenario: 编辑中介黑名单的基本信息
**Given** 用户已登录系统且具有 `dpc:intermediary:edit` 权限
**And** 系统中存在一条中介记录
**When** 用户点击该记录的"编辑"按钮
**And** 修改姓名为"李四"
**And** 点击"确定"按钮
**Then** 系统应更新中介信息并提示"操作成功"
**And** 列表中应显示更新后的姓名
#### Scenario: 编辑中介黑名单的证件号
**Given** 用户已登录系统且具有 `dpc:intermediary:edit` 权限
**And** 系统中存在一条中介记录
**When** 用户点击该记录的"编辑"按钮
**And** 修改证件号为"110101199001011235"
**And** 点击"确定"按钮
**Then** 系统应更新证件号并提示"操作成功"
#### Scenario: 编辑中介黑名单的状态为停用
**Given** 用户已登录系统且具有 `dpc:intermediary:edit` 权限
**And** 系统中存在一条状态为"正常"的中介记录
**When** 用户点击该记录的"编辑"按钮
**And** 修改状态为"停用"
**And** 点击"确定"按钮
**Then** 系统应更新状态并提示"操作成功"
**And** 该记录在列表中应显示为"停用"状态
#### Scenario: 编辑时姓名为空应校验失败
**Given** 用户已登录系统且具有 `dpc:intermediary:edit` 权限
**And** 系统中存在一条中介记录
**When** 用户点击该记录的"编辑"按钮
**And** 清空姓名字段
**And** 点击"确定"按钮
**Then** 系统应提示"姓名/机构名称不能为空"
**And** 不更新数据
---
### Requirement: 系统SHALL支持删除中介黑名单
系统MUST提供删除功能允许用户删除不再需要的中介黑名单记录以保持黑名单库的准确性。
#### Scenario: 删除单条中介黑名单记录
**Given** 用户已登录系统且具有 `dpc:intermediary:remove` 权限
**And** 系统中存在一条中介记录
**When** 用户点击该记录的"删除"按钮
**And** 确认删除操作
**Then** 系统应删除该记录并提示"操作成功"
**And** 列表中不再显示该记录
#### Scenario: 批量删除中介黑名单记录
**Given** 用户已登录系统且具有 `dpc:intermediary:remove` 权限
**And** 系统中存在多条中介记录
**When** 用户勾选3条记录
**And** 点击"删除"按钮
**And** 确认删除操作
**Then** 系统应删除选中的3条记录并提示"操作成功"
**And** 列表中不再显示这3条记录
---
### Requirement: 系统SHALL支持导出中介黑名单
系统MUST提供导出功能允许用户将查询结果导出为 Excel 文件,以便进行离线分析或备份。
#### Scenario: 导出所有中介黑名单数据
**Given** 用户已登录系统且具有 `dpc:intermediary:export` 权限
**And** 系统中存在100条中介记录
**When** 用户点击"导出"按钮
**And** 不设置任何筛选条件
**Then** 系统应生成包含100条记录的 Excel 文件并下载
#### Scenario: 导出筛选后的中介黑名单数据
**Given** 用户已登录系统且具有 `dpc:intermediary:export` 权限
**And** 系统中存在个人和机构两种类型的中介记录
**When** 用户筛选中介类型为"个人"
**And** 点击"导出"按钮
**Then** 系统应生成仅包含个人类型记录的 Excel 文件并下载
#### Scenario: 导出的 Excel 文件格式正确
**Given** 用户已登录系统且具有 `dpc:intermediary:export` 权限
**When** 用户点击"导出"按钮
**Then** Excel 文件应包含以下列:姓名/机构名称、证件号、中介类型、状态、备注、创建时间
**And** 表头应使用中文显示
**And** 数据应正确显示(中介类型、状态应显示中文而非数字)
---
### Requirement: 系统SHALL支持下载 Excel 导入模板
系统MUST提供模板下载功能允许用户下载标准的 Excel 导入模板,以便按照模板格式准备数据后批量导入。
#### Scenario: 下载导入模板
**Given** 用户已登录系统且具有 `dpc:intermediary:import` 权限
**When** 用户点击"下载模板"按钮
**Then** 系统应生成 Excel 模板文件并下载
**And** 模板应包含示例数据行
**And** 模板应包含以下列:姓名/机构名称、证件号、中介类型、状态、备注
#### Scenario: 模板中的示例数据正确
**Given** 用户已登录系统且具有 `dpc:intermediary:import` 权限
**When** 用户下载导入模板
**Then** 模板应包含至少一行示例数据
**And** 示例数据应展示正确的填写格式
**And** 中介类型示例应为"个人"或"机构"
**And** 状态示例应为"正常"或"停用"
---
### Requirement: 系统SHALL支持通过 Excel 批量导入中介黑名单
系统MUST提供批量导入功能允许用户通过 Excel 文件批量导入中介黑名单数据,以提高数据录入效率。
#### Scenario: 导入包含有效数据的 Excel 文件
**Given** 用户已登录系统且具有 `dpc:intermediary:import` 权限
**And** 用户已准备好包含10条有效数据的 Excel 文件
**When** 用户点击"导入"按钮
**And** 选择准备好的 Excel 文件
**And** 点击"确定"
**Then** 系统应导入10条记录并提示"成功导入10条数据"
**And** 列表中应显示这10条新增记录
#### Scenario: 导入时部分数据格式错误
**Given** 用户已登录系统且具有 `dpc:intermediary:import` 权限
**And** 用户准备的 Excel 文件包含10条数据
**And** 其中2条数据的姓名字段为空
**When** 用户点击"导入"按钮
**And** 选择 Excel 文件
**And** 点击"确定"
**Then** 系统应仅导入8条有效数据
**And** 提示"成功导入8条数据失败2条数据"
**And** 显示失败行的错误详情
#### Scenario: 导入时中介类型值不在允许范围内
**Given** 用户已登录系统且具有 `dpc:intermediary:import` 权限
**And** 用户准备的 Excel 文件中某条记录的中介类型填写为"未知"
**When** 用户点击"导入"按钮
**And** 选择 Excel 文件
**And** 点击"确定"
**Then** 系统应提示该行数据"中介类型只能填写'个人'或'机构'"
**And** 该行数据不被导入
#### Scenario: 导入时状态值不在允许范围内
**Given** 用户已登录系统且具有 `dpc:intermediary:import` 权限
**And** 用户准备的 Excel 文件中某条记录的状态填写为"未知"
**When** 用户点击"导入"按钮
**And** 选择 Excel 文件
**And** 点击"确定"
**Then** 系统应提示该行数据"状态只能填写'正常'或'停用'"
**And** 该行数据不被导入
#### Scenario: 导入时证件号超过50字符
**Given** 用户已登录系统且具有 `dpc:intermediary:import` 权限
**And** 用户准备的 Excel 文件中某条记录的证件号为51个字符
**When** 用户点击"导入"按钮
**And** 选择 Excel 文件
**And** 点击"确定"
**Then** 系统应提示该行数据"证件号长度不能超过50个字符"
**And** 该行数据不被导入
#### Scenario: 导入时备注超过500字符
**Given** 用户已登录系统且具有 `dpc:intermediary:import` 权限
**And** 用户准备的 Excel 文件中某条记录的备注为501个字符
**When** 用户点击"导入"按钮
**And** 选择 Excel 文件
**And** 点击"确定"
**Then** 系统应提示该行数据"备注长度不能超过500个字符"
**And** 该行数据不被导入
#### Scenario: 导入时选择更新支持模式
**Given** 用户已登录系统且具有 `dpc:intermediary:import` 权限
**And** 系统中已存在一条证件号为"110101199001011234"的记录
**And** 用户准备的 Excel 文件包含相同证件号的记录但姓名不同
**When** 用户点击"导入"按钮
**And** 选择 Excel 文件
**And** 勾选"更新已存在数据"选项
**And** 点击"确定"
**Then** 系统应更新该证件号对应的记录
**And** 提示包含更新成功的消息
---
### Requirement: 系统SHALL验证用户权限
系统MUST根据用户的角色和权限控制其对中介黑名单功能的访问确保未授权用户无法执行相应操作。
#### Scenario: 无权限用户访问列表应被拒绝
**Given** 用户已登录系统
**And** 该用户不具有 `dpc:intermediary:list` 权限
**When** 用户尝试访问中介库管理页面
**Then** 系统应提示"您没有权限执行此操作"
**And** 不显示列表数据
#### Scenario: 无权限用户尝试新增应被拒绝
**Given** 用户已登录系统
**And** 该用户不具有 `dpc:intermediary:add` 权限
**When** 用户尝试点击"新增"按钮
**Then** 系统应隐藏或禁用"新增"按钮
#### Scenario: 无权限用户尝试导出应被拒绝
**Given** 用户已登录系统
**And** 该用户不具有 `dpc:intermediary:export` 权限
**When** 用户尝试点击"导出"按钮
**Then** 系统应隐藏或禁用"导出"按钮
#### Scenario: 无权限用户尝试导入应被拒绝
**Given** 用户已登录系统
**And** 该用户不具有 `dpc:intermediary:import` 权限
**When** 用户尝试点击"导入"按钮
**Then** 系统应隐藏或禁用"导入"按钮
---
### Requirement: 系统SHALL记录操作日志
系统MUST记录用户对中介黑名单的关键操作包括新增、修改、删除、导入等操作以便审计和追溯。
#### Scenario: 新增操作应记录日志
**Given** 用户已登录系统且具有 `dpc:intermediary:add` 权限
**When** 用户成功新增一条中介记录
**Then** 系统应在操作日志中记录
**And** 日志应包含:操作人、操作时间、操作类型、操作内容
#### Scenario: 修改操作应记录日志
**Given** 用户已登录系统且具有 `dpc:intermediary:edit` 权限
**When** 用户成功修改一条中介记录
**Then** 系统应在操作日志中记录
**And** 日志应包含:操作人、操作时间、操作类型、修改内容
#### Scenario: 删除操作应记录日志
**Given** 用户已登录系统且具有 `dpc:intermediary:remove` 权限
**When** 用户成功删除一条中介记录
**Then** 系统应在操作日志中记录
**And** 日志应包含操作人、操作时间、操作类型、删除的记录ID
#### Scenario: 导入操作应记录日志
**Given** 用户已登录系统且具有 `dpc:intermediary:import` 权限
**When** 用户成功导入中介数据
**Then** 系统应在操作日志中记录
**And** 日志应包含:操作人、操作时间、操作类型、导入数量

View File

@@ -0,0 +1,219 @@
# Tasks: 添加中介人员黑名单管理模块
## 环境准备
- [ ] 1.1 确认 `replace-poi-with-easyexcel` change 已完成EasyExcel 依赖可用)
- [ ] 1.2 创建 `ruoyi-dpc` 模块目录结构(如果不存在)
- [ ] 1.3 在父 pom.xml 中添加 `ruoyi-dpc` 模块声明(如果不存在)
## 数据库设计
- [ ] 2.1 编写数据库建表 SQL
- [ ] 2.1.1 创建 `dpc_intermediary_blacklist`
- [ ] 2.1.2 添加索引name, id_card, intermediary_type
- [ ] 2.1.3 添加表注释和字段注释
- [ ] 2.2 编写菜单权限 SQL
- [ ] 2.2.1 添加"信息维护"一级菜单menu_id: 2000
- [ ] 2.2.2 添加"中介库管理"二级菜单menu_id: 2001
- [ ] 2.2.3 添加按钮权限(查询、新增、修改、删除、导出、导入)
- [ ] 2.3 编写字典数据 SQL
- [ ] 2.3.1 添加"中介类型"字典dpc_intermediary_type
- [ ] 2.3.2 添加"风险等级"字典dpc_risk_level
- [ ] 2.4 执行 SQL 脚本初始化数据
## 后端开发
- [ ] 3.1 创建 Domain 层
- [ ] 3.1.1 创建 `DpcIntermediaryBlacklist.java` 实体类
- [ ] 3.1.2 创建 `DpcIntermediaryBlacklistAddDTO.java` 新增 DTO
- [ ] 3.1.3 创建 `DpcIntermediaryBlacklistEditDTO.java` 编辑 DTO
- [ ] 3.1.4 创建 `DpcIntermediaryBlacklistQueryDTO.java` 查询 DTO
- [ ] 3.1.5 创建 `DpcIntermediaryBlacklistVO.java` 视图对象
- [ ] 3.1.6 添加 `@Excel` 注解支持导入导出
- [ ] 3.2 创建 Mapper 层
- [ ] 3.2.1 创建 `DpcIntermediaryBlacklistMapper.java` 接口
- [ ] 3.2.2 创建 `DpcIntermediaryBlacklistMapper.xml` 映射文件
- [ ] 3.2.3 实现 `selectIntermediaryList` 方法(支持条件查询)
- [ ] 3.2.4 实现 `selectIntermediaryById` 方法
- [ ] 3.2.5 实现 `insertIntermediary` 方法
- [ ] 3.2.6 实现 `updateIntermediary` 方法
- [ ] 3.2.7 实现 `deleteIntermediaryByIds` 方法
- [ ] 3.3 创建 Service 层
- [ ] 3.3.1 创建 `IDpcIntermediaryBlacklistService.java` 接口
- [ ] 3.3.2 创建 `DpcIntermediaryBlacklistServiceImpl.java` 实现类
- [ ] 3.3.3 实现查询列表业务逻辑(分页)
- [ ] 3.3.4 实现查询详情业务逻辑
- [ ] 3.3.5 实现新增业务逻辑(含数据校验)
- [ ] 3.3.6 实现修改业务逻辑(含数据校验)
- [ ] 3.3.7 实现删除业务逻辑
- [ ] 3.3.8 实现导出业务逻辑
- [ ] 3.3.9 实现导入业务逻辑(含数据验证)
- [ ] 3.4 创建 Controller 层
- [ ] 3.4.1 创建 `DpcIntermediaryBlacklistController.java`
- [ ] 3.4.2 实现 `list` 接口(查询列表)
- [ ] 3.4.3 实现 `getInfo` 接口(查询详情)
- [ ] 3.4.4 实现 `add` 接口(新增)
- [ ] 3.4.5 实现 `edit` 接口(修改)
- [ ] 3.4.6 实现 `remove` 接口(删除)
- [ ] 3.4.7 实现 `export` 接口(导出 Excel
- [ ] 3.4.8 实现 `importTemplate` 接口(下载模板)
- [ ] 3.4.9 实现 `importData` 接口(导入 Excel
- [ ] 3.4.10 添加 `@PreAuthorize` 权限注解
- [ ] 3.4.11 添加 `@Log` 操作日志注解
- [ ] 3.5 实现数据验证逻辑
- [ ] 3.5.1 姓名必填校验
- [ ] 3.5.2 姓名长度校验1-100字符
- [ ] 3.5.3 身份证号长度校验最大50字符
- [ ] 3.5.4 中介类型枚举校验1=个人2=机构)
- [ ] 3.5.5 风险等级枚举校验1=高2=中3=低)
- [ ] 3.5.6 状态枚举校验0=正常1=停用)
- [ ] 3.5.7 备注长度校验最大500字符
- [ ] 3.6 实现 Excel 导入导出功能
- [ ] 3.6.1 生成导入模板(带示例数据)
- [ ] 3.6.2 实现 Excel 数据读取
- [ ] 3.6.3 实现导入数据验证
- [ ] 3.6.4 实现导入错误提示
- [ ] 3.6.5 实现批量插入数据
- [ ] 3.6.6 实现 Excel 数据导出
- [ ] 3.6.7 支持按查询条件导出
## 前端开发
- [ ] 4.1 创建 API 接口文件
- [ ] 4.1.1 创建 `ruoyi-ui/src/api/dpcIntermediary.js`
- [ ] 4.1.2 定义 `listIntermediary` 接口
- [ ] 4.1.3 定义 `getIntermediary` 接口
- [ ] 4.1.4 定义 `addIntermediary` 接口
- [ ] 4.1.5 定义 `updateIntermediary` 接口
- [ ] 4.1.6 定义 `delIntermediary` 接口
- [ ] 4.1.7 定义 `exportIntermediary` 接口
- [ ] 4.1.8 定义 `importTemplate` 接口
- [ ] 4.1.9 定义 `importData` 接口
- [ ] 4.2 创建主页面
- [ ] 4.2.1 创建 `ruoyi-ui/src/views/dpcIntermediary/index.vue`
- [ ] 4.2.2 实现搜索表单区域
- [ ] 4.2.3 实现操作按钮区域(新增、导入、导出、下载模板)
- [ ] 4.2.4 实现数据表格(展示列表数据)
- [ ] 4.2.5 实现分页组件
- [ ] 4.2.6 实现新增/编辑对话框
- [ ] 4.2.7 实现导入对话框
- [ ] 4.2.8 实现表单验证规则
- [ ] 4.2.9 实现字典数据回显(中介类型、风险等级、状态)
- [ ] 4.3 实现前端功能细节
- [ ] 4.3.1 搜索条件组合查询
- [ ] 4.3.2 新增/编辑表单提交
- [ ] 4.3.3 单条/批量删除确认
- [ ] 4.3.4 Excel 文件上传
- [ ] 4.3.5 导入结果展示(成功/失败数量)
- [ ] 4.3.6 导入错误详情展示
- [ ] 4.3.7 权限按钮显示控制v-hasPermi
## 测试
- [ ] 5.1 后端单元测试
- [ ] 5.1.1 测试查询列表功能
- [ ] 5.1.2 测试查询详情功能
- [ ] 5.1.3 测试新增功能(含边界条件)
- [ ] 5.1.4 测试修改功能
- [ ] 5.1.5 测试删除功能
- [ ] 5.1.6 测试数据校验逻辑
- [ ] 5.1.7 测试 Excel 导入功能(含异常数据)
- [ ] 5.1.8 测试 Excel 导出功能
- [ ] 5.2 后端集成测试
- [ ] 5.2.1 测试 Controller 层接口
- [ ] 5.2.2 测试权限验证
- [ ] 5.2.3 测试操作日志记录
- [ ] 5.3 前端功能测试
- [ ] 5.3.1 测试页面加载和列表展示
- [ ] 5.3.2 测试搜索功能(各种条件组合)
- [ ] 5.3.3 测试新增功能
- [ ] 5.3.4 测试编辑功能
- [ ] 5.3.5 测试删除功能(单条和批量)
- [ ] 5.3.6 测试 Excel 模板下载
- [ ] 5.3.7 测试 Excel 导入(正常和异常数据)
- [ ] 5.3.8 测试 Excel 导出
- [ ] 5.3.9 测试权限控制
- [ ] 5.4 生成测试脚本
- [ ] 5.4.1 编写自动化测试脚本
- [ ] 5.4.2 生成测试数据
- [ ] 5.4.3 执行测试并验证结果
## 文档编写
- [ ] 6.1 生成 API 文档
- [ ] 6.1.1 生成 Swagger 接口文档
- [ ] 6.1.2 编写接口使用说明
- [ ] 6.2 编写用户手册
- [ ] 6.2.1 功能概述
- [ ] 6.2.2 操作步骤说明
- [ ] 6.2.3 常见问题解答
## 验收
- [ ] 7.1 功能完整性验收
- [ ] 7.1.1 所有 CRUD 功能正常
- [ ] 7.1.2 Excel 导入导出功能正常
- [ ] 7.1.3 数据验证功能正常
- [ ] 7.1.4 权限控制功能正常
- [ ] 7.1.5 操作日志记录正常
- [ ] 7.2 性能验收
- [ ] 7.2.1 列表查询响应时间 < 1秒1000条数据
- [ ] 7.2.2 Excel 导入 1000 条数据耗时 < 10秒
- [ ] 7.2.3 Excel 导出 1000 条数据耗时 < 5秒
- [ ] 7.3 兼容性验收
- [ ] 7.3.1 支持 Chrome 浏览器
- [ ] 7.3.2 支持 Edge 浏览器
- [ ] 7.3.3 支持 Firefox 浏览器
## 依赖关系
```
1. 环境准备
2. 数据库设计
3. 后端开发Domain → Mapper → Service → Controller
4. 前端开发API → 页面 → 功能)
5. 测试
6. 文档编写
7. 验收
```
## 并行任务
以下任务可以并行执行:
- 3.2Mapper 层)可与 3.3Service 层)部分并行(先定义接口)
- 4.1API 接口)可与 3.4Controller 层)并行
- 5.1(单元测试)可与 5.2(集成测试)部分并行
## 验收标准
所有任务完成后,必须满足:
1. 所有接口功能正常,无 Bug
2. Excel 导入导出功能完整可用
3. 数据验证规则正确执行
4. 权限控制有效
5. 操作日志正确记录
6. 前端页面交互流畅
7. 通过所有测试用例
8. API 文档完整准确

View File

@@ -201,6 +201,13 @@
<version>${ruoyi.version}</version> <version>${ruoyi.version}</version>
</dependency> </dependency>
<!-- 纪检初核系统模块-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-dpc</artifactId>
<version>${ruoyi.version}</version>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>
@@ -211,6 +218,7 @@
<module>ruoyi-quartz</module> <module>ruoyi-quartz</module>
<module>ruoyi-generator</module> <module>ruoyi-generator</module>
<module>ruoyi-common</module> <module>ruoyi-common</module>
<module>ruoyi-dpc</module>
</modules> </modules>
<packaging>pom</packaging> <packaging>pom</packaging>

View File

@@ -54,6 +54,12 @@
<artifactId>ruoyi-generator</artifactId> <artifactId>ruoyi-generator</artifactId>
</dependency> </dependency>
<!-- 纪检初核系统模块-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-dpc</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>

38
ruoyi-dpc/pom.xml Normal file
View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId>
<version>3.9.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-dpc</artifactId>
<description>
纪检初核系统模块
</description>
<dependencies>
<!-- 通用工具-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId>
</dependency>
<!-- easyexcel工具 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,136 @@
package com.ruoyi.dpc.controller;
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.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.dpc.domain.DpcIntermediaryBlacklist;
import com.ruoyi.dpc.domain.dto.DpcIntermediaryBlacklistAddDTO;
import com.ruoyi.dpc.domain.dto.DpcIntermediaryBlacklistEditDTO;
import com.ruoyi.dpc.domain.dto.DpcIntermediaryBlacklistQueryDTO;
import com.ruoyi.dpc.domain.vo.DpcIntermediaryBlacklistVO;
import com.ruoyi.dpc.service.IDpcIntermediaryBlacklistService;
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
*/
@RestController
@RequestMapping("/dpc/intermediary")
public class DpcIntermediaryBlacklistController extends BaseController {
@Resource
private IDpcIntermediaryBlacklistService intermediaryService;
/**
* 查询中介黑名单列表
*/
@PreAuthorize("@ss.hasPermi('dpc:intermediary:list')")
@GetMapping("/list")
public TableDataInfo list(DpcIntermediaryBlacklistQueryDTO queryDTO) {
startPage();
List<DpcIntermediaryBlacklistVO> list = intermediaryService.selectIntermediaryList(queryDTO);
return getDataTable(list);
}
/**
* 导出中介黑名单列表
*/
@PreAuthorize("@ss.hasPermi('dpc:intermediary:export')")
@Log(title = "中介黑名单", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, DpcIntermediaryBlacklistQueryDTO queryDTO) {
List<DpcIntermediaryBlacklist> list = intermediaryService.selectIntermediaryListForExport(queryDTO);
ExcelUtil<DpcIntermediaryBlacklist> util = new ExcelUtil<>(DpcIntermediaryBlacklist.class);
util.exportExcel(response, list, "中介黑名单数据");
}
/**
* 获取中介黑名单详细信息
*/
@PreAuthorize("@ss.hasPermi('dpc:intermediary:query')")
@GetMapping(value = "/{intermediaryId}")
public AjaxResult getInfo(@PathVariable Long intermediaryId) {
return success(intermediaryService.selectIntermediaryById(intermediaryId));
}
/**
* 新增中介黑名单
*/
@PreAuthorize("@ss.hasPermi('dpc:intermediary:add')")
@Log(title = "中介黑名单", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@Validated @RequestBody DpcIntermediaryBlacklistAddDTO addDTO) {
return toAjax(intermediaryService.insertIntermediary(addDTO));
}
/**
* 修改中介黑名单
*/
@PreAuthorize("@ss.hasPermi('dpc:intermediary:edit')")
@Log(title = "中介黑名单", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@Validated @RequestBody DpcIntermediaryBlacklistEditDTO editDTO) {
return toAjax(intermediaryService.updateIntermediary(editDTO));
}
/**
* 删除中介黑名单
*/
@PreAuthorize("@ss.hasPermi('dpc:intermediary:remove')")
@Log(title = "中介黑名单", businessType = BusinessType.DELETE)
@DeleteMapping("/{intermediaryIds}")
public AjaxResult remove(@PathVariable Long[] intermediaryIds) {
return toAjax(intermediaryService.deleteIntermediaryByIds(intermediaryIds));
}
/**
* 下载导入模板
*/
@PostMapping("/importTemplate")
public void importTemplate(HttpServletResponse response) {
ExcelUtil<DpcIntermediaryBlacklist> util = new ExcelUtil<>(DpcIntermediaryBlacklist.class);
util.importTemplateExcel(response, "中介黑名单数据");
}
/**
* 导入中介黑名单
*/
@PreAuthorize("@ss.hasPermi('dpc:intermediary:import')")
@Log(title = "中介黑名单", businessType = BusinessType.IMPORT)
@PostMapping("/importData")
public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception {
ExcelUtil<DpcIntermediaryBlacklist> util = new ExcelUtil<>(DpcIntermediaryBlacklist.class);
List<DpcIntermediaryBlacklist> list = util.importExcel(file.getInputStream());
List<DpcIntermediaryBlacklistAddDTO> addDTOList = convertToAddDTOList(list);
String message = intermediaryService.importIntermediary(addDTOList, updateSupport);
return success(message);
}
/**
* 转换为AddDTO列表
*/
private List<DpcIntermediaryBlacklistAddDTO> convertToAddDTOList(List<DpcIntermediaryBlacklist> list) {
return list.stream().map(entity -> {
DpcIntermediaryBlacklistAddDTO dto = new DpcIntermediaryBlacklistAddDTO();
dto.setName(entity.getName());
dto.setCertificateNo(entity.getCertificateNo());
dto.setIntermediaryType(entity.getIntermediaryType());
dto.setStatus(entity.getStatus());
dto.setRemark(entity.getRemark());
return dto;
}).toList();
}
}

View File

@@ -0,0 +1,134 @@
package com.ruoyi.dpc.domain;
import com.ruoyi.common.annotation.Excel;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 中介人员黑名单对象 dpc_intermediary_blacklist
*
* @author ruoyi
* @date 2026-01-27
*/
public class DpcIntermediaryBlacklist implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/** 中介ID */
private Long intermediaryId;
/** 姓名/机构名称 */
@Excel(name = "姓名/机构名称")
private String name;
/** 证件号 */
@Excel(name = "证件号")
private String certificateNo;
/** 中介类型 */
@Excel(name = "中介类型", readConverterExp = "1=个人,2=机构")
private String intermediaryType;
/** 状态 */
@Excel(name = "状态", readConverterExp = "0=正常,1=停用")
private String status;
/** 备注 */
@Excel(name = "备注")
private String remark;
/** 创建者 */
private String createBy;
/** 创建时间 */
private Date createTime;
/** 更新者 */
private String updateBy;
/** 更新时间 */
private Date updateTime;
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 getCreateBy() {
return createBy;
}
public void setCreateBy(String createBy) {
this.createBy = createBy;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public String getUpdateBy() {
return updateBy;
}
public void setUpdateBy(String updateBy) {
this.updateBy = updateBy;
}
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
}

View File

@@ -0,0 +1,86 @@
package com.ruoyi.dpc.domain.dto;
import com.ruoyi.common.annotation.Excel;
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 DpcIntermediaryBlacklistAddDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/** 姓名/机构名称 */
@Excel(name = "姓名/机构名称")
@NotBlank(message = "姓名/机构名称不能为空")
@Size(min = 1, max = 100, message = "姓名/机构名称长度不能超过100个字符")
private String name;
/** 证件号 */
@Excel(name = "证件号")
@Size(max = 50, message = "证件号长度不能超过50个字符")
private String certificateNo;
/** 中介类型 */
@Excel(name = "中介类型", readConverterExp = "1=个人,2=机构")
@NotBlank(message = "中介类型不能为空")
private String intermediaryType;
/** 状态 */
@Excel(name = "状态", readConverterExp = "0=正常,1=停用")
@NotBlank(message = "状态不能为空")
private String status;
/** 备注 */
@Excel(name = "备注")
@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 getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
}

View File

@@ -0,0 +1,99 @@
package com.ruoyi.dpc.domain.dto;
import com.ruoyi.common.annotation.Excel;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import java.io.Serial;
import java.io.Serializable;
/**
* 中介人员黑名单编辑 DTO
*
* @author ruoyi
* @date 2026-01-27
*/
public class DpcIntermediaryBlacklistEditDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/** 中介ID */
@NotNull(message = "中介ID不能为空")
private Long intermediaryId;
/** 姓名/机构名称 */
@Excel(name = "姓名/机构名称")
@NotBlank(message = "姓名/机构名称不能为空")
@Size(min = 1, max = 100, message = "姓名/机构名称长度不能超过100个字符")
private String name;
/** 证件号 */
@Excel(name = "证件号")
@Size(max = 50, message = "证件号长度不能超过50个字符")
private String certificateNo;
/** 中介类型 */
@Excel(name = "中介类型", readConverterExp = "1=个人,2=机构")
@NotBlank(message = "中介类型不能为空")
private String intermediaryType;
/** 状态 */
@Excel(name = "状态", readConverterExp = "0=正常,1=停用")
@NotBlank(message = "状态不能为空")
private String status;
/** 备注 */
@Excel(name = "备注")
@Size(max = 500, message = "备注长度不能超过500个字符")
private String remark;
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;
}
}

View File

@@ -0,0 +1,60 @@
package com.ruoyi.dpc.domain.dto;
import java.io.Serial;
import java.io.Serializable;
/**
* 中介人员黑名单查询 DTO
*
* @author ruoyi
* @date 2026-01-27
*/
public class DpcIntermediaryBlacklistQueryDTO 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;
}
}

View File

@@ -0,0 +1,153 @@
package com.ruoyi.dpc.domain.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 中介人员黑名单视图对象 VO
*
* @author ruoyi
* @date 2026-01-27
*/
public class DpcIntermediaryBlacklistVO 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;
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 getIntermediaryTypeName() {
return intermediaryTypeName;
}
public void setIntermediaryTypeName(String intermediaryTypeName) {
this.intermediaryTypeName = intermediaryTypeName;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getStatusName() {
return statusName;
}
public void setStatusName(String statusName) {
this.statusName = statusName;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public String getCreateBy() {
return createBy;
}
public void setCreateBy(String createBy) {
this.createBy = createBy;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public String getUpdateBy() {
return updateBy;
}
public void setUpdateBy(String updateBy) {
this.updateBy = updateBy;
}
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
}

View File

@@ -0,0 +1,63 @@
package com.ruoyi.dpc.mapper;
import com.ruoyi.dpc.domain.DpcIntermediaryBlacklist;
import com.ruoyi.dpc.domain.dto.DpcIntermediaryBlacklistQueryDTO;
import java.util.List;
/**
* 中介人员黑名单 数据层
*
* @author ruoyi
* @date 2026-01-27
*/
public interface DpcIntermediaryBlacklistMapper {
/**
* 查询中介黑名单列表
*
* @param queryDTO 查询条件
* @return 中介黑名单集合
*/
List<DpcIntermediaryBlacklist> selectIntermediaryList(DpcIntermediaryBlacklistQueryDTO queryDTO);
/**
* 查询中介黑名单详细
*
* @param intermediaryId 中介ID
* @return 中介黑名单对象
*/
DpcIntermediaryBlacklist selectIntermediaryById(Long intermediaryId);
/**
* 新增中介黑名单
*
* @param intermediary 中介黑名单
* @return 结果
*/
int insertIntermediary(DpcIntermediaryBlacklist intermediary);
/**
* 修改中介黑名单
*
* @param intermediary 中介黑名单
* @return 结果
*/
int updateIntermediary(DpcIntermediaryBlacklist intermediary);
/**
* 删除中介黑名单
*
* @param intermediaryId 中介ID
* @return 结果
*/
int deleteIntermediaryById(Long intermediaryId);
/**
* 批量删除中介黑名单
*
* @param intermediaryIds 需要删除的中介ID
* @return 结果
*/
int deleteIntermediaryByIds(Long[] intermediaryIds);
}

View File

@@ -0,0 +1,75 @@
package com.ruoyi.dpc.service;
import com.ruoyi.dpc.domain.DpcIntermediaryBlacklist;
import com.ruoyi.dpc.domain.dto.DpcIntermediaryBlacklistAddDTO;
import com.ruoyi.dpc.domain.dto.DpcIntermediaryBlacklistEditDTO;
import com.ruoyi.dpc.domain.dto.DpcIntermediaryBlacklistQueryDTO;
import com.ruoyi.dpc.domain.vo.DpcIntermediaryBlacklistVO;
import java.util.List;
/**
* 中介人员黑名单 服务层
*
* @author ruoyi
* @date 2026-01-27
*/
public interface IDpcIntermediaryBlacklistService {
/**
* 查询中介黑名单列表
*
* @param queryDTO 查询条件
* @return 中介黑名单集合
*/
List<DpcIntermediaryBlacklistVO> selectIntermediaryList(DpcIntermediaryBlacklistQueryDTO queryDTO);
/**
* 查询中介黑名单列表(用于导出)
*
* @param queryDTO 查询条件
* @return 中介黑名单实体集合
*/
List<DpcIntermediaryBlacklist> selectIntermediaryListForExport(DpcIntermediaryBlacklistQueryDTO queryDTO);
/**
* 查询中介黑名单详细
*
* @param intermediaryId 中介ID
* @return 中介黑名单VO
*/
DpcIntermediaryBlacklistVO selectIntermediaryById(Long intermediaryId);
/**
* 新增中介黑名单
*
* @param addDTO 新增DTO
* @return 结果
*/
int insertIntermediary(DpcIntermediaryBlacklistAddDTO addDTO);
/**
* 修改中介黑名单
*
* @param editDTO 编辑DTO
* @return 结果
*/
int updateIntermediary(DpcIntermediaryBlacklistEditDTO editDTO);
/**
* 批量删除中介黑名单
*
* @param intermediaryIds 需要删除的中介ID
* @return 结果
*/
int deleteIntermediaryByIds(Long[] intermediaryIds);
/**
* 导入中介黑名单数据
*
* @param addDTOList 新增DTO列表
* @param isUpdateSupport 是否更新支持
* @return 结果
*/
String importIntermediary(List<DpcIntermediaryBlacklistAddDTO> addDTOList, Boolean isUpdateSupport);
}

View File

@@ -0,0 +1,197 @@
package com.ruoyi.dpc.service.impl;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.dpc.domain.DpcIntermediaryBlacklist;
import com.ruoyi.dpc.domain.dto.DpcIntermediaryBlacklistAddDTO;
import com.ruoyi.dpc.domain.dto.DpcIntermediaryBlacklistEditDTO;
import com.ruoyi.dpc.domain.dto.DpcIntermediaryBlacklistQueryDTO;
import com.ruoyi.dpc.domain.vo.DpcIntermediaryBlacklistVO;
import com.ruoyi.dpc.mapper.DpcIntermediaryBlacklistMapper;
import com.ruoyi.dpc.service.IDpcIntermediaryBlacklistService;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
* 中介人员黑名单 服务层处理
*
* @author ruoyi
* @date 2026-01-27
*/
@Service
public class DpcIntermediaryBlacklistServiceImpl implements IDpcIntermediaryBlacklistService {
@Resource
private DpcIntermediaryBlacklistMapper intermediaryMapper;
/**
* 查询中介黑名单列表
*
* @param queryDTO 查询条件
* @return 中介黑名单集合
*/
@Override
public List<DpcIntermediaryBlacklistVO> selectIntermediaryList(DpcIntermediaryBlacklistQueryDTO queryDTO) {
List<DpcIntermediaryBlacklist> list = intermediaryMapper.selectIntermediaryList(queryDTO);
List<DpcIntermediaryBlacklistVO> voList = new ArrayList<>();
for (DpcIntermediaryBlacklist intermediary : list) {
voList.add(convertToVO(intermediary));
}
return voList;
}
/**
* 查询中介黑名单列表(用于导出)
*
* @param queryDTO 查询条件
* @return 中介黑名单实体集合
*/
@Override
public List<DpcIntermediaryBlacklist> selectIntermediaryListForExport(DpcIntermediaryBlacklistQueryDTO queryDTO) {
return intermediaryMapper.selectIntermediaryList(queryDTO);
}
/**
* 查询中介黑名单详细
*
* @param intermediaryId 中介ID
* @return 中介黑名单VO
*/
@Override
public DpcIntermediaryBlacklistVO selectIntermediaryById(Long intermediaryId) {
DpcIntermediaryBlacklist intermediary = intermediaryMapper.selectIntermediaryById(intermediaryId);
return convertToVO(intermediary);
}
/**
* 新增中介黑名单
*
* @param addDTO 新增DTO
* @return 结果
*/
@Override
public int insertIntermediary(DpcIntermediaryBlacklistAddDTO addDTO) {
DpcIntermediaryBlacklist intermediary = new DpcIntermediaryBlacklist();
BeanUtils.copyProperties(addDTO, intermediary);
intermediary.setCreateBy(SecurityUtils.getUsername());
return intermediaryMapper.insertIntermediary(intermediary);
}
/**
* 修改中介黑名单
*
* @param editDTO 编辑DTO
* @return 结果
*/
@Override
public int updateIntermediary(DpcIntermediaryBlacklistEditDTO editDTO) {
DpcIntermediaryBlacklist intermediary = new DpcIntermediaryBlacklist();
BeanUtils.copyProperties(editDTO, intermediary);
intermediary.setUpdateBy(SecurityUtils.getUsername());
return intermediaryMapper.updateIntermediary(intermediary);
}
/**
* 批量删除中介黑名单
*
* @param intermediaryIds 需要删除的中介ID
* @return 结果
*/
@Override
public int deleteIntermediaryByIds(Long[] intermediaryIds) {
return intermediaryMapper.deleteIntermediaryByIds(intermediaryIds);
}
/**
* 导入中介黑名单数据
*
* @param addDTOList 新增DTO列表
* @param isUpdateSupport 是否更新支持
* @return 结果
*/
@Override
public String importIntermediary(List<DpcIntermediaryBlacklistAddDTO> addDTOList, Boolean isUpdateSupport) {
if (StringUtils.isNull(addDTOList) || addDTOList.isEmpty()) {
return "至少需要一条数据";
}
int successNum = 0;
int failureNum = 0;
StringBuilder successMsg = new StringBuilder();
StringBuilder failureMsg = new StringBuilder();
for (DpcIntermediaryBlacklistAddDTO addDTO : addDTOList) {
try {
// 验证数据
validateIntermediaryData(addDTO);
DpcIntermediaryBlacklist intermediary = new DpcIntermediaryBlacklist();
BeanUtils.copyProperties(addDTO, intermediary);
intermediary.setCreateBy(SecurityUtils.getUsername());
intermediaryMapper.insertIntermediary(intermediary);
successNum++;
successMsg.append("<br/>").append(successNum).append("").append(addDTO.getName()).append(" 导入成功");
} catch (Exception e) {
failureNum++;
failureMsg.append("<br/>").append(failureNum).append("").append(addDTO.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();
}
}
/**
* 验证中介数据
*/
private void validateIntermediaryData(DpcIntermediaryBlacklistAddDTO addDTO) {
// 验证中介类型
if (!"1".equals(addDTO.getIntermediaryType()) && !"2".equals(addDTO.getIntermediaryType())) {
throw new RuntimeException("中介类型只能填写'个人'或'机构'");
}
// 验证状态
if (!"0".equals(addDTO.getStatus()) && !"1".equals(addDTO.getStatus())) {
throw new RuntimeException("状态只能填写'正常'或'停用'");
}
}
/**
* 转换为VO对象
*/
private DpcIntermediaryBlacklistVO convertToVO(DpcIntermediaryBlacklist intermediary) {
if (intermediary == null) {
return null;
}
DpcIntermediaryBlacklistVO vo = new DpcIntermediaryBlacklistVO();
BeanUtils.copyProperties(intermediary, vo);
// 设置中介类型名称
if ("1".equals(intermediary.getIntermediaryType())) {
vo.setIntermediaryTypeName("个人");
} else if ("2".equals(intermediary.getIntermediaryType())) {
vo.setIntermediaryTypeName("机构");
}
// 设置状态名称
if ("0".equals(intermediary.getStatus())) {
vo.setStatusName("正常");
} else if ("1".equals(intermediary.getStatus())) {
vo.setStatusName("停用");
}
return vo;
}
}

View File

@@ -0,0 +1,99 @@
<?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.dpc.mapper.DpcIntermediaryBlacklistMapper">
<resultMap type="DpcIntermediaryBlacklist" id="DpcIntermediaryBlacklistResult">
<id property="intermediaryId" column="intermediary_id"/>
<result property="name" column="name"/>
<result property="certificateNo" column="certificate_no"/>
<result property="intermediaryType" column="intermediary_type"/>
<result property="status" column="status"/>
<result property="remark" column="remark"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
<result property="updateTime" column="update_time"/>
</resultMap>
<sql id="selectIntermediaryVo">
select intermediary_id, name, certificate_no, intermediary_type, status, remark,
create_by, create_time, update_by, update_time
from dpc_intermediary_blacklist
</sql>
<select id="selectIntermediaryList" parameterType="DpcIntermediaryBlacklistQueryDTO"
resultMap="DpcIntermediaryBlacklistResult">
<include refid="selectIntermediaryVo"/>
<where>
<if test="name != null and name != ''">
AND name like concat('%', #{name}, '%')
</if>
<if test="certificateNo != null and certificateNo != ''">
AND certificate_no = #{certificateNo}
</if>
<if test="intermediaryType != null and intermediaryType != ''">
AND intermediary_type = #{intermediaryType}
</if>
<if test="status != null and status != ''">
AND status = #{status}
</if>
</where>
order by create_time desc
</select>
<select id="selectIntermediaryById" parameterType="Long" resultMap="DpcIntermediaryBlacklistResult">
<include refid="selectIntermediaryVo"/>
where intermediary_id = #{intermediaryId}
</select>
<insert id="insertIntermediary" parameterType="DpcIntermediaryBlacklist" useGeneratedKeys="true"
keyProperty="intermediaryId">
insert into dpc_intermediary_blacklist
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="name != null and name != ''">name,</if>
<if test="certificateNo != null and certificateNo != ''">certificate_no,</if>
<if test="intermediaryType != null and intermediaryType != ''">intermediary_type,</if>
<if test="status != null and status != ''">status,</if>
<if test="remark != null">remark,</if>
<if test="createBy != null and createBy != ''">create_by,</if>
create_time
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="name != null and name != ''">#{name},</if>
<if test="certificateNo != null and certificateNo != ''">#{certificateNo},</if>
<if test="intermediaryType != null and intermediaryType != ''">#{intermediaryType},</if>
<if test="status != null and status != ''">#{status},</if>
<if test="remark != null">#{remark},</if>
<if test="createBy != null and createBy != ''">#{createBy},</if>
sysdate()
</trim>
</insert>
<update id="updateIntermediary" parameterType="DpcIntermediaryBlacklist">
update dpc_intermediary_blacklist
<set>
<if test="name != null and name != ''">name = #{name},</if>
<if test="certificateNo != null">certificate_no = #{certificateNo},</if>
<if test="intermediaryType != null and intermediaryType != ''">intermediary_type = #{intermediaryType},</if>
<if test="status != null and status != ''">status = #{status},</if>
<if test="remark != null">remark = #{remark},</if>
<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
update_time = sysdate()
</set>
where intermediary_id = #{intermediaryId}
</update>
<delete id="deleteIntermediaryById" parameterType="Long">
delete from dpc_intermediary_blacklist where intermediary_id = #{intermediaryId}
</delete>
<delete id="deleteIntermediaryByIds" parameterType="Long">
delete from dpc_intermediary_blacklist where intermediary_id in
<foreach collection="array" item="intermediaryId" open="(" separator="," close=")">
#{intermediaryId}
</foreach>
</delete>
</mapper>

View File

@@ -0,0 +1,70 @@
import request from '@/utils/request'
// 查询中介黑名单列表
export function listIntermediary(query) {
return request({
url: '/dpc/intermediary/list',
method: 'get',
params: query
})
}
// 查询中介黑名单详细
export function getIntermediary(intermediaryId) {
return request({
url: '/dpc/intermediary/' + intermediaryId,
method: 'get'
})
}
// 新增中介黑名单
export function addIntermediary(data) {
return request({
url: '/dpc/intermediary',
method: 'post',
data: data
})
}
// 修改中介黑名单
export function updateIntermediary(data) {
return request({
url: '/dpc/intermediary',
method: 'put',
data: data
})
}
// 删除中介黑名单
export function delIntermediary(intermediaryIds) {
return request({
url: '/dpc/intermediary/' + intermediaryIds,
method: 'delete'
})
}
// 导出中介黑名单
export function exportIntermediary(query) {
return request({
url: '/dpc/intermediary/export',
method: 'post',
params: query
})
}
// 下载导入模板
export function importTemplate() {
return request({
url: '/dpc/intermediary/importTemplate',
method: 'post'
})
}
// 导入中介黑名单
export function importData(data, updateSupport) {
return request({
url: '/dpc/intermediary/importData?updateSupport=' + updateSupport,
method: 'post',
data: data
})
}

View File

@@ -0,0 +1,387 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="100px">
<el-form-item label="姓名/机构名称" prop="name">
<el-input
v-model="queryParams.name"
placeholder="请输入姓名/机构名称"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="证件号" prop="certificateNo">
<el-input
v-model="queryParams.certificateNo"
placeholder="请输入证件号"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="中介类型" prop="intermediaryType">
<el-select v-model="queryParams.intermediaryType" placeholder="中介类型" clearable style="width: 240px">
<el-option label="全部" value="" />
<el-option label="个人" value="1" />
<el-option label="机构" value="2" />
</el-select>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="状态" clearable style="width: 240px">
<el-option label="全部" value="" />
<el-option label="正常" value="0" />
<el-option label="停用" value="1" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
v-hasPermi="['dpc:intermediary:add']"
>新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="el-icon-upload2"
size="mini"
@click="handleImport"
v-hasPermi="['dpc:intermediary:import']"
>导入</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="el-icon-download"
size="mini"
@click="handleExport"
v-hasPermi="['dpc:intermediary:export']"
>导出</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="intermediaryList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="中介ID" align="center" prop="intermediaryId" width="80"/>
<el-table-column label="姓名/机构名称" align="center" prop="name" :show-overflow-tooltip="true"/>
<el-table-column label="证件号" align="center" prop="certificateNo" :show-overflow-tooltip="true"/>
<el-table-column label="中介类型" align="center" prop="intermediaryTypeName" width="100"/>
<el-table-column label="状态" align="center" prop="status" width="100">
<template slot-scope="scope">
<el-tag v-if="scope.row.status === '0'" type="success">正常</el-tag>
<el-tag v-else type="danger">停用</el-tag>
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
v-hasPermi="['dpc:intermediary:edit']"
>修改</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
v-hasPermi="['dpc:intermediary:remove']"
>删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<!-- 添加或修改对话框 -->
<el-dialog :title="title" :visible.sync="open" width="600px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="120px">
<el-form-item label="姓名/机构名称" prop="name">
<el-input v-model="form.name" placeholder="请输入姓名/机构名称" maxlength="100"/>
</el-form-item>
<el-form-item label="证件号" prop="certificateNo">
<el-input v-model="form.certificateNo" placeholder="请输入证件号" maxlength="50"/>
</el-form-item>
<el-form-item label="中介类型" prop="intermediaryType">
<el-radio-group v-model="form.intermediaryType">
<el-radio label="1">个人</el-radio>
<el-radio label="2">机构</el-radio>
</el-radio-group>
</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-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入备注" maxlength="500"/>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
<!-- 导入对话框 -->
<el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
<el-upload
ref="upload"
:limit="1"
accept=".xlsx, .xls"
:headers="upload.headers"
:action="upload.url + '?updateSupport=' + upload.updateSupport"
:disabled="upload.isUploading"
:on-progress="handleFileUploadProgress"
:on-success="handleFileSuccess"
:auto-upload="false"
drag
>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处<em>点击上传</em></div>
<div class="el-upload__tip" slot="tip">
<el-checkbox v-model="upload.updateSupport" />是否更新已经存在的中介黑名单数据
<el-link type="primary" :underline="false" style="font-size: 12px; vertical-align: baseline;" @click="importTemplate">下载模板</el-link>
</div>
<div class="el-upload__tip" slot="tip">
<span>仅允许导入"xls""xlsx"格式文件</span>
</div>
</el-upload>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitFileForm"> </el-button>
<el-button @click="upload.open = false"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import {
addIntermediary,
delIntermediary,
getIntermediary,
listIntermediary,
updateIntermediary
} from "@/api/dpcIntermediary";
import {getToken} from "@/utils/auth";
export default {
name: "Intermediary",
data() {
return {
// 遮罩层
loading: true,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 中介黑名单表格数据
intermediaryList: [],
// 弹出层标题
title: "",
// 是否显示弹出层
open: false,
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
name: null,
certificateNo: null,
intermediaryType: null,
status: null
},
// 表单参数
form: {},
// 表单校验
rules: {
name: [
{ required: true, message: "姓名/机构名称不能为空", trigger: "blur" },
{ max: 100, message: "姓名/机构名称长度不能超过100个字符", trigger: "blur" }
],
certificateNo: [
{ max: 50, message: "证件号长度不能超过50个字符", trigger: "blur" }
],
intermediaryType: [
{ required: true, message: "请选择中介类型", trigger: "change" }
],
status: [
{ required: true, message: "请选择状态", trigger: "change" }
],
remark: [
{ max: 500, message: "备注长度不能超过500个字符", trigger: "blur" }
]
},
// 导入参数
upload: {
// 是否显示弹出层
open: false,
// 弹出层标题
title: "",
// 是否禁用上传
isUploading: false,
// 是否更新已经存在的数据
updateSupport: 0,
// 设置上传的请求头部
headers: { Authorization: "Bearer " + getToken() },
// 上传的地址
url: process.env.VUE_APP_BASE_API + "/dpc/intermediary/importData"
}
};
},
created() {
this.getList();
},
methods: {
/** 查询中介黑名单列表 */
getList() {
this.loading = true;
listIntermediary(this.queryParams).then(response => {
this.intermediaryList = response.rows;
this.total = response.total;
this.loading = false;
});
},
// 取消按钮
cancel() {
this.open = false;
this.reset();
},
// 表单重置
reset() {
this.form = {
intermediaryId: null,
name: null,
certificateNo: null,
intermediaryType: "1",
status: "0",
remark: null
};
this.resetForm("form");
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
/** 多选框选中数据 */
handleSelectionChange(selection) {
this.ids = selection.map(item => item.intermediaryId);
this.single = selection.length !== 1;
this.multiple = !selection.length;
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.open = true;
this.title = "添加中介黑名单";
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset();
const intermediaryId = row.intermediaryId || this.ids[0];
getIntermediary(intermediaryId).then(response => {
this.form = response.data;
this.open = true;
this.title = "修改中介黑名单";
});
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
if (this.form.intermediaryId != null) {
updateIntermediary(this.form).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
});
} else {
addIntermediary(this.form).then(response => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
});
}
}
});
},
/** 删除按钮操作 */
handleDelete(row) {
const intermediaryIds = row.intermediaryId || this.ids;
this.$modal.confirm('是否确认删除中介黑名单编号为"' + intermediaryIds + '"的数据项?').then(function() {
return delIntermediary(intermediaryIds);
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
},
/** 导出按钮操作 */
handleExport() {
this.download('dpc/intermediary/export', {
...this.queryParams
}, `中介黑名单_${new Date().getTime()}.xlsx`)
},
/** 导入按钮操作 */
handleImport() {
this.upload.title = "中介黑名单数据导入";
this.upload.open = true;
},
/** 下载模板操作 */
importTemplate() {
this.download('dpc/intermediary/importTemplate', {}, `中介黑名单模板_${new Date().getTime()}.xlsx`)
},
// 文件上传中处理
handleFileUploadProgress(event, file, fileList) {
this.upload.isUploading = true;
},
// 文件上传成功处理
handleFileSuccess(response, file, fileList) {
this.upload.isUploading = false;
this.upload.open = false;
this.getList();
this.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导入结果");
},
// 提交上传文件
submitFileForm() {
this.$refs.upload.submit();
}
}
};
</script>

View File

@@ -0,0 +1,53 @@
-- ================================
-- 纪检初核系统 - 中介人员黑名单管理模块
-- 创建日期: 2026-01-27
-- ================================
-- ----------------------------
-- 1. 创建中介黑名单表
-- ----------------------------
DROP TABLE IF EXISTS `dpc_intermediary_blacklist`;
CREATE TABLE `dpc_intermediary_blacklist` (
`intermediary_id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '中介ID',
`name` VARCHAR(100) NOT NULL COMMENT '姓名/机构名称',
`certificate_no` VARCHAR(50) DEFAULT NULL COMMENT '证件号',
`intermediary_type` CHAR(1) NOT NULL DEFAULT '1' COMMENT '中介类型1个人 2机构',
`status` CHAR(1) NOT NULL DEFAULT '0' COMMENT '状态0正常 1停用',
`remark` VARCHAR(500) DEFAULT NULL COMMENT '备注',
`create_by` VARCHAR(64) DEFAULT '' COMMENT '创建者',
`create_time` DATETIME DEFAULT NULL COMMENT '创建时间',
`update_by` VARCHAR(64) DEFAULT '' COMMENT '更新者',
`update_time` DATETIME DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`intermediary_id`),
KEY `idx_name` (`name`),
KEY `idx_certificate_no` (`certificate_no`),
KEY `idx_intermediary_type` (`intermediary_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='中介人员黑名单表';
-- ----------------------------
-- 2. 菜单 SQL
-- ----------------------------
-- 一级菜单:信息维护
INSERT INTO `sys_menu` VALUES (2000, '信息维护', '0', '4', 'dpc', NULL, '', '', 1, 0, 'M', '0', '0', '', 'example', 'admin', sysdate(), '', NULL, '信息维护目录');
-- 二级菜单:中介库管理
INSERT INTO `sys_menu` VALUES (2001, '中介库管理', 2000, '1', 'intermediary', 'dpcIntermediary/index', '', '', 1, 0, 'C', '0', '0', 'dpc:intermediary:list', 'user', 'admin', sysdate(), '', NULL, '中介库管理菜单');
-- 中介库管理按钮权限
INSERT INTO `sys_menu` VALUES (2002, '中介查询', 2001, '1', '', '', '', '', 1, 0, 'F', '0', '0', 'dpc:intermediary:query', '#', 'admin', sysdate(), '', NULL, '');
INSERT INTO `sys_menu` VALUES (2003, '中介新增', 2001, '2', '', '', '', '', 1, 0, 'F', '0', '0', 'dpc:intermediary:add', '#', 'admin', sysdate(), '', NULL, '');
INSERT INTO `sys_menu` VALUES (2004, '中介修改', 2001, '3', '', '', '', '', 1, 0, 'F', '0', '0', 'dpc:intermediary:edit', '#', 'admin', sysdate(), '', NULL, '');
INSERT INTO `sys_menu` VALUES (2005, '中介删除', 2001, '4', '', '', '', '', 1, 0, 'F', '0', '0', 'dpc:intermediary:remove', '#', 'admin', sysdate(), '', NULL, '');
INSERT INTO `sys_menu` VALUES (2006, '中介导出', 2001, '5', '', '', '', '', 1, 0, 'F', '0', '0', 'dpc:intermediary:export', '#', 'admin', sysdate(), '', NULL, '');
INSERT INTO `sys_menu` VALUES (2007, '中介导入', 2001, '6', '', '', '', '', 1, 0, 'F', '0', '0', 'dpc:intermediary:import', '#', 'admin', sysdate(), '', NULL, '');
-- ----------------------------
-- 3. 字典数据 SQL
-- ----------------------------
-- 中介类型字典
INSERT INTO `sys_dict_type` VALUES (100, '中介类型', 'dpc_intermediary_type', '0', 'admin', sysdate(), '', NULL, '中介类型列表');
INSERT INTO `sys_dict_data` VALUES (100, 1, '个人', '1', 'dpc_intermediary_type', '', '', 'N', '0', 'admin', sysdate(), '', NULL, '个人中介');
INSERT INTO `sys_dict_data` VALUES (101, 2, '机构', '2', 'dpc_intermediary_type', '', '', 'N', '0', 'admin', sysdate(), '', NULL, '机构中介');