Compare commits
10 Commits
1a990087ac
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 01101d422f | |||
| 4ec637d7f8 | |||
| 30a53e7283 | |||
| 9ec44dbe5c | |||
| 89ac0d109c | |||
| 7095c4bf96 | |||
| cc2fe7b172 | |||
| b6a3d407e4 | |||
| db5ca691d7 | |||
| ad23922a7c |
17
.workbuddy/expert-history.json
Normal file
17
.workbuddy/expert-history.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"version": 2,
|
||||
"sessions": {
|
||||
"8b8cdf8cb3404efeac18615f9f419cb1": [
|
||||
{
|
||||
"expertId": "SeniorDeveloper",
|
||||
"name": "吴八哥",
|
||||
"profession": "高级开发工程师",
|
||||
"avatarUrl": "https://acc-1258344699.cos.accelerate.myqcloud.com/workbuddy/experts/avatars/02-Engineering/SeniorDeveloper/SeniorDeveloper.png",
|
||||
"promptUrl": "https://acc-1258344699.cos.accelerate.myqcloud.com/workbuddy/experts/experts/02-Engineering/SeniorDeveloper/SeniorDeveloper_zh.md",
|
||||
"usedAt": 1776323986694,
|
||||
"industryId": "02-Engineering"
|
||||
}
|
||||
]
|
||||
},
|
||||
"lastUpdated": 1776324781452
|
||||
}
|
||||
0
.workbuddy/memory/MEMORY.md
Normal file
0
.workbuddy/memory/MEMORY.md
Normal file
230
docs/ai/customer-lead-system-summary.md
Normal file
230
docs/ai/customer-lead-system-summary.md
Normal file
@@ -0,0 +1,230 @@
|
||||
# 客资管理系统实施总结
|
||||
|
||||
> 创建时间:2026-04-14
|
||||
> 作者:AI助手
|
||||
> 状态:实施完成
|
||||
|
||||
---
|
||||
|
||||
## 一、需求概述
|
||||
|
||||
根据客户需求,实现一个完整的**客资管理系统**,具备以下功能:
|
||||
|
||||
| 功能 | 描述 |
|
||||
|------|------|
|
||||
| 客资派单 | 管理员可以直接派单客资给业务员 |
|
||||
| 全民推荐 | 任何人都可以推荐客户赚取推荐费 |
|
||||
| 推荐人报备 | 注册用户可以报备客户(推荐人报备) |
|
||||
| 实时跟进 | 实时查看跟进情况和成交状态 |
|
||||
| 多管理员 | 支持多管理员设置 |
|
||||
| 数据统计导出 | 生成统计报表功能 |
|
||||
|
||||
---
|
||||
|
||||
## 二、实施成果
|
||||
|
||||
### 2.1 Java后端 (`/Users/gxwebsoft/JAVA/mp-java`)
|
||||
|
||||
#### 数据库变更
|
||||
**文件**: `docs/sql/customer_lead_system.sql`
|
||||
|
||||
| 表名 | 说明 |
|
||||
|------|------|
|
||||
| `cms_contact_lead` | 扩展现有客资表,添加派单、推荐人等字段 |
|
||||
| `lead_dispatch` | 派单记录表 |
|
||||
| `lead_follow_log` | 跟进记录表 |
|
||||
| `lead_referral` | 推荐人关系表(全民推荐) |
|
||||
| `sys_user_role_extend` | 用户角色扩展表(多管理员) |
|
||||
| `lead_statistics` | 数据统计汇总表 |
|
||||
| `lead_referral_settlement` | 推荐费结算记录表 |
|
||||
| `v_lead_full_info` | 客资完整信息视图 |
|
||||
|
||||
#### 新增实体类
|
||||
| 文件路径 | 说明 |
|
||||
|----------|------|
|
||||
| `cms/entity/CustomerLeadEntity.java` | 客资管理扩展实体 |
|
||||
| `cms/entity/LeadDispatch.java` | 派单记录实体 |
|
||||
| `cms/entity/LeadFollowLog.java` | 跟进记录实体 |
|
||||
| `cms/entity/LeadReferral.java` | 推荐关系实体 |
|
||||
| `cms/entity/LeadStatistics.java` | 统计实体 |
|
||||
| `common/system/entity/UserRoleExtend.java` | 用户角色扩展实体 |
|
||||
|
||||
#### 新增参数类
|
||||
| 文件路径 | 说明 |
|
||||
|----------|------|
|
||||
| `cms/param/CustomerLeadParam.java` | 客资查询参数 |
|
||||
| `cms/param/LeadDispatchParam.java` | 派单请求参数 |
|
||||
| `cms/param/LeadFollowParam.java` | 跟进请求参数 |
|
||||
| `cms/param/LeadReferralParam.java` | 推荐人报备参数 |
|
||||
|
||||
#### 新增Mapper
|
||||
| 文件路径 | 说明 |
|
||||
|----------|------|
|
||||
| `cms/mapper/CustomerLeadMapper.java` | 客资管理Mapper |
|
||||
| `cms/mapper/LeadDispatchMapper.java` | 派单记录Mapper |
|
||||
| `cms/mapper/LeadFollowLogMapper.java` | 跟进记录Mapper |
|
||||
| `cms/mapper/LeadReferralMapper.java` | 推荐关系Mapper |
|
||||
|
||||
#### 新增Service
|
||||
| 文件路径 | 说明 |
|
||||
|----------|------|
|
||||
| `cms/service/CustomerLeadService.java` | 客资管理服务接口 |
|
||||
| `cms/service/impl/CustomerLeadServiceImpl.java` | 客资管理服务实现 |
|
||||
| `cms/service/LeadReferralService.java` | 推荐人服务接口 |
|
||||
| `cms/service/impl/LeadReferralServiceImpl.java` | 推荐人服务实现 |
|
||||
|
||||
#### 新增Controller
|
||||
| 文件路径 | 说明 |
|
||||
|----------|------|
|
||||
| `cms/controller/CustomerLeadController.java` | 客资管理控制器 |
|
||||
| `cms/controller/LeadReferralController.java` | 推荐人控制器 |
|
||||
|
||||
#### API端点
|
||||
| 接口 | 方法 | 说明 |
|
||||
|------|------|------|
|
||||
| `/customer/lead/page` | GET | 分页查询客资列表 |
|
||||
| `/customer/lead/detail/{leadId}` | GET | 获取客资详情 |
|
||||
| `/customer/lead/create` | POST | 创建客资 |
|
||||
| `/customer/lead/update` | PUT | 更新客资信息 |
|
||||
| `/customer/lead/status/{leadId}` | PUT | 更新客资状态 |
|
||||
| `/customer/lead/dispatch` | POST | 派单给业务员 |
|
||||
| `/customer/lead/dispatch/batch` | POST | 批量派单 |
|
||||
| `/customer/lead/follow` | POST | 添加跟进记录 |
|
||||
| `/customer/lead/follow/history/{leadId}` | GET | 获取跟进历史 |
|
||||
| `/customer/lead/statistics` | GET | 获取统计数据 |
|
||||
| `/customer/lead/export` | GET | 导出客资数据 |
|
||||
| `/customer/lead/unassigned` | GET | 获取未分配客资 |
|
||||
| `/lead/referral/anonymous` | POST | 匿名用户报备 |
|
||||
| `/lead/referral/user` | POST | 注册用户报备 |
|
||||
| `/lead/referral/page` | GET | 推荐人推荐记录 |
|
||||
| `/lead/referral/stats/{userId}` | GET | 推荐人统计 |
|
||||
|
||||
---
|
||||
|
||||
### 2.2 Vue后台管理端 (`/Users/gxwebsoft/VUE/mp-vue`)
|
||||
|
||||
#### 新增API
|
||||
| 文件路径 | 说明 |
|
||||
|----------|------|
|
||||
| `api/cms/customerLead/model.ts` | 类型定义 |
|
||||
| `api/cms/customerLead/index.ts` | API接口 |
|
||||
|
||||
#### 新增页面
|
||||
| 文件路径 | 说明 |
|
||||
|----------|------|
|
||||
| `views/cms/customerLead/index.vue` | 客资管理列表页面 |
|
||||
|
||||
**功能特性**:
|
||||
- 客资列表(分页、筛选、搜索)
|
||||
- 统计卡片(总客资、待跟进、已成交、成交金额)
|
||||
- 新增/编辑客资
|
||||
- 派单给业务员(支持批量派单)
|
||||
- 添加跟进记录
|
||||
- 查看跟进历史
|
||||
- 客资详情弹窗
|
||||
|
||||
---
|
||||
|
||||
### 2.3 微信小程序端 (`/Users/gxwebsoft/VUE/template-10582`)
|
||||
|
||||
#### 新增API
|
||||
| 文件路径 | 说明 |
|
||||
|----------|------|
|
||||
| `api/shop/referral.ts` | 推荐人API |
|
||||
|
||||
#### 新增页面
|
||||
| 文件路径 | 说明 |
|
||||
|----------|------|
|
||||
| `dealer/referral/index.config.ts` | 页面配置 |
|
||||
| `dealer/referral/index.tsx` | 推荐人报备页面 |
|
||||
| `dealer/referral/index.scss` | 页面样式 |
|
||||
|
||||
**功能特性**:
|
||||
- 推荐人统计(总推荐、待确认、有效、待结算金额)
|
||||
- 推荐新客户表单
|
||||
- 推荐记录列表
|
||||
- 状态追踪
|
||||
|
||||
#### 首页入口
|
||||
在分销商首页 `/dealer/index.tsx` 添加了「推荐客户」入口
|
||||
|
||||
---
|
||||
|
||||
## 三、数据字典
|
||||
|
||||
### 客资状态
|
||||
| 值 | 文本 | 说明 |
|
||||
|----|------|------|
|
||||
| 0 | 待跟进 | 新客资,未分配或未联系 |
|
||||
| 1 | 跟进中 | 正在跟进 |
|
||||
| 2 | 已成交 | 客户已付款 |
|
||||
| 3 | 无效 | 商机流失 |
|
||||
|
||||
### 客资来源
|
||||
| 值 | 文本 | 说明 |
|
||||
|----|------|------|
|
||||
| form | 表单 | 网站/小程序表单提交 |
|
||||
| website | 网站 | 网站表单 |
|
||||
| miniapp | 小程序 | 小程序表单 |
|
||||
| referral | 推荐人 | 推荐人报备 |
|
||||
| admin | 管理员录入 | 后台手动添加 |
|
||||
|
||||
### 跟进方式
|
||||
| 值 | 文本 | 说明 |
|
||||
|----|------|------|
|
||||
| 1 | 电话 | 电话沟通 |
|
||||
| 2 | 微信 | 微信联系 |
|
||||
| 3 | 上门 | 上门拜访 |
|
||||
| 4 | 短信 | 短信通知 |
|
||||
| 5 | 其他 | 其他方式 |
|
||||
|
||||
### 推荐状态
|
||||
| 值 | 文本 | 说明 |
|
||||
|----|------|------|
|
||||
| 0 | 待确认 | 等待管理员确认 |
|
||||
| 1 | 有效 | 推荐有效 |
|
||||
| 2 | 无效 | 推荐无效 |
|
||||
| 3 | 已结算 | 推荐费已结算 |
|
||||
|
||||
---
|
||||
|
||||
## 四、部署说明
|
||||
|
||||
### 4.1 数据库部署
|
||||
```bash
|
||||
# 执行SQL脚本
|
||||
mysql -u root -p your_database < docs/sql/customer_lead_system.sql
|
||||
```
|
||||
|
||||
### 4.2 后端部署
|
||||
1. 重新编译Java项目
|
||||
2. 部署到应用服务器
|
||||
3. 确保Mapper XML文件正确部署
|
||||
|
||||
### 4.3 前端部署
|
||||
1. Vue后台:`npm run build` 部署dist目录
|
||||
2. 小程序:使用Taro构建并上传
|
||||
|
||||
---
|
||||
|
||||
## 五、后续优化建议
|
||||
|
||||
1. **权限细化**:根据实际业务需求,配置细粒度的按钮权限
|
||||
2. **数据看板**:开发可视化数据大屏
|
||||
3. **消息通知**:接入微信模板消息,实时推送派单/跟进通知
|
||||
4. **小程序入口**:在首页增加「全民推荐」独立入口(非分销商专属)
|
||||
5. **推荐海报**:生成带参数的推广海报,方便分享传播
|
||||
6. **佣金结算**:完善佣金提现流程
|
||||
|
||||
---
|
||||
|
||||
## 六、注意事项
|
||||
|
||||
1. **SQL执行顺序**:先执行数据库变更SQL,再部署后端代码
|
||||
2. **Mapper XML**:需要创建对应的Mapper XML文件
|
||||
3. **权限配置**:在后台管理系统中配置对应的菜单和按钮权限
|
||||
4. **推荐费配置**:可后续在配置表中添加推荐费比例等配置项
|
||||
|
||||
---
|
||||
|
||||
*文档生成时间:2026-04-14*
|
||||
178
docs/sql/customer_lead_system.sql
Normal file
178
docs/sql/customer_lead_system.sql
Normal file
@@ -0,0 +1,178 @@
|
||||
-- =====================================================
|
||||
-- 客资管理系统数据库变更脚本
|
||||
-- 适用于: mp-java 数据库
|
||||
-- 创建时间: 2026-04-14
|
||||
-- =====================================================
|
||||
|
||||
-- 1. 扩展客资表 - 添加派单、推荐人相关字段
|
||||
ALTER TABLE cms_contact_lead
|
||||
ADD COLUMN assigned_user_id INT DEFAULT NULL COMMENT '被分配的业务员用户ID',
|
||||
ADD COLUMN referrer_user_id INT DEFAULT NULL COMMENT '推荐人用户ID(全民推荐)',
|
||||
ADD COLUMN referral_fee DECIMAL(10,2) DEFAULT 0.00 COMMENT '推荐费金额',
|
||||
ADD COLUMN referral_fee_paid TINYINT DEFAULT 0 COMMENT '推荐费是否已支付 0否 1是',
|
||||
ADD COLUMN referrer_share DECIMAL(5,2) DEFAULT 0.00 COMMENT '推荐人分成比例%',
|
||||
ADD COLUMN dispatch_time DATETIME DEFAULT NULL COMMENT '派单时间',
|
||||
ADD COLUMN dispatch_admin_id INT DEFAULT NULL COMMENT '派单管理员ID',
|
||||
ADD COLUMN follow_count INT DEFAULT 0 COMMENT '跟进次数',
|
||||
ADD COLUMN last_follow_time DATETIME DEFAULT NULL COMMENT '最后跟进时间',
|
||||
ADD COLUMN appointment_time DATETIME DEFAULT NULL COMMENT '预约时间',
|
||||
ADD COLUMN deal_amount DECIMAL(12,2) DEFAULT NULL COMMENT '成交金额',
|
||||
ADD COLUMN deal_time DATETIME DEFAULT NULL COMMENT '成交时间',
|
||||
ADD COLUMN source_type VARCHAR(20) DEFAULT 'form' COMMENT '来源类型: form表单 website网站 miniapp小程序 referral推荐人 admin录入';
|
||||
|
||||
-- 创建索引
|
||||
CREATE INDEX idx_lead_assigned ON cms_contact_lead(assigned_user_id);
|
||||
CREATE INDEX idx_lead_referrer ON cms_contact_lead(referrer_user_id);
|
||||
CREATE INDEX idx_lead_status ON cms_contact_lead(status);
|
||||
CREATE INDEX idx_lead_source ON cms_contact_lead(source_type);
|
||||
|
||||
-- 2. 派单记录表
|
||||
CREATE TABLE IF NOT EXISTS lead_dispatch (
|
||||
dispatch_id INT PRIMARY KEY AUTO_INCREMENT COMMENT '派单ID',
|
||||
lead_id INT NOT NULL COMMENT '客资ID',
|
||||
from_user_id INT DEFAULT NULL COMMENT '原分配用户ID(如果重新分配)',
|
||||
to_user_id INT NOT NULL COMMENT '新分配用户ID(业务员)',
|
||||
admin_id INT NOT NULL COMMENT '执行派单的管理员ID',
|
||||
dispatch_remarks VARCHAR(500) DEFAULT NULL COMMENT '派单备注',
|
||||
dispatch_type TINYINT DEFAULT 1 COMMENT '派单类型: 1新分配 2重新分配 3抢单',
|
||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '派单时间',
|
||||
INDEX idx_dispatch_lead (lead_id),
|
||||
INDEX idx_dispatch_to_user (to_user_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='客资派单记录表';
|
||||
|
||||
-- 3. 跟进记录表
|
||||
CREATE TABLE IF NOT EXISTS lead_follow_log (
|
||||
follow_id INT PRIMARY KEY AUTO_INCREMENT,
|
||||
lead_id INT NOT NULL COMMENT '客资ID',
|
||||
user_id INT NOT NULL COMMENT '跟进人ID',
|
||||
follow_type TINYINT NOT NULL COMMENT '跟进方式: 1电话 2微信 3上门 4短信 5其他',
|
||||
follow_content VARCHAR(1000) NOT NULL COMMENT '跟进内容',
|
||||
next_follow_time DATETIME DEFAULT NULL COMMENT '下次跟进时间',
|
||||
next_follow_plan VARCHAR(500) DEFAULT NULL COMMENT '下次跟进计划',
|
||||
attachment_urls VARCHAR(1000) DEFAULT NULL COMMENT '附件URLs(JSON数组)',
|
||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
INDEX idx_follow_lead (lead_id),
|
||||
INDEX idx_follow_user (user_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='客资跟进记录表';
|
||||
|
||||
-- 4. 推荐人关系表(全民推荐)
|
||||
CREATE TABLE IF NOT EXISTS lead_referral (
|
||||
referral_id INT PRIMARY KEY AUTO_INCREMENT,
|
||||
referrer_user_id INT NOT NULL COMMENT '推荐人用户ID',
|
||||
referred_lead_id INT NOT NULL COMMENT '被推荐的客资ID',
|
||||
referral_code VARCHAR(32) DEFAULT NULL COMMENT '推荐码(用于匿名推荐)',
|
||||
referral_fee DECIMAL(10,2) NOT NULL DEFAULT 0.00 COMMENT '推荐费',
|
||||
referral_status TINYINT DEFAULT 0 COMMENT '推荐状态: 0待确认 1有效 2无效 3已结算',
|
||||
customer_name VARCHAR(100) DEFAULT NULL COMMENT '客户姓名(匿名推荐时存储)',
|
||||
customer_phone VARCHAR(20) DEFAULT NULL COMMENT '客户电话(匿名推荐时存储)',
|
||||
settlement_time DATETIME DEFAULT NULL COMMENT '结算时间',
|
||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
INDEX idx_referral_referrer (referrer_user_id),
|
||||
INDEX idx_referral_lead (referred_lead_id),
|
||||
INDEX idx_referral_code (referral_code)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='客资推荐关系表';
|
||||
|
||||
-- 5. 用户角色扩展表(多管理员支持)
|
||||
CREATE TABLE IF NOT EXISTS gxwebsoft_core.sys_user_role_extend (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT,
|
||||
user_id INT NOT NULL COMMENT '用户ID',
|
||||
role_type VARCHAR(20) NOT NULL COMMENT '角色类型: admin管理员 salesman业务员 referrer推荐人',
|
||||
is_primary TINYINT DEFAULT 1 COMMENT '是否主角色 0否 1是',
|
||||
permissions JSON DEFAULT NULL COMMENT '权限配置(JSON)',
|
||||
max_leads INT DEFAULT NULL COMMENT '最大客资分配数(业务员)',
|
||||
commission_rate DECIMAL(5,2) DEFAULT NULL COMMENT '佣金比例%(业务员)',
|
||||
referral_bonus DECIMAL(10,2) DEFAULT NULL COMMENT '推荐奖金%(推荐人)',
|
||||
status TINYINT DEFAULT 1 COMMENT '状态: 0禁用 1启用',
|
||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_user_role (user_id, role_type),
|
||||
INDEX idx_user (user_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户角色扩展表';
|
||||
|
||||
-- 6. 数据统计汇总表(定期生成报表用)
|
||||
CREATE TABLE IF NOT EXISTS lead_statistics (
|
||||
stat_id INT PRIMARY KEY AUTO_INCREMENT,
|
||||
stat_date DATE NOT NULL COMMENT '统计日期',
|
||||
user_id INT DEFAULT NULL COMMENT '用户ID(Null表示全站)',
|
||||
role_type VARCHAR(20) DEFAULT NULL COMMENT '角色类型',
|
||||
total_leads INT DEFAULT 0 COMMENT '总客资数',
|
||||
new_leads INT DEFAULT 0 COMMENT '新增客资数',
|
||||
assigned_leads INT DEFAULT 0 COMMENT '已分配客资数',
|
||||
followed_leads INT DEFAULT 0 COMMENT '已跟进客资数',
|
||||
dealed_leads INT DEFAULT 0 COMMENT '已成交客资数',
|
||||
deal_amount DECIMAL(15,2) DEFAULT 0.00 COMMENT '成交总金额',
|
||||
referral_count INT DEFAULT 0 COMMENT '推荐成功数',
|
||||
referral_fee DECIMAL(12,2) DEFAULT 0.00 COMMENT '推荐费总额',
|
||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uk_stat_date_user (stat_date, user_id, role_type),
|
||||
INDEX idx_stat_date (stat_date)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='客资数据统计表';
|
||||
|
||||
-- 7. 推荐费结算记录表
|
||||
CREATE TABLE IF NOT EXISTS lead_referral_settlement (
|
||||
settlement_id INT PRIMARY KEY AUTO_INCREMENT,
|
||||
referral_id INT NOT NULL COMMENT '推荐关系ID',
|
||||
referrer_user_id INT NOT NULL COMMENT '推荐人ID',
|
||||
lead_id INT NOT NULL COMMENT '关联客资ID',
|
||||
settlement_amount DECIMAL(10,2) NOT NULL COMMENT '结算金额',
|
||||
settlement_type TINYINT DEFAULT 1 COMMENT '结算方式: 1自动 2手动',
|
||||
settlement_admin_id INT DEFAULT NULL COMMENT '操作管理员ID',
|
||||
settlement_remarks VARCHAR(500) DEFAULT NULL COMMENT '结算备注',
|
||||
status TINYINT DEFAULT 0 COMMENT '状态: 0待确认 1已转账 2已到账',
|
||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
confirm_time DATETIME DEFAULT NULL COMMENT '确认时间',
|
||||
INDEX idx_settlement_referrer (referrer_user_id),
|
||||
INDEX idx_settlement_lead (lead_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='推荐费结算记录表';
|
||||
|
||||
-- =====================================================
|
||||
-- 初始化数据
|
||||
-- =====================================================
|
||||
|
||||
-- 插入默认管理员角色扩展
|
||||
INSERT INTO gxwebsoft_core.sys_user_role_extend (user_id, role_type, is_primary, permissions, status)
|
||||
SELECT user_id, 'admin', 1, '{"canDispatch": true, "canManageUsers": true, "canViewStats": true, "canSetCommission": true}', 1
|
||||
FROM gxwebsoft_core.sys_user WHERE status = 0 AND deleted = 0 LIMIT 1;
|
||||
|
||||
-- =====================================================
|
||||
-- 视图: 客资完整信息视图
|
||||
-- =====================================================
|
||||
CREATE OR REPLACE VIEW v_lead_full_info AS
|
||||
SELECT
|
||||
l.lead_id,
|
||||
l.name AS customer_name,
|
||||
l.phone AS customer_phone,
|
||||
l.company,
|
||||
l.need AS requirement,
|
||||
l.status,
|
||||
l.source_type,
|
||||
l.create_time,
|
||||
l.dispatch_time,
|
||||
l.deal_amount,
|
||||
l.deal_time,
|
||||
l.referral_fee,
|
||||
l.referral_fee_paid,
|
||||
au.user_id AS assigned_user_id,
|
||||
au.nickname AS assigned_user_name,
|
||||
au.real_name AS assigned_real_name,
|
||||
au.phone AS assigned_user_phone,
|
||||
ru.user_id AS referrer_user_id,
|
||||
ru.nickname AS referrer_name,
|
||||
ru.phone AS referrer_phone,
|
||||
admin.user_id AS dispatch_admin_id,
|
||||
admin.nickname AS dispatch_admin_name,
|
||||
l.follow_count,
|
||||
l.last_follow_time,
|
||||
l.appointment_time,
|
||||
CASE l.status
|
||||
WHEN 0 THEN '待跟进'
|
||||
WHEN 1 THEN '跟进中'
|
||||
WHEN 2 THEN '已成交'
|
||||
WHEN 3 THEN '无效'
|
||||
ELSE '未知'
|
||||
END AS status_text
|
||||
FROM cms_contact_lead l
|
||||
LEFT JOIN gxwebsoft_core.sys_user au ON l.assigned_user_id = au.user_id
|
||||
LEFT JOIN gxwebsoft_core.sys_user ru ON l.referrer_user_id = ru.user_id
|
||||
LEFT JOIN gxwebsoft_core.sys_user admin ON l.dispatch_admin_id = admin.user_id
|
||||
WHERE l.deleted = 0;
|
||||
@@ -0,0 +1,132 @@
|
||||
package com.gxwebsoft.cms.controller;
|
||||
|
||||
import com.gxwebsoft.cms.param.CustomerLeadParam;
|
||||
import com.gxwebsoft.cms.param.LeadDispatchParam;
|
||||
import com.gxwebsoft.cms.param.LeadFollowParam;
|
||||
import com.gxwebsoft.cms.service.CustomerLeadService;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 客资管理控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-04-14
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/customer/lead")
|
||||
@Tag(name = "客资管理", description = "客资管理相关接口")
|
||||
public class CustomerLeadController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private CustomerLeadService customerLeadService;
|
||||
|
||||
@Operation(summary = "分页查询客资列表")
|
||||
@GetMapping("/page")
|
||||
@PreAuthorize("@pms.hasPermission('customer:lead:page') or @pms.hasPermission('customer:lead:view')")
|
||||
public ApiResult<Map<String, Object>> getLeadPage(CustomerLeadParam param) {
|
||||
return success(customerLeadService.getLeadPage(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "获取客资详情")
|
||||
@GetMapping("/detail/{leadId}")
|
||||
@PreAuthorize("@pms.hasPermission('customer:lead:detail') or @pms.hasPermission('customer:lead:view')")
|
||||
public ApiResult<?> getLeadDetail(
|
||||
@Parameter(description = "客资ID") @PathVariable Integer leadId) {
|
||||
return success(customerLeadService.getLeadDetail(leadId));
|
||||
}
|
||||
|
||||
@Operation(summary = "创建客资(管理员录入)")
|
||||
@PostMapping("/create")
|
||||
@PreAuthorize("@pms.hasPermission('customer:lead:create')")
|
||||
public ApiResult<?> createLead(@RequestBody CustomerLeadParam param) {
|
||||
return success(customerLeadService.createLead(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "更新客资信息")
|
||||
@PutMapping("/update")
|
||||
@PreAuthorize("@pms.hasPermission('customer:lead:update')")
|
||||
public ApiResult<?> updateLead(@RequestBody CustomerLeadParam param) {
|
||||
return success(customerLeadService.updateLead(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "更新客资状态")
|
||||
@PutMapping("/status/{leadId}")
|
||||
@PreAuthorize("@pms.hasPermission('customer:lead:status')")
|
||||
public ApiResult<?> updateLeadStatus(
|
||||
@Parameter(description = "客资ID") @PathVariable Integer leadId,
|
||||
@Parameter(description = "状态") @RequestParam Integer status,
|
||||
@Parameter(description = "备注") @RequestParam(required = false) String remarks) {
|
||||
return success(customerLeadService.updateLeadStatus(leadId, status, remarks));
|
||||
}
|
||||
|
||||
@Operation(summary = "派单给业务员")
|
||||
@PostMapping("/dispatch")
|
||||
@PreAuthorize("@pms.hasPermission('customer:lead:dispatch')")
|
||||
public ApiResult<?> dispatchLead(@RequestBody LeadDispatchParam param) {
|
||||
return success(customerLeadService.dispatchLead(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "批量派单")
|
||||
@PostMapping("/dispatch/batch")
|
||||
@PreAuthorize("@pms.hasPermission('customer:lead:dispatch')")
|
||||
public ApiResult<?> batchDispatchLeads(@RequestBody LeadDispatchParam param) {
|
||||
return success(customerLeadService.batchDispatchLeads(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "添加跟进记录")
|
||||
@PostMapping("/follow")
|
||||
@PreAuthorize("@pms.hasPermission('customer:lead:follow')")
|
||||
public ApiResult<?> addFollowLog(@RequestBody LeadFollowParam param) {
|
||||
return success(customerLeadService.addFollowLog(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "获取跟进历史")
|
||||
@GetMapping("/follow/history/{leadId}")
|
||||
@PreAuthorize("@pms.hasPermission('customer:lead:view')")
|
||||
public ApiResult<?> getFollowHistory(
|
||||
@Parameter(description = "客资ID") @PathVariable Integer leadId) {
|
||||
return success(customerLeadService.getFollowHistory(leadId));
|
||||
}
|
||||
|
||||
@Operation(summary = "获取统计数据")
|
||||
@GetMapping("/statistics")
|
||||
@PreAuthorize("@pms.hasPermission('customer:lead:statistics')")
|
||||
public ApiResult<?> getStatistics(CustomerLeadParam param) {
|
||||
return success(customerLeadService.getStatistics(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "导出客资数据")
|
||||
@GetMapping("/export")
|
||||
@PreAuthorize("@pms.hasPermission('customer:lead:export')")
|
||||
public ApiResult<?> exportLeads(CustomerLeadParam param) {
|
||||
List<Map<String, Object>> data = customerLeadService.exportLeads(param);
|
||||
return success(data);
|
||||
}
|
||||
|
||||
@Operation(summary = "获取未分配客资")
|
||||
@GetMapping("/unassigned")
|
||||
@PreAuthorize("@pms.hasPermission('customer:lead:view')")
|
||||
public ApiResult<?> getUnassignedLeads() {
|
||||
return success(customerLeadService.getUnassignedLeads());
|
||||
}
|
||||
|
||||
@Operation(summary = "获取业务员客资统计")
|
||||
@GetMapping("/salesman/stats/{salesmanId}")
|
||||
@PreAuthorize("@pms.hasPermission('customer:lead:view')")
|
||||
public ApiResult<?> getSalesmanLeadStats(
|
||||
@Parameter(description = "业务员ID") @PathVariable Integer salesmanId) {
|
||||
return success(customerLeadService.getSalesmanLeadStats(salesmanId));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package com.gxwebsoft.cms.controller;
|
||||
|
||||
import com.gxwebsoft.cms.param.CustomerLeadParam;
|
||||
import com.gxwebsoft.cms.param.LeadReferralParam;
|
||||
import com.gxwebsoft.cms.service.LeadReferralService;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 推荐人控制器(全民推荐)
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-04-14
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/lead/referral")
|
||||
@Tag(name = "全民推荐", description = "推荐人报备相关接口")
|
||||
public class LeadReferralController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private LeadReferralService leadReferralService;
|
||||
|
||||
@Operation(summary = "匿名用户报备客户")
|
||||
@PostMapping("/anonymous")
|
||||
public ApiResult<?> anonymousReferral(@RequestBody LeadReferralParam param) {
|
||||
return success(leadReferralService.anonymousReferral(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "注册用户报备客户")
|
||||
@PostMapping("/user")
|
||||
@PreAuthorize("@pms.hasPermission('referral:user') or true")
|
||||
public ApiResult<?> userReferral(@RequestBody LeadReferralParam param) {
|
||||
return success(leadReferralService.userReferral(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "获取推荐人的推荐记录")
|
||||
@GetMapping("/page")
|
||||
@PreAuthorize("@pms.hasPermission('referral:page') or @pms.hasPermission('referral:view')")
|
||||
public ApiResult<Map<String, Object>> getReferralPage(CustomerLeadParam param) {
|
||||
return success(leadReferralService.getReferralPage(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "获取推荐人统计")
|
||||
@GetMapping("/stats/{userId}")
|
||||
@PreAuthorize("@pms.hasPermission('referral:view')")
|
||||
public ApiResult<?> getReferralStats(
|
||||
@Parameter(description = "用户ID") @PathVariable Integer userId) {
|
||||
return success(leadReferralService.getReferralStats(userId));
|
||||
}
|
||||
|
||||
@Operation(summary = "生成推荐码")
|
||||
@GetMapping("/generateCode")
|
||||
@PreAuthorize("@pms.hasPermission('referral:generate')")
|
||||
public ApiResult<?> generateReferralCode() {
|
||||
return success(leadReferralService.generateReferralCode());
|
||||
}
|
||||
|
||||
@Operation(summary = "根据推荐码获取推荐人信息")
|
||||
@GetMapping("/referrer/{code}")
|
||||
public ApiResult<?> getReferrerByCode(
|
||||
@Parameter(description = "推荐码") @PathVariable String code) {
|
||||
return success(leadReferralService.getReferrerByCode(code));
|
||||
}
|
||||
|
||||
@Operation(summary = "确认推荐有效(管理员)")
|
||||
@PutMapping("/confirm/{referralId}")
|
||||
@PreAuthorize("@pms.hasPermission('referral:confirm')")
|
||||
public ApiResult<?> confirmReferral(
|
||||
@Parameter(description = "推荐ID") @PathVariable Integer referralId) {
|
||||
return success(leadReferralService.confirmReferral(referralId));
|
||||
}
|
||||
|
||||
@Operation(summary = "作废推荐(管理员)")
|
||||
@PutMapping("/invalidate/{referralId}")
|
||||
@PreAuthorize("@pms.hasPermission('referral:invalidate')")
|
||||
public ApiResult<?> invalidateReferral(
|
||||
@Parameter(description = "推荐ID") @PathVariable Integer referralId,
|
||||
@Parameter(description = "原因") @RequestParam(required = false) String reason) {
|
||||
return success(leadReferralService.invalidateReferral(referralId, reason));
|
||||
}
|
||||
|
||||
@Operation(summary = "结算推荐费(管理员)")
|
||||
@PutMapping("/settle/{referralId}")
|
||||
@PreAuthorize("@pms.hasPermission('referral:settle')")
|
||||
public ApiResult<?> settleReferral(
|
||||
@Parameter(description = "推荐ID") @PathVariable Integer referralId) {
|
||||
return success(leadReferralService.settleReferral(referralId));
|
||||
}
|
||||
|
||||
@Operation(summary = "批量结算推荐费")
|
||||
@PutMapping("/settle/batch")
|
||||
@PreAuthorize("@pms.hasPermission('referral:settle')")
|
||||
public ApiResult<?> batchSettleReferrals(@RequestBody Integer[] referralIds) {
|
||||
return success(leadReferralService.batchSettleReferrals(referralIds));
|
||||
}
|
||||
}
|
||||
112
src/main/java/com/gxwebsoft/cms/entity/CustomerLeadEntity.java
Normal file
112
src/main/java/com/gxwebsoft/cms/entity/CustomerLeadEntity.java
Normal file
@@ -0,0 +1,112 @@
|
||||
package com.gxwebsoft.cms.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 客资管理扩展实体
|
||||
* 在CmsContactLead基础上扩展派单、推荐人等字段
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-04-14
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("cms_contact_lead")
|
||||
@Schema(name = "CustomerLeadEntity", description = "客资管理扩展实体")
|
||||
public class CustomerLeadEntity extends CmsContactLead implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "被分配的业务员用户ID")
|
||||
private Integer assignedUserId;
|
||||
|
||||
@Schema(description = "推荐人用户ID")
|
||||
private Integer referrerUserId;
|
||||
|
||||
@Schema(description = "推荐费金额")
|
||||
private BigDecimal referralFee;
|
||||
|
||||
@Schema(description = "推荐费是否已支付 0否 1是")
|
||||
private Integer referralFeePaid;
|
||||
|
||||
@Schema(description = "推荐人分成比例%")
|
||||
private BigDecimal referrerShare;
|
||||
|
||||
@Schema(description = "派单时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime dispatchTime;
|
||||
|
||||
@Schema(description = "派单管理员ID")
|
||||
private Integer dispatchAdminId;
|
||||
|
||||
@Schema(description = "跟进次数")
|
||||
private Integer followCount;
|
||||
|
||||
@Schema(description = "最后跟进时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime lastFollowTime;
|
||||
|
||||
@Schema(description = "预约时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime appointmentTime;
|
||||
|
||||
@Schema(description = "成交金额")
|
||||
private BigDecimal dealAmount;
|
||||
|
||||
@Schema(description = "成交时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime dealTime;
|
||||
|
||||
@Schema(description = "来源类型: form表单 website网站 miniapp小程序 referral推荐人 admin录入")
|
||||
private String sourceType;
|
||||
|
||||
// ========== 关联用户信息(非数据库字段)==========
|
||||
@Schema(description = "被分配的业务员昵称")
|
||||
private String assignedUserName;
|
||||
|
||||
@Schema(description = "被分配的业务员真实姓名")
|
||||
private String assignedRealName;
|
||||
|
||||
@Schema(description = "被分配的业务员电话")
|
||||
private String assignedUserPhone;
|
||||
|
||||
@Schema(description = "推荐人昵称")
|
||||
private String referrerName;
|
||||
|
||||
@Schema(description = "推荐人电话")
|
||||
private String referrerPhone;
|
||||
|
||||
@Schema(description = "派单管理员昵称")
|
||||
private String dispatchAdminName;
|
||||
|
||||
@Schema(description = "业务员跟进次数统计")
|
||||
private Integer userLeadCount;
|
||||
|
||||
@Schema(description = "业务员本月成交数")
|
||||
private Integer userDealCount;
|
||||
|
||||
// ========== 来源类型常量 ==========
|
||||
public static final String SOURCE_FORM = "form"; // 表单
|
||||
public static final String SOURCE_WEBSITE = "website"; // 网站
|
||||
public static final String SOURCE_MINIAPP = "miniapp"; // 小程序
|
||||
public static final String SOURCE_REFERRAL = "referral"; // 推荐人
|
||||
public static final String SOURCE_ADMIN = "admin"; // 管理员录入
|
||||
|
||||
// ========== 状态常量 ==========
|
||||
public static final int STATUS_PENDING = 0; // 待跟进
|
||||
public static final int STATUS_FOLLOWING = 1; // 跟进中
|
||||
public static final int STATUS_DEALED = 2; // 已成交
|
||||
public static final int STATUS_INVALID = 3; // 无效
|
||||
|
||||
}
|
||||
69
src/main/java/com/gxwebsoft/cms/entity/LeadDispatch.java
Normal file
69
src/main/java/com/gxwebsoft/cms/entity/LeadDispatch.java
Normal file
@@ -0,0 +1,69 @@
|
||||
package com.gxwebsoft.cms.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 客资派单记录实体
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-04-14
|
||||
*/
|
||||
@Data
|
||||
@TableName("lead_dispatch")
|
||||
@Schema(name = "LeadDispatch", description = "客资派单记录")
|
||||
public class LeadDispatch implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "派单ID")
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Integer dispatchId;
|
||||
|
||||
@Schema(description = "客资ID")
|
||||
private Integer leadId;
|
||||
|
||||
@Schema(description = "原分配用户ID")
|
||||
private Integer fromUserId;
|
||||
|
||||
@Schema(description = "新分配用户ID(业务员)")
|
||||
private Integer toUserId;
|
||||
|
||||
@Schema(description = "执行派单的管理员ID")
|
||||
private Integer adminId;
|
||||
|
||||
@Schema(description = "派单备注")
|
||||
private String dispatchRemarks;
|
||||
|
||||
@Schema(description = "派单类型: 1新分配 2重新分配 3抢单")
|
||||
private Integer dispatchType;
|
||||
|
||||
@Schema(description = "派单时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
// ========== 关联信息(非数据库字段)==========
|
||||
@Schema(description = "业务员昵称")
|
||||
private String toUserName;
|
||||
|
||||
@Schema(description = "管理员昵称")
|
||||
private String adminName;
|
||||
|
||||
@Schema(description = "客资客户姓名")
|
||||
private String leadCustomerName;
|
||||
|
||||
@Schema(description = "客资客户电话")
|
||||
private String leadCustomerPhone;
|
||||
|
||||
// ========== 派单类型常量 ==========
|
||||
public static final int TYPE_NEW = 1; // 新分配
|
||||
public static final int TYPE_REDISPATCH = 2; // 重新分配
|
||||
public static final int TYPE_GRAB = 3; // 抢单
|
||||
}
|
||||
84
src/main/java/com/gxwebsoft/cms/entity/LeadFollowLog.java
Normal file
84
src/main/java/com/gxwebsoft/cms/entity/LeadFollowLog.java
Normal file
@@ -0,0 +1,84 @@
|
||||
package com.gxwebsoft.cms.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 客资跟进记录实体
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-04-14
|
||||
*/
|
||||
@Data
|
||||
@TableName("lead_follow_log")
|
||||
@Schema(name = "LeadFollowLog", description = "客资跟进记录")
|
||||
public class LeadFollowLog implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "跟进ID")
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Integer followId;
|
||||
|
||||
@Schema(description = "客资ID")
|
||||
private Integer leadId;
|
||||
|
||||
@Schema(description = "跟进人ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "跟进方式: 1电话 2微信 3上门 4短信 5其他")
|
||||
private Integer followType;
|
||||
|
||||
@Schema(description = "跟进内容")
|
||||
private String followContent;
|
||||
|
||||
@Schema(description = "下次跟进时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime nextFollowTime;
|
||||
|
||||
@Schema(description = "下次跟进计划")
|
||||
private String nextFollowPlan;
|
||||
|
||||
@Schema(description = "附件URLs(JSON数组)")
|
||||
private String attachmentUrls;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
// ========== 关联信息(非数据库字段)==========
|
||||
@Schema(description = "跟进人昵称")
|
||||
private String userName;
|
||||
|
||||
@Schema(description = "客资客户姓名")
|
||||
private String customerName;
|
||||
|
||||
@Schema(description = "客资客户电话")
|
||||
private String customerPhone;
|
||||
|
||||
// ========== 跟进方式常量 ==========
|
||||
public static final int TYPE_PHONE = 1; // 电话
|
||||
public static final int TYPE_WECHAT = 2; // 微信
|
||||
public static final int TYPE_VISIT = 3; // 上门
|
||||
public static final int TYPE_SMS = 4; // 短信
|
||||
public static final int TYPE_OTHER = 5; // 其他
|
||||
|
||||
public String getFollowTypeText() {
|
||||
if (this.followType == null) return "";
|
||||
return switch (this.followType) {
|
||||
case TYPE_PHONE -> "电话";
|
||||
case TYPE_WECHAT -> "微信";
|
||||
case TYPE_VISIT -> "上门";
|
||||
case TYPE_SMS -> "短信";
|
||||
case TYPE_OTHER -> "其他";
|
||||
default -> "";
|
||||
};
|
||||
}
|
||||
}
|
||||
89
src/main/java/com/gxwebsoft/cms/entity/LeadReferral.java
Normal file
89
src/main/java/com/gxwebsoft/cms/entity/LeadReferral.java
Normal file
@@ -0,0 +1,89 @@
|
||||
package com.gxwebsoft.cms.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 推荐人关系实体(全民推荐)
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-04-14
|
||||
*/
|
||||
@Data
|
||||
@TableName("lead_referral")
|
||||
@Schema(name = "LeadReferral", description = "推荐人关系")
|
||||
public class LeadReferral implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "推荐关系ID")
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Integer referralId;
|
||||
|
||||
@Schema(description = "推荐人用户ID")
|
||||
private Integer referrerUserId;
|
||||
|
||||
@Schema(description = "被推荐的客资ID")
|
||||
private Integer referredLeadId;
|
||||
|
||||
@Schema(description = "推荐码")
|
||||
private String referralCode;
|
||||
|
||||
@Schema(description = "推荐费")
|
||||
private BigDecimal referralFee;
|
||||
|
||||
@Schema(description = "推荐状态: 0待确认 1有效 2无效 3已结算")
|
||||
private Integer referralStatus;
|
||||
|
||||
@Schema(description = "客户姓名")
|
||||
private String customerName;
|
||||
|
||||
@Schema(description = "客户电话")
|
||||
private String customerPhone;
|
||||
|
||||
@Schema(description = "结算时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime settlementTime;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
// ========== 关联信息(非数据库字段)==========
|
||||
@Schema(description = "推荐人昵称")
|
||||
private String referrerName;
|
||||
|
||||
@Schema(description = "推荐人电话")
|
||||
private String referrerPhone;
|
||||
|
||||
@Schema(description = "客资状态")
|
||||
private Integer leadStatus;
|
||||
|
||||
@Schema(description = "客资成交金额")
|
||||
private BigDecimal dealAmount;
|
||||
|
||||
// ========== 状态常量 ==========
|
||||
public static final int STATUS_PENDING = 0; // 待确认
|
||||
public static final int STATUS_VALID = 1; // 有效
|
||||
public static final int STATUS_INVALID = 2; // 无效
|
||||
public static final int STATUS_SETTLED = 3; // 已结算
|
||||
|
||||
public String getStatusText() {
|
||||
if (this.referralStatus == null) return "";
|
||||
return switch (this.referralStatus) {
|
||||
case STATUS_PENDING -> "待确认";
|
||||
case STATUS_VALID -> "有效";
|
||||
case STATUS_INVALID -> "无效";
|
||||
case STATUS_SETTLED -> "已结算";
|
||||
default -> "";
|
||||
};
|
||||
}
|
||||
}
|
||||
72
src/main/java/com/gxwebsoft/cms/entity/LeadStatistics.java
Normal file
72
src/main/java/com/gxwebsoft/cms/entity/LeadStatistics.java
Normal file
@@ -0,0 +1,72 @@
|
||||
package com.gxwebsoft.cms.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 客资数据统计实体
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-04-14
|
||||
*/
|
||||
@Data
|
||||
@TableName("lead_statistics")
|
||||
@Schema(name = "LeadStatistics", description = "客资数据统计")
|
||||
public class LeadStatistics implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "统计ID")
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Integer statId;
|
||||
|
||||
@Schema(description = "统计日期")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private LocalDateTime statDate;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "角色类型")
|
||||
private String roleType;
|
||||
|
||||
@Schema(description = "总客资数")
|
||||
private Integer totalLeads;
|
||||
|
||||
@Schema(description = "新增客资数")
|
||||
private Integer newLeads;
|
||||
|
||||
@Schema(description = "已分配客资数")
|
||||
private Integer assignedLeads;
|
||||
|
||||
@Schema(description = "已跟进客资数")
|
||||
private Integer followedLeads;
|
||||
|
||||
@Schema(description = "已成交客资数")
|
||||
private Integer dealedLeads;
|
||||
|
||||
@Schema(description = "成交总金额")
|
||||
private BigDecimal dealAmount;
|
||||
|
||||
@Schema(description = "推荐成功数")
|
||||
private Integer referralCount;
|
||||
|
||||
@Schema(description = "推荐费总额")
|
||||
private BigDecimal referralFee;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
// ========== 关联信息(非数据库字段)==========
|
||||
@Schema(description = "用户昵称")
|
||||
private String userName;
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package com.gxwebsoft.cms.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.gxwebsoft.cms.entity.CustomerLeadEntity;
|
||||
import com.gxwebsoft.cms.param.CustomerLeadParam;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 客资管理Mapper
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-04-14
|
||||
*/
|
||||
@Mapper
|
||||
public interface CustomerLeadMapper extends BaseMapper<CustomerLeadEntity> {
|
||||
|
||||
/**
|
||||
* 分页查询客资列表
|
||||
*/
|
||||
List<CustomerLeadEntity> selectLeadPage(CustomerLeadParam param);
|
||||
|
||||
/**
|
||||
* 查询客资详情
|
||||
*/
|
||||
CustomerLeadEntity selectLeadDetail(@Param("leadId") Integer leadId);
|
||||
|
||||
/**
|
||||
* 获取业务员待处理客资数量
|
||||
*/
|
||||
Integer countBySalesman(@Param("salesmanId") Integer salesmanId, @Param("status") Integer status);
|
||||
|
||||
/**
|
||||
* 批量更新客资状态
|
||||
*/
|
||||
int batchUpdateStatus(@Param("leadIds") List<Integer> leadIds, @Param("status") Integer status);
|
||||
|
||||
/**
|
||||
* 派单给业务员
|
||||
*/
|
||||
int dispatchToUser(@Param("leadId") Integer leadId, @Param("userId") Integer userId,
|
||||
@Param("adminId") Integer adminId, @Param("remarks") String remarks);
|
||||
|
||||
/**
|
||||
* 统计数据
|
||||
*/
|
||||
Map<String, Object> selectStatistics(@Param("startDate") String startDate, @Param("endDate") String endDate,
|
||||
@Param("salesmanId") Integer salesmanId);
|
||||
|
||||
/**
|
||||
* 按状态统计
|
||||
*/
|
||||
List<Map<String, Object>> selectStatusStatistics(@Param("startDate") String startDate, @Param("endDate") String endDate);
|
||||
|
||||
/**
|
||||
* 按来源统计
|
||||
*/
|
||||
List<Map<String, Object>> selectSourceStatistics(@Param("startDate") String startDate, @Param("endDate") String endDate);
|
||||
|
||||
/**
|
||||
* 按日统计趋势
|
||||
*/
|
||||
List<Map<String, Object>> selectDailyTrend(@Param("startDate") String startDate, @Param("endDate") String endDate);
|
||||
|
||||
/**
|
||||
* 查询未分配客资
|
||||
*/
|
||||
List<CustomerLeadEntity> selectUnassignedLeads();
|
||||
|
||||
/**
|
||||
* 批量派单
|
||||
*/
|
||||
int batchDispatch(@Param("leadIds") List<Integer> leadIds, @Param("userId") Integer userId,
|
||||
@Param("adminId") Integer adminId, @Param("remarks") String remarks);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.gxwebsoft.cms.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.gxwebsoft.cms.entity.LeadDispatch;
|
||||
import com.gxwebsoft.cms.param.CustomerLeadParam;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 客资派单Mapper
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-04-14
|
||||
*/
|
||||
@Mapper
|
||||
public interface LeadDispatchMapper extends BaseMapper<LeadDispatch> {
|
||||
|
||||
/**
|
||||
* 查询客资的派单历史
|
||||
*/
|
||||
List<LeadDispatch> selectDispatchHistory(@Param("leadId") Integer leadId);
|
||||
|
||||
/**
|
||||
* 查询业务员的派单记录
|
||||
*/
|
||||
List<LeadDispatch> selectSalesmanDispatches(CustomerLeadParam param);
|
||||
|
||||
/**
|
||||
* 查询今日派单数量
|
||||
*/
|
||||
Integer countTodayDispatches(@Param("adminId") Integer adminId);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.gxwebsoft.cms.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.gxwebsoft.cms.entity.LeadFollowLog;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 客资跟进记录Mapper
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-04-14
|
||||
*/
|
||||
@Mapper
|
||||
public interface LeadFollowLogMapper extends BaseMapper<LeadFollowLog> {
|
||||
|
||||
/**
|
||||
* 查询客资的跟进历史
|
||||
*/
|
||||
List<LeadFollowLog> selectFollowHistory(@Param("leadId") Integer leadId);
|
||||
|
||||
/**
|
||||
* 查询用户的跟进记录
|
||||
*/
|
||||
List<LeadFollowLog> selectUserFollows(@Param("userId") Integer userId,
|
||||
@Param("startDate") String startDate,
|
||||
@Param("endDate") String endDate);
|
||||
|
||||
/**
|
||||
* 查询需要跟进的客资(根据下次跟进时间)
|
||||
*/
|
||||
List<Integer> selectNeedFollowLeadIds(@Param("userId") Integer userId);
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.gxwebsoft.cms.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.gxwebsoft.cms.entity.LeadReferral;
|
||||
import com.gxwebsoft.cms.param.CustomerLeadParam;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 推荐人关系Mapper
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-04-14
|
||||
*/
|
||||
@Mapper
|
||||
public interface LeadReferralMapper extends BaseMapper<LeadReferral> {
|
||||
|
||||
/**
|
||||
* 分页查询推荐关系
|
||||
*/
|
||||
List<LeadReferral> selectReferralPage(CustomerLeadParam param);
|
||||
|
||||
/**
|
||||
* 查询用户的推荐记录
|
||||
*/
|
||||
List<LeadReferral> selectUserReferrals(@Param("userId") Integer userId);
|
||||
|
||||
/**
|
||||
* 根据推荐码查询
|
||||
*/
|
||||
LeadReferral selectByCode(@Param("referralCode") String referralCode);
|
||||
|
||||
/**
|
||||
* 统计推荐人的推荐数量
|
||||
*/
|
||||
Integer countUserReferrals(@Param("userId") Integer userId, @Param("status") Integer status);
|
||||
|
||||
/**
|
||||
* 统计推荐人待结算金额
|
||||
*/
|
||||
java.math.BigDecimal sumPendingFee(@Param("userId") Integer userId);
|
||||
}
|
||||
81
src/main/java/com/gxwebsoft/cms/param/CustomerLeadParam.java
Normal file
81
src/main/java/com/gxwebsoft/cms/param/CustomerLeadParam.java
Normal file
@@ -0,0 +1,81 @@
|
||||
package com.gxwebsoft.cms.param;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 客资管理请求参数
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-04-14
|
||||
*/
|
||||
@Data
|
||||
@Schema(name = "CustomerLeadParam", description = "客资管理请求参数")
|
||||
public class CustomerLeadParam implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "客资ID")
|
||||
private Integer leadId;
|
||||
|
||||
@Schema(description = "客户姓名")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "客户电话")
|
||||
private String phone;
|
||||
|
||||
@Schema(description = "单位/公司名称")
|
||||
private String company;
|
||||
|
||||
@Schema(description = "需求描述")
|
||||
private String need;
|
||||
|
||||
@Schema(description = "分配给的用户ID")
|
||||
private Integer assignedUserId;
|
||||
|
||||
@Schema(description = "派单备注")
|
||||
private String dispatchRemarks;
|
||||
|
||||
@Schema(description = "跟进状态: 0待跟进 1跟进中 2已成交 3无效")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "销售备注")
|
||||
private String remarks;
|
||||
|
||||
@Schema(description = "预约时间")
|
||||
private String appointmentTime;
|
||||
|
||||
@Schema(description = "成交金额")
|
||||
private BigDecimal dealAmount;
|
||||
|
||||
@Schema(description = "来源类型")
|
||||
private String sourceType;
|
||||
|
||||
// ========== 查询条件 ==========
|
||||
@Schema(description = "开始日期")
|
||||
private String startDate;
|
||||
|
||||
@Schema(description = "结束日期")
|
||||
private String endDate;
|
||||
|
||||
@Schema(description = "跟进状态(可多选,逗号分隔)")
|
||||
private String statusList;
|
||||
|
||||
@Schema(description = "业务员ID")
|
||||
private Integer salesmanId;
|
||||
|
||||
@Schema(description = "推荐人ID")
|
||||
private Integer referrerId;
|
||||
|
||||
@Schema(description = "关键词(姓名/电话/公司)")
|
||||
private String keyword;
|
||||
|
||||
@Schema(description = "当前页码")
|
||||
private Integer pageNum = 1;
|
||||
|
||||
@Schema(description = "每页数量")
|
||||
private Integer pageSize = 10;
|
||||
}
|
||||
38
src/main/java/com/gxwebsoft/cms/param/LeadDispatchParam.java
Normal file
38
src/main/java/com/gxwebsoft/cms/param/LeadDispatchParam.java
Normal file
@@ -0,0 +1,38 @@
|
||||
package com.gxwebsoft.cms.param;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 客资派单请求参数
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-04-14
|
||||
*/
|
||||
@Data
|
||||
@Schema(name = "LeadDispatchParam", description = "客资派单请求参数")
|
||||
public class LeadDispatchParam implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "客资ID")
|
||||
private Integer leadId;
|
||||
|
||||
@Schema(description = "目标用户ID(业务员)")
|
||||
private Integer toUserId;
|
||||
|
||||
@Schema(description = "派单备注")
|
||||
private String remarks;
|
||||
|
||||
@Schema(description = "派单类型: 1新分配 2重新分配")
|
||||
private Integer dispatchType = 1;
|
||||
|
||||
// ========== 批量派单 ==========
|
||||
@Schema(description = "批量客资ID列表")
|
||||
private Integer[] leadIds;
|
||||
|
||||
@Schema(description = "是否批量派单")
|
||||
private Boolean batchMode = false;
|
||||
}
|
||||
43
src/main/java/com/gxwebsoft/cms/param/LeadFollowParam.java
Normal file
43
src/main/java/com/gxwebsoft/cms/param/LeadFollowParam.java
Normal file
@@ -0,0 +1,43 @@
|
||||
package com.gxwebsoft.cms.param;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 客资跟进请求参数
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-04-14
|
||||
*/
|
||||
@Data
|
||||
@Schema(name = "LeadFollowParam", description = "客资跟进请求参数")
|
||||
public class LeadFollowParam implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "客资ID")
|
||||
private Integer leadId;
|
||||
|
||||
@Schema(description = "跟进方式: 1电话 2微信 3上门 4短信 5其他")
|
||||
private Integer followType;
|
||||
|
||||
@Schema(description = "跟进内容")
|
||||
private String followContent;
|
||||
|
||||
@Schema(description = "下次跟进时间(yyyy-MM-dd HH:mm:ss)")
|
||||
private String nextFollowTime;
|
||||
|
||||
@Schema(description = "下次跟进计划")
|
||||
private String nextFollowPlan;
|
||||
|
||||
@Schema(description = "附件URLs(JSON数组字符串)")
|
||||
private String attachmentUrls;
|
||||
|
||||
@Schema(description = "是否同时更新状态")
|
||||
private Boolean updateStatus = false;
|
||||
|
||||
@Schema(description = "新状态(当updateStatus=true时生效): 0待跟进 1跟进中 2已成交 3无效")
|
||||
private Integer newStatus;
|
||||
}
|
||||
44
src/main/java/com/gxwebsoft/cms/param/LeadReferralParam.java
Normal file
44
src/main/java/com/gxwebsoft/cms/param/LeadReferralParam.java
Normal file
@@ -0,0 +1,44 @@
|
||||
package com.gxwebsoft.cms.param;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 推荐人报备请求参数(全民推荐)
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-04-14
|
||||
*/
|
||||
@Data
|
||||
@Schema(name = "LeadReferralParam", description = "推荐人报备请求参数")
|
||||
public class LeadReferralParam implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "推荐码(匿名推荐时使用)")
|
||||
private String referralCode;
|
||||
|
||||
@Schema(description = "客户姓名")
|
||||
private String customerName;
|
||||
|
||||
@Schema(description = "客户电话")
|
||||
private String customerPhone;
|
||||
|
||||
@Schema(description = "客户公司")
|
||||
private String customerCompany;
|
||||
|
||||
@Schema(description = "需求描述")
|
||||
private String requirement;
|
||||
|
||||
@Schema(description = "预约时间")
|
||||
private String appointmentTime;
|
||||
|
||||
@Schema(description = "备注说明")
|
||||
private String remarks;
|
||||
|
||||
@Schema(description = "推荐费(可选,管理员可设置默认值)")
|
||||
private BigDecimal referralFee;
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package com.gxwebsoft.cms.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.gxwebsoft.cms.entity.CustomerLeadEntity;
|
||||
import com.gxwebsoft.cms.param.CustomerLeadParam;
|
||||
import com.gxwebsoft.cms.param.LeadDispatchParam;
|
||||
import com.gxwebsoft.cms.param.LeadFollowParam;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 客资管理服务接口
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-04-14
|
||||
*/
|
||||
public interface CustomerLeadService extends IService<CustomerLeadEntity> {
|
||||
|
||||
/**
|
||||
* 分页查询客资列表
|
||||
*/
|
||||
Map<String, Object> getLeadPage(CustomerLeadParam param);
|
||||
|
||||
/**
|
||||
* 获取客资详情
|
||||
*/
|
||||
CustomerLeadEntity getLeadDetail(Integer leadId);
|
||||
|
||||
/**
|
||||
* 创建客资(管理员录入)
|
||||
*/
|
||||
CustomerLeadEntity createLead(CustomerLeadParam param);
|
||||
|
||||
/**
|
||||
* 更新客资信息
|
||||
*/
|
||||
boolean updateLead(CustomerLeadParam param);
|
||||
|
||||
/**
|
||||
* 更新客资状态
|
||||
*/
|
||||
boolean updateLeadStatus(Integer leadId, Integer status, String remarks);
|
||||
|
||||
/**
|
||||
* 派单给业务员
|
||||
*/
|
||||
boolean dispatchLead(LeadDispatchParam param);
|
||||
|
||||
/**
|
||||
* 批量派单
|
||||
*/
|
||||
Map<String, Object> batchDispatchLeads(LeadDispatchParam param);
|
||||
|
||||
/**
|
||||
* 添加跟进记录
|
||||
*/
|
||||
boolean addFollowLog(LeadFollowParam param);
|
||||
|
||||
/**
|
||||
* 获取客资跟进历史
|
||||
*/
|
||||
List<Map<String, Object>> getFollowHistory(Integer leadId);
|
||||
|
||||
/**
|
||||
* 获取统计数据
|
||||
*/
|
||||
Map<String, Object> getStatistics(CustomerLeadParam param);
|
||||
|
||||
/**
|
||||
* 导出客资数据
|
||||
*/
|
||||
List<Map<String, Object>> exportLeads(CustomerLeadParam param);
|
||||
|
||||
/**
|
||||
* 获取未分配客资列表
|
||||
*/
|
||||
List<CustomerLeadEntity> getUnassignedLeads();
|
||||
|
||||
/**
|
||||
* 获取业务员的客资统计
|
||||
*/
|
||||
Map<String, Object> getSalesmanLeadStats(Integer salesmanId);
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.gxwebsoft.cms.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.gxwebsoft.cms.entity.LeadReferral;
|
||||
import com.gxwebsoft.cms.param.CustomerLeadParam;
|
||||
import com.gxwebsoft.cms.param.LeadReferralParam;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 推荐人服务接口(全民推荐)
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-04-14
|
||||
*/
|
||||
public interface LeadReferralService extends IService<LeadReferral> {
|
||||
|
||||
/**
|
||||
* 匿名用户通过推荐码报备客户
|
||||
*/
|
||||
LeadReferral anonymousReferral(LeadReferralParam param);
|
||||
|
||||
/**
|
||||
* 注册用户报备客户
|
||||
*/
|
||||
LeadReferral userReferral(LeadReferralParam param);
|
||||
|
||||
/**
|
||||
* 获取推荐人的推荐记录
|
||||
*/
|
||||
Map<String, Object> getReferralPage(CustomerLeadParam param);
|
||||
|
||||
/**
|
||||
* 获取推荐人的推荐统计
|
||||
*/
|
||||
Map<String, Object> getReferralStats(Integer userId);
|
||||
|
||||
/**
|
||||
* 生成推荐码
|
||||
*/
|
||||
String generateReferralCode();
|
||||
|
||||
/**
|
||||
* 根据推荐码获取推荐人信息
|
||||
*/
|
||||
Map<String, Object> getReferrerByCode(String referralCode);
|
||||
|
||||
/**
|
||||
* 确认推荐有效
|
||||
*/
|
||||
boolean confirmReferral(Integer referralId);
|
||||
|
||||
/**
|
||||
* 作废推荐
|
||||
*/
|
||||
boolean invalidateReferral(Integer referralId, String reason);
|
||||
|
||||
/**
|
||||
* 结算推荐费
|
||||
*/
|
||||
boolean settleReferral(Integer referralId);
|
||||
|
||||
/**
|
||||
* 批量结算推荐费
|
||||
*/
|
||||
Map<String, Object> batchSettleReferrals(Integer[] referralIds);
|
||||
|
||||
/**
|
||||
* 计算推荐费(根据成交金额和配置比例)
|
||||
*/
|
||||
BigDecimal calculateReferralFee(BigDecimal dealAmount);
|
||||
}
|
||||
@@ -0,0 +1,382 @@
|
||||
package com.gxwebsoft.cms.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.gxwebsoft.cms.entity.CustomerLeadEntity;
|
||||
import com.gxwebsoft.cms.entity.LeadDispatch;
|
||||
import com.gxwebsoft.cms.entity.LeadFollowLog;
|
||||
import com.gxwebsoft.cms.mapper.CustomerLeadMapper;
|
||||
import com.gxwebsoft.cms.mapper.LeadDispatchMapper;
|
||||
import com.gxwebsoft.cms.mapper.LeadFollowLogMapper;
|
||||
import com.gxwebsoft.cms.param.CustomerLeadParam;
|
||||
import com.gxwebsoft.cms.param.LeadDispatchParam;
|
||||
import com.gxwebsoft.cms.param.LeadFollowParam;
|
||||
import com.gxwebsoft.cms.service.CustomerLeadService;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 客资管理服务实现
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-04-14
|
||||
*/
|
||||
@Service
|
||||
public class CustomerLeadServiceImpl extends ServiceImpl<CustomerLeadMapper, CustomerLeadEntity> implements CustomerLeadService {
|
||||
|
||||
@Autowired
|
||||
private CustomerLeadMapper customerLeadMapper;
|
||||
|
||||
@Autowired
|
||||
private LeadDispatchMapper leadDispatchMapper;
|
||||
|
||||
@Autowired
|
||||
private LeadFollowLogMapper leadFollowLogMapper;
|
||||
|
||||
/**
|
||||
* 获取当前登录用户(与 BaseController.getLoginUser() 逻辑一致)
|
||||
*/
|
||||
private User getLoginUser() {
|
||||
try {
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
if (authentication != null) {
|
||||
Object principal = authentication.getPrincipal();
|
||||
if (principal instanceof User) {
|
||||
return (User) principal;
|
||||
}
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getLeadPage(CustomerLeadParam param) {
|
||||
// 处理分页参数
|
||||
if (param.getPageNum() == null || param.getPageNum() < 1) {
|
||||
param.setPageNum(1);
|
||||
}
|
||||
if (param.getPageSize() == null || param.getPageSize() < 1 || param.getPageSize() > 100) {
|
||||
param.setPageSize(10);
|
||||
}
|
||||
|
||||
Page<CustomerLeadEntity> page = new Page<>(param.getPageNum(), param.getPageSize());
|
||||
List<CustomerLeadEntity> list = customerLeadMapper.selectLeadPage(param);
|
||||
long total = page.getTotal();
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("list", list);
|
||||
result.put("total", total);
|
||||
result.put("pageNum", param.getPageNum());
|
||||
result.put("pageSize", param.getPageSize());
|
||||
result.put("pages", (total + param.getPageSize() - 1) / param.getPageSize());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomerLeadEntity getLeadDetail(Integer leadId) {
|
||||
return customerLeadMapper.selectLeadDetail(leadId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public CustomerLeadEntity createLead(CustomerLeadParam param) {
|
||||
CustomerLeadEntity lead = new CustomerLeadEntity();
|
||||
lead.setName(param.getName());
|
||||
lead.setPhone(param.getPhone());
|
||||
lead.setCompany(param.getCompany());
|
||||
lead.setNeed(param.getNeed());
|
||||
lead.setStatus(CustomerLeadEntity.STATUS_PENDING); // 默认待跟进
|
||||
lead.setSourceType(CustomerLeadEntity.SOURCE_ADMIN); // 管理员录入
|
||||
lead.setReferralFee(BigDecimal.ZERO);
|
||||
lead.setReferralFeePaid(0);
|
||||
lead.setFollowCount(0);
|
||||
|
||||
// 如果指定了业务员,直接派单
|
||||
if (param.getAssignedUserId() != null) {
|
||||
User currentUser = getLoginUser();
|
||||
lead.setAssignedUserId(param.getAssignedUserId());
|
||||
lead.setDispatchTime(LocalDateTime.now());
|
||||
lead.setDispatchAdminId(currentUser != null ? currentUser.getUserId() : null);
|
||||
lead.setStatus(CustomerLeadEntity.STATUS_FOLLOWING);
|
||||
}
|
||||
|
||||
this.save(lead);
|
||||
return lead;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean updateLead(CustomerLeadParam param) {
|
||||
CustomerLeadEntity lead = this.getById(param.getLeadId());
|
||||
if (lead == null) {
|
||||
throw new RuntimeException("客资不存在");
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(param.getName())) {
|
||||
lead.setName(param.getName());
|
||||
}
|
||||
if (StringUtils.hasText(param.getPhone())) {
|
||||
lead.setPhone(param.getPhone());
|
||||
}
|
||||
if (StringUtils.hasText(param.getCompany())) {
|
||||
lead.setCompany(param.getCompany());
|
||||
}
|
||||
if (StringUtils.hasText(param.getNeed())) {
|
||||
lead.setNeed(param.getNeed());
|
||||
}
|
||||
if (StringUtils.hasText(param.getRemarks())) {
|
||||
lead.setRemarks(param.getRemarks());
|
||||
}
|
||||
if (param.getDealAmount() != null) {
|
||||
lead.setDealAmount(param.getDealAmount());
|
||||
lead.setDealTime(LocalDateTime.now());
|
||||
}
|
||||
|
||||
return this.updateById(lead);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean updateLeadStatus(Integer leadId, Integer status, String remarks) {
|
||||
CustomerLeadEntity lead = this.getById(leadId);
|
||||
if (lead == null) {
|
||||
throw new RuntimeException("客资不存在");
|
||||
}
|
||||
|
||||
lead.setStatus(status);
|
||||
if (StringUtils.hasText(remarks)) {
|
||||
lead.setRemarks(remarks);
|
||||
}
|
||||
|
||||
// 成交时记录成交时间
|
||||
if (status == CustomerLeadEntity.STATUS_DEALED) {
|
||||
lead.setDealTime(LocalDateTime.now());
|
||||
}
|
||||
|
||||
return this.updateById(lead);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean dispatchLead(LeadDispatchParam param) {
|
||||
CustomerLeadEntity lead = this.getById(param.getLeadId());
|
||||
if (lead == null) {
|
||||
throw new RuntimeException("客资不存在");
|
||||
}
|
||||
|
||||
User currentUser = getLoginUser();
|
||||
Integer adminId = currentUser != null ? currentUser.getUserId() : null;
|
||||
|
||||
// 更新客资分配信息
|
||||
lead.setAssignedUserId(param.getToUserId());
|
||||
lead.setDispatchTime(LocalDateTime.now());
|
||||
lead.setDispatchAdminId(adminId);
|
||||
lead.setStatus(CustomerLeadEntity.STATUS_FOLLOWING); // 派单后变为跟进中
|
||||
|
||||
// 如果有备注,更新备注
|
||||
if (StringUtils.hasText(param.getRemarks())) {
|
||||
String oldRemarks = lead.getRemarks() != null ? lead.getRemarks() + "\n" : "";
|
||||
lead.setRemarks(oldRemarks + "【派单备注】" + param.getRemarks());
|
||||
}
|
||||
|
||||
this.updateById(lead);
|
||||
|
||||
// 记录派单历史
|
||||
LeadDispatch dispatch = new LeadDispatch();
|
||||
dispatch.setLeadId(param.getLeadId());
|
||||
dispatch.setFromUserId(lead.getAssignedUserId()); // 原分配用户
|
||||
dispatch.setToUserId(param.getToUserId());
|
||||
dispatch.setAdminId(adminId);
|
||||
dispatch.setDispatchRemarks(param.getRemarks());
|
||||
dispatch.setDispatchType(param.getDispatchType() != null ? param.getDispatchType() : LeadDispatch.TYPE_NEW);
|
||||
dispatch.setCreateTime(LocalDateTime.now());
|
||||
leadDispatchMapper.insert(dispatch);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Map<String, Object> batchDispatchLeads(LeadDispatchParam param) {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
int successCount = 0;
|
||||
int failCount = 0;
|
||||
List<String> errors = new ArrayList<>();
|
||||
|
||||
if (param.getLeadIds() == null || param.getLeadIds().length == 0) {
|
||||
throw new RuntimeException("请选择要派单的客资");
|
||||
}
|
||||
|
||||
User currentUser = getLoginUser();
|
||||
Integer adminId = currentUser != null ? currentUser.getUserId() : null;
|
||||
|
||||
for (Integer leadId : param.getLeadIds()) {
|
||||
try {
|
||||
LeadDispatchParam singleParam = new LeadDispatchParam();
|
||||
singleParam.setLeadId(leadId);
|
||||
singleParam.setToUserId(param.getToUserId());
|
||||
singleParam.setRemarks(param.getRemarks());
|
||||
singleParam.setDispatchType(LeadDispatch.TYPE_NEW);
|
||||
|
||||
this.dispatchLead(singleParam);
|
||||
successCount++;
|
||||
} catch (Exception e) {
|
||||
failCount++;
|
||||
errors.add("客资ID[" + leadId + "]: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
result.put("successCount", successCount);
|
||||
result.put("failCount", failCount);
|
||||
result.put("errors", errors);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean addFollowLog(LeadFollowParam param) {
|
||||
CustomerLeadEntity lead = this.getById(param.getLeadId());
|
||||
if (lead == null) {
|
||||
throw new RuntimeException("客资不存在");
|
||||
}
|
||||
|
||||
User currentUser = getLoginUser();
|
||||
Integer userId = currentUser != null ? currentUser.getUserId() : null;
|
||||
|
||||
// 添加跟进记录
|
||||
LeadFollowLog followLog = new LeadFollowLog();
|
||||
followLog.setLeadId(param.getLeadId());
|
||||
followLog.setUserId(userId);
|
||||
followLog.setFollowType(param.getFollowType());
|
||||
followLog.setFollowContent(param.getFollowContent());
|
||||
followLog.setNextFollowPlan(param.getNextFollowPlan());
|
||||
followLog.setAttachmentUrls(param.getAttachmentUrls());
|
||||
followLog.setCreateTime(LocalDateTime.now());
|
||||
|
||||
if (StringUtils.hasText(param.getNextFollowTime())) {
|
||||
followLog.setNextFollowTime(LocalDateTime.parse(param.getNextFollowTime().replace(" ", "T")));
|
||||
}
|
||||
|
||||
leadFollowLogMapper.insert(followLog);
|
||||
|
||||
// 更新客资跟进信息
|
||||
lead.setFollowCount(lead.getFollowCount() != null ? lead.getFollowCount() + 1 : 1);
|
||||
lead.setLastFollowTime(LocalDateTime.now());
|
||||
|
||||
// 如果需要更新状态
|
||||
if (Boolean.TRUE.equals(param.getUpdateStatus()) && param.getNewStatus() != null) {
|
||||
lead.setStatus(param.getNewStatus());
|
||||
}
|
||||
|
||||
// 如果是成交
|
||||
if (param.getNewStatus() != null && param.getNewStatus() == CustomerLeadEntity.STATUS_DEALED) {
|
||||
lead.setDealTime(LocalDateTime.now());
|
||||
}
|
||||
|
||||
return this.updateById(lead);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Map<String, Object>> getFollowHistory(Integer leadId) {
|
||||
List<LeadFollowLog> logs = leadFollowLogMapper.selectFollowHistory(leadId);
|
||||
List<Map<String, Object>> result = new ArrayList<>();
|
||||
|
||||
for (LeadFollowLog log : logs) {
|
||||
Map<String, Object> item = new HashMap<>();
|
||||
item.put("followId", log.getFollowId());
|
||||
item.put("followType", log.getFollowType());
|
||||
item.put("followTypeText", log.getFollowTypeText());
|
||||
item.put("followContent", log.getFollowContent());
|
||||
item.put("nextFollowTime", log.getNextFollowTime());
|
||||
item.put("nextFollowPlan", log.getNextFollowPlan());
|
||||
item.put("userName", log.getUserName());
|
||||
item.put("createTime", log.getCreateTime());
|
||||
result.add(item);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getStatistics(CustomerLeadParam param) {
|
||||
Map<String, Object> stats = new HashMap<>();
|
||||
|
||||
// 基础统计
|
||||
Map<String, Object> basicStats = customerLeadMapper.selectStatistics(
|
||||
param.getStartDate(), param.getEndDate(), param.getSalesmanId());
|
||||
stats.put("basic", basicStats);
|
||||
|
||||
// 按状态统计
|
||||
stats.put("byStatus", customerLeadMapper.selectStatusStatistics(param.getStartDate(), param.getEndDate()));
|
||||
|
||||
// 按来源统计
|
||||
stats.put("bySource", customerLeadMapper.selectSourceStatistics(param.getStartDate(), param.getEndDate()));
|
||||
|
||||
// 每日趋势
|
||||
stats.put("dailyTrend", customerLeadMapper.selectDailyTrend(param.getStartDate(), param.getEndDate()));
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Map<String, Object>> exportLeads(CustomerLeadParam param) {
|
||||
// 设置不分页,导出全部
|
||||
param.setPageNum(1);
|
||||
param.setPageSize(10000);
|
||||
|
||||
List<CustomerLeadEntity> leads = customerLeadMapper.selectLeadPage(param);
|
||||
List<Map<String, Object>> result = new ArrayList<>();
|
||||
|
||||
for (CustomerLeadEntity lead : leads) {
|
||||
Map<String, Object> item = new HashMap<>();
|
||||
item.put("客户姓名", lead.getName());
|
||||
item.put("联系电话", lead.getPhone());
|
||||
item.put("公司名称", lead.getCompany());
|
||||
item.put("需求描述", lead.getNeed());
|
||||
item.put("状态", lead.getStatusText());
|
||||
item.put("来源", lead.getSourceType());
|
||||
item.put("业务员", lead.getAssignedUserName());
|
||||
item.put("推荐人", lead.getReferrerName());
|
||||
item.put("跟进次数", lead.getFollowCount());
|
||||
item.put("成交金额", lead.getDealAmount());
|
||||
item.put("创建时间", lead.getCreateTime());
|
||||
item.put("派单时间", lead.getDispatchTime());
|
||||
item.put("成交时间", lead.getDealTime());
|
||||
item.put("备注", lead.getRemarks());
|
||||
result.add(item);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CustomerLeadEntity> getUnassignedLeads() {
|
||||
return customerLeadMapper.selectUnassignedLeads();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getSalesmanLeadStats(Integer salesmanId) {
|
||||
Map<String, Object> stats = new HashMap<>();
|
||||
|
||||
stats.put("total", customerLeadMapper.countBySalesman(salesmanId, null));
|
||||
stats.put("pending", customerLeadMapper.countBySalesman(salesmanId, CustomerLeadEntity.STATUS_PENDING));
|
||||
stats.put("following", customerLeadMapper.countBySalesman(salesmanId, CustomerLeadEntity.STATUS_FOLLOWING));
|
||||
stats.put("dealed", customerLeadMapper.countBySalesman(salesmanId, CustomerLeadEntity.STATUS_DEALED));
|
||||
stats.put("invalid", customerLeadMapper.countBySalesman(salesmanId, CustomerLeadEntity.STATUS_INVALID));
|
||||
|
||||
return stats;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,305 @@
|
||||
package com.gxwebsoft.cms.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.gxwebsoft.cms.entity.CustomerLeadEntity;
|
||||
import com.gxwebsoft.cms.entity.LeadReferral;
|
||||
import com.gxwebsoft.cms.mapper.CustomerLeadMapper;
|
||||
import com.gxwebsoft.cms.mapper.LeadReferralMapper;
|
||||
import com.gxwebsoft.cms.param.CustomerLeadParam;
|
||||
import com.gxwebsoft.cms.param.LeadReferralParam;
|
||||
import com.gxwebsoft.cms.service.CustomerLeadService;
|
||||
import com.gxwebsoft.cms.service.LeadReferralService;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.common.system.service.UserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 推荐人服务实现(全民推荐)
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-04-14
|
||||
*/
|
||||
@Service
|
||||
public class LeadReferralServiceImpl extends ServiceImpl<LeadReferralMapper, LeadReferral> implements LeadReferralService {
|
||||
|
||||
@Autowired
|
||||
private LeadReferralMapper leadReferralMapper;
|
||||
|
||||
@Autowired
|
||||
private CustomerLeadMapper customerLeadMapper;
|
||||
|
||||
@Autowired
|
||||
private CustomerLeadService customerLeadService;
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
// 默认推荐费比例 5%
|
||||
private static final BigDecimal DEFAULT_REFERRAL_RATE = new BigDecimal("0.05");
|
||||
|
||||
/**
|
||||
* 获取当前登录用户(与 BaseController.getLoginUser() 逻辑一致)
|
||||
*/
|
||||
private User getLoginUser() {
|
||||
try {
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
if (authentication != null) {
|
||||
Object principal = authentication.getPrincipal();
|
||||
if (principal instanceof User) {
|
||||
return (User) principal;
|
||||
}
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public LeadReferral anonymousReferral(LeadReferralParam param) {
|
||||
// 1. 如果有推荐码,先查询推荐人
|
||||
Integer referrerUserId = null;
|
||||
if (StringUtils.hasText(param.getReferralCode())) {
|
||||
LeadReferral referral = leadReferralMapper.selectByCode(param.getReferralCode());
|
||||
if (referral != null) {
|
||||
referrerUserId = referral.getReferrerUserId();
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 创建客资
|
||||
CustomerLeadEntity lead = new CustomerLeadEntity();
|
||||
lead.setName(param.getCustomerName());
|
||||
lead.setPhone(param.getCustomerPhone());
|
||||
lead.setCompany(param.getCustomerCompany());
|
||||
lead.setNeed(param.getRequirement());
|
||||
lead.setSourceType(CustomerLeadEntity.SOURCE_REFERRAL);
|
||||
lead.setStatus(CustomerLeadEntity.STATUS_PENDING);
|
||||
lead.setReferrerUserId(referrerUserId);
|
||||
lead.setFollowCount(0);
|
||||
lead.setReferralFee(BigDecimal.ZERO);
|
||||
lead.setReferralFeePaid(0);
|
||||
|
||||
if (StringUtils.hasText(param.getAppointmentTime())) {
|
||||
lead.setAppointmentTime(LocalDateTime.parse(param.getAppointmentTime().replace(" ", "T")));
|
||||
}
|
||||
|
||||
customerLeadMapper.insert(lead);
|
||||
|
||||
// 3. 创建推荐关系
|
||||
LeadReferral referral = new LeadReferral();
|
||||
referral.setReferrerUserId(referrerUserId);
|
||||
referral.setReferredLeadId(lead.getLeadId());
|
||||
referral.setReferralCode(StringUtils.hasText(param.getReferralCode()) ? param.getReferralCode() : null);
|
||||
referral.setReferralFee(param.getReferralFee() != null ? param.getReferralFee() : BigDecimal.ZERO);
|
||||
referral.setReferralStatus(LeadReferral.STATUS_PENDING); // 待确认
|
||||
referral.setCustomerName(param.getCustomerName());
|
||||
referral.setCustomerPhone(param.getCustomerPhone());
|
||||
referral.setCreateTime(LocalDateTime.now());
|
||||
|
||||
leadReferralMapper.insert(referral);
|
||||
|
||||
// 4. 更新客资的推荐费
|
||||
lead.setReferralFee(referral.getReferralFee());
|
||||
customerLeadMapper.updateById(lead);
|
||||
|
||||
return referral;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public LeadReferral userReferral(LeadReferralParam param) {
|
||||
User currentUser = getLoginUser();
|
||||
if (currentUser == null) {
|
||||
throw new RuntimeException("请先登录");
|
||||
}
|
||||
|
||||
// 1. 创建客资
|
||||
CustomerLeadEntity lead = new CustomerLeadEntity();
|
||||
lead.setName(param.getCustomerName());
|
||||
lead.setPhone(param.getCustomerPhone());
|
||||
lead.setCompany(param.getCustomerCompany());
|
||||
lead.setNeed(param.getRequirement());
|
||||
lead.setSourceType(CustomerLeadEntity.SOURCE_REFERRAL);
|
||||
lead.setStatus(CustomerLeadEntity.STATUS_PENDING);
|
||||
lead.setReferrerUserId(currentUser.getUserId());
|
||||
lead.setFollowCount(0);
|
||||
lead.setReferralFee(param.getReferralFee() != null ? param.getReferralFee() : BigDecimal.ZERO);
|
||||
lead.setReferralFeePaid(0);
|
||||
|
||||
if (StringUtils.hasText(param.getAppointmentTime())) {
|
||||
lead.setAppointmentTime(LocalDateTime.parse(param.getAppointmentTime().replace(" ", "T")));
|
||||
}
|
||||
|
||||
customerLeadMapper.insert(lead);
|
||||
|
||||
// 2. 创建推荐关系
|
||||
LeadReferral referral = new LeadReferral();
|
||||
referral.setReferrerUserId(currentUser.getUserId());
|
||||
referral.setReferredLeadId(lead.getLeadId());
|
||||
referral.setReferralCode(this.generateReferralCode()); // 生成推荐码
|
||||
referral.setReferralFee(param.getReferralFee() != null ? param.getReferralFee() : BigDecimal.ZERO);
|
||||
referral.setReferralStatus(LeadReferral.STATUS_PENDING);
|
||||
referral.setCustomerName(param.getCustomerName());
|
||||
referral.setCustomerPhone(param.getCustomerPhone());
|
||||
referral.setCreateTime(LocalDateTime.now());
|
||||
|
||||
leadReferralMapper.insert(referral);
|
||||
|
||||
return referral;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getReferralPage(CustomerLeadParam param) {
|
||||
Page<LeadReferral> page = new Page<>(param.getPageNum(), param.getPageSize());
|
||||
List<LeadReferral> list = leadReferralMapper.selectReferralPage(param);
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("list", list);
|
||||
result.put("total", page.getTotal());
|
||||
result.put("pageNum", param.getPageNum());
|
||||
result.put("pageSize", param.getPageSize());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getReferralStats(Integer userId) {
|
||||
Map<String, Object> stats = new HashMap<>();
|
||||
|
||||
stats.put("totalCount", leadReferralMapper.countUserReferrals(userId, null));
|
||||
stats.put("pendingCount", leadReferralMapper.countUserReferrals(userId, LeadReferral.STATUS_PENDING));
|
||||
stats.put("validCount", leadReferralMapper.countUserReferrals(userId, LeadReferral.STATUS_VALID));
|
||||
stats.put("settledCount", leadReferralMapper.countUserReferrals(userId, LeadReferral.STATUS_SETTLED));
|
||||
stats.put("pendingAmount", leadReferralMapper.sumPendingFee(userId));
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateReferralCode() {
|
||||
return "RF" + System.currentTimeMillis() + (int)(Math.random() * 100);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getReferrerByCode(String referralCode) {
|
||||
LeadReferral referral = leadReferralMapper.selectByCode(referralCode);
|
||||
if (referral == null || referral.getReferrerUserId() == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
User referrer = userService.getByIdRel(referral.getReferrerUserId());
|
||||
if (referrer == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("referrerId", referrer.getUserId());
|
||||
result.put("referrerName", referrer.getNickname());
|
||||
result.put("referrerPhone", referrer.getPhone());
|
||||
result.put("referralCode", referralCode);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean confirmReferral(Integer referralId) {
|
||||
LeadReferral referral = this.getById(referralId);
|
||||
if (referral == null) {
|
||||
throw new RuntimeException("推荐记录不存在");
|
||||
}
|
||||
|
||||
referral.setReferralStatus(LeadReferral.STATUS_VALID);
|
||||
return this.updateById(referral);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean invalidateReferral(Integer referralId, String reason) {
|
||||
LeadReferral referral = this.getById(referralId);
|
||||
if (referral == null) {
|
||||
throw new RuntimeException("推荐记录不存在");
|
||||
}
|
||||
|
||||
referral.setReferralStatus(LeadReferral.STATUS_INVALID);
|
||||
|
||||
// 同步更新客资推荐费状态
|
||||
CustomerLeadEntity lead = customerLeadMapper.selectById(referral.getReferredLeadId());
|
||||
if (lead != null) {
|
||||
lead.setReferralFeePaid(-1); // 标记为已作废
|
||||
customerLeadMapper.updateById(lead);
|
||||
}
|
||||
|
||||
return this.updateById(referral);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean settleReferral(Integer referralId) {
|
||||
LeadReferral referral = this.getById(referralId);
|
||||
if (referral == null) {
|
||||
throw new RuntimeException("推荐记录不存在");
|
||||
}
|
||||
|
||||
if (referral.getReferralStatus() != LeadReferral.STATUS_VALID) {
|
||||
throw new RuntimeException("只有有效的推荐才能结算");
|
||||
}
|
||||
|
||||
referral.setReferralStatus(LeadReferral.STATUS_SETTLED);
|
||||
referral.setSettlementTime(LocalDateTime.now());
|
||||
|
||||
// 同步更新客资推荐费状态
|
||||
CustomerLeadEntity lead = customerLeadMapper.selectById(referral.getReferredLeadId());
|
||||
if (lead != null) {
|
||||
lead.setReferralFeePaid(1); // 已支付
|
||||
customerLeadMapper.updateById(lead);
|
||||
}
|
||||
|
||||
return this.updateById(referral);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Map<String, Object> batchSettleReferrals(Integer[] referralIds) {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
int successCount = 0;
|
||||
int failCount = 0;
|
||||
List<String> errors = new ArrayList<>();
|
||||
|
||||
for (Integer id : referralIds) {
|
||||
try {
|
||||
this.settleReferral(id);
|
||||
successCount++;
|
||||
} catch (Exception e) {
|
||||
failCount++;
|
||||
errors.add("ID[" + id + "]: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
result.put("successCount", successCount);
|
||||
result.put("failCount", failCount);
|
||||
result.put("errors", errors);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigDecimal calculateReferralFee(BigDecimal dealAmount) {
|
||||
if (dealAmount == null || dealAmount.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
return dealAmount.multiply(DEFAULT_REFERRAL_RATE).setScale(2, RoundingMode.HALF_UP);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package com.gxwebsoft.common.system.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 用户角色扩展实体(支持多角色)
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-04-14
|
||||
*/
|
||||
@Data
|
||||
@TableName("sys_user_role_extend")
|
||||
@Schema(name = "UserRoleExtend", description = "用户角色扩展")
|
||||
public class UserRoleExtend implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "ID")
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "角色类型: admin管理员 salesman业务员 referrer推荐人")
|
||||
private String roleType;
|
||||
|
||||
@Schema(description = "是否主角色 0否 1是")
|
||||
private Integer isPrimary;
|
||||
|
||||
@Schema(description = "权限配置(JSON)")
|
||||
private String permissions;
|
||||
|
||||
@Schema(description = "最大客资分配数(业务员)")
|
||||
private Integer maxLeads;
|
||||
|
||||
@Schema(description = "佣金比例%(业务员)")
|
||||
private BigDecimal commissionRate;
|
||||
|
||||
@Schema(description = "推荐奖金%(推荐人)")
|
||||
private BigDecimal referralBonus;
|
||||
|
||||
@Schema(description = "状态: 0禁用 1启用")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "更新时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
// ========== 关联信息(非数据库字段)==========
|
||||
@Schema(description = "用户昵称")
|
||||
private String userName;
|
||||
|
||||
@Schema(description = "用户电话")
|
||||
private String userPhone;
|
||||
|
||||
@Schema(description = "当前分配的客资数")
|
||||
private Integer currentLeads;
|
||||
|
||||
// ========== 角色类型常量 ==========
|
||||
public static final String ROLE_ADMIN = "admin"; // 管理员
|
||||
public static final String ROLE_SALESMAN = "salesman"; // 业务员
|
||||
public static final String ROLE_REFERRER = "referrer"; // 推荐人
|
||||
|
||||
public String getRoleTypeText() {
|
||||
if (this.roleType == null) return "";
|
||||
return switch (this.roleType) {
|
||||
case ROLE_ADMIN -> "管理员";
|
||||
case ROLE_SALESMAN -> "业务员";
|
||||
case ROLE_REFERRER -> "推荐人";
|
||||
default -> this.roleType;
|
||||
};
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,543 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditCompany;
|
||||
import com.gxwebsoft.credit.entity.CreditAdministrativeLicense;
|
||||
import com.gxwebsoft.credit.param.CreditAdministrativeLicenseImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditAdministrativeLicenseParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditAdministrativeLicenseService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 行政许可控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-01-07 13:52:14
|
||||
*/
|
||||
@Tag(name = "行政许可管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-administrative-license")
|
||||
public class CreditAdministrativeLicenseController extends BaseController {
|
||||
@Resource
|
||||
private CreditAdministrativeLicenseService creditAdministrativeLicenseService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询行政许可")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditAdministrativeLicense>> page(CreditAdministrativeLicenseParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditAdministrativeLicenseService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部行政许可")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditAdministrativeLicense>> list(CreditAdministrativeLicenseParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditAdministrativeLicenseService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询行政许可")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditAdministrativeLicense> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditAdministrativeLicenseService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditAdministrativeLicense:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加行政许可")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditAdministrativeLicense creditAdministrativeLicense) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditAdministrativeLicense.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditAdministrativeLicenseService.save(creditAdministrativeLicense)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditAdministrativeLicense:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改行政许可")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditAdministrativeLicense creditAdministrativeLicense) {
|
||||
if (creditAdministrativeLicenseService.updateById(creditAdministrativeLicense)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditAdministrativeLicense:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除行政许可")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (batchImportSupport.hardRemoveById(CreditAdministrativeLicense.class, id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditAdministrativeLicense:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加行政许可")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditAdministrativeLicense> list) {
|
||||
if (creditAdministrativeLicenseService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditAdministrativeLicense:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改行政许可")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditAdministrativeLicense> batchParam) {
|
||||
if (batchParam.update(creditAdministrativeLicenseService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditAdministrativeLicense:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除行政许可")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (batchImportSupport.hardRemoveByIds(CreditAdministrativeLicense.class, ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditAdministrativeLicense:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
|
||||
creditAdministrativeLicenseService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditAdministrativeLicense::getId,
|
||||
CreditAdministrativeLicense::setId,
|
||||
CreditAdministrativeLicense::getName,
|
||||
CreditAdministrativeLicense::getCompanyId,
|
||||
CreditAdministrativeLicense::setCompanyId,
|
||||
CreditAdministrativeLicense::setCompanyName,
|
||||
CreditAdministrativeLicense::getHasData,
|
||||
CreditAdministrativeLicense::setHasData,
|
||||
CreditAdministrativeLicense::getTenantId,
|
||||
CreditAdministrativeLicense::new
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入行政许可
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditAdministrativeLicense:save')")
|
||||
@Operation(summary = "批量导入行政许可")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
ExcelImportSupport.ImportResult<CreditAdministrativeLicenseImportParam> importResult = ExcelImportSupport.readAnySheet(
|
||||
file, CreditAdministrativeLicenseImportParam.class, this::isEmptyImportRow);
|
||||
List<CreditAdministrativeLicenseImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByCode = ExcelImportSupport.readHyperlinksByHeaderKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "决定文书/许可编号");
|
||||
Map<String, String> urlByName = ExcelImportSupport.readHyperlinksByHeaderKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "决定文书/许可证名称");
|
||||
String fixedCompanyName = null;
|
||||
if (companyId != null && companyId > 0) {
|
||||
CreditCompany fixedCompany = creditCompanyService.getById(companyId);
|
||||
fixedCompanyName = fixedCompany != null ? fixedCompany.getName() : null;
|
||||
}
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditAdministrativeLicense> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditAdministrativeLicenseImportParam param = list.get(i);
|
||||
try {
|
||||
CreditAdministrativeLicense item = convertImportParamToEntity(param);
|
||||
String link = null;
|
||||
if (!ImportHelper.isBlank(item.getCode())) {
|
||||
link = urlByCode.get(item.getCode().trim());
|
||||
}
|
||||
if ((link == null || link.isEmpty()) && !ImportHelper.isBlank(item.getName())) {
|
||||
link = urlByName.get(item.getName().trim());
|
||||
}
|
||||
if (link != null && !link.isEmpty()) {
|
||||
item.setUrl(link);
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
if (ImportHelper.isBlank(item.getCompanyName()) && !ImportHelper.isBlank(fixedCompanyName)) {
|
||||
item.setCompanyName(fixedCompanyName);
|
||||
}
|
||||
}
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getName())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:决定文书/许可证名称不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditAdministrativeLicenseService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditAdministrativeLicense::getName,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditAdministrativeLicenseService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditAdministrativeLicense::getName,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.ADMINISTRATIVE_LICENSE, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入历史行政许可(仅解析“历史行政许可”选项卡)
|
||||
* 规则:使用数据库唯一索引约束,重复数据不导入。
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditAdministrativeLicense:save')")
|
||||
@Operation(summary = "批量导入历史行政许可")
|
||||
@PostMapping("/import/history")
|
||||
public ApiResult<List<String>> importHistoryBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "历史行政许可");
|
||||
if (sheetIndex < 0) {
|
||||
return fail("未读取到数据,请确认文件中存在“历史行政许可”选项卡且表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
ExcelImportSupport.ImportResult<CreditAdministrativeLicenseImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditAdministrativeLicenseImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditAdministrativeLicenseImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByCode = ExcelImportSupport.readHyperlinksByHeaderKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "决定文书/许可编号");
|
||||
Map<String, String> urlByName = ExcelImportSupport.readHyperlinksByHeaderKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "决定文书/许可证名称");
|
||||
String fixedCompanyName = null;
|
||||
if (companyId != null && companyId > 0) {
|
||||
CreditCompany fixedCompany = creditCompanyService.getById(companyId);
|
||||
fixedCompanyName = fixedCompany != null ? fixedCompany.getName() : null;
|
||||
}
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditAdministrativeLicense> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditAdministrativeLicenseImportParam param = list.get(i);
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
try {
|
||||
CreditAdministrativeLicense item = convertImportParamToEntity(param);
|
||||
if (item.getCode() != null) {
|
||||
item.setCode(item.getCode().trim());
|
||||
}
|
||||
if (item.getName() != null) {
|
||||
item.setName(item.getName().trim());
|
||||
}
|
||||
|
||||
if (ImportHelper.isBlank(item.getName())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:决定文书/许可证名称不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
String link = null;
|
||||
if (!ImportHelper.isBlank(item.getCode())) {
|
||||
link = urlByCode.get(item.getCode());
|
||||
}
|
||||
if ((link == null || link.isEmpty()) && !ImportHelper.isBlank(item.getName())) {
|
||||
link = urlByName.get(item.getName());
|
||||
}
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
if (ImportHelper.isBlank(item.getCompanyName()) && !ImportHelper.isBlank(fixedCompanyName)) {
|
||||
item.setCompanyName(fixedCompanyName);
|
||||
}
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
// 历史导入的数据统一标记为“失效”
|
||||
item.setDataStatus("失效");
|
||||
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditAdministrativeLicenseService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditAdministrativeLicense::getName,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditAdministrativeLicenseService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditAdministrativeLicense::getName,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.ADMINISTRATIVE_LICENSE, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
}
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载行政许可导入模板
|
||||
*/
|
||||
@Operation(summary = "下载行政许可导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditAdministrativeLicenseImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditAdministrativeLicenseImportParam example = new CreditAdministrativeLicenseImportParam();
|
||||
example.setCode("(2024)示例许可编号");
|
||||
example.setName("示例行政许可名称");
|
||||
example.setStatusText("有效");
|
||||
example.setType("行政许可");
|
||||
example.setValidityStart("2024-01-01");
|
||||
example.setValidityEnd("2029-01-01");
|
||||
example.setLicensingAuthority("某某许可机关");
|
||||
example.setLicenseContent("许可内容示例");
|
||||
example.setDataSourceUnit("数据来源单位示例");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("行政许可导入模板", "行政许可", CreditAdministrativeLicenseImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_administrative_license_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditAdministrativeLicenseImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
if (isImportHeaderRow(param)) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getCode())
|
||||
&& ImportHelper.isBlank(param.getName())
|
||||
&& ImportHelper.isBlank(param.getStatusText());
|
||||
}
|
||||
|
||||
private boolean isImportHeaderRow(CreditAdministrativeLicenseImportParam param) {
|
||||
return isHeaderValue(param.getCode(), "决定文书/许可编号")
|
||||
|| isHeaderValue(param.getName(), "决定文书/许可证名称")
|
||||
|| isHeaderValue(param.getStatusText(), "许可状态");
|
||||
}
|
||||
|
||||
private static boolean isHeaderValue(String value, String headerText) {
|
||||
if (value == null) {
|
||||
return false;
|
||||
}
|
||||
return headerText.equals(value.trim());
|
||||
}
|
||||
|
||||
private CreditAdministrativeLicense convertImportParamToEntity(CreditAdministrativeLicenseImportParam param) {
|
||||
CreditAdministrativeLicense entity = new CreditAdministrativeLicense();
|
||||
|
||||
entity.setCode(param.getCode());
|
||||
entity.setName(param.getName());
|
||||
entity.setStatusText(param.getStatusText());
|
||||
entity.setType(param.getType());
|
||||
entity.setValidityStart(param.getValidityStart());
|
||||
entity.setValidityEnd(param.getValidityEnd());
|
||||
entity.setLicensingAuthority(param.getLicensingAuthority());
|
||||
entity.setLicenseContent(param.getLicenseContent());
|
||||
entity.setDataSourceUnit(param.getDataSourceUnit());
|
||||
entity.setComments(param.getComments());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,507 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditBankruptcy;
|
||||
import com.gxwebsoft.credit.param.CreditBankruptcyImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditBankruptcyParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditBankruptcyService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 破产重整控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-01-07 13:52:14
|
||||
*/
|
||||
@Tag(name = "破产重整管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-bankruptcy")
|
||||
public class CreditBankruptcyController extends BaseController {
|
||||
@Resource
|
||||
private CreditBankruptcyService creditBankruptcyService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询破产重整")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditBankruptcy>> page(CreditBankruptcyParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditBankruptcyService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部破产重整")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditBankruptcy>> list(CreditBankruptcyParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditBankruptcyService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询破产重整")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditBankruptcy> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditBankruptcyService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditBankruptcy:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加破产重整")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditBankruptcy creditBankruptcy) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditBankruptcy.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditBankruptcyService.save(creditBankruptcy)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditBankruptcy:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改破产重整")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditBankruptcy creditBankruptcy) {
|
||||
if (creditBankruptcyService.updateById(creditBankruptcy)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditBankruptcy:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除破产重整")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (batchImportSupport.hardRemoveById(CreditBankruptcy.class, id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditBankruptcy:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加破产重整")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditBankruptcy> list) {
|
||||
if (creditBankruptcyService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditBankruptcy:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改破产重整")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditBankruptcy> batchParam) {
|
||||
if (batchParam.update(creditBankruptcyService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditBankruptcy:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除破产重整")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (batchImportSupport.hardRemoveByIds(CreditBankruptcy.class, ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditBankruptcy:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
|
||||
creditBankruptcyService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditBankruptcy::getId,
|
||||
CreditBankruptcy::setId,
|
||||
CreditBankruptcy::getParty,
|
||||
CreditBankruptcy::getCompanyId,
|
||||
CreditBankruptcy::setCompanyId,
|
||||
CreditBankruptcy::getHasData,
|
||||
CreditBankruptcy::setHasData,
|
||||
CreditBankruptcy::getTenantId,
|
||||
CreditBankruptcy::new
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入破产重整
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditBankruptcy:save')")
|
||||
@Operation(summary = "批量导入破产重整")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
// Prefer importing from the explicit tab name "破产重整" when present.
|
||||
// This avoids accidentally importing from other sheets (e.g. "历史破产重整") in multi-sheet workbooks.
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "破产重整");
|
||||
ExcelImportSupport.ImportResult<CreditBankruptcyImportParam> importResult;
|
||||
if (sheetIndex >= 0) {
|
||||
importResult = ExcelImportSupport.read(file, CreditBankruptcyImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
} else {
|
||||
// Backward compatible: try any sheet for older templates without the expected tab name.
|
||||
importResult = ExcelImportSupport.readAnySheet(file, CreditBankruptcyImportParam.class, this::isEmptyImportRow);
|
||||
}
|
||||
List<CreditBankruptcyImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByCode = ExcelImportSupport.readHyperlinksByHeaderKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditBankruptcy> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditBankruptcyImportParam param = list.get(i);
|
||||
try {
|
||||
CreditBankruptcy item = convertImportParamToEntity(param);
|
||||
if (!ImportHelper.isBlank(item.getCode())) {
|
||||
String link = urlByCode.get(item.getCode().trim());
|
||||
if (link != null && !link.isEmpty()) {
|
||||
item.setUrl(link);
|
||||
}
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getCode())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditBankruptcyService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditBankruptcy::getCode,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditBankruptcyService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditBankruptcy::getCode,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.BANKRUPTCY, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入历史破产重整(仅解析“历史破产重整”选项卡)
|
||||
* 规则:使用数据库唯一索引约束,重复数据不导入。
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditBankruptcy:save')")
|
||||
@Operation(summary = "批量导入历史破产重整")
|
||||
@PostMapping("/import/history")
|
||||
public ApiResult<List<String>> importHistoryBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "历史破产重整");
|
||||
if (sheetIndex < 0) {
|
||||
return fail("未读取到数据,请确认文件中存在“历史破产重整”选项卡且表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
ExcelImportSupport.ImportResult<CreditBankruptcyImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditBankruptcyImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditBankruptcyImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByCode = ExcelImportSupport.readHyperlinksByHeaderKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditBankruptcy> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditBankruptcyImportParam param = list.get(i);
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
try {
|
||||
CreditBankruptcy item = convertImportParamToEntity(param);
|
||||
if (item.getCode() != null) {
|
||||
item.setCode(item.getCode().trim());
|
||||
}
|
||||
if (ImportHelper.isBlank(item.getCode())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
String link = urlByCode.get(item.getCode());
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditBankruptcyService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditBankruptcy::getCode,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditBankruptcyService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditBankruptcy::getCode,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.BANKRUPTCY, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
}
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载破产重整导入模板
|
||||
*/
|
||||
@Operation(summary = "下载破产重整导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditBankruptcyImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditBankruptcyImportParam example = new CreditBankruptcyImportParam();
|
||||
example.setCode("(2024)示例案号");
|
||||
example.setType("破产清算");
|
||||
example.setParty("某某公司");
|
||||
example.setCourt("某某人民法院");
|
||||
example.setPublicDate("2024-01-10");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("破产重整导入模板", "破产重整", CreditBankruptcyImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_bankruptcy_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditBankruptcyImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
if (isImportHeaderRow(param)) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getCode())
|
||||
&& ImportHelper.isBlank(param.getParty())
|
||||
&& ImportHelper.isBlank(param.getCourt());
|
||||
}
|
||||
|
||||
private boolean isImportHeaderRow(CreditBankruptcyImportParam param) {
|
||||
return isHeaderValue(param.getCode(), "案号")
|
||||
|| isHeaderValue(param.getType(), "案件类型")
|
||||
|| isHeaderValue(param.getParty(), "当事人");
|
||||
}
|
||||
|
||||
private static boolean isHeaderValue(String value, String headerText) {
|
||||
if (value == null) {
|
||||
return false;
|
||||
}
|
||||
return headerText.equals(value.trim());
|
||||
}
|
||||
|
||||
private CreditBankruptcy convertImportParamToEntity(CreditBankruptcyImportParam param) {
|
||||
CreditBankruptcy entity = new CreditBankruptcy();
|
||||
|
||||
entity.setCode(param.getCode());
|
||||
entity.setType(param.getType());
|
||||
entity.setParty(param.getParty());
|
||||
entity.setCourt(param.getCourt());
|
||||
entity.setPublicDate(param.getPublicDate());
|
||||
entity.setComments(param.getComments());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,380 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditCompany;
|
||||
import com.gxwebsoft.credit.entity.CreditBranch;
|
||||
import com.gxwebsoft.credit.param.CreditBranchImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditBranchParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditBranchService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 分支机构控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-01-07 13:52:14
|
||||
*/
|
||||
@Tag(name = "分支机构管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-branch")
|
||||
public class CreditBranchController extends BaseController {
|
||||
@Resource
|
||||
private CreditBranchService creditBranchService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询分支机构")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditBranch>> page(CreditBranchParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditBranchService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部分支机构")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditBranch>> list(CreditBranchParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditBranchService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询分支机构")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditBranch> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditBranchService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditBranch:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加分支机构")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditBranch creditBranch) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditBranch.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditBranchService.save(creditBranch)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditBranch:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改分支机构")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditBranch creditBranch) {
|
||||
if (creditBranchService.updateById(creditBranch)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditBranch:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除分支机构")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (batchImportSupport.hardRemoveById(CreditBranch.class, id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditBranch:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加分支机构")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditBranch> list) {
|
||||
if (creditBranchService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditBranch:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改分支机构")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditBranch> batchParam) {
|
||||
if (batchParam.update(creditBranchService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditBranch:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除分支机构")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (batchImportSupport.hardRemoveByIds(CreditBranch.class, ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditBranch:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
|
||||
creditBranchService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditBranch::getId,
|
||||
CreditBranch::setId,
|
||||
CreditBranch::getName,
|
||||
CreditBranch::getCompanyId,
|
||||
CreditBranch::setCompanyId,
|
||||
CreditBranch::setCompanyName,
|
||||
CreditBranch::getHasData,
|
||||
CreditBranch::setHasData,
|
||||
CreditBranch::getTenantId,
|
||||
CreditBranch::new
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入分支机构
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditBranch:save')")
|
||||
@Operation(summary = "批量导入分支机构")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
ExcelImportSupport.ImportResult<CreditBranchImportParam> importResult = ExcelImportSupport.readAnySheet(
|
||||
file, CreditBranchImportParam.class, this::isEmptyImportRow);
|
||||
List<CreditBranchImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByName = ExcelImportSupport.readHyperlinksByHeaderKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "分支机构名称");
|
||||
String fixedCompanyName = null;
|
||||
if (companyId != null && companyId > 0) {
|
||||
CreditCompany fixedCompany = creditCompanyService.getById(companyId);
|
||||
fixedCompanyName = fixedCompany != null ? fixedCompany.getName() : null;
|
||||
}
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditBranch> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditBranchImportParam param = list.get(i);
|
||||
try {
|
||||
CreditBranch item = convertImportParamToEntity(param);
|
||||
if (!ImportHelper.isBlank(item.getName())) {
|
||||
String link = urlByName.get(item.getName().trim());
|
||||
if (link != null && !link.isEmpty()) {
|
||||
item.setUrl(link);
|
||||
}
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
if (ImportHelper.isBlank(item.getCompanyName()) && !ImportHelper.isBlank(fixedCompanyName)) {
|
||||
item.setCompanyName(fixedCompanyName);
|
||||
}
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getName())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:分支机构名称不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditBranchService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditBranch::getName,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditBranchService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditBranch::getName,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.BRANCH, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载分支机构导入模板
|
||||
*/
|
||||
@Operation(summary = "下载分支机构导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditBranchImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditBranchImportParam example = new CreditBranchImportParam();
|
||||
example.setName("某某公司分支机构");
|
||||
example.setCurator("张三");
|
||||
example.setRegion("广西南宁");
|
||||
example.setEstablishDate("2020-06-01");
|
||||
example.setStatusText("存续");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("分支机构导入模板", "分支机构", CreditBranchImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_branch_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditBranchImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
if (isImportHeaderRow(param)) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getName())
|
||||
&& ImportHelper.isBlank(param.getCurator())
|
||||
&& ImportHelper.isBlank(param.getRegion());
|
||||
}
|
||||
|
||||
private boolean isImportHeaderRow(CreditBranchImportParam param) {
|
||||
return isHeaderValue(param.getName(), "分支机构名称")
|
||||
|| isHeaderValue(param.getCurator(), "负责人")
|
||||
|| isHeaderValue(param.getRegion(), "地区");
|
||||
}
|
||||
|
||||
private static boolean isHeaderValue(String value, String headerText) {
|
||||
if (value == null) {
|
||||
return false;
|
||||
}
|
||||
return headerText.equals(value.trim());
|
||||
}
|
||||
|
||||
private CreditBranch convertImportParamToEntity(CreditBranchImportParam param) {
|
||||
CreditBranch entity = new CreditBranch();
|
||||
|
||||
entity.setName(param.getName());
|
||||
entity.setCurator(param.getCurator());
|
||||
entity.setRegion(param.getRegion());
|
||||
entity.setEstablishDate(param.getEstablishDate());
|
||||
entity.setStatusText(param.getStatusText());
|
||||
entity.setComments(param.getComments());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,513 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditBreachOfTrust;
|
||||
import com.gxwebsoft.credit.param.CreditBreachOfTrustImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditBreachOfTrustParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditBreachOfTrustService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 失信被执行人控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:46:14
|
||||
*/
|
||||
@Tag(name = "失信被执行人管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-breach-of-trust")
|
||||
public class CreditBreachOfTrustController extends BaseController {
|
||||
@Resource
|
||||
private CreditBreachOfTrustService creditBreachOfTrustService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询失信被执行人")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditBreachOfTrust>> page(CreditBreachOfTrustParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditBreachOfTrustService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部失信被执行人")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditBreachOfTrust>> list(CreditBreachOfTrustParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditBreachOfTrustService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询失信被执行人")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditBreachOfTrust> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditBreachOfTrustService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditBreachOfTrust:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加失信被执行人")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditBreachOfTrust creditBreachOfTrust) {
|
||||
if (creditBreachOfTrustService.save(creditBreachOfTrust)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditBreachOfTrust:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改失信被执行人")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditBreachOfTrust creditBreachOfTrust) {
|
||||
if (creditBreachOfTrustService.updateById(creditBreachOfTrust)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditBreachOfTrust:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除失信被执行人")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (batchImportSupport.hardRemoveById(CreditBreachOfTrust.class, id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditBreachOfTrust:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加失信被执行人")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditBreachOfTrust> list) {
|
||||
if (creditBreachOfTrustService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditBreachOfTrust:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改失信被执行人")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditBreachOfTrust> batchParam) {
|
||||
if (batchParam.update(creditBreachOfTrustService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditBreachOfTrust:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除失信被执行人")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (batchImportSupport.hardRemoveByIds(CreditBreachOfTrust.class, ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditBreachOfTrust:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
// Party columns may contain multiple roles/names; match if any company name is contained in the text.
|
||||
// Priority: 原告/上诉人 > 被告/被上诉人 > 其他当事人/第三人
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyNameContainedInText(
|
||||
creditBreachOfTrustService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditBreachOfTrust::getId,
|
||||
CreditBreachOfTrust::setId,
|
||||
CreditBreachOfTrust::getCompanyId,
|
||||
CreditBreachOfTrust::setCompanyId,
|
||||
CreditBreachOfTrust::getHasData,
|
||||
CreditBreachOfTrust::setHasData,
|
||||
CreditBreachOfTrust::getTenantId,
|
||||
CreditBreachOfTrust::new,
|
||||
CreditBreachOfTrust::getPlaintiffAppellant,
|
||||
CreditBreachOfTrust::getAppellee,
|
||||
CreditBreachOfTrust::getOtherPartiesThirdParty
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入失信被执行人
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditBreachOfTrust:save')")
|
||||
@Operation(summary = "批量导入失信被执行人")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "失信被执行人", 0);
|
||||
ExcelImportSupport.ImportResult<CreditBreachOfTrustImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditBreachOfTrustImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditBreachOfTrustImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditBreachOfTrust> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditBreachOfTrustImportParam param = list.get(i);
|
||||
try {
|
||||
CreditBreachOfTrust item = convertImportParamToEntity(param);
|
||||
if (!ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
String link = urlByCaseNumber.get(item.getCaseNumber().trim());
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditBreachOfTrustService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditBreachOfTrust::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditBreachOfTrustService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditBreachOfTrust::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.BREACH_OF_TRUST, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入历史失信被执行人(仅解析“历史失信被执行人”选项卡)
|
||||
* 规则:使用数据库唯一索引约束,重复数据不导入。
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditBreachOfTrust:save')")
|
||||
@Operation(summary = "批量导入历史失信被执行人")
|
||||
@PostMapping("/import/history")
|
||||
public ApiResult<List<String>> importHistoryBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "历史失信被执行人");
|
||||
if (sheetIndex < 0) {
|
||||
return fail("未读取到数据,请确认文件中存在“历史失信被执行人”选项卡且表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
ExcelImportSupport.ImportResult<CreditBreachOfTrustImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditBreachOfTrustImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditBreachOfTrustImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
|
||||
// 同案号多条:以导入文件中“最后一条”为准(视为最新)
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditBreachOfTrust> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditBreachOfTrustImportParam param = list.get(i);
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
try {
|
||||
CreditBreachOfTrust item = convertImportParamToEntity(param);
|
||||
if (item.getCaseNumber() != null) {
|
||||
item.setCaseNumber(item.getCaseNumber().trim());
|
||||
}
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
String link = urlByCaseNumber.get(item.getCaseNumber());
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
// 历史导入的数据统一标记为“失效”
|
||||
item.setDataStatus("失效");
|
||||
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditBreachOfTrustService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditBreachOfTrust::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditBreachOfTrustService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditBreachOfTrust::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.BREACH_OF_TRUST, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
}
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载失信被执行人导入模板
|
||||
*/
|
||||
@Operation(summary = "下载失信被执行人导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditBreachOfTrustImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditBreachOfTrustImportParam example = new CreditBreachOfTrustImportParam();
|
||||
example.setDataType("失信被执行人");
|
||||
example.setCaseNumber("(2024)示例案号");
|
||||
example.setPlaintiffAppellant("原告示例");
|
||||
example.setAppellee("被告示例");
|
||||
example.setOtherPartiesThirdParty("第三人示例");
|
||||
example.setInvolvedAmount("20,293.91");
|
||||
example.setDataStatus("正常");
|
||||
example.setOccurrenceTime("2024-01-01");
|
||||
example.setCourtName("示例法院");
|
||||
example.setReleaseDate("2024-01-01");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("失信被执行人导入模板", "失信被执行人", CreditBreachOfTrustImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_breach_of_trust_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditBreachOfTrustImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getCaseNumber())
|
||||
&& ImportHelper.isBlank(param.getPlaintiffAppellant())
|
||||
&& ImportHelper.isBlank(param.getPlaintiffAppellant2())
|
||||
&& ImportHelper.isBlank(param.getAppellee())
|
||||
&& ImportHelper.isBlank(param.getAppellee2());
|
||||
}
|
||||
|
||||
private CreditBreachOfTrust convertImportParamToEntity(CreditBreachOfTrustImportParam param) {
|
||||
CreditBreachOfTrust entity = new CreditBreachOfTrust();
|
||||
|
||||
entity.setDataType(param.getDataType());
|
||||
entity.setCaseNumber(param.getCaseNumber());
|
||||
|
||||
String plaintiffAppellant = !ImportHelper.isBlank(param.getPlaintiffAppellant2())
|
||||
? param.getPlaintiffAppellant2()
|
||||
: param.getPlaintiffAppellant();
|
||||
entity.setPlaintiffAppellant(plaintiffAppellant);
|
||||
|
||||
String appellee = !ImportHelper.isBlank(param.getAppellee2())
|
||||
? param.getAppellee2()
|
||||
: param.getAppellee();
|
||||
entity.setAppellee(appellee);
|
||||
|
||||
entity.setOtherPartiesThirdParty(param.getOtherPartiesThirdParty());
|
||||
entity.setDataStatus(param.getDataStatus());
|
||||
|
||||
entity.setInvolvedAmount(!ImportHelper.isBlank(param.getInvolvedAmount2())
|
||||
? param.getInvolvedAmount2()
|
||||
: param.getInvolvedAmount());
|
||||
entity.setOccurrenceTime(!ImportHelper.isBlank(param.getOccurrenceTime2())
|
||||
? param.getOccurrenceTime2()
|
||||
: param.getOccurrenceTime());
|
||||
entity.setCourtName(!ImportHelper.isBlank(param.getCourtName2())
|
||||
? param.getCourtName2()
|
||||
: param.getCourtName());
|
||||
entity.setReleaseDate(param.getReleaseDate());
|
||||
entity.setComments(param.getComments());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,525 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditCaseFiling;
|
||||
import com.gxwebsoft.credit.param.CreditCaseFilingImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditCaseFilingParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditCaseFilingService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 司法大数据控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:47:23
|
||||
*/
|
||||
@Tag(name = "司法大数据管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-case-filing")
|
||||
public class CreditCaseFilingController extends BaseController {
|
||||
@Resource
|
||||
private CreditCaseFilingService creditCaseFilingService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询司法大数据")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditCaseFiling>> page(CreditCaseFilingParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditCaseFilingService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部司法大数据")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditCaseFiling>> list(CreditCaseFilingParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditCaseFilingService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询司法大数据")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditCaseFiling> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditCaseFilingService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCaseFiling:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加司法大数据")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditCaseFiling creditCaseFiling) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditCaseFiling.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditCaseFilingService.save(creditCaseFiling)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCaseFiling:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改司法大数据")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditCaseFiling creditCaseFiling) {
|
||||
if (creditCaseFilingService.updateById(creditCaseFiling)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCaseFiling:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除司法大数据")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (batchImportSupport.hardRemoveById(CreditCaseFiling.class, id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCaseFiling:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加司法大数据")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditCaseFiling> list) {
|
||||
if (creditCaseFilingService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCaseFiling:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改司法大数据")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditCaseFiling> batchParam) {
|
||||
if (batchParam.update(creditCaseFilingService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCaseFiling:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除司法大数据")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (batchImportSupport.hardRemoveByIds(CreditCaseFiling.class, ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditCaseFiling:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
// Special: party columns may contain multiple roles/names; match if any company name is contained in the text.
|
||||
// Priority: 原告/上诉人 > 被告/被上诉人 > 其他当事人/第三人
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyNameContainedInText(
|
||||
creditCaseFilingService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditCaseFiling::getId,
|
||||
CreditCaseFiling::setId,
|
||||
CreditCaseFiling::getCompanyId,
|
||||
CreditCaseFiling::setCompanyId,
|
||||
CreditCaseFiling::getHasData,
|
||||
CreditCaseFiling::setHasData,
|
||||
CreditCaseFiling::getTenantId,
|
||||
CreditCaseFiling::new,
|
||||
CreditCaseFiling::getPlaintiffAppellant,
|
||||
CreditCaseFiling::getAppellee,
|
||||
CreditCaseFiling::getOtherPartiesThirdParty
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入立案信息
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditCaseFiling:save')")
|
||||
@Operation(summary = "批量导入立案信息")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "立案信息", 0);
|
||||
ExcelImportSupport.ImportResult<CreditCaseFilingImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditCaseFilingImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditCaseFilingImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
// easypoi 默认不会读取单元格超链接地址;url 通常挂在“案号”列的超链接中,需要额外读取回填。
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readHyperlinksByHeaderKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditCaseFiling> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditCaseFilingImportParam param = list.get(i);
|
||||
try {
|
||||
CreditCaseFiling item = convertImportParamToEntity(param);
|
||||
if (!ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
String link = urlByCaseNumber.get(item.getCaseNumber().trim());
|
||||
if (link != null && !link.isEmpty()) {
|
||||
item.setUrl(link);
|
||||
}
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditCaseFilingService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditCaseFiling::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditCaseFilingService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditCaseFiling::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.CASE_FILING, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入历史立案信息(仅解析“历史立案信息”选项卡)
|
||||
* 规则:使用数据库唯一索引约束,重复数据不导入。
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditCaseFiling:save')")
|
||||
@Operation(summary = "批量导入历史立案信息")
|
||||
@PostMapping("/import/history")
|
||||
public ApiResult<List<String>> importHistoryBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "历史立案信息");
|
||||
if (sheetIndex < 0) {
|
||||
return fail("未读取到数据,请确认文件中存在“历史立案信息”选项卡且表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
ExcelImportSupport.ImportResult<CreditCaseFilingImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditCaseFilingImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditCaseFilingImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditCaseFiling> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditCaseFilingImportParam param = list.get(i);
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
try {
|
||||
CreditCaseFiling item = convertImportParamToEntity(param);
|
||||
if (item.getCaseNumber() != null) {
|
||||
item.setCaseNumber(item.getCaseNumber().trim());
|
||||
}
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
String link = urlByCaseNumber.get(item.getCaseNumber());
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
// 历史导入的数据统一标记为“失效”
|
||||
item.setDataStatus("失效");
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditCaseFilingService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditCaseFiling::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditCaseFilingService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditCaseFiling::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.CASE_FILING, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
}
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载立案信息导入模板
|
||||
*/
|
||||
@Operation(summary = "下载立案信息导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditCaseFilingImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditCaseFilingImportParam example = new CreditCaseFilingImportParam();
|
||||
example.setDataType("立案信息");
|
||||
example.setPlaintiffAppellant("原告示例");
|
||||
example.setAppellee("被告示例");
|
||||
example.setOtherPartiesThirdParty2("第三人示例");
|
||||
example.setInvolvedAmount("100000");
|
||||
example.setDataStatus("正常");
|
||||
example.setCaseNumber("(2024)示例案号");
|
||||
example.setCauseOfAction("案由示例");
|
||||
example.setCourtName("示例法院");
|
||||
example.setOccurrenceTime("2024-01-01");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("立案信息导入模板", "立案信息", CreditCaseFilingImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_case_filing_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditCaseFilingImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getCaseNumber())
|
||||
&& ImportHelper.isBlank(param.getPlaintiffAppellant())
|
||||
&& ImportHelper.isBlank(param.getAppellee())
|
||||
&& ImportHelper.isBlank(param.getCauseOfAction())
|
||||
&& ImportHelper.isBlank(param.getOtherPartiesThirdParty())
|
||||
&& ImportHelper.isBlank(param.getOtherPartiesThirdParty2())
|
||||
&& ImportHelper.isBlank(param.getCourtName())
|
||||
&& ImportHelper.isBlank(param.getCourtName2())
|
||||
&& ImportHelper.isBlank(param.getOccurrenceTime())
|
||||
&& ImportHelper.isBlank(param.getOccurrenceTime2())
|
||||
&& ImportHelper.isBlank(param.getInvolvedAmount())
|
||||
&& ImportHelper.isBlank(param.getInvolvedAmount2())
|
||||
&& ImportHelper.isBlank(param.getDataStatus())
|
||||
&& ImportHelper.isBlank(param.getDataType())
|
||||
&& ImportHelper.isBlank(param.getComments());
|
||||
}
|
||||
|
||||
private CreditCaseFiling convertImportParamToEntity(CreditCaseFilingImportParam param) {
|
||||
CreditCaseFiling entity = new CreditCaseFiling();
|
||||
|
||||
// Template compatibility: prefer new columns when present.
|
||||
String occurrenceTime = !ImportHelper.isBlank(param.getOccurrenceTime2())
|
||||
? param.getOccurrenceTime2()
|
||||
: param.getOccurrenceTime();
|
||||
String otherPartiesThirdParty = !ImportHelper.isBlank(param.getOtherPartiesThirdParty2())
|
||||
? param.getOtherPartiesThirdParty2()
|
||||
: param.getOtherPartiesThirdParty();
|
||||
String courtName = !ImportHelper.isBlank(param.getCourtName2())
|
||||
? param.getCourtName2()
|
||||
: param.getCourtName();
|
||||
String involvedAmount = !ImportHelper.isBlank(param.getInvolvedAmount2())
|
||||
? param.getInvolvedAmount2()
|
||||
: param.getInvolvedAmount();
|
||||
|
||||
entity.setDataType(param.getDataType());
|
||||
entity.setPlaintiffAppellant(param.getPlaintiffAppellant());
|
||||
entity.setAppellee(param.getAppellee());
|
||||
entity.setDataStatus(param.getDataStatus());
|
||||
|
||||
entity.setCaseNumber(param.getCaseNumber());
|
||||
entity.setCauseOfAction(param.getCauseOfAction());
|
||||
entity.setOtherPartiesThirdParty(otherPartiesThirdParty);
|
||||
entity.setCourtName(courtName);
|
||||
entity.setOccurrenceTime(occurrenceTime);
|
||||
entity.setInvolvedAmount(involvedAmount);
|
||||
entity.setComments(param.getComments());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,567 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import cn.afterturn.easypoi.excel.ExcelExportUtil;
|
||||
import cn.afterturn.easypoi.excel.ExcelImportUtil;
|
||||
import cn.afterturn.easypoi.excel.entity.ExportParams;
|
||||
import cn.afterturn.easypoi.excel.entity.ImportParams;
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditCompany;
|
||||
import com.gxwebsoft.credit.param.CreditCompanyImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditCompanyParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 企业控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-17 08:28:03
|
||||
*/
|
||||
@Tag(name = "企业管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-company")
|
||||
public class CreditCompanyController extends BaseController {
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询企业")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditCompany>> page(CreditCompanyParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditCompanyService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部企业")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditCompany>> list(CreditCompanyParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditCompanyService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询企业")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditCompany> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditCompanyService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCompany:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加企业")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditCompany creditCompany) {
|
||||
if (creditCompanyService.save(creditCompany)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCompany:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改企业")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditCompany creditCompany) {
|
||||
if (creditCompanyService.updateById(creditCompany)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCompany:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除企业")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (batchImportSupport.hardRemoveById(CreditCompany.class, id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCompany:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加企业")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditCompany> list) {
|
||||
if (creditCompanyService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCompany:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改企业")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditCompany> batchParam) {
|
||||
if (batchParam.update(creditCompanyService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCompany:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除企业")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (batchImportSupport.hardRemoveByIds(CreditCompany.class, ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入企业
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditJudiciary:save')")
|
||||
@Operation(summary = "批量导入企业")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int insertedCount = 0;
|
||||
Set<String> touchedMatchNames = new HashSet<>();
|
||||
String refreshWarning = null;
|
||||
|
||||
try {
|
||||
List<CreditCompanyImportParam> list = null;
|
||||
int usedTitleRows = 0;
|
||||
int usedHeadRows = 0;
|
||||
int[][] tryConfigs = new int[][]{{1, 1}, {0, 1}, {0, 2}, {0, 3}};
|
||||
|
||||
for (int[] config : tryConfigs) {
|
||||
list = filterEmptyRows(tryImport(file, config[0], config[1]));
|
||||
if (!CollectionUtils.isEmpty(list)) {
|
||||
usedTitleRows = config[0];
|
||||
usedHeadRows = config[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByName = ExcelImportSupport.readHyperlinksByHeaderKey(file, 0, usedTitleRows, usedHeadRows, "原文件导入名称");
|
||||
Map<String, String> urlByMatchName = ExcelImportSupport.readHyperlinksByHeaderKey(file, 0, usedTitleRows, usedHeadRows, "系统匹配企业名称");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditCompany> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditCompanyImportParam param = list.get(i);
|
||||
try {
|
||||
CreditCompany item = convertImportParamToEntity(param);
|
||||
String link = null;
|
||||
if (item.getName() != null) {
|
||||
link = urlByName.get(item.getName().trim());
|
||||
}
|
||||
if ((link == null || link.isEmpty()) && item.getMatchName() != null) {
|
||||
link = urlByMatchName.get(item.getMatchName().trim());
|
||||
}
|
||||
if (link != null && !link.isEmpty()) {
|
||||
item.setUrl(link);
|
||||
}
|
||||
|
||||
// 设置默认值
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
// 验证必填字段
|
||||
if (item.getMatchName() == null || item.getMatchName().trim().isEmpty()) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:项目名称不能为空");
|
||||
continue;
|
||||
}
|
||||
// if (item.getCode() == null || item.getCode().trim().isEmpty()) {
|
||||
// errorMessages.add("第" + excelRowNumber + "行:唯一标识不能为空");
|
||||
// continue;
|
||||
// }
|
||||
|
||||
touchedMatchNames.add(item.getMatchName().trim());
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
insertedCount += batchImportSupport.persistChunkWithFallbackCount(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> {
|
||||
int delta = countInsertedByMatchName(chunkItems);
|
||||
batchImportSupport.upsertBySingleKey(
|
||||
creditCompanyService,
|
||||
chunkItems,
|
||||
CreditCompany::getId,
|
||||
CreditCompany::setId,
|
||||
CreditCompany::getMatchName,
|
||||
CreditCompany::getMatchName,
|
||||
null,
|
||||
mpBatchSize
|
||||
);
|
||||
return delta;
|
||||
},
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditCompanyService.save(rowItem);
|
||||
if (saved) {
|
||||
return 1; // insert 入库
|
||||
}
|
||||
CreditCompany existing = creditCompanyService.getByMatchName(rowItem.getMatchName());
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditCompanyService.updateById(rowItem)) {
|
||||
return 0; // update 不计入“入库”条数
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("保存失败");
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
insertedCount += batchImportSupport.persistChunkWithFallbackCount(
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
() -> {
|
||||
int delta = countInsertedByMatchName(chunkItems);
|
||||
batchImportSupport.upsertBySingleKey(
|
||||
creditCompanyService,
|
||||
chunkItems,
|
||||
CreditCompany::getId,
|
||||
CreditCompany::setId,
|
||||
CreditCompany::getMatchName,
|
||||
CreditCompany::getMatchName,
|
||||
null,
|
||||
mpBatchSize
|
||||
);
|
||||
return delta;
|
||||
},
|
||||
(rowItem, rowNumber) -> {
|
||||
boolean saved = creditCompanyService.save(rowItem);
|
||||
if (saved) {
|
||||
return 1; // insert 入库
|
||||
}
|
||||
CreditCompany existing = creditCompanyService.getByMatchName(rowItem.getMatchName());
|
||||
if (existing != null) {
|
||||
rowItem.setId(existing.getId());
|
||||
if (creditCompanyService.updateById(rowItem)) {
|
||||
return 0; // update 不计入“入库”条数
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("保存失败");
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
// 导入完成后,按 matchName 定位本次涉及的企业并回填“关联记录数”字段(避免 companyId/自增 id 在导入对象里拿不到)。
|
||||
if (!touchedMatchNames.isEmpty()) {
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
List<String> allMatchNames = new ArrayList<>(touchedMatchNames);
|
||||
final int inChunkSize = 800;
|
||||
for (int i = 0; i < allMatchNames.size(); i += inChunkSize) {
|
||||
List<String> chunk = allMatchNames.subList(i, Math.min(allMatchNames.size(), i + inChunkSize));
|
||||
List<CreditCompany> dbRows = creditCompanyService.lambdaQuery()
|
||||
.select(CreditCompany::getId)
|
||||
.in(CreditCompany::getMatchName, chunk)
|
||||
.list();
|
||||
if (!CollectionUtils.isEmpty(dbRows)) {
|
||||
for (CreditCompany row : dbRows) {
|
||||
if (row != null && row.getId() != null) {
|
||||
touchedCompanyIds.add(row.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
creditCompanyRecordCountService.refreshAll(touchedCompanyIds);
|
||||
} catch (Exception ex) {
|
||||
// 导入本身已经成功写入,回填计数字段失败不应导致整个导入失败(可后续单独重试刷新)。
|
||||
String msg = ex.getMessage();
|
||||
if (msg != null && msg.length() > 300) {
|
||||
msg = msg.substring(0, 300) + "...";
|
||||
}
|
||||
refreshWarning = "关联记录数回填失败:" + (msg != null ? msg : ex.getClass().getSimpleName());
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
String msg = "成功入库" + insertedCount + "条数据";
|
||||
if (refreshWarning != null) {
|
||||
msg = msg + ";" + refreshWarning;
|
||||
}
|
||||
return success(msg, null);
|
||||
} else {
|
||||
String msg = "导入完成,入库" + insertedCount + "条,失败" + errorMessages.size() + "条";
|
||||
if (refreshWarning != null) {
|
||||
msg = msg + ";" + refreshWarning;
|
||||
}
|
||||
return success(msg, errorMessages);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载企业导入模板
|
||||
*/
|
||||
@Operation(summary = "下载企业导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditCompanyImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditCompanyImportParam example = new CreditCompanyImportParam();
|
||||
example.setName("示例客户");
|
||||
example.setCode("C0001");
|
||||
example.setMatchName("匹配名称");
|
||||
example.setRegistrationStatus("登记状态");
|
||||
example.setLegalPerson("法定代表人");
|
||||
example.setRegisteredCapital("注册资本");
|
||||
example.setPaidinCapital("实缴资本");
|
||||
example.setEstablishDate("成立日期");
|
||||
example.setAddress("地址");
|
||||
example.setTel("电话");
|
||||
example.setMoreTel("更多电话");
|
||||
example.setEmail("邮箱");
|
||||
example.setMoreEmail("更多邮箱");
|
||||
example.setProvince("省");
|
||||
example.setCity("市");
|
||||
example.setRegion("区");
|
||||
example.setInstitutionType("机构类型");
|
||||
example.setTaxpayerCode("纳税人识别号");
|
||||
example.setRegistrationNumber("注册号");
|
||||
example.setOrganizationalCode("组织机构代码");
|
||||
example.setNumberOfInsuredPersons("参保人数");
|
||||
example.setAnnualReport("入库时间");
|
||||
example.setBusinessTerm("营业期限");
|
||||
example.setNationalStandardIndustryCategories("国标行业门类");
|
||||
example.setNationalStandardIndustryCategories2("国标行业大类");
|
||||
example.setNationalStandardIndustryCategories3("国标行业中类");
|
||||
example.setNationalStandardIndustryCategories4("国标行业小类");
|
||||
example.setNationalStandardIndustryCategories5("企查查行业门类");
|
||||
example.setNationalStandardIndustryCategories6("企查查行业大类");
|
||||
example.setNationalStandardIndustryCategories7("企查查行业中类");
|
||||
example.setNationalStandardIndustryCategories8("企查查行业小类");
|
||||
example.setCompanySize("企业规模");
|
||||
example.setFormerName("曾用名");
|
||||
example.setEnglishName("英文名");
|
||||
example.setDomain("官网");
|
||||
example.setMailingAddress("通信地址");
|
||||
example.setCompanyProfile("企业简介");
|
||||
example.setNatureOfBusiness("经营范围");
|
||||
example.setRegistrationAuthority("登记机关");
|
||||
example.setTaxpayerQualification("纳税人资质");
|
||||
example.setLatestAnnualReportYear("最新年报年份");
|
||||
example.setLatestAnnualReportOnOperatingRevenue("最新年报营业额");
|
||||
example.setEnterpriseScoreCheck("企查分");
|
||||
example.setCreditRating("信用等级");
|
||||
example.setCechnologyScore("科创分");
|
||||
example.setCechnologyLevel("科创等级");
|
||||
example.setSmallEnterprise("是否小微企业");
|
||||
templateList.add(example);
|
||||
|
||||
ExportParams exportParams = new ExportParams("一级企业主表导入模板", "企业");
|
||||
|
||||
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, CreditCompanyImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_company_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private List<CreditCompanyImportParam> tryImport(MultipartFile file, int titleRows, int headRows) throws Exception {
|
||||
ImportParams importParams = new ImportParams();
|
||||
importParams.setTitleRows(titleRows);
|
||||
importParams.setHeadRows(headRows);
|
||||
importParams.setStartSheetIndex(0);
|
||||
importParams.setSheetNum(1);
|
||||
return ExcelImportUtil.importExcel(file.getInputStream(), CreditCompanyImportParam.class, importParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤掉完全空白的导入行,避免空行导致导入失败
|
||||
*/
|
||||
private List<CreditCompanyImportParam> filterEmptyRows(List<CreditCompanyImportParam> rawList) {
|
||||
if (CollectionUtils.isEmpty(rawList)) {
|
||||
return rawList;
|
||||
}
|
||||
rawList.removeIf(this::isEmptyImportRow);
|
||||
return rawList;
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditCompanyImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
return isBlank(param.getName())
|
||||
&& isBlank(param.getCode());
|
||||
}
|
||||
|
||||
private boolean isBlank(String value) {
|
||||
return value == null || value.trim().isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* 入库条数以 insert 为准:matchName 在数据库中不存在时计 1,否则计 0。
|
||||
*
|
||||
* <p>统计口径需与批量 upsert 的匹配字段保持一致(matchName)。</p>
|
||||
*/
|
||||
private int countInsertedByMatchName(List<CreditCompany> items) {
|
||||
if (CollectionUtils.isEmpty(items)) {
|
||||
return 0;
|
||||
}
|
||||
List<String> matchNames = new ArrayList<>(items.size());
|
||||
for (CreditCompany item : items) {
|
||||
if (item == null) {
|
||||
continue;
|
||||
}
|
||||
String key = item.getMatchName();
|
||||
if (!isBlank(key)) {
|
||||
matchNames.add(key.trim());
|
||||
}
|
||||
}
|
||||
if (matchNames.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Set<String> existing = new HashSet<>();
|
||||
List<CreditCompany> dbRows = creditCompanyService.lambdaQuery()
|
||||
.select(CreditCompany::getMatchName)
|
||||
.in(CreditCompany::getMatchName, matchNames)
|
||||
.list();
|
||||
if (!CollectionUtils.isEmpty(dbRows)) {
|
||||
for (CreditCompany row : dbRows) {
|
||||
String v = row != null ? row.getMatchName() : null;
|
||||
if (!isBlank(v)) {
|
||||
existing.add(v.trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
for (CreditCompany item : items) {
|
||||
String key = item != null ? item.getMatchName() : null;
|
||||
if (!isBlank(key) && !existing.contains(key.trim())) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将CreditCompanyImportParam转换为CreditCompany实体
|
||||
*/
|
||||
private CreditCompany convertImportParamToEntity(CreditCompanyImportParam param) {
|
||||
CreditCompany entity = new CreditCompany();
|
||||
|
||||
entity.setCode(param.getCode());
|
||||
entity.setName(param.getName());
|
||||
entity.setMatchName(param.getMatchName());
|
||||
entity.setRegistrationStatus(param.getRegistrationStatus());
|
||||
entity.setLegalPerson(param.getLegalPerson());
|
||||
entity.setRegisteredCapital(param.getRegisteredCapital());
|
||||
entity.setPaidinCapital(param.getPaidinCapital());
|
||||
entity.setEstablishDate(param.getEstablishDate());
|
||||
entity.setAddress(param.getAddress());
|
||||
entity.setTel(param.getTel());
|
||||
entity.setMoreTel(param.getMoreTel());
|
||||
entity.setEmail(param.getEmail());
|
||||
entity.setMoreEmail(param.getMoreEmail());
|
||||
entity.setProvince(param.getProvince());
|
||||
entity.setCity(param.getCity());
|
||||
entity.setRegion(param.getRegion());
|
||||
entity.setInstitutionType(param.getInstitutionType());
|
||||
entity.setTaxpayerCode(param.getTaxpayerCode());
|
||||
entity.setRegistrationNumber(param.getRegistrationNumber());
|
||||
entity.setOrganizationalCode(param.getOrganizationalCode());
|
||||
entity.setNumberOfInsuredPersons(param.getNumberOfInsuredPersons());
|
||||
entity.setAnnualReport(param.getAnnualReport());
|
||||
entity.setBusinessTerm(param.getBusinessTerm());
|
||||
entity.setNationalStandardIndustryCategories(param.getNationalStandardIndustryCategories());
|
||||
entity.setNationalStandardIndustryCategories2(param.getNationalStandardIndustryCategories2());
|
||||
entity.setNationalStandardIndustryCategories3(param.getNationalStandardIndustryCategories3());
|
||||
entity.setNationalStandardIndustryCategories4(param.getNationalStandardIndustryCategories4());
|
||||
entity.setNationalStandardIndustryCategories5(param.getNationalStandardIndustryCategories5());
|
||||
entity.setNationalStandardIndustryCategories6(param.getNationalStandardIndustryCategories6());
|
||||
entity.setNationalStandardIndustryCategories7(param.getNationalStandardIndustryCategories7());
|
||||
entity.setNationalStandardIndustryCategories8(param.getNationalStandardIndustryCategories8());
|
||||
entity.setCompanySize(param.getCompanySize());
|
||||
entity.setFormerName(param.getFormerName());
|
||||
entity.setEnglishName(param.getEnglishName());
|
||||
entity.setDomain(param.getDomain());
|
||||
entity.setMailingAddress(param.getMailingAddress());
|
||||
entity.setCompanyProfile(param.getCompanyProfile());
|
||||
entity.setNatureOfBusiness(param.getNatureOfBusiness());
|
||||
entity.setRegistrationAuthority(param.getRegistrationAuthority());
|
||||
entity.setTaxpayerQualification(param.getTaxpayerQualification());
|
||||
entity.setLatestAnnualReportYear(param.getLatestAnnualReportYear());
|
||||
entity.setLatestAnnualReportOnOperatingRevenue(param.getLatestAnnualReportOnOperatingRevenue());
|
||||
entity.setEnterpriseScoreCheck(param.getEnterpriseScoreCheck());
|
||||
entity.setCreditRating(param.getCreditRating());
|
||||
entity.setCechnologyScore(param.getCechnologyScore());
|
||||
entity.setCechnologyLevel(param.getCechnologyLevel());
|
||||
entity.setSmallEnterprise(param.getSmallEnterprise());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,372 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditCompany;
|
||||
import com.gxwebsoft.credit.entity.CreditCompetitor;
|
||||
import com.gxwebsoft.credit.param.CreditCompetitorImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditCompetitorParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditCompetitorService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 竞争对手控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:49:05
|
||||
*/
|
||||
@Tag(name = "竞争对手管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-competitor")
|
||||
public class CreditCompetitorController extends BaseController {
|
||||
@Resource
|
||||
private CreditCompetitorService creditCompetitorService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询竞争对手")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditCompetitor>> page(CreditCompetitorParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditCompetitorService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部竞争对手")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditCompetitor>> list(CreditCompetitorParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditCompetitorService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询竞争对手")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditCompetitor> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditCompetitorService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCompetitor:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加竞争对手")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditCompetitor creditCompetitor) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditCompetitor.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditCompetitorService.save(creditCompetitor)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCompetitor:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改竞争对手")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditCompetitor creditCompetitor) {
|
||||
if (creditCompetitorService.updateById(creditCompetitor)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCompetitor:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除竞争对手")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (batchImportSupport.hardRemoveById(CreditCompetitor.class, id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCompetitor:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加竞争对手")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditCompetitor> list) {
|
||||
if (creditCompetitorService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCompetitor:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改竞争对手")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditCompetitor> batchParam) {
|
||||
if (batchParam.update(creditCompetitorService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCompetitor:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除竞争对手")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (batchImportSupport.hardRemoveByIds(CreditCompetitor.class, ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditCompetitor:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
|
||||
creditCompetitorService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditCompetitor::getId,
|
||||
CreditCompetitor::setId,
|
||||
CreditCompetitor::getName,
|
||||
CreditCompetitor::getCompanyId,
|
||||
CreditCompetitor::setCompanyId,
|
||||
CreditCompetitor::setCompanyName,
|
||||
CreditCompetitor::getHasData,
|
||||
CreditCompetitor::setHasData,
|
||||
CreditCompetitor::getTenantId,
|
||||
CreditCompetitor::new
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入竞争对手
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditCompetitor:save')")
|
||||
@Operation(summary = "批量导入竞争对手")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "竞争对手", 2);
|
||||
ExcelImportSupport.ImportResult<CreditCompetitorImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditCompetitorImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditCompetitorImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByName = ExcelImportSupport.readUrlByKey(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "企业名称");
|
||||
String fixedCompanyName = null;
|
||||
if (companyId != null && companyId > 0) {
|
||||
CreditCompany fixedCompany = creditCompanyService.getById(companyId);
|
||||
fixedCompanyName = fixedCompany != null ? fixedCompany.getName() : null;
|
||||
}
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditCompetitor> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditCompetitorImportParam param = list.get(i);
|
||||
try {
|
||||
CreditCompetitor item = convertImportParamToEntity(param);
|
||||
// name 为竞争对手企业名称;companyName 为主体企业名称。
|
||||
if (!ImportHelper.isBlank(item.getName())) {
|
||||
String link = urlByName.get(item.getName().trim());
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
if (ImportHelper.isBlank(item.getCompanyName()) && !ImportHelper.isBlank(fixedCompanyName)) {
|
||||
item.setCompanyName(fixedCompanyName);
|
||||
}
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getName())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:企业名称不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditCompetitorService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditCompetitor::getName,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditCompetitorService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditCompetitor::getName,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.COMPETITOR, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载竞争对手导入模板
|
||||
*/
|
||||
@Operation(summary = "下载竞争对手导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditCompetitorImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditCompetitorImportParam example = new CreditCompetitorImportParam();
|
||||
example.setName("示例科技有限公司");
|
||||
example.setLegalRepresentative("张三");
|
||||
example.setRegisteredCapital("5000");
|
||||
example.setEstablishmentDate("2015-01-01");
|
||||
example.setRegistrationStatus("存续");
|
||||
example.setIndustry("软件和信息服务业");
|
||||
example.setProvince("广东省");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("竞争对手导入模板", "竞争对手", CreditCompetitorImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_competitor_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditCompetitorImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getName())
|
||||
&& ImportHelper.isBlank(param.getLegalRepresentative())
|
||||
&& ImportHelper.isBlank(param.getRegisteredCapital())
|
||||
&& ImportHelper.isBlank(param.getEstablishmentDate());
|
||||
}
|
||||
|
||||
private CreditCompetitor convertImportParamToEntity(CreditCompetitorImportParam param) {
|
||||
CreditCompetitor entity = new CreditCompetitor();
|
||||
|
||||
entity.setName(param.getName());
|
||||
entity.setLegalRepresentative(param.getLegalRepresentative());
|
||||
entity.setRegisteredCapital(param.getRegisteredCapital());
|
||||
entity.setEstablishmentDate(param.getEstablishmentDate());
|
||||
entity.setRegistrationStatus(param.getRegistrationStatus());
|
||||
entity.setIndustry(param.getIndustry());
|
||||
entity.setProvince(param.getProvince());
|
||||
entity.setComments(param.getComments());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,517 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditCourtAnnouncement;
|
||||
import com.gxwebsoft.credit.param.CreditCourtAnnouncementImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditCourtAnnouncementParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditCourtAnnouncementService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 法院公告司法大数据控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:49:13
|
||||
*/
|
||||
@Tag(name = "法院公告司法大数据管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-court-announcement")
|
||||
public class CreditCourtAnnouncementController extends BaseController {
|
||||
@Resource
|
||||
private CreditCourtAnnouncementService creditCourtAnnouncementService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询法院公告司法大数据")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditCourtAnnouncement>> page(CreditCourtAnnouncementParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditCourtAnnouncementService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部法院公告司法大数据")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditCourtAnnouncement>> list(CreditCourtAnnouncementParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditCourtAnnouncementService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询法院公告司法大数据")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditCourtAnnouncement> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditCourtAnnouncementService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCourtAnnouncement:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加法院公告司法大数据")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditCourtAnnouncement creditCourtAnnouncement) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditCourtAnnouncement.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditCourtAnnouncementService.save(creditCourtAnnouncement)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCourtAnnouncement:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改法院公告司法大数据")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditCourtAnnouncement creditCourtAnnouncement) {
|
||||
if (creditCourtAnnouncementService.updateById(creditCourtAnnouncement)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCourtAnnouncement:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除法院公告司法大数据")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (batchImportSupport.hardRemoveById(CreditCourtAnnouncement.class, id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCourtAnnouncement:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加法院公告司法大数据")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditCourtAnnouncement> list) {
|
||||
if (creditCourtAnnouncementService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCourtAnnouncement:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改法院公告司法大数据")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditCourtAnnouncement> batchParam) {
|
||||
if (batchParam.update(creditCourtAnnouncementService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCourtAnnouncement:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除法院公告司法大数据")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (batchImportSupport.hardRemoveByIds(CreditCourtAnnouncement.class, ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditCourtAnnouncement:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
// Party columns may contain multiple roles/names; match if any company name is contained in the text.
|
||||
// Priority: 原告/上诉人 > 被告/被上诉人 > 其他当事人/第三人
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyNameContainedInText(
|
||||
creditCourtAnnouncementService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditCourtAnnouncement::getId,
|
||||
CreditCourtAnnouncement::setId,
|
||||
CreditCourtAnnouncement::getCompanyId,
|
||||
CreditCourtAnnouncement::setCompanyId,
|
||||
CreditCourtAnnouncement::getHasData,
|
||||
CreditCourtAnnouncement::setHasData,
|
||||
CreditCourtAnnouncement::getTenantId,
|
||||
CreditCourtAnnouncement::new,
|
||||
CreditCourtAnnouncement::getPlaintiffAppellant,
|
||||
CreditCourtAnnouncement::getAppellee,
|
||||
CreditCourtAnnouncement::getOtherPartiesThirdParty
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入法院公告司法大数据
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditCourtAnnouncement:save')")
|
||||
@Operation(summary = "批量导入法院公告司法大数据")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
// 兼容多 sheet 文件:优先定位“法院公告”sheet,否则默认第 0 个。
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "法院公告", 0);
|
||||
ExcelImportSupport.ImportResult<CreditCourtAnnouncementImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditCourtAnnouncementImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditCourtAnnouncementImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditCourtAnnouncement> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditCourtAnnouncementImportParam param = list.get(i);
|
||||
try {
|
||||
CreditCourtAnnouncement item = convertImportParamToEntity(param);
|
||||
if (!ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
String link = urlByCaseNumber.get(item.getCaseNumber().trim());
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditCourtAnnouncementService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditCourtAnnouncement::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditCourtAnnouncementService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditCourtAnnouncement::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.COURT_ANNOUNCEMENT, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入历史法院公告(仅解析“历史法院公告”选项卡;兼容“历史法庭公告”)
|
||||
* 规则:使用数据库唯一索引约束,重复数据不导入。
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditCourtAnnouncement:save')")
|
||||
@Operation(summary = "批量导入历史法院公告司法大数据")
|
||||
@PostMapping("/import/history")
|
||||
public ApiResult<List<String>> importHistoryBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "历史法院公告");
|
||||
if (sheetIndex < 0) {
|
||||
// 兼容旧命名
|
||||
sheetIndex = ExcelImportSupport.findSheetIndex(file, "历史法庭公告");
|
||||
}
|
||||
if (sheetIndex < 0) {
|
||||
return fail("未读取到数据,请确认文件中存在“历史法院公告”选项卡且表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
ExcelImportSupport.ImportResult<CreditCourtAnnouncementImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditCourtAnnouncementImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditCourtAnnouncementImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditCourtAnnouncement> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditCourtAnnouncementImportParam param = list.get(i);
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
try {
|
||||
CreditCourtAnnouncement item = convertImportParamToEntity(param);
|
||||
if (item.getCaseNumber() != null) {
|
||||
item.setCaseNumber(item.getCaseNumber().trim());
|
||||
}
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
String link = urlByCaseNumber.get(item.getCaseNumber());
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
// 历史导入的数据统一标记为“失效”
|
||||
item.setDataStatus("失效");
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditCourtAnnouncementService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditCourtAnnouncement::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditCourtAnnouncementService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditCourtAnnouncement::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.COURT_ANNOUNCEMENT, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
}
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载法院公告司法大数据导入模板
|
||||
*/
|
||||
@Operation(summary = "下载法院公告司法大数据导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditCourtAnnouncementImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditCourtAnnouncementImportParam example = new CreditCourtAnnouncementImportParam();
|
||||
example.setDataType("法院公告");
|
||||
example.setPlaintiffAppellant("原告示例");
|
||||
example.setAppellee("被告示例");
|
||||
example.setOtherPartiesThirdParty("第三人示例");
|
||||
example.setOccurrenceTime("2024-01-01");
|
||||
example.setCaseNumber("(2024)示例案号");
|
||||
example.setCauseOfAction("案由示例");
|
||||
example.setCourtName("示例法院");
|
||||
example.setInvolvedAmount("100000");
|
||||
example.setDataStatus("正常");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("法院公告导入模板", "法院公告", CreditCourtAnnouncementImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_court_announcement_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditCourtAnnouncementImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getCaseNumber())
|
||||
&& ImportHelper.isBlank(param.getCauseOfAction());
|
||||
}
|
||||
|
||||
private CreditCourtAnnouncement convertImportParamToEntity(CreditCourtAnnouncementImportParam param) {
|
||||
CreditCourtAnnouncement entity = new CreditCourtAnnouncement();
|
||||
|
||||
String dataType = !ImportHelper.isBlank(param.getDataType2())
|
||||
? param.getDataType2()
|
||||
: param.getDataType();
|
||||
String plaintiffAppellant = !ImportHelper.isBlank(param.getPlaintiffAppellant2())
|
||||
? param.getPlaintiffAppellant2()
|
||||
: param.getPlaintiffAppellant();
|
||||
String otherPartiesThirdParty = !ImportHelper.isBlank(param.getOtherPartiesThirdParty2())
|
||||
? param.getOtherPartiesThirdParty2()
|
||||
: param.getOtherPartiesThirdParty();
|
||||
String involvedAmount = !ImportHelper.isBlank(param.getInvolvedAmount2())
|
||||
? param.getInvolvedAmount2()
|
||||
: param.getInvolvedAmount();
|
||||
|
||||
String occurrenceTime = !ImportHelper.isBlank(param.getOccurrenceTime2())
|
||||
? param.getOccurrenceTime2()
|
||||
: param.getOccurrenceTime();
|
||||
|
||||
entity.setDataType(dataType);
|
||||
entity.setPlaintiffAppellant(plaintiffAppellant);
|
||||
entity.setAppellee(param.getAppellee());
|
||||
entity.setOtherPartiesThirdParty(otherPartiesThirdParty);
|
||||
entity.setOccurrenceTime(occurrenceTime);
|
||||
entity.setCaseNumber(param.getCaseNumber());
|
||||
entity.setCauseOfAction(param.getCauseOfAction());
|
||||
entity.setCourtName(param.getCourtName());
|
||||
entity.setInvolvedAmount(involvedAmount);
|
||||
entity.setDataStatus(param.getDataStatus());
|
||||
entity.setComments(param.getComments());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,512 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditCourtSession;
|
||||
import com.gxwebsoft.credit.param.CreditCourtSessionImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditCourtSessionParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditCourtSessionService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 开庭公告司法大数据控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:49:33
|
||||
*/
|
||||
@Tag(name = "开庭公告司法大数据管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-court-session")
|
||||
public class CreditCourtSessionController extends BaseController {
|
||||
@Resource
|
||||
private CreditCourtSessionService creditCourtSessionService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询开庭公告司法大数据")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditCourtSession>> page(CreditCourtSessionParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditCourtSessionService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部开庭公告司法大数据")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditCourtSession>> list(CreditCourtSessionParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditCourtSessionService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询开庭公告司法大数据")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditCourtSession> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditCourtSessionService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCourtSession:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加开庭公告司法大数据")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditCourtSession creditCourtSession) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditCourtSession.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditCourtSessionService.save(creditCourtSession)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCourtSession:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改开庭公告司法大数据")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditCourtSession creditCourtSession) {
|
||||
if (creditCourtSessionService.updateById(creditCourtSession)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCourtSession:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除开庭公告司法大数据")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (batchImportSupport.hardRemoveById(CreditCourtSession.class, id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCourtSession:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加开庭公告司法大数据")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditCourtSession> list) {
|
||||
if (creditCourtSessionService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCourtSession:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改开庭公告司法大数据")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditCourtSession> batchParam) {
|
||||
if (batchParam.update(creditCourtSessionService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCourtSession:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除开庭公告司法大数据")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (batchImportSupport.hardRemoveByIds(CreditCourtSession.class, ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditCourtSession:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
// Party columns may contain multiple roles/names; match if any company name is contained in the text.
|
||||
// Priority: 原告/上诉人 > 被告/被上诉人 > 其他当事人/第三人
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyNameContainedInText(
|
||||
creditCourtSessionService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditCourtSession::getId,
|
||||
CreditCourtSession::setId,
|
||||
CreditCourtSession::getCompanyId,
|
||||
CreditCourtSession::setCompanyId,
|
||||
CreditCourtSession::getHasData,
|
||||
CreditCourtSession::setHasData,
|
||||
CreditCourtSession::getTenantId,
|
||||
CreditCourtSession::new,
|
||||
CreditCourtSession::getPlaintiffAppellant,
|
||||
CreditCourtSession::getAppellee,
|
||||
CreditCourtSession::getOtherPartiesThirdParty
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入开庭公告司法大数据
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditCourtSession:save')")
|
||||
@Operation(summary = "批量导入开庭公告司法大数据")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
// 兼容多 sheet 文件:优先定位“开庭公告”sheet,否则默认第 0 个。
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "开庭公告", 0);
|
||||
ExcelImportSupport.ImportResult<CreditCourtSessionImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditCourtSessionImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditCourtSessionImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditCourtSession> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditCourtSessionImportParam param = list.get(i);
|
||||
try {
|
||||
CreditCourtSession item = convertImportParamToEntity(param);
|
||||
if (!ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
String link = urlByCaseNumber.get(item.getCaseNumber().trim());
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditCourtSessionService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditCourtSession::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditCourtSessionService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditCourtSession::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.COURT_SESSION, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入历史开庭公告(仅解析“历史开庭公告”选项卡)
|
||||
* 规则:使用数据库唯一索引约束,重复数据不导入。
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditCourtSession:save')")
|
||||
@Operation(summary = "批量导入历史开庭公告司法大数据")
|
||||
@PostMapping("/import/history")
|
||||
public ApiResult<List<String>> importHistoryBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "历史开庭公告");
|
||||
if (sheetIndex < 0) {
|
||||
return fail("未读取到数据,请确认文件中存在“历史开庭公告”选项卡且表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
ExcelImportSupport.ImportResult<CreditCourtSessionImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditCourtSessionImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditCourtSessionImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditCourtSession> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditCourtSessionImportParam param = list.get(i);
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
try {
|
||||
CreditCourtSession item = convertImportParamToEntity(param);
|
||||
if (item.getCaseNumber() != null) {
|
||||
item.setCaseNumber(item.getCaseNumber().trim());
|
||||
}
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
String link = urlByCaseNumber.get(item.getCaseNumber());
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
// 历史导入的数据统一标记为“失效”
|
||||
item.setDataStatus("失效");
|
||||
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditCourtSessionService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditCourtSession::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditCourtSessionService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditCourtSession::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.COURT_SESSION, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
}
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载开庭公告司法大数据导入模板
|
||||
*/
|
||||
@Operation(summary = "下载开庭公告司法大数据导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditCourtSessionImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditCourtSessionImportParam example = new CreditCourtSessionImportParam();
|
||||
example.setDataType("开庭公告");
|
||||
example.setPlaintiffAppellant("原告示例");
|
||||
example.setAppellee("被告示例");
|
||||
example.setOtherPartiesThirdParty2("第三人示例");
|
||||
example.setCaseNumber("(2024)示例案号");
|
||||
example.setCauseOfAction("案由示例");
|
||||
example.setCourtName("示例法院");
|
||||
example.setOccurrenceTime("2024-01-01");
|
||||
example.setInvolvedAmount("100000");
|
||||
example.setDataStatus("正常");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("开庭公告导入模板", "开庭公告", CreditCourtSessionImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_court_session_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditCourtSessionImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getCaseNumber())
|
||||
&& ImportHelper.isBlank(param.getCauseOfAction());
|
||||
}
|
||||
|
||||
private CreditCourtSession convertImportParamToEntity(CreditCourtSessionImportParam param) {
|
||||
CreditCourtSession entity = new CreditCourtSession();
|
||||
|
||||
// Template compatibility: prefer new columns ("发生时间"/"其他当事人/第三人") when present.
|
||||
String occurrenceTime = !ImportHelper.isBlank(param.getOccurrenceTime2())
|
||||
? param.getOccurrenceTime2()
|
||||
: param.getOccurrenceTime();
|
||||
String otherPartiesThirdParty = !ImportHelper.isBlank(param.getOtherPartiesThirdParty2())
|
||||
? param.getOtherPartiesThirdParty2()
|
||||
: param.getOtherPartiesThirdParty();
|
||||
String involvedAmount = !ImportHelper.isBlank(param.getInvolvedAmount2())
|
||||
? param.getInvolvedAmount2()
|
||||
: param.getInvolvedAmount();
|
||||
|
||||
entity.setDataType(param.getDataType());
|
||||
entity.setPlaintiffAppellant(param.getPlaintiffAppellant());
|
||||
entity.setAppellee(param.getAppellee());
|
||||
entity.setDataStatus(param.getDataStatus());
|
||||
entity.setInvolvedAmount(involvedAmount);
|
||||
|
||||
entity.setOtherPartiesThirdParty(otherPartiesThirdParty);
|
||||
entity.setOccurrenceTime(occurrenceTime);
|
||||
entity.setCaseNumber(param.getCaseNumber());
|
||||
entity.setCauseOfAction(param.getCauseOfAction());
|
||||
entity.setCourtName(param.getCourtName());
|
||||
entity.setComments(param.getComments());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,420 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditCompany;
|
||||
import com.gxwebsoft.credit.entity.CreditCustomer;
|
||||
import com.gxwebsoft.credit.param.CreditCustomerImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditCustomerParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditCustomerService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 客户控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-21 21:20:58
|
||||
*/
|
||||
@Tag(name = "客户管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-customer")
|
||||
public class CreditCustomerController extends BaseController {
|
||||
@Resource
|
||||
private CreditCustomerService creditCustomerService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询客户")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditCustomer>> page(CreditCustomerParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditCustomerService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部客户")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditCustomer>> list(CreditCustomerParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditCustomerService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询客户")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditCustomer> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditCustomerService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCustomer:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加客户")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditCustomer creditCustomer) {
|
||||
if (creditCustomerService.save(creditCustomer)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCustomer:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改客户")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditCustomer creditCustomer) {
|
||||
if (creditCustomerService.updateById(creditCustomer)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCustomer:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除客户")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (batchImportSupport.hardRemoveById(CreditCustomer.class, id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCustomer:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加客户")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditCustomer> list) {
|
||||
if (creditCustomerService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCustomer:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改客户")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditCustomer> batchParam) {
|
||||
if (batchParam.update(creditCustomerService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditCustomer:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除客户")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (batchImportSupport.hardRemoveByIds(CreditCustomer.class, ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditCustomer:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
|
||||
creditCustomerService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditCustomer::getId,
|
||||
CreditCustomer::setId,
|
||||
CreditCustomer::getName,
|
||||
CreditCustomer::getCompanyId,
|
||||
CreditCustomer::setCompanyId,
|
||||
CreditCustomer::setCompanyName,
|
||||
CreditCustomer::getHasData,
|
||||
CreditCustomer::setHasData,
|
||||
CreditCustomer::getTenantId,
|
||||
CreditCustomer::new
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入客户
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditCustomer:save')")
|
||||
@Operation(summary = "批量导入客户")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "客户", 4);
|
||||
ExcelImportSupport.ImportResult<CreditCustomerImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditCustomerImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditCustomerImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByName = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "客户");
|
||||
String fixedCompanyName = null;
|
||||
if (companyId != null && companyId > 0) {
|
||||
CreditCompany fixedCompany = creditCompanyService.getById(companyId);
|
||||
fixedCompanyName = fixedCompany != null ? fixedCompany.getName() : null;
|
||||
}
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditCustomer> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditCustomerImportParam param = list.get(i);
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
try {
|
||||
CreditCustomer item = convertImportParamToEntity(param);
|
||||
if (!ImportHelper.isBlank(item.getName())) {
|
||||
item.setName(item.getName().trim());
|
||||
String link = urlByName.get(item.getName());
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
if (ImportHelper.isBlank(item.getCompanyName()) && !ImportHelper.isBlank(fixedCompanyName)) {
|
||||
item.setCompanyName(fixedCompanyName);
|
||||
}
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
if (ImportHelper.isBlank(item.getName())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:客户不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += persistImportChunk(chunkItems, chunkRowNumbers, mpBatchSize, errorMessages);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += persistImportChunk(chunkItems, chunkRowNumbers, mpBatchSize, errorMessages);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.CUSTOMER, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载客户导入模板
|
||||
*/
|
||||
@Operation(summary = "下载客户导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditCustomerImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditCustomerImportParam example = new CreditCustomerImportParam();
|
||||
example.setName("示例客户");
|
||||
example.setStatusTxt("合作中");
|
||||
example.setPrice("88.8");
|
||||
example.setPublicDate("2024-01-01");
|
||||
example.setDataSource("公开渠道");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("客户导入模板", "客户", CreditCustomerImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_customer_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditCustomerImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getName())
|
||||
&& ImportHelper.isBlank(param.getStatusTxt())
|
||||
&& ImportHelper.isBlank(param.getPrice());
|
||||
}
|
||||
|
||||
private CreditCustomer convertImportParamToEntity(CreditCustomerImportParam param) {
|
||||
CreditCustomer entity = new CreditCustomer();
|
||||
|
||||
entity.setName(normalizeString(param.getName()));
|
||||
entity.setStatusTxt(normalizeString(param.getStatusTxt()));
|
||||
entity.setPrice(normalizeString(param.getPrice()));
|
||||
entity.setPublicDate(normalizeString(param.getPublicDate()));
|
||||
entity.setDataSource(normalizeString(param.getDataSource()));
|
||||
entity.setComments(normalizeString(param.getComments()));
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
private String normalizeString(String value) {
|
||||
if (ImportHelper.isBlank(value)) {
|
||||
return null;
|
||||
}
|
||||
return value.trim();
|
||||
}
|
||||
|
||||
private int persistImportChunk(List<CreditCustomer> items,
|
||||
List<Integer> excelRowNumbers,
|
||||
int mpBatchSize,
|
||||
List<String> errorMessages) {
|
||||
return batchImportSupport.persistChunkWithFallback(
|
||||
items,
|
||||
excelRowNumbers,
|
||||
() -> {
|
||||
boolean ok = creditCustomerService.saveBatch(items, mpBatchSize);
|
||||
if (!ok) {
|
||||
throw new RuntimeException("批量保存失败");
|
||||
}
|
||||
return items.size();
|
||||
},
|
||||
(rowItem, rowNumber) -> {
|
||||
try {
|
||||
boolean saved = creditCustomerService.save(rowItem);
|
||||
if (saved) {
|
||||
return true;
|
||||
}
|
||||
if (rowNumber != null && rowNumber > 0) {
|
||||
errorMessages.add("第" + rowNumber + "行:保存失败");
|
||||
} else {
|
||||
errorMessages.add("保存失败");
|
||||
}
|
||||
return false;
|
||||
} catch (DataIntegrityViolationException e) {
|
||||
if (isDuplicateKey(e)) {
|
||||
String name = rowItem != null ? rowItem.getName() : null;
|
||||
String label = ImportHelper.isBlank(name) ? "数据" : ("客户【" + name.trim() + "】");
|
||||
if (rowNumber != null && rowNumber > 0) {
|
||||
errorMessages.add("第" + rowNumber + "行:" + label + "重复(唯一索引冲突)");
|
||||
} else {
|
||||
errorMessages.add(label + "重复(唯一索引冲突)");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
},
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
private static boolean isDuplicateKey(DataIntegrityViolationException e) {
|
||||
// Prefer structured detection (SQLState / vendor error code), fall back to message contains.
|
||||
for (Throwable t = e; t != null; t = t.getCause()) {
|
||||
if (t instanceof SQLException) {
|
||||
SQLException se = (SQLException) t;
|
||||
// MySQL: 1062 Duplicate entry; PostgreSQL/H2: SQLState 23505 unique_violation
|
||||
if (se.getErrorCode() == 1062) {
|
||||
return true;
|
||||
}
|
||||
if ("23505".equals(se.getSQLState())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Throwable mostSpecificCause = e.getMostSpecificCause();
|
||||
String message = mostSpecificCause != null ? mostSpecificCause.getMessage() : e.getMessage();
|
||||
if (message == null) {
|
||||
return false;
|
||||
}
|
||||
String lower = message.toLowerCase();
|
||||
return lower.contains("duplicate") && lower.contains("key");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,516 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditDeliveryNotice;
|
||||
import com.gxwebsoft.credit.param.CreditDeliveryNoticeImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditDeliveryNoticeParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditDeliveryNoticeService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 送达公告司法大数据控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:49:52
|
||||
*/
|
||||
@Tag(name = "送达公告司法大数据管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-delivery-notice")
|
||||
public class CreditDeliveryNoticeController extends BaseController {
|
||||
@Resource
|
||||
private CreditDeliveryNoticeService creditDeliveryNoticeService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询送达公告司法大数据")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditDeliveryNotice>> page(CreditDeliveryNoticeParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditDeliveryNoticeService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部送达公告司法大数据")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditDeliveryNotice>> list(CreditDeliveryNoticeParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditDeliveryNoticeService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询送达公告司法大数据")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditDeliveryNotice> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditDeliveryNoticeService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditDeliveryNotice:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加送达公告司法大数据")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditDeliveryNotice creditDeliveryNotice) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditDeliveryNotice.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditDeliveryNoticeService.save(creditDeliveryNotice)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditDeliveryNotice:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改送达公告司法大数据")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditDeliveryNotice creditDeliveryNotice) {
|
||||
if (creditDeliveryNoticeService.updateById(creditDeliveryNotice)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditDeliveryNotice:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除送达公告司法大数据")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (batchImportSupport.hardRemoveById(CreditDeliveryNotice.class, id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditDeliveryNotice:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加送达公告司法大数据")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditDeliveryNotice> list) {
|
||||
if (creditDeliveryNoticeService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditDeliveryNotice:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改送达公告司法大数据")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditDeliveryNotice> batchParam) {
|
||||
if (batchParam.update(creditDeliveryNoticeService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditDeliveryNotice:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除送达公告司法大数据")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (batchImportSupport.hardRemoveByIds(CreditDeliveryNotice.class, ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditDeliveryNotice:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
// Party columns may contain multiple roles/names; match if any company name is contained in the text.
|
||||
// Priority: 原告/上诉人 > 被告/被上诉人 > 其他当事人/第三人
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyNameContainedInText(
|
||||
creditDeliveryNoticeService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditDeliveryNotice::getId,
|
||||
CreditDeliveryNotice::setId,
|
||||
CreditDeliveryNotice::getCompanyId,
|
||||
CreditDeliveryNotice::setCompanyId,
|
||||
CreditDeliveryNotice::getHasData,
|
||||
CreditDeliveryNotice::setHasData,
|
||||
CreditDeliveryNotice::getTenantId,
|
||||
CreditDeliveryNotice::new,
|
||||
CreditDeliveryNotice::getPlaintiffAppellant,
|
||||
CreditDeliveryNotice::getAppellee,
|
||||
CreditDeliveryNotice::getOtherPartiesThirdParty
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入送达公告司法大数据
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditDeliveryNotice:save')")
|
||||
@Operation(summary = "批量导入送达公告司法大数据")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "送达公告", 0);
|
||||
ExcelImportSupport.ImportResult<CreditDeliveryNoticeImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditDeliveryNoticeImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditDeliveryNoticeImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
// URL 通常以超链接形式存在于“案号”列里
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readHyperlinksByHeaderKey(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditDeliveryNotice> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditDeliveryNoticeImportParam param = list.get(i);
|
||||
try {
|
||||
CreditDeliveryNotice item = convertImportParamToEntity(param);
|
||||
if (!ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
String link = urlByCaseNumber.get(item.getCaseNumber().trim());
|
||||
if (link != null && !link.isEmpty()) {
|
||||
item.setUrl(link);
|
||||
}
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditDeliveryNoticeService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditDeliveryNotice::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditDeliveryNoticeService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditDeliveryNotice::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.DELIVERY_NOTICE, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入历史送达公告(仅解析“历史送达公告”选项卡)
|
||||
* 规则:使用数据库唯一索引约束,重复数据不导入。
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditDeliveryNotice:save')")
|
||||
@Operation(summary = "批量导入历史送达公告司法大数据")
|
||||
@PostMapping("/import/history")
|
||||
public ApiResult<List<String>> importHistoryBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "历史送达公告");
|
||||
if (sheetIndex < 0) {
|
||||
return fail("未读取到数据,请确认文件中存在“历史送达公告”选项卡且表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
ExcelImportSupport.ImportResult<CreditDeliveryNoticeImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditDeliveryNoticeImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditDeliveryNoticeImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditDeliveryNotice> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditDeliveryNoticeImportParam param = list.get(i);
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
try {
|
||||
CreditDeliveryNotice item = convertImportParamToEntity(param);
|
||||
if (item.getCaseNumber() != null) {
|
||||
item.setCaseNumber(item.getCaseNumber().trim());
|
||||
}
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
String link = urlByCaseNumber.get(item.getCaseNumber());
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
// 历史导入的数据统一标记为“失效”
|
||||
item.setDataStatus("失效");
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditDeliveryNoticeService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditDeliveryNotice::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditDeliveryNoticeService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditDeliveryNotice::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.DELIVERY_NOTICE, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
}
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载送达公告导入模板
|
||||
*/
|
||||
@Operation(summary = "下载送达公告导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditDeliveryNoticeImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditDeliveryNoticeImportParam example = new CreditDeliveryNoticeImportParam();
|
||||
example.setDataType("送达公告");
|
||||
example.setPlaintiffAppellant("原告示例");
|
||||
example.setAppellee("被告示例");
|
||||
example.setOtherPartiesThirdParty2("第三人示例");
|
||||
example.setInvolvedAmount("100000");
|
||||
example.setDataStatus("正常");
|
||||
example.setOccurrenceTime("2024-01-01");
|
||||
example.setCaseNumber("(2024)示例案号");
|
||||
example.setCauseOfAction("案由示例");
|
||||
example.setCourtName("示例法院");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("送达公告导入模板", "送达公告", CreditDeliveryNoticeImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_delivery_notice_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditDeliveryNoticeImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getCaseNumber())
|
||||
&& ImportHelper.isBlank(param.getCauseOfAction())
|
||||
&& ImportHelper.isBlank(param.getOtherPartiesThirdParty())
|
||||
&& ImportHelper.isBlank(param.getOtherPartiesThirdParty2())
|
||||
&& ImportHelper.isBlank(param.getPlaintiffAppellant())
|
||||
&& ImportHelper.isBlank(param.getAppellee());
|
||||
}
|
||||
|
||||
private CreditDeliveryNotice convertImportParamToEntity(CreditDeliveryNoticeImportParam param) {
|
||||
CreditDeliveryNotice entity = new CreditDeliveryNotice();
|
||||
|
||||
String occurrenceTime = !ImportHelper.isBlank(param.getOccurrenceTime2())
|
||||
? param.getOccurrenceTime2()
|
||||
: param.getOccurrenceTime();
|
||||
String otherPartiesThirdParty = !ImportHelper.isBlank(param.getOtherPartiesThirdParty2())
|
||||
? param.getOtherPartiesThirdParty2()
|
||||
: param.getOtherPartiesThirdParty();
|
||||
String courtName = !ImportHelper.isBlank(param.getCourtName2())
|
||||
? param.getCourtName2()
|
||||
: param.getCourtName();
|
||||
String involvedAmount = !ImportHelper.isBlank(param.getInvolvedAmount2())
|
||||
? param.getInvolvedAmount2()
|
||||
: param.getInvolvedAmount();
|
||||
|
||||
entity.setDataType(param.getDataType());
|
||||
entity.setPlaintiffAppellant(param.getPlaintiffAppellant());
|
||||
entity.setAppellee(param.getAppellee());
|
||||
entity.setInvolvedAmount(involvedAmount);
|
||||
entity.setDataStatus(param.getDataStatus());
|
||||
|
||||
entity.setOtherPartiesThirdParty(otherPartiesThirdParty);
|
||||
entity.setOccurrenceTime(occurrenceTime);
|
||||
entity.setCaseNumber(param.getCaseNumber());
|
||||
entity.setCauseOfAction(param.getCauseOfAction());
|
||||
entity.setCourtName(courtName);
|
||||
entity.setComments(param.getComments());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,384 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditCompany;
|
||||
import com.gxwebsoft.credit.entity.CreditExternal;
|
||||
import com.gxwebsoft.credit.param.CreditExternalImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditExternalParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditExternalService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 对外投资控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:50:12
|
||||
*/
|
||||
@Tag(name = "对外投资管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-external")
|
||||
public class CreditExternalController extends BaseController {
|
||||
@Resource
|
||||
private CreditExternalService creditExternalService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询对外投资")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditExternal>> page(CreditExternalParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditExternalService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部对外投资")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditExternal>> list(CreditExternalParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditExternalService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询对外投资")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditExternal> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditExternalService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditExternal:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加对外投资")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditExternal creditExternal) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditExternal.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditExternalService.save(creditExternal)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditExternal:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改对外投资")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditExternal creditExternal) {
|
||||
if (creditExternalService.updateById(creditExternal)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditExternal:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除对外投资")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (batchImportSupport.hardRemoveById(CreditExternal.class, id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditExternal:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加对外投资")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditExternal> list) {
|
||||
if (creditExternalService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditExternal:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改对外投资")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditExternal> batchParam) {
|
||||
if (batchParam.update(creditExternalService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditExternal:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除对外投资")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (batchImportSupport.hardRemoveByIds(CreditExternal.class, ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditExternal:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
|
||||
creditExternalService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditExternal::getId,
|
||||
CreditExternal::setId,
|
||||
CreditExternal::getName,
|
||||
CreditExternal::getCompanyId,
|
||||
CreditExternal::setCompanyId,
|
||||
CreditExternal::setCompanyName,
|
||||
CreditExternal::getHasData,
|
||||
CreditExternal::setHasData,
|
||||
CreditExternal::getTenantId,
|
||||
CreditExternal::new
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入对外投资
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditExternal:save')")
|
||||
@Operation(summary = "批量导入对外投资")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "对外投资", 0);
|
||||
ExcelImportSupport.ImportResult<CreditExternalImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditExternalImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditExternalImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByName = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "被投资企业名称");
|
||||
String fixedCompanyName = null;
|
||||
if (companyId != null && companyId > 0) {
|
||||
CreditCompany fixedCompany = creditCompanyService.getById(companyId);
|
||||
fixedCompanyName = fixedCompany != null ? fixedCompany.getName() : null;
|
||||
}
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditExternal> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditExternalImportParam param = list.get(i);
|
||||
try {
|
||||
CreditExternal item = convertImportParamToEntity(param);
|
||||
if (!ImportHelper.isBlank(item.getName())) {
|
||||
String link = urlByName.get(item.getName().trim());
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
if (ImportHelper.isBlank(item.getCompanyName()) && !ImportHelper.isBlank(fixedCompanyName)) {
|
||||
item.setCompanyName(fixedCompanyName);
|
||||
}
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getName())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:被投资企业名称不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditExternalService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditExternal::getName,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditExternalService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditExternal::getName,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.EXTERNAL, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载对外投资导入模板
|
||||
*/
|
||||
@Operation(summary = "下载对外投资导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditExternalImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditExternalImportParam example = new CreditExternalImportParam();
|
||||
example.setName("示例科技有限公司");
|
||||
example.setStatusTxt("存续");
|
||||
example.setLegalRepresentative("李四");
|
||||
example.setRegisteredCapital("10000");
|
||||
example.setEstablishmentDate("2018-06-01");
|
||||
example.setShareholdingRatio("20");
|
||||
example.setSubscribedInvestmentAmount("2000");
|
||||
example.setSubscribedInvestmentDate("2019-01-01");
|
||||
example.setIndirectShareholdingRatio("5");
|
||||
example.setInvestmentDate("2019-06-01");
|
||||
example.setRegion("上海");
|
||||
example.setIndustry("信息技术");
|
||||
example.setInvestmentCount(1);
|
||||
example.setRelatedProductsInstitutions("关联产品示例");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("对外投资导入模板", "对外投资", CreditExternalImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_external_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditExternalImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getName())
|
||||
&& ImportHelper.isBlank(param.getLegalRepresentative())
|
||||
&& ImportHelper.isBlank(param.getRegisteredCapital())
|
||||
&& ImportHelper.isBlank(param.getEstablishmentDate());
|
||||
}
|
||||
|
||||
private CreditExternal convertImportParamToEntity(CreditExternalImportParam param) {
|
||||
CreditExternal entity = new CreditExternal();
|
||||
|
||||
entity.setName(param.getName());
|
||||
entity.setStatusTxt(param.getStatusTxt());
|
||||
entity.setLegalRepresentative(param.getLegalRepresentative());
|
||||
entity.setRegisteredCapital(param.getRegisteredCapital());
|
||||
entity.setEstablishmentDate(param.getEstablishmentDate());
|
||||
entity.setShareholdingRatio(param.getShareholdingRatio());
|
||||
entity.setSubscribedInvestmentAmount(param.getSubscribedInvestmentAmount());
|
||||
entity.setSubscribedInvestmentDate(param.getSubscribedInvestmentDate());
|
||||
entity.setIndirectShareholdingRatio(param.getIndirectShareholdingRatio());
|
||||
entity.setInvestmentDate(param.getInvestmentDate());
|
||||
entity.setRegion(param.getRegion());
|
||||
entity.setIndustry(param.getIndustry());
|
||||
entity.setInvestmentCount(param.getInvestmentCount());
|
||||
entity.setRelatedProductsInstitutions(param.getRelatedProductsInstitutions());
|
||||
entity.setComments(param.getComments());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,517 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditFinalVersion;
|
||||
import com.gxwebsoft.credit.param.CreditFinalVersionImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditFinalVersionParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditFinalVersionService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 终本案件控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:50:19
|
||||
*/
|
||||
@Tag(name = "终本案件管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-final-version")
|
||||
public class CreditFinalVersionController extends BaseController {
|
||||
@Resource
|
||||
private CreditFinalVersionService creditFinalVersionService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询终本案件")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditFinalVersion>> page(CreditFinalVersionParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditFinalVersionService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部终本案件")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditFinalVersion>> list(CreditFinalVersionParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditFinalVersionService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询终本案件")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditFinalVersion> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditFinalVersionService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditFinalVersion:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加终本案件")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditFinalVersion creditFinalVersion) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditFinalVersion.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditFinalVersionService.save(creditFinalVersion)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditFinalVersion:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改终本案件")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditFinalVersion creditFinalVersion) {
|
||||
if (creditFinalVersionService.updateById(creditFinalVersion)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditFinalVersion:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除终本案件")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (batchImportSupport.hardRemoveById(CreditFinalVersion.class, id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditFinalVersion:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加终本案件")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditFinalVersion> list) {
|
||||
if (creditFinalVersionService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditFinalVersion:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改终本案件")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditFinalVersion> batchParam) {
|
||||
if (batchParam.update(creditFinalVersionService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditFinalVersion:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除终本案件")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (batchImportSupport.hardRemoveByIds(CreditFinalVersion.class, ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditFinalVersion:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
// Party columns may contain multiple roles/names; match if any company name is contained in the text.
|
||||
// Priority: 原告/上诉人 > 被告/被上诉人 > 其他当事人/第三人
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyNameContainedInText(
|
||||
creditFinalVersionService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditFinalVersion::getId,
|
||||
CreditFinalVersion::setId,
|
||||
CreditFinalVersion::getCompanyId,
|
||||
CreditFinalVersion::setCompanyId,
|
||||
CreditFinalVersion::getHasData,
|
||||
CreditFinalVersion::setHasData,
|
||||
CreditFinalVersion::getTenantId,
|
||||
CreditFinalVersion::new,
|
||||
CreditFinalVersion::getPlaintiffAppellant,
|
||||
CreditFinalVersion::getAppellee,
|
||||
CreditFinalVersion::getOtherPartiesThirdParty
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入终本案件
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditFinalVersion:save')")
|
||||
@Operation(summary = "批量导入终本案件")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
// 按选项卡名称读取(客户提供的文件可能不是把目标 sheet 放在第一个)
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "终本案件", 0);
|
||||
ExcelImportSupport.ImportResult<CreditFinalVersionImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditFinalVersionImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditFinalVersionImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditFinalVersion> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditFinalVersionImportParam param = list.get(i);
|
||||
try {
|
||||
CreditFinalVersion item = convertImportParamToEntity(param);
|
||||
if (!ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
String link = urlByCaseNumber.get(item.getCaseNumber().trim());
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditFinalVersionService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditFinalVersion::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditFinalVersionService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditFinalVersion::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.FINAL_VERSION, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入历史终本案件(仅解析“历史终本案件”选项卡)
|
||||
* 规则:使用数据库唯一索引约束,重复数据不导入。
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditFinalVersion:save')")
|
||||
@Operation(summary = "批量导入历史终本案件")
|
||||
@PostMapping("/import/history")
|
||||
public ApiResult<List<String>> importHistoryBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "历史终本案件");
|
||||
if (sheetIndex < 0) {
|
||||
return fail("未读取到数据,请确认文件中存在“历史终本案件”选项卡且表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
ExcelImportSupport.ImportResult<CreditFinalVersionImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditFinalVersionImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditFinalVersionImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditFinalVersion> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditFinalVersionImportParam param = list.get(i);
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
try {
|
||||
CreditFinalVersion item = convertImportParamToEntity(param);
|
||||
if (item.getCaseNumber() != null) {
|
||||
item.setCaseNumber(item.getCaseNumber().trim());
|
||||
}
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
String link = urlByCaseNumber.get(item.getCaseNumber());
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
// 历史导入的数据统一标记为“失效”
|
||||
item.setDataStatus("失效");
|
||||
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditFinalVersionService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditFinalVersion::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditFinalVersionService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditFinalVersion::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.FINAL_VERSION, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
}
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载终本案件导入模板
|
||||
*/
|
||||
@Operation(summary = "下载终本案件导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditFinalVersionImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditFinalVersionImportParam example = new CreditFinalVersionImportParam();
|
||||
example.setCaseNumber("(2024)示例案号");
|
||||
example.setPlaintiffAppellant("原告示例");
|
||||
example.setAppellee("被告示例");
|
||||
example.setOtherPartiesThirdParty("第三人示例");
|
||||
example.setInvolvedAmount("20,293.91");
|
||||
example.setDataStatus("正常");
|
||||
example.setCourtName("示例法院");
|
||||
example.setOccurrenceTime("2024-01-01");
|
||||
example.setFinalDate("2024-01-01");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("终本案件导入模板", "终本案件", CreditFinalVersionImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_final_version_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditFinalVersionImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getCaseNumber());
|
||||
}
|
||||
|
||||
private CreditFinalVersion convertImportParamToEntity(CreditFinalVersionImportParam param) {
|
||||
CreditFinalVersion entity = new CreditFinalVersion();
|
||||
|
||||
String plaintiffAppellant = !ImportHelper.isBlank(param.getPlaintiffAppellant2())
|
||||
? param.getPlaintiffAppellant2()
|
||||
: param.getPlaintiffAppellant();
|
||||
String appellee = !ImportHelper.isBlank(param.getAppellee2())
|
||||
? param.getAppellee2()
|
||||
: param.getAppellee();
|
||||
String otherPartiesThirdParty = !ImportHelper.isBlank(param.getOtherPartiesThirdParty())
|
||||
? param.getOtherPartiesThirdParty()
|
||||
: param.getOtherPartiesThirdParty2();
|
||||
String involvedAmount = !ImportHelper.isBlank(param.getInvolvedAmount2())
|
||||
? param.getInvolvedAmount2()
|
||||
: param.getInvolvedAmount();
|
||||
String courtName = !ImportHelper.isBlank(param.getCourtName2())
|
||||
? param.getCourtName2()
|
||||
: param.getCourtName();
|
||||
String occurrenceTime = !ImportHelper.isBlank(param.getOccurrenceTime2())
|
||||
? param.getOccurrenceTime2()
|
||||
: param.getOccurrenceTime();
|
||||
|
||||
entity.setCaseNumber(param.getCaseNumber());
|
||||
entity.setPlaintiffAppellant(plaintiffAppellant);
|
||||
entity.setAppellee(appellee);
|
||||
entity.setUnfulfilledAmount(param.getUnfulfilledAmount());
|
||||
entity.setInvolvedAmount(involvedAmount);
|
||||
entity.setOtherPartiesThirdParty(otherPartiesThirdParty);
|
||||
entity.setDataStatus(param.getDataStatus());
|
||||
entity.setCourtName(courtName);
|
||||
entity.setOccurrenceTime(occurrenceTime);
|
||||
entity.setFinalDate(param.getFinalDate());
|
||||
entity.setComments(param.getComments());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,686 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditGqdj;
|
||||
import com.gxwebsoft.credit.param.CreditGqdjImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditGqdjParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditGqdjService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 股权冻结控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:50:37
|
||||
*/
|
||||
@Tag(name = "股权冻结管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-gqdj")
|
||||
public class CreditGqdjController extends BaseController {
|
||||
@Resource
|
||||
private CreditGqdjService creditGqdjService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询股权冻结")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditGqdj>> page(CreditGqdjParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditGqdjService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部股权冻结")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditGqdj>> list(CreditGqdjParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditGqdjService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询股权冻结")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditGqdj> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditGqdjService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditGqdj:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加股权冻结")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditGqdj creditGqdj) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditGqdj.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditGqdjService.save(creditGqdj)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditGqdj:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改股权冻结")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditGqdj creditGqdj) {
|
||||
if (creditGqdjService.updateById(creditGqdj)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditGqdj:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除股权冻结")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (batchImportSupport.hardRemoveById(CreditGqdj.class, id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditGqdj:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加股权冻结")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditGqdj> list) {
|
||||
if (creditGqdjService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditGqdj:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改股权冻结")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditGqdj> batchParam) {
|
||||
if (batchParam.update(creditGqdjService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditGqdj:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除股权冻结")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (batchImportSupport.hardRemoveByIds(CreditGqdj.class, ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据当事人/企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId 为空/0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditGqdj:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
// Match companyId by any party/company-name column (e.g. plaintiff/appellant, defendant/appellee).
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyNames(
|
||||
creditGqdjService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditGqdj::getId,
|
||||
CreditGqdj::setId,
|
||||
CreditGqdj::getCompanyId,
|
||||
CreditGqdj::setCompanyId,
|
||||
CreditGqdj::getHasData,
|
||||
CreditGqdj::setHasData,
|
||||
CreditGqdj::getTenantId,
|
||||
CreditGqdj::new,
|
||||
CreditGqdj::getPlaintiffAppellant,
|
||||
CreditGqdj::getAppellee
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入股权冻结司法大数据
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditGqdj:save')")
|
||||
@Operation(summary = "批量导入股权冻结司法大数据")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "股权冻结", 0);
|
||||
// Prefer the "best" header configuration; many upstream files have extra title rows or multi-row headers.
|
||||
ExcelImportSupport.ImportResult<CreditGqdjImportParam> importResult = ExcelImportSupport.readBest(
|
||||
file,
|
||||
CreditGqdjImportParam.class,
|
||||
this::isEmptyImportRow,
|
||||
// Score rows that look like real data (at least has a case number in either column).
|
||||
p -> p != null
|
||||
&& (!ImportHelper.isBlank(p.getCaseNumber())
|
||||
|| !ImportHelper.isBlank(p.getCaseNumber2())
|
||||
),
|
||||
sheetIndex
|
||||
);
|
||||
List<CreditGqdjImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
// Fallback: try other sheets if the named/default sheet doesn't match.
|
||||
importResult = ExcelImportSupport.readAnySheetBest(
|
||||
file,
|
||||
CreditGqdjImportParam.class,
|
||||
this::isEmptyImportRow,
|
||||
p -> p != null
|
||||
&& (!ImportHelper.isBlank(p.getCaseNumber())
|
||||
|| !ImportHelper.isBlank(p.getCaseNumber2()))
|
||||
);
|
||||
list = importResult.getData();
|
||||
usedTitleRows = importResult.getTitleRows();
|
||||
usedHeadRows = importResult.getHeadRows();
|
||||
usedSheetIndex = importResult.getSheetIndex();
|
||||
}
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
// easypoi 默认不会读取单元格超链接地址;url 通常挂在“案号/执行通知文书号”列的超链接中,需要额外读取回填。
|
||||
String caseNumberHeader = "执行通知文书号";
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readHyperlinksByHeaderKey(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, caseNumberHeader);
|
||||
// Some upstream sources use "案号" as the case number header.
|
||||
Map<String, String> urlByCaseNumberFromAh = ExcelImportSupport.readHyperlinksByHeaderKey(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
urlByCaseNumberFromAh.forEach(urlByCaseNumber::putIfAbsent);
|
||||
// Some upstream sources use "暗号" as the case number header.
|
||||
Map<String, String> urlByCaseNumberFromAh2 = ExcelImportSupport.readHyperlinksByHeaderKey(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "暗号");
|
||||
urlByCaseNumberFromAh2.forEach(urlByCaseNumber::putIfAbsent);
|
||||
// 有些源文件会单独提供“url/网址/链接”等列(可能是纯文本也可能是超链接)
|
||||
Map<String, String> urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, caseNumberHeader, "url");
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, caseNumberHeader, "URL");
|
||||
}
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, caseNumberHeader, "网址");
|
||||
}
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, caseNumberHeader, "链接");
|
||||
}
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
// Try again with "案号" as the key column name.
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号", "url");
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号", "URL");
|
||||
}
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号", "网址");
|
||||
}
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号", "链接");
|
||||
}
|
||||
}
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
// Try again with "暗号" as the key column name.
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "暗号", "url");
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "暗号", "URL");
|
||||
}
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "暗号", "网址");
|
||||
}
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "暗号", "链接");
|
||||
}
|
||||
}
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditGqdj> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditGqdjImportParam param = list.get(i);
|
||||
try {
|
||||
CreditGqdj item = convertImportParamToEntity(param);
|
||||
if (!ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
String key = item.getCaseNumber().trim();
|
||||
String link = urlByCaseNumber.get(key);
|
||||
if (ImportHelper.isBlank(link)) {
|
||||
link = urlByCaseNumberFromUrlCol.get(key);
|
||||
}
|
||||
if (link != null && !link.isEmpty()) {
|
||||
item.setUrl(link);
|
||||
}
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditGqdjService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditGqdj::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditGqdjService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditGqdj::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.GQDJ, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入历史股权冻结(仅解析“历史股权冻结”选项卡)
|
||||
* 规则:使用数据库唯一索引约束,重复数据不导入。
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditGqdj:save')")
|
||||
@Operation(summary = "批量导入历史股权冻结司法大数据")
|
||||
@PostMapping("/import/history")
|
||||
public ApiResult<List<String>> importHistoryBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "历史股权冻结");
|
||||
if (sheetIndex < 0) {
|
||||
return fail("未读取到数据,请确认文件中存在“历史股权冻结”选项卡且表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
ExcelImportSupport.ImportResult<CreditGqdjImportParam> importResult = ExcelImportSupport.readBest(
|
||||
file,
|
||||
CreditGqdjImportParam.class,
|
||||
this::isEmptyImportRow,
|
||||
p -> p != null
|
||||
&& (!ImportHelper.isBlank(p.getCaseNumber())
|
||||
|| !ImportHelper.isBlank(p.getCaseNumber2())),
|
||||
sheetIndex
|
||||
);
|
||||
List<CreditGqdjImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
String caseNumberHeader = "执行通知文书号";
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readHyperlinksByHeaderKey(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, caseNumberHeader);
|
||||
Map<String, String> urlByCaseNumberFromAh = ExcelImportSupport.readHyperlinksByHeaderKey(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
urlByCaseNumberFromAh.forEach(urlByCaseNumber::putIfAbsent);
|
||||
Map<String, String> urlByCaseNumberFromAh2 = ExcelImportSupport.readHyperlinksByHeaderKey(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "暗号");
|
||||
urlByCaseNumberFromAh2.forEach(urlByCaseNumber::putIfAbsent);
|
||||
Map<String, String> urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, caseNumberHeader, "url");
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, caseNumberHeader, "URL");
|
||||
}
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, caseNumberHeader, "网址");
|
||||
}
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, caseNumberHeader, "链接");
|
||||
}
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号", "url");
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号", "URL");
|
||||
}
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号", "网址");
|
||||
}
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号", "链接");
|
||||
}
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "暗号", "url");
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "暗号", "URL");
|
||||
}
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "暗号", "网址");
|
||||
}
|
||||
if (urlByCaseNumberFromUrlCol.isEmpty()) {
|
||||
urlByCaseNumberFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(
|
||||
file, usedSheetIndex, usedTitleRows, usedHeadRows, "暗号", "链接");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditGqdj> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditGqdjImportParam param = list.get(i);
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
try {
|
||||
CreditGqdj item = convertImportParamToEntity(param);
|
||||
if (item.getCaseNumber() != null) {
|
||||
item.setCaseNumber(item.getCaseNumber().trim());
|
||||
}
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
String key = item.getCaseNumber();
|
||||
String link = urlByCaseNumber.get(key);
|
||||
if (ImportHelper.isBlank(link)) {
|
||||
link = urlByCaseNumberFromUrlCol.get(key);
|
||||
}
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
// 历史导入的数据统一标记为“失效”
|
||||
item.setDataType("失效");
|
||||
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditGqdjService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditGqdj::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditGqdjService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditGqdj::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.GQDJ, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
}
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载股权冻结导入模板
|
||||
*/
|
||||
@Operation(summary = "下载股权冻结导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditGqdjImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditGqdjImportParam example = new CreditGqdjImportParam();
|
||||
example.setDataType("股权冻结");
|
||||
example.setPlaintiffAppellant("原告示例");
|
||||
example.setAppellee("被告示例");
|
||||
example.setCaseNumber("(2024)示例案号");
|
||||
example.setInvolvedAmount("100000");
|
||||
example.setCourtName("示例法院");
|
||||
example.setDataStatus("已公开");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("股权冻结导入模板", "股权冻结", CreditGqdjImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_gqdj_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditGqdjImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
// Don't over-filter here: if some columns are mapped but case number header differs,
|
||||
// we still want to read the row and report "案号不能为空" instead of "未读取到数据".
|
||||
return ImportHelper.isBlank(param.getCaseNumber())
|
||||
&& ImportHelper.isBlank(param.getCaseNumber2())
|
||||
&& ImportHelper.isBlank(param.getAppellee())
|
||||
&& ImportHelper.isBlank(param.getAppellee2())
|
||||
&& ImportHelper.isBlank(param.getPlaintiffAppellant())
|
||||
&& ImportHelper.isBlank(param.getPlaintiffAppellant2())
|
||||
&& ImportHelper.isBlank(param.getInvolvedAmount())
|
||||
&& ImportHelper.isBlank(param.getCourtName())
|
||||
&& ImportHelper.isBlank(param.getDataType())
|
||||
&& ImportHelper.isBlank(param.getDataStatus())
|
||||
&& ImportHelper.isBlank(param.getDataStatus2())
|
||||
&& ImportHelper.isBlank(param.getFreezeDateStart())
|
||||
&& ImportHelper.isBlank(param.getFreezeDateEnd())
|
||||
&& ImportHelper.isBlank(param.getFreezeDateStart2())
|
||||
&& ImportHelper.isBlank(param.getFreezeDateEnd2())
|
||||
&& ImportHelper.isBlank(param.getPublicDate());
|
||||
}
|
||||
|
||||
private CreditGqdj convertImportParamToEntity(CreditGqdjImportParam param) {
|
||||
CreditGqdj entity = new CreditGqdj();
|
||||
|
||||
// Template compatibility: some sources use alternate headers for the same columns.
|
||||
String appellee = !ImportHelper.isBlank(param.getAppellee()) ? param.getAppellee() : param.getAppellee2();
|
||||
String plaintiffAppellant = !ImportHelper.isBlank(param.getPlaintiffAppellant())
|
||||
? param.getPlaintiffAppellant()
|
||||
: param.getPlaintiffAppellant2();
|
||||
|
||||
if (!ImportHelper.isBlank(param.getCaseNumber2())) {
|
||||
entity.setCaseNumber(param.getCaseNumber2());
|
||||
} else {
|
||||
entity.setCaseNumber(param.getCaseNumber());
|
||||
}
|
||||
entity.setAppellee(appellee);
|
||||
entity.setPlaintiffAppellant(plaintiffAppellant);
|
||||
entity.setInvolvedAmount(param.getInvolvedAmount());
|
||||
entity.setCourtName(param.getCourtName());
|
||||
if (!ImportHelper.isBlank(param.getDataStatus2())) {
|
||||
entity.setDataStatus(param.getDataStatus2());
|
||||
} else {
|
||||
entity.setDataStatus(param.getDataStatus());
|
||||
}
|
||||
entity.setDataType(param.getDataType());
|
||||
entity.setPublicDate(param.getPublicDate());
|
||||
if (!ImportHelper.isBlank(param.getFreezeDateStart2())) {
|
||||
entity.setFreezeDateStart(param.getFreezeDateStart2());
|
||||
} else {
|
||||
entity.setFreezeDateStart(param.getFreezeDateStart());
|
||||
}
|
||||
if (!ImportHelper.isBlank(param.getFreezeDateEnd2())) {
|
||||
entity.setFreezeDateEnd(param.getFreezeDateEnd2());
|
||||
} else {
|
||||
entity.setFreezeDateEnd(param.getFreezeDateEnd());
|
||||
}
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,376 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditCompany;
|
||||
import com.gxwebsoft.credit.entity.CreditHistoricalLegalPerson;
|
||||
import com.gxwebsoft.credit.param.CreditHistoricalLegalPersonImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditHistoricalLegalPersonParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditHistoricalLegalPersonService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 历史法定代表人控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-01-07 13:52:14
|
||||
*/
|
||||
@Tag(name = "历史法定代表人管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-historical-legal-person")
|
||||
public class CreditHistoricalLegalPersonController extends BaseController {
|
||||
@Resource
|
||||
private CreditHistoricalLegalPersonService creditHistoricalLegalPersonService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询历史法定代表人")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditHistoricalLegalPerson>> page(CreditHistoricalLegalPersonParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditHistoricalLegalPersonService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部历史法定代表人")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditHistoricalLegalPerson>> list(CreditHistoricalLegalPersonParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditHistoricalLegalPersonService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询历史法定代表人")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditHistoricalLegalPerson> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditHistoricalLegalPersonService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditHistoricalLegalPerson:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加历史法定代表人")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditHistoricalLegalPerson creditHistoricalLegalPerson) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditHistoricalLegalPerson.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditHistoricalLegalPersonService.save(creditHistoricalLegalPerson)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditHistoricalLegalPerson:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改历史法定代表人")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditHistoricalLegalPerson creditHistoricalLegalPerson) {
|
||||
if (creditHistoricalLegalPersonService.updateById(creditHistoricalLegalPerson)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditHistoricalLegalPerson:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除历史法定代表人")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (batchImportSupport.hardRemoveById(CreditHistoricalLegalPerson.class, id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditHistoricalLegalPerson:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加历史法定代表人")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditHistoricalLegalPerson> list) {
|
||||
if (creditHistoricalLegalPersonService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditHistoricalLegalPerson:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改历史法定代表人")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditHistoricalLegalPerson> batchParam) {
|
||||
if (batchParam.update(creditHistoricalLegalPersonService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditHistoricalLegalPerson:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除历史法定代表人")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (batchImportSupport.hardRemoveByIds(CreditHistoricalLegalPerson.class, ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditHistoricalLegalPerson:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
|
||||
creditHistoricalLegalPersonService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditHistoricalLegalPerson::getId,
|
||||
CreditHistoricalLegalPerson::setId,
|
||||
CreditHistoricalLegalPerson::getName,
|
||||
CreditHistoricalLegalPerson::getCompanyId,
|
||||
CreditHistoricalLegalPerson::setCompanyId,
|
||||
CreditHistoricalLegalPerson::setCompanyName,
|
||||
CreditHistoricalLegalPerson::getHasData,
|
||||
CreditHistoricalLegalPerson::setHasData,
|
||||
CreditHistoricalLegalPerson::getTenantId,
|
||||
CreditHistoricalLegalPerson::new
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入历史法定代表人
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditHistoricalLegalPerson:save')")
|
||||
@Operation(summary = "批量导入历史法定代表人")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
ExcelImportSupport.ImportResult<CreditHistoricalLegalPersonImportParam> importResult = ExcelImportSupport.readAnySheet(
|
||||
file, CreditHistoricalLegalPersonImportParam.class, this::isEmptyImportRow);
|
||||
List<CreditHistoricalLegalPersonImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByName = ExcelImportSupport.readHyperlinksByHeaderKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "名称");
|
||||
String fixedCompanyName = null;
|
||||
if (companyId != null && companyId > 0) {
|
||||
CreditCompany fixedCompany = creditCompanyService.getById(companyId);
|
||||
fixedCompanyName = fixedCompany != null ? fixedCompany.getName() : null;
|
||||
}
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditHistoricalLegalPerson> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditHistoricalLegalPersonImportParam param = list.get(i);
|
||||
try {
|
||||
CreditHistoricalLegalPerson item = convertImportParamToEntity(param);
|
||||
if (!ImportHelper.isBlank(item.getName())) {
|
||||
String link = urlByName.get(item.getName().trim());
|
||||
if (link != null && !link.isEmpty()) {
|
||||
item.setUrl(link);
|
||||
}
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
if (ImportHelper.isBlank(item.getCompanyName()) && !ImportHelper.isBlank(fixedCompanyName)) {
|
||||
item.setCompanyName(fixedCompanyName);
|
||||
}
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getName())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:名称不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditHistoricalLegalPersonService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditHistoricalLegalPerson::getName,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditHistoricalLegalPersonService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditHistoricalLegalPerson::getName,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.HISTORICAL_LEGAL_PERSON, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载历史法定代表人导入模板
|
||||
*/
|
||||
@Operation(summary = "下载历史法定代表人导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditHistoricalLegalPersonImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditHistoricalLegalPersonImportParam example = new CreditHistoricalLegalPersonImportParam();
|
||||
example.setName("张三");
|
||||
example.setRegisterDate("2020-01-01");
|
||||
example.setPublicDate("2023-06-01");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("历史法定代表人导入模板", "历史法定代表人", CreditHistoricalLegalPersonImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_historical_legal_person_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditHistoricalLegalPersonImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
if (isImportHeaderRow(param)) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getName())
|
||||
&& ImportHelper.isBlank(param.getRegisterDate())
|
||||
&& ImportHelper.isBlank(param.getPublicDate());
|
||||
}
|
||||
|
||||
private boolean isImportHeaderRow(CreditHistoricalLegalPersonImportParam param) {
|
||||
return isHeaderValue(param.getName(), "名称")
|
||||
|| isHeaderValue(param.getRegisterDate(), "任职日期")
|
||||
|| isHeaderValue(param.getPublicDate(), "卸任日期");
|
||||
}
|
||||
|
||||
private static boolean isHeaderValue(String value, String headerText) {
|
||||
if (value == null) {
|
||||
return false;
|
||||
}
|
||||
return headerText.equals(value.trim());
|
||||
}
|
||||
|
||||
private CreditHistoricalLegalPerson convertImportParamToEntity(CreditHistoricalLegalPersonImportParam param) {
|
||||
CreditHistoricalLegalPerson entity = new CreditHistoricalLegalPerson();
|
||||
|
||||
entity.setName(param.getName());
|
||||
entity.setRegisterDate(param.getRegisterDate());
|
||||
entity.setPublicDate(param.getPublicDate());
|
||||
entity.setComments(param.getComments());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,881 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditJudgmentDebtor;
|
||||
import com.gxwebsoft.credit.param.CreditJudgmentDebtorImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditJudgmentDebtorParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditJudgmentDebtorService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.ss.usermodel.WorkbookFactory;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Locale;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
/**
|
||||
* 被执行人控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:50:55
|
||||
*/
|
||||
@Tag(name = "被执行人管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-judgment-debtor")
|
||||
public class CreditJudgmentDebtorController extends BaseController {
|
||||
@Resource
|
||||
private CreditJudgmentDebtorService creditJudgmentDebtorService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询被执行人")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditJudgmentDebtor>> page(CreditJudgmentDebtorParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditJudgmentDebtorService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部被执行人")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditJudgmentDebtor>> list(CreditJudgmentDebtorParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditJudgmentDebtorService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询被执行人")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditJudgmentDebtor> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditJudgmentDebtorService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditJudgmentDebtor:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加被执行人")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditJudgmentDebtor creditJudgmentDebtor) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditJudgmentDebtor.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditJudgmentDebtorService.save(creditJudgmentDebtor)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditJudgmentDebtor:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改被执行人")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditJudgmentDebtor creditJudgmentDebtor) {
|
||||
if (creditJudgmentDebtorService.updateById(creditJudgmentDebtor)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditJudgmentDebtor:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除被执行人")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (batchImportSupport.hardRemoveById(CreditJudgmentDebtor.class, id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditJudgmentDebtor:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加被执行人")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditJudgmentDebtor> list) {
|
||||
if (creditJudgmentDebtorService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditJudgmentDebtor:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改被执行人")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditJudgmentDebtor> batchParam) {
|
||||
if (batchParam.update(creditJudgmentDebtorService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditJudgmentDebtor:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除被执行人")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (batchImportSupport.hardRemoveByIds(CreditJudgmentDebtor.class, ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditJudgmentDebtor:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit,
|
||||
@RequestParam(value = "topLevelOnly", required = false, defaultValue = "true") Boolean topLevelOnly
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
// Match only on "name" column: debtor.name contains a (top-level) CreditCompany name/matchName.
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyNameContainedInText(
|
||||
creditJudgmentDebtorService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditJudgmentDebtor::getId,
|
||||
CreditJudgmentDebtor::setId,
|
||||
CreditJudgmentDebtor::getCompanyId,
|
||||
CreditJudgmentDebtor::setCompanyId,
|
||||
CreditJudgmentDebtor::getHasData,
|
||||
CreditJudgmentDebtor::setHasData,
|
||||
CreditJudgmentDebtor::getTenantId,
|
||||
CreditJudgmentDebtor::new,
|
||||
q -> {
|
||||
if (!Boolean.TRUE.equals(topLevelOnly)) {
|
||||
return;
|
||||
}
|
||||
// "一级企业":parentId=0(部分历史数据可能为 NULL,兼容处理)
|
||||
q.and(w -> w.eq(com.gxwebsoft.credit.entity.CreditCompany::getParentId, 0)
|
||||
.or()
|
||||
.isNull(com.gxwebsoft.credit.entity.CreditCompany::getParentId));
|
||||
},
|
||||
CreditJudgmentDebtor::getName
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入被执行人
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditJudgmentDebtor:save')")
|
||||
@Operation(summary = "批量导入被执行人")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
try {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
ImportOutcome outcome;
|
||||
if (isZip(file)) {
|
||||
outcome = importFromZip(file, currentUserId, currentTenantId, companyId);
|
||||
} else {
|
||||
outcome = importFromExcel(file, safeFileLabel(file.getOriginalFilename()), currentUserId, currentTenantId, companyId, false);
|
||||
}
|
||||
|
||||
if (!outcome.anyDataRead) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.JUDGMENT_DEBTOR, outcome.touchedCompanyIds);
|
||||
|
||||
if (outcome.errorMessages.isEmpty()) {
|
||||
return success("成功导入" + outcome.successCount + "条数据", null);
|
||||
}
|
||||
return success("导入完成,成功" + outcome.successCount + "条,失败" + outcome.errorMessages.size() + "条", outcome.errorMessages);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入历史被执行人(写入被执行人表 credit_judgment_debtor,仅解析“历史被执行人”选项卡)
|
||||
* 规则:使用数据库唯一索引约束,重复数据不导入。
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditJudgmentDebtor:save')")
|
||||
@Operation(summary = "批量导入历史被执行人")
|
||||
@PostMapping("/import/history")
|
||||
public ApiResult<List<String>> importHistoryBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
try {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
ImportOutcome outcome;
|
||||
if (isZip(file)) {
|
||||
outcome = importHistoryFromZip(file, currentUserId, currentTenantId, companyId);
|
||||
} else {
|
||||
outcome = importHistoryFromExcel(file, safeFileLabel(file.getOriginalFilename()), currentUserId, currentTenantId, companyId);
|
||||
}
|
||||
|
||||
if (!outcome.anyDataRead) {
|
||||
return fail("未读取到数据,请确认文件中存在“历史被执行人”选项卡且表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.JUDGMENT_DEBTOR, outcome.touchedCompanyIds);
|
||||
|
||||
if (outcome.errorMessages.isEmpty()) {
|
||||
return success("成功导入" + outcome.successCount + "条数据", null);
|
||||
}
|
||||
return success("导入完成,成功" + outcome.successCount + "条,失败" + outcome.errorMessages.size() + "条", outcome.errorMessages);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载被执行人导入模板
|
||||
*/
|
||||
@Operation(summary = "下载被执行人导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditJudgmentDebtorImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditJudgmentDebtorImportParam example = new CreditJudgmentDebtorImportParam();
|
||||
example.setCaseNumber("(2024)示例案号");
|
||||
example.setName("某某公司");
|
||||
example.setCode("1234567890");
|
||||
example.setOccurrenceTime("2024-01-10");
|
||||
example.setDataStatus("已公开");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("被执行人导入模板", "被执行人", CreditJudgmentDebtorImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_judgment_debtor_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditJudgmentDebtorImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
if (isImportHeaderRow(param)) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getCaseNumber());
|
||||
}
|
||||
|
||||
private boolean isImportHeaderRow(CreditJudgmentDebtorImportParam param) {
|
||||
return isHeaderValue(param.getName(), "序号")
|
||||
|| isHeaderValue(param.getName1(), "序号")
|
||||
|| isHeaderValue(param.getCaseNumber(), "案号")
|
||||
|| isHeaderValue(param.getName(), "被执行人名称")
|
||||
|| isHeaderValue(param.getName1(), "被执行人")
|
||||
|| isHeaderValue(param.getCode(), "证件号/组织机构代码")
|
||||
|| isHeaderValue(param.getOccurrenceTime(), "立案日期")
|
||||
|| isHeaderValue(param.getCourtName(), "法院")
|
||||
|| isHeaderValue(param.getCourtNameQcc(), "执行法院")
|
||||
|| isHeaderValue(param.getInvolvedAmount(), "涉案金额")
|
||||
|| isHeaderValue(param.getInvolvedAmountQcc(), "执行标的(元)")
|
||||
|| isHeaderValue(param.getDataStatus(), "数据状态");
|
||||
}
|
||||
|
||||
private static boolean isHeaderValue(String value, String headerText) {
|
||||
if (value == null) {
|
||||
return false;
|
||||
}
|
||||
return headerText.equals(value.trim());
|
||||
}
|
||||
|
||||
private static boolean hasMeaningfulPartyValue(String value) {
|
||||
if (ImportHelper.isBlank(value)) {
|
||||
return false;
|
||||
}
|
||||
return !"-".equals(value.trim());
|
||||
}
|
||||
|
||||
private CreditJudgmentDebtor convertImportParamToEntity(CreditJudgmentDebtorImportParam param) {
|
||||
CreditJudgmentDebtor entity = new CreditJudgmentDebtor();
|
||||
|
||||
entity.setCaseNumber(param.getCaseNumber());
|
||||
entity.setName1(param.getName1());
|
||||
String debtorName = ImportHelper.isBlank(param.getName()) ? param.getName1() : param.getName();
|
||||
if (debtorName != null) {
|
||||
debtorName = debtorName.trim();
|
||||
}
|
||||
entity.setPlaintiffAppellant(param.getPlaintiffAppellant());
|
||||
entity.setAppellee(param.getAppellee());
|
||||
entity.setOtherPartiesThirdParty(param.getOtherPartiesThirdParty());
|
||||
// Some upstream XLS templates store party/company name in "原告/上诉人/被告/第三人" columns.
|
||||
// When present, use them to populate the debtor "name" for compatibility.
|
||||
if (hasMeaningfulPartyValue(param.getPlaintiffAppellant())) {
|
||||
debtorName = param.getPlaintiffAppellant().trim();
|
||||
} else if (hasMeaningfulPartyValue(param.getAppellee())) {
|
||||
debtorName = param.getAppellee().trim();
|
||||
} else if (hasMeaningfulPartyValue(param.getOtherPartiesThirdParty())) {
|
||||
debtorName = param.getOtherPartiesThirdParty().trim();
|
||||
}
|
||||
entity.setName(debtorName);
|
||||
entity.setCode(param.getCode());
|
||||
String occurrenceTime = !ImportHelper.isBlank(param.getOccurrenceTime2())
|
||||
? param.getOccurrenceTime2().trim()
|
||||
: (param.getOccurrenceTime() != null ? param.getOccurrenceTime().trim() : null);
|
||||
entity.setOccurrenceTime(occurrenceTime);
|
||||
// 兼容企查查历史被执行人:执行标的(元) / 执行法院
|
||||
String amount = !ImportHelper.isBlank(param.getInvolvedAmountQcc())
|
||||
? param.getInvolvedAmountQcc()
|
||||
: param.getInvolvedAmount();
|
||||
if (amount != null) {
|
||||
amount = amount.trim();
|
||||
}
|
||||
entity.setAmount(amount);
|
||||
|
||||
String courtName = !ImportHelper.isBlank(param.getCourtName())
|
||||
? param.getCourtName()
|
||||
: param.getCourtNameQcc();
|
||||
if (courtName != null) {
|
||||
courtName = courtName.trim();
|
||||
}
|
||||
entity.setCourtName(courtName);
|
||||
entity.setDataStatus(param.getDataStatus());
|
||||
entity.setComments(param.getComments());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
private static class ImportOutcome {
|
||||
private final boolean anyDataRead;
|
||||
private final int successCount;
|
||||
private final List<String> errorMessages;
|
||||
private final Set<Integer> touchedCompanyIds;
|
||||
|
||||
private ImportOutcome(boolean anyDataRead, int successCount, List<String> errorMessages, Set<Integer> touchedCompanyIds) {
|
||||
this.anyDataRead = anyDataRead;
|
||||
this.successCount = successCount;
|
||||
this.errorMessages = errorMessages;
|
||||
this.touchedCompanyIds = touchedCompanyIds != null ? touchedCompanyIds : new HashSet<>();
|
||||
}
|
||||
}
|
||||
|
||||
private ImportOutcome importFromExcel(MultipartFile excelFile, String fileLabel, Integer currentUserId, Integer currentTenantId, Integer companyId, boolean strictDebtorSheet) throws Exception {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
ExcelImportSupport.ImportResult<CreditJudgmentDebtorImportParam> importResult = readDebtorImport(excelFile, strictDebtorSheet);
|
||||
List<CreditJudgmentDebtorImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return new ImportOutcome(false, 0, errorMessages, touchedCompanyIds);
|
||||
}
|
||||
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readHyperlinksByHeaderKey(excelFile, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
Map<String, String> urlByName = ExcelImportSupport.readHyperlinksByHeaderKey(excelFile, usedSheetIndex, usedTitleRows, usedHeadRows, "被执行人名称");
|
||||
Map<String, String> urlByName1 = ExcelImportSupport.readHyperlinksByHeaderKey(excelFile, usedSheetIndex, usedTitleRows, usedHeadRows, "被执行人");
|
||||
|
||||
String prefix = ImportHelper.isBlank(fileLabel) ? "" : "【" + fileLabel + "】";
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditJudgmentDebtor> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditJudgmentDebtorImportParam param = list.get(i);
|
||||
try {
|
||||
CreditJudgmentDebtor item = convertImportParamToEntity(param);
|
||||
String link = null;
|
||||
if (!ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
link = urlByCaseNumber.get(item.getCaseNumber().trim());
|
||||
}
|
||||
if ((link == null || link.isEmpty()) && !ImportHelper.isBlank(item.getName())) {
|
||||
link = urlByName.get(item.getName().trim());
|
||||
}
|
||||
if ((link == null || link.isEmpty()) && !ImportHelper.isBlank(item.getName1())) {
|
||||
link = urlByName1.get(item.getName1().trim());
|
||||
}
|
||||
if (link != null && !link.isEmpty()) {
|
||||
item.setUrl(link);
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add(prefix + "第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += persistImportChunk(chunkItems, chunkRowNumbers, prefix, mpBatchSize, errorMessages);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add(prefix + "第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += persistImportChunk(chunkItems, chunkRowNumbers, prefix, mpBatchSize, errorMessages);
|
||||
}
|
||||
return new ImportOutcome(true, successCount, errorMessages, touchedCompanyIds);
|
||||
}
|
||||
|
||||
private ImportOutcome importHistoryFromExcel(MultipartFile excelFile, String fileLabel, Integer currentUserId, Integer currentTenantId, Integer companyId) throws Exception {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
int historySheetIndex = ExcelImportSupport.findSheetIndex(excelFile, "历史被执行人");
|
||||
if (historySheetIndex < 0) {
|
||||
return new ImportOutcome(false, 0, errorMessages, touchedCompanyIds);
|
||||
}
|
||||
|
||||
ExcelImportSupport.ImportResult<CreditJudgmentDebtorImportParam> importResult = ExcelImportSupport.readBest(
|
||||
excelFile,
|
||||
CreditJudgmentDebtorImportParam.class,
|
||||
this::isEmptyImportRow,
|
||||
this::isScoreImportRow,
|
||||
historySheetIndex
|
||||
);
|
||||
|
||||
List<CreditJudgmentDebtorImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return new ImportOutcome(false, 0, errorMessages, touchedCompanyIds);
|
||||
}
|
||||
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readHyperlinksByHeaderKey(excelFile, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
Map<String, String> urlByName = ExcelImportSupport.readHyperlinksByHeaderKey(excelFile, usedSheetIndex, usedTitleRows, usedHeadRows, "被执行人名称");
|
||||
Map<String, String> urlByName1 = ExcelImportSupport.readHyperlinksByHeaderKey(excelFile, usedSheetIndex, usedTitleRows, usedHeadRows, "被执行人");
|
||||
|
||||
String prefix = ImportHelper.isBlank(fileLabel) ? "" : "【" + fileLabel + "】";
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditJudgmentDebtor> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditJudgmentDebtorImportParam param = list.get(i);
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
try {
|
||||
CreditJudgmentDebtor item = convertImportParamToEntity(param);
|
||||
|
||||
if (item.getCaseNumber() != null) {
|
||||
item.setCaseNumber(item.getCaseNumber().trim());
|
||||
}
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add(prefix + "第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
String link = urlByCaseNumber.get(item.getCaseNumber());
|
||||
if ((link == null || link.isEmpty()) && !ImportHelper.isBlank(item.getName())) {
|
||||
link = urlByName.get(item.getName().trim());
|
||||
}
|
||||
if ((link == null || link.isEmpty()) && !ImportHelper.isBlank(item.getName1())) {
|
||||
link = urlByName1.get(item.getName1().trim());
|
||||
}
|
||||
if (link != null && !link.isEmpty()) {
|
||||
item.setUrl(link);
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
// 历史导入的数据统一标记为“失效”
|
||||
item.setDataStatus("失效");
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += persistHistoryImportChunk(chunkItems, chunkRowNumbers, prefix, mpBatchSize, errorMessages);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
errorMessages.add(prefix + "第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += persistHistoryImportChunk(chunkItems, chunkRowNumbers, prefix, mpBatchSize, errorMessages);
|
||||
}
|
||||
|
||||
return new ImportOutcome(true, successCount, errorMessages, touchedCompanyIds);
|
||||
}
|
||||
|
||||
private int persistHistoryImportChunk(List<CreditJudgmentDebtor> items,
|
||||
List<Integer> excelRowNumbers,
|
||||
String prefix,
|
||||
int mpBatchSize,
|
||||
List<String> errorMessages) {
|
||||
return batchImportSupport.persistInsertOnlyChunk(
|
||||
creditJudgmentDebtorService,
|
||||
items,
|
||||
excelRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditJudgmentDebtor::getCaseNumber,
|
||||
prefix,
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
private int persistImportChunk(List<CreditJudgmentDebtor> items,
|
||||
List<Integer> excelRowNumbers,
|
||||
String prefix,
|
||||
int mpBatchSize,
|
||||
List<String> errorMessages) {
|
||||
return batchImportSupport.persistInsertOnlyChunk(
|
||||
creditJudgmentDebtorService,
|
||||
items,
|
||||
excelRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditJudgmentDebtor::getCaseNumber,
|
||||
prefix,
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
private ImportOutcome importFromZip(MultipartFile zipFile, Integer currentUserId, Integer currentTenantId, Integer companyId) throws Exception {
|
||||
try {
|
||||
return importFromZip(zipFile, currentUserId, currentTenantId, companyId, StandardCharsets.UTF_8);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return importFromZip(zipFile, currentUserId, currentTenantId, companyId, Charset.forName("GBK"));
|
||||
}
|
||||
}
|
||||
|
||||
private ImportOutcome importFromZip(MultipartFile zipFile, Integer currentUserId, Integer currentTenantId, Integer companyId, Charset charset) throws Exception {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
boolean anyDataRead = false;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try (InputStream is = zipFile.getInputStream(); ZipInputStream zis = new ZipInputStream(is, charset)) {
|
||||
ZipEntry entry;
|
||||
while ((entry = zis.getNextEntry()) != null) {
|
||||
if (entry.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
String entryName = entry.getName();
|
||||
if (!isExcelFileName(entryName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
byte[] bytes = readAllBytes(zis);
|
||||
String entryFileName = safeFileLabel(entryName);
|
||||
MultipartFile excelFile = new InMemoryMultipartFile(entryFileName, bytes);
|
||||
|
||||
try {
|
||||
ImportOutcome outcome = importFromExcel(excelFile, entryFileName, currentUserId, currentTenantId, companyId, true);
|
||||
if (outcome.anyDataRead) {
|
||||
anyDataRead = true;
|
||||
successCount += outcome.successCount;
|
||||
errorMessages.addAll(outcome.errorMessages);
|
||||
touchedCompanyIds.addAll(outcome.touchedCompanyIds);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
errorMessages.add("【" + entryFileName + "】解析失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
return new ImportOutcome(anyDataRead, successCount, errorMessages, touchedCompanyIds);
|
||||
}
|
||||
|
||||
private ImportOutcome importHistoryFromZip(MultipartFile zipFile, Integer currentUserId, Integer currentTenantId, Integer companyId) throws Exception {
|
||||
try {
|
||||
return importHistoryFromZip(zipFile, currentUserId, currentTenantId, companyId, StandardCharsets.UTF_8);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return importHistoryFromZip(zipFile, currentUserId, currentTenantId, companyId, Charset.forName("GBK"));
|
||||
}
|
||||
}
|
||||
|
||||
private ImportOutcome importHistoryFromZip(MultipartFile zipFile, Integer currentUserId, Integer currentTenantId, Integer companyId, Charset charset) throws Exception {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
boolean anyDataRead = false;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try (InputStream is = zipFile.getInputStream(); ZipInputStream zis = new ZipInputStream(is, charset)) {
|
||||
ZipEntry entry;
|
||||
while ((entry = zis.getNextEntry()) != null) {
|
||||
if (entry.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
String entryName = entry.getName();
|
||||
if (!isExcelFileName(entryName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
byte[] bytes = readAllBytes(zis);
|
||||
String entryFileName = safeFileLabel(entryName);
|
||||
MultipartFile excelFile = new InMemoryMultipartFile(entryFileName, bytes);
|
||||
|
||||
try {
|
||||
ImportOutcome outcome = importHistoryFromExcel(excelFile, entryFileName, currentUserId, currentTenantId, companyId);
|
||||
if (outcome.anyDataRead) {
|
||||
anyDataRead = true;
|
||||
successCount += outcome.successCount;
|
||||
errorMessages.addAll(outcome.errorMessages);
|
||||
touchedCompanyIds.addAll(outcome.touchedCompanyIds);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
errorMessages.add("【" + entryFileName + "】解析失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
return new ImportOutcome(anyDataRead, successCount, errorMessages, touchedCompanyIds);
|
||||
}
|
||||
|
||||
private static boolean isZip(MultipartFile file) {
|
||||
String filename = file != null ? file.getOriginalFilename() : null;
|
||||
if (filename == null) {
|
||||
return false;
|
||||
}
|
||||
return filename.toLowerCase(Locale.ROOT).endsWith(".zip");
|
||||
}
|
||||
|
||||
private ExcelImportSupport.ImportResult<CreditJudgmentDebtorImportParam> readDebtorImport(MultipartFile excelFile, boolean strictDebtorSheet) throws Exception {
|
||||
List<Integer> debtorSheetIndices = findDebtorSheetIndices(excelFile);
|
||||
for (Integer sheetIndex : debtorSheetIndices) {
|
||||
ExcelImportSupport.ImportResult<CreditJudgmentDebtorImportParam> sheetResult = ExcelImportSupport.readBest(
|
||||
excelFile,
|
||||
CreditJudgmentDebtorImportParam.class,
|
||||
this::isEmptyImportRow,
|
||||
this::isScoreImportRow,
|
||||
sheetIndex
|
||||
);
|
||||
if (!CollectionUtils.isEmpty(sheetResult.getData())) {
|
||||
return sheetResult;
|
||||
}
|
||||
}
|
||||
if (strictDebtorSheet) {
|
||||
return new ExcelImportSupport.ImportResult<>(new ArrayList<>(), 0, 0);
|
||||
}
|
||||
return ExcelImportSupport.readAnySheetBest(excelFile, CreditJudgmentDebtorImportParam.class, this::isEmptyImportRow, this::isScoreImportRow);
|
||||
}
|
||||
|
||||
private boolean isScoreImportRow(CreditJudgmentDebtorImportParam param) {
|
||||
if (param == null) {
|
||||
return false;
|
||||
}
|
||||
if (isImportHeaderRow(param)) {
|
||||
return false;
|
||||
}
|
||||
return !ImportHelper.isBlank(param.getCaseNumber());
|
||||
}
|
||||
|
||||
private List<Integer> findDebtorSheetIndices(MultipartFile excelFile) throws Exception {
|
||||
// Prefer an explicitly-named "被执行人" sheet when present.
|
||||
List<Integer> preferred = new ArrayList<>();
|
||||
List<Integer> indices = new ArrayList<>();
|
||||
try (InputStream is = excelFile.getInputStream(); Workbook workbook = WorkbookFactory.create(is)) {
|
||||
int sheetCount = workbook.getNumberOfSheets();
|
||||
for (int i = 0; i < sheetCount; i++) {
|
||||
String sheetName = workbook.getSheetName(i);
|
||||
if (!isDebtorSheetName(sheetName)) {
|
||||
continue;
|
||||
}
|
||||
String normalized = normalizeSheetName(sheetName);
|
||||
if ("被执行人".equals(normalized)) {
|
||||
preferred.add(i);
|
||||
} else {
|
||||
indices.add(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
preferred.addAll(indices);
|
||||
return preferred;
|
||||
}
|
||||
|
||||
private static boolean isDebtorSheetName(String sheetName) {
|
||||
if (sheetName == null) {
|
||||
return false;
|
||||
}
|
||||
String normalized = normalizeSheetName(sheetName);
|
||||
return normalized.contains("被执行人") && !normalized.contains("失信") && !normalized.contains("历史");
|
||||
}
|
||||
|
||||
private static String normalizeSheetName(String sheetName) {
|
||||
if (sheetName == null) {
|
||||
return "";
|
||||
}
|
||||
return sheetName.replace(" ", "").replace(" ", "").trim();
|
||||
}
|
||||
|
||||
private static boolean isExcelFileName(String name) {
|
||||
if (name == null) {
|
||||
return false;
|
||||
}
|
||||
String lower = name.toLowerCase(Locale.ROOT);
|
||||
return lower.endsWith(".xlsx") || lower.endsWith(".xls") || lower.endsWith(".xlsm");
|
||||
}
|
||||
|
||||
private static String safeFileLabel(String name) {
|
||||
if (ImportHelper.isBlank(name)) {
|
||||
return "";
|
||||
}
|
||||
int lastSlash = name.lastIndexOf('/');
|
||||
if (lastSlash >= 0 && lastSlash + 1 < name.length()) {
|
||||
return name.substring(lastSlash + 1);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
private static byte[] readAllBytes(InputStream inputStream) throws IOException {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
byte[] buffer = new byte[8192];
|
||||
int read;
|
||||
while ((read = inputStream.read(buffer)) != -1) {
|
||||
out.write(buffer, 0, read);
|
||||
}
|
||||
return out.toByteArray();
|
||||
}
|
||||
|
||||
private static class InMemoryMultipartFile implements MultipartFile {
|
||||
private final String originalFilename;
|
||||
private final byte[] bytes;
|
||||
|
||||
private InMemoryMultipartFile(String originalFilename, byte[] bytes) {
|
||||
this.originalFilename = originalFilename;
|
||||
this.bytes = bytes != null ? bytes : new byte[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return originalFilename;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOriginalFilename() {
|
||||
return originalFilename;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContentType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return bytes.length == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSize() {
|
||||
return bytes.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getBytes() {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() {
|
||||
return new java.io.ByteArrayInputStream(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferTo(java.io.File dest) throws IOException {
|
||||
Files.write(dest.toPath(), bytes);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,513 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditJudicialDocument;
|
||||
import com.gxwebsoft.credit.param.CreditJudicialDocumentImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditJudicialDocumentParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditJudicialDocumentService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 裁判文书司法大数据控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:51:03
|
||||
*/
|
||||
@Tag(name = "裁判文书司法大数据管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-judicial-document")
|
||||
public class CreditJudicialDocumentController extends BaseController {
|
||||
@Resource
|
||||
private CreditJudicialDocumentService creditJudicialDocumentService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询裁判文书司法大数据")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditJudicialDocument>> page(CreditJudicialDocumentParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditJudicialDocumentService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部裁判文书司法大数据")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditJudicialDocument>> list(CreditJudicialDocumentParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditJudicialDocumentService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询裁判文书司法大数据")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditJudicialDocument> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditJudicialDocumentService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditJudicialDocument:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加裁判文书司法大数据")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditJudicialDocument creditJudicialDocument) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditJudicialDocument.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditJudicialDocumentService.save(creditJudicialDocument)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditJudicialDocument:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改裁判文书司法大数据")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditJudicialDocument creditJudicialDocument) {
|
||||
if (creditJudicialDocumentService.updateById(creditJudicialDocument)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditJudicialDocument:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除裁判文书司法大数据")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (batchImportSupport.hardRemoveById(CreditJudicialDocument.class, id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditJudicialDocument:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加裁判文书司法大数据")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditJudicialDocument> list) {
|
||||
if (creditJudicialDocumentService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditJudicialDocument:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改裁判文书司法大数据")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditJudicialDocument> batchParam) {
|
||||
if (batchParam.update(creditJudicialDocumentService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditJudicialDocument:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除裁判文书司法大数据")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (batchImportSupport.hardRemoveByIds(CreditJudicialDocument.class, ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据“当事人/第三人”文本中包含的企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditJudicialDocument:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据当事人字段包含企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyNameContainedInText(
|
||||
creditJudicialDocumentService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditJudicialDocument::getId,
|
||||
CreditJudicialDocument::setId,
|
||||
CreditJudicialDocument::getCompanyId,
|
||||
CreditJudicialDocument::setCompanyId,
|
||||
CreditJudicialDocument::getHasData,
|
||||
CreditJudicialDocument::setHasData,
|
||||
CreditJudicialDocument::getTenantId,
|
||||
CreditJudicialDocument::new,
|
||||
// 需求:otherPartiesThirdParty 字段包含企业名称时,回填 companyId
|
||||
CreditJudicialDocument::getOtherPartiesThirdParty
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入裁判文书司法大数据
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditJudicialDocument:save')")
|
||||
@Operation(summary = "批量导入裁判文书司法大数据")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
// 支持按选项卡名称导入:默认读取“裁判文书”sheet(不存在则回退到第 0 个sheet)
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "裁判文书", 0);
|
||||
ExcelImportSupport.ImportResult<CreditJudicialDocumentImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditJudicialDocumentImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditJudicialDocumentImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
Map<String, String> urlByTitle = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "文书标题");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditJudicialDocument> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditJudicialDocumentImportParam param = list.get(i);
|
||||
try {
|
||||
CreditJudicialDocument item = convertImportParamToEntity(param);
|
||||
String link = null;
|
||||
if (!ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
link = urlByCaseNumber.get(item.getCaseNumber().trim());
|
||||
}
|
||||
if (ImportHelper.isBlank(link) && !ImportHelper.isBlank(item.getTitle())) {
|
||||
link = urlByTitle.get(item.getTitle().trim());
|
||||
}
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditJudicialDocumentService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditJudicialDocument::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditJudicialDocumentService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditJudicialDocument::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.JUDICIAL_DOCUMENT, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入历史裁判文书(仅解析“历史裁判文书”选项卡)
|
||||
* 规则:使用数据库唯一索引约束,重复数据不导入。
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditJudicialDocument:save')")
|
||||
@Operation(summary = "批量导入历史裁判文书司法大数据")
|
||||
@PostMapping("/import/history")
|
||||
public ApiResult<List<String>> importHistoryBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "历史裁判文书");
|
||||
if (sheetIndex < 0) {
|
||||
return fail("未读取到数据,请确认文件中存在“历史裁判文书”选项卡且表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
ExcelImportSupport.ImportResult<CreditJudicialDocumentImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditJudicialDocumentImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditJudicialDocumentImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
Map<String, String> urlByTitle = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "文书标题");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditJudicialDocument> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditJudicialDocumentImportParam param = list.get(i);
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
try {
|
||||
CreditJudicialDocument item = convertImportParamToEntity(param);
|
||||
if (item.getCaseNumber() != null) {
|
||||
item.setCaseNumber(item.getCaseNumber().trim());
|
||||
}
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
String link = null;
|
||||
if (!ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
link = urlByCaseNumber.get(item.getCaseNumber());
|
||||
}
|
||||
if (ImportHelper.isBlank(link) && !ImportHelper.isBlank(item.getTitle())) {
|
||||
link = urlByTitle.get(item.getTitle().trim());
|
||||
}
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
// 历史导入的数据统一标记为“失效”
|
||||
item.setDataStatus("失效");
|
||||
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditJudicialDocumentService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditJudicialDocument::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditJudicialDocumentService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditJudicialDocument::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.JUDICIAL_DOCUMENT, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
}
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载裁判文书导入模板
|
||||
*/
|
||||
@Operation(summary = "下载裁判文书导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditJudicialDocumentImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditJudicialDocumentImportParam example = new CreditJudicialDocumentImportParam();
|
||||
example.setTitle("裁判文书");
|
||||
example.setOtherPartiesThirdParty("第三人示例");
|
||||
example.setOccurrenceTime("2024-01-01");
|
||||
example.setCaseNumber("(2024)示例案号");
|
||||
example.setCauseOfAction("案由示例");
|
||||
example.setInvolvedAmount("100000");
|
||||
example.setDefendantAppellee("裁判结果示例");
|
||||
example.setCourtName("示例法院");
|
||||
example.setReleaseDate("2024-01-02");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("裁判文书导入模板", "裁判文书", CreditJudicialDocumentImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_judicial_document_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditJudicialDocumentImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getCaseNumber());
|
||||
}
|
||||
|
||||
private CreditJudicialDocument convertImportParamToEntity(CreditJudicialDocumentImportParam param) {
|
||||
CreditJudicialDocument entity = new CreditJudicialDocument();
|
||||
|
||||
String involvedAmount = !ImportHelper.isBlank(param.getInvolvedAmount2())
|
||||
? param.getInvolvedAmount2()
|
||||
: param.getInvolvedAmount();
|
||||
|
||||
entity.setTitle(param.getTitle());
|
||||
entity.setDocumentType(param.getDocumentType());
|
||||
entity.setDataStatus(param.getDataStatus());
|
||||
entity.setOtherPartiesThirdParty(param.getOtherPartiesThirdParty());
|
||||
entity.setOccurrenceTime(param.getOccurrenceTime());
|
||||
entity.setCaseNumber(param.getCaseNumber());
|
||||
entity.setCauseOfAction(param.getCauseOfAction());
|
||||
entity.setInvolvedAmount(involvedAmount);
|
||||
// Excel导入字段映射补全:否则对应数据库字段(defendant_appellee/release_date)会一直为空
|
||||
entity.setDefendantAppellee(param.getDefendantAppellee());
|
||||
entity.setReleaseDate(param.getReleaseDate());
|
||||
entity.setCourtName(param.getCourtName());
|
||||
entity.setComments(param.getComments());
|
||||
System.out.println("entity = " + entity);
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,430 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import cn.afterturn.easypoi.excel.ExcelExportUtil;
|
||||
import cn.afterturn.easypoi.excel.ExcelImportUtil;
|
||||
import cn.afterturn.easypoi.excel.entity.ExportParams;
|
||||
import cn.afterturn.easypoi.excel.entity.ImportParams;
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditJudiciary;
|
||||
import com.gxwebsoft.credit.param.CreditJudiciaryImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditJudiciaryParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditJudiciaryService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 司法案件控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-16 15:23:58
|
||||
*/
|
||||
@Tag(name = "司法案件管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-judiciary")
|
||||
public class CreditJudiciaryController extends BaseController {
|
||||
@Resource
|
||||
private CreditJudiciaryService creditJudiciaryService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询司法案件")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditJudiciary>> page(CreditJudiciaryParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditJudiciaryService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部司法案件")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditJudiciary>> list(CreditJudiciaryParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditJudiciaryService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询司法案件")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditJudiciary> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditJudiciaryService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditJudiciary:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加司法案件")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditJudiciary creditJudiciary) {
|
||||
if (creditJudiciaryService.save(creditJudiciary)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditJudiciary:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改司法案件")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditJudiciary creditJudiciary) {
|
||||
if (creditJudiciaryService.updateById(creditJudiciary)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditJudiciary:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除司法案件")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (batchImportSupport.hardRemoveById(CreditJudiciary.class, id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditJudiciary:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加司法案件")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditJudiciary> list) {
|
||||
if (creditJudiciaryService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditJudiciary:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改司法案件")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditJudiciary> batchParam) {
|
||||
if (batchParam.update(creditJudiciaryService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditJudiciary:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除司法案件")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (batchImportSupport.hardRemoveByIds(CreditJudiciary.class, ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditJudiciary:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
|
||||
creditJudiciaryService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditJudiciary::getId,
|
||||
CreditJudiciary::setId,
|
||||
CreditJudiciary::getName,
|
||||
CreditJudiciary::getCompanyId,
|
||||
CreditJudiciary::setCompanyId,
|
||||
CreditJudiciary::getHasData,
|
||||
CreditJudiciary::setHasData,
|
||||
CreditJudiciary::getTenantId,
|
||||
CreditJudiciary::new
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入司法案件
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditJudiciary:save')")
|
||||
@Operation(summary = "批量导入司法案件")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
// 支持按选项卡名称导入:默认读取“司法案件”sheet(不存在则回退到第 0 个sheet)
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "司法案件", 0);
|
||||
|
||||
List<CreditJudiciaryImportParam> list = null;
|
||||
int usedTitleRows = 0;
|
||||
int usedHeadRows = 0;
|
||||
int[][] tryConfigs = new int[][]{{1, 1}, {0, 1}, {0, 2}, {0, 3}};
|
||||
|
||||
for (int[] config : tryConfigs) {
|
||||
list = filterEmptyRows(tryImport(file, config[0], config[1], sheetIndex));
|
||||
if (!CollectionUtils.isEmpty(list)) {
|
||||
usedTitleRows = config[0];
|
||||
usedHeadRows = config[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
// easypoi 默认不会读取单元格超链接地址;url 可能挂在“案号/案件名称”等列的超链接中,需要额外读取回填。
|
||||
Map<String, String> urlByCode = ExcelImportSupport.readHyperlinksByHeaderKey(file, sheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
Map<String, String> urlByName = ExcelImportSupport.readHyperlinksByHeaderKey(file, sheetIndex, usedTitleRows, usedHeadRows, "案件名称");
|
||||
// 有些源文件会单独提供“url/网址/链接”等列(可能是纯文本也可能是超链接)
|
||||
Map<String, String> urlByCodeFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(file, sheetIndex, usedTitleRows, usedHeadRows, "案号", "url");
|
||||
if (urlByCodeFromUrlCol.isEmpty()) {
|
||||
urlByCodeFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(file, sheetIndex, usedTitleRows, usedHeadRows, "案号", "URL");
|
||||
}
|
||||
if (urlByCodeFromUrlCol.isEmpty()) {
|
||||
urlByCodeFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(file, sheetIndex, usedTitleRows, usedHeadRows, "案号", "网址");
|
||||
}
|
||||
if (urlByCodeFromUrlCol.isEmpty()) {
|
||||
urlByCodeFromUrlCol = ExcelImportSupport.readKeyValueByHeaders(file, sheetIndex, usedTitleRows, usedHeadRows, "案号", "链接");
|
||||
}
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditJudiciary> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditJudiciaryImportParam param = list.get(i);
|
||||
try {
|
||||
CreditJudiciary item = convertImportParamToEntity(param);
|
||||
if (!isBlank(item.getCode())) {
|
||||
String key = item.getCode().trim();
|
||||
String link = urlByCode.get(key);
|
||||
if (isBlank(link)) {
|
||||
link = urlByCodeFromUrlCol.get(key);
|
||||
}
|
||||
if (!isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
} else if (!isBlank(item.getName())) {
|
||||
String link = urlByName.get(item.getName().trim());
|
||||
if (!isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
}
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
|
||||
// 设置默认值
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getType() == null) {
|
||||
item.setType(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
// 验证必填字段
|
||||
// if (item.getName() == null || item.getName().trim().isEmpty()) {
|
||||
// errorMessages.add("第" + excelRowNumber + "行:项目名称不能为空");
|
||||
// continue;
|
||||
// }
|
||||
if (item.getCode() == null || item.getCode().trim().isEmpty()) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:唯一标识不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditJudiciaryService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditJudiciary::getCode,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditJudiciaryService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditJudiciary::getCode,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.JUDICIARY, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载司法案件导入模板
|
||||
*/
|
||||
@Operation(summary = "下载司法案件导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditJudiciaryImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditJudiciaryImportParam example = new CreditJudiciaryImportParam();
|
||||
example.setName("示例客户");
|
||||
example.setCode("C0001");
|
||||
example.setInfoType("执行案件");
|
||||
example.setReason("买卖合同纠纷");
|
||||
example.setProcessDate("2025-08-27");
|
||||
example.setCaseProgress("首次执行");
|
||||
example.setCaseIdentity("被执行人");
|
||||
example.setCode("(2025)闽0103执5480号");
|
||||
example.setCourt("福建省福州市台江区人民法院");
|
||||
example.setCaseAmount("5134060.00");
|
||||
templateList.add(example);
|
||||
|
||||
ExportParams exportParams = new ExportParams("司法案件导入模板", "司法案件");
|
||||
|
||||
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, CreditJudiciaryImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_judiciary_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private List<CreditJudiciaryImportParam> tryImport(MultipartFile file, int titleRows, int headRows, int sheetIndex) throws Exception {
|
||||
ImportParams importParams = new ImportParams();
|
||||
importParams.setTitleRows(titleRows);
|
||||
importParams.setHeadRows(headRows);
|
||||
importParams.setStartSheetIndex(sheetIndex);
|
||||
importParams.setSheetNum(1);
|
||||
return ExcelImportUtil.importExcel(file.getInputStream(), CreditJudiciaryImportParam.class, importParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤掉完全空白的导入行,避免空行导致导入失败
|
||||
*/
|
||||
private List<CreditJudiciaryImportParam> filterEmptyRows(List<CreditJudiciaryImportParam> rawList) {
|
||||
if (CollectionUtils.isEmpty(rawList)) {
|
||||
return rawList;
|
||||
}
|
||||
rawList.removeIf(this::isEmptyImportRow);
|
||||
return rawList;
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditJudiciaryImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
return isBlank(param.getName())
|
||||
&& isBlank(param.getCode())
|
||||
&& isBlank(param.getName())
|
||||
&& isBlank(param.getInfoType());
|
||||
}
|
||||
|
||||
private boolean isBlank(String value) {
|
||||
return value == null || value.trim().isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将CreditJudiciaryImportParam转换为CreditJudiciary实体
|
||||
*/
|
||||
private CreditJudiciary convertImportParamToEntity(CreditJudiciaryImportParam param) {
|
||||
CreditJudiciary entity = new CreditJudiciary();
|
||||
|
||||
entity.setCode(param.getCode());
|
||||
entity.setName(param.getName());
|
||||
entity.setInfoType(param.getInfoType());
|
||||
entity.setReason(param.getReason());
|
||||
entity.setProcessDate(param.getProcessDate());
|
||||
entity.setCaseProgress(param.getCaseProgress());
|
||||
entity.setCaseIdentity(param.getCaseIdentity());
|
||||
entity.setCourt(param.getCourt());
|
||||
entity.setCaseAmount(param.getCaseAmount());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,498 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditMediation;
|
||||
import com.gxwebsoft.credit.param.CreditMediationImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditMediationParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditMediationService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 诉前调解司法大数据控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:51:25
|
||||
*/
|
||||
@Tag(name = "诉前调解司法大数据管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-mediation")
|
||||
public class CreditMediationController extends BaseController {
|
||||
@Resource
|
||||
private CreditMediationService creditMediationService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询诉前调解司法大数据")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditMediation>> page(CreditMediationParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditMediationService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部诉前调解司法大数据")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditMediation>> list(CreditMediationParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditMediationService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询诉前调解司法大数据")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditMediation> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditMediationService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditMediation:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加诉前调解司法大数据")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditMediation creditMediation) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditMediation.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditMediationService.save(creditMediation)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditMediation:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改诉前调解司法大数据")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditMediation creditMediation) {
|
||||
if (creditMediationService.updateById(creditMediation)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditMediation:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除诉前调解司法大数据")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (batchImportSupport.hardRemoveById(CreditMediation.class, id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditMediation:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加诉前调解司法大数据")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditMediation> list) {
|
||||
if (creditMediationService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditMediation:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改诉前调解司法大数据")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditMediation> batchParam) {
|
||||
if (batchParam.update(creditMediationService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditMediation:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除诉前调解司法大数据")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (batchImportSupport.hardRemoveByIds(CreditMediation.class, ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditMediation:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
// Party columns may contain multiple roles/names; match if any company name is contained in the text.
|
||||
// Priority: 原告/上诉人 > 被告/被上诉人 > 其他当事人/第三人
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyNameContainedInText(
|
||||
creditMediationService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditMediation::getId,
|
||||
CreditMediation::setId,
|
||||
CreditMediation::getCompanyId,
|
||||
CreditMediation::setCompanyId,
|
||||
CreditMediation::getHasData,
|
||||
CreditMediation::setHasData,
|
||||
CreditMediation::getTenantId,
|
||||
CreditMediation::new,
|
||||
CreditMediation::getPlaintiffAppellant,
|
||||
CreditMediation::getAppellee,
|
||||
CreditMediation::getOtherPartiesThirdParty
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入诉前调解司法大数据
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditMediation:save')")
|
||||
@Operation(summary = "批量导入诉前调解司法大数据")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "诉前调解", 0);
|
||||
ExcelImportSupport.ImportResult<CreditMediationImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditMediationImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditMediationImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditMediation> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditMediationImportParam param = list.get(i);
|
||||
try {
|
||||
CreditMediation item = convertImportParamToEntity(param);
|
||||
if (!ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
String link = urlByCaseNumber.get(item.getCaseNumber().trim());
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditMediationService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditMediation::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditMediationService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditMediation::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.MEDIATION, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入历史诉前调解(仅解析“历史诉前调解”选项卡)
|
||||
* 规则:使用数据库唯一索引约束,重复数据不导入。
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditMediation:save')")
|
||||
@Operation(summary = "批量导入历史诉前调解")
|
||||
@PostMapping("/import/history")
|
||||
public ApiResult<List<String>> importHistoryBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "历史诉前调解");
|
||||
if (sheetIndex < 0) {
|
||||
return fail("未读取到数据,请确认文件中存在“历史诉前调解”选项卡且表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
ExcelImportSupport.ImportResult<CreditMediationImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditMediationImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditMediationImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditMediation> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditMediationImportParam param = list.get(i);
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
try {
|
||||
CreditMediation item = convertImportParamToEntity(param);
|
||||
if (item.getCaseNumber() != null) {
|
||||
item.setCaseNumber(item.getCaseNumber().trim());
|
||||
}
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
String link = urlByCaseNumber.get(item.getCaseNumber());
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
// 历史导入的数据统一标记为“失效”
|
||||
item.setDataStatus("失效");
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditMediationService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditMediation::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditMediationService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditMediation::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.MEDIATION, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
}
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载诉前调解导入模板
|
||||
*/
|
||||
@Operation(summary = "下载诉前调解导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditMediationImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditMediationImportParam example = new CreditMediationImportParam();
|
||||
example.setOtherPartiesThirdParty("当事人");
|
||||
example.setCaseNumber("(2024)示例案号");
|
||||
example.setCauseOfAction("案由示例");
|
||||
example.setCourtName("示例法院");
|
||||
example.setOccurrenceTime("2024-01-01");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("诉前调解导入模板", "诉前调解", CreditMediationImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_mediation_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditMediationImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getCaseNumber())
|
||||
&& ImportHelper.isBlank(param.getCauseOfAction());
|
||||
}
|
||||
|
||||
private CreditMediation convertImportParamToEntity(CreditMediationImportParam param) {
|
||||
CreditMediation entity = new CreditMediation();
|
||||
|
||||
// Template compatibility: prefer new columns ("发生时间"/"其他当事人/第三人"), fallback to legacy ones ("立案日期"/"当事人").
|
||||
String occurrenceTime = !ImportHelper.isBlank(param.getOccurrenceTime2())
|
||||
? param.getOccurrenceTime2()
|
||||
: param.getOccurrenceTime();
|
||||
String otherPartiesThirdParty = !ImportHelper.isBlank(param.getOtherPartiesThirdParty2())
|
||||
? param.getOtherPartiesThirdParty2()
|
||||
: param.getOtherPartiesThirdParty();
|
||||
|
||||
entity.setOccurrenceTime(occurrenceTime);
|
||||
entity.setOtherPartiesThirdParty(otherPartiesThirdParty);
|
||||
entity.setCaseNumber(param.getCaseNumber());
|
||||
entity.setCauseOfAction(param.getCauseOfAction());
|
||||
entity.setCourtName(param.getCourtName());
|
||||
entity.setComments(param.getComments());
|
||||
entity.setPlaintiffAppellant(param.getPlaintiffAppellant());
|
||||
entity.setAppellee(param.getAppellee());
|
||||
entity.setInvolvedAmount(param.getInvolvedAmount());
|
||||
entity.setDataStatus(param.getDataStatus());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,178 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.credit.service.CreditMpCustomerService;
|
||||
import com.gxwebsoft.credit.entity.CreditMpCustomer;
|
||||
import com.gxwebsoft.credit.param.CreditMpCustomerParam;
|
||||
import com.gxwebsoft.credit.param.BatchFollowStepApprovalDTO;
|
||||
import com.gxwebsoft.credit.param.EndFollowProcessDTO;
|
||||
import com.gxwebsoft.credit.param.FollowStepApprovalDTO;
|
||||
import com.gxwebsoft.credit.param.FollowStepQueryDTO;
|
||||
import com.gxwebsoft.credit.vo.FollowStatisticsDTO;
|
||||
import com.gxwebsoft.credit.vo.PendingApprovalStepVO;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.core.web.PageParam;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 小程序端客户控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-03-16 20:59:17
|
||||
*/
|
||||
@Tag(name = "小程序端客户管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-mp-customer")
|
||||
public class CreditMpCustomerController extends BaseController {
|
||||
@Resource
|
||||
private CreditMpCustomerService creditMpCustomerService;
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditMpCustomer:list')")
|
||||
@Operation(summary = "分页查询小程序端客户")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditMpCustomer>> page(CreditMpCustomerParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditMpCustomerService.pageRel(param));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditMpCustomer:list')")
|
||||
@Operation(summary = "查询全部小程序端客户")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditMpCustomer>> list(CreditMpCustomerParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditMpCustomerService.listRel(param));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditMpCustomer:list')")
|
||||
@Operation(summary = "根据id查询小程序端客户")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditMpCustomer> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditMpCustomerService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditMpCustomer:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加小程序端客户")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditMpCustomer creditMpCustomer) {
|
||||
// 记录当前登录用户id
|
||||
User loginUser = getLoginUser();
|
||||
if (loginUser != null) {
|
||||
creditMpCustomer.setUserId(loginUser.getUserId());
|
||||
}
|
||||
if (creditMpCustomerService.save(creditMpCustomer)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditMpCustomer:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改小程序端客户")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditMpCustomer creditMpCustomer) {
|
||||
if (creditMpCustomerService.updateById(creditMpCustomer)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditMpCustomer:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除小程序端客户")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (creditMpCustomerService.removeById(id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditMpCustomer:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加小程序端客户")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditMpCustomer> list) {
|
||||
if (creditMpCustomerService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditMpCustomer:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改小程序端客户")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditMpCustomer> batchParam) {
|
||||
if (batchParam.update(creditMpCustomerService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditMpCustomer:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除小程序端客户")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (creditMpCustomerService.removeByIds(ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditMpCustomer:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "审核跟进步骤")
|
||||
@PostMapping("/approve-follow-step")
|
||||
public ApiResult<?> approveFollowStep(@RequestBody FollowStepApprovalDTO dto) {
|
||||
creditMpCustomerService.approveFollowStep(dto);
|
||||
return success("审核成功");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditMpCustomer:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量审核跟进步骤")
|
||||
@PostMapping("/batch-approve-follow-steps")
|
||||
public ApiResult<?> batchApproveFollowSteps(@RequestBody BatchFollowStepApprovalDTO dto) {
|
||||
creditMpCustomerService.batchApproveFollowSteps(dto);
|
||||
return success("批量审核成功");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditMpCustomer:list')")
|
||||
@Operation(summary = "获取待审核的跟进步骤")
|
||||
@GetMapping("/pending-approval-steps")
|
||||
public ApiResult<List<PendingApprovalStepVO>> getPendingApprovalSteps(FollowStepQueryDTO query) {
|
||||
List<PendingApprovalStepVO> list = creditMpCustomerService.getPendingApprovalSteps(query);
|
||||
return success(list);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditMpCustomer:list')")
|
||||
@Operation(summary = "获取客户跟进统计")
|
||||
@GetMapping("/follow-statistics/{customerId}")
|
||||
public ApiResult<FollowStatisticsDTO> getFollowStatistics(@PathVariable Long customerId) {
|
||||
FollowStatisticsDTO statistics = creditMpCustomerService.getFollowStatistics(customerId);
|
||||
return success(statistics);
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditMpCustomer:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "结束客户跟进流程")
|
||||
@PostMapping("/end-follow-process")
|
||||
public ApiResult<?> endFollowProcess(@RequestBody EndFollowProcessDTO dto) {
|
||||
creditMpCustomerService.endFollowProcess(dto);
|
||||
return success("流程结束成功");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,462 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditCompany;
|
||||
import com.gxwebsoft.credit.entity.CreditNearbyCompany;
|
||||
import com.gxwebsoft.credit.param.CreditNearbyCompanyImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditNearbyCompanyParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditNearbyCompanyService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 附近企业控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-01-07 13:52:14
|
||||
*/
|
||||
@Tag(name = "附近企业管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-nearby-company")
|
||||
public class CreditNearbyCompanyController extends BaseController {
|
||||
@Resource
|
||||
private CreditNearbyCompanyService creditNearbyCompanyService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询附近企业")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditNearbyCompany>> page(CreditNearbyCompanyParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditNearbyCompanyService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部附近企业")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditNearbyCompany>> list(CreditNearbyCompanyParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditNearbyCompanyService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询附近企业")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditNearbyCompany> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditNearbyCompanyService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditNearbyCompany:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加附近企业")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditNearbyCompany creditNearbyCompany) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditNearbyCompany.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditNearbyCompanyService.save(creditNearbyCompany)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditNearbyCompany:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改附近企业")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditNearbyCompany creditNearbyCompany) {
|
||||
if (creditNearbyCompanyService.updateById(creditNearbyCompany)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditNearbyCompany:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除附近企业")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (batchImportSupport.hardRemoveById(CreditNearbyCompany.class, id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditNearbyCompany:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加附近企业")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditNearbyCompany> list) {
|
||||
if (creditNearbyCompanyService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditNearbyCompany:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改附近企业")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditNearbyCompany> batchParam) {
|
||||
if (batchParam.update(creditNearbyCompanyService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditNearbyCompany:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除附近企业")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (batchImportSupport.hardRemoveByIds(CreditNearbyCompany.class, ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditNearbyCompany:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
|
||||
creditNearbyCompanyService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditNearbyCompany::getId,
|
||||
CreditNearbyCompany::setId,
|
||||
CreditNearbyCompany::getName,
|
||||
CreditNearbyCompany::getCompanyId,
|
||||
CreditNearbyCompany::setCompanyId,
|
||||
CreditNearbyCompany::setCompanyName,
|
||||
CreditNearbyCompany::getHasData,
|
||||
CreditNearbyCompany::setHasData,
|
||||
CreditNearbyCompany::getTenantId,
|
||||
CreditNearbyCompany::new
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入附近企业
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditNearbyCompany:save')")
|
||||
@Operation(summary = "批量导入附近企业")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId,
|
||||
@RequestParam(value = "parentId", required = false) Integer parentId,
|
||||
@RequestParam(value = "type", required = false) Integer type) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
ExcelImportSupport.ImportResult<CreditNearbyCompanyImportParam> importResult = ExcelImportSupport.readAnySheet(
|
||||
file, CreditNearbyCompanyImportParam.class, this::isEmptyImportRow);
|
||||
List<CreditNearbyCompanyImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByCode = ExcelImportSupport.readHyperlinksByHeaderKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "统一社会信用代码");
|
||||
Map<String, String> urlByName = ExcelImportSupport.readHyperlinksByHeaderKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "企业名称");
|
||||
String fixedCompanyName = null;
|
||||
if (companyId != null && companyId > 0) {
|
||||
CreditCompany fixedCompany = creditCompanyService.getById(companyId);
|
||||
fixedCompanyName = fixedCompany != null ? fixedCompany.getName() : null;
|
||||
}
|
||||
|
||||
// 避免逐行写库:按批处理,显著降低 SQL 次数与事务开销
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditNearbyCompany> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditNearbyCompanyImportParam param = list.get(i);
|
||||
try {
|
||||
CreditNearbyCompany item = convertImportParamToEntity(param);
|
||||
String link = null;
|
||||
if (!ImportHelper.isBlank(item.getCode())) {
|
||||
link = urlByCode.get(item.getCode().trim());
|
||||
}
|
||||
if ((link == null || link.isEmpty()) && !ImportHelper.isBlank(item.getName())) {
|
||||
link = urlByName.get(item.getName().trim());
|
||||
}
|
||||
if (link != null && !link.isEmpty()) {
|
||||
item.setUrl(link);
|
||||
}
|
||||
|
||||
if (item.getParentId() == null && parentId != null) {
|
||||
item.setParentId(parentId);
|
||||
}
|
||||
if (item.getType() == null && type != null) {
|
||||
item.setType(type);
|
||||
}
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
if (ImportHelper.isBlank(item.getCompanyName()) && !ImportHelper.isBlank(fixedCompanyName)) {
|
||||
item.setCompanyName(fixedCompanyName);
|
||||
}
|
||||
}
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getName())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:企业名称不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += persistImportChunk(chunkItems, chunkRowNumbers, companyId, parentId, type, currentTenantId, mpBatchSize, errorMessages);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += persistImportChunk(chunkItems, chunkRowNumbers, companyId, parentId, type, currentTenantId, mpBatchSize, errorMessages);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.NEARBY_COMPANY, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
private int persistImportChunk(List<CreditNearbyCompany> items,
|
||||
List<Integer> excelRowNumbers,
|
||||
Integer companyId,
|
||||
Integer parentId,
|
||||
Integer type,
|
||||
Integer tenantId,
|
||||
int mpBatchSize,
|
||||
List<String> errorMessages) {
|
||||
return batchImportSupport.persistInsertOnlyChunk(
|
||||
creditNearbyCompanyService,
|
||||
items,
|
||||
excelRowNumbers,
|
||||
mpBatchSize,
|
||||
it -> {
|
||||
if (it == null) {
|
||||
return null;
|
||||
}
|
||||
String code = it.getCode();
|
||||
if (code != null && !code.trim().isEmpty()) {
|
||||
return code;
|
||||
}
|
||||
return it.getName();
|
||||
},
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载附近企业导入模板
|
||||
*/
|
||||
@Operation(summary = "下载附近企业导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditNearbyCompanyImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditNearbyCompanyImportParam example = new CreditNearbyCompanyImportParam();
|
||||
example.setName("示例科技有限公司");
|
||||
example.setRegistrationStatus("存续");
|
||||
example.setLegalPerson("李四");
|
||||
example.setRegisteredCapital("1000万人民币");
|
||||
example.setPaidinCapital("200万人民币");
|
||||
example.setEstablishDate("2018-06-01");
|
||||
example.setCode("91440101MA5XXXXXXX");
|
||||
example.setAddress("广西南宁市某某路1号");
|
||||
example.setPhone("13800000000");
|
||||
example.setEmail("demo@example.com");
|
||||
example.setProvince("广西");
|
||||
example.setCity("南宁");
|
||||
example.setRegion("青秀区");
|
||||
example.setDomain("https://example.com");
|
||||
example.setInstitutionType("有限责任公司");
|
||||
example.setCompanySize("小微企业");
|
||||
example.setRegistrationAuthority("南宁市市场监督管理局");
|
||||
example.setTaxpayerQualification("一般纳税人");
|
||||
example.setLatestAnnualReportYear("2023");
|
||||
example.setLatestAnnualReportOnOperatingRevenue("1000万");
|
||||
example.setEnterpriseScoreCheck("85");
|
||||
example.setCreditRating("A级");
|
||||
example.setCechnologyScore("70");
|
||||
example.setCechnologyLevel("良好");
|
||||
example.setSmallEnterprise("是");
|
||||
example.setCompanyProfile("企业简介示例");
|
||||
example.setNatureOfBusiness("经营范围示例");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("附近企业导入模板", "附近企业", CreditNearbyCompanyImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_nearby_company_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditNearbyCompanyImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
if (isImportHeaderRow(param)) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getName())
|
||||
&& ImportHelper.isBlank(param.getCode())
|
||||
&& ImportHelper.isBlank(param.getLegalPerson());
|
||||
}
|
||||
|
||||
private boolean isImportHeaderRow(CreditNearbyCompanyImportParam param) {
|
||||
return isHeaderValue(param.getName(), "企业名称")
|
||||
|| isHeaderValue(param.getCode(), "统一社会信用代码")
|
||||
|| isHeaderValue(param.getLegalPerson(), "法定代表人");
|
||||
}
|
||||
|
||||
private static boolean isHeaderValue(String value, String headerText) {
|
||||
if (value == null) {
|
||||
return false;
|
||||
}
|
||||
return headerText.equals(value.trim());
|
||||
}
|
||||
|
||||
private CreditNearbyCompany convertImportParamToEntity(CreditNearbyCompanyImportParam param) {
|
||||
CreditNearbyCompany entity = new CreditNearbyCompany();
|
||||
|
||||
entity.setName(param.getName());
|
||||
entity.setRegistrationStatus(param.getRegistrationStatus());
|
||||
entity.setLegalPerson(param.getLegalPerson());
|
||||
entity.setRegisteredCapital(param.getRegisteredCapital());
|
||||
entity.setEstablishDate(param.getEstablishDate());
|
||||
entity.setCode(param.getCode());
|
||||
entity.setAddress(param.getAddress());
|
||||
entity.setPhone(param.getPhone());
|
||||
entity.setEmail(param.getEmail());
|
||||
entity.setProvince(param.getProvince());
|
||||
entity.setCity(param.getCity());
|
||||
entity.setRegion(param.getRegion());
|
||||
entity.setTaxpayerCode(param.getTaxpayerCode());
|
||||
entity.setRegistrationNumber(param.getRegistrationNumber());
|
||||
entity.setOrganizationalCode(param.getOrganizationalCode());
|
||||
entity.setNumberOfInsuredPersons(param.getNumberOfInsuredPersons());
|
||||
entity.setAnnualReport(param.getAnnualReport());
|
||||
entity.setDomain(param.getDomain());
|
||||
entity.setBusinessTerm(param.getBusinessTerm());
|
||||
entity.setNationalStandardIndustryCategories(param.getNationalStandardIndustryCategories());
|
||||
entity.setNationalStandardIndustryCategories2(param.getNationalStandardIndustryCategories2());
|
||||
entity.setNationalStandardIndustryCategories3(param.getNationalStandardIndustryCategories3());
|
||||
entity.setNationalStandardIndustryCategories4(param.getNationalStandardIndustryCategories4());
|
||||
entity.setFormerName(param.getFormerName());
|
||||
entity.setEnglishName(param.getEnglishName());
|
||||
entity.setMailingAddress(param.getMailingAddress());
|
||||
entity.setMailingEmail(param.getMailingEmail());
|
||||
entity.setTel(param.getTel());
|
||||
entity.setPostalCode(param.getPostalCode());
|
||||
entity.setNationalStandardIndustryCategories5(param.getNationalStandardIndustryCategories5());
|
||||
entity.setNationalStandardIndustryCategories6(param.getNationalStandardIndustryCategories6());
|
||||
entity.setNationalStandardIndustryCategories7(param.getNationalStandardIndustryCategories7());
|
||||
entity.setNationalStandardIndustryCategories8(param.getNationalStandardIndustryCategories8());
|
||||
entity.setType(param.getType());
|
||||
entity.setInstitutionType(param.getInstitutionType());
|
||||
entity.setCompanySize(param.getCompanySize());
|
||||
entity.setCompanyProfile(param.getCompanyProfile());
|
||||
entity.setNatureOfBusiness(param.getNatureOfBusiness());
|
||||
entity.setComments(param.getComments());
|
||||
entity.setMoreEmail(param.getMoreEmail());
|
||||
entity.setMoreTel(param.getMoreTel());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,395 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditPatent;
|
||||
import com.gxwebsoft.credit.param.CreditPatentImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditPatentParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditPatentService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 专利控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-01-07 13:52:14
|
||||
*/
|
||||
@Tag(name = "专利管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-patent")
|
||||
public class CreditPatentController extends BaseController {
|
||||
@Resource
|
||||
private CreditPatentService creditPatentService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询专利")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditPatent>> page(CreditPatentParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditPatentService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部专利")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditPatent>> list(CreditPatentParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditPatentService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询专利")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditPatent> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditPatentService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditPatent:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加专利")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditPatent creditPatent) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditPatent.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditPatentService.save(creditPatent)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditPatent:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改专利")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditPatent creditPatent) {
|
||||
if (creditPatentService.updateById(creditPatent)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditPatent:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除专利")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (batchImportSupport.hardRemoveById(CreditPatent.class, id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditPatent:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加专利")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditPatent> list) {
|
||||
if (creditPatentService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditPatent:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改专利")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditPatent> batchParam) {
|
||||
if (batchParam.update(creditPatentService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditPatent:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除专利")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (batchImportSupport.hardRemoveByIds(CreditPatent.class, ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditPatent:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
|
||||
creditPatentService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditPatent::getId,
|
||||
CreditPatent::setId,
|
||||
CreditPatent::getPatentApplicant,
|
||||
CreditPatent::getCompanyId,
|
||||
CreditPatent::setCompanyId,
|
||||
CreditPatent::getHasData,
|
||||
CreditPatent::setHasData,
|
||||
CreditPatent::getTenantId,
|
||||
CreditPatent::new
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入专利
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditPatent:save')")
|
||||
@Operation(summary = "批量导入专利")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
// 单企业表通常是多 sheet,专利页签名一般为“专利”
|
||||
int preferredSheetIndex = ExcelImportSupport.findSheetIndex(file, "专利", 0);
|
||||
ExcelImportSupport.ImportResult<CreditPatentImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditPatentImportParam.class, this::isEmptyImportRow, preferredSheetIndex);
|
||||
if (CollectionUtils.isEmpty(importResult.getData())) {
|
||||
importResult = ExcelImportSupport.readAnySheet(file, CreditPatentImportParam.class, this::isEmptyImportRow);
|
||||
}
|
||||
List<CreditPatentImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByRegisterNo = ExcelImportSupport.readHyperlinksByHeaderKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "申请号");
|
||||
Map<String, String> urlByName = ExcelImportSupport.readHyperlinksByHeaderKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "发明名称");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditPatent> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditPatentImportParam param = list.get(i);
|
||||
try {
|
||||
CreditPatent item = convertImportParamToEntity(param);
|
||||
String link = null;
|
||||
if (!ImportHelper.isBlank(item.getRegisterNo())) {
|
||||
link = urlByRegisterNo.get(item.getRegisterNo().trim());
|
||||
}
|
||||
if ((link == null || link.isEmpty()) && !ImportHelper.isBlank(item.getName())) {
|
||||
link = urlByName.get(item.getName().trim());
|
||||
}
|
||||
if (link != null && !link.isEmpty()) {
|
||||
item.setUrl(link);
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getRegisterNo())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:申请号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditPatentService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditPatent::getRegisterNo,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditPatentService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditPatent::getRegisterNo,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.PATENT, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载专利导入模板
|
||||
*/
|
||||
@Operation(summary = "下载专利导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditPatentImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditPatentImportParam example = new CreditPatentImportParam();
|
||||
example.setName("一种示例装置及方法");
|
||||
example.setType("发明专利");
|
||||
example.setStatusText("有效");
|
||||
example.setRegisterNo("CN2024XXXXXXXX.X");
|
||||
example.setRegisterDate("2024-01-01");
|
||||
example.setPublicNo("CN1XXXXXXXXX");
|
||||
example.setPublicDate("2024-06-01");
|
||||
example.setInventor("张三;李四");
|
||||
example.setPatentApplicant("示例科技有限公司");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("专利导入模板", "专利", CreditPatentImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_patent_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditPatentImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
if (isImportHeaderRow(param)) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getName())
|
||||
&& ImportHelper.isBlank(param.getType())
|
||||
&& ImportHelper.isBlank(param.getStatusText())
|
||||
&& ImportHelper.isBlank(param.getRegisterNo())
|
||||
&& ImportHelper.isBlank(param.getRegisterDate())
|
||||
&& ImportHelper.isBlank(param.getPublicNo())
|
||||
&& ImportHelper.isBlank(param.getPublicDate())
|
||||
&& ImportHelper.isBlank(param.getInventor())
|
||||
&& ImportHelper.isBlank(param.getPatentApplicant())
|
||||
&& ImportHelper.isBlank(param.getComments());
|
||||
}
|
||||
|
||||
private boolean isImportHeaderRow(CreditPatentImportParam param) {
|
||||
return isHeaderValue(param.getRegisterNo(), "申请号")
|
||||
|| isHeaderValue(param.getName(), "发明名称")
|
||||
|| isHeaderValue(param.getPatentApplicant(), "申请(专利权)人");
|
||||
}
|
||||
|
||||
private static boolean isHeaderValue(String value, String headerText) {
|
||||
if (value == null) {
|
||||
return false;
|
||||
}
|
||||
return headerText.equals(value.trim());
|
||||
}
|
||||
|
||||
private CreditPatent convertImportParamToEntity(CreditPatentImportParam param) {
|
||||
CreditPatent entity = new CreditPatent();
|
||||
|
||||
entity.setName(param.getName());
|
||||
entity.setType(param.getType());
|
||||
entity.setStatusText(param.getStatusText());
|
||||
entity.setRegisterNo(param.getRegisterNo());
|
||||
entity.setRegisterDate(param.getRegisterDate());
|
||||
entity.setPublicNo(param.getPublicNo());
|
||||
entity.setPublicDate(param.getPublicDate());
|
||||
entity.setInventor(param.getInventor());
|
||||
entity.setPatentApplicant(param.getPatentApplicant());
|
||||
entity.setComments(param.getComments());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,359 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditCompany;
|
||||
import com.gxwebsoft.credit.entity.CreditRiskRelation;
|
||||
import com.gxwebsoft.credit.param.CreditRiskRelationImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditRiskRelationParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditRiskRelationService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 风险关系表控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:51:41
|
||||
*/
|
||||
@Tag(name = "风险关系表管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-risk-relation")
|
||||
public class CreditRiskRelationController extends BaseController {
|
||||
@Resource
|
||||
private CreditRiskRelationService creditRiskRelationService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询风险关系表")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditRiskRelation>> page(CreditRiskRelationParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditRiskRelationService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部风险关系表")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditRiskRelation>> list(CreditRiskRelationParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditRiskRelationService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询风险关系表")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditRiskRelation> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditRiskRelationService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditRiskRelation:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加风险关系表")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditRiskRelation creditRiskRelation) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditRiskRelation.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditRiskRelationService.save(creditRiskRelation)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditRiskRelation:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改风险关系表")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditRiskRelation creditRiskRelation) {
|
||||
if (creditRiskRelationService.updateById(creditRiskRelation)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditRiskRelation:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除风险关系表")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (batchImportSupport.hardRemoveById(CreditRiskRelation.class, id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditRiskRelation:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加风险关系表")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditRiskRelation> list) {
|
||||
if (creditRiskRelationService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditRiskRelation:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改风险关系表")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditRiskRelation> batchParam) {
|
||||
if (batchParam.update(creditRiskRelationService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditRiskRelation:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除风险关系表")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (batchImportSupport.hardRemoveByIds(CreditRiskRelation.class, ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditRiskRelation:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
|
||||
creditRiskRelationService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditRiskRelation::getId,
|
||||
CreditRiskRelation::setId,
|
||||
CreditRiskRelation::getMainBodyName,
|
||||
CreditRiskRelation::getCompanyId,
|
||||
CreditRiskRelation::setCompanyId,
|
||||
CreditRiskRelation::setCompanyName,
|
||||
CreditRiskRelation::getHasData,
|
||||
CreditRiskRelation::setHasData,
|
||||
CreditRiskRelation::getTenantId,
|
||||
CreditRiskRelation::new
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入风险关系表
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditRiskRelation:save')")
|
||||
@Operation(summary = "批量导入风险关系表")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "风险关系", 1);
|
||||
ExcelImportSupport.ImportResult<CreditRiskRelationImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditRiskRelationImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditRiskRelationImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
String fixedCompanyName = null;
|
||||
if (companyId != null && companyId > 0) {
|
||||
CreditCompany fixedCompany = creditCompanyService.getById(companyId);
|
||||
fixedCompanyName = fixedCompany != null ? fixedCompany.getName() : null;
|
||||
}
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditRiskRelation> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditRiskRelationImportParam param = list.get(i);
|
||||
try {
|
||||
CreditRiskRelation item = convertImportParamToEntity(param);
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
if (ImportHelper.isBlank(item.getCompanyName()) && !ImportHelper.isBlank(fixedCompanyName)) {
|
||||
item.setCompanyName(fixedCompanyName);
|
||||
}
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getMainBodyName())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:主体名称不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditRiskRelationService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditRiskRelation::getMainBodyName,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditRiskRelationService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditRiskRelation::getMainBodyName,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.RISK_RELATION, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载风险关系导入模板
|
||||
*/
|
||||
@Operation(summary = "下载风险关系导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditRiskRelationImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditRiskRelationImportParam example = new CreditRiskRelationImportParam();
|
||||
example.setMainBodyName("示例企业");
|
||||
example.setRegistrationStatus("存续");
|
||||
example.setRegisteredCapital("8000");
|
||||
example.setProvinceRegion("浙江");
|
||||
example.setAssociatedRelation("关联企业");
|
||||
example.setRiskRelation("存在风险关联");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("风险关系导入模板", "风险关系", CreditRiskRelationImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_risk_relation_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditRiskRelationImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getMainBodyName())
|
||||
&& ImportHelper.isBlank(param.getRegistrationStatus())
|
||||
&& ImportHelper.isBlank(param.getRegisteredCapital());
|
||||
}
|
||||
|
||||
private CreditRiskRelation convertImportParamToEntity(CreditRiskRelationImportParam param) {
|
||||
CreditRiskRelation entity = new CreditRiskRelation();
|
||||
|
||||
entity.setMainBodyName(param.getMainBodyName());
|
||||
entity.setRegistrationStatus(param.getRegistrationStatus());
|
||||
entity.setRegisteredCapital(param.getRegisteredCapital());
|
||||
entity.setProvinceRegion(param.getProvinceRegion());
|
||||
entity.setAssociatedRelation(param.getAssociatedRelation());
|
||||
entity.setRiskRelation(param.getRiskRelation());
|
||||
entity.setComments(param.getComments());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,365 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditCompany;
|
||||
import com.gxwebsoft.credit.entity.CreditSupplier;
|
||||
import com.gxwebsoft.credit.param.CreditSupplierImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditSupplierParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditSupplierService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 供应商控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:51:47
|
||||
*/
|
||||
@Tag(name = "供应商管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-supplier")
|
||||
public class CreditSupplierController extends BaseController {
|
||||
@Resource
|
||||
private CreditSupplierService creditSupplierService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询供应商")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditSupplier>> page(CreditSupplierParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditSupplierService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部供应商")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditSupplier>> list(CreditSupplierParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditSupplierService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询供应商")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditSupplier> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditSupplierService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditSupplier:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加供应商")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditSupplier creditSupplier) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditSupplier.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditSupplierService.save(creditSupplier)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditSupplier:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改供应商")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditSupplier creditSupplier) {
|
||||
if (creditSupplierService.updateById(creditSupplier)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditSupplier:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除供应商")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (batchImportSupport.hardRemoveById(CreditSupplier.class, id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditSupplier:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加供应商")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditSupplier> list) {
|
||||
if (creditSupplierService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditSupplier:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改供应商")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditSupplier> batchParam) {
|
||||
if (batchParam.update(creditSupplierService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditSupplier:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除供应商")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (batchImportSupport.hardRemoveByIds(CreditSupplier.class, ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditSupplier:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
|
||||
creditSupplierService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditSupplier::getId,
|
||||
CreditSupplier::setId,
|
||||
CreditSupplier::getSupplier,
|
||||
CreditSupplier::getCompanyId,
|
||||
CreditSupplier::setCompanyId,
|
||||
CreditSupplier::setCompanyName,
|
||||
CreditSupplier::getHasData,
|
||||
CreditSupplier::setHasData,
|
||||
CreditSupplier::getTenantId,
|
||||
CreditSupplier::new
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入供应商
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditSupplier:save')")
|
||||
@Operation(summary = "批量导入供应商")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "供应商", 3);
|
||||
ExcelImportSupport.ImportResult<CreditSupplierImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditSupplierImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditSupplierImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlBySupplier = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "供应商");
|
||||
String fixedCompanyName = null;
|
||||
if (companyId != null && companyId > 0) {
|
||||
CreditCompany fixedCompany = creditCompanyService.getById(companyId);
|
||||
fixedCompanyName = fixedCompany != null ? fixedCompany.getName() : null;
|
||||
}
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditSupplier> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditSupplierImportParam param = list.get(i);
|
||||
try {
|
||||
CreditSupplier item = convertImportParamToEntity(param);
|
||||
if (!ImportHelper.isBlank(item.getSupplier())) {
|
||||
String link = urlBySupplier.get(item.getSupplier().trim());
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
if (ImportHelper.isBlank(item.getCompanyName()) && !ImportHelper.isBlank(fixedCompanyName)) {
|
||||
item.setCompanyName(fixedCompanyName);
|
||||
}
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getSupplier())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:供应商不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditSupplierService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditSupplier::getSupplier,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditSupplierService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditSupplier::getSupplier,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.SUPPLIER, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载供应商导入模板
|
||||
*/
|
||||
@Operation(summary = "下载供应商导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditSupplierImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditSupplierImportParam example = new CreditSupplierImportParam();
|
||||
example.setSupplier("示例供应商");
|
||||
example.setStatusTxt("合作中");
|
||||
example.setPurchaseAmount("120");
|
||||
example.setPublicDate("2024-02-01");
|
||||
example.setDataSource("公开渠道");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("供应商导入模板", "供应商", CreditSupplierImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_supplier_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditSupplierImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getSupplier())
|
||||
&& ImportHelper.isBlank(param.getStatusTxt())
|
||||
&& ImportHelper.isBlank(param.getPurchaseAmount());
|
||||
}
|
||||
|
||||
private CreditSupplier convertImportParamToEntity(CreditSupplierImportParam param) {
|
||||
CreditSupplier entity = new CreditSupplier();
|
||||
|
||||
entity.setSupplier(param.getSupplier());
|
||||
entity.setStatusTxt(param.getStatusTxt());
|
||||
entity.setPurchaseAmount(param.getPurchaseAmount());
|
||||
entity.setPublicDate(param.getPublicDate());
|
||||
entity.setDataSource(param.getDataSource());
|
||||
entity.setComments(param.getComments());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,422 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditCompany;
|
||||
import com.gxwebsoft.credit.entity.CreditSuspectedRelationship;
|
||||
import com.gxwebsoft.credit.param.CreditSuspectedRelationshipImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditSuspectedRelationshipParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditSuspectedRelationshipService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 疑似关系控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-01-07 13:52:14
|
||||
*/
|
||||
@Tag(name = "疑似关系管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-suspected-relationship")
|
||||
public class CreditSuspectedRelationshipController extends BaseController {
|
||||
@Resource
|
||||
private CreditSuspectedRelationshipService creditSuspectedRelationshipService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询疑似关系")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditSuspectedRelationship>> page(CreditSuspectedRelationshipParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditSuspectedRelationshipService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部疑似关系")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditSuspectedRelationship>> list(CreditSuspectedRelationshipParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditSuspectedRelationshipService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询疑似关系")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditSuspectedRelationship> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditSuspectedRelationshipService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditSuspectedRelationship:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加疑似关系")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditSuspectedRelationship creditSuspectedRelationship) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditSuspectedRelationship.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditSuspectedRelationshipService.save(creditSuspectedRelationship)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditSuspectedRelationship:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改疑似关系")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditSuspectedRelationship creditSuspectedRelationship) {
|
||||
if (creditSuspectedRelationshipService.updateById(creditSuspectedRelationship)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditSuspectedRelationship:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除疑似关系")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (batchImportSupport.hardRemoveById(CreditSuspectedRelationship.class, id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditSuspectedRelationship:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加疑似关系")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditSuspectedRelationship> list) {
|
||||
if (creditSuspectedRelationshipService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditSuspectedRelationship:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改疑似关系")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditSuspectedRelationship> batchParam) {
|
||||
if (batchParam.update(creditSuspectedRelationshipService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditSuspectedRelationship:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除疑似关系")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (batchImportSupport.hardRemoveByIds(CreditSuspectedRelationship.class, ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditSuspectedRelationship:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
|
||||
creditSuspectedRelationshipService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditSuspectedRelationship::getId,
|
||||
CreditSuspectedRelationship::setId,
|
||||
CreditSuspectedRelationship::getName,
|
||||
CreditSuspectedRelationship::getCompanyId,
|
||||
CreditSuspectedRelationship::setCompanyId,
|
||||
CreditSuspectedRelationship::setCompanyName,
|
||||
CreditSuspectedRelationship::getHasData,
|
||||
CreditSuspectedRelationship::setHasData,
|
||||
CreditSuspectedRelationship::getTenantId,
|
||||
CreditSuspectedRelationship::new
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入疑似关系
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditSuspectedRelationship:save')")
|
||||
@Operation(summary = "批量导入疑似关系")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
ExcelImportSupport.ImportResult<CreditSuspectedRelationshipImportParam> importResult = ExcelImportSupport.readAnySheet(
|
||||
file, CreditSuspectedRelationshipImportParam.class, this::isEmptyImportRow);
|
||||
List<CreditSuspectedRelationshipImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByName = ExcelImportSupport.readHyperlinksByHeaderKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "企业名称");
|
||||
String fixedCompanyName = null;
|
||||
if (companyId != null && companyId > 0) {
|
||||
CreditCompany fixedCompany = creditCompanyService.getById(companyId);
|
||||
fixedCompanyName = fixedCompany != null ? fixedCompany.getName() : null;
|
||||
}
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditSuspectedRelationship> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditSuspectedRelationshipImportParam param = list.get(i);
|
||||
try {
|
||||
CreditSuspectedRelationship item = convertImportParamToEntity(param);
|
||||
if (!ImportHelper.isBlank(item.getName())) {
|
||||
String link = urlByName.get(item.getName().trim());
|
||||
if (link != null && !link.isEmpty()) {
|
||||
item.setUrl(link);
|
||||
}
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
if (ImportHelper.isBlank(item.getCompanyName()) && !ImportHelper.isBlank(fixedCompanyName)) {
|
||||
item.setCompanyName(fixedCompanyName);
|
||||
}
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getName())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:企业名称不能为空");
|
||||
continue;
|
||||
}
|
||||
if (ImportHelper.isBlank(item.getRelatedParty())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:关联方不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditSuspectedRelationshipService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
it -> {
|
||||
if (it == null) {
|
||||
return null;
|
||||
}
|
||||
String n = it.getName();
|
||||
String r = it.getRelatedParty();
|
||||
if (n != null) {
|
||||
n = n.trim();
|
||||
}
|
||||
if (r != null) {
|
||||
r = r.trim();
|
||||
}
|
||||
if (n != null && !n.isEmpty() && r != null && !r.isEmpty()) {
|
||||
return n + "->" + r;
|
||||
}
|
||||
return n;
|
||||
},
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditSuspectedRelationshipService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
it -> {
|
||||
if (it == null) {
|
||||
return null;
|
||||
}
|
||||
String n = it.getName();
|
||||
String r = it.getRelatedParty();
|
||||
if (n != null) {
|
||||
n = n.trim();
|
||||
}
|
||||
if (r != null) {
|
||||
r = r.trim();
|
||||
}
|
||||
if (n != null && !n.isEmpty() && r != null && !r.isEmpty()) {
|
||||
return n + "->" + r;
|
||||
}
|
||||
return n;
|
||||
},
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.SUSPECTED_RELATIONSHIP, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载疑似关系导入模板
|
||||
*/
|
||||
@Operation(summary = "下载疑似关系导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditSuspectedRelationshipImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditSuspectedRelationshipImportParam example = new CreditSuspectedRelationshipImportParam();
|
||||
example.setName("示例科技有限公司");
|
||||
example.setStatusText("存续");
|
||||
example.setLegalPerson("李四");
|
||||
example.setRegisteredCapital("1000万人民币");
|
||||
example.setCreateDate("2018-06-01");
|
||||
example.setRelatedParty("关联方示例");
|
||||
example.setType("股权关联");
|
||||
example.setDetail("疑似关系详情示例");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("疑似关系导入模板", "疑似关系", CreditSuspectedRelationshipImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_suspected_relationship_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditSuspectedRelationshipImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
if (isImportHeaderRow(param)) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getName())
|
||||
&& ImportHelper.isBlank(param.getRelatedParty())
|
||||
&& ImportHelper.isBlank(param.getType());
|
||||
}
|
||||
|
||||
private boolean isImportHeaderRow(CreditSuspectedRelationshipImportParam param) {
|
||||
return isHeaderValue(param.getName(), "企业名称")
|
||||
|| isHeaderValue(param.getRelatedParty(), "关联方")
|
||||
|| isHeaderValue(param.getType(), "疑似关系类型");
|
||||
}
|
||||
|
||||
private static boolean isHeaderValue(String value, String headerText) {
|
||||
if (value == null) {
|
||||
return false;
|
||||
}
|
||||
return headerText.equals(value.trim());
|
||||
}
|
||||
|
||||
private CreditSuspectedRelationship convertImportParamToEntity(CreditSuspectedRelationshipImportParam param) {
|
||||
CreditSuspectedRelationship entity = new CreditSuspectedRelationship();
|
||||
|
||||
entity.setName(param.getName());
|
||||
entity.setStatusText(param.getStatusText());
|
||||
entity.setLegalPerson(param.getLegalPerson());
|
||||
entity.setRegisteredCapital(param.getRegisteredCapital());
|
||||
entity.setCreateDate(param.getCreateDate());
|
||||
entity.setRelatedParty(param.getRelatedParty());
|
||||
entity.setType(param.getType());
|
||||
entity.setDetail(param.getDetail());
|
||||
entity.setComments(param.getComments());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,453 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import cn.afterturn.easypoi.excel.ExcelExportUtil;
|
||||
import cn.afterturn.easypoi.excel.entity.ExportParams;
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditCompany;
|
||||
import com.gxwebsoft.credit.entity.CreditUser;
|
||||
import com.gxwebsoft.credit.param.CreditUserImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditUserParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditUserService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.ss.usermodel.WorkbookFactory;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 招投标信息表控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-15 13:16:04
|
||||
*/
|
||||
@Tag(name = "招投标信息表管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-user")
|
||||
public class CreditUserController extends BaseController {
|
||||
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
@Resource
|
||||
private CreditUserService creditUserService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询招投标信息表")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditUser>> page(CreditUserParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditUserService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部招投标信息表")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditUser>> list(CreditUserParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditUserService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询招投标信息表")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditUser> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditUserService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditUser:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加招投标信息表")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditUser creditUser) {
|
||||
if (creditUserService.save(creditUser)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditUser:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改招投标信息表")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditUser creditUser) {
|
||||
if (creditUserService.updateById(creditUser)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditUser:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除招投标信息表")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (batchImportSupport.hardRemoveById(CreditUser.class, id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditUser:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加招投标信息表")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditUser> list) {
|
||||
if (creditUserService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditUser:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改招投标信息表")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditUser> batchParam) {
|
||||
if (batchParam.update(creditUserService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditUser:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除招投标信息表")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (batchImportSupport.hardRemoveByIds(CreditUser.class, ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditUser:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
|
||||
creditUserService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditUser::getId,
|
||||
CreditUser::setId,
|
||||
CreditUser::getWinningName,
|
||||
CreditUser::getCompanyId,
|
||||
CreditUser::setCompanyId,
|
||||
CreditUser::setCompanyName,
|
||||
CreditUser::getHasData,
|
||||
CreditUser::setHasData,
|
||||
CreditUser::getTenantId,
|
||||
CreditUser::new
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入招投标信息
|
||||
* Excel表头格式:客户名称、唯一标识、类型、企业角色、上级ID、信息类型、所在国家、所在省份、所在城市、所在辖区、街道地址、招采单位名称、中标单位名称、中标金额、备注、是否推荐、到期时间、排序、状态、用户ID、租户ID
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditUser:save')")
|
||||
@Operation(summary = "批量导入招投标信息")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "招投标", 0);
|
||||
ExcelImportSupport.ImportResult<CreditUserImportParam> importResult =
|
||||
ExcelImportSupport.read(file, CreditUserImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditUserImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<Integer, String> urlMap = readNameHyperlinks(file, sheetIndex, usedTitleRows, usedHeadRows);
|
||||
String fixedCompanyName = null;
|
||||
if (companyId != null && companyId > 0) {
|
||||
CreditCompany fixedCompany = creditCompanyService.getById(companyId);
|
||||
fixedCompanyName = fixedCompany != null ? fixedCompany.getName() : null;
|
||||
}
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditUser> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditUserImportParam param = list.get(i);
|
||||
try {
|
||||
CreditUser item = convertImportParamToEntity(param);
|
||||
|
||||
String link = urlMap.get(i);
|
||||
if (link != null && !link.isEmpty()) {
|
||||
item.setUrl(link);
|
||||
}
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
if (ImportHelper.isBlank(item.getCompanyName()) && !ImportHelper.isBlank(fixedCompanyName)) {
|
||||
item.setCompanyName(fixedCompanyName);
|
||||
}
|
||||
}
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
// 设置默认值
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getType() == null) {
|
||||
item.setType(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
// 验证必填字段
|
||||
if (item.getName() == null || item.getName().trim().isEmpty()) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:项目名称不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditUserService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditUser::getName,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditUserService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditUser::getName,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.USER, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载招投标信息导入模板
|
||||
*/
|
||||
@Operation(summary = "下载招投标信息导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditUserImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditUserImportParam example = new CreditUserImportParam();
|
||||
example.setCode("CUS001");
|
||||
example.setName("示例客户");
|
||||
example.setReleaseDate("2023-01-01");
|
||||
example.setType(0);
|
||||
example.setRole("采购方");
|
||||
example.setInfoType("企业");
|
||||
example.setAddress("广东省-广州市-南沙区");
|
||||
example.setProcurementName("示例招采单位");
|
||||
example.setWinningName("示例中标单位");
|
||||
example.setWinningPrice("100000");
|
||||
templateList.add(example);
|
||||
|
||||
ExportParams exportParams = new ExportParams("招投标信息导入模板", "招投标信息");
|
||||
|
||||
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, CreditUserImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_user_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取“项目名称”列的超链接,按数据行顺序返回。
|
||||
*/
|
||||
private Map<Integer, String> readNameHyperlinks(MultipartFile file, int sheetIndex, int titleRows, int headRows) throws Exception {
|
||||
Map<Integer, String> result = new HashMap<>();
|
||||
try (InputStream is = file.getInputStream(); Workbook workbook = WorkbookFactory.create(is)) {
|
||||
Sheet sheet = workbook.getSheetAt(sheetIndex);
|
||||
if (sheet == null) {
|
||||
return result;
|
||||
}
|
||||
int headerRowNum = titleRows + headRows - 1;
|
||||
Row headerRow = sheet.getRow(headerRowNum);
|
||||
int nameColIndex = 0;
|
||||
if (headerRow != null) {
|
||||
for (int c = headerRow.getFirstCellNum(); c < headerRow.getLastCellNum(); c++) {
|
||||
Cell cell = headerRow.getCell(c);
|
||||
if (cell != null && "项目名称".equals(normalizeHeaderText(cell.getStringCellValue()))) {
|
||||
nameColIndex = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
int dataStartRow = titleRows + headRows;
|
||||
for (int r = dataStartRow; r <= sheet.getLastRowNum(); r++) {
|
||||
Row row = sheet.getRow(r);
|
||||
if (row == null) {
|
||||
continue;
|
||||
}
|
||||
Cell cell = row.getCell(nameColIndex);
|
||||
if (cell != null && cell.getHyperlink() != null) {
|
||||
String address = cell.getHyperlink().getAddress();
|
||||
if (address != null && !address.isEmpty()) {
|
||||
result.put(r - dataStartRow, address);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于表头匹配:仅做最常见的空白字符规整(避免表头中存在换行/空格导致无法定位列)。
|
||||
*/
|
||||
private static String normalizeHeaderText(String text) {
|
||||
if (text == null) {
|
||||
return "";
|
||||
}
|
||||
return text
|
||||
.replace(" ", "")
|
||||
.replace("\t", "")
|
||||
.replace("\r", "")
|
||||
.replace("\n", "")
|
||||
.replace("\u00A0", "")
|
||||
.replace(" ", "")
|
||||
.trim();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditUserImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
return isBlank(param.getName())
|
||||
&& isBlank(param.getCode())
|
||||
&& isBlank(param.getRole())
|
||||
&& isBlank(param.getInfoType())
|
||||
&& isBlank(param.getAddress())
|
||||
&& isBlank(param.getProcurementName())
|
||||
&& isBlank(param.getWinningName())
|
||||
&& isBlank(param.getWinningPrice());
|
||||
}
|
||||
|
||||
private boolean isBlank(String value) {
|
||||
return value == null || value.trim().isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将CreditUserImportParam转换为CreditUser实体
|
||||
*/
|
||||
private CreditUser convertImportParamToEntity(CreditUserImportParam param) {
|
||||
CreditUser entity = new CreditUser();
|
||||
|
||||
entity.setCode(param.getCode());
|
||||
entity.setName(param.getName());
|
||||
entity.setReleaseDate(param.getReleaseDate());
|
||||
entity.setType(param.getType());
|
||||
entity.setRole(param.getRole());
|
||||
entity.setInfoType(param.getInfoType());
|
||||
entity.setAddress(param.getAddress());
|
||||
entity.setPlaintiffAppellant(param.getPlaintiffAppellant());
|
||||
entity.setProcurementName(param.getProcurementName());
|
||||
entity.setWinningName(param.getWinningName());
|
||||
entity.setWinningPrice(param.getWinningPrice());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,510 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import com.gxwebsoft.common.core.annotation.OperationLog;
|
||||
import com.gxwebsoft.common.core.web.ApiResult;
|
||||
import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.common.core.web.BatchParam;
|
||||
import com.gxwebsoft.common.core.web.PageResult;
|
||||
import com.gxwebsoft.common.system.entity.User;
|
||||
import com.gxwebsoft.credit.entity.CreditXgxf;
|
||||
import com.gxwebsoft.credit.param.CreditXgxfImportParam;
|
||||
import com.gxwebsoft.credit.param.CreditXgxfParam;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyService;
|
||||
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
|
||||
import com.gxwebsoft.credit.service.CreditXgxfService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 限制高消费控制器
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:51:55
|
||||
*/
|
||||
@Tag(name = "限制高消费管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/credit/credit-xgxf")
|
||||
public class CreditXgxfController extends BaseController {
|
||||
@Resource
|
||||
private CreditXgxfService creditXgxfService;
|
||||
|
||||
@Resource
|
||||
private BatchImportSupport batchImportSupport;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyService creditCompanyService;
|
||||
|
||||
@Resource
|
||||
private CreditCompanyRecordCountService creditCompanyRecordCountService;
|
||||
|
||||
@Operation(summary = "分页查询限制高消费")
|
||||
@GetMapping("/page")
|
||||
public ApiResult<PageResult<CreditXgxf>> page(CreditXgxfParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditXgxfService.pageRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "查询全部限制高消费")
|
||||
@GetMapping()
|
||||
public ApiResult<List<CreditXgxf>> list(CreditXgxfParam param) {
|
||||
// 使用关联查询
|
||||
return success(creditXgxfService.listRel(param));
|
||||
}
|
||||
|
||||
@Operation(summary = "根据id查询限制高消费")
|
||||
@GetMapping("/{id}")
|
||||
public ApiResult<CreditXgxf> get(@PathVariable("id") Integer id) {
|
||||
// 使用关联查询
|
||||
return success(creditXgxfService.getByIdRel(id));
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditXgxf:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "添加限制高消费")
|
||||
@PostMapping()
|
||||
public ApiResult<?> save(@RequestBody CreditXgxf creditXgxf) {
|
||||
// 记录当前登录用户id
|
||||
// User loginUser = getLoginUser();
|
||||
// if (loginUser != null) {
|
||||
// creditXgxf.setUserId(loginUser.getUserId());
|
||||
// }
|
||||
if (creditXgxfService.save(creditXgxf)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditXgxf:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "修改限制高消费")
|
||||
@PutMapping()
|
||||
public ApiResult<?> update(@RequestBody CreditXgxf creditXgxf) {
|
||||
if (creditXgxfService.updateById(creditXgxf)) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditXgxf:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "删除限制高消费")
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||
if (batchImportSupport.hardRemoveById(CreditXgxf.class, id)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditXgxf:save')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量添加限制高消费")
|
||||
@PostMapping("/batch")
|
||||
public ApiResult<?> saveBatch(@RequestBody List<CreditXgxf> list) {
|
||||
if (creditXgxfService.saveBatch(list)) {
|
||||
return success("添加成功");
|
||||
}
|
||||
return fail("添加失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditXgxf:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量修改限制高消费")
|
||||
@PutMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditXgxf> batchParam) {
|
||||
if (batchParam.update(creditXgxfService, "id")) {
|
||||
return success("修改成功");
|
||||
}
|
||||
return fail("修改失败");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAuthority('credit:creditXgxf:remove')")
|
||||
@OperationLog
|
||||
@Operation(summary = "批量删除限制高消费")
|
||||
@DeleteMapping("/batch")
|
||||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||
if (batchImportSupport.hardRemoveByIds(CreditXgxf.class, ids)) {
|
||||
return success("删除成功");
|
||||
}
|
||||
return fail("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据企业名称匹配企业并更新 companyId(匹配 CreditCompany.name / CreditCompany.matchName)
|
||||
*
|
||||
* <p>默认仅更新 companyId=0 的记录;如需覆盖更新,传 onlyNull=false。</p>
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditXgxf:update')")
|
||||
@OperationLog
|
||||
@Operation(summary = "根据企业名称匹配并更新companyId")
|
||||
@PostMapping("/company-id/refresh")
|
||||
public ApiResult<Map<String, Object>> refreshCompanyIdByCompanyName(
|
||||
@RequestParam(value = "onlyNull", required = false, defaultValue = "true") Boolean onlyNull,
|
||||
@RequestParam(value = "limit", required = false) Integer limit
|
||||
) {
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
|
||||
// Party columns may contain multiple roles/names; match if any company name is contained in the text.
|
||||
// Priority: 原告/上诉人 > 被告/被上诉人 > 其他当事人/第三人
|
||||
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyNameContainedInText(
|
||||
creditXgxfService,
|
||||
creditCompanyService,
|
||||
currentTenantId,
|
||||
onlyNull,
|
||||
limit,
|
||||
CreditXgxf::getId,
|
||||
CreditXgxf::setId,
|
||||
CreditXgxf::getCompanyId,
|
||||
CreditXgxf::setCompanyId,
|
||||
CreditXgxf::getHasData,
|
||||
CreditXgxf::setHasData,
|
||||
CreditXgxf::getTenantId,
|
||||
CreditXgxf::new,
|
||||
CreditXgxf::getPlaintiffAppellant,
|
||||
CreditXgxf::getAppellee,
|
||||
CreditXgxf::getOtherPartiesThirdParty
|
||||
);
|
||||
|
||||
if (!stats.anyDataRead) {
|
||||
return success("无可更新数据", stats.toMap());
|
||||
}
|
||||
return success("更新完成,更新" + stats.updated + "条", stats.toMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入限制高消费司法大数据
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditXgxf:save')")
|
||||
@Operation(summary = "批量导入限制高消费司法大数据")
|
||||
@PostMapping("/import")
|
||||
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "限制高消费", 0);
|
||||
ExcelImportSupport.ImportResult<CreditXgxfImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditXgxfImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditXgxfImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
// easypoi 默认不会读取单元格超链接地址;url 可能挂在“案号”等列的超链接中,或单独提供 url/网址/链接 列。
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditXgxf> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditXgxfImportParam param = list.get(i);
|
||||
try {
|
||||
CreditXgxf item = convertImportParamToEntity(param);
|
||||
if (!ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
String link = urlByCaseNumber.get(item.getCaseNumber().trim());
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditXgxfService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditXgxf::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditXgxfService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditXgxf::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.XGXF, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
} else {
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入历史限制高消费(仅解析“历史限制高消费”选项卡)
|
||||
* 规则:使用数据库唯一索引约束,重复数据不导入。
|
||||
*/
|
||||
@PreAuthorize("hasAuthority('credit:creditXgxf:save')")
|
||||
@Operation(summary = "批量导入历史限制高消费司法大数据")
|
||||
@PostMapping("/import/history")
|
||||
public ApiResult<List<String>> importHistoryBatch(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "companyId", required = false) Integer companyId) {
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
int successCount = 0;
|
||||
Set<Integer> touchedCompanyIds = new HashSet<>();
|
||||
|
||||
try {
|
||||
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "历史限制高消费");
|
||||
if (sheetIndex < 0) {
|
||||
return fail("未读取到数据,请确认文件中存在“历史限制高消费”选项卡且表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
ExcelImportSupport.ImportResult<CreditXgxfImportParam> importResult = ExcelImportSupport.read(
|
||||
file, CreditXgxfImportParam.class, this::isEmptyImportRow, sheetIndex);
|
||||
List<CreditXgxfImportParam> list = importResult.getData();
|
||||
int usedTitleRows = importResult.getTitleRows();
|
||||
int usedHeadRows = importResult.getHeadRows();
|
||||
int usedSheetIndex = importResult.getSheetIndex();
|
||||
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
|
||||
}
|
||||
|
||||
User loginUser = getLoginUser();
|
||||
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
|
||||
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
|
||||
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
|
||||
|
||||
final int chunkSize = 500;
|
||||
final int mpBatchSize = 500;
|
||||
List<CreditXgxf> chunkItems = new ArrayList<>(chunkSize);
|
||||
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
CreditXgxfImportParam param = list.get(i);
|
||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||
try {
|
||||
CreditXgxf item = convertImportParamToEntity(param);
|
||||
if (item.getCaseNumber() != null) {
|
||||
item.setCaseNumber(item.getCaseNumber().trim());
|
||||
}
|
||||
if (ImportHelper.isBlank(item.getCaseNumber())) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:案号不能为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
String link = urlByCaseNumber.get(item.getCaseNumber());
|
||||
if (!ImportHelper.isBlank(link)) {
|
||||
item.setUrl(link.trim());
|
||||
}
|
||||
|
||||
if (item.getCompanyId() == null && companyId != null) {
|
||||
item.setCompanyId(companyId);
|
||||
}
|
||||
if (item.getUserId() == null && currentUserId != null) {
|
||||
item.setUserId(currentUserId);
|
||||
}
|
||||
if (item.getTenantId() == null && currentTenantId != null) {
|
||||
item.setTenantId(currentTenantId);
|
||||
}
|
||||
if (item.getStatus() == null) {
|
||||
item.setStatus(0);
|
||||
}
|
||||
if (item.getDeleted() == null) {
|
||||
item.setDeleted(0);
|
||||
}
|
||||
// 历史导入的数据统一标记为“失效”
|
||||
item.setDataStatus("失效");
|
||||
|
||||
if (item.getRecommend() == null) {
|
||||
item.setRecommend(0);
|
||||
}
|
||||
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
|
||||
touchedCompanyIds.add(item.getCompanyId());
|
||||
}
|
||||
|
||||
chunkItems.add(item);
|
||||
chunkRowNumbers.add(excelRowNumber);
|
||||
if (chunkItems.size() >= chunkSize) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditXgxfService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditXgxf::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
chunkItems.clear();
|
||||
chunkRowNumbers.clear();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!chunkItems.isEmpty()) {
|
||||
successCount += batchImportSupport.persistInsertOnlyChunk(
|
||||
creditXgxfService,
|
||||
chunkItems,
|
||||
chunkRowNumbers,
|
||||
mpBatchSize,
|
||||
CreditXgxf::getCaseNumber,
|
||||
"",
|
||||
errorMessages
|
||||
);
|
||||
}
|
||||
|
||||
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.XGXF, touchedCompanyIds);
|
||||
|
||||
if (errorMessages.isEmpty()) {
|
||||
return success("成功导入" + successCount + "条数据", null);
|
||||
}
|
||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return fail("导入失败:" + e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载限制高消费导入模板
|
||||
*/
|
||||
@Operation(summary = "下载限制高消费导入模板")
|
||||
@GetMapping("/import/template")
|
||||
public void downloadTemplate(HttpServletResponse response) throws IOException {
|
||||
List<CreditXgxfImportParam> templateList = new ArrayList<>();
|
||||
|
||||
CreditXgxfImportParam example = new CreditXgxfImportParam();
|
||||
example.setDataType("限制高消费");
|
||||
example.setPlaintiffAppellant("原告示例");
|
||||
example.setAppellee("被告示例");
|
||||
example.setOccurrenceTime("2024-01-01");
|
||||
example.setCaseNumber("(2024)示例案号");
|
||||
example.setInvolvedAmount("100000");
|
||||
example.setCourtName("示例法院");
|
||||
example.setComments("备注信息");
|
||||
templateList.add(example);
|
||||
|
||||
Workbook workbook = ExcelImportSupport.buildTemplate("限制高消费导入模板", "限制高消费", CreditXgxfImportParam.class, templateList);
|
||||
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=credit_xgxf_import_template.xlsx");
|
||||
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(CreditXgxfImportParam param) {
|
||||
if (param == null) {
|
||||
return true;
|
||||
}
|
||||
return ImportHelper.isBlank(param.getCaseNumber());
|
||||
}
|
||||
|
||||
private CreditXgxf convertImportParamToEntity(CreditXgxfImportParam param) {
|
||||
CreditXgxf entity = new CreditXgxf();
|
||||
|
||||
// Template compatibility: some upstream multi-company exports use alternate headers for the same columns.
|
||||
String plaintiffAppellant = !ImportHelper.isBlank(param.getPlaintiffAppellant())
|
||||
? param.getPlaintiffAppellant()
|
||||
: param.getPlaintiffAppellant2();
|
||||
String appellee = !ImportHelper.isBlank(param.getAppellee())
|
||||
? param.getAppellee()
|
||||
: param.getDataType();
|
||||
String courtName = !ImportHelper.isBlank(param.getCourtName())
|
||||
? param.getCourtName()
|
||||
: param.getCourtName2();
|
||||
|
||||
|
||||
entity.setCaseNumber(param.getCaseNumber());
|
||||
entity.setType(param.getType());
|
||||
entity.setDataType(param.getDataType());
|
||||
entity.setPlaintiffAppellant(plaintiffAppellant);
|
||||
entity.setAppellee(appellee);
|
||||
entity.setOtherPartiesThirdParty(param.getOtherPartiesThirdParty());
|
||||
entity.setDataStatus(param.getDataStatus());
|
||||
|
||||
entity.setInvolvedAmount(param.getInvolvedAmount());
|
||||
entity.setOccurrenceTime(param.getOccurrenceTime());
|
||||
entity.setCourtName(courtName);
|
||||
entity.setReleaseDate(param.getReleaseDate());
|
||||
entity.setComments(param.getComments());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,719 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import cn.afterturn.easypoi.excel.ExcelExportUtil;
|
||||
import cn.afterturn.easypoi.excel.ExcelImportUtil;
|
||||
import cn.afterturn.easypoi.excel.annotation.Excel;
|
||||
import cn.afterturn.easypoi.excel.entity.ExportParams;
|
||||
import cn.afterturn.easypoi.excel.entity.ImportParams;
|
||||
import com.gxwebsoft.credit.excel.ExcelHeaderAlias;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellType;
|
||||
import org.apache.poi.ss.usermodel.DataFormatter;
|
||||
import org.apache.poi.ss.usermodel.Hyperlink;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.ss.usermodel.WorkbookFactory;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Excel 导入导出通用支持
|
||||
*/
|
||||
public class ExcelImportSupport {
|
||||
|
||||
public static class ImportResult<T> {
|
||||
private final List<T> data;
|
||||
private final int titleRows;
|
||||
private final int headRows;
|
||||
private final int sheetIndex;
|
||||
|
||||
public ImportResult(List<T> data, int titleRows, int headRows) {
|
||||
this(data, titleRows, headRows, 0);
|
||||
}
|
||||
|
||||
public ImportResult(List<T> data, int titleRows, int headRows, int sheetIndex) {
|
||||
this.data = data;
|
||||
this.titleRows = titleRows;
|
||||
this.headRows = headRows;
|
||||
this.sheetIndex = sheetIndex;
|
||||
}
|
||||
|
||||
public List<T> getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public int getTitleRows() {
|
||||
return titleRows;
|
||||
}
|
||||
|
||||
public int getHeadRows() {
|
||||
return headRows;
|
||||
}
|
||||
|
||||
public int getSheetIndex() {
|
||||
return sheetIndex;
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> ImportResult<T> read(MultipartFile file, Class<T> clazz, Predicate<T> emptyRowPredicate) throws Exception {
|
||||
return read(file, clazz, emptyRowPredicate, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动尝试所有 sheet(从第 0 个开始),直到读取到非空数据。
|
||||
*/
|
||||
public static <T> ImportResult<T> readAnySheet(MultipartFile file, Class<T> clazz, Predicate<T> emptyRowPredicate) throws Exception {
|
||||
ImportResult<T> result = read(file, clazz, emptyRowPredicate, 0);
|
||||
if (!CollectionUtils.isEmpty(result.getData())) {
|
||||
return result;
|
||||
}
|
||||
|
||||
int sheetCount = getSheetCount(file);
|
||||
for (int i = 1; i < sheetCount; i++) {
|
||||
ImportResult<T> sheetResult = read(file, clazz, emptyRowPredicate, i);
|
||||
if (!CollectionUtils.isEmpty(sheetResult.getData())) {
|
||||
return sheetResult;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动尝试所有 sheet(从第 0 个开始),并在每个 sheet 内选择“得分”最高的表头配置。
|
||||
*/
|
||||
public static <T> ImportResult<T> readAnySheetBest(MultipartFile file, Class<T> clazz, Predicate<T> emptyRowPredicate, Predicate<T> scoreRowPredicate) throws Exception {
|
||||
ImportResult<T> result = readBest(file, clazz, emptyRowPredicate, scoreRowPredicate, 0);
|
||||
if (!CollectionUtils.isEmpty(result.getData())) {
|
||||
return result;
|
||||
}
|
||||
|
||||
int sheetCount = getSheetCount(file);
|
||||
for (int i = 1; i < sheetCount; i++) {
|
||||
ImportResult<T> sheetResult = readBest(file, clazz, emptyRowPredicate, scoreRowPredicate, i);
|
||||
if (!CollectionUtils.isEmpty(sheetResult.getData())) {
|
||||
return sheetResult;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取指定 sheet 的 Excel。
|
||||
*
|
||||
* @param sheetIndex 目标 sheet 下标,从 0 开始。第二个选项卡传 1。
|
||||
*/
|
||||
public static <T> ImportResult<T> read(MultipartFile file, Class<T> clazz, Predicate<T> emptyRowPredicate, int sheetIndex) throws Exception {
|
||||
List<T> list = null;
|
||||
int usedTitleRows = 0;
|
||||
int usedHeadRows = 0;
|
||||
int[][] tryConfigs = new int[][]{{1, 1}, {0, 1}, {2, 1}, {3, 1}, {0, 2}, {0, 3}, {0, 4}};
|
||||
Exception lastFailure = null;
|
||||
boolean anyImported = false;
|
||||
|
||||
for (int[] config : tryConfigs) {
|
||||
try {
|
||||
list = filterEmptyRows(importSheet(file, clazz, config[0], config[1], sheetIndex), emptyRowPredicate);
|
||||
anyImported = true;
|
||||
} catch (Exception e) {
|
||||
// Some source files can trigger easypoi/POI runtime exceptions for certain title/head row combinations.
|
||||
// Keep trying other configurations instead of failing the whole import.
|
||||
lastFailure = e;
|
||||
continue;
|
||||
}
|
||||
if (!CollectionUtils.isEmpty(list)) {
|
||||
usedTitleRows = config[0];
|
||||
usedHeadRows = config[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback for upstream files with extra banner/title rows or wider multi-row headers.
|
||||
// Keep the default fast path above for common templates.
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
final int maxTitleRows = 10;
|
||||
final int maxHeadRows = 6;
|
||||
outer:
|
||||
for (int titleRows = 0; titleRows <= maxTitleRows; titleRows++) {
|
||||
for (int headRows = 1; headRows <= maxHeadRows; headRows++) {
|
||||
try {
|
||||
list = filterEmptyRows(importSheet(file, clazz, titleRows, headRows, sheetIndex), emptyRowPredicate);
|
||||
anyImported = true;
|
||||
} catch (Exception e) {
|
||||
lastFailure = e;
|
||||
continue;
|
||||
}
|
||||
if (!CollectionUtils.isEmpty(list)) {
|
||||
usedTitleRows = titleRows;
|
||||
usedHeadRows = headRows;
|
||||
break outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (list == null) {
|
||||
if (!anyImported && lastFailure != null) {
|
||||
throw lastFailure;
|
||||
}
|
||||
list = Collections.emptyList();
|
||||
}
|
||||
return new ImportResult<>(list, usedTitleRows, usedHeadRows, sheetIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取指定 sheet 的 Excel,并从多组表头配置中挑选“得分”最高的结果。
|
||||
*/
|
||||
public static <T> ImportResult<T> readBest(MultipartFile file, Class<T> clazz, Predicate<T> emptyRowPredicate, Predicate<T> scoreRowPredicate, int sheetIndex) throws Exception {
|
||||
List<T> bestList = null;
|
||||
int bestTitleRows = 0;
|
||||
int bestHeadRows = 0;
|
||||
int bestScore = -1;
|
||||
int bestSize = -1;
|
||||
Exception lastFailure = null;
|
||||
boolean anyImported = false;
|
||||
|
||||
int[][] tryConfigs = new int[][]{{1, 1}, {0, 1}, {2, 1}, {3, 1}, {0, 2}, {0, 3}, {0, 4}, {1, 2}, {1, 3}, {1, 4}, {2, 2}, {2, 3}, {2, 4}, {3, 2}, {3, 3}, {3, 4}};
|
||||
|
||||
for (int[] config : tryConfigs) {
|
||||
List<T> list;
|
||||
try {
|
||||
list = filterEmptyRows(importSheet(file, clazz, config[0], config[1], sheetIndex), emptyRowPredicate);
|
||||
anyImported = true;
|
||||
} catch (Exception e) {
|
||||
lastFailure = e;
|
||||
continue;
|
||||
}
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int score = 0;
|
||||
if (scoreRowPredicate != null) {
|
||||
for (T row : list) {
|
||||
if (scoreRowPredicate.test(row)) {
|
||||
score++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int size = list.size();
|
||||
if (score > bestScore || (score == bestScore && size > bestSize)) {
|
||||
bestList = list;
|
||||
bestTitleRows = config[0];
|
||||
bestHeadRows = config[1];
|
||||
bestScore = score;
|
||||
bestSize = size;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback scan: broaden the search space for messy source files (extra title rows, multi-row headers).
|
||||
if (bestList == null) {
|
||||
final int maxTitleRows = 10;
|
||||
final int maxHeadRows = 6;
|
||||
for (int titleRows = 0; titleRows <= maxTitleRows; titleRows++) {
|
||||
for (int headRows = 1; headRows <= maxHeadRows; headRows++) {
|
||||
List<T> list;
|
||||
try {
|
||||
list = filterEmptyRows(importSheet(file, clazz, titleRows, headRows, sheetIndex), emptyRowPredicate);
|
||||
anyImported = true;
|
||||
} catch (Exception e) {
|
||||
lastFailure = e;
|
||||
continue;
|
||||
}
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int score = 0;
|
||||
if (scoreRowPredicate != null) {
|
||||
for (T row : list) {
|
||||
if (scoreRowPredicate.test(row)) {
|
||||
score++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int size = list.size();
|
||||
if (score > bestScore || (score == bestScore && size > bestSize)) {
|
||||
bestList = list;
|
||||
bestTitleRows = titleRows;
|
||||
bestHeadRows = headRows;
|
||||
bestScore = score;
|
||||
bestSize = size;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bestList != null) {
|
||||
return new ImportResult<>(bestList, bestTitleRows, bestHeadRows, sheetIndex);
|
||||
}
|
||||
|
||||
if (!anyImported && lastFailure != null) {
|
||||
throw lastFailure;
|
||||
}
|
||||
return read(file, clazz, emptyRowPredicate, sheetIndex);
|
||||
}
|
||||
|
||||
private static <T> List<T> importSheet(MultipartFile file, Class<T> clazz, int titleRows, int headRows, int sheetIndex) throws Exception {
|
||||
ImportParams importParams = new ImportParams();
|
||||
importParams.setTitleRows(titleRows);
|
||||
importParams.setHeadRows(headRows);
|
||||
importParams.setStartSheetIndex(sheetIndex);
|
||||
importParams.setSheetNum(1);
|
||||
|
||||
// Easypoi matches headers by exact string. Some upstream files contain extra spaces/tabs/newlines in header cells
|
||||
// (e.g. "原告 / 上诉人" or "原告/上诉人\t"), which makes specific columns silently not mapped.
|
||||
// Normalize header cells first to make imports robust.
|
||||
try (InputStream is = file.getInputStream(); Workbook workbook = WorkbookFactory.create(is)) {
|
||||
if (workbook.getNumberOfSheets() > sheetIndex) {
|
||||
Sheet sheet = workbook.getSheetAt(sheetIndex);
|
||||
if (sheet != null) {
|
||||
normalizeHeaderCells(sheet, titleRows, headRows, clazz);
|
||||
}
|
||||
}
|
||||
try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
|
||||
workbook.write(bos);
|
||||
try (ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray())) {
|
||||
return ExcelImportUtil.importExcel(bis, clazz, importParams);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void normalizeHeaderCells(Sheet sheet, int titleRows, int headRows, Class<?> clazz) {
|
||||
if (sheet == null || headRows <= 0) {
|
||||
return;
|
||||
}
|
||||
Map<String, String> expectedHeadersByKey = buildExpectedHeaderKeyMap(clazz);
|
||||
if (expectedHeadersByKey.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
int headerStart = Math.max(titleRows, 0);
|
||||
int headerEnd = headerStart + headRows - 1;
|
||||
for (int r = headerStart; r <= headerEnd; r++) {
|
||||
Row row = sheet.getRow(r);
|
||||
if (row == null) {
|
||||
continue;
|
||||
}
|
||||
short last = row.getLastCellNum();
|
||||
for (int c = 0; c < last; c++) {
|
||||
Cell cell = row.getCell(c);
|
||||
if (cell == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String text = null;
|
||||
CellType type = cell.getCellType();
|
||||
if (type == CellType.STRING) {
|
||||
text = cell.getStringCellValue();
|
||||
} else if (type == CellType.FORMULA && cell.getCachedFormulaResultType() == CellType.STRING) {
|
||||
text = cell.getStringCellValue();
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
String canonical = findCanonicalHeader(text, expectedHeadersByKey);
|
||||
if (canonical != null && !canonical.equals(text)) {
|
||||
cell.setCellValue(canonical);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Map<String, String> buildExpectedHeaderKeyMap(Class<?> clazz) {
|
||||
if (clazz == null) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
Map<String, String> map = new HashMap<>();
|
||||
Class<?> current = clazz;
|
||||
while (current != null && current != Object.class) {
|
||||
Field[] fields = current.getDeclaredFields();
|
||||
for (Field field : fields) {
|
||||
Excel excel = field.getAnnotation(Excel.class);
|
||||
if (excel == null) {
|
||||
continue;
|
||||
}
|
||||
String name = excel.name();
|
||||
if (name == null || name.trim().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
String key = normalizeHeaderKey(name);
|
||||
if (!key.isEmpty()) {
|
||||
// key -> canonical annotation name
|
||||
map.putIfAbsent(key, name);
|
||||
}
|
||||
|
||||
// Allow import-time header aliases without changing the exported template header.
|
||||
ExcelHeaderAlias alias = field.getAnnotation(ExcelHeaderAlias.class);
|
||||
if (alias != null && alias.value() != null) {
|
||||
for (String aliasName : alias.value()) {
|
||||
if (aliasName == null || aliasName.trim().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
String aliasKey = normalizeHeaderKey(aliasName);
|
||||
if (!aliasKey.isEmpty()) {
|
||||
map.putIfAbsent(aliasKey, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
current = current.getSuperclass();
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private static String findCanonicalHeader(String rawHeaderText, Map<String, String> expectedHeadersByKey) {
|
||||
if (rawHeaderText == null) {
|
||||
return null;
|
||||
}
|
||||
String key = normalizeHeaderKey(rawHeaderText);
|
||||
if (key.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String canonical = expectedHeadersByKey.get(key);
|
||||
if (canonical != null) {
|
||||
return canonical;
|
||||
}
|
||||
|
||||
// Some upstream templates append explanations in brackets, e.g. "原告/上诉人(申请执行人)".
|
||||
// Only strip trailing bracket groups when the full header doesn't match any known expected header.
|
||||
String strippedKey = stripTrailingBracketSuffix(key);
|
||||
if (!strippedKey.equals(key)) {
|
||||
canonical = expectedHeadersByKey.get(strippedKey);
|
||||
if (canonical != null) {
|
||||
return canonical;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize header text for matching purposes only.
|
||||
*
|
||||
* <p>Do NOT drop bracket content (e.g. keep "(元)" or "(公告)" in the middle), because many templates use them as
|
||||
* part of the canonical header name. We only remove whitespace and unify common full-width punctuation.</p>
|
||||
*/
|
||||
private static String normalizeHeaderKey(String text) {
|
||||
if (text == null) {
|
||||
return "";
|
||||
}
|
||||
String normalized = text
|
||||
// unify common full-width punctuation
|
||||
.replace("/", "/")
|
||||
.replace("【", "[")
|
||||
.replace("】", "]")
|
||||
// remove common invisible whitespace characters, including full-width space.
|
||||
.replace(" ", "")
|
||||
.replace("\t", "")
|
||||
.replace("\r", "")
|
||||
.replace("\n", "")
|
||||
.replace("\u00A0", "")
|
||||
.replace(" ", "")
|
||||
.trim();
|
||||
|
||||
// Make ( ) and ( ) comparable by normalizing both to ASCII.
|
||||
normalized = normalized.replace('(', '(').replace(')', ')');
|
||||
return normalized;
|
||||
}
|
||||
|
||||
private static String stripTrailingBracketSuffix(String text) {
|
||||
if (text == null) {
|
||||
return "";
|
||||
}
|
||||
String s = text.trim();
|
||||
while (true) {
|
||||
if (s.endsWith(")")) {
|
||||
int idx = s.lastIndexOf('(');
|
||||
if (idx >= 0) {
|
||||
s = s.substring(0, idx).trim();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (s.endsWith("]")) {
|
||||
int idx = s.lastIndexOf('[');
|
||||
if (idx >= 0) {
|
||||
s = s.substring(0, idx).trim();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> List<T> filterEmptyRows(List<T> rawList, Predicate<T> emptyRowPredicate) {
|
||||
if (CollectionUtils.isEmpty(rawList)) {
|
||||
return rawList;
|
||||
}
|
||||
rawList.removeIf(emptyRowPredicate);
|
||||
return rawList;
|
||||
}
|
||||
|
||||
private static int getSheetCount(MultipartFile file) throws Exception {
|
||||
try (InputStream is = file.getInputStream(); Workbook workbook = WorkbookFactory.create(is)) {
|
||||
return workbook.getNumberOfSheets();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 sheet 名称查找下标(优先精确匹配,其次前缀匹配/包含匹配)。
|
||||
*
|
||||
* @return 找不到返回 -1
|
||||
*/
|
||||
public static int findSheetIndex(MultipartFile file, String sheetName) throws Exception {
|
||||
if (file == null || sheetName == null || sheetName.trim().isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
String target = normalizeSheetName(sheetName);
|
||||
if (target.isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
try (InputStream is = file.getInputStream(); Workbook workbook = WorkbookFactory.create(is)) {
|
||||
int sheetCount = workbook.getNumberOfSheets();
|
||||
for (int i = 0; i < sheetCount; i++) {
|
||||
String candidate = normalizeSheetName(workbook.getSheetName(i));
|
||||
if (Objects.equals(candidate, target)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < sheetCount; i++) {
|
||||
String candidate = normalizeSheetName(workbook.getSheetName(i));
|
||||
if (candidate.startsWith(target) || candidate.contains(target) || target.startsWith(candidate)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static int findSheetIndex(MultipartFile file, String sheetName, int defaultIndex) throws Exception {
|
||||
int idx = findSheetIndex(file, sheetName);
|
||||
return idx >= 0 ? idx : defaultIndex;
|
||||
}
|
||||
|
||||
private static String normalizeSheetName(String sheetName) {
|
||||
if (sheetName == null) {
|
||||
return "";
|
||||
}
|
||||
return sheetName.replace(" ", "").replace(" ", "").trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取指定列(由表头名定位)的超链接,返回:单元格显示值 -> 超链接地址。
|
||||
*
|
||||
* <p>适用于:导入对象没有 url 字段,但 Excel 把链接放在某个“名称/案号”等列的超链接里。</p>
|
||||
*/
|
||||
public static Map<String, String> readHyperlinksByHeaderKey(MultipartFile file, int sheetIndex, int titleRows, int headRows, String headerName) throws Exception {
|
||||
if (file == null || headerName == null || headerName.trim().isEmpty()) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
try (InputStream is = file.getInputStream(); Workbook workbook = WorkbookFactory.create(is)) {
|
||||
if (workbook.getNumberOfSheets() <= sheetIndex) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
Sheet sheet = workbook.getSheetAt(sheetIndex);
|
||||
if (sheet == null) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
int colIndex = findColumnIndexByHeader(sheet, titleRows, headRows, headerName);
|
||||
if (colIndex < 0) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
Map<String, String> result = new HashMap<>();
|
||||
DataFormatter formatter = new DataFormatter();
|
||||
int dataStartRow = titleRows + headRows;
|
||||
for (int r = dataStartRow; r <= sheet.getLastRowNum(); r++) {
|
||||
Row row = sheet.getRow(r);
|
||||
if (row == null) {
|
||||
continue;
|
||||
}
|
||||
Cell cell = row.getCell(colIndex);
|
||||
if (cell == null) {
|
||||
continue;
|
||||
}
|
||||
String address = extractHyperlinkAddress(cell);
|
||||
if (address == null || address.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
String key = formatter.formatCellValue(cell);
|
||||
if (key == null || key.trim().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
result.put(key.trim(), address);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取两列(由表头名定位)的文本/超链接,返回:key列显示值 -> value列(优先超链接地址,其次单元格文本)。
|
||||
*
|
||||
* <p>适用于:Excel 把 url 放在单独一列(可能是纯文本,也可能是超链接)。</p>
|
||||
*/
|
||||
public static Map<String, String> readKeyValueByHeaders(MultipartFile file,
|
||||
int sheetIndex,
|
||||
int titleRows,
|
||||
int headRows,
|
||||
String keyHeaderName,
|
||||
String valueHeaderName) throws Exception {
|
||||
if (file == null
|
||||
|| keyHeaderName == null || keyHeaderName.trim().isEmpty()
|
||||
|| valueHeaderName == null || valueHeaderName.trim().isEmpty()) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
try (InputStream is = file.getInputStream(); Workbook workbook = WorkbookFactory.create(is)) {
|
||||
if (workbook.getNumberOfSheets() <= sheetIndex) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
Sheet sheet = workbook.getSheetAt(sheetIndex);
|
||||
if (sheet == null) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
int keyCol = findColumnIndexByHeader(sheet, titleRows, headRows, keyHeaderName);
|
||||
int valCol = findColumnIndexByHeader(sheet, titleRows, headRows, valueHeaderName);
|
||||
if (keyCol < 0 || valCol < 0) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
Map<String, String> result = new HashMap<>();
|
||||
DataFormatter formatter = new DataFormatter();
|
||||
int dataStartRow = titleRows + headRows;
|
||||
for (int r = dataStartRow; r <= sheet.getLastRowNum(); r++) {
|
||||
Row row = sheet.getRow(r);
|
||||
if (row == null) {
|
||||
continue;
|
||||
}
|
||||
Cell keyCell = row.getCell(keyCol);
|
||||
if (keyCell == null) {
|
||||
continue;
|
||||
}
|
||||
String key = formatter.formatCellValue(keyCell);
|
||||
if (key == null || key.trim().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Cell valCell = row.getCell(valCol);
|
||||
if (valCell == null) {
|
||||
continue;
|
||||
}
|
||||
String value = extractHyperlinkAddress(valCell);
|
||||
if (value == null || value.trim().isEmpty()) {
|
||||
value = formatter.formatCellValue(valCell);
|
||||
}
|
||||
if (value == null || value.trim().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
result.put(key.trim(), value.trim());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取“key列 -> url”的映射:
|
||||
* - 优先读取 key 列自身的超链接(url 常挂在名称/案号等列的超链接里)
|
||||
* - 如果源文件提供独立的 url/URL/网址/链接/链接地址 等列,则读取该列(支持文本或超链接)
|
||||
*/
|
||||
public static Map<String, String> readUrlByKey(MultipartFile file,
|
||||
int sheetIndex,
|
||||
int titleRows,
|
||||
int headRows,
|
||||
String keyHeaderName) throws Exception {
|
||||
if (file == null || keyHeaderName == null || keyHeaderName.trim().isEmpty()) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
Map<String, String> result = new HashMap<>();
|
||||
|
||||
// 1) url 挂在 key 列超链接里(最常见)
|
||||
Map<String, String> fromKeyHyperlinks = readHyperlinksByHeaderKey(file, sheetIndex, titleRows, headRows, keyHeaderName);
|
||||
if (!fromKeyHyperlinks.isEmpty()) {
|
||||
result.putAll(fromKeyHyperlinks);
|
||||
}
|
||||
|
||||
// 2) url 作为单独一列(多种表头命名)
|
||||
String[] urlHeaders = new String[]{"url", "URL", "网址", "链接", "链接地址"};
|
||||
for (String urlHeader : urlHeaders) {
|
||||
Map<String, String> fromUrlCol = readKeyValueByHeaders(file, sheetIndex, titleRows, headRows, keyHeaderName, urlHeader);
|
||||
if (fromUrlCol.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
for (Map.Entry<String, String> entry : fromUrlCol.entrySet()) {
|
||||
// 不覆盖已从 key 超链接读取到的地址
|
||||
result.putIfAbsent(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static int findColumnIndexByHeader(Sheet sheet, int titleRows, int headRows, String headerName) {
|
||||
String targetKey = normalizeHeaderKey(headerName);
|
||||
if (targetKey.isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
int firstHeaderRow = Math.max(0, titleRows);
|
||||
int lastHeaderRow = Math.max(0, titleRows + headRows - 1);
|
||||
for (int r = firstHeaderRow; r <= lastHeaderRow; r++) {
|
||||
Row row = sheet.getRow(r);
|
||||
if (row == null) {
|
||||
continue;
|
||||
}
|
||||
for (int c = row.getFirstCellNum(); c < row.getLastCellNum(); c++) {
|
||||
Cell cell = row.getCell(c);
|
||||
if (cell == null) {
|
||||
continue;
|
||||
}
|
||||
DataFormatter formatter = new DataFormatter();
|
||||
String value = formatter.formatCellValue(cell);
|
||||
if (targetKey.equals(normalizeHeaderKey(value))) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static String extractHyperlinkAddress(Cell cell) {
|
||||
Hyperlink hyperlink = cell.getHyperlink();
|
||||
if (hyperlink != null && hyperlink.getAddress() != null && !hyperlink.getAddress().isEmpty()) {
|
||||
return hyperlink.getAddress();
|
||||
}
|
||||
if (cell.getCellType() == CellType.FORMULA) {
|
||||
String formula = cell.getCellFormula();
|
||||
if (formula != null && formula.toUpperCase().startsWith("HYPERLINK(")) {
|
||||
int firstQuote = formula.indexOf('\"');
|
||||
if (firstQuote >= 0) {
|
||||
int secondQuote = formula.indexOf('\"', firstQuote + 1);
|
||||
if (secondQuote > firstQuote) {
|
||||
return formula.substring(firstQuote + 1, secondQuote);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T> Workbook buildTemplate(String title, String sheetName, Class<T> clazz, List<T> examples) {
|
||||
ExportParams exportParams = new ExportParams(title, sheetName);
|
||||
return ExcelExportUtil.exportExcel(exportParams, clazz, examples);
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package com.gxwebsoft.credit.controller;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
|
||||
/**
|
||||
* 导入解析辅助工具
|
||||
*/
|
||||
public final class ImportHelper {
|
||||
|
||||
private ImportHelper() {
|
||||
}
|
||||
|
||||
public static boolean isBlank(String value) {
|
||||
return value == null || value.trim().isEmpty();
|
||||
}
|
||||
|
||||
public static BigDecimal parseBigDecimal(String value, String fieldLabel) {
|
||||
if (isBlank(value)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return new BigDecimal(value.trim());
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException(fieldLabel + "格式不正确");
|
||||
}
|
||||
}
|
||||
|
||||
public static LocalDate parseLocalDate(String value, String fieldLabel) {
|
||||
if (isBlank(value)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return LocalDate.parse(value.trim());
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException(fieldLabel + "日期格式应为yyyy-MM-dd");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
package com.gxwebsoft.credit.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 行政许可
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-01-07 13:52:13
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "CreditAdministrativeLicense对象", description = "行政许可")
|
||||
public class CreditAdministrativeLicense implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "决定文书/许可编号")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "决定文书/许可证名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "许可状态")
|
||||
private String statusText;
|
||||
|
||||
@Schema(description = "许可类别")
|
||||
private String type;
|
||||
|
||||
@Schema(description = "链接")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "有效期自")
|
||||
private String validityStart;
|
||||
|
||||
@Schema(description = "有效期至")
|
||||
private String validityEnd;
|
||||
|
||||
@Schema(description = "许可机关")
|
||||
private String licensingAuthority;
|
||||
|
||||
@Schema(description = "许可内容")
|
||||
@TableField("License_content")
|
||||
private String licenseContent;
|
||||
|
||||
@Schema(description = "数据来源单位")
|
||||
private String dataSourceUnit;
|
||||
|
||||
@Schema(description = "是否有数据")
|
||||
private Boolean hasData;
|
||||
|
||||
@Schema(description = "数据状态")
|
||||
private String dataStatus;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "企业ID")
|
||||
private Integer companyId;
|
||||
|
||||
@Schema(description = "企业别名")
|
||||
private String companyAlias;
|
||||
|
||||
@Schema(description = "主体企业")
|
||||
@TableField(exist = false)
|
||||
private String companyName;
|
||||
|
||||
@Schema(description = "是否推荐")
|
||||
private Integer recommend;
|
||||
|
||||
@Schema(description = "排序(数字越小越靠前)")
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "状态, 0正常, 1冻结")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "是否删除, 0否, 1是")
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "真实姓名")
|
||||
@TableField(exist = false)
|
||||
private String realName;
|
||||
|
||||
@Schema(description = "租户id")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
package com.gxwebsoft.credit.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 破产重整
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-01-07 13:52:14
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "CreditBankruptcy对象", description = "破产重整")
|
||||
public class CreditBankruptcy implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "案号")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "案件类型")
|
||||
private String type;
|
||||
|
||||
@Schema(description = "当事人")
|
||||
private String party;
|
||||
|
||||
@Schema(description = "链接")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "经办法院")
|
||||
private String court;
|
||||
|
||||
@Schema(description = "公开日期")
|
||||
private String publicDate;
|
||||
|
||||
@Schema(description = "是否有数据")
|
||||
private Boolean hasData;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "企业ID")
|
||||
private Integer companyId;
|
||||
|
||||
@Schema(description = "主体企业")
|
||||
@TableField(exist = false)
|
||||
private String companyName;
|
||||
|
||||
@Schema(description = "是否推荐")
|
||||
private Integer recommend;
|
||||
|
||||
@Schema(description = "排序(数字越小越靠前)")
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "状态, 0正常, 1冻结")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "是否删除, 0否, 1是")
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "真实姓名")
|
||||
@TableField(exist = false)
|
||||
private String realName;
|
||||
|
||||
@Schema(description = "租户id")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
package com.gxwebsoft.credit.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 分支机构
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-01-07 13:52:14
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "CreditBranch对象", description = "分支机构")
|
||||
public class CreditBranch implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "分支机构名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "负责人")
|
||||
private String curator;
|
||||
|
||||
@Schema(description = "地区")
|
||||
private String region;
|
||||
|
||||
@Schema(description = "链接")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "成立日期")
|
||||
private String establishDate;
|
||||
|
||||
@Schema(description = "状态")
|
||||
private String statusText;
|
||||
|
||||
@Schema(description = "是否有数据")
|
||||
private Boolean hasData;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "企业ID")
|
||||
private Integer companyId;
|
||||
|
||||
@Schema(description = "企业别名")
|
||||
private String companyAlias;
|
||||
|
||||
@Schema(description = "主题企业")
|
||||
@TableField(exist = false)
|
||||
private String companyName;
|
||||
|
||||
@Schema(description = "是否推荐")
|
||||
private Integer recommend;
|
||||
|
||||
@Schema(description = "排序(数字越小越靠前)")
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "状态, 0正常, 1冻结")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "是否删除, 0否, 1是")
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "真实姓名")
|
||||
@TableField(exist = false)
|
||||
private String realName;
|
||||
|
||||
@Schema(description = "租户id")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
package com.gxwebsoft.credit.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 失信被执行人
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:46:14
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "CreditBreachOfTrust对象", description = "失信被执行人")
|
||||
public class CreditBreachOfTrust implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "案号")
|
||||
private String caseNumber;
|
||||
|
||||
@Schema(description = "失信被执行人")
|
||||
private String plaintiffAppellant;
|
||||
|
||||
@Schema(description = "疑似申请执行人")
|
||||
private String appellee;
|
||||
|
||||
@Schema(description = "涉案金额(元)")
|
||||
private String involvedAmount;
|
||||
|
||||
@Schema(description = "执行法院")
|
||||
private String courtName;
|
||||
|
||||
@Schema(description = "立案日期")
|
||||
private String occurrenceTime;
|
||||
|
||||
@Schema(description = "发布日期")
|
||||
private String releaseDate;
|
||||
|
||||
@Schema(description = "数据类型")
|
||||
private String dataType;
|
||||
|
||||
@Schema(description = "链接地址")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "其他当事人/第三人")
|
||||
private String otherPartiesThirdParty;
|
||||
|
||||
@Schema(description = "案由")
|
||||
private String causeOfAction;
|
||||
|
||||
@Schema(description = "数据状态")
|
||||
private String dataStatus;
|
||||
|
||||
@Schema(description = "企业ID")
|
||||
private Integer companyId;
|
||||
|
||||
@Schema(description = "企业名称")
|
||||
@TableField(exist = false)
|
||||
private String companyName;
|
||||
|
||||
@Schema(description = "是否有数据")
|
||||
private Boolean hasData;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "是否推荐")
|
||||
private Integer recommend;
|
||||
|
||||
@Schema(description = "排序(数字越小越靠前)")
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "状态, 0正常, 1冻结")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "是否删除, 0否, 1是")
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "真实姓名")
|
||||
@TableField(exist = false)
|
||||
private String realName;
|
||||
|
||||
@Schema(description = "租户id")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
package com.gxwebsoft.credit.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 司法大数据
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:47:22
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "CreditCaseFiling对象", description = "司法大数据")
|
||||
public class CreditCaseFiling implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "数据类型")
|
||||
private String dataType;
|
||||
|
||||
@Schema(description = "原告/上诉人")
|
||||
private String plaintiffAppellant;
|
||||
|
||||
@Schema(description = "被告/被上诉人")
|
||||
private String appellee;
|
||||
|
||||
@Schema(description = "其他当事人/第三人")
|
||||
private String otherPartiesThirdParty;
|
||||
|
||||
@Schema(description = "立案日期")
|
||||
private String occurrenceTime;
|
||||
|
||||
@Schema(description = "案号")
|
||||
private String caseNumber;
|
||||
|
||||
@Schema(description = "项目网址")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "案由")
|
||||
private String causeOfAction;
|
||||
|
||||
@Schema(description = "涉案金额")
|
||||
private String involvedAmount;
|
||||
|
||||
@Schema(description = "法院")
|
||||
private String courtName;
|
||||
|
||||
@Schema(description = "数据状态")
|
||||
private String dataStatus;
|
||||
|
||||
@Schema(description = "企业ID")
|
||||
private Integer companyId;
|
||||
|
||||
@Schema(description = "企业名称")
|
||||
@TableField(exist = false)
|
||||
private String companyName;
|
||||
|
||||
@Schema(description = "是否有数据")
|
||||
private Boolean hasData;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "是否推荐")
|
||||
private Integer recommend;
|
||||
|
||||
@Schema(description = "排序(数字越小越靠前)")
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "状态, 0正常, 1冻结")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "是否删除, 0否, 1是")
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "真实姓名")
|
||||
@TableField(exist = false)
|
||||
private String realName;
|
||||
|
||||
@Schema(description = "租户id")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -1,297 +0,0 @@
|
||||
package com.gxwebsoft.credit.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 企业
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-17 08:28:03
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "CreditCompany对象", description = "企业")
|
||||
public class CreditCompany implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "原文件导入名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "系统匹配企业名称")
|
||||
private String matchName;
|
||||
|
||||
@Schema(description = "登记状态")
|
||||
private String registrationStatus;
|
||||
|
||||
@Schema(description = "法定代表人")
|
||||
private String legalPerson;
|
||||
|
||||
@Schema(description = "注册资本")
|
||||
private String registeredCapital;
|
||||
|
||||
@Schema(description = "实缴资本")
|
||||
private String paidinCapital;
|
||||
|
||||
@Schema(description = "成立日期")
|
||||
private String establishDate;
|
||||
|
||||
@Schema(description = "统一社会信用代码")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "企业地址")
|
||||
private String address;
|
||||
|
||||
@Schema(description = "所属省份")
|
||||
private String province;
|
||||
|
||||
@Schema(description = "所属城市")
|
||||
private String city;
|
||||
|
||||
@Schema(description = "所属区县")
|
||||
private String region;
|
||||
|
||||
@Schema(description = "电话")
|
||||
private String tel;
|
||||
|
||||
@Schema(description = "更多电话")
|
||||
private String moreTel;
|
||||
|
||||
@Schema(description = "邮箱")
|
||||
private String email;
|
||||
|
||||
@Schema(description = "更多邮箱")
|
||||
private String moreEmail;
|
||||
|
||||
@Schema(description = "企业(机构)类型")
|
||||
private String institutionType;
|
||||
|
||||
@Schema(description = "纳税人识别号")
|
||||
private String taxpayerCode;
|
||||
|
||||
@Schema(description = "注册号")
|
||||
private String registrationNumber;
|
||||
|
||||
@Schema(description = "组织机构代码")
|
||||
private String organizationalCode;
|
||||
|
||||
@Schema(description = "参保人数")
|
||||
private String numberOfInsuredPersons;
|
||||
|
||||
@Schema(description = "参保人数所属年报")
|
||||
private String annualReport;
|
||||
|
||||
@Schema(description = "营业期限")
|
||||
private String businessTerm;
|
||||
|
||||
@Schema(description = "国标行业门类")
|
||||
private String nationalStandardIndustryCategories;
|
||||
|
||||
@Schema(description = "国标行业大类")
|
||||
private String nationalStandardIndustryCategories2;
|
||||
|
||||
@Schema(description = "国标行业中类")
|
||||
private String nationalStandardIndustryCategories3;
|
||||
|
||||
@Schema(description = "国标行业小类")
|
||||
private String nationalStandardIndustryCategories4;
|
||||
|
||||
@Schema(description = "企查查行业门类")
|
||||
private String nationalStandardIndustryCategories5;
|
||||
|
||||
@Schema(description = "企查查行业大类")
|
||||
private String nationalStandardIndustryCategories6;
|
||||
|
||||
@Schema(description = "企查查行业中类")
|
||||
private String nationalStandardIndustryCategories7;
|
||||
|
||||
@Schema(description = "企查查行业小类")
|
||||
private String nationalStandardIndustryCategories8;
|
||||
|
||||
@Schema(description = "企业规模")
|
||||
private String companySize;
|
||||
|
||||
@Schema(description = "曾用名")
|
||||
private String formerName;
|
||||
|
||||
@Schema(description = "英文名")
|
||||
private String englishName;
|
||||
|
||||
@Schema(description = "官网")
|
||||
private String domain;
|
||||
|
||||
@Schema(description = "通信地址")
|
||||
private String mailingAddress;
|
||||
|
||||
@Schema(description = "企业简介")
|
||||
private String companyProfile;
|
||||
|
||||
@Schema(description = "经营范围")
|
||||
private String natureOfBusiness;
|
||||
|
||||
@Schema(description = "登记机关")
|
||||
private String registrationAuthority;
|
||||
|
||||
@Schema(description = "纳税人资质")
|
||||
private String taxpayerQualification;
|
||||
|
||||
@Schema(description = "最新年报年份")
|
||||
private String latestAnnualReportYear;
|
||||
|
||||
@Schema(description = "最新年报营业收入")
|
||||
private String latestAnnualReportOnOperatingRevenue;
|
||||
|
||||
@Schema(description = "企查分")
|
||||
private String enterpriseScoreCheck;
|
||||
|
||||
@Schema(description = "信用等级")
|
||||
private String creditRating;
|
||||
|
||||
@Schema(description = "科创分")
|
||||
private String cechnologyScore;
|
||||
|
||||
@Schema(description = "科创等级")
|
||||
private String cechnologyLevel;
|
||||
|
||||
@Schema(description = "是否小微企业")
|
||||
private String smallEnterprise;
|
||||
|
||||
|
||||
@Schema(description = "项目网址")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "类型")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "是否客户")
|
||||
private Integer isCustomer;
|
||||
|
||||
@Schema(description = "上级id, 0是顶级")
|
||||
private Integer parentId;
|
||||
|
||||
@Schema(description = "所在国家")
|
||||
private String country;
|
||||
|
||||
@Schema(description = "记录数")
|
||||
private Integer creditAdministrativeLicense;
|
||||
|
||||
@Schema(description = "记录数")
|
||||
private Integer creditBankruptcy;
|
||||
|
||||
@Schema(description = "记录数")
|
||||
private Integer creditBranch;
|
||||
|
||||
@Schema(description = "记录数")
|
||||
private Integer creditBreachOfTrust;
|
||||
|
||||
@Schema(description = "记录数")
|
||||
private Integer creditCaseFiling;
|
||||
|
||||
@Schema(description = "记录数")
|
||||
private Integer creditCompetitor;
|
||||
|
||||
@Schema(description = "记录数")
|
||||
private Integer creditCourtAnnouncement;
|
||||
|
||||
@Schema(description = "记录数")
|
||||
private Integer creditCourtSession;
|
||||
|
||||
@Schema(description = "记录数")
|
||||
private Integer creditCustomer;
|
||||
|
||||
@Schema(description = "记录数")
|
||||
private Integer creditDeliveryNotice;
|
||||
|
||||
@Schema(description = "记录数")
|
||||
private Integer creditExternal;
|
||||
|
||||
@Schema(description = "记录数")
|
||||
private Integer creditFinalVersion;
|
||||
|
||||
@Schema(description = "记录数")
|
||||
private Integer creditGqdj;
|
||||
|
||||
@Schema(description = "记录数")
|
||||
private Integer creditHistoricalLegalPerson;
|
||||
|
||||
@Schema(description = "记录数")
|
||||
private Integer creditJudgmentDebtor;
|
||||
|
||||
@Schema(description = "记录数")
|
||||
private Integer creditJudicialDocument;
|
||||
|
||||
@Schema(description = "记录数")
|
||||
private Integer creditJudiciary;
|
||||
|
||||
@Schema(description = "记录数")
|
||||
private Integer creditMediation;
|
||||
|
||||
@Schema(description = "记录数")
|
||||
private Integer creditNearbyCompany;
|
||||
|
||||
@Schema(description = "记录数")
|
||||
private Integer creditPatent;
|
||||
|
||||
@Schema(description = "记录数")
|
||||
private Integer creditRiskRelation;
|
||||
|
||||
@Schema(description = "记录数")
|
||||
private Integer creditSupplier;
|
||||
|
||||
@Schema(description = "记录数")
|
||||
private Integer creditSuspectedRelationship;
|
||||
|
||||
@Schema(description = "记录数")
|
||||
private Integer creditUser;
|
||||
|
||||
@Schema(description = "记录数")
|
||||
private Integer creditXgxf;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "是否推荐")
|
||||
private Integer recommend;
|
||||
|
||||
@Schema(description = "排序(数字越小越靠前)")
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "状态, 0正常, 1冻结")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "是否删除, 0否, 1是")
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "真实姓名")
|
||||
@TableField(exist = false)
|
||||
private String realName;
|
||||
|
||||
@Schema(description = "租户id")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
package com.gxwebsoft.credit.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 竞争对手
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:49:04
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "CreditCompetitor对象", description = "竞争对手")
|
||||
public class CreditCompetitor implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "序号")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "企业名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "链接地址")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "法定代表人")
|
||||
private String legalRepresentative;
|
||||
|
||||
@Schema(description = "注册资本")
|
||||
private String registeredCapital;
|
||||
|
||||
@Schema(description = "成立日期")
|
||||
private String establishmentDate;
|
||||
|
||||
@Schema(description = "登记状态")
|
||||
private String registrationStatus;
|
||||
|
||||
@Schema(description = "所属行业")
|
||||
private String industry;
|
||||
|
||||
@Schema(description = "所属省份")
|
||||
private String province;
|
||||
|
||||
@Schema(description = "企业ID")
|
||||
private Integer companyId;
|
||||
|
||||
@Schema(description = "企业别名")
|
||||
private String companyAlias;
|
||||
|
||||
@Schema(description = "企业名称")
|
||||
private String companyName;
|
||||
|
||||
@Schema(description = "所属企业名称")
|
||||
@TableField(exist = false)
|
||||
private String mainCompanyName;
|
||||
|
||||
@Schema(description = "是否有数据")
|
||||
private Boolean hasData;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "是否推荐")
|
||||
private Integer recommend;
|
||||
|
||||
@Schema(description = "排序(数字越小越靠前)")
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "状态, 0正常, 1冻结")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "是否删除, 0否, 1是")
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "真实姓名")
|
||||
@TableField(exist = false)
|
||||
private String realName;
|
||||
|
||||
@Schema(description = "租户id")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
package com.gxwebsoft.credit.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 法院公告司法大数据
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:49:13
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "CreditCourtAnnouncement对象", description = "法院公告司法大数据")
|
||||
public class CreditCourtAnnouncement implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "案号")
|
||||
private String caseNumber;
|
||||
|
||||
@Schema(description = "案由")
|
||||
private String causeOfAction;
|
||||
|
||||
@Schema(description = "当事人")
|
||||
private String otherPartiesThirdParty;
|
||||
|
||||
@Schema(description = "公告类型")
|
||||
private String dataType;
|
||||
|
||||
@Schema(description = "原告/上诉人")
|
||||
private String plaintiffAppellant;
|
||||
|
||||
@Schema(description = "刊登日期")
|
||||
private String occurrenceTime;
|
||||
|
||||
@Schema(description = "被告/被上诉人")
|
||||
private String appellee;
|
||||
|
||||
@Schema(description = "链接地址")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "涉案金额")
|
||||
private String involvedAmount;
|
||||
|
||||
@Schema(description = "法院")
|
||||
private String courtName;
|
||||
|
||||
@Schema(description = "数据状态")
|
||||
private String dataStatus;
|
||||
|
||||
@Schema(description = "企业ID")
|
||||
private Integer companyId;
|
||||
|
||||
@Schema(description = "企业名称")
|
||||
@TableField(exist = false)
|
||||
private String companyName;
|
||||
|
||||
@Schema(description = "是否有数据")
|
||||
private Boolean hasData;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "是否推荐")
|
||||
private Integer recommend;
|
||||
|
||||
@Schema(description = "排序(数字越小越靠前)")
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "状态, 0正常, 1冻结")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "是否删除, 0否, 1是")
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "真实姓名")
|
||||
@TableField(exist = false)
|
||||
private String realName;
|
||||
|
||||
@Schema(description = "租户id")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
package com.gxwebsoft.credit.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 开庭公告司法大数据
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:49:32
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "CreditCourtSession对象", description = "开庭公告司法大数据")
|
||||
public class CreditCourtSession implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "数据类型")
|
||||
private String dataType;
|
||||
|
||||
@Schema(description = "原告/上诉人")
|
||||
private String plaintiffAppellant;
|
||||
|
||||
@Schema(description = "被告/被上诉人")
|
||||
private String appellee;
|
||||
|
||||
@Schema(description = "其他当事人/第三人")
|
||||
private String otherPartiesThirdParty;
|
||||
|
||||
@Schema(description = "发生时间")
|
||||
private String occurrenceTime;
|
||||
|
||||
@Schema(description = "案号")
|
||||
private String caseNumber;
|
||||
|
||||
@Schema(description = "链接地址")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "案由")
|
||||
private String causeOfAction;
|
||||
|
||||
@Schema(description = "涉案金额")
|
||||
private String involvedAmount;
|
||||
|
||||
@Schema(description = "法院")
|
||||
private String courtName;
|
||||
|
||||
@Schema(description = "数据状态")
|
||||
private String dataStatus;
|
||||
|
||||
@Schema(description = "企业ID")
|
||||
private Integer companyId;
|
||||
|
||||
@Schema(description = "企业名称")
|
||||
@TableField(exist = false)
|
||||
private String companyName;
|
||||
|
||||
@Schema(description = "是否有数据")
|
||||
private Boolean hasData;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "是否推荐")
|
||||
private Integer recommend;
|
||||
|
||||
@Schema(description = "排序(数字越小越靠前)")
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "状态, 0正常, 1冻结")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "是否删除, 0否, 1是")
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "真实姓名")
|
||||
@TableField(exist = false)
|
||||
private String realName;
|
||||
|
||||
@Schema(description = "租户id")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
package com.gxwebsoft.credit.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 客户
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-21 21:20:58
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "CreditCustomer对象", description = "客户")
|
||||
public class CreditCustomer implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "客户")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "链接地址")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "状态")
|
||||
private String statusTxt;
|
||||
|
||||
@Schema(description = "销售金额(万元)")
|
||||
private String price;
|
||||
|
||||
@Schema(description = "公开日期")
|
||||
private String publicDate;
|
||||
|
||||
@Schema(description = "数据来源")
|
||||
private String dataSource;
|
||||
|
||||
@Schema(description = "企业ID")
|
||||
private Integer companyId;
|
||||
|
||||
@Schema(description = "企业别名")
|
||||
private String companyAlias;
|
||||
|
||||
@Schema(description = "企业名称")
|
||||
private String companyName;
|
||||
|
||||
@Schema(description = "是否有数据")
|
||||
private Boolean hasData;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "是否推荐")
|
||||
private Integer recommend;
|
||||
|
||||
@Schema(description = "排序(数字越小越靠前)")
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "状态, 0正常, 1冻结")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "是否删除, 0否, 1是")
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "真实姓名")
|
||||
@TableField(exist = false)
|
||||
private String realName;
|
||||
|
||||
@Schema(description = "租户id")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
package com.gxwebsoft.credit.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 送达公告司法大数据
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:49:51
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "CreditDeliveryNotice对象", description = "送达公告司法大数据")
|
||||
public class CreditDeliveryNotice implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "案号")
|
||||
private String caseNumber;
|
||||
|
||||
@Schema(description = "链接地址")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "案由")
|
||||
private String causeOfAction;
|
||||
|
||||
@Schema(description = "当事人")
|
||||
private String otherPartiesThirdParty;
|
||||
|
||||
@Schema(description = "法院")
|
||||
private String courtName;
|
||||
|
||||
@Schema(description = "发布日期")
|
||||
private String occurrenceTime;
|
||||
|
||||
@Schema(description = "数据类型")
|
||||
private String dataType;
|
||||
|
||||
@Schema(description = "原告/上诉人")
|
||||
private String plaintiffAppellant;
|
||||
|
||||
@Schema(description = "被告/被上诉人")
|
||||
private String appellee;
|
||||
|
||||
@Schema(description = "涉案金额")
|
||||
private String involvedAmount;
|
||||
|
||||
@Schema(description = "数据状态")
|
||||
private String dataStatus;
|
||||
|
||||
@Schema(description = "企业ID")
|
||||
private Integer companyId;
|
||||
|
||||
@Schema(description = "企业名称")
|
||||
@TableField(exist = false)
|
||||
private String companyName;
|
||||
|
||||
@Schema(description = "是否有数据")
|
||||
private Boolean hasData;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "是否推荐")
|
||||
private Integer recommend;
|
||||
|
||||
@Schema(description = "排序(数字越小越靠前)")
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "状态, 0正常, 1冻结")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "是否删除, 0否, 1是")
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "真实姓名")
|
||||
@TableField(exist = false)
|
||||
private String realName;
|
||||
|
||||
@Schema(description = "租户id")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
package com.gxwebsoft.credit.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 对外投资
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:50:11
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "CreditExternal对象", description = "对外投资")
|
||||
public class CreditExternal implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "被投资企业名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "状态")
|
||||
private String statusTxt;
|
||||
|
||||
@Schema(description = "链接地址")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "法定代表人")
|
||||
private String legalRepresentative;
|
||||
|
||||
@Schema(description = "注册资本(金额)")
|
||||
private String registeredCapital;
|
||||
|
||||
@Schema(description = "成立日期")
|
||||
private String establishmentDate;
|
||||
|
||||
@Schema(description = "持股比例")
|
||||
private String shareholdingRatio;
|
||||
|
||||
@Schema(description = "认缴出资额")
|
||||
private String subscribedInvestmentAmount;
|
||||
|
||||
@Schema(description = "认缴出资日期")
|
||||
private String subscribedInvestmentDate;
|
||||
|
||||
@Schema(description = "间接持股比例")
|
||||
private String indirectShareholdingRatio;
|
||||
|
||||
@Schema(description = "投资日期")
|
||||
private String investmentDate;
|
||||
|
||||
@Schema(description = "所属地区")
|
||||
private String region;
|
||||
|
||||
@Schema(description = "所属行业")
|
||||
private String industry;
|
||||
|
||||
@Schema(description = "投资数量")
|
||||
private Integer investmentCount;
|
||||
|
||||
@Schema(description = "关联产品/机构")
|
||||
private String relatedProductsInstitutions;
|
||||
|
||||
@Schema(description = "企业ID")
|
||||
private Integer companyId;
|
||||
|
||||
@Schema(description = "企业别名")
|
||||
private String companyAlias;
|
||||
|
||||
@Schema(description = "企业名称")
|
||||
private String companyName;
|
||||
|
||||
@Schema(description = "是否有数据")
|
||||
private Boolean hasData;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "是否推荐")
|
||||
private Integer recommend;
|
||||
|
||||
@Schema(description = "排序(数字越小越靠前)")
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "状态, 0正常, 1冻结")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "是否删除, 0否, 1是")
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "真实姓名")
|
||||
@TableField(exist = false)
|
||||
private String realName;
|
||||
|
||||
@Schema(description = "租户id")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
package com.gxwebsoft.credit.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 终本案件
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:50:19
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "CreditFinalVersion对象", description = "终本案件")
|
||||
public class CreditFinalVersion implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "案号")
|
||||
private String caseNumber;
|
||||
|
||||
@Schema(description = "链接地址")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "被执行人")
|
||||
private String appellee;
|
||||
|
||||
@Schema(description = "疑似申请执行人")
|
||||
private String plaintiffAppellant;
|
||||
|
||||
@Schema(description = "未履行金额(元)")
|
||||
private String unfulfilledAmount;
|
||||
|
||||
@Schema(description = "执行标的(元)")
|
||||
private String involvedAmount;
|
||||
|
||||
@Schema(description = "其他当事人/第三人")
|
||||
private String otherPartiesThirdParty;
|
||||
|
||||
@Schema(description = "执行法院")
|
||||
private String courtName;
|
||||
|
||||
@Schema(description = "立案日期")
|
||||
private String occurrenceTime;
|
||||
|
||||
@Schema(description = "终本日期")
|
||||
private String finalDate;
|
||||
|
||||
@Schema(description = "数据状态")
|
||||
private String dataStatus;
|
||||
|
||||
@Schema(description = "企业ID")
|
||||
private Integer companyId;
|
||||
|
||||
@Schema(description = "企业名称")
|
||||
@TableField(exist = false)
|
||||
private String companyName;
|
||||
|
||||
@Schema(description = "是否有数据")
|
||||
private Boolean hasData;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "是否推荐")
|
||||
private Integer recommend;
|
||||
|
||||
@Schema(description = "排序(数字越小越靠前)")
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "状态, 0正常, 1冻结")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "是否删除, 0否, 1是")
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "真实姓名")
|
||||
@TableField(exist = false)
|
||||
private String realName;
|
||||
|
||||
@Schema(description = "租户id")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
package com.gxwebsoft.credit.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 股权冻结
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:50:37
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "CreditGqdj对象", description = "股权冻结")
|
||||
public class CreditGqdj implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "执行通知文书号")
|
||||
private String caseNumber;;
|
||||
|
||||
@Schema(description = "被执行人")
|
||||
private String appellee;
|
||||
|
||||
@Schema(description = "冻结股权标的企业")
|
||||
private String plaintiffAppellant;
|
||||
|
||||
@Schema(description = "被执行人持有股权、其他投资权益数额")
|
||||
private String involvedAmount;
|
||||
|
||||
@Schema(description = "执行法院")
|
||||
private String courtName;
|
||||
|
||||
@Schema(description = "类型")
|
||||
private String dataType;
|
||||
|
||||
@Schema(description = "状态")
|
||||
private String dataStatus;
|
||||
|
||||
@Schema(description = "详情链接")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "冻结日期自")
|
||||
private String freezeDateStart;
|
||||
|
||||
@Schema(description = "冻结日期至")
|
||||
private String freezeDateEnd;
|
||||
|
||||
@Schema(description = "公示日期")
|
||||
private String publicDate;
|
||||
|
||||
@Schema(description = "企业ID")
|
||||
private Integer companyId;
|
||||
|
||||
@Schema(description = "企业名称")
|
||||
@TableField(exist = false)
|
||||
private String companyName;
|
||||
|
||||
@Schema(description = "是否有数据")
|
||||
private Boolean hasData;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "是否推荐")
|
||||
private Integer recommend;
|
||||
|
||||
@Schema(description = "排序(数字越小越靠前)")
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "状态, 0正常, 1冻结")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "是否删除, 0否, 1是")
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "真实姓名")
|
||||
@TableField(exist = false)
|
||||
private String realName;
|
||||
|
||||
@Schema(description = "租户id")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
package com.gxwebsoft.credit.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 历史法定代表人
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-01-07 13:52:14
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "CreditHistoricalLegalPerson对象", description = "历史法定代表人")
|
||||
public class CreditHistoricalLegalPerson implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "任职日期")
|
||||
private String registerDate;
|
||||
|
||||
@Schema(description = "卸任日期")
|
||||
private String publicDate;
|
||||
|
||||
@Schema(description = "链接")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "是否有数据")
|
||||
private Boolean hasData;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "企业ID")
|
||||
private Integer companyId;
|
||||
|
||||
@Schema(description = "企业别名")
|
||||
private String companyAlias;
|
||||
|
||||
@Schema(description = "主体企业")
|
||||
@TableField(exist = false)
|
||||
private String companyName;
|
||||
|
||||
@Schema(description = "是否推荐")
|
||||
private Integer recommend;
|
||||
|
||||
@Schema(description = "排序(数字越小越靠前)")
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "状态, 0正常, 1冻结")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "是否删除, 0否, 1是")
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "真实姓名")
|
||||
@TableField(exist = false)
|
||||
private String realName;
|
||||
|
||||
@Schema(description = "租户id")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -1,126 +0,0 @@
|
||||
package com.gxwebsoft.credit.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 被执行人
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:50:55
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "CreditJudgmentDebtor对象", description = "被执行人")
|
||||
public class CreditJudgmentDebtor implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "案号")
|
||||
private String caseNumber;
|
||||
|
||||
@Schema(description = "被执行人名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "被执行人")
|
||||
private String name1;
|
||||
|
||||
@Schema(description = "原告/上诉人")
|
||||
private String plaintiffAppellant;
|
||||
|
||||
@Schema(description = "被告/被上诉人")
|
||||
private String appellee;
|
||||
|
||||
@Schema(description = "其他当事人/第三人")
|
||||
private String otherPartiesThirdParty;
|
||||
|
||||
@Schema(description = "证件号/组织机构代码")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "项目网址")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "发生时间")
|
||||
private String occurrenceTime;
|
||||
|
||||
@Schema(description = "涉案金额")
|
||||
private String amount;
|
||||
|
||||
@Schema(description = "执行标的(元)")
|
||||
private String involvedAmountQcc;
|
||||
|
||||
@Schema(description = "法院")
|
||||
private String courtName;
|
||||
|
||||
@Schema(description = "数据状态")
|
||||
private String dataStatus;
|
||||
|
||||
@Schema(description = "企业ID")
|
||||
private Integer companyId;
|
||||
|
||||
@Schema(description = "企业名称")
|
||||
@TableField(exist = false)
|
||||
private String companyName;
|
||||
|
||||
@Schema(description = "是否有数据")
|
||||
private Boolean hasData;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "是否推荐")
|
||||
private Integer recommend;
|
||||
|
||||
@Schema(description = "排序(数字越小越靠前)")
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "状态, 0正常, 1冻结")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "是否删除, 0否, 1是")
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "真实姓名")
|
||||
@TableField(exist = false)
|
||||
private String realName;
|
||||
|
||||
@Schema(description = "租户id")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
@Schema(description = "历史被执行人ID")
|
||||
@TableField(exist = false)
|
||||
private Integer historyId;
|
||||
|
||||
@Schema(description = "历史被执行人名称")
|
||||
@TableField(exist = false)
|
||||
private String historyName;
|
||||
|
||||
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
package com.gxwebsoft.credit.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 裁判文书司法大数据
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:51:02
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "CreditJudicialDocument对象", description = "裁判文书司法大数据")
|
||||
public class CreditJudicialDocument implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "文书标题")
|
||||
private String title;
|
||||
|
||||
@Schema(description = "文书类型")
|
||||
private String documentType;
|
||||
|
||||
@Schema(description = "案号")
|
||||
private String caseNumber;
|
||||
|
||||
@Schema(description = "链接地址")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "案由")
|
||||
private String causeOfAction;
|
||||
|
||||
@Schema(description = "当事人")
|
||||
private String otherPartiesThirdParty;
|
||||
|
||||
@Schema(description = "案件金额")
|
||||
private String involvedAmount;
|
||||
|
||||
@Schema(description = "裁判结果")
|
||||
private String defendantAppellee;
|
||||
|
||||
@Schema(description = "裁判日期")
|
||||
private String occurrenceTime;
|
||||
|
||||
@Schema(description = "发布日期")
|
||||
private String releaseDate;
|
||||
|
||||
@Schema(description = "被告/被上诉人")
|
||||
private String appellee;
|
||||
|
||||
@Schema(description = "法院")
|
||||
private String courtName;
|
||||
|
||||
@Schema(description = "数据状态")
|
||||
private String dataStatus;
|
||||
|
||||
@Schema(description = "企业ID")
|
||||
private Integer companyId;
|
||||
|
||||
@Schema(description = "企业名称")
|
||||
@TableField(exist = false)
|
||||
private String companyName;
|
||||
|
||||
@Schema(description = "是否有数据")
|
||||
private Boolean hasData;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "是否推荐")
|
||||
private Integer recommend;
|
||||
|
||||
@Schema(description = "排序(数字越小越靠前)")
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "状态, 0正常, 1冻结")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "是否删除, 0否, 1是")
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "真实姓名")
|
||||
@TableField(exist = false)
|
||||
private String realName;
|
||||
|
||||
@Schema(description = "租户id")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
package com.gxwebsoft.credit.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 司法案件
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-16 15:23:58
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "CreditJudiciary对象", description = "司法案件")
|
||||
public class CreditJudiciary implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "案件名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "案号")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "详情链接")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "类型, 0普通用户, 1招投标")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "案由")
|
||||
private String reason;
|
||||
|
||||
@Schema(description = "上级id, 0是顶级")
|
||||
private Integer parentId;
|
||||
|
||||
@Schema(description = "案件类型")
|
||||
private String infoType;
|
||||
|
||||
@Schema(description = "所在国家")
|
||||
private String country;
|
||||
|
||||
@Schema(description = "所在省份")
|
||||
private String province;
|
||||
|
||||
@Schema(description = "所在城市")
|
||||
private String city;
|
||||
|
||||
@Schema(description = "所在辖区")
|
||||
private String region;
|
||||
|
||||
@Schema(description = "街道地址")
|
||||
private String address;
|
||||
|
||||
@Schema(description = "案件进程")
|
||||
private String caseProgress;
|
||||
|
||||
@Schema(description = "案件身份")
|
||||
private String caseIdentity;
|
||||
|
||||
@Schema(description = "法院")
|
||||
private String court;
|
||||
|
||||
@Schema(description = "进程日期")
|
||||
private String processDate;
|
||||
|
||||
@Schema(description = "案件金额(元)")
|
||||
private String caseAmount;
|
||||
|
||||
@Schema(description = "企业ID")
|
||||
private Integer companyId;
|
||||
|
||||
@Schema(description = "企业名称")
|
||||
@TableField(exist = false)
|
||||
private String companyName;
|
||||
|
||||
@Schema(description = "是否有数据")
|
||||
private Boolean hasData;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "是否推荐")
|
||||
private Integer recommend;
|
||||
|
||||
@Schema(description = "到期时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime expirationTime;
|
||||
|
||||
@Schema(description = "排序(数字越小越靠前)")
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "状态, 0正常, 1冻结")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "是否删除, 0否, 1是")
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "真实姓名")
|
||||
@TableField(exist = false)
|
||||
private String realName;
|
||||
|
||||
@Schema(description = "租户id")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
package com.gxwebsoft.credit.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 诉前调解司法大数据
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:51:25
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "CreditMediation对象", description = "诉前调解司法大数据")
|
||||
public class CreditMediation implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "数据类型")
|
||||
private String dataType;
|
||||
|
||||
@Schema(description = "原告/上诉人")
|
||||
private String plaintiffAppellant;
|
||||
|
||||
@Schema(description = "被告/被上诉人")
|
||||
private String appellee;
|
||||
|
||||
@Schema(description = "其他当事人/第三人")
|
||||
private String otherPartiesThirdParty;
|
||||
|
||||
@Schema(description = "发生时间")
|
||||
private String occurrenceTime;
|
||||
|
||||
@Schema(description = "案号")
|
||||
private String caseNumber;
|
||||
|
||||
@Schema(description = "链接地址")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "案由")
|
||||
private String causeOfAction;
|
||||
|
||||
@Schema(description = "涉案金额")
|
||||
private String involvedAmount;
|
||||
|
||||
@Schema(description = "法院")
|
||||
private String courtName;
|
||||
|
||||
@Schema(description = "数据状态")
|
||||
private String dataStatus;
|
||||
|
||||
@Schema(description = "企业ID")
|
||||
private Integer companyId;
|
||||
|
||||
@Schema(description = "企业名称")
|
||||
@TableField(exist = false)
|
||||
private String companyName;
|
||||
|
||||
@Schema(description = "是否有数据")
|
||||
private Boolean hasData;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "是否推荐")
|
||||
private Integer recommend;
|
||||
|
||||
@Schema(description = "排序(数字越小越靠前)")
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "状态, 0正常, 1冻结")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "是否删除, 0否, 1是")
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "真实姓名")
|
||||
@TableField(exist = false)
|
||||
private String realName;
|
||||
|
||||
@Schema(description = "租户id")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
@Schema(description = "发生时间")
|
||||
@TableField(exist = false)
|
||||
private String occurrenceTime2;
|
||||
|
||||
}
|
||||
@@ -1,295 +0,0 @@
|
||||
package com.gxwebsoft.credit.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import java.time.LocalDateTime;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 小程序端客户
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-03-16 20:59:17
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "CreditMpCustomer对象", description = "小程序端客户")
|
||||
public class CreditMpCustomer implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "拖欠方")
|
||||
private String toUser;
|
||||
|
||||
@Schema(description = "拖欠金额")
|
||||
private String price;
|
||||
|
||||
@Schema(description = "拖欠年数")
|
||||
private String years;
|
||||
|
||||
@Schema(description = "链接")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "状态")
|
||||
private String statusTxt;
|
||||
|
||||
@Schema(description = "企业ID")
|
||||
private Integer companyId;
|
||||
|
||||
@Schema(description = "所在省份")
|
||||
private String province;
|
||||
|
||||
@Schema(description = "所在城市")
|
||||
private String city;
|
||||
|
||||
@Schema(description = "所在辖区")
|
||||
private String region;
|
||||
|
||||
@Schema(description = "文件路径")
|
||||
private String files;
|
||||
|
||||
@Schema(description = "是否有数据")
|
||||
private Boolean hasData;
|
||||
|
||||
@Schema(description = "步骤, 0未受理1已受理2材料提交3合同签订4执行回款5完结")
|
||||
private Integer step;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "是否推荐")
|
||||
private Integer recommend;
|
||||
|
||||
@Schema(description = "排序(数字越小越靠前)")
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "状态, 0未受理, 1已受理")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "是否删除, 0否, 1是")
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "用户昵称")
|
||||
@TableField(exist = false)
|
||||
private String nickname;
|
||||
|
||||
@Schema(description = "用户手机号")
|
||||
@TableField(exist = false)
|
||||
private String phone;
|
||||
|
||||
@Schema(description = "用户头像")
|
||||
@TableField(exist = false)
|
||||
private String avatar;
|
||||
|
||||
@Schema(description = "真实姓名")
|
||||
@TableField(exist = false)
|
||||
private String realName;
|
||||
|
||||
@Schema(description = "租户id")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
// 第1步:案件受理字段
|
||||
@Schema(description = "第1步是否已提交")
|
||||
private Integer followStep1Submitted;
|
||||
|
||||
@Schema(description = "第1步提交时间")
|
||||
private String followStep1SubmittedAt;
|
||||
|
||||
@Schema(description = "第1步联系人")
|
||||
private String followStep1Contact;
|
||||
|
||||
@Schema(description = "第1步联系电话")
|
||||
private String followStep1Phone;
|
||||
|
||||
@Schema(description = "第1步电话录音URL")
|
||||
private String followStep1AudioUrl;
|
||||
|
||||
@Schema(description = "第1步电话录音文件名")
|
||||
private String followStep1AudioName;
|
||||
|
||||
@Schema(description = "第1步短信截图JSON")
|
||||
private String followStep1SmsShots;
|
||||
|
||||
@Schema(description = "第1步电话沟通截图JSON")
|
||||
private String followStep1CallShots;
|
||||
|
||||
@Schema(description = "第1步沟通情况")
|
||||
private String followStep1Remark;
|
||||
|
||||
@Schema(description = "第1步意向(无意向/有意向)")
|
||||
private String followStep1Intention;
|
||||
|
||||
@Schema(description = "第1步沟通次数")
|
||||
private Integer followStep1CommunicationCount;
|
||||
|
||||
@Schema(description = "第1步是否需要审核")
|
||||
private Integer followStep1NeedApproval;
|
||||
|
||||
@Schema(description = "第1步是否审核通过")
|
||||
private Integer followStep1Approved;
|
||||
|
||||
@Schema(description = "第1步审核时间")
|
||||
private String followStep1ApprovedAt;
|
||||
|
||||
@Schema(description = "第1步审核人ID")
|
||||
private Long followStep1ApprovedBy;
|
||||
|
||||
// 第2步:材料准备字段
|
||||
@Schema(description = "第2步是否已提交")
|
||||
private Integer followStep2Submitted;
|
||||
|
||||
@Schema(description = "第2步提交时间")
|
||||
private String followStep2SubmittedAt;
|
||||
|
||||
@Schema(description = "第2步是否需要审核")
|
||||
private Integer followStep2NeedApproval;
|
||||
|
||||
@Schema(description = "第2步是否审核通过")
|
||||
private Integer followStep2Approved;
|
||||
|
||||
@Schema(description = "第2步审核时间")
|
||||
private String followStep2ApprovedAt;
|
||||
|
||||
@Schema(description = "第2步审核人ID")
|
||||
private Long followStep2ApprovedBy;
|
||||
|
||||
// 第3步:案件办理字段
|
||||
@Schema(description = "第3步是否已提交")
|
||||
private Integer followStep3Submitted;
|
||||
|
||||
@Schema(description = "第3步提交时间")
|
||||
private String followStep3SubmittedAt;
|
||||
|
||||
@Schema(description = "第3步是否需要审核")
|
||||
private Integer followStep3NeedApproval;
|
||||
|
||||
@Schema(description = "第3步是否审核通过")
|
||||
private Integer followStep3Approved;
|
||||
|
||||
@Schema(description = "第3步审核时间")
|
||||
private String followStep3ApprovedAt;
|
||||
|
||||
@Schema(description = "第3步审核人ID")
|
||||
private Long followStep3ApprovedBy;
|
||||
|
||||
// 第4步:送达签收字段
|
||||
@Schema(description = "第4步是否已提交")
|
||||
private Integer followStep4Submitted;
|
||||
|
||||
@Schema(description = "第4步提交时间")
|
||||
private String followStep4SubmittedAt;
|
||||
|
||||
@Schema(description = "第4步是否需要审核")
|
||||
private Integer followStep4NeedApproval;
|
||||
|
||||
@Schema(description = "第4步是否审核通过")
|
||||
private Integer followStep4Approved;
|
||||
|
||||
@Schema(description = "第4步审核时间")
|
||||
private String followStep4ApprovedAt;
|
||||
|
||||
@Schema(description = "第4步审核人ID")
|
||||
private Long followStep4ApprovedBy;
|
||||
|
||||
// 第5步:合同签订字段
|
||||
@Schema(description = "第5步是否已提交")
|
||||
private Integer followStep5Submitted;
|
||||
|
||||
@Schema(description = "第5步提交时间")
|
||||
private String followStep5SubmittedAt;
|
||||
|
||||
@Schema(description = "第5步合同信息JSON数组")
|
||||
private String followStep5Contracts;
|
||||
|
||||
@Schema(description = "第5步是否需要审核")
|
||||
private Integer followStep5NeedApproval;
|
||||
|
||||
@Schema(description = "第5步是否审核通过")
|
||||
private Integer followStep5Approved;
|
||||
|
||||
@Schema(description = "第5步审核时间")
|
||||
private String followStep5ApprovedAt;
|
||||
|
||||
@Schema(description = "第5步审核人ID")
|
||||
private Long followStep5ApprovedBy;
|
||||
|
||||
// 第6步:订单回款字段
|
||||
@Schema(description = "第6步是否已提交")
|
||||
private Integer followStep6Submitted;
|
||||
|
||||
@Schema(description = "第6步提交时间")
|
||||
private String followStep6SubmittedAt;
|
||||
|
||||
@Schema(description = "第6步财务录入的回款记录JSON数组")
|
||||
private String followStep6PaymentRecords;
|
||||
|
||||
@Schema(description = "第6步预计回款JSON数组")
|
||||
private String followStep6ExpectedPayments;
|
||||
|
||||
@Schema(description = "第6步是否需要审核")
|
||||
private Integer followStep6NeedApproval;
|
||||
|
||||
@Schema(description = "第6步是否审核通过")
|
||||
private Integer followStep6Approved;
|
||||
|
||||
@Schema(description = "第6步审核时间")
|
||||
private String followStep6ApprovedAt;
|
||||
|
||||
@Schema(description = "第6步审核人ID")
|
||||
private Long followStep6ApprovedBy;
|
||||
|
||||
// 第7步:电话回访字段
|
||||
@Schema(description = "第7步是否已提交")
|
||||
private Integer followStep7Submitted;
|
||||
|
||||
@Schema(description = "第7步提交时间")
|
||||
private String followStep7SubmittedAt;
|
||||
|
||||
@Schema(description = "第7步回访记录JSON数组")
|
||||
private String followStep7VisitRecords;
|
||||
|
||||
@Schema(description = "第7步是否需要审核")
|
||||
private Integer followStep7NeedApproval;
|
||||
|
||||
@Schema(description = "第7步是否审核通过")
|
||||
private Integer followStep7Approved;
|
||||
|
||||
@Schema(description = "第7步审核时间")
|
||||
private String followStep7ApprovedAt;
|
||||
|
||||
@Schema(description = "第7步审核人ID")
|
||||
private Long followStep7ApprovedBy;
|
||||
|
||||
// 流程结束字段
|
||||
@Schema(description = "流程是否已结束")
|
||||
private Integer followProcessEnded;
|
||||
|
||||
@Schema(description = "流程结束时间")
|
||||
private String followProcessEndTime;
|
||||
|
||||
@Schema(description = "流程结束原因")
|
||||
private String followProcessEndReason;
|
||||
|
||||
}
|
||||
@@ -1,247 +0,0 @@
|
||||
package com.gxwebsoft.credit.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 附近企业
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-01-07 13:52:14
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "CreditNearbyCompany对象", description = "附近企业")
|
||||
public class CreditNearbyCompany implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "企业名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "登记状态")
|
||||
private String registrationStatus;
|
||||
|
||||
@Schema(description = "法定代表人")
|
||||
private String legalPerson;
|
||||
|
||||
@Schema(description = "注册资本")
|
||||
private String registeredCapital;
|
||||
|
||||
@Schema(description = "成立日期")
|
||||
private String establishDate;
|
||||
|
||||
@Schema(description = "统一社会信用代码")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "注册地址")
|
||||
private String address;
|
||||
|
||||
@Schema(description = "注册地址邮编")
|
||||
private String postalCode;
|
||||
|
||||
@Schema(description = "有效手机号")
|
||||
private String phone;
|
||||
|
||||
@Schema(description = "更多电话")
|
||||
private String moreTel;
|
||||
|
||||
@Schema(description = "邮箱")
|
||||
private String email;
|
||||
|
||||
@Schema(description = "更多邮箱")
|
||||
private String moreEmail;
|
||||
|
||||
@Schema(description = "所在国家")
|
||||
private String country;
|
||||
|
||||
@Schema(description = "所属省份")
|
||||
private String province;
|
||||
|
||||
@Schema(description = "所属城市")
|
||||
private String city;
|
||||
|
||||
@Schema(description = "所属区县")
|
||||
private String region;
|
||||
|
||||
@Schema(description = "企业ID")
|
||||
private Integer companyId;
|
||||
|
||||
@Schema(description = "企业别名")
|
||||
private String companyAlias;
|
||||
|
||||
@Schema(description = "主体企业")
|
||||
@TableField(exist = false)
|
||||
private String companyName;
|
||||
|
||||
@Schema(description = "纳税人识别号")
|
||||
private String taxpayerCode;
|
||||
|
||||
@Schema(description = "注册号")
|
||||
private String registrationNumber;
|
||||
|
||||
@Schema(description = "组织机构代码")
|
||||
private String organizationalCode;
|
||||
|
||||
@Schema(description = "参保人数")
|
||||
private String numberOfInsuredPersons;
|
||||
|
||||
@Schema(description = "参保人数所属年报")
|
||||
private String annualReport;
|
||||
|
||||
@Schema(description = "企业(机构)类型")
|
||||
private String institutionType;
|
||||
|
||||
@Schema(description = "企业规模")
|
||||
private String companySize;
|
||||
|
||||
@Schema(description = "营业期限")
|
||||
private String businessTerm;
|
||||
|
||||
@Schema(description = "国标行业门类")
|
||||
private String nationalStandardIndustryCategories;
|
||||
|
||||
@Schema(description = "国标行业大类")
|
||||
private String nationalStandardIndustryCategories2;
|
||||
|
||||
@Schema(description = "国标行业中类")
|
||||
private String nationalStandardIndustryCategories3;
|
||||
|
||||
@Schema(description = "国标行业小类")
|
||||
private String nationalStandardIndustryCategories4;
|
||||
|
||||
@Schema(description = "曾用名")
|
||||
private String formerName;
|
||||
|
||||
@Schema(description = "英文名")
|
||||
private String englishName;
|
||||
|
||||
@Schema(description = "官网网址")
|
||||
private String domain;
|
||||
|
||||
@Schema(description = "通信地址")
|
||||
private String mailingAddress;
|
||||
|
||||
@Schema(description = "通信地址邮编")
|
||||
private String mailingEmail;
|
||||
|
||||
@Schema(description = "企业简介")
|
||||
private String companyProfile;
|
||||
|
||||
@Schema(description = "经营范围")
|
||||
private String natureOfBusiness;
|
||||
|
||||
@Schema(description = "电话")
|
||||
private String tel;
|
||||
|
||||
@Schema(description = "企查查行业门类")
|
||||
private String nationalStandardIndustryCategories5;
|
||||
|
||||
@Schema(description = "企查查行业大类")
|
||||
private String nationalStandardIndustryCategories6;
|
||||
|
||||
@Schema(description = "企查查行业中类")
|
||||
private String nationalStandardIndustryCategories7;
|
||||
|
||||
@Schema(description = "企查查行业小类")
|
||||
private String nationalStandardIndustryCategories8;
|
||||
|
||||
@Schema(description = "链接")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "类型")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "上级id, 0是顶级")
|
||||
private Integer parentId;
|
||||
|
||||
// @Schema(description = "实缴资本")
|
||||
// @TableField(exist = false)
|
||||
// private String paidinCapital;
|
||||
//
|
||||
// @Schema(description = "登记机关")
|
||||
// @TableField(exist = false)
|
||||
// private String registrationAuthority;
|
||||
//
|
||||
// @Schema(description = "纳税人资质")
|
||||
// @TableField(exist = false)
|
||||
// private String taxpayerQualification;
|
||||
//
|
||||
// @Schema(description = "最新年报年份")
|
||||
// @TableField(exist = false)
|
||||
// private String latestAnnualReportYear;
|
||||
//
|
||||
// @Schema(description = "最新年报营业收入")
|
||||
// @TableField(exist = false)
|
||||
// private String latestAnnualReportOnOperatingRevenue;
|
||||
//
|
||||
// @Schema(description = "企查分")
|
||||
// @TableField(exist = false)
|
||||
// private String enterpriseScoreCheck;
|
||||
//
|
||||
// @Schema(description = "信用等级")
|
||||
// @TableField(exist = false)
|
||||
// private String creditRating;
|
||||
//
|
||||
// @Schema(description = "科创分")
|
||||
// @TableField(exist = false)
|
||||
// private String cechnologyScore;
|
||||
//
|
||||
// @Schema(description = "科创等级")
|
||||
// @TableField(exist = false)
|
||||
// private String cechnologyLevel;
|
||||
//
|
||||
// @Schema(description = "是否小微企业")
|
||||
// @TableField(exist = false)
|
||||
// private String smallEnterprise;
|
||||
|
||||
@Schema(description = "是否有数据")
|
||||
private Boolean hasData;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "是否推荐")
|
||||
private Integer recommend;
|
||||
|
||||
@Schema(description = "排序(数字越小越靠前)")
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "状态, 0正常, 1冻结")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "是否删除, 0否, 1是")
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "真实姓名")
|
||||
@TableField(exist = false)
|
||||
private String realName;
|
||||
|
||||
@Schema(description = "租户id")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
package com.gxwebsoft.credit.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 专利
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-01-07 13:52:14
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "CreditPatent对象", description = "专利")
|
||||
public class CreditPatent implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "发明名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "专利类型")
|
||||
private String type;
|
||||
|
||||
@Schema(description = "法律状态")
|
||||
private String statusText;
|
||||
|
||||
@Schema(description = "申请号")
|
||||
private String registerNo;
|
||||
|
||||
@Schema(description = "申请日")
|
||||
private String registerDate;
|
||||
|
||||
@Schema(description = "公开(公告)号")
|
||||
private String publicNo;
|
||||
|
||||
@Schema(description = "公开(公告)日期")
|
||||
private String publicDate;
|
||||
|
||||
@Schema(description = "发明人")
|
||||
private String inventor;
|
||||
|
||||
@Schema(description = "申请(专利权)人")
|
||||
private String patentApplicant;
|
||||
|
||||
@Schema(description = "链接")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "是否有数据")
|
||||
private Boolean hasData;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "企业ID")
|
||||
private Integer companyId;
|
||||
|
||||
@Schema(description = "主体企业")
|
||||
@TableField(exist = false)
|
||||
private String companyName;
|
||||
|
||||
@Schema(description = "是否推荐")
|
||||
private Integer recommend;
|
||||
|
||||
@Schema(description = "排序(数字越小越靠前)")
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "状态, 0正常, 1冻结")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "是否删除, 0否, 1是")
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "真实姓名")
|
||||
@TableField(exist = false)
|
||||
private String realName;
|
||||
|
||||
@Schema(description = "租户id")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
package com.gxwebsoft.credit.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 风险关系表
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:51:40
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "CreditRiskRelation对象", description = "风险关系表")
|
||||
public class CreditRiskRelation implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "序号")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "主体名称")
|
||||
private String mainBodyName;
|
||||
|
||||
@Schema(description = "登记状态")
|
||||
private String registrationStatus;
|
||||
|
||||
@Schema(description = "注册资本")
|
||||
private String registeredCapital;
|
||||
|
||||
@Schema(description = "省份地区")
|
||||
private String provinceRegion;
|
||||
|
||||
@Schema(description = "关联关系")
|
||||
private String associatedRelation;
|
||||
|
||||
@Schema(description = "风险关系")
|
||||
private String riskRelation;
|
||||
|
||||
@Schema(description = "企业ID")
|
||||
private Integer companyId;
|
||||
|
||||
@Schema(description = "企业别名")
|
||||
private String companyAlias;
|
||||
|
||||
@Schema(description = "企业名称")
|
||||
private String companyName;
|
||||
|
||||
@Schema(description = "是否有数据")
|
||||
private Boolean hasData;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "是否推荐")
|
||||
private Integer recommend;
|
||||
|
||||
@Schema(description = "排序(数字越小越靠前)")
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "状态, 0正常, 1冻结")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "是否删除, 0否, 1是")
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "真实姓名")
|
||||
@TableField(exist = false)
|
||||
private String realName;
|
||||
|
||||
@Schema(description = "租户id")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
package com.gxwebsoft.credit.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 供应商
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:51:47
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "CreditSupplier对象", description = "供应商")
|
||||
public class CreditSupplier implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "供应商")
|
||||
private String supplier;
|
||||
|
||||
@Schema(description = "链接地址")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "状态")
|
||||
private String statusTxt;
|
||||
|
||||
@Schema(description = "采购金额(万元)")
|
||||
private String purchaseAmount;
|
||||
|
||||
@Schema(description = "公开日期")
|
||||
private String publicDate;
|
||||
|
||||
@Schema(description = "数据来源")
|
||||
private String dataSource;
|
||||
|
||||
@Schema(description = "企业ID")
|
||||
private Integer companyId;
|
||||
|
||||
@Schema(description = "企业别名")
|
||||
private String companyAlias;
|
||||
|
||||
@Schema(description = "企业名称")
|
||||
private String companyName;
|
||||
|
||||
@Schema(description = "是否有数据")
|
||||
private Boolean hasData;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "是否推荐")
|
||||
private Integer recommend;
|
||||
|
||||
@Schema(description = "排序(数字越小越靠前)")
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "状态, 0正常, 1冻结")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "是否删除, 0否, 1是")
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "真实姓名")
|
||||
@TableField(exist = false)
|
||||
private String realName;
|
||||
|
||||
@Schema(description = "租户id")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
package com.gxwebsoft.credit.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 疑似关系
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-01-07 13:52:14
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "CreditSuspectedRelationship对象", description = "疑似关系")
|
||||
public class CreditSuspectedRelationship implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "企业名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "状态")
|
||||
private String statusText;
|
||||
|
||||
@Schema(description = "法定代表人")
|
||||
private String legalPerson;
|
||||
|
||||
@Schema(description = "注册资本")
|
||||
private String registeredCapital;
|
||||
|
||||
@Schema(description = "成立日期")
|
||||
private String createDate;
|
||||
|
||||
@Schema(description = "关联方")
|
||||
private String relatedParty;
|
||||
|
||||
@Schema(description = "疑似关系类型")
|
||||
private String type;
|
||||
|
||||
@Schema(description = "疑似关系详情")
|
||||
private String detail;
|
||||
|
||||
@Schema(description = "链接")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "是否有数据")
|
||||
private Boolean hasData;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "企业ID")
|
||||
private Integer companyId;
|
||||
|
||||
@Schema(description = "企业别名")
|
||||
private String companyAlias;
|
||||
|
||||
@Schema(description = "主体企业")
|
||||
@TableField(exist = false)
|
||||
private String companyName;
|
||||
|
||||
@Schema(description = "是否推荐")
|
||||
private Integer recommend;
|
||||
|
||||
@Schema(description = "排序(数字越小越靠前)")
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "状态, 0正常, 1冻结")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "是否删除, 0否, 1是")
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "真实姓名")
|
||||
@TableField(exist = false)
|
||||
private String realName;
|
||||
|
||||
@Schema(description = "租户id")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
package com.gxwebsoft.credit.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import java.time.LocalDateTime;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import java.io.Serializable;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
|
||||
/**
|
||||
* 招投标信息表
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-15 13:16:03
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "CreditUser对象", description = "招投标信息表")
|
||||
public class CreditUser implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "项目名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "项目网址")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "唯一标识")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "类型, 0普通用户, 1招投标")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "原告/上诉人")
|
||||
private String plaintiffAppellant;
|
||||
|
||||
@Schema(description = "企业角色")
|
||||
private String role;
|
||||
|
||||
@Schema(description = "上级id, 0是顶级")
|
||||
private Integer parentId;
|
||||
|
||||
@Schema(description = "信息类型")
|
||||
private String infoType;
|
||||
|
||||
@Schema(description = "所在国家")
|
||||
private String country;
|
||||
|
||||
@Schema(description = "所在省份")
|
||||
private String province;
|
||||
|
||||
@Schema(description = "所在城市")
|
||||
private String city;
|
||||
|
||||
@Schema(description = "所在辖区")
|
||||
private String region;
|
||||
|
||||
@Schema(description = "街道地址")
|
||||
private String address;
|
||||
|
||||
@Schema(description = "招采单位")
|
||||
private String procurementName;
|
||||
|
||||
@Schema(description = "中标单位")
|
||||
private String winningName;
|
||||
|
||||
@Schema(description = "中标金额")
|
||||
private String winningPrice;
|
||||
|
||||
@Schema(description = "发布日期")
|
||||
private String releaseDate;
|
||||
|
||||
@Schema(description = "企业ID")
|
||||
private Integer companyId;
|
||||
|
||||
@Schema(description = "企业别名")
|
||||
private String companyAlias;
|
||||
|
||||
@Schema(description = "企业名称")
|
||||
private String companyName;
|
||||
|
||||
@Schema(description = "是否有数据")
|
||||
private Boolean hasData;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "是否推荐")
|
||||
private Integer recommend;
|
||||
|
||||
@Schema(description = "排序(数字越小越靠前)")
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "状态, 0正常, 1冻结")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "是否删除, 0否, 1是")
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "真实姓名")
|
||||
@TableField(exist = false)
|
||||
private String realName;
|
||||
|
||||
@Schema(description = "租户id")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
package com.gxwebsoft.credit.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 限制高消费
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:51:55
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(name = "CreditXgxf对象", description = "限制高消费")
|
||||
public class CreditXgxf implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Schema(description = "链接地址")
|
||||
private String url;
|
||||
|
||||
@Schema(description = "数据类型")
|
||||
private String type;
|
||||
|
||||
@Schema(description = "原告/上诉人")
|
||||
private String plaintiffAppellant;
|
||||
|
||||
@Schema(description = "被告/被上诉人")
|
||||
private String appellee;
|
||||
|
||||
@Schema(description = "其他当事人/第三人")
|
||||
private String otherPartiesThirdParty;
|
||||
|
||||
@Schema(description = "发生时间")
|
||||
private String occurrenceTime;
|
||||
|
||||
@Schema(description = "案号")
|
||||
private String caseNumber;
|
||||
|
||||
@Schema(description = "涉案金额")
|
||||
private String involvedAmount;
|
||||
|
||||
@Schema(description = "法院")
|
||||
private String courtName;
|
||||
|
||||
@Schema(description = "数据状态")
|
||||
private String dataStatus;
|
||||
|
||||
@Schema(description = "限消令对象")
|
||||
private String dataType;
|
||||
|
||||
@Schema(description = "原告/上诉人2")
|
||||
private String plaintiffUser;
|
||||
|
||||
@Schema(description = "被告/被上诉人2")
|
||||
private String defendantUser;
|
||||
|
||||
@Schema(description = "发布日期")
|
||||
private String releaseDate;
|
||||
|
||||
@Schema(description = "案由")
|
||||
private String causeOfAction;
|
||||
|
||||
@Schema(description = "企业ID")
|
||||
private Integer companyId;
|
||||
|
||||
@Schema(description = "企业名称")
|
||||
@TableField(exist = false)
|
||||
private String companyName;
|
||||
|
||||
@Schema(description = "是否有数据")
|
||||
private Boolean hasData;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
@Schema(description = "是否推荐")
|
||||
private Integer recommend;
|
||||
|
||||
@Schema(description = "排序(数字越小越靠前)")
|
||||
private Integer sortNumber;
|
||||
|
||||
@Schema(description = "状态, 0正常, 1冻结")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "是否删除, 0否, 1是")
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@Schema(description = "真实姓名")
|
||||
@TableField(exist = false)
|
||||
private String realName;
|
||||
|
||||
@Schema(description = "租户id")
|
||||
private Integer tenantId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "修改时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package com.gxwebsoft.credit.excel;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Excel 导入表头别名。
|
||||
*
|
||||
* <p>EasyPOI 的 {@code @Excel(name=...)} 仅支持一个表头名;当上游模板存在多种表头写法时,
|
||||
* 可用此注解声明别名,让 {@link com.gxwebsoft.credit.controller.ExcelImportSupport} 在导入前把别名规范化为 canonical 表头。</p>
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface ExcelHeaderAlias {
|
||||
|
||||
/**
|
||||
* 允许匹配的表头别名列表(任意一个匹配即视为该列)。
|
||||
*/
|
||||
String[] value();
|
||||
}
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.gxwebsoft.credit.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.gxwebsoft.credit.entity.CreditAdministrativeLicense;
|
||||
import com.gxwebsoft.credit.param.CreditAdministrativeLicenseParam;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 行政许可Mapper
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-01-07 13:52:13
|
||||
*/
|
||||
public interface CreditAdministrativeLicenseMapper extends BaseMapper<CreditAdministrativeLicense> {
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param page 分页对象
|
||||
* @param param 查询参数
|
||||
* @return List<CreditAdministrativeLicense>
|
||||
*/
|
||||
List<CreditAdministrativeLicense> selectPageRel(@Param("page") IPage<CreditAdministrativeLicense> page,
|
||||
@Param("param") CreditAdministrativeLicenseParam param);
|
||||
|
||||
/**
|
||||
* 查询全部
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return List<User>
|
||||
*/
|
||||
List<CreditAdministrativeLicense> selectListRel(@Param("param") CreditAdministrativeLicenseParam param);
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.gxwebsoft.credit.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.gxwebsoft.credit.entity.CreditBankruptcy;
|
||||
import com.gxwebsoft.credit.param.CreditBankruptcyParam;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 破产重整Mapper
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-01-07 13:52:14
|
||||
*/
|
||||
public interface CreditBankruptcyMapper extends BaseMapper<CreditBankruptcy> {
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param page 分页对象
|
||||
* @param param 查询参数
|
||||
* @return List<CreditBankruptcy>
|
||||
*/
|
||||
List<CreditBankruptcy> selectPageRel(@Param("page") IPage<CreditBankruptcy> page,
|
||||
@Param("param") CreditBankruptcyParam param);
|
||||
|
||||
/**
|
||||
* 查询全部
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return List<User>
|
||||
*/
|
||||
List<CreditBankruptcy> selectListRel(@Param("param") CreditBankruptcyParam param);
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.gxwebsoft.credit.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.gxwebsoft.credit.entity.CreditBranch;
|
||||
import com.gxwebsoft.credit.param.CreditBranchParam;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分支机构Mapper
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-01-07 13:52:14
|
||||
*/
|
||||
public interface CreditBranchMapper extends BaseMapper<CreditBranch> {
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param page 分页对象
|
||||
* @param param 查询参数
|
||||
* @return List<CreditBranch>
|
||||
*/
|
||||
List<CreditBranch> selectPageRel(@Param("page") IPage<CreditBranch> page,
|
||||
@Param("param") CreditBranchParam param);
|
||||
|
||||
/**
|
||||
* 查询全部
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return List<User>
|
||||
*/
|
||||
List<CreditBranch> selectListRel(@Param("param") CreditBranchParam param);
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.gxwebsoft.credit.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.gxwebsoft.credit.entity.CreditBreachOfTrust;
|
||||
import com.gxwebsoft.credit.param.CreditBreachOfTrustParam;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 失信被执行人Mapper
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:46:14
|
||||
*/
|
||||
public interface CreditBreachOfTrustMapper extends BaseMapper<CreditBreachOfTrust> {
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param page 分页对象
|
||||
* @param param 查询参数
|
||||
* @return List<CreditBreachOfTrust>
|
||||
*/
|
||||
List<CreditBreachOfTrust> selectPageRel(@Param("page") IPage<CreditBreachOfTrust> page,
|
||||
@Param("param") CreditBreachOfTrustParam param);
|
||||
|
||||
/**
|
||||
* 查询全部
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return List<User>
|
||||
*/
|
||||
List<CreditBreachOfTrust> selectListRel(@Param("param") CreditBreachOfTrustParam param);
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.gxwebsoft.credit.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.gxwebsoft.credit.entity.CreditCaseFiling;
|
||||
import com.gxwebsoft.credit.param.CreditCaseFilingParam;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 司法大数据Mapper
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:47:22
|
||||
*/
|
||||
public interface CreditCaseFilingMapper extends BaseMapper<CreditCaseFiling> {
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param page 分页对象
|
||||
* @param param 查询参数
|
||||
* @return List<CreditCaseFiling>
|
||||
*/
|
||||
List<CreditCaseFiling> selectPageRel(@Param("page") IPage<CreditCaseFiling> page,
|
||||
@Param("param") CreditCaseFilingParam param);
|
||||
|
||||
/**
|
||||
* 查询全部
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return List<User>
|
||||
*/
|
||||
List<CreditCaseFiling> selectListRel(@Param("param") CreditCaseFilingParam param);
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.gxwebsoft.credit.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.gxwebsoft.credit.entity.CreditCompany;
|
||||
import com.gxwebsoft.credit.param.CreditCompanyParam;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 企业Mapper
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-17 08:28:03
|
||||
*/
|
||||
public interface CreditCompanyMapper extends BaseMapper<CreditCompany> {
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param page 分页对象
|
||||
* @param param 查询参数
|
||||
* @return List<CreditCompany>
|
||||
*/
|
||||
List<CreditCompany> selectPageRel(@Param("page") IPage<CreditCompany> page,
|
||||
@Param("param") CreditCompanyParam param);
|
||||
|
||||
/**
|
||||
* 查询全部
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return List<User>
|
||||
*/
|
||||
List<CreditCompany> selectListRel(@Param("param") CreditCompanyParam param);
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.gxwebsoft.credit.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.gxwebsoft.credit.entity.CreditCompetitor;
|
||||
import com.gxwebsoft.credit.param.CreditCompetitorParam;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 竞争对手Mapper
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:49:04
|
||||
*/
|
||||
public interface CreditCompetitorMapper extends BaseMapper<CreditCompetitor> {
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param page 分页对象
|
||||
* @param param 查询参数
|
||||
* @return List<CreditCompetitor>
|
||||
*/
|
||||
List<CreditCompetitor> selectPageRel(@Param("page") IPage<CreditCompetitor> page,
|
||||
@Param("param") CreditCompetitorParam param);
|
||||
|
||||
/**
|
||||
* 查询全部
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return List<User>
|
||||
*/
|
||||
List<CreditCompetitor> selectListRel(@Param("param") CreditCompetitorParam param);
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.gxwebsoft.credit.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.gxwebsoft.credit.entity.CreditCourtAnnouncement;
|
||||
import com.gxwebsoft.credit.param.CreditCourtAnnouncementParam;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 法院公告司法大数据Mapper
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:49:13
|
||||
*/
|
||||
public interface CreditCourtAnnouncementMapper extends BaseMapper<CreditCourtAnnouncement> {
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param page 分页对象
|
||||
* @param param 查询参数
|
||||
* @return List<CreditCourtAnnouncement>
|
||||
*/
|
||||
List<CreditCourtAnnouncement> selectPageRel(@Param("page") IPage<CreditCourtAnnouncement> page,
|
||||
@Param("param") CreditCourtAnnouncementParam param);
|
||||
|
||||
/**
|
||||
* 查询全部
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return List<User>
|
||||
*/
|
||||
List<CreditCourtAnnouncement> selectListRel(@Param("param") CreditCourtAnnouncementParam param);
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.gxwebsoft.credit.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.gxwebsoft.credit.entity.CreditCourtSession;
|
||||
import com.gxwebsoft.credit.param.CreditCourtSessionParam;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 开庭公告司法大数据Mapper
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:49:32
|
||||
*/
|
||||
public interface CreditCourtSessionMapper extends BaseMapper<CreditCourtSession> {
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param page 分页对象
|
||||
* @param param 查询参数
|
||||
* @return List<CreditCourtSession>
|
||||
*/
|
||||
List<CreditCourtSession> selectPageRel(@Param("page") IPage<CreditCourtSession> page,
|
||||
@Param("param") CreditCourtSessionParam param);
|
||||
|
||||
/**
|
||||
* 查询全部
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return List<User>
|
||||
*/
|
||||
List<CreditCourtSession> selectListRel(@Param("param") CreditCourtSessionParam param);
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.gxwebsoft.credit.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.gxwebsoft.credit.entity.CreditCustomer;
|
||||
import com.gxwebsoft.credit.param.CreditCustomerParam;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 客户Mapper
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-21 21:20:58
|
||||
*/
|
||||
public interface CreditCustomerMapper extends BaseMapper<CreditCustomer> {
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param page 分页对象
|
||||
* @param param 查询参数
|
||||
* @return List<CreditCustomer>
|
||||
*/
|
||||
List<CreditCustomer> selectPageRel(@Param("page") IPage<CreditCustomer> page,
|
||||
@Param("param") CreditCustomerParam param);
|
||||
|
||||
/**
|
||||
* 查询全部
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return List<User>
|
||||
*/
|
||||
List<CreditCustomer> selectListRel(@Param("param") CreditCustomerParam param);
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.gxwebsoft.credit.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.gxwebsoft.credit.entity.CreditDeliveryNotice;
|
||||
import com.gxwebsoft.credit.param.CreditDeliveryNoticeParam;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 送达公告司法大数据Mapper
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:49:51
|
||||
*/
|
||||
public interface CreditDeliveryNoticeMapper extends BaseMapper<CreditDeliveryNotice> {
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param page 分页对象
|
||||
* @param param 查询参数
|
||||
* @return List<CreditDeliveryNotice>
|
||||
*/
|
||||
List<CreditDeliveryNotice> selectPageRel(@Param("page") IPage<CreditDeliveryNotice> page,
|
||||
@Param("param") CreditDeliveryNoticeParam param);
|
||||
|
||||
/**
|
||||
* 查询全部
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return List<User>
|
||||
*/
|
||||
List<CreditDeliveryNotice> selectListRel(@Param("param") CreditDeliveryNoticeParam param);
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.gxwebsoft.credit.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.gxwebsoft.credit.entity.CreditExternal;
|
||||
import com.gxwebsoft.credit.param.CreditExternalParam;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 对外投资Mapper
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:50:11
|
||||
*/
|
||||
public interface CreditExternalMapper extends BaseMapper<CreditExternal> {
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param page 分页对象
|
||||
* @param param 查询参数
|
||||
* @return List<CreditExternal>
|
||||
*/
|
||||
List<CreditExternal> selectPageRel(@Param("page") IPage<CreditExternal> page,
|
||||
@Param("param") CreditExternalParam param);
|
||||
|
||||
/**
|
||||
* 查询全部
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return List<User>
|
||||
*/
|
||||
List<CreditExternal> selectListRel(@Param("param") CreditExternalParam param);
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.gxwebsoft.credit.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.gxwebsoft.credit.entity.CreditFinalVersion;
|
||||
import com.gxwebsoft.credit.param.CreditFinalVersionParam;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 终本案件Mapper
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:50:19
|
||||
*/
|
||||
public interface CreditFinalVersionMapper extends BaseMapper<CreditFinalVersion> {
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param page 分页对象
|
||||
* @param param 查询参数
|
||||
* @return List<CreditFinalVersion>
|
||||
*/
|
||||
List<CreditFinalVersion> selectPageRel(@Param("page") IPage<CreditFinalVersion> page,
|
||||
@Param("param") CreditFinalVersionParam param);
|
||||
|
||||
/**
|
||||
* 查询全部
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return List<User>
|
||||
*/
|
||||
List<CreditFinalVersion> selectListRel(@Param("param") CreditFinalVersionParam param);
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.gxwebsoft.credit.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.gxwebsoft.credit.entity.CreditGqdj;
|
||||
import com.gxwebsoft.credit.param.CreditGqdjParam;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 股权冻结Mapper
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:50:37
|
||||
*/
|
||||
public interface CreditGqdjMapper extends BaseMapper<CreditGqdj> {
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param page 分页对象
|
||||
* @param param 查询参数
|
||||
* @return List<CreditGqdj>
|
||||
*/
|
||||
List<CreditGqdj> selectPageRel(@Param("page") IPage<CreditGqdj> page,
|
||||
@Param("param") CreditGqdjParam param);
|
||||
|
||||
/**
|
||||
* 查询全部
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return List<User>
|
||||
*/
|
||||
List<CreditGqdj> selectListRel(@Param("param") CreditGqdjParam param);
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.gxwebsoft.credit.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.gxwebsoft.credit.entity.CreditHistoricalLegalPerson;
|
||||
import com.gxwebsoft.credit.param.CreditHistoricalLegalPersonParam;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 历史法定代表人Mapper
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2026-01-07 13:52:14
|
||||
*/
|
||||
public interface CreditHistoricalLegalPersonMapper extends BaseMapper<CreditHistoricalLegalPerson> {
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param page 分页对象
|
||||
* @param param 查询参数
|
||||
* @return List<CreditHistoricalLegalPerson>
|
||||
*/
|
||||
List<CreditHistoricalLegalPerson> selectPageRel(@Param("page") IPage<CreditHistoricalLegalPerson> page,
|
||||
@Param("param") CreditHistoricalLegalPersonParam param);
|
||||
|
||||
/**
|
||||
* 查询全部
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return List<User>
|
||||
*/
|
||||
List<CreditHistoricalLegalPerson> selectListRel(@Param("param") CreditHistoricalLegalPersonParam param);
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.gxwebsoft.credit.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.gxwebsoft.credit.entity.CreditJudgmentDebtor;
|
||||
import com.gxwebsoft.credit.param.CreditJudgmentDebtorParam;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 被执行人Mapper
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:50:55
|
||||
*/
|
||||
public interface CreditJudgmentDebtorMapper extends BaseMapper<CreditJudgmentDebtor> {
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param page 分页对象
|
||||
* @param param 查询参数
|
||||
* @return List<CreditJudgmentDebtor>
|
||||
*/
|
||||
List<CreditJudgmentDebtor> selectPageRel(@Param("page") IPage<CreditJudgmentDebtor> page,
|
||||
@Param("param") CreditJudgmentDebtorParam param);
|
||||
|
||||
/**
|
||||
* 查询全部
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return List<User>
|
||||
*/
|
||||
List<CreditJudgmentDebtor> selectListRel(@Param("param") CreditJudgmentDebtorParam param);
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.gxwebsoft.credit.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.gxwebsoft.credit.entity.CreditJudicialDocument;
|
||||
import com.gxwebsoft.credit.param.CreditJudicialDocumentParam;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 裁判文书司法大数据Mapper
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-19 19:51:02
|
||||
*/
|
||||
public interface CreditJudicialDocumentMapper extends BaseMapper<CreditJudicialDocument> {
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param page 分页对象
|
||||
* @param param 查询参数
|
||||
* @return List<CreditJudicialDocument>
|
||||
*/
|
||||
List<CreditJudicialDocument> selectPageRel(@Param("page") IPage<CreditJudicialDocument> page,
|
||||
@Param("param") CreditJudicialDocumentParam param);
|
||||
|
||||
/**
|
||||
* 查询全部
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return List<User>
|
||||
*/
|
||||
List<CreditJudicialDocument> selectListRel(@Param("param") CreditJudicialDocumentParam param);
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.gxwebsoft.credit.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.gxwebsoft.credit.entity.CreditJudiciary;
|
||||
import com.gxwebsoft.credit.param.CreditJudiciaryParam;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 司法案件Mapper
|
||||
*
|
||||
* @author 科技小王子
|
||||
* @since 2025-12-16 15:23:58
|
||||
*/
|
||||
public interface CreditJudiciaryMapper extends BaseMapper<CreditJudiciary> {
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param page 分页对象
|
||||
* @param param 查询参数
|
||||
* @return List<CreditJudiciary>
|
||||
*/
|
||||
List<CreditJudiciary> selectPageRel(@Param("page") IPage<CreditJudiciary> page,
|
||||
@Param("param") CreditJudiciaryParam param);
|
||||
|
||||
/**
|
||||
* 查询全部
|
||||
*
|
||||
* @param param 查询参数
|
||||
* @return List<User>
|
||||
*/
|
||||
List<CreditJudiciary> selectListRel(@Param("param") CreditJudiciaryParam param);
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user