Compare commits

..

55 Commits

Author SHA1 Message Date
89177db718 fix(core): 修复LocalDateTime反序列化和微信支付参数验证问题
- 移除JacksonConfig中未使用的LocalDateTimeDeserializer导入
- 增强LocalDateTimeDeserializer支持时间戳格式解析,兼容前端发送的数字时间戳
- 添加构造函数支持自定义日期时间格式器
- 修复ShopDealerWithdrawController中微信支付批次号长度不足问题,使用零填充确保最小长度
- 添加微信支付服务中outBatchNo和outDetailNo参数长度验证规则
- 移除WxTransferService中的冗余代码行
2026-01-29 01:19:51 +08:00
d93dd04211 feat(withdraw): 实现分销商提现微信自动转账功能
- 新增 WxTransferService 服务类实现微信商家转账到零钱功能
- 在 ShopDealerWithdrawController 中集成微信转账服务
- 修改 update 方法支持微信收款方式的自动转账处理
- 添加事务管理确保转账操作的数据一致性
- 实现转账参数验证和错误处理机制
- 支持通过 openid 自动获取和用户姓名验证
- 添加转账金额转换和批次号生成逻辑
2026-01-29 00:28:47 +08:00
a3e812a9c4 feat(data): 更新公司记录计数服务并优化导入功能
- 在多个控制器中引入 CreditCompanyRecordCountService 依赖注入
- 添加 HashSet 和 Set 类型导入以支持公司ID集合操作
- 在Excel导入过程中跟踪受影响的公司ID集合
- 实现导入完成后批量刷新公司记录计数的功能
- 扩展 CreditCompany 实体类添加各类信用记录计数字段
- 优化导入逻辑确保公司记录计数实时更新
2026-01-28 21:46:45 +08:00
5e804bbf9a feat(data): 更新公司记录计数服务并优化导入功能
- 在多个控制器中引入 CreditCompanyRecordCountService 依赖注入
- 添加 HashSet 和 Set 类型导入以支持公司ID集合操作
- 在Excel导入过程中跟踪受影响的公司ID集合
- 实现导入完成后批量刷新公司记录计数的功能
- 扩展 CreditCompany 实体类添加各类信用记录计数字段
- 优化导入逻辑确保公司记录计数实时更新
2026-01-28 21:46:30 +08:00
ad2562c06e feat(order): 添加单一商品订单的formId更新逻辑
- 在OrderBusinessService中添加单一商品订单的formId设置功能
- 在ShopOrderServiceImpl中实现订单商品数量为1时的formId更新逻辑
- 确保只有当订单中只有一个商品时才更新formId字段
2026-01-28 17:13:32 +08:00
5a95375cda feat(settlement): 更新分销结算逻辑支持固定金额和百分比两种佣金类型
- 替换 CommissionRateConfig 为 CommissionConfig,支持 commissionType 字段区分固定金额和百分比模式
- 新增 calcMoneyByCommissionType 方法,根据 commissionType 计算佣金金额
- 修改 findOrderSingleGoods 为 findOrderSingleGoodsInfo,返回商品信息和数量
- 更新日志输出格式,显示商品数量和佣金类型信息
- 调整信用分销商佣金方法参数,传递商品数量和佣金配置对象
- 新增 OrderGoodsInfo 和 CommissionConfig 内部类定义
- 实现固定金额模式按件计算佣金的逻辑
- 添加安全数值处理方法 safeValue 和 safePositive
- 更新佣金注释构建方法,显示佣金类型和具体数值信息
2026-01-28 16:05:24 +08:00
9e5c5ceab3 feat(settlement): 更新分销结算逻辑支持固定金额和百分比两种佣金类型
- 替换 CommissionRateConfig 为 CommissionConfig,支持 commissionType 字段区分固定金额和百分比模式
- 新增 calcMoneyByCommissionType 方法,根据 commissionType 计算佣金金额
- 修改 findOrderSingleGoods 为 findOrderSingleGoodsInfo,返回商品信息和数量
- 更新日志输出格式,显示商品数量和佣金类型信息
- 调整信用分销商佣金方法参数,传递商品数量和佣金配置对象
- 新增 OrderGoodsInfo 和 CommissionConfig 内部类定义
- 实现固定金额模式按件计算佣金的逻辑
- 添加安全数值处理方法 safeValue 和 safePositive
- 更新佣金注释构建方法,显示佣金类型和具体数值信息
2026-01-28 15:11:22 +08:00
fa53fd399f feat(task): 完善经销商订单结算功能支持三级分销和商品级别配置
- 引入商品实体和订单商品实体依赖,新增相关服务注入
- 实现商品分销开关检查,未开启分销的商品跳过结算流程
- 添加三级分销佣金计算逻辑,支持第三级经销商佣金结算
- 实现商品级别的分润比例配置,支持按商品设置不同的佣金率
- 新增商品分销配置解析功能,兼容旧版固定比例逻辑
- 扩展分佣记录实体,增加第三级用户和金额字段
- 更新日志输出格式,显示详细的分润比例和金额信息
- 优化门店分红计算,支持单门店汇总分润和多门店分级分润
2026-01-28 14:49:49 +08:00
cbc9a1c861 fix(shop): 修复分销订单结算中的文案和逻辑错误
- 修复CmsOrderController中save方法的空行格式问题
- 将所有"简推"相关文案统一更正为"间推",包括注释和日志输出
- 修正ShopRoleCommission方法中的佣金类型描述从"简推"改为"间推"
- 修复门店分红规则描述中的术语一致性
- 修正ShopDealerOrderMapper.xml中的重复条件查询逻辑,
2026-01-28 14:00:20 +08:00
3814711ec4 feat(cms): 添加网站订单管理功能
- 创建 CmsOrder 实体类,包含订单基本信息、支付信息、物流信息等完整字段
- 实现 CmsOrderController 控制器,提供增删改查及批量操作接口
- 开发 CmsOrderMapper 数据访问层,集成 MyBatis-Plus 基础功能
- 配置 CmsOrderMapper.xml XML 映射文件,实现关联查询 SQL 语句
- 定义 CmsOrderParam 查询参数类,支持多条件动态查询
- 构建 CmsOrderService 业务接口及其实现类,封装订单业务逻辑
- 集成 Swagger 文档注解,提供 API 接口文档支持
- 添加权限控制注解,确保接口安全性
- 实现分页查询、列表查询、单条查询等多种数据获取方式
2026-01-27 13:22:37 +08:00
e4d4a19020 feat(settlement): 调整门店直推佣金比例并完善用户信息展示
- 将门店直推佣金从2%调整为3%(仅1门店情况)
- 新增RATE_0_03常量用于门店直推佣金计算
- 在ShopDealerCapital实体中添加分销商昵称字段
- 在ShopDealerOrder实体中添加门店名称字段
- 在ShopDealerUser实体中添加头像字段
- 更新Mapper XML文件以关联查询用户昵称和头像信息
- 修改日志输出信息以反映新的佣金比例和门店信息
2026-01-26 23:02:05 +08:00
3b63172012 refactor(task): 重构经销商订单结算任务中的上级用户查找逻辑
- 引入 UpstreamUserFinder 工具类来统一处理向上游用户链路的遍历逻辑
- 添加缓存机制减少数据库查询次数,提高性能
- 修改 settleOneOrder 方法签名以传递缓存对象
- 更新门店分红上级查找逻辑,从简单的链路取前两级改为精确查找门店角色用户
- 删除废弃的 ShopOrderSettlement10584Task 临时排查任务类
- 添加 UpstreamUserFinder 的单元测试确保逻辑正确性
2026-01-26 12:34:56 +08:00
803ac3301e refactor(task): 优化经销商订单结算任务的推荐关系查询逻辑
- 移除废弃的 isShopRole 扩展字段及相关 SQL 查询
- 将推荐关系查询逻辑改为基于 level=1 链路的简单向上遍历
- 添加分红金额计算精度控制,使用 3 位小数精度
- 调整定时任务执行频率从 30 秒改为 20 秒
- 优化订单结算时的分红用户和金额更新逻辑,支持增量更新
- 新增一次性排查任务用于调试订单推荐关系链路问题
2026-01-26 11:52:53 +08:00
375a65be6a refactor(task): 优化门店分佣逻辑按type字段判定
- 替换原有的角色shop判定逻辑,改为按ShopDealerUser.type=1判定门店分红用户
- 新增User和UserMapper依赖注入用于获取用户基础信息
- 添加幂等检查机制避免同一订单重复发放佣金
- 在创建分销商账户时补充基础信息防止字段约束导致插入失败
- 优化SQL查询逻辑,直接关联shop_dealer_user表而非查询系统角色表
- 更新日志信息中的描述文字以反映新的判定方式
- 添加对已存在订单记录的回填功能,支持补发门店分佣时更新分红字段
2026-01-26 01:01:13 +08:00
918190148b refactor(settlement): 优化经销商订单结算逻辑
- 移除不必要的UserRoleService依赖注入
- 将定时任务执行频率从每20秒调整为每30秒
- 删除过期的shopRoleCache缓存机制
- 重构推荐关系查询逻辑,支持多级关系和门店角色识别
- 添加对两种数据形态的兼容处理(level=1/2多级关系 vs 仅level=1关系)
- 修改佣金分配逻辑,区分直推佣金和推荐奖金
- 优化门店角色佣金计算,调整为直推2%和简推1%
- 添加分销商账户自动创建机制,确保佣金能够正常发放
- 更新资金明细记录,准确关联到对应的用户ID
- 新增自定义SQL查询方法,一次性获取推荐关系链路和门店角色信息
- 扩展ShopDealerReferee实体,增加isShopRole扩展字段
- 优化MyBatis XML映射,使用LEFT JOIN预加载角色信息避免N+1查询问题
2026-01-26 00:14:34 +08:00
d15cc03e48 feat(credit): 扩展信用实体并调整经销商结算逻辑
- 在CreditXgxf实体中添加原告/上诉人和被告/被上诉人字段
- 调整经销商订单结算任务中的佣金费率配置
- 修改简推佣金计算逻辑,允许同一个人获得双重佣金
- 更新门店推广佣金分配策略,第二名佣金从8%降至1%
- 扩展店铺经销商订单查询条件以支持更多用户层级
2026-01-25 12:08:36 +08:00
0035d3cd7d fix(search): 修复查询条件中的字段映射错误
- 移除无效的 code 字段查询条件
- 修正关键词搜索中错误的字段引用,将 code 替换为 case_number
- 清理多余的参数绑定表达式
2026-01-23 23:15:23 +08:00
08ab8da7d9 feat(order): 添加门店分红相关字段
- 添加门店(一级)字段 firstDividendUser
- 添加分红(一级)字段 firstDividend
- 添加门店(二级)字段 secondDividendUser
- 添加分红(二级)字段 secondDividend
- 为新增字段添加 Swagger 文档注解
- 保持原有分销佣金字段结构不变
2026-01-23 15:56:50 +08:00
06c20b8418 feat(settlement): 优化经销商订单结算任务并添加案件编号搜索功能
- 在多个信用查询映射文件中添加案件编号关键词搜索条件
- 在CreditGqdjMapper中添加代码字段搜索过滤器
- 修改结算任务逻辑,将void方法改为返回详细佣金信息的对象
- 添加经销商订单记录创建功能,用于结算追踪和统计
- 增加详细的日志记录便于调试和监控
- 添加防止重复结算的幂等功能
- 重构佣金计算逻辑,支持更精确的分佣跟踪
2026-01-23 14:11:28 +08:00
16e5e31f33 feat(credit): 添加数据类型字段支持
- 在CreditXgxf实体类中新增type字段并添加Swagger文档注解
- 在CreditXgxfController控制器中设置导入参数的type字段值
- 在CreditXgxfImportParam导入参数类中新增type字段并配置Excel映射
- 在CreditXgxfParam参数类中新增type字段并添加Swagger文档注解
2026-01-23 13:35:24 +08:00
afa5dd8ab2 feat(task): 添加租户10584分销订单结算定时任务
- 实现每20秒执行一次的定时任务,处理已付款且未结算的订单
- 添加直推和简推佣金计算逻辑,按10%比例发放
- 实现shop角色推荐人佣金分配,支持最多两级推荐
- 添加订单认领机制防止重复结算,并使用事务模板确保数据一致性
- 实现分销商账户余额累加和资金流水记录功能
- 添加缓存机制减少重复角色查询,提升性能
2026-01-23 00:22:54 +08:00
4ffc62fef1 feat(task): 添加租户10584分销订单结算定时任务
- 实现每20秒执行一次的定时任务,处理已付款且未结算的订单
- 添加直推和简推佣金计算逻辑,按10%比例发放
- 实现shop角色推荐人佣金分配,支持最多两级推荐
- 添加订单认领机制防止重复结算,并使用事务模板确保数据一致性
- 实现分销商账户余额累加和资金流水记录功能
- 添加缓存机制减少重复角色查询,提升性能
2026-01-23 00:20:36 +08:00
757291f256 config(application): 重命名测试配置文件并调整端口
- 将 application-test.yml 重命名为 application-cms.yml
- 将服务器端口从 9300 修改为 9100
- 在 ShopDealerReferee 实体类中为 source 和 scene 字段添加 @TableField(exist = false) 注解
- 移除 ShopDealerUserController 中 save 方法的权限验证注解和操作日志注解
2026-01-22 20:32:49 +08:00
f40010433d feat(credit): 添加主体企业名称关联查询功能
- 在多个实体类中添加companyName字段用于显示主体企业名称
- 修改XML映射文件实现与credit_company表的左连接查询
- 将企业名称作为companyName字段返回到查询结果中
- 修复CreditBranch实体类中字段描述的一致性问题
- 更新CreditNearbyCompany的关键词搜索逻辑以支持企业名称搜索
2026-01-22 08:51:32 +08:00
a6aba2c49b feat(shop): 添加客户编号查询功能
- 在 ShopDealerApplyParam 中新增 dealerCode 字段用于客户编号查询
- 在 ShopDealerApplyMapper.xml 中添加 dealer_code 查询条件
- 实现按客户编号精确匹配的查询逻辑
- 更新参数校验和文档注释
2026-01-21 17:40:51 +08:00
492928667a feat(shop): 添加分销商申请地址详情字段
- 在 ShopDealerApply 实体类中新增社区、楼栋号、单元号、房号字段
- 更新 ShopDealerApplyController 中的 Excel 导入功能,修改表头格式说明
- 在控制器中添加测试数据并完善实体对象设置逻辑
- 扩展 ShopDealerApplyImportParam 参数类,增加地址相关字段映射
- 更新 ShopDealerApplyMapper.xml 添加地址查询条件
- 在 ShopDealerApplyParam 查询参数类中添加地址过滤字段
- 统一多个信用模块的关键词搜索逻辑,从精确匹配改为模糊匹配
2026-01-21 17:34:47 +08:00
416027ffe8 feat(navigation): 添加网站导航导入参数类
- 创建 CmsNavigationImportParam 类用于 Excel 批量导入功能
- 定义导航ID、类型、菜单名称等基础字段映射
- 添加上级id、模型、标识等关联属性配置
- 集成路径、组件、打开位置等路由相关字段
- 包含图标、颜色、隐藏设置等UI显示属性
- 实现权限控制、访问密码等安全相关字段
- 添加位置、顶部底部显示等布局控制选项
- 配置活动路径、元信息、样式等扩展功能
- 整合模型名称、页面ID、详情页ID等数据关联
- 支持微信小程序菜单、间距宽度等特殊设置
- 包含阅读量、商户ID、语言等业务相关字段
- 添加设为首页、推荐、排序等管理功能
- 配置备注、状态、用户及租户ID等系统属性
- 使用 EasyPOI 注解实现 Excel 数据映射
- 继承 Serializable 接口支持序列化操作
2026-01-21 17:15:34 +08:00
30924cb7c3 feat(navigation): 添加网站导航导入参数类
- 创建 CmsNavigationImportParam 类用于 Excel 批量导入功能
- 定义导航ID、类型、菜单名称等基础字段映射
- 添加上级id、模型、标识等关联属性配置
- 集成路径、组件、打开位置等路由相关字段
- 包含图标、颜色、隐藏设置等UI显示属性
- 实现权限控制、访问密码
2026-01-21 13:18:13 +08:00
0104eccd34 feat(controller): 新增企业ID批量更新功能
- 在BatchImportSupport中添加CompanyIdRefreshStats统计类
- 实现基于企业名称匹配的companyId批量更新逻辑
- 添加normalizeCompanyName和addCompanyNameMapping辅助方法
- 在各个Credit控制器中注入CreditCompanyService依赖
- 为所有相关控制器添加/company-id/refresh接口端点
- 实现多租户环境下的安全匹配和更新机制
- 支持limit参数控制批量处理数量
- 提供详细的更新统计数据返回
2026-01-21 13:18:00 +08:00
7ba034ab1e feat(controller): 新增企业ID批量更新功能
- 在BatchImportSupport中添加CompanyIdRefreshStats统计类
- 实现基于企业名称匹配的companyId批量更新逻辑
- 添加normalizeCompanyName和addCompanyNameMapping辅助方法
- 在各个Credit控制器中注入CreditCompanyService依赖
- 为所有相关控制器添加/company-id/refresh接口端点
- 实现多租户环境下的安全匹配和更新机制
- 支持limit参数控制批量处理数量
- 提供详细的更新统计数据返回
2026-01-20 22:13:06 +08:00
15fc17e54b fix(credit): 修复债务人公司ID匹配逻辑
- 将默认更新条件从 companyId 为空改为 companyId=0
- 修改查询条件从 isNull 改为等于 0 的判断
- 更新业务逻辑中对 needUpdate 的判断条件

docs(shop): 添加经销商推荐绑定接口文档

- 新增 SHOP_DEALER_REFEREE_BINDING.md 文档
- 定义 POST /api/shop/shop-dealer-referee 接口规则
- 说明邀请人有效性验证和防止自绑限制
- 描述首次绑定幂等性和溯源字段要求
- 提供数据库唯一索引建议和建表语句
2026-01-20 17:25:28 +08:00
7487236ac6 feat(credit): 添加被执行人企业关联匹配功能
- 在 CreditJudgmentDebtorController 中新增 refreshCompanyIdByCompanyName 接口
- 实现根据企业名称自动匹配并更新 companyId 的批量处理逻辑
- 支持按租户维度进行企业名称匹配,避免跨租户误匹配
- 添加企业名称标准化处理和模糊匹配机制
- 实现批量更新和事务管理,提升处理效率
- 优化关键词搜索条件,精确匹配企业名称而非模糊匹配
- 添加公司名称规范化方法 normalizeCompanyName
- 修复竞品表字段别名从 mainCompanyName 改为 companyName

feat(shop): 优化分销商推荐关系绑定机制

- 修改 ShopDealerRefereeController 的 save 方法为幂等绑定
- 新增 bindFirstLevel 方法实现一级推荐关系的幂等绑定
- 添加用户身份验证和安全校验机制
- 增加 source 和 scene 字段支持来源追踪
- 实现重复绑定防护和业务异常处理
- 添加经销商有效性校验机制
2026-01-20 17:02:59 +08:00
1898d3ac9b refactor(user-card): 优化用户卡包统计数据获取逻辑
- 移除对UserService的依赖,改为使用UserCardStatsMapper直接查询
- 新增UserCardStatsMapper接口用于跨库查询用户余额和积分
- 添加MyBatis XML映射文件实现跨库查询gxwebsoft_core.sys_user表
- 实现类型转换工具方法toBigDecimal和toIntObj确保数据类型安全
- 修复因模块间依赖导致无法访问sys_user表的问题
- 保持租户隔离支持,确保数据安全性
2026-01-20 14:07:31 +08:00
8e5271ae38 feat(shop): 添加用户订单和卡包统计功能
- 在 ShopOrderMapper 中新增 selectUserOrderStats 方法用于订单状态统计
- 在 ShopOrderService 和 ShopOrderServiceImpl 中实现用户订单统计功能
- 添加 UserOrderStats DTO 类定义订单各状态数量统计
- 创建 UserOrderController 提供用户订单统计 API 接口
- 实现用户卡包统计功能,包括余额、积分、优惠券、礼品卡统计
- 添加 UserCardController 和 UserCardStats DTO 类
- 优化 Swagger 配置以支持 /api/user/** 路径的 API 文档
- 为统计接口添加 Redis 缓存以提升性能
- 清理 ShopOrderController 中不必要的导入依赖
2026-01-20 13:02:58 +08:00
b1b106c397 feat(shop): 添加用户订单和卡包统计功能
- 在 ShopOrderMapper 中新增 selectUserOrderStats 方法用于订单状态统计
- 在 ShopOrderService 和 ShopOrderServiceImpl 中实现用户订单统计功能
- 添加 UserOrderStats DTO 类定义订单各状态数量统计
- 创建 UserOrderController 提供用户订单统计 API 接口
- 实现用户卡包统计功能,包括余额、积分、优惠券、礼品卡统计
- 添加 UserCardController 和 UserCardStats DTO 类
- 优化 Swagger 配置以支持 /api/user/** 路径的 API 文档
- 为统计接口添加 Redis 缓存以提升性能
- 清理 ShopOrderController 中不必要的导入依赖
2026-01-20 13:00:41 +08:00
ceaaf287b0 feat(login): 添加微信登录中的应用运行状态检查功能
- 引入 CmsWebsite 和 CmsWebsiteService 依赖
- 注入 CmsWebsiteService 服务实例
- 实现基于租户ID的应用运行状态判断逻辑
- 根据运行状态动态设置页面检查路径和环境版本参数
- 当应用状态为试用模式时禁用路径检查并切换到试用环境
2026-01-20 11:21:40 +08:00
e36524de3a feat(credit): 添加用户真实姓名关联查询功能
- 在多个实体类中添加 realName 字段用于显示用户真实姓名
- 更新 XML 映射文件以关联查询 sys_user 表中的真实姓名
- 统一为所有信用相关实体添加真实姓名查询支持
- 修复了多个实体缺少 TableField 注解导入的问题
- 实现了跨库关联查询以获取用户的完整信息
2026-01-20 01:41:44 +08:00
e647a5d066 feat(import): 添加批量导入功能支持历史数据处理
- 新增 upsertBySingleKeyAndIncrementCounterOnUpdate 方法用于单字段键匹配的批量更新插入操作
- 新增 upsertByCodeOrNameAndIncrementCounterOnUpdate 方法用于代码或名称匹配的批量更新插入操作
- 在 CreditAdministrativeLicenseController 中添加历史行政许可批量导入接口
- 在 CreditBankruptcyController 中添加历史破产重整批量导入接口
- 在 CreditBreachOfTrustController 中添加历史失信被执行人批量导入接口
- 在 CreditCourtSessionController 中添加历史开庭公告批量导入接口
- 实现基于案号或名称的重复数据检测和计数器递增逻辑
- 添加 Excel 文件解析和超链接读取功能支持
- 实现分块处理机制提高大批量数据导入性能
- 添加异常处理和错误消息收集机制确保导入过程稳定性
2026-01-20 00:53:58 +08:00
fc0dc99ccc feat(credit): 添加历史被执行人批量导入功能
- 新增 /import/history 接口支持历史被执行人数据批量导入
- 实现 Excel 和 ZIP 格式文件的历史被执行人数据解析
- 添加案号重复时取最后一条记录的去重逻辑
- 支持 ZIP 文件自动解压并逐个处理内部 Excel 文件
- 实现导入过程中的数据验证和错误信息收集
- 添加 hyperlink 链接提取功能用于案号和被执行人名称
- 实现按案号 upsert 更新或插入历史被执行人记录
- 支持导入时设置企业 ID、用户 ID 和租户 ID 等上下文信息
- 提供详细的导入结果统计包括成功和失败数量
- 删除不再使用的 CreditJudgmentDebtorHistory 相关代码文件
2026-01-20 00:24:32 +08:00
850c18d639 fix(import): 修复导入参数中的Excel注解配置
- 将dataType字段的@Schema注解替换为@Excel注解
- 将plaintiffAppellant字段的@Schema注解替换为@Excel注解
- 确保字段正确映射到Excel导入功能
2026-01-19 22:44:38 +08:00
c902bbd214 feat: 优化失信记录实体和导入功能
- 调整CreditBreachOfTrust实体中url字段的位置
- 为法院公告导入增加多sheet文件兼容性支持
- 为开庭公告导入增加多sheet文件兼容性支持
- 导入时优先查找指定名称的sheet,如"法院公告"或"开庭公告"
- 当指定sheet不存在时,默认使用第0个sheet进行导入
2026-01-19 21:56:22 +08:00
84e6222c4d refactor(credit): 重构竞争对手实体的公司名称字段
- 将 CreditCompetitor 实体中的 companyName 字段重命名为 name
- 保留 companyName 字段作为关联查询的临时字段(exist=false)
- 更新控制器中导入逻辑,使用 name 字段进行数据处理
- 修改 XML 映射文件中的查询条件,使用 name 替代 companyName
- 更新导入参数和查询参数类中的字段映射
- 修复专利控制器中的导入验证逻辑
- 调整外部投资企业实体的字段描述文案
2026-01-19 21:20:12 +08:00
ba683bd578 refactor(credit): 重构竞争对手实体的公司名称字段
- 将 CreditCompetitor 实体中的 companyName 字段重命名为 name
- 保留 companyName 字段作为关联查询的临时字段(exist=false)
- 更新控制器中导入逻辑,使用 name 字段进行数据处理
- 修改 XML 映射文件中的查询条件,使用 name 替代 companyName
- 更新导入参数和查询参数类中的字段映射
- 修复专利控制器中的导入验证逻辑
- 调整外部投资企业实体的字段描述文案
2026-01-19 17:26:28 +08:00
12fc77b35c feat(import): 实现Excel导入时链接地址自动提取功能
- 修改CreditAdministrativeLicense相关类将"许可类型"字段描述改为"许可类别"
- 在多个实体类(CreditBreachOfTrust、CreditCompetitor、CreditCourtAnnouncement等)中新增url字段用于存储链接地址
- 重构CreditCompany实体类调整字段顺序和位置
- 在各个控制器中实现Excel导入时链接地址的自动提取和填充逻辑
- 新增readKeyValueByHeaders方法支持从指定列读取键值对数据
- 新增readUrlByKey方法支持从超链接或独立列提取URL地址
- 优化Excel导入流程增加链接地址批量处理功能
- 修复EasyPOI无法读取单元格超链接地址的问题
2026-01-19 14:23:48 +08:00
071c44679a refactor(credit): 重构司法信用实体和导入参数结构
- 修改 CreditBreachOfTrust 实体字段定义,调整案号、当事人、涉案金额等字段映射
- 创建新的 CreditBreachOfTrustImportParam 导入参数类替代原有司法通用参数
- 更新 Controller 中的导入功能实现,使用新的参数类进行数据转换
- 调整查询条件过滤逻辑,移除不必要的字段匹配
- 为终本案件模块创建独立的导入参数类 CreditFinalVersionImportParam
- 优化导入模板生成逻辑,支持按标签页名称查找对应工作表
- 重构终本案件实体字段映射,调整被执行人和申请执行人字段定义
- 更新 Excel 导入验证逻辑,简化空行判断条件
2026-01-19 13:33:29 +08:00
f2f7595674 refactor(credit): 重构司法信用实体和导入参数结构
- 修改 CreditBreachOfTrust 实体字段定义,调整案号、当事人、涉案金额等字段映射
- 创建新的 CreditBreachOfTrustImportParam 导入参数类替代原有司法通用参数
- 更新 Controller 中的导入功能实现,使用新的参数类进行数据转换
- 调整查询条件过滤逻辑,移除不必要的字段匹配
- 为终本案件模块创建独立的导入参数类 CreditFinalVersionImportParam
- 优化导入模板生成逻辑,支持按标签页名称查找对应工作表
- 重构终本案件实体字段映射,调整被执行人和申请执行人字段定义
- 更新 Excel 导入验证逻辑,简化空行判断条件
2026-01-19 12:02:53 +08:00
f799c2d7ea refactor(credit): 重构司法信用实体和导入参数结构
- 修改 CreditBreachOfTrust 实体字段定义,调整案号、当事人、涉案金额等字段映射
- 创建新的 CreditBreachOfTrustImportParam 导入参数类替代原有司法通用参数
- 更新 Controller 中的导入功能实现,使用新的参数类进行数据转换
- 调整查询条件过滤逻辑,移除不必要的字段匹配
- 为终本案件模块创建独立的导入参数类 CreditFinalVersionImportParam
- 优化导入模板生成逻辑,支持按标签页名称查找对应工作表
- 重构终本案件实体字段映射,调整被执行人和申请执行人字段定义
- 更新 Excel 导入验证逻辑,简化空行判断条件
2026-01-19 11:59:44 +08:00
18f2903f35 refactor(credit): 重构司法信用实体和导入参数结构
- 修改 CreditBreachOfTrust 实体字段定义,调整案号、当事人、涉案金额等字段映射
- 创建新的 CreditBreachOfTrustImportParam 导入参数类替代原有司法通用参数
- 更新 Controller 中的导入功能实现,使用新的参数类进行数据转换
- 调整查询条件过滤逻辑,移除不必要的字段匹配
- 为终本案件模块创建独立的导入参数类 CreditFinalVersionImportParam
- 优化导入模板生成逻辑,支持按标签页名称查找对应工作表
- 重构终本案件实体字段映射,调整被执行人和申请执行人字段定义
- 更新 Excel 导入验证逻辑,简化空行判断条件
2026-01-19 00:05:11 +08:00
d7c15cb22f refactor(credit): 重构司法信用实体和导入参数结构
- 修改 CreditBreachOfTrust 实体字段定义,调整案号、当事人、涉案金额等字段映射
- 创建新的 CreditBreachOfTrustImportParam 导入参数类替代原有司法通用参数
- 更新 Controller 中的导入功能实现,使用新的参数类进行数据转换
- 调整查询条件过滤逻辑,移除不必要的字段匹配
- 为终本案件模块创建独立的导入参数类 CreditFinalVersionImportParam
- 优化导入模板生成逻辑,支持按标签页名称查找对应工作表
- 重构终本案件实体字段映射,调整被执行人和申请执行人字段定义
- 更新 Excel 导入验证逻辑,简化空行判断条件
2026-01-18 23:50:07 +08:00
3582a3076e refactor(credit): 调整司法文书实体和参数结构
- 移除 dataType、plaintiffAppellant 等字段,新增 title 字段
- 重命名 involvedAmount 为案件金额(元),defendantAppellee 为裁判结果
- 新增 releaseDate 发布日期字段和 defendantAppellee 裁判结果字段
- 更新导入参数类 CreditJudicialDocumentImportParam 替代旧参数类
- 修改
2026-01-18 23:01:39 +08:00
e4a3ea9c7f refactor(credit): 调整司法文书实体和参数结构
- 移除 dataType、plaintiffAppellant 等字段,新增 title 字段
- 重命名 involvedAmount 为案件金额(元),defendantAppellee 为裁判结果
- 新增 releaseDate 发布日期字段和 defendantAppellee 裁判结果字段
- 更新导入参数类 CreditJudicialDocumentImportParam 替代旧参数类
- 修改
2026-01-18 22:16:40 +08:00
e62b900bb1 refactor(judicial): 优化法院公告和送达公告的数据结构和导入功能
- 重命名 CreditJudicialImportParam 为 CreditCourtAnnouncementImportParam 和 CreditDeliveryNoticeImportParam
- 更新实体类字段描述,将 dataType 改为 公告类型,plaintiffAppellant 改为 公告人,occurrenceTime 改为 刊登日期
- 移除不再使用的字段如 appellee、involvedAmount、courtName、dataStatus 等
- 添加送达公告的 url 字段用于存储链接地址
- 更新导入模板生成逻辑,适配新的参数类结构
- 优化导入验证方法,移除对已删除字段的检查
- 在送达公告导入中增加超链接提取功能,从案号列读取URL信息
- 更新数据库查询条件,移除对已删除字段的过滤条件
2026-01-18 11:44:46 +08:00
4794a9af3e feat(judicial): 增加URL字段并优化Excel导入功能
- 在CreditCaseFiling、CreditCourtSession和CreditMediation实体中新增URL字段
- 实现Excel导入时自动读取案号列的超链接地址并回填到URL字段
- 创建独立的CreditCourtSessionImportParam和CreditMediationImportParam导入参数类
- 将立案时间字段名称统一调整为立案日期
- 优化导入模板生成和空行判断逻辑
- 更新导入参数转换方法,移除冗余字段映射
2026-01-18 11:16:35 +08:00
07ea48795b feat(credit): 更新立案信息导入功能
- 修改CreditCaseFiling实体类中occurrenceTime字段描述为"立案时间"
- 替换导入参数类从CreditJudicialImportParam为CreditCaseFilingImportParam
- 更新导入接口文档注释从"司法大数据"为"立案信息"
- 实现Excel导入时指定"立案信息"工作表索引进行读取
- 更新模板下载功能使用新的导入参数类并修改模板名称
- 新增CreditCaseFilingImportParam导入参数类定义立案信息字段
- 在CreditExternal实体类中新增url字段用于存储链接地址
2026-01-18 10:02:30 +08:00
d49ce6e73e feat(excel): 优化Excel导入功能支持指定工作表名称
- 在CreditBreachOfTrustController中添加对"失信被执行人"工作表的精确匹配
- 在CreditXgxfController中添加对"限制高消费"工作表的精确匹配
- 在CreditJudgmentDebtorController中实现被执行人工作表的优先级排序逻辑
- 新增normalizeSheetName方法统一处理工作表名称的空格和特殊字符
- 改进findDebtorSheetIndices方法优先选择名为"被执行人"的工作表
- 调整ExcelImportSupport调用方式以支持指定工作表索引参数
2026-01-16 15:31:27 +08:00
168 changed files with 9563 additions and 1861 deletions

View File

@@ -0,0 +1,118 @@
/**
* Copyright 2013-2015 JueYue (qrb.jueyue@gmail.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.afterturn.easypoi.excel.entity;
import cn.afterturn.easypoi.handler.inter.IExcelVerifyHandler;
import lombok.Data;
/**
* 导入参数设置
*
* @author JueYue
* 2013-9-24
* @version 1.0
*/
@Data
public class ImportParams extends ExcelBaseParams {
public static final String SAVE_URL = "/excel/upload/excelUpload";
/**
* 表格标题行数,默认0
*/
private int titleRows = 0;
/**
* 表头行数,默认1
*/
private int headRows = 1;
/**
* 字段真正值和列标题之间的距离 默认0
*/
private int startRows = 0;
/**
* 主键设置,如何这个cell没有值,就跳过 或者认为这个是list的下面的值
* 大家不理解,去掉这个
*/
private Integer keyIndex = null;
/**
* 开始读取的sheet位置,默认为0
*/
private int startSheetIndex = 0;
/**
* 上传表格需要读取的sheet 数量,默认为1
*/
private int sheetNum = 1;
/**
* 是否需要保存上传的Excel,默认为false
*/
private boolean needSave = false;
/**
* 校验组
*/
private Class[] verifyGroup = null;
/**
* 是否需要校验上传的Excel,默认为false
*/
private boolean needVerify = false;
/**
* 返回文件是否分割,默认是分割
*/
private boolean verifyFileSplit = true;
/**
* 校验处理接口
*/
private IExcelVerifyHandler verifyHandler;
/**
* 保存上传的Excel目录,默认是 如 TestEntity这个类保存路径就是
* upload/excelUpload/Test/yyyyMMddHHmss_***** 保存名称上传时间_五位随机数
*/
private String saveUrl = SAVE_URL;
/**
* 最后的无效行数
*/
private int lastOfInvalidRow = 0;
/**
* 手动控制读取的行数
*/
private int readRows = 0;
/**
* 导入时校验数据模板,是不是正确的Excel
*/
private String[] importFields;
/**
* 导入时校验excel的标题列顺序。依赖于importFields的配置顺序
*/
private boolean needCheckOrder = false;
/**
* Key-Value 读取标记,以这个为Key,后面一个Cell 为Value,多个改为ArrayList
*/
private String keyMark = ":";
/**
* 按照Key-Value 规则读取全局扫描Excel,但是跳过List读取范围提升性能
* 仅仅支持titleRows + headRows + startRows 以及 lastOfInvalidRow
*/
private boolean readSingleCell = false;
/**
* 是否并行计算
*/
private boolean concurrentTask = false;
/**
* 最小截取大小
*/
private Integer critical = 1000;
}

View File

@@ -0,0 +1,26 @@
# ShopDealerReferee 绑定接口规则与索引建议
接口:`POST /api/shop/shop-dealer-referee`
## 业务规则(后端)
- 邀请人(dealerId)必须存在且有效:以 `shop_dealer_user` 记录存在且 `is_delete=0` 为准
- 当前用户(userId)仅从 token 获取;若 body.userId 存在且与 token 不一致则拒绝
- 禁止自己绑定自己:`dealerId == userId`
- 仅首次绑定生效:若已存在(同一 tenant、同一 user、`level=1`)则直接返回成功(幂等,不改绑)
- 记录溯源字段:`source``scene`
## 并发幂等(数据库建议)
建议在 `shop_dealer_referee` 增加溯源字段,并加唯一索引保证并发下不重复写入:
```sql
ALTER TABLE shop_dealer_referee
ADD COLUMN source VARCHAR(32) NULL COMMENT '来源(如 goods_share)',
ADD COLUMN scene VARCHAR(255) NULL COMMENT '场景参数(溯源统计)';
-- 约束:同一 tenant 下,一个用户每个 level 只能有一条推荐关系
ALTER TABLE shop_dealer_referee
ADD UNIQUE KEY uk_shop_dealer_referee_tenant_user_level (tenant_id, user_id, level);
```

View File

@@ -1,13 +1,17 @@
package com.gxwebsoft.cms.controller; package com.gxwebsoft.cms.controller;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.gxwebsoft.cms.entity.CmsDesign; import com.gxwebsoft.cms.entity.CmsDesign;
import com.gxwebsoft.cms.entity.CmsModel; import com.gxwebsoft.cms.entity.CmsModel;
import com.gxwebsoft.cms.param.CmsNavigationImportParam;
import com.gxwebsoft.cms.service.CmsDesignService; import com.gxwebsoft.cms.service.CmsDesignService;
import com.gxwebsoft.cms.service.CmsModelService; import com.gxwebsoft.cms.service.CmsModelService;
import com.gxwebsoft.common.core.annotation.OperationLog;
import com.gxwebsoft.common.core.utils.CommonUtil; import com.gxwebsoft.common.core.utils.CommonUtil;
import com.gxwebsoft.common.core.utils.RedisUtil; import com.gxwebsoft.common.core.utils.RedisUtil;
import com.gxwebsoft.common.core.web.BaseController; import com.gxwebsoft.common.core.web.BaseController;
@@ -21,11 +25,18 @@ import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.common.system.service.UserService; import com.gxwebsoft.common.system.service.UserService;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* 网站导航记录表控制器 * 网站导航记录表控制器
@@ -79,6 +90,7 @@ public class CmsNavigationController extends BaseController {
return success(cmsNavigationService.getByIdRelByCodeRel(code)); return success(cmsNavigationService.getByIdRelByCodeRel(code));
} }
@PreAuthorize("hasAuthority('cms:cmsNavigation:save')")
@Operation(summary = "添加网站导航记录表") @Operation(summary = "添加网站导航记录表")
@PostMapping() @PostMapping()
public ApiResult<?> save(@RequestBody CmsNavigation cmsNavigation) { public ApiResult<?> save(@RequestBody CmsNavigation cmsNavigation) {
@@ -99,6 +111,7 @@ public class CmsNavigationController extends BaseController {
return fail("添加失败"); return fail("添加失败");
} }
@PreAuthorize("hasAuthority('cms:cmsNavigation:update')")
@Operation(summary = "修改网站导航记录表") @Operation(summary = "修改网站导航记录表")
@PutMapping() @PutMapping()
public ApiResult<?> update(@RequestBody CmsNavigation cmsNavigation) { public ApiResult<?> update(@RequestBody CmsNavigation cmsNavigation) {
@@ -111,6 +124,7 @@ public class CmsNavigationController extends BaseController {
return fail("修改失败"); return fail("修改失败");
} }
@PreAuthorize("hasAuthority('cms:cmsNavigation:remove')")
@Operation(summary = "删除网站导航记录表") @Operation(summary = "删除网站导航记录表")
@DeleteMapping("/{id}") @DeleteMapping("/{id}")
public ApiResult<?> remove(@PathVariable("id") Integer id) { public ApiResult<?> remove(@PathVariable("id") Integer id) {
@@ -121,6 +135,7 @@ public class CmsNavigationController extends BaseController {
return fail("删除失败"); return fail("删除失败");
} }
@PreAuthorize("hasAuthority('cms:cmsNavigation:save')")
@Operation(summary = "批量添加网站导航记录表") @Operation(summary = "批量添加网站导航记录表")
@PostMapping("/batch") @PostMapping("/batch")
public ApiResult<?> saveBatch(@RequestBody List<CmsNavigation> list) { public ApiResult<?> saveBatch(@RequestBody List<CmsNavigation> list) {
@@ -131,6 +146,7 @@ public class CmsNavigationController extends BaseController {
return fail("添加失败"); return fail("添加失败");
} }
@PreAuthorize("hasAuthority('cms:cmsNavigation:update')")
@Operation(summary = "批量修改网站导航记录表") @Operation(summary = "批量修改网站导航记录表")
@PutMapping("/batch") @PutMapping("/batch")
public ApiResult<?> removeBatch(@RequestBody BatchParam<CmsNavigation> batchParam) { public ApiResult<?> removeBatch(@RequestBody BatchParam<CmsNavigation> batchParam) {
@@ -141,6 +157,7 @@ public class CmsNavigationController extends BaseController {
return fail("修改失败"); return fail("修改失败");
} }
@PreAuthorize("hasAuthority('cms:cmsNavigation:remove')")
@Operation(summary = "批量删除网站导航记录表") @Operation(summary = "批量删除网站导航记录表")
@DeleteMapping("/batch") @DeleteMapping("/batch")
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) { public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
@@ -151,6 +168,173 @@ public class CmsNavigationController extends BaseController {
return fail("删除失败"); return fail("删除失败");
} }
/**
* excel批量导入网站导航
*/
@PreAuthorize("hasAuthority('cms:cmsNavigation:save')")
@OperationLog
@Operation(summary = "批量导入网站导航")
@Transactional(rollbackFor = {Exception.class})
@PostMapping("/import")
public ApiResult<?> importBatch(@RequestParam("file") MultipartFile file) {
ImportParams importParams = new ImportParams();
try {
User loginUser = getLoginUser();
if (loginUser == null) {
return fail("请先登录");
}
Integer currentUserId = loginUser.getUserId();
Integer currentTenantId = loginUser.getTenantId();
// 1) 清理当前租户的历史数据:先清理 deleted=1再把 deleted=0 标记为 deleted=1
List<CmsNavigation> undeleted = cmsNavigationService.list(new LambdaQueryWrapper<CmsNavigation>()
.eq(CmsNavigation::getTenantId, currentTenantId)
.eq(CmsNavigation::getDeleted, 0));
cmsNavigationService.remove(new LambdaQueryWrapper<CmsNavigation>()
.eq(CmsNavigation::getTenantId, currentTenantId)
.eq(CmsNavigation::getDeleted, 1));
if (!CollectionUtils.isEmpty(undeleted)) {
LambdaUpdateWrapper<CmsNavigation> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(CmsNavigation::getTenantId, currentTenantId);
updateWrapper.eq(CmsNavigation::getDeleted, 0);
updateWrapper.set(CmsNavigation::getDeleted, 1);
cmsNavigationService.update(updateWrapper);
}
// 2) 读取Excel
List<CmsNavigationImportParam> list = ExcelImportUtil.importExcel(
file.getInputStream(), CmsNavigationImportParam.class, importParams);
if (CollectionUtils.isEmpty(list)) {
return fail("未读取到数据,请确认模板表头与示例格式一致");
}
// 3) 先全部落库(先按根节点保存),再尝试按“导入文件的 parentId -> 导入文件的 navigationId”映射回填层级。
// 这样即使 parentId 无法匹配导入文件缺少导航ID/父节点缺失),也能把数据全部导入,无法还原层级的作为根节点处理。
Map<Integer, Integer> newIdByOldId = new HashMap<>();
List<Integer> newIds = new ArrayList<>(list.size());
List<Integer> oldIds = new ArrayList<>(list.size());
List<Integer> oldParentIds = new ArrayList<>(list.size());
for (CmsNavigationImportParam param : list) {
CmsNavigation nav = convertToNavigation(param, currentUserId, currentTenantId);
nav.setParentId(0);
cmsNavigationService.save(nav);
cmsNavigationService.saveAsync(nav);
Integer oldId = param.getNavigationId();
if (oldId != null) {
newIdByOldId.put(oldId, nav.getNavigationId());
}
newIds.add(nav.getNavigationId());
oldIds.add(oldId);
oldParentIds.add(param.getParentId() != null ? param.getParentId() : 0);
}
int orphanCount = 0;
int restoredCount = 0;
for (int i = 0; i < newIds.size(); i++) {
Integer oldParentId = oldParentIds.get(i);
if (oldParentId == null || oldParentId == 0) {
continue;
}
Integer oldId = oldIds.get(i);
Integer newId = newIds.get(i);
Integer newParentId = newIdByOldId.get(oldParentId);
// 无法匹配父节点(或出现自引用)就当作孤儿节点,保持根节点
if (newParentId == null || (oldId != null && oldParentId.equals(oldId)) || (newId != null && newParentId.equals(newId))) {
orphanCount++;
continue;
}
cmsNavigationService.update(new LambdaUpdateWrapper<CmsNavigation>()
.eq(CmsNavigation::getNavigationId, newId)
.set(CmsNavigation::getParentId, newParentId));
restoredCount++;
}
redisUtil.delete(SITE_INFO_KEY_PREFIX.concat(currentTenantId.toString()));
return success("成功导入" + list.size() + "条,恢复层级" + restoredCount + "条,无法还原层级的孤儿节点" + orphanCount + "条(已作为根节点导入)");
} catch (Exception e) {
e.printStackTrace();
return fail("导入失败: " + e.getMessage());
}
}
/**
* 递归创建子级导航
*/
private void createChildNavigations(Map<Integer, List<CmsNavigationImportParam>> navGroups,
Map<Integer, CmsNavigation> tempIdMapping,
Integer originalParentId,
Integer defaultUserId,
Integer defaultTenantId) {
if (originalParentId == null || originalParentId == 0) {
return;
}
List<CmsNavigationImportParam> children = navGroups.get(originalParentId);
if (CollectionUtils.isEmpty(children)) {
return;
}
CmsNavigation parent = tempIdMapping.get(originalParentId);
if (parent == null || parent.getNavigationId() == null) {
return;
}
Integer newParentId = parent.getNavigationId();
for (CmsNavigationImportParam param : children) {
CmsNavigation nav = convertToNavigation(param, defaultUserId, defaultTenantId);
nav.setParentId(newParentId);
cmsNavigationService.save(nav);
cmsNavigationService.saveAsync(nav);
if (param.getNavigationId() != null) {
tempIdMapping.put(param.getNavigationId(), nav);
}
createChildNavigations(navGroups, tempIdMapping, param.getNavigationId(), defaultUserId, defaultTenantId);
}
}
private CmsNavigation convertToNavigation(CmsNavigationImportParam param, Integer defaultUserId, Integer defaultTenantId) {
CmsNavigation nav = new CmsNavigation();
nav.setType(param.getType());
nav.setTitle(StrUtil.trimStart(param.getTitle()));
nav.setParentId(param.getParentId() != null ? param.getParentId() : 0);
// saveAsync 依赖 model 生成路由/页面;缺省按 page 处理
nav.setModel(StrUtil.isBlank(param.getModel()) ? "page" : param.getModel());
nav.setCode(param.getCode());
nav.setPath(param.getPath());
nav.setComponent(param.getComponent());
nav.setTarget(param.getTarget());
nav.setIcon(param.getIcon());
nav.setColor(param.getColor());
nav.setHide(param.getHide());
nav.setPermission(param.getPermission());
nav.setPassword(param.getPassword());
nav.setPosition(param.getPosition());
nav.setTop(param.getTop());
nav.setBottom(param.getBottom());
nav.setActive(param.getActive());
nav.setMeta(param.getMeta());
nav.setStyle(param.getStyle());
nav.setModelName(param.getModelName());
nav.setPageId(param.getPageId());
nav.setItemId(param.getItemId());
nav.setIsMpWeixin(param.getIsMpWeixin());
nav.setGutter(param.getGutter());
nav.setSpan(param.getSpan());
nav.setReadNum(param.getReadNum());
nav.setMerchantId(param.getMerchantId());
nav.setLang(param.getLang());
nav.setHome(param.getHome());
nav.setRecommend(param.getRecommend());
nav.setSortNumber(param.getSortNumber() != null ? param.getSortNumber() : 0);
nav.setComments(param.getComments());
nav.setStatus(param.getStatus() != null ? param.getStatus() : 0);
// 导入时强制落到当前登录用户/租户,避免“导出其他租户 -> 导入”写回原租户导致当前租户数据不全。
nav.setUserId(defaultUserId);
nav.setTenantId(defaultTenantId);
nav.setDeleted(0);
return nav;
}
@Operation(summary = "获取树形结构的网站导航数据") @Operation(summary = "获取树形结构的网站导航数据")
@GetMapping("/tree") @GetMapping("/tree")
public ApiResult<List<CmsNavigation>> tree(CmsNavigationParam param) { public ApiResult<List<CmsNavigation>> tree(CmsNavigationParam param) {

View File

@@ -0,0 +1,122 @@
package com.gxwebsoft.cms.controller;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.cms.service.CmsOrderService;
import com.gxwebsoft.cms.entity.CmsOrder;
import com.gxwebsoft.cms.param.CmsOrderParam;
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 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-01-27 13:03:25
*/
@Tag(name = "网站订单管理")
@RestController
@RequestMapping("/api/cms/cms-order")
public class CmsOrderController extends BaseController {
@Resource
private CmsOrderService cmsOrderService;
@PreAuthorize("hasAuthority('cms:cmsOrder:list')")
@Operation(summary = "分页查询网站订单")
@GetMapping("/page")
public ApiResult<PageResult<CmsOrder>> page(CmsOrderParam param) {
// 使用关联查询
return success(cmsOrderService.pageRel(param));
}
@PreAuthorize("hasAuthority('cms:cmsOrder:list')")
@Operation(summary = "查询全部网站订单")
@GetMapping()
public ApiResult<List<CmsOrder>> list(CmsOrderParam param) {
// 使用关联查询
return success(cmsOrderService.listRel(param));
}
@PreAuthorize("hasAuthority('cms:cmsOrder:list')")
@Operation(summary = "根据id查询网站订单")
@GetMapping("/{id}")
public ApiResult<CmsOrder> get(@PathVariable("id") Integer id) {
// 使用关联查询
return success(cmsOrderService.getByIdRel(id));
}
@Operation(summary = "添加网站订单")
@PostMapping()
public ApiResult<?> save(@RequestBody CmsOrder cmsOrder) {
if (cmsOrderService.save(cmsOrder)) {
return success("添加成功");
}
return fail("添加失败");
}
@PreAuthorize("hasAuthority('cms:cmsOrder:update')")
@OperationLog
@Operation(summary = "修改网站订单")
@PutMapping()
public ApiResult<?> update(@RequestBody CmsOrder cmsOrder) {
if (cmsOrderService.updateById(cmsOrder)) {
return success("修改成功");
}
return fail("修改失败");
}
@PreAuthorize("hasAuthority('cms:cmsOrder:remove')")
@OperationLog
@Operation(summary = "删除网站订单")
@DeleteMapping("/{id}")
public ApiResult<?> remove(@PathVariable("id") Integer id) {
if (cmsOrderService.removeById(id)) {
return success("删除成功");
}
return fail("删除失败");
}
@PreAuthorize("hasAuthority('cms:cmsOrder:save')")
@OperationLog
@Operation(summary = "批量添加网站订单")
@PostMapping("/batch")
public ApiResult<?> saveBatch(@RequestBody List<CmsOrder> list) {
if (cmsOrderService.saveBatch(list)) {
return success("添加成功");
}
return fail("添加失败");
}
@PreAuthorize("hasAuthority('cms:cmsOrder:update')")
@OperationLog
@Operation(summary = "批量修改网站订单")
@PutMapping("/batch")
public ApiResult<?> removeBatch(@RequestBody BatchParam<CmsOrder> batchParam) {
if (batchParam.update(cmsOrderService, "id")) {
return success("修改成功");
}
return fail("修改失败");
}
@PreAuthorize("hasAuthority('cms:cmsOrder:remove')")
@OperationLog
@Operation(summary = "批量删除网站订单")
@DeleteMapping("/batch")
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
if (cmsOrderService.removeByIds(ids)) {
return success("删除成功");
}
return fail("删除失败");
}
}

View File

@@ -0,0 +1,266 @@
package com.gxwebsoft.cms.entity;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.IdType;
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 2026-01-27 13:03:24
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Schema(name = "CmsOrder对象", description = "网站订单")
public class CmsOrder implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "id")
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@Schema(description = "订单类型0售前咨询 1售后服务 2意见反馈")
private Integer type;
@Schema(description = "订单标题")
private String title;
@Schema(description = "公司/团队名称")
private String company;
@Schema(description = "订单内容")
private String content;
@Schema(description = "订单编号")
private String orderNo;
@Schema(description = "快递/自提")
private Integer deliveryType;
@Schema(description = "下单渠道0网站 1微信小程序 2其他")
private Integer channel;
@Schema(description = "微信支付交易号号")
private String transactionId;
@Schema(description = "微信退款订单号")
private String refundOrder;
@Schema(description = "商户ID")
private Integer merchantId;
@Schema(description = "商户名称")
private String merchantName;
@Schema(description = "商户编号")
private String merchantCode;
@Schema(description = "使用的优惠券id")
private Integer couponId;
@Schema(description = "使用的会员卡id")
private String cardId;
@Schema(description = "关联管理员id")
private Integer adminId;
@Schema(description = "核销管理员id")
private Integer confirmId;
@Schema(description = "IC卡号")
private String icCard;
@Schema(description = "真实姓名")
private String realName;
@Schema(description = "关联收货地址")
private Integer addressId;
@Schema(description = "收货地址")
private String address;
private String addressLat;
private String addressLng;
@Schema(description = "自提店铺id")
private Integer selfTakeMerchantId;
@Schema(description = "自提店铺")
private String selfTakeMerchantName;
@Schema(description = "配送开始时间")
private String sendStartTime;
@Schema(description = "配送结束时间")
private String sendEndTime;
@Schema(description = "发货店铺id")
private Integer expressMerchantId;
@Schema(description = "发货店铺")
private String expressMerchantName;
@Schema(description = "订单总额")
private BigDecimal totalPrice;
@Schema(description = "减少的金额使用VIP会员折扣、优惠券抵扣、优惠券折扣后减去的价格")
private BigDecimal reducePrice;
@Schema(description = "实际付款")
private BigDecimal payPrice;
@Schema(description = "用于统计")
private BigDecimal price;
@Schema(description = "价钱,用于积分赠送")
private BigDecimal money;
@Schema(description = "取消时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime cancelTime;
@Schema(description = "取消原因")
private String cancelReason;
@Schema(description = "退款金额")
private BigDecimal refundMoney;
@Schema(description = "教练价格")
private BigDecimal coachPrice;
@Schema(description = "购买数量")
private Integer totalNum;
@Schema(description = "教练id")
private Integer coachId;
@Schema(description = "商品ID")
private Integer formId;
@Schema(description = "支付的用户id")
private Integer payUserId;
@Schema(description = "0余额支付1微信支付2支付宝支付3银联支付4现金支付5POS机支付6免费7积分支付")
private Integer payType;
@Schema(description = "微信支付子类型JSAPI小程序支付NATIVE扫码支付")
private String wechatPayType;
@Schema(description = "0余额支付1微信支付2支付宝支付3银联支付4现金支付5POS机支付6免费7积分支付")
private Integer friendPayType;
@Schema(description = "0未付款1已付款")
private Integer payStatus;
@Schema(description = "0未使用1已完成2已取消3取消中4退款申请中5退款被拒绝6退款成功7客户端申请退款")
private Integer orderStatus;
@Schema(description = "发货状态(10未发货 20已发货 30部分发货)")
private Integer deliveryStatus;
@Schema(description = "无需发货备注")
private String deliveryNote;
@Schema(description = "发货时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime deliveryTime;
@Schema(description = "评价状态(0未评价 1已评价)")
private Integer evaluateStatus;
@Schema(description = "评价时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime evaluateTime;
@Schema(description = "优惠类型0无、1抵扣优惠券、2折扣优惠券、3、VIP月卡、4VIP年卡5VIP次卡、6VIP会员卡、7IC月卡、8IC年卡、9IC次卡、10IC会员卡、11免费订单、12VIP充值卡、13IC充值卡、14VIP季卡、15IC季卡")
private Integer couponType;
@Schema(description = "优惠说明")
private String couponDesc;
@Schema(description = "二维码地址,保存订单号,支付成功后才生成")
private String qrcode;
@Schema(description = "vip月卡年卡、ic月卡年卡回退次数")
private Integer returnNum;
@Schema(description = "vip充值回退金额")
private BigDecimal returnMoney;
@Schema(description = "预约详情开始时间数组")
private String startTime;
@Schema(description = "是否已开具发票0未开发票1已开发票2不能开具发票")
private Integer isInvoice;
@Schema(description = "发票流水号")
private String invoiceNo;
@Schema(description = "商家留言")
private String merchantRemarks;
@Schema(description = "支付时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime payTime;
@Schema(description = "退款时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime refundTime;
@Schema(description = "申请退款时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime refundApplyTime;
@Schema(description = "过期时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime expirationTime;
@Schema(description = "自提码")
private String selfTakeCode;
@Schema(description = "是否已收到赠品")
private Boolean hasTakeGift;
@Schema(description = "对账情况0=未对账1=已对账3=已对账金额对不上4=未查询到该订单")
private Integer checkBill;
@Schema(description = "订单是否已结算(0未结算 1已结算)")
private Integer isSettled;
@Schema(description = "系统版本号 0当前版本 value=其他版本")
private Integer version;
@Schema(description = "用户id")
private Integer userId;
@Schema(description = "备注")
private String comments;
@Schema(description = "排序号")
private Integer sortNumber;
@Schema(description = "是否删除, 0否, 1是")
@TableLogic
private Integer deleted;
@Schema(description = "租户id")
private Integer tenantId;
@Schema(description = "修改时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime updateTime;
@Schema(description = "创建时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
}

View File

@@ -0,0 +1,37 @@
package com.gxwebsoft.cms.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.gxwebsoft.cms.entity.CmsOrder;
import com.gxwebsoft.cms.param.CmsOrderParam;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 网站订单Mapper
*
* @author 科技小王子
* @since 2026-01-27 13:03:24
*/
public interface CmsOrderMapper extends BaseMapper<CmsOrder> {
/**
* 分页查询
*
* @param page 分页对象
* @param param 查询参数
* @return List<CmsOrder>
*/
List<CmsOrder> selectPageRel(@Param("page") IPage<CmsOrder> page,
@Param("param") CmsOrderParam param);
/**
* 查询全部
*
* @param param 查询参数
* @return List<User>
*/
List<CmsOrder> selectListRel(@Param("param") CmsOrderParam param);
}

View File

@@ -0,0 +1,258 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.gxwebsoft.cms.mapper.CmsOrderMapper">
<!-- 关联查询sql -->
<sql id="selectSql">
SELECT a.*
FROM cms_order a
<where>
<if test="param.id != null">
AND a.id = #{param.id}
</if>
<if test="param.type != null">
AND a.type = #{param.type}
</if>
<if test="param.title != null">
AND a.title LIKE CONCAT('%', #{param.title}, '%')
</if>
<if test="param.company != null">
AND a.company LIKE CONCAT('%', #{param.company}, '%')
</if>
<if test="param.content != null">
AND a.content LIKE CONCAT('%', #{param.content}, '%')
</if>
<if test="param.orderNo != null">
AND a.order_no LIKE CONCAT('%', #{param.orderNo}, '%')
</if>
<if test="param.deliveryType != null">
AND a.delivery_type = #{param.deliveryType}
</if>
<if test="param.channel != null">
AND a.channel = #{param.channel}
</if>
<if test="param.transactionId != null">
AND a.transaction_id LIKE CONCAT('%', #{param.transactionId}, '%')
</if>
<if test="param.refundOrder != null">
AND a.refund_order LIKE CONCAT('%', #{param.refundOrder}, '%')
</if>
<if test="param.merchantId != null">
AND a.merchant_id = #{param.merchantId}
</if>
<if test="param.merchantName != null">
AND a.merchant_name LIKE CONCAT('%', #{param.merchantName}, '%')
</if>
<if test="param.merchantCode != null">
AND a.merchant_code LIKE CONCAT('%', #{param.merchantCode}, '%')
</if>
<if test="param.couponId != null">
AND a.coupon_id = #{param.couponId}
</if>
<if test="param.cardId != null">
AND a.card_id LIKE CONCAT('%', #{param.cardId}, '%')
</if>
<if test="param.adminId != null">
AND a.admin_id = #{param.adminId}
</if>
<if test="param.confirmId != null">
AND a.confirm_id = #{param.confirmId}
</if>
<if test="param.icCard != null">
AND a.ic_card LIKE CONCAT('%', #{param.icCard}, '%')
</if>
<if test="param.realName != null">
AND a.real_name LIKE CONCAT('%', #{param.realName}, '%')
</if>
<if test="param.addressId != null">
AND a.address_id = #{param.addressId}
</if>
<if test="param.address != null">
AND a.address LIKE CONCAT('%', #{param.address}, '%')
</if>
<if test="param.addressLat != null">
AND a.address_lat LIKE CONCAT('%', #{param.addressLat}, '%')
</if>
<if test="param.addressLng != null">
AND a.address_lng LIKE CONCAT('%', #{param.addressLng}, '%')
</if>
<if test="param.selfTakeMerchantId != null">
AND a.self_take_merchant_id = #{param.selfTakeMerchantId}
</if>
<if test="param.selfTakeMerchantName != null">
AND a.self_take_merchant_name LIKE CONCAT('%', #{param.selfTakeMerchantName}, '%')
</if>
<if test="param.sendStartTime != null">
AND a.send_start_time LIKE CONCAT('%', #{param.sendStartTime}, '%')
</if>
<if test="param.sendEndTime != null">
AND a.send_end_time LIKE CONCAT('%', #{param.sendEndTime}, '%')
</if>
<if test="param.expressMerchantId != null">
AND a.express_merchant_id = #{param.expressMerchantId}
</if>
<if test="param.expressMerchantName != null">
AND a.express_merchant_name LIKE CONCAT('%', #{param.expressMerchantName}, '%')
</if>
<if test="param.totalPrice != null">
AND a.total_price = #{param.totalPrice}
</if>
<if test="param.reducePrice != null">
AND a.reduce_price = #{param.reducePrice}
</if>
<if test="param.payPrice != null">
AND a.pay_price = #{param.payPrice}
</if>
<if test="param.price != null">
AND a.price = #{param.price}
</if>
<if test="param.money != null">
AND a.money = #{param.money}
</if>
<if test="param.cancelTime != null">
AND a.cancel_time LIKE CONCAT('%', #{param.cancelTime}, '%')
</if>
<if test="param.cancelReason != null">
AND a.cancel_reason LIKE CONCAT('%', #{param.cancelReason}, '%')
</if>
<if test="param.refundMoney != null">
AND a.refund_money = #{param.refundMoney}
</if>
<if test="param.coachPrice != null">
AND a.coach_price = #{param.coachPrice}
</if>
<if test="param.totalNum != null">
AND a.total_num = #{param.totalNum}
</if>
<if test="param.coachId != null">
AND a.coach_id = #{param.coachId}
</if>
<if test="param.formId != null">
AND a.form_id = #{param.formId}
</if>
<if test="param.payUserId != null">
AND a.pay_user_id = #{param.payUserId}
</if>
<if test="param.payType != null">
AND a.pay_type = #{param.payType}
</if>
<if test="param.wechatPayType != null">
AND a.wechat_pay_type LIKE CONCAT('%', #{param.wechatPayType}, '%')
</if>
<if test="param.friendPayType != null">
AND a.friend_pay_type = #{param.friendPayType}
</if>
<if test="param.payStatus != null">
AND a.pay_status = #{param.payStatus}
</if>
<if test="param.orderStatus != null">
AND a.order_status = #{param.orderStatus}
</if>
<if test="param.deliveryStatus != null">
AND a.delivery_status = #{param.deliveryStatus}
</if>
<if test="param.deliveryNote != null">
AND a.delivery_note LIKE CONCAT('%', #{param.deliveryNote}, '%')
</if>
<if test="param.deliveryTime != null">
AND a.delivery_time LIKE CONCAT('%', #{param.deliveryTime}, '%')
</if>
<if test="param.evaluateStatus != null">
AND a.evaluate_status = #{param.evaluateStatus}
</if>
<if test="param.evaluateTime != null">
AND a.evaluate_time LIKE CONCAT('%', #{param.evaluateTime}, '%')
</if>
<if test="param.couponType != null">
AND a.coupon_type = #{param.couponType}
</if>
<if test="param.couponDesc != null">
AND a.coupon_desc LIKE CONCAT('%', #{param.couponDesc}, '%')
</if>
<if test="param.qrcode != null">
AND a.qrcode LIKE CONCAT('%', #{param.qrcode}, '%')
</if>
<if test="param.returnNum != null">
AND a.return_num = #{param.returnNum}
</if>
<if test="param.returnMoney != null">
AND a.return_money = #{param.returnMoney}
</if>
<if test="param.startTime != null">
AND a.start_time LIKE CONCAT('%', #{param.startTime}, '%')
</if>
<if test="param.isInvoice != null">
AND a.is_invoice = #{param.isInvoice}
</if>
<if test="param.invoiceNo != null">
AND a.invoice_no LIKE CONCAT('%', #{param.invoiceNo}, '%')
</if>
<if test="param.merchantRemarks != null">
AND a.merchant_remarks LIKE CONCAT('%', #{param.merchantRemarks}, '%')
</if>
<if test="param.payTime != null">
AND a.pay_time LIKE CONCAT('%', #{param.payTime}, '%')
</if>
<if test="param.refundTime != null">
AND a.refund_time LIKE CONCAT('%', #{param.refundTime}, '%')
</if>
<if test="param.refundApplyTime != null">
AND a.refund_apply_time LIKE CONCAT('%', #{param.refundApplyTime}, '%')
</if>
<if test="param.expirationTime != null">
AND a.expiration_time LIKE CONCAT('%', #{param.expirationTime}, '%')
</if>
<if test="param.selfTakeCode != null">
AND a.self_take_code LIKE CONCAT('%', #{param.selfTakeCode}, '%')
</if>
<if test="param.hasTakeGift != null">
AND a.has_take_gift = #{param.hasTakeGift}
</if>
<if test="param.checkBill != null">
AND a.check_bill = #{param.checkBill}
</if>
<if test="param.isSettled != null">
AND a.is_settled = #{param.isSettled}
</if>
<if test="param.version != null">
AND a.version = #{param.version}
</if>
<if test="param.userId != null">
AND a.user_id = #{param.userId}
</if>
<if test="param.comments != null">
AND a.comments LIKE CONCAT('%', #{param.comments}, '%')
</if>
<if test="param.sortNumber != null">
AND a.sort_number = #{param.sortNumber}
</if>
<if test="param.deleted != null">
AND a.deleted = #{param.deleted}
</if>
<if test="param.deleted == null">
AND a.deleted = 0
</if>
<if test="param.createTimeStart != null">
AND a.create_time &gt;= #{param.createTimeStart}
</if>
<if test="param.createTimeEnd != null">
AND a.create_time &lt;= #{param.createTimeEnd}
</if>
<if test="param.keywords != null">
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
)
</if>
</where>
</sql>
<!-- 分页查询 -->
<select id="selectPageRel" resultType="com.gxwebsoft.cms.entity.CmsOrder">
<include refid="selectSql"></include>
</select>
<!-- 查询全部 -->
<select id="selectListRel" resultType="com.gxwebsoft.cms.entity.CmsOrder">
<include refid="selectSql"></include>
</select>
</mapper>

View File

@@ -0,0 +1,123 @@
package com.gxwebsoft.cms.param;
import cn.afterturn.easypoi.excel.annotation.Excel;
import lombok.Data;
import java.io.Serializable;
/**
* 网站导航导入参数Excel 批量导入)
*/
@Data
public class CmsNavigationImportParam implements Serializable {
private static final long serialVersionUID = 1L;
@Excel(name = "导航ID")
private Integer navigationId;
@Excel(name = "类型")
private Integer type;
@Excel(name = "菜单名称")
private String title;
@Excel(name = "上级id")
private Integer parentId;
@Excel(name = "模型")
private String model;
@Excel(name = "标识")
private String code;
@Excel(name = "菜单路由地址")
private String path;
@Excel(name = "菜单组件地址")
private String component;
@Excel(name = "打开位置")
private String target;
@Excel(name = "菜单图标")
private String icon;
@Excel(name = "图标颜色")
private String color;
@Excel(name = "是否隐藏")
private Integer hide;
@Excel(name = "可见类型")
private Integer permission;
@Excel(name = "访问密码")
private String password;
@Excel(name = "位置")
private Integer position;
@Excel(name = "仅在顶部显示")
private Integer top;
@Excel(name = "仅在底部显示")
private Integer bottom;
@Excel(name = "选中path")
private String active;
@Excel(name = "其它路由元信息")
private String meta;
@Excel(name = "css样式")
private String style;
@Excel(name = "模型名称")
private String modelName;
@Excel(name = "页面ID")
private Integer pageId;
@Excel(name = "详情页ID")
private Integer itemId;
@Excel(name = "是否微信小程序菜单")
private Boolean isMpWeixin;
@Excel(name = "菜单间距")
private Integer gutter;
@Excel(name = "菜单宽度")
private Integer span;
@Excel(name = "阅读量")
private Integer readNum;
@Excel(name = "商户ID")
private Long merchantId;
@Excel(name = "国际化语言")
private String lang;
@Excel(name = "设为首页")
private Integer home;
@Excel(name = "是否推荐")
private Boolean recommend;
@Excel(name = "排序")
private Integer sortNumber;
@Excel(name = "备注")
private String comments;
@Excel(name = "状态")
private Integer status;
@Excel(name = "用户ID")
private Integer userId;
@Excel(name = "租户ID")
private Integer tenantId;
}

View File

@@ -0,0 +1,284 @@
package com.gxwebsoft.cms.param;
import java.math.BigDecimal;
import com.gxwebsoft.common.core.annotation.QueryField;
import com.gxwebsoft.common.core.annotation.QueryType;
import com.gxwebsoft.common.core.web.BaseParam;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 网站订单查询参数
*
* @author 科技小王子
* @since 2026-01-27 13:03:24
*/
@Data
@EqualsAndHashCode(callSuper = false)
@JsonInclude(JsonInclude.Include.NON_NULL)
@Schema(name = "CmsOrderParam对象", description = "网站订单查询参数")
public class CmsOrderParam extends BaseParam {
private static final long serialVersionUID = 1L;
@Schema(description = "id")
@QueryField(type = QueryType.EQ)
private Integer id;
@Schema(description = "订单类型0售前咨询 1售后服务 2意见反馈")
@QueryField(type = QueryType.EQ)
private Integer type;
@Schema(description = "订单标题")
private String title;
@Schema(description = "公司/团队名称")
private String company;
@Schema(description = "订单内容")
private String content;
@Schema(description = "订单编号")
private String orderNo;
@Schema(description = "快递/自提")
@QueryField(type = QueryType.EQ)
private Integer deliveryType;
@Schema(description = "下单渠道0网站 1微信小程序 2其他")
@QueryField(type = QueryType.EQ)
private Integer channel;
@Schema(description = "微信支付交易号号")
private String transactionId;
@Schema(description = "微信退款订单号")
private String refundOrder;
@Schema(description = "商户ID")
@QueryField(type = QueryType.EQ)
private Long merchantId;
@Schema(description = "商户名称")
private String merchantName;
@Schema(description = "商户编号")
private String merchantCode;
@Schema(description = "使用的优惠券id")
@QueryField(type = QueryType.EQ)
private Integer couponId;
@Schema(description = "使用的会员卡id")
private String cardId;
@Schema(description = "关联管理员id")
@QueryField(type = QueryType.EQ)
private Integer adminId;
@Schema(description = "核销管理员id")
@QueryField(type = QueryType.EQ)
private Integer confirmId;
@Schema(description = "IC卡号")
private String icCard;
@Schema(description = "真实姓名")
private String realName;
@Schema(description = "关联收货地址")
@QueryField(type = QueryType.EQ)
private Integer addressId;
@Schema(description = "收货地址")
private String address;
private String addressLat;
private String addressLng;
@Schema(description = "自提店铺id")
@QueryField(type = QueryType.EQ)
private Integer selfTakeMerchantId;
@Schema(description = "自提店铺")
private String selfTakeMerchantName;
@Schema(description = "配送开始时间")
private String sendStartTime;
@Schema(description = "配送结束时间")
private String sendEndTime;
@Schema(description = "发货店铺id")
@QueryField(type = QueryType.EQ)
private Integer expressMerchantId;
@Schema(description = "发货店铺")
private String expressMerchantName;
@Schema(description = "订单总额")
@QueryField(type = QueryType.EQ)
private BigDecimal totalPrice;
@Schema(description = "减少的金额使用VIP会员折扣、优惠券抵扣、优惠券折扣后减去的价格")
@QueryField(type = QueryType.EQ)
private BigDecimal reducePrice;
@Schema(description = "实际付款")
@QueryField(type = QueryType.EQ)
private BigDecimal payPrice;
@Schema(description = "用于统计")
@QueryField(type = QueryType.EQ)
private BigDecimal price;
@Schema(description = "价钱,用于积分赠送")
@QueryField(type = QueryType.EQ)
private BigDecimal money;
@Schema(description = "取消时间")
private String cancelTime;
@Schema(description = "取消原因")
private String cancelReason;
@Schema(description = "退款金额")
@QueryField(type = QueryType.EQ)
private BigDecimal refundMoney;
@Schema(description = "教练价格")
@QueryField(type = QueryType.EQ)
private BigDecimal coachPrice;
@Schema(description = "购买数量")
@QueryField(type = QueryType.EQ)
private Integer totalNum;
@Schema(description = "教练id")
@QueryField(type = QueryType.EQ)
private Integer coachId;
@Schema(description = "商品ID")
@QueryField(type = QueryType.EQ)
private Integer formId;
@Schema(description = "支付的用户id")
@QueryField(type = QueryType.EQ)
private Integer payUserId;
@Schema(description = "0余额支付1微信支付2支付宝支付3银联支付4现金支付5POS机支付6免费7积分支付")
@QueryField(type = QueryType.EQ)
private Integer payType;
@Schema(description = "微信支付子类型JSAPI小程序支付NATIVE扫码支付")
private String wechatPayType;
@Schema(description = "0余额支付1微信支付2支付宝支付3银联支付4现金支付5POS机支付6免费7积分支付")
@QueryField(type = QueryType.EQ)
private Integer friendPayType;
@Schema(description = "0未付款1已付款")
@QueryField(type = QueryType.EQ)
private Integer payStatus;
@Schema(description = "0未使用1已完成2已取消3取消中4退款申请中5退款被拒绝6退款成功7客户端申请退款")
@QueryField(type = QueryType.EQ)
private Integer orderStatus;
@Schema(description = "发货状态(10未发货 20已发货 30部分发货)")
@QueryField(type = QueryType.EQ)
private Integer deliveryStatus;
@Schema(description = "无需发货备注")
private String deliveryNote;
@Schema(description = "发货时间")
private String deliveryTime;
@Schema(description = "评价状态(0未评价 1已评价)")
@QueryField(type = QueryType.EQ)
private Integer evaluateStatus;
@Schema(description = "评价时间")
private String evaluateTime;
@Schema(description = "优惠类型0无、1抵扣优惠券、2折扣优惠券、3、VIP月卡、4VIP年卡5VIP次卡、6VIP会员卡、7IC月卡、8IC年卡、9IC次卡、10IC会员卡、11免费订单、12VIP充值卡、13IC充值卡、14VIP季卡、15IC季卡")
@QueryField(type = QueryType.EQ)
private Integer couponType;
@Schema(description = "优惠说明")
private String couponDesc;
@Schema(description = "二维码地址,保存订单号,支付成功后才生成")
private String qrcode;
@Schema(description = "vip月卡年卡、ic月卡年卡回退次数")
@QueryField(type = QueryType.EQ)
private Integer returnNum;
@Schema(description = "vip充值回退金额")
@QueryField(type = QueryType.EQ)
private BigDecimal returnMoney;
@Schema(description = "预约详情开始时间数组")
private String startTime;
@Schema(description = "是否已开具发票0未开发票1已开发票2不能开具发票")
@QueryField(type = QueryType.EQ)
private Integer isInvoice;
@Schema(description = "发票流水号")
private String invoiceNo;
@Schema(description = "商家留言")
private String merchantRemarks;
@Schema(description = "支付时间")
private String payTime;
@Schema(description = "退款时间")
private String refundTime;
@Schema(description = "申请退款时间")
private String refundApplyTime;
@Schema(description = "过期时间")
private String expirationTime;
@Schema(description = "自提码")
private String selfTakeCode;
@Schema(description = "是否已收到赠品")
@QueryField(type = QueryType.EQ)
private Boolean hasTakeGift;
@Schema(description = "对账情况0=未对账1=已对账3=已对账金额对不上4=未查询到该订单")
@QueryField(type = QueryType.EQ)
private Integer checkBill;
@Schema(description = "订单是否已结算(0未结算 1已结算)")
@QueryField(type = QueryType.EQ)
private Integer isSettled;
@Schema(description = "系统版本号 0当前版本 value=其他版本")
@QueryField(type = QueryType.EQ)
private Integer version;
@Schema(description = "用户id")
@QueryField(type = QueryType.EQ)
private Integer userId;
@Schema(description = "备注")
private String comments;
@Schema(description = "排序号")
@QueryField(type = QueryType.EQ)
private Integer sortNumber;
@Schema(description = "是否删除, 0否, 1是")
@QueryField(type = QueryType.EQ)
private Integer deleted;
}

View File

@@ -0,0 +1,42 @@
package com.gxwebsoft.cms.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.cms.entity.CmsOrder;
import com.gxwebsoft.cms.param.CmsOrderParam;
import java.util.List;
/**
* 网站订单Service
*
* @author 科技小王子
* @since 2026-01-27 13:03:24
*/
public interface CmsOrderService extends IService<CmsOrder> {
/**
* 分页关联查询
*
* @param param 查询参数
* @return PageResult<CmsOrder>
*/
PageResult<CmsOrder> pageRel(CmsOrderParam param);
/**
* 关联查询全部
*
* @param param 查询参数
* @return List<CmsOrder>
*/
List<CmsOrder> listRel(CmsOrderParam param);
/**
* 根据id查询
*
* @param id id
* @return CmsOrder
*/
CmsOrder getByIdRel(Integer id);
}

View File

@@ -0,0 +1,47 @@
package com.gxwebsoft.cms.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gxwebsoft.cms.mapper.CmsOrderMapper;
import com.gxwebsoft.cms.service.CmsOrderService;
import com.gxwebsoft.cms.entity.CmsOrder;
import com.gxwebsoft.cms.param.CmsOrderParam;
import com.gxwebsoft.common.core.web.PageParam;
import com.gxwebsoft.common.core.web.PageResult;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 网站订单Service实现
*
* @author 科技小王子
* @since 2026-01-27 13:03:24
*/
@Service
public class CmsOrderServiceImpl extends ServiceImpl<CmsOrderMapper, CmsOrder> implements CmsOrderService {
@Override
public PageResult<CmsOrder> pageRel(CmsOrderParam param) {
PageParam<CmsOrder, CmsOrderParam> page = new PageParam<>(param);
page.setDefaultOrder("sort_number asc, create_time desc");
List<CmsOrder> list = baseMapper.selectPageRel(page, param);
return new PageResult<>(list, page.getTotal());
}
@Override
public List<CmsOrder> listRel(CmsOrderParam param) {
List<CmsOrder> list = baseMapper.selectListRel(param);
// 排序
PageParam<CmsOrder, CmsOrderParam> page = new PageParam<>();
page.setDefaultOrder("sort_number asc, create_time desc");
return page.sortRecords(list);
}
@Override
public CmsOrder getByIdRel(Integer id) {
CmsOrderParam param = new CmsOrderParam();
param.setId(id);
return param.getOne(baseMapper.selectListRel(param));
}
}

View File

@@ -4,7 +4,6 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;

View File

@@ -1,11 +1,14 @@
package com.gxwebsoft.common.core.config; package com.gxwebsoft.common.core.config;
import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonDeserializer;
import java.io.IOException; import java.io.IOException;
import java.time.Instant;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
/** /**
@@ -16,14 +19,43 @@ import java.time.format.DateTimeFormatter;
*/ */
public class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> { public class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); private final DateTimeFormatter formatter;
public LocalDateTimeDeserializer() {
this(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
}
public LocalDateTimeDeserializer(DateTimeFormatter formatter) {
this.formatter = formatter;
}
@Override @Override
public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
String value = p.getValueAsString(); JsonToken t = p.currentToken();
if (value != null && !value.isEmpty()) { ZoneId zoneId = ctxt.getTimeZone() != null ? ctxt.getTimeZone().toZoneId() : ZoneId.systemDefault();
return LocalDateTime.parse(value, FORMATTER);
// Accept epoch timestamps (seconds or millis) for compatibility with frontends that send numbers.
if (t == JsonToken.VALUE_NUMBER_INT) {
long ts = p.getLongValue();
// Heuristic: 10+ digits is seconds; 13+ digits is millis (most common in JS).
Instant instant = (String.valueOf(Math.abs(ts)).length() >= 13)
? Instant.ofEpochMilli(ts)
: Instant.ofEpochSecond(ts);
return LocalDateTime.ofInstant(instant, zoneId);
} }
return null;
String value = p.getValueAsString();
if (value == null || value.isEmpty()) {
return null;
}
// Handle numeric timestamps passed as strings, e.g. "1769618486000"
if (value.chars().allMatch(Character::isDigit)) {
long ts = Long.parseLong(value);
Instant instant = (value.length() >= 13) ? Instant.ofEpochMilli(ts) : Instant.ofEpochSecond(ts);
return LocalDateTime.ofInstant(instant, zoneId);
}
return LocalDateTime.parse(value, formatter);
} }
} }

View File

@@ -80,7 +80,8 @@ public class SwaggerConfig {
public GroupedOpenApi shopApi() { public GroupedOpenApi shopApi() {
return GroupedOpenApi.builder() return GroupedOpenApi.builder()
.group("shop") .group("shop")
.pathsToMatch("/api/shop/**") // 订单等用户侧接口在 shop 包内,但路径使用 /api/user/**(前端统一 user 侧 API 前缀)
.pathsToMatch("/api/shop/**", "/api/user/**")
.packagesToScan("com.gxwebsoft.shop") .packagesToScan("com.gxwebsoft.shop")
.build(); .build();
} }

View File

@@ -1,20 +1,29 @@
package com.gxwebsoft.common.system.controller; package com.gxwebsoft.common.system.controller;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.gxwebsoft.common.core.annotation.OperationLog; import com.gxwebsoft.common.core.annotation.OperationLog;
import com.gxwebsoft.common.core.web.*; import com.gxwebsoft.common.core.web.*;
import com.gxwebsoft.common.system.entity.Menu; import com.gxwebsoft.common.system.entity.*;
import com.gxwebsoft.common.system.entity.Plug; import com.gxwebsoft.common.system.param.MenuImportParam;
import com.gxwebsoft.common.system.param.MenuParam; import com.gxwebsoft.common.system.param.MenuParam;
import com.gxwebsoft.common.system.service.MenuService; import com.gxwebsoft.common.system.param.VersionParam;
import com.gxwebsoft.common.system.service.PlugService; import com.gxwebsoft.common.system.service.*;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation; 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.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.List; import java.util.*;
import java.util.stream.Collectors;
/** /**
* 菜单控制器 * 菜单控制器
@@ -22,21 +31,27 @@ import java.util.List;
* @author WebSoft * @author WebSoft
* @since 2018-12-24 16:10:23 * @since 2018-12-24 16:10:23
*/ */
@Tag(name = "菜单管理") @Tag(name = "菜单")
@RestController @RestController
@RequestMapping("/api/system/menu") @RequestMapping("/api/system/menu")
public class MenuController extends BaseController { public class MenuController extends BaseController {
@Resource @Resource
private MenuService menuService; private MenuService menuService;
@Resource @Resource
private PlugService plugService; private CompanyService companyService;
@Resource
private UserService userService;
@Resource
private RoleService roleService;
@Resource
private RoleMenuService roleMenuService;
@PreAuthorize("hasAuthority('sys:menu:list')") @PreAuthorize("hasAuthority('sys:menu:list')")
@Operation(summary = "分页查询菜单") @Operation(summary = "分页查询菜单")
@GetMapping("/page") @GetMapping("/page")
public ApiResult<PageResult<Menu>> page(MenuParam param) { public ApiResult<PageResult<Menu>> page(MenuParam param) {
PageParam<Menu, MenuParam> page = new PageParam<>(param); PageParam<Menu, MenuParam> page = new PageParam<>(param);
page.setDefaultOrder("sort_number"); page.setDefaultOrder("sort_number asc, create_time desc");
return success(menuService.page(page, page.getWrapper())); return success(menuService.page(page, page.getWrapper()));
} }
@@ -45,7 +60,7 @@ public class MenuController extends BaseController {
@GetMapping() @GetMapping()
public ApiResult<List<Menu>> list(MenuParam param) { public ApiResult<List<Menu>> list(MenuParam param) {
PageParam<Menu, MenuParam> page = new PageParam<>(param); PageParam<Menu, MenuParam> page = new PageParam<>(param);
page.setDefaultOrder("sort_number"); page.setDefaultOrder("sort_number asc, create_time desc");
return success(menuService.list(page.getOrderWrapper())); return success(menuService.list(page.getOrderWrapper()));
} }
@@ -57,12 +72,18 @@ public class MenuController extends BaseController {
} }
@PreAuthorize("hasAuthority('sys:menu:save')") @PreAuthorize("hasAuthority('sys:menu:save')")
@OperationLog
@Operation(summary = "添加菜单") @Operation(summary = "添加菜单")
@PostMapping() @PostMapping()
public ApiResult<?> add(@RequestBody Menu menu) { public ApiResult<?> add(@RequestBody Menu menu) {
if (menu.getParentId() == null) { if (menu.getParentId() == null) {
menu.setParentId(0); menu.setParentId(0);
} }
// 去除字符串前面的空格
menu.setTitle(StrUtil.trimStart(menu.getTitle()));
menu.setPath(StrUtil.trimStart(menu.getPath()));
menu.setComponent(StrUtil.trimStart(menu.getComponent()));
menu.setAuthority(StrUtil.trimStart(menu.getAuthority()));
if (menuService.save(menu)) { if (menuService.save(menu)) {
return success("添加成功"); return success("添加成功");
} }
@@ -70,9 +91,15 @@ public class MenuController extends BaseController {
} }
@PreAuthorize("hasAuthority('sys:menu:update')") @PreAuthorize("hasAuthority('sys:menu:update')")
@OperationLog
@Operation(summary = "修改菜单") @Operation(summary = "修改菜单")
@PutMapping() @PutMapping()
public ApiResult<?> update(@RequestBody Menu menu) { public ApiResult<?> update(@RequestBody Menu menu) {
// 去除字符串前面的空格
menu.setTitle(StrUtil.trimStart(menu.getTitle()));
menu.setPath(StrUtil.trimStart(menu.getPath()));
menu.setComponent(StrUtil.trimStart(menu.getComponent()));
menu.setAuthority(StrUtil.trimStart(menu.getAuthority()));
if (menuService.updateById(menu)) { if (menuService.updateById(menu)) {
return success("修改成功"); return success("修改成功");
} }
@@ -80,6 +107,7 @@ public class MenuController extends BaseController {
} }
@PreAuthorize("hasAuthority('sys:menu:remove')") @PreAuthorize("hasAuthority('sys:menu:remove')")
@OperationLog
@Operation(summary = "删除菜单") @Operation(summary = "删除菜单")
@DeleteMapping("/{id}") @DeleteMapping("/{id}")
public ApiResult<?> remove(@PathVariable("id") Integer id) { public ApiResult<?> remove(@PathVariable("id") Integer id) {
@@ -90,6 +118,7 @@ public class MenuController extends BaseController {
} }
@PreAuthorize("hasAuthority('sys:menu:save')") @PreAuthorize("hasAuthority('sys:menu:save')")
@OperationLog
@Operation(summary = "批量添加菜单") @Operation(summary = "批量添加菜单")
@PostMapping("/batch") @PostMapping("/batch")
public ApiResult<?> saveBatch(@RequestBody List<Menu> menus) { public ApiResult<?> saveBatch(@RequestBody List<Menu> menus) {
@@ -100,6 +129,7 @@ public class MenuController extends BaseController {
} }
@PreAuthorize("hasAuthority('sys:menu:update')") @PreAuthorize("hasAuthority('sys:menu:update')")
@OperationLog
@Operation(summary = "批量修改菜单") @Operation(summary = "批量修改菜单")
@PutMapping("/batch") @PutMapping("/batch")
public ApiResult<?> updateBatch(@RequestBody BatchParam<Menu> batchParam) { public ApiResult<?> updateBatch(@RequestBody BatchParam<Menu> batchParam) {
@@ -110,6 +140,7 @@ public class MenuController extends BaseController {
} }
@PreAuthorize("hasAuthority('sys:menu:remove')") @PreAuthorize("hasAuthority('sys:menu:remove')")
@OperationLog
@Operation(summary = "批量删除菜单") @Operation(summary = "批量删除菜单")
@DeleteMapping("/batch") @DeleteMapping("/batch")
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) { public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
@@ -119,14 +150,35 @@ public class MenuController extends BaseController {
return fail("删除失败"); return fail("删除失败");
} }
@PreAuthorize("hasAuthority('sys:menu:update')") @PreAuthorize("hasAuthority('sys:menu:remove')")
@Operation(summary = "菜单克隆") @Operation(summary = "删除父级以下菜单")
@PostMapping("/clone") @DeleteMapping("/deleteParentMenu/{id}")
public ApiResult<?> onClone(@RequestBody MenuParam param){ public ApiResult<?> deleteParentMenu(@PathVariable("id") Integer id) {
if(menuService.cloneMenu(param)){ final List<Menu> list = menuService.list(new LambdaQueryWrapper<Menu>().eq(Menu::getParentId, id));
return success("克隆成功,请刷新"); if (CollectionUtils.isEmpty(list)) {
menuService.removeById(id);
return success("删除成功");
} }
return fail("克隆失败"); final Set<Integer> ids = list.stream().map(Menu::getMenuId).collect(Collectors.toSet());
final List<Menu> list2 = menuService.list(new LambdaUpdateWrapper<Menu>().in(Menu::getParentId, ids));
final Set<Integer> collect = list2.stream().map(Menu::getMenuId).collect(Collectors.toSet());
if (!CollectionUtils.isEmpty(list2)) {
ids.addAll(collect);
final List<Menu> list3 = menuService.list(new LambdaUpdateWrapper<Menu>().in(Menu::getParentId, ids));
final Set<Integer> collect1 = list3.stream().map(Menu::getMenuId).collect(Collectors.toSet());
if (!CollectionUtils.isEmpty(collect1)) {
ids.addAll(collect1);
}
ids.add(id);
if (menuService.removeByIds(ids)) {
return success("删除成功");
}
}
ids.add(id);
if (menuService.removeByIds(ids)) {
return success("删除成功");
}
return fail("删除失败");
} }
@PreAuthorize("hasAuthority('sys:menu:update')") @PreAuthorize("hasAuthority('sys:menu:update')")
@@ -135,11 +187,271 @@ public class MenuController extends BaseController {
public ApiResult<?> install(@PathVariable("id") Integer id){ public ApiResult<?> install(@PathVariable("id") Integer id){
if(menuService.install(id)){ if(menuService.install(id)){
// 更新安装次数 // 更新安装次数
final Plug plug = plugService.getOne(new LambdaQueryWrapper<Plug>().eq(Plug::getMenuId, id)); // final Plug plug = plugService.getOne(new LambdaQueryWrapper<Plug>().eq(Plug::getMenuId, id));
plug.setInstalls(plug.getInstalls() + 1); // plug.setInstalls(plug.getInstalls() + 1);
plugService.updateById(plug); // plugService.updateById(plug);
return success("安装成功"); return success("安装成功");
} }
return fail("安装失败",id); return fail("安装失败",id);
} }
/**
* excel批量导入菜单
*/
@PreAuthorize("hasAuthority('sys:menu:save')")
@Operation(summary = "批量导入菜单")
@Transactional(rollbackFor = {Exception.class})
@PostMapping("/import")
public ApiResult<?> importBatch(MultipartFile file) {
ImportParams importParams = new ImportParams();
try {
System.out.println("=== 开始菜单导入流程 ===");
// 检查导入前的菜单数据
long beforeCount = menuService.count();
System.out.println("导入前菜单总数: " + beforeCount);
// 检查当前未删除的菜单
List<Menu> undeletedMenus = menuService.list(new LambdaQueryWrapper<Menu>().eq(Menu::getDeleted, 0));
System.out.println("当前未删除的菜单数: " + undeletedMenus.size());
if (!undeletedMenus.isEmpty()) {
System.out.println("未删除菜单列表:");
for (Menu menu : undeletedMenus) {
System.out.println(" ID: " + menu.getMenuId() + ", 名称: " + menu.getTitle() +
", 父级ID: " + menu.getParentId() + ", deleted: " + menu.getDeleted());
}
}
// 第一步:永久删除已标记为 deleted=1 的记录
boolean deleteResult = menuService.remove(new LambdaQueryWrapper<Menu>().eq(Menu::getDeleted, 1));
System.out.println("已永久删除标记为deleted=1的菜单记录结果: " + deleteResult);
// 第二步将现有未删除的记录deleted=0标记为 deleted=1
if (!undeletedMenus.isEmpty()) {
LambdaUpdateWrapper<Menu> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(Menu::getDeleted, 0);
updateWrapper.set(Menu::getDeleted, 1);
boolean updateResult = menuService.update(updateWrapper);
System.out.println("更新未删除菜单记录的结果: " + updateResult);
}
// 检查更新后的菜单数据
long afterCleanupCount = menuService.count(new LambdaQueryWrapper<Menu>().eq(Menu::getDeleted, 0));
System.out.println("清理后未标记删除的菜单数: " + afterCleanupCount);
// 第三步导入XLS文件的内容
List<MenuImportParam> list = ExcelImportUtil.importExcel(file.getInputStream(), MenuImportParam.class, importParams);
System.out.println("从Excel文件中读取到" + list.size() + "条菜单记录");
// 存储原始parentId到菜单列表的映射关系
Map<Integer, List<MenuImportParam>> menuGroups = new HashMap<>();
// 存储原始ID到新菜单对象的映射关系用于后续设置正确的parentId
Map<Integer, Menu> tempIdMapping = new HashMap<>();
// 按parentId分组处理null值
for (MenuImportParam param : list) {
Integer parentId = param.getParentId() != null ? param.getParentId() : 0;
menuGroups.computeIfAbsent(parentId, k -> new ArrayList<>()).add(param);
}
System.out.println("菜单分组情况:");
for (Map.Entry<Integer, List<MenuImportParam>> entry : menuGroups.entrySet()) {
System.out.println(" parentId=" + entry.getKey() + " 的菜单数: " + entry.getValue().size());
}
// 先创建所有父级菜单parentId为0的菜单
List<MenuImportParam> rootMenus = menuGroups.getOrDefault(0, new ArrayList<>());
List<Menu> createdRootMenus = new ArrayList<>();
System.out.println("开始创建" + rootMenus.size() + "个根菜单");
for (MenuImportParam param : rootMenus) {
Menu menu = convertToMenu(param);
menu.setParentId(0); // 根菜单的parentId为0
menuService.save(menu);
createdRootMenus.add(menu);
System.out.println("创建根菜单: " + menu.getTitle() + ", ID: " + menu.getMenuId() + ", 原始ID: " + param.getMenuId());
// 记录原始ID到新菜单的映射关系
if (param.getMenuId() != null) {
tempIdMapping.put(param.getMenuId(), menu);
}
}
// 递归创建子级菜单注意这里不再处理parentId=0的菜单因为已经在上面处理过了
System.out.println("开始创建子级菜单(跳过根菜单)");
// 只处理非根菜单的子级菜单
for (Map.Entry<Integer, List<MenuImportParam>> entry : menuGroups.entrySet()) {
Integer parentId = entry.getKey();
if (parentId != 0) { // 跳过根菜单parentId=0
System.out.println("处理parentId=" + parentId + "的子菜单");
createChildMenus(menuGroups, tempIdMapping, parentId);
}
}
// 获取所有导入的菜单ID
List<Integer> allImportedMenuIds = new ArrayList<>();
for (Menu menu : tempIdMapping.values()) {
allImportedMenuIds.add(menu.getMenuId());
}
System.out.println("总共导入了" + allImportedMenuIds.size() + "个菜单");
// 显示导入的菜单详情
if (!allImportedMenuIds.isEmpty()) {
List<Menu> allImportedMenus = menuService.list(new LambdaQueryWrapper<Menu>()
.in(Menu::getMenuId, allImportedMenuIds)
.orderByAsc(Menu::getParentId, Menu::getSortNumber));
System.out.println("导入的菜单详情:");
for (Menu menu : allImportedMenus) {
System.out.println(" ID: " + menu.getMenuId() + ", 名称: " + menu.getTitle() +
", 父级ID: " + menu.getParentId() + ", 类型: " + menu.getMenuType());
}
}
// 为超级管理员配置菜单权限
if (!allImportedMenuIds.isEmpty()) {
List<Menu> allImportedMenus = menuService.list(new LambdaQueryWrapper<Menu>()
.in(Menu::getMenuId, allImportedMenuIds));
System.out.println("" + allImportedMenus.size() + "个菜单配置超级管理员权限");
configureSuperAdminPermissionsForImportedMenus(allImportedMenus);
}
// 最终检查
long finalCount = menuService.count();
System.out.println("导入后菜单总数: " + finalCount);
System.out.println("=== 菜单导入流程结束 ===");
return success("成功导入" + list.size() + "");
} catch (Exception e) {
e.printStackTrace();
return fail("导入失败: " + e.getMessage());
}
}
/**
* 递归创建子级菜单
* @param menuGroups 菜单分组
* @param tempIdMapping 临时ID映射关系
* @param originalParentId 原始父级ID
*/
private void createChildMenus(Map<Integer, List<MenuImportParam>> menuGroups,
Map<Integer, Menu> tempIdMapping,
Integer originalParentId) {
System.out.println(">>> 进入createChildMenus方法处理originalParentId=" + originalParentId);
// 特殊处理originalParentId=0的情况已经在主方法中处理过了这里不应该再处理
if (originalParentId == 0) {
System.out.println(" 跳过originalParentId=0的处理已在主方法中处理");
System.out.println("<<< 退出createChildMenus方法处理originalParentId=" + originalParentId);
return;
}
List<MenuImportParam> childMenus = menuGroups.get(originalParentId);
if (childMenus == null || childMenus.isEmpty()) {
System.out.println(" 没有找到originalParentId=" + originalParentId + "的子菜单");
System.out.println("<<< 退出createChildMenus方法处理originalParentId=" + originalParentId);
return;
}
// 获取新的父级菜单对象
Menu parentMenu = tempIdMapping.get(originalParentId);
if (parentMenu == null) {
System.out.println(" 未找到原始ID为" + originalParentId + "的父级菜单,跳过处理");
System.out.println("<<< 退出createChildMenus方法处理originalParentId=" + originalParentId);
return;
}
Integer newParentId = parentMenu.getMenuId();
System.out.println(" 创建父级ID为" + originalParentId + "(新ID:" + newParentId + ")的子菜单,共" + childMenus.size() + "");
// 创建所有子菜单
for (int i = 0; i < childMenus.size(); i++) {
MenuImportParam param = childMenus.get(i);
System.out.println(" 处理第" + (i+1) + "个子菜单原始ID: " + param.getMenuId() + ", 原始ParentId: " + param.getParentId());
Menu menu = convertToMenu(param);
menu.setParentId(newParentId);
menuService.save(menu);
System.out.println(" 创建子菜单: " + menu.getTitle() + ", ID: " + menu.getMenuId() +
", 父级ID: " + menu.getParentId() + ", 原始ID: " + param.getMenuId());
// 记录原始ID到新菜单的映射关系
if (param.getMenuId() != null) {
tempIdMapping.put(param.getMenuId(), menu);
}
// 递归创建当前菜单的子级菜单使用原始ID作为下一个递归的父级ID
System.out.println(" 递归调用createChildMenus处理原始ID=" + param.getMenuId() + "的子菜单");
createChildMenus(menuGroups, tempIdMapping, param.getMenuId());
}
System.out.println("<<< 退出createChildMenus方法处理originalParentId=" + originalParentId);
}
/**
* 将MenuImportParam转换为Menu实体
* @param param MenuImportParam对象
* @return Menu实体
*/
private Menu convertToMenu(MenuImportParam param) {
Menu menu = new Menu();
menu.setParentId(param.getParentId());
menu.setTitle(param.getTitle());
menu.setPath(param.getPath());
menu.setComponent(param.getComponent());
menu.setModules(param.getModules());
menu.setModulesUrl(param.getModulesUrl());
menu.setMenuType(param.getMenuType());
menu.setSortNumber(param.getSortNumber() != null ? param.getSortNumber() : 0);
menu.setAuthority(param.getAuthority());
menu.setIcon(param.getIcon());
menu.setHide(param.getHide());
menu.setAppId(param.getAppId());
menu.setTenantId(param.getTenantId());
menu.setDeleted(0); // 新导入的数据deleted设为0
return menu;
}
/**
* 为超级管理员配置导入菜单的权限
* @param importedMenus 导入的菜单列表
*/
private void configureSuperAdminPermissionsForImportedMenus(List<Menu> importedMenus) {
try {
// 1.查找当前租户的超管权限的roleId
final Role superAdmin = roleService.getOne(new LambdaQueryWrapper<Role>().eq(Role::getRoleCode, "superAdmin"));
if (superAdmin == null) {
System.out.println("未找到superAdmin角色");
return;
}
final Integer roleId = superAdmin.getRoleId();
final Integer tenantId = superAdmin.getTenantId();
// 为所有导入的菜单配置权限
for (Menu menu : importedMenus) {
RoleMenu roleMenu = new RoleMenu();
roleMenu.setRoleId(roleId);
roleMenu.setMenuId(menu.getMenuId());
roleMenu.setTenantId(tenantId);
roleMenuService.save(roleMenu);
}
// 调整根菜单的排序(如果有根菜单的话)
for (Menu menu : importedMenus) {
if (menu.getParentId() == 0) {
menu.setSortNumber(0);
menuService.updateById(menu);
break;
}
}
System.out.println("为超级管理员配置菜单权限成功,共配置了" + importedMenus.size() + "个菜单");
} catch (Exception e) {
System.err.println("为超级管理员配置菜单权限失败: " + e.getMessage());
e.printStackTrace();
}
}
} }

View File

@@ -10,6 +10,8 @@ import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.gxwebsoft.cms.entity.CmsWebsite;
import com.gxwebsoft.cms.service.CmsWebsiteService;
import com.gxwebsoft.common.core.config.ConfigProperties; import com.gxwebsoft.common.core.config.ConfigProperties;
import com.gxwebsoft.common.core.exception.BusinessException; import com.gxwebsoft.common.core.exception.BusinessException;
import com.gxwebsoft.common.core.security.JwtSubject; import com.gxwebsoft.common.core.security.JwtSubject;
@@ -74,6 +76,8 @@ public class WxLoginController extends BaseController {
private ConfigProperties config; private ConfigProperties config;
@Resource @Resource
private UserRefereeService userRefereeService; private UserRefereeService userRefereeService;
@Resource
private CmsWebsiteService cmsWebsiteService;
public WxLoginController(StringRedisTemplate redisTemplate) { public WxLoginController(StringRedisTemplate redisTemplate) {
@@ -442,6 +446,13 @@ public class WxLoginController extends BaseController {
map.put("page", "pages/index/index"); map.put("page", "pages/index/index");
map.put("env_version", "release"); map.put("env_version", "release");
// 判断应用运行状态
final CmsWebsite website = cmsWebsiteService.getByTenantId(tenantId);
if(website.getRunning().equals(2)){
map.put("check_path",false);
map.put("env_version","trial");
}
String jsonBody = JSON.toJSONString(map); String jsonBody = JSON.toJSONString(map);
System.out.println("请求的 JSON body = " + jsonBody); System.out.println("请求的 JSON body = " + jsonBody);

View File

@@ -1,13 +1,12 @@
package com.gxwebsoft.common.system.entity; package com.gxwebsoft.common.system.entity;
import com.baomidou.mybatisplus.annotation.*; import com.baomidou.mybatisplus.annotation.*;
import io.swagger.v3.oas.annotations.media.Schema; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
import java.time.LocalDateTime; import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.util.List; import java.util.List;
/** /**
@@ -19,6 +18,7 @@ import java.util.List;
@Data @Data
@Schema(description = "菜单") @Schema(description = "菜单")
@TableName("sys_menu") @TableName("sys_menu")
@JsonIgnoreProperties(ignoreUnknown = true)
public class Menu implements GrantedAuthority { public class Menu implements GrantedAuthority {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public static final int TYPE_MENU = 0; // 菜单类型 public static final int TYPE_MENU = 0; // 菜单类型
@@ -40,9 +40,19 @@ public class Menu implements GrantedAuthority {
@Schema(description = "菜单组件地址") @Schema(description = "菜单组件地址")
private String component; private String component;
@Schema(description = "模块ID")
private String modules;
@Schema(description = "模块API")
private String modulesUrl;
@Schema(description = "菜单类型, 0菜单, 1按钮") @Schema(description = "菜单类型, 0菜单, 1按钮")
private Integer menuType; private Integer menuType;
@Schema(description = "打开方式, 0当前页, 1新窗口")
@TableField(exist = false)
private Integer openType;
@Schema(description = "排序号") @Schema(description = "排序号")
private Integer sortNumber; private Integer sortNumber;
@@ -69,12 +79,10 @@ public class Menu implements GrantedAuthority {
private Integer tenantId; private Integer tenantId;
@Schema(description = "创建时间") @Schema(description = "创建时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date createTime;
private LocalDateTime createTime;
@Schema(description = "修改时间") @Schema(description = "修改时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date updateTime;
private LocalDateTime updateTime;
@Schema(description = "子菜单") @Schema(description = "子菜单")
@TableField(exist = false) @TableField(exist = false)

View File

@@ -3,7 +3,7 @@
<mapper namespace="com.gxwebsoft.common.system.mapper.UserRoleMapper"> <mapper namespace="com.gxwebsoft.common.system.mapper.UserRoleMapper">
<insert id="insertBatch"> <insert id="insertBatch">
INSERT INTO sys_user_role(user_id, role_id) VALUES INSERT INTO gxwebsoft_core.sys_user_role(user_id, role_id) VALUES
<foreach collection="roleIds" item="roleId" separator=","> <foreach collection="roleIds" item="roleId" separator=",">
(#{userId}, #{roleId}) (#{userId}, #{roleId})
</foreach> </foreach>
@@ -11,10 +11,10 @@
<select id="selectByUserId" resultType="com.gxwebsoft.common.system.entity.Role"> <select id="selectByUserId" resultType="com.gxwebsoft.common.system.entity.Role">
SELECT * SELECT *
FROM sys_role FROM gxwebsoft_core.sys_role
WHERE role_id IN ( WHERE role_id IN (
SELECT role_id SELECT role_id
FROM sys_user_role FROM gxwebsoft_core.sys_user_role
WHERE user_id = #{userId} WHERE user_id = #{userId}
) )
AND deleted = 0 AND deleted = 0
@@ -23,7 +23,7 @@
<select id="selectByUserIds" resultType="com.gxwebsoft.common.system.entity.Role"> <select id="selectByUserIds" resultType="com.gxwebsoft.common.system.entity.Role">
SELECT a.user_id, b.* SELECT a.user_id, b.*
FROM sys_user_role a FROM gxwebsoft_core.sys_user_role a
LEFT JOIN gxwebsoft_core.sys_role b ON a.role_id = b.role_id LEFT JOIN gxwebsoft_core.sys_role b ON a.role_id = b.role_id
WHERE a.user_id IN WHERE a.user_id IN
<foreach collection="userIds" open="(" close=")" separator="," item="userId"> <foreach collection="userIds" open="(" close=")" separator="," item="userId">

View File

@@ -0,0 +1,60 @@
package com.gxwebsoft.common.system.param;
import cn.afterturn.easypoi.excel.annotation.Excel;
import lombok.Data;
import java.io.Serializable;
/**
* 菜单导入参数
*
* @author WebSoft
* @since 2025-09-30
*/
@Data
public class MenuImportParam implements Serializable {
private static final long serialVersionUID = 1L;
@Excel(name = "菜单ID")
private Integer menuId;
@Excel(name = "父级ID")
private Integer parentId;
@Excel(name = "菜单名称")
private String title;
@Excel(name = "路由地址")
private String path;
@Excel(name = "组件路径")
private String component;
@Excel(name = "模块ID")
private String modules;
@Excel(name = "模块API")
private String modulesUrl;
@Excel(name = "菜单类型")
private Integer menuType;
@Excel(name = "排序号")
private Integer sortNumber;
@Excel(name = "权限标识")
private String authority;
@Excel(name = "图标")
private String icon;
@Excel(name = "是否隐藏")
private Integer hide;
@Excel(name = "关联应用")
private Integer appId;
@Excel(name = "租户id")
private Integer tenantId;
}

View File

@@ -1,11 +1,11 @@
package com.gxwebsoft.common.system.param; package com.gxwebsoft.common.system.param;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableLogic; import com.baomidou.mybatisplus.annotation.TableLogic;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.gxwebsoft.common.core.annotation.QueryField; import com.gxwebsoft.common.core.annotation.QueryField;
import com.gxwebsoft.common.core.annotation.QueryType; import com.gxwebsoft.common.core.annotation.QueryType;
import com.gxwebsoft.common.core.web.BaseParam; import com.gxwebsoft.common.core.web.BaseParam;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
@@ -40,10 +40,17 @@ public class MenuParam extends BaseParam {
@Schema(description = "菜单组件地址") @Schema(description = "菜单组件地址")
private String component; private String component;
@Schema(description = "模块ID")
private String modules;
@Schema(description = "菜单类型, 0菜单, 1按钮") @Schema(description = "菜单类型, 0菜单, 1按钮")
@QueryField(type = QueryType.EQ) @QueryField(type = QueryType.EQ)
private Integer menuType; private Integer menuType;
@Schema(description = "打开方式, 0当前页, 1新窗口")
@TableField(exist = false)
private Integer openType;
@Schema(description = "权限标识") @Schema(description = "权限标识")
private String authority; private String authority;
@@ -65,4 +72,12 @@ public class MenuParam extends BaseParam {
@QueryField(type = QueryType.EQ) @QueryField(type = QueryType.EQ)
private Integer tenantId; private Integer tenantId;
@Schema(description = "企业ID")
@QueryField(type = QueryType.EQ)
private Integer companyId;
@Schema(description = "租户名称")
@TableField(exist = false)
private String tenantName;
} }

View File

@@ -0,0 +1,70 @@
package com.gxwebsoft.common.system.param;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.gxwebsoft.common.core.annotation.QueryField;
import com.gxwebsoft.common.core.annotation.QueryType;
import com.gxwebsoft.common.core.web.BaseParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 版本更新查询参数
*
* @author 科技小王子
* @since 2024-01-15 18:52:24
*/
@Data
@EqualsAndHashCode(callSuper = false)
@JsonInclude(JsonInclude.Include.NON_NULL)
@Schema(name = "VersionParam对象", description = "版本更新查询参数")
public class VersionParam extends BaseParam {
private static final long serialVersionUID = 1L;
@Schema(description = "ID")
@QueryField(type = QueryType.EQ)
private Integer id;
@Schema(description = "版本名")
private String versionName;
@Schema(description = "版本号")
@QueryField(type = QueryType.EQ)
private Integer versionCode;
@Schema(description = "下载链接")
private String androidDownloadUrl;
@Schema(description = "下载链接")
private String iosDownloadUrl;
@Schema(description = "更新日志")
private String updateInfo;
@Schema(description = "强制更新")
@QueryField(type = QueryType.EQ)
private Integer isHard;
@Schema(description = "热更")
@QueryField(type = QueryType.EQ)
private Integer isHot;
@Schema(description = "备注")
private String comments;
@Schema(description = "文章排序(数字越小越靠前)")
@QueryField(type = QueryType.EQ)
private Integer sortNumber;
@QueryField(type = QueryType.EQ)
private Integer userId;
@Schema(description = "状态, 0正常, 1冻结")
@QueryField(type = QueryType.EQ)
private Integer status;
@Schema(description = "是否删除, 0否, 1是")
@QueryField(type = QueryType.EQ)
private Integer deleted;
}

View File

@@ -3,6 +3,8 @@ package com.gxwebsoft.credit.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction; import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import com.gxwebsoft.credit.entity.CreditCompany;
import com.gxwebsoft.credit.service.CreditCompanyService;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.TransactionDefinition;
@@ -11,6 +13,8 @@ import org.springframework.util.CollectionUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
@@ -39,6 +43,202 @@ public class BatchImportSupport {
return requiresNewTx.execute(status -> supplier.get()); return requiresNewTx.execute(status -> supplier.get());
} }
public static final class CompanyIdRefreshStats {
public final boolean anyDataRead;
public final int updated;
public final int matched;
public final int notFound;
public final int ambiguous;
private CompanyIdRefreshStats(boolean anyDataRead, int updated, int matched, int notFound, int ambiguous) {
this.anyDataRead = anyDataRead;
this.updated = updated;
this.matched = matched;
this.notFound = notFound;
this.ambiguous = ambiguous;
}
public Map<String, Object> toMap() {
Map<String, Object> result = new LinkedHashMap<>();
result.put("updated", updated);
result.put("matched", matched);
result.put("notFound", notFound);
result.put("ambiguous", ambiguous);
return result;
}
}
/**
* 按企业名称匹配 CreditCompany(name / matchName) 并回填 companyId。
*
* <p>默认仅更新 companyId=0 的记录onlyNull=trueonlyNull=false 时会覆盖更新(仅当 companyId 不同)。</p>
*
* <p>注意:为避免跨租户误更新,当 currentTenantId 为空时会按记录自身 tenantId 维度匹配,
* tenantId 为空的记录将被跳过并计入 notFound。</p>
*/
public <T> CompanyIdRefreshStats refreshCompanyIdByCompanyName(IService<T> service,
CreditCompanyService creditCompanyService,
Integer currentTenantId,
Boolean onlyNull,
Integer limit,
SFunction<T, Integer> idGetter,
BiConsumer<T, Integer> idSetter,
SFunction<T, String> nameGetter,
SFunction<T, Integer> companyIdGetter,
BiConsumer<T, Integer> companyIdSetter,
SFunction<T, Boolean> hasDataGetter,
BiConsumer<T, Boolean> hasDataSetter,
SFunction<T, Integer> tenantIdGetter,
Supplier<T> patchFactory) {
boolean onlyNullFlag = (onlyNull == null) || Boolean.TRUE.equals(onlyNull);
// 1) 读取待处理数据(仅取必要字段,避免一次性拉全表字段)
var query = service.lambdaQuery()
.select(idGetter, nameGetter, companyIdGetter, hasDataGetter, tenantIdGetter)
.eq(currentTenantId != null, tenantIdGetter, currentTenantId)
.isNotNull(nameGetter);
if (onlyNullFlag) {
query.eq(companyIdGetter, 0);
}
if (limit != null && limit > 0) {
query.last("limit " + Math.min(limit, 200000));
}
List<T> rows = query.list();
if (CollectionUtils.isEmpty(rows)) {
return new CompanyIdRefreshStats(false, 0, 0, 0, 0);
}
// 2) 按租户维度匹配(避免管理员/跨租户场景误匹配)
Map<Integer, List<T>> rowsByTenant = new LinkedHashMap<>();
int missingTenant = 0;
for (T row : rows) {
if (row == null) {
continue;
}
Integer tenantId = currentTenantId != null ? currentTenantId : tenantIdGetter.apply(row);
if (tenantId == null) {
// 未知租户下不做跨租户匹配,避免误更新
missingTenant++;
continue;
}
rowsByTenant.computeIfAbsent(tenantId, k -> new ArrayList<>()).add(row);
}
// 3) 批量更新 companyId
int updated = 0;
int matched = 0;
int notFound = 0;
int ambiguous = 0;
final int batchSize = 500;
List<T> updates = new ArrayList<>(batchSize);
final int inChunkSize = 900;
for (Map.Entry<Integer, List<T>> entry : rowsByTenant.entrySet()) {
Integer tenantId = entry.getKey();
List<T> tenantRows = entry.getValue();
if (tenantId == null || CollectionUtils.isEmpty(tenantRows)) {
continue;
}
// 3.1) 查询当前租户下的 companyId 映射
LinkedHashMap<String, Integer> companyIdByName = new LinkedHashMap<>();
LinkedHashMap<String, Integer> ambiguousByName = new LinkedHashMap<>();
LinkedHashSet<String> nameSet = new LinkedHashSet<>();
for (T row : tenantRows) {
String name = normalizeCompanyName(row != null ? nameGetter.apply(row) : null);
if (name != null) {
nameSet.add(name);
}
}
List<String> allNames = new ArrayList<>(nameSet);
for (int i = 0; i < allNames.size(); i += inChunkSize) {
List<String> chunk = allNames.subList(i, Math.min(allNames.size(), i + inChunkSize));
if (CollectionUtils.isEmpty(chunk)) {
continue;
}
List<CreditCompany> companies = creditCompanyService.lambdaQuery()
.select(CreditCompany::getId, CreditCompany::getName, CreditCompany::getMatchName, CreditCompany::getTenantId)
.eq(CreditCompany::getTenantId, tenantId)
.and(w -> w.in(CreditCompany::getName, chunk).or().in(CreditCompany::getMatchName, chunk))
.list();
for (CreditCompany c : companies) {
if (c == null || c.getId() == null) {
continue;
}
addCompanyNameMapping(companyIdByName, ambiguousByName, normalizeCompanyName(c.getName()), c.getId());
addCompanyNameMapping(companyIdByName, ambiguousByName, normalizeCompanyName(c.getMatchName()), c.getId());
}
}
// 3.2) 更新当前租户下的数据 companyId
for (T row : tenantRows) {
String key = normalizeCompanyName(row != null ? nameGetter.apply(row) : null);
if (key == null) {
continue;
}
Integer amb = ambiguousByName.get(key);
if (amb != null && amb > 0) {
ambiguous++;
continue;
}
Integer companyId = companyIdByName.get(key);
if (companyId == null) {
notFound++;
continue;
}
matched++;
Integer oldCompanyId = row != null ? companyIdGetter.apply(row) : null;
Boolean oldHasData = row != null ? hasDataGetter.apply(row) : null;
boolean needUpdate;
if (onlyNullFlag) {
needUpdate = oldCompanyId != null && oldCompanyId == 0;
} else {
needUpdate = oldCompanyId == null || !companyId.equals(oldCompanyId);
}
// 若已匹配到企业,但 hasData 未标记,则也需要回填 hasData=1
if (!Boolean.TRUE.equals(oldHasData)) {
needUpdate = true;
}
if (!needUpdate) {
continue;
}
Integer id = row != null ? idGetter.apply(row) : null;
if (id == null) {
continue;
}
T patch = patchFactory.get();
idSetter.accept(patch, id);
companyIdSetter.accept(patch, companyId);
hasDataSetter.accept(patch, Boolean.TRUE);
updates.add(patch);
if (updates.size() >= batchSize) {
List<T> batch = new ArrayList<>(updates);
updates.clear();
updated += runInNewTx(() -> service.updateBatchById(batch, batchSize) ? batch.size() : 0);
}
}
}
// currentTenantId 为空时,租户缺失的数据不做匹配更新,避免误更新
if (currentTenantId == null && missingTenant > 0) {
notFound += missingTenant;
}
if (!updates.isEmpty()) {
List<T> batch = new ArrayList<>(updates);
updates.clear();
updated += runInNewTx(() -> service.updateBatchById(batch, batchSize) ? batch.size() : 0);
}
return new CompanyIdRefreshStats(true, updated, matched, notFound, ambiguous);
}
/** /**
* 批量 upsert优先按 code 匹配code 为空时按 name 匹配。 * 批量 upsert优先按 code 匹配code 为空时按 name 匹配。
*/ */
@@ -209,6 +409,216 @@ public class BatchImportSupport {
return updates.size() + inserts.size(); return updates.size() + inserts.size();
} }
/**
* 批量 upsert按单字段 key 匹配key 非空)。当匹配到已存在记录时:
* - 覆盖更新
* - 将 counter通常是 recommend在数据库原值基础上 +1用于记录“被更新次数”
*
* <p>注意counter 会被覆盖写入(不是 SQL 自增),因此该方法适合导入场景。</p>
*/
public <T> int upsertBySingleKeyAndIncrementCounterOnUpdate(IService<T> service,
List<T> items,
SFunction<T, Integer> idColumn,
BiConsumer<T, Integer> idSetter,
SFunction<T, String> keyColumn,
Function<T, String> keyGetter,
SFunction<T, Integer> counterColumn,
BiConsumer<T, Integer> counterSetter,
Consumer<LambdaQueryWrapper<T>> extraConditions,
int batchSize) {
if (CollectionUtils.isEmpty(items)) {
return 0;
}
List<String> keys = new ArrayList<>(items.size());
for (T item : items) {
if (item == null) {
continue;
}
String key = normalize(keyGetter.apply(item));
if (key != null) {
keys.add(key);
}
}
Map<String, Integer> idByKey = new HashMap<>();
Map<String, Integer> counterByKey = new HashMap<>();
if (!keys.isEmpty()) {
LambdaQueryWrapper<T> wrapper = new LambdaQueryWrapper<>();
if (extraConditions != null) {
extraConditions.accept(wrapper);
}
wrapper.in(keyColumn, keys);
wrapper.select(idColumn, keyColumn, counterColumn);
for (T dbRow : service.list(wrapper)) {
String key = normalize(keyGetter.apply(dbRow));
Integer id = extractId(dbRow, idColumn);
if (key == null || id == null) {
continue;
}
idByKey.putIfAbsent(key, id);
if (counterColumn != null) {
counterByKey.putIfAbsent(key, counterColumn.apply(dbRow));
}
}
}
List<T> updates = new ArrayList<>();
List<T> inserts = new ArrayList<>();
for (T item : items) {
if (item == null) {
continue;
}
String key = normalize(keyGetter.apply(item));
Integer id = key != null ? idByKey.get(key) : null;
if (id != null) {
idSetter.accept(item, id);
Integer old = key != null ? counterByKey.get(key) : null;
if (counterSetter != null) {
counterSetter.accept(item, old == null ? 1 : old + 1);
}
updates.add(item);
} else {
// insert如果未提供 counterSetter则不做处理如果提供则默认 0。
if (counterSetter != null) {
counterSetter.accept(item, 0);
}
inserts.add(item);
}
}
if (!updates.isEmpty()) {
service.updateBatchById(updates, batchSize);
}
if (!inserts.isEmpty()) {
service.saveBatch(inserts, batchSize);
}
return updates.size() + inserts.size();
}
/**
* 批量 upsert优先按 code 匹配code 为空时按 name 匹配。匹配到已存在记录时 counter +1。
*/
public <T> int upsertByCodeOrNameAndIncrementCounterOnUpdate(IService<T> service,
List<T> items,
SFunction<T, Integer> idColumn,
BiConsumer<T, Integer> idSetter,
SFunction<T, String> codeColumn,
Function<T, String> codeGetter,
SFunction<T, String> nameColumn,
Function<T, String> nameGetter,
SFunction<T, Integer> counterColumn,
BiConsumer<T, Integer> counterSetter,
Consumer<LambdaQueryWrapper<T>> extraConditions,
int batchSize) {
if (CollectionUtils.isEmpty(items)) {
return 0;
}
List<String> codes = new ArrayList<>();
List<String> names = new ArrayList<>();
for (T item : items) {
if (item == null) {
continue;
}
String code = normalize(codeGetter.apply(item));
if (code != null) {
codes.add(code);
} else {
String name = normalize(nameGetter.apply(item));
if (name != null) {
names.add(name);
}
}
}
Map<String, Integer> idByCode = new HashMap<>();
Map<String, Integer> counterByCode = new HashMap<>();
if (!codes.isEmpty()) {
LambdaQueryWrapper<T> wrapper = new LambdaQueryWrapper<>();
if (extraConditions != null) {
extraConditions.accept(wrapper);
}
wrapper.in(codeColumn, codes);
wrapper.select(idColumn, codeColumn, counterColumn);
for (T dbRow : service.list(wrapper)) {
String code = normalize(codeGetter.apply(dbRow));
Integer id = extractId(dbRow, idColumn);
if (code == null || id == null) {
continue;
}
idByCode.putIfAbsent(code, id);
if (counterColumn != null) {
counterByCode.putIfAbsent(code, counterColumn.apply(dbRow));
}
}
}
Map<String, Integer> idByName = new HashMap<>();
Map<String, Integer> counterByName = new HashMap<>();
if (!names.isEmpty()) {
LambdaQueryWrapper<T> wrapper = new LambdaQueryWrapper<>();
if (extraConditions != null) {
extraConditions.accept(wrapper);
}
wrapper.in(nameColumn, names);
wrapper.select(idColumn, nameColumn, counterColumn);
for (T dbRow : service.list(wrapper)) {
String name = normalize(nameGetter.apply(dbRow));
Integer id = extractId(dbRow, idColumn);
if (name == null || id == null) {
continue;
}
idByName.putIfAbsent(name, id);
if (counterColumn != null) {
counterByName.putIfAbsent(name, counterColumn.apply(dbRow));
}
}
}
List<T> updates = new ArrayList<>();
List<T> inserts = new ArrayList<>();
for (T item : items) {
if (item == null) {
continue;
}
String code = normalize(codeGetter.apply(item));
Integer id = null;
Integer old = null;
if (code != null) {
id = idByCode.get(code);
old = counterByCode.get(code);
} else {
String name = normalize(nameGetter.apply(item));
if (name != null) {
id = idByName.get(name);
old = counterByName.get(name);
}
}
if (id != null) {
idSetter.accept(item, id);
if (counterSetter != null) {
counterSetter.accept(item, old == null ? 1 : old + 1);
}
updates.add(item);
} else {
if (counterSetter != null) {
counterSetter.accept(item, 0);
}
inserts.add(item);
}
}
if (!updates.isEmpty()) {
service.updateBatchById(updates, batchSize);
}
if (!inserts.isEmpty()) {
service.saveBatch(inserts, batchSize);
}
return updates.size() + inserts.size();
}
/** /**
* 批量失败时降级逐行,尽量保留“第 N 行”错误定位。 * 批量失败时降级逐行,尽量保留“第 N 行”错误定位。
*/ */
@@ -244,6 +654,45 @@ public class BatchImportSupport {
} }
} }
/**
* 批量失败时降级逐行:允许调用方自定义“成功条数”的计算口径(例如:仅统计 insert 入库条数)。
*
* <p>batchPersistCount / rowPersistCount 返回的是“需要累计的条数增量”,并不等同于“是否成功”。</p>
*/
public <T> int persistChunkWithFallbackCount(List<T> items,
List<Integer> excelRowNumbers,
Supplier<Integer> batchPersistCount,
BiFunction<T, Integer, Integer> rowPersistCount,
List<String> errorMessages) {
if (CollectionUtils.isEmpty(items)) {
return 0;
}
try {
return runInNewTx(batchPersistCount);
} catch (Exception batchException) {
int count = 0;
for (int i = 0; i < items.size(); i++) {
T item = items.get(i);
int excelRowNumber = (excelRowNumbers != null && i < excelRowNumbers.size()) ? excelRowNumbers.get(i) : -1;
try {
Integer delta = runInNewTx(() -> rowPersistCount.apply(item, excelRowNumber));
if (delta != null && delta > 0) {
count += delta;
}
} catch (Exception e) {
if (errorMessages != null) {
if (excelRowNumber > 0) {
errorMessages.add("" + excelRowNumber + "行:" + e.getMessage());
} else {
errorMessages.add(e.getMessage());
}
}
}
}
return count;
}
}
private static String normalize(String value) { private static String normalize(String value) {
if (value == null) { if (value == null) {
return null; return null;
@@ -252,9 +701,34 @@ public class BatchImportSupport {
return trimmed.isEmpty() ? null : trimmed; return trimmed.isEmpty() ? null : trimmed;
} }
private static String normalizeCompanyName(String name) {
if (name == null) {
return null;
}
// 兼容 Excel/网页复制带来的全角空格
String v = name.replace(' ', ' ').trim();
return v.isEmpty() ? null : v;
}
private static void addCompanyNameMapping(Map<String, Integer> idByName,
Map<String, Integer> ambiguousByName,
String key,
Integer companyId) {
if (key == null || companyId == null) {
return;
}
Integer existing = idByName.get(key);
if (existing == null) {
idByName.put(key, companyId);
return;
}
if (!existing.equals(companyId)) {
ambiguousByName.put(key, 1);
}
}
private static <T> Integer extractId(T entity, SFunction<T, Integer> idColumn) { private static <T> Integer extractId(T entity, SFunction<T, Integer> idColumn) {
// SFunction 是 getter method ref直接调用即可 // SFunction 是 getter method ref直接调用即可
return idColumn.apply(entity); return idColumn.apply(entity);
} }
} }

View File

@@ -9,6 +9,8 @@ import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.credit.entity.CreditAdministrativeLicense; import com.gxwebsoft.credit.entity.CreditAdministrativeLicense;
import com.gxwebsoft.credit.param.CreditAdministrativeLicenseImportParam; import com.gxwebsoft.credit.param.CreditAdministrativeLicenseImportParam;
import com.gxwebsoft.credit.param.CreditAdministrativeLicenseParam; 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 com.gxwebsoft.credit.service.CreditAdministrativeLicenseService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@@ -22,8 +24,11 @@ import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
/** /**
* 行政许可控制器 * 行政许可控制器
@@ -41,6 +46,12 @@ public class CreditAdministrativeLicenseController extends BaseController {
@Resource @Resource
private BatchImportSupport batchImportSupport; private BatchImportSupport batchImportSupport;
@Resource
private CreditCompanyService creditCompanyService;
@Resource
private CreditCompanyRecordCountService creditCompanyRecordCountService;
@Operation(summary = "分页查询行政许可") @Operation(summary = "分页查询行政许可")
@GetMapping("/page") @GetMapping("/page")
public ApiResult<PageResult<CreditAdministrativeLicense>> page(CreditAdministrativeLicenseParam param) { public ApiResult<PageResult<CreditAdministrativeLicense>> page(CreditAdministrativeLicenseParam param) {
@@ -133,6 +144,45 @@ public class CreditAdministrativeLicenseController extends BaseController {
return fail("删除失败"); 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::getHasData,
CreditAdministrativeLicense::setHasData,
CreditAdministrativeLicense::getTenantId,
CreditAdministrativeLicense::new
);
if (!stats.anyDataRead) {
return success("无可更新数据", stats.toMap());
}
return success("更新完成,更新" + stats.updated + "", stats.toMap());
}
/** /**
* 批量导入行政许可 * 批量导入行政许可
*/ */
@@ -143,6 +193,7 @@ public class CreditAdministrativeLicenseController extends BaseController {
@RequestParam(value = "companyId", required = false) Integer companyId) { @RequestParam(value = "companyId", required = false) Integer companyId) {
List<String> errorMessages = new ArrayList<>(); List<String> errorMessages = new ArrayList<>();
int successCount = 0; int successCount = 0;
Set<Integer> touchedCompanyIds = new HashSet<>();
try { try {
ExcelImportSupport.ImportResult<CreditAdministrativeLicenseImportParam> importResult = ExcelImportSupport.readAnySheet( ExcelImportSupport.ImportResult<CreditAdministrativeLicenseImportParam> importResult = ExcelImportSupport.readAnySheet(
@@ -185,6 +236,9 @@ public class CreditAdministrativeLicenseController extends BaseController {
if (item.getCompanyId() == null && companyId != null) { if (item.getCompanyId() == null && companyId != null) {
item.setCompanyId(companyId); item.setCompanyId(companyId);
} }
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
touchedCompanyIds.add(item.getCompanyId());
}
if (item.getUserId() == null && currentUserId != null) { if (item.getUserId() == null && currentUserId != null) {
item.setUserId(currentUserId); item.setUserId(currentUserId);
} }
@@ -207,6 +261,10 @@ public class CreditAdministrativeLicenseController extends BaseController {
continue; continue;
} }
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
touchedCompanyIds.add(item.getCompanyId());
}
chunkItems.add(item); chunkItems.add(item);
chunkRowNumbers.add(excelRowNumber); chunkRowNumbers.add(excelRowNumber);
if (chunkItems.size() >= chunkSize) { if (chunkItems.size() >= chunkSize) {
@@ -311,6 +369,8 @@ public class CreditAdministrativeLicenseController extends BaseController {
); );
} }
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.ADMINISTRATIVE_LICENSE, touchedCompanyIds);
if (errorMessages.isEmpty()) { if (errorMessages.isEmpty()) {
return success("成功导入" + successCount + "条数据", null); return success("成功导入" + successCount + "条数据", null);
} else { } else {
@@ -322,6 +382,243 @@ public class CreditAdministrativeLicenseController extends BaseController {
} }
} }
/**
* 批量导入历史行政许可(仅解析“历史行政许可”选项卡)
* 规则:优先按编号(code)匹配code 为空时按名称(name)匹配匹配到则覆盖更新recommend++ 记录更新次数)。
*/
@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, "决定文书/许可证名称");
LinkedHashMap<String, CreditAdministrativeLicense> latestByKey = new LinkedHashMap<>();
LinkedHashMap<String, Integer> latestRowByKey = new LinkedHashMap<>();
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 (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);
}
String dedupKey = !ImportHelper.isBlank(item.getCode()) ? ("CODE:" + item.getCode()) : ("NAME:" + item.getName());
latestByKey.put(dedupKey, item);
latestRowByKey.put(dedupKey, excelRowNumber);
} catch (Exception e) {
errorMessages.add("" + excelRowNumber + "行:" + e.getMessage());
e.printStackTrace();
}
}
if (latestByKey.isEmpty()) {
if (errorMessages.isEmpty()) {
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
}
return success("导入完成成功0条失败" + errorMessages.size() + "", errorMessages);
}
final int chunkSize = 500;
final int mpBatchSize = 500;
List<CreditAdministrativeLicense> chunkItems = new ArrayList<>(chunkSize);
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
for (Map.Entry<String, CreditAdministrativeLicense> entry : latestByKey.entrySet()) {
String dedupKey = entry.getKey();
CreditAdministrativeLicense item = entry.getValue();
Integer rowNo = latestRowByKey.get(dedupKey);
chunkItems.add(item);
chunkRowNumbers.add(rowNo != null ? rowNo : -1);
if (chunkItems.size() >= chunkSize) {
successCount += batchImportSupport.persistChunkWithFallback(
chunkItems,
chunkRowNumbers,
() -> batchImportSupport.upsertByCodeOrNameAndIncrementCounterOnUpdate(
creditAdministrativeLicenseService,
chunkItems,
CreditAdministrativeLicense::getId,
CreditAdministrativeLicense::setId,
CreditAdministrativeLicense::getCode,
CreditAdministrativeLicense::getCode,
CreditAdministrativeLicense::getName,
CreditAdministrativeLicense::getName,
CreditAdministrativeLicense::getRecommend,
CreditAdministrativeLicense::setRecommend,
null,
mpBatchSize
),
(rowItem, rowNumber) -> {
if (rowItem.getRecommend() == null) {
rowItem.setRecommend(0);
}
boolean saved = creditAdministrativeLicenseService.save(rowItem);
if (!saved) {
CreditAdministrativeLicense existing = null;
if (!ImportHelper.isBlank(rowItem.getCode())) {
existing = creditAdministrativeLicenseService.lambdaQuery()
.eq(CreditAdministrativeLicense::getCode, rowItem.getCode())
.select(CreditAdministrativeLicense::getId, CreditAdministrativeLicense::getRecommend)
.one();
}
if (existing == null && !ImportHelper.isBlank(rowItem.getName())) {
existing = creditAdministrativeLicenseService.lambdaQuery()
.eq(CreditAdministrativeLicense::getName, rowItem.getName())
.select(CreditAdministrativeLicense::getId, CreditAdministrativeLicense::getRecommend)
.one();
}
if (existing != null) {
rowItem.setId(existing.getId());
Integer old = existing.getRecommend();
rowItem.setRecommend(old == null ? 1 : old + 1);
if (creditAdministrativeLicenseService.updateById(rowItem)) {
return true;
}
}
} else {
return true;
}
String prefix = rowNumber > 0 ? ("" + rowNumber + "行:") : "";
errorMessages.add(prefix + "保存失败");
return false;
},
errorMessages
);
chunkItems.clear();
chunkRowNumbers.clear();
}
}
if (!chunkItems.isEmpty()) {
successCount += batchImportSupport.persistChunkWithFallback(
chunkItems,
chunkRowNumbers,
() -> batchImportSupport.upsertByCodeOrNameAndIncrementCounterOnUpdate(
creditAdministrativeLicenseService,
chunkItems,
CreditAdministrativeLicense::getId,
CreditAdministrativeLicense::setId,
CreditAdministrativeLicense::getCode,
CreditAdministrativeLicense::getCode,
CreditAdministrativeLicense::getName,
CreditAdministrativeLicense::getName,
CreditAdministrativeLicense::getRecommend,
CreditAdministrativeLicense::setRecommend,
null,
mpBatchSize
),
(rowItem, rowNumber) -> {
if (rowItem.getRecommend() == null) {
rowItem.setRecommend(0);
}
boolean saved = creditAdministrativeLicenseService.save(rowItem);
if (!saved) {
CreditAdministrativeLicense existing = null;
if (!ImportHelper.isBlank(rowItem.getCode())) {
existing = creditAdministrativeLicenseService.lambdaQuery()
.eq(CreditAdministrativeLicense::getCode, rowItem.getCode())
.select(CreditAdministrativeLicense::getId, CreditAdministrativeLicense::getRecommend)
.one();
}
if (existing == null && !ImportHelper.isBlank(rowItem.getName())) {
existing = creditAdministrativeLicenseService.lambdaQuery()
.eq(CreditAdministrativeLicense::getName, rowItem.getName())
.select(CreditAdministrativeLicense::getId, CreditAdministrativeLicense::getRecommend)
.one();
}
if (existing != null) {
rowItem.setId(existing.getId());
Integer old = existing.getRecommend();
rowItem.setRecommend(old == null ? 1 : old + 1);
if (creditAdministrativeLicenseService.updateById(rowItem)) {
return true;
}
}
} else {
return true;
}
String prefix = rowNumber > 0 ? ("" + rowNumber + "行:") : "";
errorMessages.add(prefix + "保存失败");
return false;
},
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);
}
}
/** /**
* 下载行政许可导入模板 * 下载行政许可导入模板
*/ */

View File

@@ -9,6 +9,8 @@ import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.credit.entity.CreditBankruptcy; import com.gxwebsoft.credit.entity.CreditBankruptcy;
import com.gxwebsoft.credit.param.CreditBankruptcyImportParam; import com.gxwebsoft.credit.param.CreditBankruptcyImportParam;
import com.gxwebsoft.credit.param.CreditBankruptcyParam; 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 com.gxwebsoft.credit.service.CreditBankruptcyService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@@ -22,8 +24,11 @@ import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
/** /**
* 破产重整控制器 * 破产重整控制器
@@ -41,6 +46,12 @@ public class CreditBankruptcyController extends BaseController {
@Resource @Resource
private BatchImportSupport batchImportSupport; private BatchImportSupport batchImportSupport;
@Resource
private CreditCompanyService creditCompanyService;
@Resource
private CreditCompanyRecordCountService creditCompanyRecordCountService;
@Operation(summary = "分页查询破产重整") @Operation(summary = "分页查询破产重整")
@GetMapping("/page") @GetMapping("/page")
public ApiResult<PageResult<CreditBankruptcy>> page(CreditBankruptcyParam param) { public ApiResult<PageResult<CreditBankruptcy>> page(CreditBankruptcyParam param) {
@@ -133,6 +144,45 @@ public class CreditBankruptcyController extends BaseController {
return fail("删除失败"); 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());
}
/** /**
* 批量导入破产重整 * 批量导入破产重整
*/ */
@@ -143,6 +193,7 @@ public class CreditBankruptcyController extends BaseController {
@RequestParam(value = "companyId", required = false) Integer companyId) { @RequestParam(value = "companyId", required = false) Integer companyId) {
List<String> errorMessages = new ArrayList<>(); List<String> errorMessages = new ArrayList<>();
int successCount = 0; int successCount = 0;
Set<Integer> touchedCompanyIds = new HashSet<>();
try { try {
ExcelImportSupport.ImportResult<CreditBankruptcyImportParam> importResult = ExcelImportSupport.readAnySheet( ExcelImportSupport.ImportResult<CreditBankruptcyImportParam> importResult = ExcelImportSupport.readAnySheet(
@@ -180,6 +231,9 @@ public class CreditBankruptcyController extends BaseController {
if (item.getCompanyId() == null && companyId != null) { if (item.getCompanyId() == null && companyId != null) {
item.setCompanyId(companyId); item.setCompanyId(companyId);
} }
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
touchedCompanyIds.add(item.getCompanyId());
}
if (item.getUserId() == null && currentUserId != null) { if (item.getUserId() == null && currentUserId != null) {
item.setUserId(currentUserId); item.setUserId(currentUserId);
} }
@@ -202,6 +256,10 @@ public class CreditBankruptcyController extends BaseController {
continue; continue;
} }
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
touchedCompanyIds.add(item.getCompanyId());
}
chunkItems.add(item); chunkItems.add(item);
chunkRowNumbers.add(excelRowNumber); chunkRowNumbers.add(excelRowNumber);
if (chunkItems.size() >= chunkSize) { if (chunkItems.size() >= chunkSize) {
@@ -286,6 +344,8 @@ public class CreditBankruptcyController extends BaseController {
); );
} }
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.BANKRUPTCY, touchedCompanyIds);
if (errorMessages.isEmpty()) { if (errorMessages.isEmpty()) {
return success("成功导入" + successCount + "条数据", null); return success("成功导入" + successCount + "条数据", null);
} else { } else {
@@ -297,6 +357,209 @@ public class CreditBankruptcyController extends BaseController {
} }
} }
/**
* 批量导入历史破产重整(仅解析“历史破产重整”选项卡)
* 规则:案号/唯一标识相同则覆盖更新recommend++ 记录更新次数);不存在则插入。
*/
@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, "案号");
LinkedHashMap<String, CreditBankruptcy> latestByCode = new LinkedHashMap<>();
LinkedHashMap<String, Integer> latestRowByCode = new LinkedHashMap<>();
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);
}
latestByCode.put(item.getCode(), item);
latestRowByCode.put(item.getCode(), excelRowNumber);
} catch (Exception e) {
errorMessages.add("" + excelRowNumber + "行:" + e.getMessage());
e.printStackTrace();
}
}
if (latestByCode.isEmpty()) {
if (errorMessages.isEmpty()) {
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
}
return success("导入完成成功0条失败" + errorMessages.size() + "", errorMessages);
}
final int chunkSize = 500;
final int mpBatchSize = 500;
List<CreditBankruptcy> chunkItems = new ArrayList<>(chunkSize);
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
for (Map.Entry<String, CreditBankruptcy> entry : latestByCode.entrySet()) {
String code = entry.getKey();
CreditBankruptcy item = entry.getValue();
Integer rowNo = latestRowByCode.get(code);
chunkItems.add(item);
chunkRowNumbers.add(rowNo != null ? rowNo : -1);
if (chunkItems.size() >= chunkSize) {
successCount += batchImportSupport.persistChunkWithFallback(
chunkItems,
chunkRowNumbers,
() -> batchImportSupport.upsertBySingleKeyAndIncrementCounterOnUpdate(
creditBankruptcyService,
chunkItems,
CreditBankruptcy::getId,
CreditBankruptcy::setId,
CreditBankruptcy::getCode,
CreditBankruptcy::getCode,
CreditBankruptcy::getRecommend,
CreditBankruptcy::setRecommend,
null,
mpBatchSize
),
(rowItem, rowNumber) -> {
if (rowItem.getRecommend() == null) {
rowItem.setRecommend(0);
}
boolean saved = creditBankruptcyService.save(rowItem);
if (!saved) {
CreditBankruptcy existing = creditBankruptcyService.lambdaQuery()
.eq(CreditBankruptcy::getCode, rowItem.getCode())
.select(CreditBankruptcy::getId, CreditBankruptcy::getRecommend)
.one();
if (existing != null) {
rowItem.setId(existing.getId());
Integer old = existing.getRecommend();
rowItem.setRecommend(old == null ? 1 : old + 1);
if (creditBankruptcyService.updateById(rowItem)) {
return true;
}
}
} else {
return true;
}
String prefix = rowNumber > 0 ? ("" + rowNumber + "行:") : "";
errorMessages.add(prefix + "保存失败");
return false;
},
errorMessages
);
chunkItems.clear();
chunkRowNumbers.clear();
}
}
if (!chunkItems.isEmpty()) {
successCount += batchImportSupport.persistChunkWithFallback(
chunkItems,
chunkRowNumbers,
() -> batchImportSupport.upsertBySingleKeyAndIncrementCounterOnUpdate(
creditBankruptcyService,
chunkItems,
CreditBankruptcy::getId,
CreditBankruptcy::setId,
CreditBankruptcy::getCode,
CreditBankruptcy::getCode,
CreditBankruptcy::getRecommend,
CreditBankruptcy::setRecommend,
null,
mpBatchSize
),
(rowItem, rowNumber) -> {
if (rowItem.getRecommend() == null) {
rowItem.setRecommend(0);
}
boolean saved = creditBankruptcyService.save(rowItem);
if (!saved) {
CreditBankruptcy existing = creditBankruptcyService.lambdaQuery()
.eq(CreditBankruptcy::getCode, rowItem.getCode())
.select(CreditBankruptcy::getId, CreditBankruptcy::getRecommend)
.one();
if (existing != null) {
rowItem.setId(existing.getId());
Integer old = existing.getRecommend();
rowItem.setRecommend(old == null ? 1 : old + 1);
if (creditBankruptcyService.updateById(rowItem)) {
return true;
}
}
} else {
return true;
}
String prefix = rowNumber > 0 ? ("" + rowNumber + "行:") : "";
errorMessages.add(prefix + "保存失败");
return false;
},
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);
}
}
/** /**
* 下载破产重整导入模板 * 下载破产重整导入模板
*/ */

View File

@@ -9,6 +9,8 @@ import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.credit.entity.CreditBranch; import com.gxwebsoft.credit.entity.CreditBranch;
import com.gxwebsoft.credit.param.CreditBranchImportParam; import com.gxwebsoft.credit.param.CreditBranchImportParam;
import com.gxwebsoft.credit.param.CreditBranchParam; 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 com.gxwebsoft.credit.service.CreditBranchService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@@ -22,8 +24,10 @@ import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
/** /**
* 分支机构控制器 * 分支机构控制器
@@ -41,6 +45,12 @@ public class CreditBranchController extends BaseController {
@Resource @Resource
private BatchImportSupport batchImportSupport; private BatchImportSupport batchImportSupport;
@Resource
private CreditCompanyService creditCompanyService;
@Resource
private CreditCompanyRecordCountService creditCompanyRecordCountService;
@Operation(summary = "分页查询分支机构") @Operation(summary = "分页查询分支机构")
@GetMapping("/page") @GetMapping("/page")
public ApiResult<PageResult<CreditBranch>> page(CreditBranchParam param) { public ApiResult<PageResult<CreditBranch>> page(CreditBranchParam param) {
@@ -133,6 +143,45 @@ public class CreditBranchController extends BaseController {
return fail("删除失败"); 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::getHasData,
CreditBranch::setHasData,
CreditBranch::getTenantId,
CreditBranch::new
);
if (!stats.anyDataRead) {
return success("无可更新数据", stats.toMap());
}
return success("更新完成,更新" + stats.updated + "", stats.toMap());
}
/** /**
* 批量导入分支机构 * 批量导入分支机构
*/ */
@@ -143,6 +192,7 @@ public class CreditBranchController extends BaseController {
@RequestParam(value = "companyId", required = false) Integer companyId) { @RequestParam(value = "companyId", required = false) Integer companyId) {
List<String> errorMessages = new ArrayList<>(); List<String> errorMessages = new ArrayList<>();
int successCount = 0; int successCount = 0;
Set<Integer> touchedCompanyIds = new HashSet<>();
try { try {
ExcelImportSupport.ImportResult<CreditBranchImportParam> importResult = ExcelImportSupport.readAnySheet( ExcelImportSupport.ImportResult<CreditBranchImportParam> importResult = ExcelImportSupport.readAnySheet(
@@ -202,6 +252,10 @@ public class CreditBranchController extends BaseController {
continue; continue;
} }
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
touchedCompanyIds.add(item.getCompanyId());
}
chunkItems.add(item); chunkItems.add(item);
chunkRowNumbers.add(excelRowNumber); chunkRowNumbers.add(excelRowNumber);
if (chunkItems.size() >= chunkSize) { if (chunkItems.size() >= chunkSize) {
@@ -286,6 +340,8 @@ public class CreditBranchController extends BaseController {
); );
} }
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.BRANCH, touchedCompanyIds);
if (errorMessages.isEmpty()) { if (errorMessages.isEmpty()) {
return success("成功导入" + successCount + "条数据", null); return success("成功导入" + successCount + "条数据", null);
} else { } else {

View File

@@ -7,8 +7,10 @@ import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.common.core.web.PageResult; import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.system.entity.User; import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.credit.entity.CreditBreachOfTrust; import com.gxwebsoft.credit.entity.CreditBreachOfTrust;
import com.gxwebsoft.credit.param.CreditJudicialImportParam; import com.gxwebsoft.credit.param.CreditBreachOfTrustImportParam;
import com.gxwebsoft.credit.param.CreditBreachOfTrustParam; 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 com.gxwebsoft.credit.service.CreditBreachOfTrustService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@@ -23,7 +25,11 @@ import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set;
/** /**
* 失信被执行人控制器 * 失信被执行人控制器
@@ -41,6 +47,12 @@ public class CreditBreachOfTrustController extends BaseController {
@Resource @Resource
private BatchImportSupport batchImportSupport; private BatchImportSupport batchImportSupport;
@Resource
private CreditCompanyService creditCompanyService;
@Resource
private CreditCompanyRecordCountService creditCompanyRecordCountService;
@Operation(summary = "分页查询失信被执行人") @Operation(summary = "分页查询失信被执行人")
@GetMapping("/page") @GetMapping("/page")
public ApiResult<PageResult<CreditBreachOfTrust>> page(CreditBreachOfTrustParam param) { public ApiResult<PageResult<CreditBreachOfTrust>> page(CreditBreachOfTrustParam param) {
@@ -128,6 +140,45 @@ public class CreditBreachOfTrustController extends BaseController {
return fail("删除失败"); 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;
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
creditBreachOfTrustService,
creditCompanyService,
currentTenantId,
onlyNull,
limit,
CreditBreachOfTrust::getId,
CreditBreachOfTrust::setId,
CreditBreachOfTrust::getPlaintiffAppellant,
CreditBreachOfTrust::getCompanyId,
CreditBreachOfTrust::setCompanyId,
CreditBreachOfTrust::getHasData,
CreditBreachOfTrust::setHasData,
CreditBreachOfTrust::getTenantId,
CreditBreachOfTrust::new
);
if (!stats.anyDataRead) {
return success("无可更新数据", stats.toMap());
}
return success("更新完成,更新" + stats.updated + "", stats.toMap());
}
/** /**
* 批量导入失信被执行人 * 批量导入失信被执行人
*/ */
@@ -138,13 +189,16 @@ public class CreditBreachOfTrustController extends BaseController {
@RequestParam(value = "companyId", required = false) Integer companyId) { @RequestParam(value = "companyId", required = false) Integer companyId) {
List<String> errorMessages = new ArrayList<>(); List<String> errorMessages = new ArrayList<>();
int successCount = 0; int successCount = 0;
Set<Integer> touchedCompanyIds = new HashSet<>();
try { try {
ExcelImportSupport.ImportResult<CreditJudicialImportParam> importResult = ExcelImportSupport.read( int sheetIndex = ExcelImportSupport.findSheetIndex(file, "失信被执行人", 0);
file, CreditJudicialImportParam.class, this::isEmptyImportRow); ExcelImportSupport.ImportResult<CreditBreachOfTrustImportParam> importResult = ExcelImportSupport.read(
List<CreditJudicialImportParam> list = importResult.getData(); file, CreditBreachOfTrustImportParam.class, this::isEmptyImportRow, sheetIndex);
List<CreditBreachOfTrustImportParam> list = importResult.getData();
int usedTitleRows = importResult.getTitleRows(); int usedTitleRows = importResult.getTitleRows();
int usedHeadRows = importResult.getHeadRows(); int usedHeadRows = importResult.getHeadRows();
int usedSheetIndex = importResult.getSheetIndex();
if (CollectionUtils.isEmpty(list)) { if (CollectionUtils.isEmpty(list)) {
return fail("未读取到数据,请确认模板表头与示例格式一致", null); return fail("未读取到数据,请确认模板表头与示例格式一致", null);
@@ -153,6 +207,7 @@ public class CreditBreachOfTrustController extends BaseController {
User loginUser = getLoginUser(); User loginUser = getLoginUser();
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null; Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null; Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
final int chunkSize = 500; final int chunkSize = 500;
final int mpBatchSize = 500; final int mpBatchSize = 500;
@@ -160,13 +215,22 @@ public class CreditBreachOfTrustController extends BaseController {
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize); List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
for (int i = 0; i < list.size(); i++) { for (int i = 0; i < list.size(); i++) {
CreditJudicialImportParam param = list.get(i); CreditBreachOfTrustImportParam param = list.get(i);
try { try {
CreditBreachOfTrust item = convertImportParamToEntity(param); 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) { if (item.getCompanyId() == null && companyId != null) {
item.setCompanyId(companyId); item.setCompanyId(companyId);
} }
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
touchedCompanyIds.add(item.getCompanyId());
}
if (item.getUserId() == null && currentUserId != null) { if (item.getUserId() == null && currentUserId != null) {
item.setUserId(currentUserId); item.setUserId(currentUserId);
} }
@@ -189,6 +253,10 @@ public class CreditBreachOfTrustController extends BaseController {
continue; continue;
} }
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
touchedCompanyIds.add(item.getCompanyId());
}
chunkItems.add(item); chunkItems.add(item);
chunkRowNumbers.add(excelRowNumber); chunkRowNumbers.add(excelRowNumber);
if (chunkItems.size() >= chunkSize) { if (chunkItems.size() >= chunkSize) {
@@ -273,6 +341,8 @@ public class CreditBreachOfTrustController extends BaseController {
); );
} }
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.BREACH_OF_TRUST, touchedCompanyIds);
if (errorMessages.isEmpty()) { if (errorMessages.isEmpty()) {
return success("成功导入" + successCount + "条数据", null); return success("成功导入" + successCount + "条数据", null);
} else { } else {
@@ -284,29 +354,229 @@ public class CreditBreachOfTrustController extends BaseController {
} }
} }
/**
* 批量导入历史失信被执行人(仅解析“历史失信被执行人”选项卡)
* 规则案号相同则覆盖更新recommend++ 记录更新次数);案号不存在则插入。
*/
@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, "案号");
// 同案号多条:以导入文件中“最后一条”为准(视为最新)
LinkedHashMap<String, CreditBreachOfTrust> latestByCaseNumber = new LinkedHashMap<>();
LinkedHashMap<String, Integer> latestRowByCaseNumber = new LinkedHashMap<>();
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);
}
latestByCaseNumber.put(item.getCaseNumber(), item);
latestRowByCaseNumber.put(item.getCaseNumber(), excelRowNumber);
} catch (Exception e) {
errorMessages.add("" + excelRowNumber + "行:" + e.getMessage());
e.printStackTrace();
}
}
if (latestByCaseNumber.isEmpty()) {
if (errorMessages.isEmpty()) {
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
}
return success("导入完成成功0条失败" + errorMessages.size() + "", errorMessages);
}
final int chunkSize = 500;
final int mpBatchSize = 500;
List<CreditBreachOfTrust> chunkItems = new ArrayList<>(chunkSize);
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
for (Map.Entry<String, CreditBreachOfTrust> entry : latestByCaseNumber.entrySet()) {
String caseNumber = entry.getKey();
CreditBreachOfTrust item = entry.getValue();
Integer rowNo = latestRowByCaseNumber.get(caseNumber);
chunkItems.add(item);
chunkRowNumbers.add(rowNo != null ? rowNo : -1);
if (chunkItems.size() >= chunkSize) {
successCount += batchImportSupport.persistChunkWithFallback(
chunkItems,
chunkRowNumbers,
() -> batchImportSupport.upsertBySingleKeyAndIncrementCounterOnUpdate(
creditBreachOfTrustService,
chunkItems,
CreditBreachOfTrust::getId,
CreditBreachOfTrust::setId,
CreditBreachOfTrust::getCaseNumber,
CreditBreachOfTrust::getCaseNumber,
CreditBreachOfTrust::getRecommend,
CreditBreachOfTrust::setRecommend,
null,
mpBatchSize
),
(rowItem, rowNumber) -> {
if (rowItem.getRecommend() == null) {
rowItem.setRecommend(0);
}
boolean saved = creditBreachOfTrustService.save(rowItem);
if (!saved) {
CreditBreachOfTrust existing = creditBreachOfTrustService.lambdaQuery()
.eq(CreditBreachOfTrust::getCaseNumber, rowItem.getCaseNumber())
.select(CreditBreachOfTrust::getId, CreditBreachOfTrust::getRecommend)
.one();
if (existing != null) {
rowItem.setId(existing.getId());
Integer old = existing.getRecommend();
rowItem.setRecommend(old == null ? 1 : old + 1);
if (creditBreachOfTrustService.updateById(rowItem)) {
return true;
}
}
} else {
return true;
}
String prefix = rowNumber > 0 ? ("" + rowNumber + "行:") : "";
errorMessages.add(prefix + "保存失败");
return false;
},
errorMessages
);
chunkItems.clear();
chunkRowNumbers.clear();
}
}
if (!chunkItems.isEmpty()) {
successCount += batchImportSupport.persistChunkWithFallback(
chunkItems,
chunkRowNumbers,
() -> batchImportSupport.upsertBySingleKeyAndIncrementCounterOnUpdate(
creditBreachOfTrustService,
chunkItems,
CreditBreachOfTrust::getId,
CreditBreachOfTrust::setId,
CreditBreachOfTrust::getCaseNumber,
CreditBreachOfTrust::getCaseNumber,
CreditBreachOfTrust::getRecommend,
CreditBreachOfTrust::setRecommend,
null,
mpBatchSize
),
(rowItem, rowNumber) -> {
if (rowItem.getRecommend() == null) {
rowItem.setRecommend(0);
}
boolean saved = creditBreachOfTrustService.save(rowItem);
if (!saved) {
CreditBreachOfTrust existing = creditBreachOfTrustService.lambdaQuery()
.eq(CreditBreachOfTrust::getCaseNumber, rowItem.getCaseNumber())
.select(CreditBreachOfTrust::getId, CreditBreachOfTrust::getRecommend)
.one();
if (existing != null) {
rowItem.setId(existing.getId());
Integer old = existing.getRecommend();
rowItem.setRecommend(old == null ? 1 : old + 1);
if (creditBreachOfTrustService.updateById(rowItem)) {
return true;
}
}
} else {
return true;
}
String prefix = rowNumber > 0 ? ("" + rowNumber + "行:") : "";
errorMessages.add(prefix + "保存失败");
return false;
},
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 = "下载失信被执行人导入模板") @Operation(summary = "下载失信被执行人导入模板")
@GetMapping("/import/template") @GetMapping("/import/template")
public void downloadTemplate(HttpServletResponse response) throws IOException { public void downloadTemplate(HttpServletResponse response) throws IOException {
List<CreditJudicialImportParam> templateList = new ArrayList<>(); List<CreditBreachOfTrustImportParam> templateList = new ArrayList<>();
CreditJudicialImportParam example = new CreditJudicialImportParam(); CreditBreachOfTrustImportParam example = new CreditBreachOfTrustImportParam();
example.setDataType("失信被执行人"); example.setCaseNumber("2024示例案号");
example.setPlaintiffAppellant("原告示例"); example.setPlaintiffAppellant("原告示例");
example.setAppellee("被告示例"); example.setAppellee("被告示例");
example.setOtherPartiesThirdParty("第三人示例"); example.setInvolvedAmount("20,293.91");
example.setOccurrenceTime("2024-01-01"); example.setOccurrenceTime("2024-01-01");
example.setCaseNumber("2024示例案号");
example.setCauseOfAction("案由示例");
example.setInvolvedAmount("100000");
example.setCourtName("示例法院"); example.setCourtName("示例法院");
example.setDataStatus("已公开"); example.setReleaseDate("2024-01-01");
example.setComments("备注信息");
templateList.add(example); templateList.add(example);
Workbook workbook = ExcelImportSupport.buildTemplate("失信被执行人导入模板", "失信被执行人", CreditJudicialImportParam.class, templateList); Workbook workbook = ExcelImportSupport.buildTemplate("失信被执行人导入模板", "失信被执行人", CreditBreachOfTrustImportParam.class, templateList);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment; filename=credit_breach_of_trust_import_template.xlsx"); response.setHeader("Content-Disposition", "attachment; filename=credit_breach_of_trust_import_template.xlsx");
@@ -315,29 +585,25 @@ public class CreditBreachOfTrustController extends BaseController {
workbook.close(); workbook.close();
} }
private boolean isEmptyImportRow(CreditJudicialImportParam param) { private boolean isEmptyImportRow(CreditBreachOfTrustImportParam param) {
if (param == null) { if (param == null) {
return true; return true;
} }
return ImportHelper.isBlank(param.getCaseNumber()) return ImportHelper.isBlank(param.getCaseNumber())
&& ImportHelper.isBlank(param.getPlaintiffAppellant()) && ImportHelper.isBlank(param.getPlaintiffAppellant())
&& ImportHelper.isBlank(param.getAppellee()) && ImportHelper.isBlank(param.getAppellee());
&& ImportHelper.isBlank(param.getCauseOfAction());
} }
private CreditBreachOfTrust convertImportParamToEntity(CreditJudicialImportParam param) { private CreditBreachOfTrust convertImportParamToEntity(CreditBreachOfTrustImportParam param) {
CreditBreachOfTrust entity = new CreditBreachOfTrust(); CreditBreachOfTrust entity = new CreditBreachOfTrust();
entity.setDataType(param.getDataType()); entity.setCaseNumber(param.getCaseNumber());
entity.setPlaintiffAppellant(param.getPlaintiffAppellant()); entity.setPlaintiffAppellant(param.getPlaintiffAppellant());
entity.setAppellee(param.getAppellee()); entity.setAppellee(param.getAppellee());
entity.setOtherPartiesThirdParty(param.getOtherPartiesThirdParty());
entity.setOccurrenceTime(param.getOccurrenceTime());
entity.setCaseNumber(param.getCaseNumber());
entity.setCauseOfAction(param.getCauseOfAction());
entity.setInvolvedAmount(param.getInvolvedAmount()); entity.setInvolvedAmount(param.getInvolvedAmount());
entity.setOccurrenceTime(param.getOccurrenceTime());
entity.setCourtName(param.getCourtName()); entity.setCourtName(param.getCourtName());
entity.setDataStatus(param.getDataStatus()); entity.setReleaseDate(param.getReleaseDate());
entity.setComments(param.getComments()); entity.setComments(param.getComments());
return entity; return entity;

View File

@@ -7,8 +7,10 @@ import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.common.core.web.PageResult; import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.system.entity.User; import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.credit.entity.CreditCaseFiling; import com.gxwebsoft.credit.entity.CreditCaseFiling;
import com.gxwebsoft.credit.param.CreditJudicialImportParam; import com.gxwebsoft.credit.param.CreditCaseFilingImportParam;
import com.gxwebsoft.credit.param.CreditCaseFilingParam; 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 com.gxwebsoft.credit.service.CreditCaseFilingService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@@ -22,7 +24,10 @@ import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set;
/** /**
* 司法大数据控制器 * 司法大数据控制器
@@ -40,6 +45,12 @@ public class CreditCaseFilingController extends BaseController {
@Resource @Resource
private BatchImportSupport batchImportSupport; private BatchImportSupport batchImportSupport;
@Resource
private CreditCompanyService creditCompanyService;
@Resource
private CreditCompanyRecordCountService creditCompanyRecordCountService;
@Operation(summary = "分页查询司法大数据") @Operation(summary = "分页查询司法大数据")
@GetMapping("/page") @GetMapping("/page")
public ApiResult<PageResult<CreditCaseFiling>> page(CreditCaseFilingParam param) { public ApiResult<PageResult<CreditCaseFiling>> page(CreditCaseFilingParam param) {
@@ -133,22 +144,64 @@ public class CreditCaseFilingController extends BaseController {
} }
/** /**
* 批量导入司法大数据 * 根据企业名称匹配企业并更新 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;
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
creditCaseFilingService,
creditCompanyService,
currentTenantId,
onlyNull,
limit,
CreditCaseFiling::getId,
CreditCaseFiling::setId,
CreditCaseFiling::getAppellee,
CreditCaseFiling::getCompanyId,
CreditCaseFiling::setCompanyId,
CreditCaseFiling::getHasData,
CreditCaseFiling::setHasData,
CreditCaseFiling::getTenantId,
CreditCaseFiling::new
);
if (!stats.anyDataRead) {
return success("无可更新数据", stats.toMap());
}
return success("更新完成,更新" + stats.updated + "", stats.toMap());
}
/**
* 批量导入立案信息
*/ */
@PreAuthorize("hasAuthority('credit:creditCaseFiling:save')") @PreAuthorize("hasAuthority('credit:creditCaseFiling:save')")
@Operation(summary = "批量导入司法大数据") @Operation(summary = "批量导入立案信息")
@PostMapping("/import") @PostMapping("/import")
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file, public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
@RequestParam(value = "companyId", required = false) Integer companyId) { @RequestParam(value = "companyId", required = false) Integer companyId) {
List<String> errorMessages = new ArrayList<>(); List<String> errorMessages = new ArrayList<>();
int successCount = 0; int successCount = 0;
Set<Integer> touchedCompanyIds = new HashSet<>();
try { try {
ExcelImportSupport.ImportResult<CreditJudicialImportParam> importResult = ExcelImportSupport.read( int sheetIndex = ExcelImportSupport.findSheetIndex(file, "立案信息", 0);
file, CreditJudicialImportParam.class, this::isEmptyImportRow); ExcelImportSupport.ImportResult<CreditCaseFilingImportParam> importResult = ExcelImportSupport.read(
List<CreditJudicialImportParam> list = importResult.getData(); file, CreditCaseFilingImportParam.class, this::isEmptyImportRow, sheetIndex);
List<CreditCaseFilingImportParam> list = importResult.getData();
int usedTitleRows = importResult.getTitleRows(); int usedTitleRows = importResult.getTitleRows();
int usedHeadRows = importResult.getHeadRows(); int usedHeadRows = importResult.getHeadRows();
int usedSheetIndex = importResult.getSheetIndex();
if (CollectionUtils.isEmpty(list)) { if (CollectionUtils.isEmpty(list)) {
return fail("未读取到数据,请确认模板表头与示例格式一致", null); return fail("未读取到数据,请确认模板表头与示例格式一致", null);
@@ -157,6 +210,8 @@ public class CreditCaseFilingController extends BaseController {
User loginUser = getLoginUser(); User loginUser = getLoginUser();
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null; Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : 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 chunkSize = 500;
final int mpBatchSize = 500; final int mpBatchSize = 500;
@@ -164,9 +219,15 @@ public class CreditCaseFilingController extends BaseController {
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize); List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
for (int i = 0; i < list.size(); i++) { for (int i = 0; i < list.size(); i++) {
CreditJudicialImportParam param = list.get(i); CreditCaseFilingImportParam param = list.get(i);
try { try {
CreditCaseFiling item = convertImportParamToEntity(param); 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) { if (item.getCompanyId() == null && companyId != null) {
item.setCompanyId(companyId); item.setCompanyId(companyId);
@@ -193,6 +254,10 @@ public class CreditCaseFilingController extends BaseController {
continue; continue;
} }
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
touchedCompanyIds.add(item.getCompanyId());
}
chunkItems.add(item); chunkItems.add(item);
chunkRowNumbers.add(excelRowNumber); chunkRowNumbers.add(excelRowNumber);
if (chunkItems.size() >= chunkSize) { if (chunkItems.size() >= chunkSize) {
@@ -277,6 +342,8 @@ public class CreditCaseFilingController extends BaseController {
); );
} }
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.CASE_FILING, touchedCompanyIds);
if (errorMessages.isEmpty()) { if (errorMessages.isEmpty()) {
return success("成功导入" + successCount + "条数据", null); return success("成功导入" + successCount + "条数据", null);
} else { } else {
@@ -289,28 +356,23 @@ public class CreditCaseFilingController extends BaseController {
} }
/** /**
* 下载司法大数据导入模板 * 下载立案信息导入模板
*/ */
@Operation(summary = "下载司法大数据导入模板") @Operation(summary = "下载立案信息导入模板")
@GetMapping("/import/template") @GetMapping("/import/template")
public void downloadTemplate(HttpServletResponse response) throws IOException { public void downloadTemplate(HttpServletResponse response) throws IOException {
List<CreditJudicialImportParam> templateList = new ArrayList<>(); List<CreditCaseFilingImportParam> templateList = new ArrayList<>();
CreditJudicialImportParam example = new CreditJudicialImportParam(); CreditCaseFilingImportParam example = new CreditCaseFilingImportParam();
example.setDataType("司法大数据");
example.setPlaintiffAppellant("原告示例");
example.setAppellee("被告示例");
example.setOtherPartiesThirdParty("第三人示例");
example.setOccurrenceTime("2024-01-01");
example.setCaseNumber("2024示例案号"); example.setCaseNumber("2024示例案号");
example.setCauseOfAction("案由示例"); example.setCauseOfAction("案由示例");
example.setInvolvedAmount("100000"); example.setOtherPartiesThirdParty("当事人示例");
example.setCourtName("示例法院"); example.setCourtName("示例法院");
example.setDataStatus("已公开"); example.setOccurrenceTime("2024-01-01");
example.setComments("备注信息"); example.setComments("备注信息");
templateList.add(example); templateList.add(example);
Workbook workbook = ExcelImportSupport.buildTemplate("司法大数据导入模板", "司法大数据", CreditJudicialImportParam.class, templateList); Workbook workbook = ExcelImportSupport.buildTemplate("立案信息导入模板", "立案信息", CreditCaseFilingImportParam.class, templateList);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment; filename=credit_case_filing_import_template.xlsx"); response.setHeader("Content-Disposition", "attachment; filename=credit_case_filing_import_template.xlsx");
@@ -319,29 +381,26 @@ public class CreditCaseFilingController extends BaseController {
workbook.close(); workbook.close();
} }
private boolean isEmptyImportRow(CreditJudicialImportParam param) { private boolean isEmptyImportRow(CreditCaseFilingImportParam param) {
if (param == null) { if (param == null) {
return true; return true;
} }
return ImportHelper.isBlank(param.getCaseNumber()) return ImportHelper.isBlank(param.getCaseNumber())
&& ImportHelper.isBlank(param.getPlaintiffAppellant()) && ImportHelper.isBlank(param.getCauseOfAction())
&& ImportHelper.isBlank(param.getAppellee()) && ImportHelper.isBlank(param.getOtherPartiesThirdParty())
&& ImportHelper.isBlank(param.getCauseOfAction()); && ImportHelper.isBlank(param.getCourtName())
&& ImportHelper.isBlank(param.getOccurrenceTime())
&& ImportHelper.isBlank(param.getComments());
} }
private CreditCaseFiling convertImportParamToEntity(CreditJudicialImportParam param) { private CreditCaseFiling convertImportParamToEntity(CreditCaseFilingImportParam param) {
CreditCaseFiling entity = new CreditCaseFiling(); CreditCaseFiling entity = new CreditCaseFiling();
entity.setDataType(param.getDataType());
entity.setPlaintiffAppellant(param.getPlaintiffAppellant());
entity.setAppellee(param.getAppellee());
entity.setOtherPartiesThirdParty(param.getOtherPartiesThirdParty());
entity.setOccurrenceTime(param.getOccurrenceTime());
entity.setCaseNumber(param.getCaseNumber()); entity.setCaseNumber(param.getCaseNumber());
entity.setCauseOfAction(param.getCauseOfAction()); entity.setCauseOfAction(param.getCauseOfAction());
entity.setInvolvedAmount(param.getInvolvedAmount()); entity.setOtherPartiesThirdParty(param.getOtherPartiesThirdParty());
entity.setCourtName(param.getCourtName()); entity.setCourtName(param.getCourtName());
entity.setDataStatus(param.getDataStatus()); entity.setOccurrenceTime(param.getOccurrenceTime());
entity.setComments(param.getComments()); entity.setComments(param.getComments());
return entity; return entity;

View File

@@ -14,6 +14,7 @@ import com.gxwebsoft.credit.entity.CreditCompany;
import com.gxwebsoft.credit.param.CreditCompanyImportParam; import com.gxwebsoft.credit.param.CreditCompanyImportParam;
import com.gxwebsoft.credit.param.CreditCompanyParam; import com.gxwebsoft.credit.param.CreditCompanyParam;
import com.gxwebsoft.credit.service.CreditCompanyService; 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.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.Workbook;
@@ -26,8 +27,10 @@ import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
/** /**
* 企业控制器 * 企业控制器
@@ -45,6 +48,9 @@ public class CreditCompanyController extends BaseController {
@Resource @Resource
private BatchImportSupport batchImportSupport; private BatchImportSupport batchImportSupport;
@Resource
private CreditCompanyRecordCountService creditCompanyRecordCountService;
@Operation(summary = "分页查询企业") @Operation(summary = "分页查询企业")
@GetMapping("/page") @GetMapping("/page")
public ApiResult<PageResult<CreditCompany>> page(CreditCompanyParam param) { public ApiResult<PageResult<CreditCompany>> page(CreditCompanyParam param) {
@@ -141,7 +147,8 @@ public class CreditCompanyController extends BaseController {
public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file, public ApiResult<List<String>> importBatch(@RequestParam("file") MultipartFile file,
@RequestParam(value = "companyId", required = false) Integer companyId) { @RequestParam(value = "companyId", required = false) Integer companyId) {
List<String> errorMessages = new ArrayList<>(); List<String> errorMessages = new ArrayList<>();
int successCount = 0; int insertedCount = 0;
Set<String> touchedMatchNames = new HashSet<>();
try { try {
List<CreditCompanyImportParam> list = null; List<CreditCompanyImportParam> list = null;
@@ -214,37 +221,41 @@ public class CreditCompanyController extends BaseController {
// continue; // continue;
// } // }
touchedMatchNames.add(item.getMatchName().trim());
chunkItems.add(item); chunkItems.add(item);
chunkRowNumbers.add(excelRowNumber); chunkRowNumbers.add(excelRowNumber);
if (chunkItems.size() >= chunkSize) { if (chunkItems.size() >= chunkSize) {
successCount += batchImportSupport.persistChunkWithFallback( insertedCount += batchImportSupport.persistChunkWithFallbackCount(
chunkItems, chunkItems,
chunkRowNumbers, chunkRowNumbers,
() -> batchImportSupport.upsertBySingleKey( () -> {
creditCompanyService, int delta = countInsertedByMatchName(chunkItems);
chunkItems, batchImportSupport.upsertBySingleKey(
CreditCompany::getId, creditCompanyService,
CreditCompany::setId, chunkItems,
CreditCompany::getMatchName, CreditCompany::getId,
CreditCompany::getMatchName, CreditCompany::setId,
null, CreditCompany::getMatchName,
mpBatchSize CreditCompany::getMatchName,
), null,
mpBatchSize
);
return delta;
},
(rowItem, rowNumber) -> { (rowItem, rowNumber) -> {
boolean saved = creditCompanyService.save(rowItem); boolean saved = creditCompanyService.save(rowItem);
if (!saved) { if (saved) {
CreditCompany existing = creditCompanyService.getByMatchName(rowItem.getMatchName()); return 1; // insert 入库
if (existing != null) {
rowItem.setId(existing.getId());
if (creditCompanyService.updateById(rowItem)) {
return true;
}
}
} else {
return true;
} }
errorMessages.add("" + rowNumber + "行:保存失败"); CreditCompany existing = creditCompanyService.getByMatchName(rowItem.getMatchName());
return false; if (existing != null) {
rowItem.setId(existing.getId());
if (creditCompanyService.updateById(rowItem)) {
return 0; // update 不计入“入库”条数
}
}
throw new RuntimeException("保存失败");
}, },
errorMessages errorMessages
); );
@@ -259,43 +270,67 @@ public class CreditCompanyController extends BaseController {
} }
if (!chunkItems.isEmpty()) { if (!chunkItems.isEmpty()) {
successCount += batchImportSupport.persistChunkWithFallback( insertedCount += batchImportSupport.persistChunkWithFallbackCount(
chunkItems, chunkItems,
chunkRowNumbers, chunkRowNumbers,
() -> batchImportSupport.upsertBySingleKey( () -> {
creditCompanyService, int delta = countInsertedByMatchName(chunkItems);
chunkItems, batchImportSupport.upsertBySingleKey(
CreditCompany::getId, creditCompanyService,
CreditCompany::setId, chunkItems,
CreditCompany::getMatchName, CreditCompany::getId,
CreditCompany::getMatchName, CreditCompany::setId,
null, CreditCompany::getMatchName,
mpBatchSize CreditCompany::getMatchName,
), null,
mpBatchSize
);
return delta;
},
(rowItem, rowNumber) -> { (rowItem, rowNumber) -> {
boolean saved = creditCompanyService.save(rowItem); boolean saved = creditCompanyService.save(rowItem);
if (!saved) { if (saved) {
CreditCompany existing = creditCompanyService.getByMatchName(rowItem.getMatchName()); return 1; // insert 入库
if (existing != null) {
rowItem.setId(existing.getId());
if (creditCompanyService.updateById(rowItem)) {
return true;
}
}
} else {
return true;
} }
errorMessages.add("" + rowNumber + "行:保存失败"); CreditCompany existing = creditCompanyService.getByMatchName(rowItem.getMatchName());
return false; if (existing != null) {
rowItem.setId(existing.getId());
if (creditCompanyService.updateById(rowItem)) {
return 0; // update 不计入“入库”条数
}
}
throw new RuntimeException("保存失败");
}, },
errorMessages 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());
}
}
}
}
creditCompanyRecordCountService.refreshAll(touchedCompanyIds);
}
if (errorMessages.isEmpty()) { if (errorMessages.isEmpty()) {
return success("成功" + successCount + "条数据", null); return success("成功入" + insertedCount + "条数据", null);
} else { } else {
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "", errorMessages); return success("导入完成,入库" + insertedCount + "条,失败" + errorMessages.size() + "", errorMessages);
} }
} catch (Exception e) { } catch (Exception e) {
@@ -405,6 +440,53 @@ public class CreditCompanyController extends BaseController {
return value == null || value.trim().isEmpty(); 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实体 * 将CreditCompanyImportParam转换为CreditCompany实体
*/ */

View File

@@ -9,6 +9,8 @@ import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.credit.entity.CreditCompetitor; import com.gxwebsoft.credit.entity.CreditCompetitor;
import com.gxwebsoft.credit.param.CreditCompetitorImportParam; import com.gxwebsoft.credit.param.CreditCompetitorImportParam;
import com.gxwebsoft.credit.param.CreditCompetitorParam; 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 com.gxwebsoft.credit.service.CreditCompetitorService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@@ -22,7 +24,10 @@ import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set;
/** /**
* 竞争对手控制器 * 竞争对手控制器
@@ -40,6 +45,12 @@ public class CreditCompetitorController extends BaseController {
@Resource @Resource
private BatchImportSupport batchImportSupport; private BatchImportSupport batchImportSupport;
@Resource
private CreditCompanyService creditCompanyService;
@Resource
private CreditCompanyRecordCountService creditCompanyRecordCountService;
@Operation(summary = "分页查询竞争对手") @Operation(summary = "分页查询竞争对手")
@GetMapping("/page") @GetMapping("/page")
public ApiResult<PageResult<CreditCompetitor>> page(CreditCompetitorParam param) { public ApiResult<PageResult<CreditCompetitor>> page(CreditCompetitorParam param) {
@@ -132,6 +143,45 @@ public class CreditCompetitorController extends BaseController {
return fail("删除失败"); 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::getHasData,
CreditCompetitor::setHasData,
CreditCompetitor::getTenantId,
CreditCompetitor::new
);
if (!stats.anyDataRead) {
return success("无可更新数据", stats.toMap());
}
return success("更新完成,更新" + stats.updated + "", stats.toMap());
}
/** /**
* 批量导入竞争对手 * 批量导入竞争对手
*/ */
@@ -142,6 +192,7 @@ public class CreditCompetitorController extends BaseController {
@RequestParam(value = "companyId", required = false) Integer companyId) { @RequestParam(value = "companyId", required = false) Integer companyId) {
List<String> errorMessages = new ArrayList<>(); List<String> errorMessages = new ArrayList<>();
int successCount = 0; int successCount = 0;
Set<Integer> touchedCompanyIds = new HashSet<>();
try { try {
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "竞争对手", 2); int sheetIndex = ExcelImportSupport.findSheetIndex(file, "竞争对手", 2);
@@ -150,6 +201,7 @@ public class CreditCompetitorController extends BaseController {
List<CreditCompetitorImportParam> list = importResult.getData(); List<CreditCompetitorImportParam> list = importResult.getData();
int usedTitleRows = importResult.getTitleRows(); int usedTitleRows = importResult.getTitleRows();
int usedHeadRows = importResult.getHeadRows(); int usedHeadRows = importResult.getHeadRows();
int usedSheetIndex = importResult.getSheetIndex();
if (CollectionUtils.isEmpty(list)) { if (CollectionUtils.isEmpty(list)) {
return fail("未读取到数据,请确认模板表头与示例格式一致", null); return fail("未读取到数据,请确认模板表头与示例格式一致", null);
@@ -158,6 +210,8 @@ public class CreditCompetitorController extends BaseController {
User loginUser = getLoginUser(); User loginUser = getLoginUser();
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null; Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null; Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
Map<String, String> urlByName = ExcelImportSupport.readUrlByKey(
file, usedSheetIndex, usedTitleRows, usedHeadRows, "企业名称");
final int chunkSize = 500; final int chunkSize = 500;
final int mpBatchSize = 500; final int mpBatchSize = 500;
@@ -168,6 +222,13 @@ public class CreditCompetitorController extends BaseController {
CreditCompetitorImportParam param = list.get(i); CreditCompetitorImportParam param = list.get(i);
try { try {
CreditCompetitor item = convertImportParamToEntity(param); CreditCompetitor item = convertImportParamToEntity(param);
// name 才是持久化字段companyName 为关联查询的临时字段exist=false导入时不应使用。
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) { if (item.getCompanyId() == null && companyId != null) {
item.setCompanyId(companyId); item.setCompanyId(companyId);
@@ -189,11 +250,15 @@ public class CreditCompetitorController extends BaseController {
} }
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows; int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
if (ImportHelper.isBlank(item.getCompanyName())) { if (ImportHelper.isBlank(item.getName())) {
errorMessages.add("" + excelRowNumber + "行:企业名称不能为空"); errorMessages.add("" + excelRowNumber + "行:企业名称不能为空");
continue; continue;
} }
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
touchedCompanyIds.add(item.getCompanyId());
}
chunkItems.add(item); chunkItems.add(item);
chunkRowNumbers.add(excelRowNumber); chunkRowNumbers.add(excelRowNumber);
if (chunkItems.size() >= chunkSize) { if (chunkItems.size() >= chunkSize) {
@@ -205,8 +270,8 @@ public class CreditCompetitorController extends BaseController {
chunkItems, chunkItems,
CreditCompetitor::getId, CreditCompetitor::getId,
CreditCompetitor::setId, CreditCompetitor::setId,
CreditCompetitor::getCompanyName, CreditCompetitor::getName,
CreditCompetitor::getCompanyName, CreditCompetitor::getName,
null, null,
mpBatchSize mpBatchSize
), ),
@@ -214,7 +279,7 @@ public class CreditCompetitorController extends BaseController {
boolean saved = creditCompetitorService.save(rowItem); boolean saved = creditCompetitorService.save(rowItem);
if (!saved) { if (!saved) {
CreditCompetitor existing = creditCompetitorService.lambdaQuery() CreditCompetitor existing = creditCompetitorService.lambdaQuery()
.eq(CreditCompetitor::getCompanyName, rowItem.getCompanyName()) .eq(CreditCompetitor::getName, rowItem.getName())
.one(); .one();
if (existing != null) { if (existing != null) {
rowItem.setId(existing.getId()); rowItem.setId(existing.getId());
@@ -250,8 +315,8 @@ public class CreditCompetitorController extends BaseController {
chunkItems, chunkItems,
CreditCompetitor::getId, CreditCompetitor::getId,
CreditCompetitor::setId, CreditCompetitor::setId,
CreditCompetitor::getCompanyName, CreditCompetitor::getName,
CreditCompetitor::getCompanyName, CreditCompetitor::getName,
null, null,
mpBatchSize mpBatchSize
), ),
@@ -259,7 +324,7 @@ public class CreditCompetitorController extends BaseController {
boolean saved = creditCompetitorService.save(rowItem); boolean saved = creditCompetitorService.save(rowItem);
if (!saved) { if (!saved) {
CreditCompetitor existing = creditCompetitorService.lambdaQuery() CreditCompetitor existing = creditCompetitorService.lambdaQuery()
.eq(CreditCompetitor::getCompanyName, rowItem.getCompanyName()) .eq(CreditCompetitor::getName, rowItem.getName())
.one(); .one();
if (existing != null) { if (existing != null) {
rowItem.setId(existing.getId()); rowItem.setId(existing.getId());
@@ -278,6 +343,8 @@ public class CreditCompetitorController extends BaseController {
); );
} }
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.COMPETITOR, touchedCompanyIds);
if (errorMessages.isEmpty()) { if (errorMessages.isEmpty()) {
return success("成功导入" + successCount + "条数据", null); return success("成功导入" + successCount + "条数据", null);
} else { } else {
@@ -298,7 +365,7 @@ public class CreditCompetitorController extends BaseController {
List<CreditCompetitorImportParam> templateList = new ArrayList<>(); List<CreditCompetitorImportParam> templateList = new ArrayList<>();
CreditCompetitorImportParam example = new CreditCompetitorImportParam(); CreditCompetitorImportParam example = new CreditCompetitorImportParam();
example.setCompanyName("示例科技有限公司"); example.setName("示例科技有限公司");
example.setLegalRepresentative("张三"); example.setLegalRepresentative("张三");
example.setRegisteredCapital("5000"); example.setRegisteredCapital("5000");
example.setEstablishmentDate("2015-01-01"); example.setEstablishmentDate("2015-01-01");
@@ -321,7 +388,7 @@ public class CreditCompetitorController extends BaseController {
if (param == null) { if (param == null) {
return true; return true;
} }
return ImportHelper.isBlank(param.getCompanyName()) return ImportHelper.isBlank(param.getName())
&& ImportHelper.isBlank(param.getLegalRepresentative()) && ImportHelper.isBlank(param.getLegalRepresentative())
&& ImportHelper.isBlank(param.getRegisteredCapital()) && ImportHelper.isBlank(param.getRegisteredCapital())
&& ImportHelper.isBlank(param.getEstablishmentDate()); && ImportHelper.isBlank(param.getEstablishmentDate());
@@ -330,7 +397,7 @@ public class CreditCompetitorController extends BaseController {
private CreditCompetitor convertImportParamToEntity(CreditCompetitorImportParam param) { private CreditCompetitor convertImportParamToEntity(CreditCompetitorImportParam param) {
CreditCompetitor entity = new CreditCompetitor(); CreditCompetitor entity = new CreditCompetitor();
entity.setCompanyName(param.getCompanyName()); entity.setName(param.getName());
entity.setLegalRepresentative(param.getLegalRepresentative()); entity.setLegalRepresentative(param.getLegalRepresentative());
entity.setRegisteredCapital(param.getRegisteredCapital()); entity.setRegisteredCapital(param.getRegisteredCapital());
entity.setEstablishmentDate(param.getEstablishmentDate()); entity.setEstablishmentDate(param.getEstablishmentDate());

View File

@@ -7,8 +7,10 @@ import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.common.core.web.PageResult; import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.system.entity.User; import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.credit.entity.CreditCourtAnnouncement; import com.gxwebsoft.credit.entity.CreditCourtAnnouncement;
import com.gxwebsoft.credit.param.CreditJudicialImportParam; import com.gxwebsoft.credit.param.CreditCourtAnnouncementImportParam;
import com.gxwebsoft.credit.param.CreditCourtAnnouncementParam; 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 com.gxwebsoft.credit.service.CreditCourtAnnouncementService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@@ -22,7 +24,10 @@ import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set;
/** /**
* 法院公告司法大数据控制器 * 法院公告司法大数据控制器
@@ -40,6 +45,12 @@ public class CreditCourtAnnouncementController extends BaseController {
@Resource @Resource
private BatchImportSupport batchImportSupport; private BatchImportSupport batchImportSupport;
@Resource
private CreditCompanyService creditCompanyService;
@Resource
private CreditCompanyRecordCountService creditCompanyRecordCountService;
@Operation(summary = "分页查询法院公告司法大数据") @Operation(summary = "分页查询法院公告司法大数据")
@GetMapping("/page") @GetMapping("/page")
public ApiResult<PageResult<CreditCourtAnnouncement>> page(CreditCourtAnnouncementParam param) { public ApiResult<PageResult<CreditCourtAnnouncement>> page(CreditCourtAnnouncementParam param) {
@@ -132,6 +143,45 @@ public class CreditCourtAnnouncementController extends BaseController {
return fail("删除失败"); 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;
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
creditCourtAnnouncementService,
creditCompanyService,
currentTenantId,
onlyNull,
limit,
CreditCourtAnnouncement::getId,
CreditCourtAnnouncement::setId,
CreditCourtAnnouncement::getAppellee,
CreditCourtAnnouncement::getCompanyId,
CreditCourtAnnouncement::setCompanyId,
CreditCourtAnnouncement::getHasData,
CreditCourtAnnouncement::setHasData,
CreditCourtAnnouncement::getTenantId,
CreditCourtAnnouncement::new
);
if (!stats.anyDataRead) {
return success("无可更新数据", stats.toMap());
}
return success("更新完成,更新" + stats.updated + "", stats.toMap());
}
/** /**
* 批量导入法院公告司法大数据 * 批量导入法院公告司法大数据
*/ */
@@ -142,13 +192,17 @@ public class CreditCourtAnnouncementController extends BaseController {
@RequestParam(value = "companyId", required = false) Integer companyId) { @RequestParam(value = "companyId", required = false) Integer companyId) {
List<String> errorMessages = new ArrayList<>(); List<String> errorMessages = new ArrayList<>();
int successCount = 0; int successCount = 0;
Set<Integer> touchedCompanyIds = new HashSet<>();
try { try {
ExcelImportSupport.ImportResult<CreditJudicialImportParam> importResult = ExcelImportSupport.read( // 兼容多 sheet 文件优先定位“法院公告”sheet否则默认第 0 个。
file, CreditJudicialImportParam.class, this::isEmptyImportRow); int sheetIndex = ExcelImportSupport.findSheetIndex(file, "法院公告", 0);
List<CreditJudicialImportParam> list = importResult.getData(); ExcelImportSupport.ImportResult<CreditCourtAnnouncementImportParam> importResult = ExcelImportSupport.read(
file, CreditCourtAnnouncementImportParam.class, this::isEmptyImportRow, sheetIndex);
List<CreditCourtAnnouncementImportParam> list = importResult.getData();
int usedTitleRows = importResult.getTitleRows(); int usedTitleRows = importResult.getTitleRows();
int usedHeadRows = importResult.getHeadRows(); int usedHeadRows = importResult.getHeadRows();
int usedSheetIndex = importResult.getSheetIndex();
if (CollectionUtils.isEmpty(list)) { if (CollectionUtils.isEmpty(list)) {
return fail("未读取到数据,请确认模板表头与示例格式一致", null); return fail("未读取到数据,请确认模板表头与示例格式一致", null);
@@ -157,6 +211,7 @@ public class CreditCourtAnnouncementController extends BaseController {
User loginUser = getLoginUser(); User loginUser = getLoginUser();
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null; Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null; Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
final int chunkSize = 500; final int chunkSize = 500;
final int mpBatchSize = 500; final int mpBatchSize = 500;
@@ -164,9 +219,15 @@ public class CreditCourtAnnouncementController extends BaseController {
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize); List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
for (int i = 0; i < list.size(); i++) { for (int i = 0; i < list.size(); i++) {
CreditJudicialImportParam param = list.get(i); CreditCourtAnnouncementImportParam param = list.get(i);
try { try {
CreditCourtAnnouncement item = convertImportParamToEntity(param); 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) { if (item.getCompanyId() == null && companyId != null) {
item.setCompanyId(companyId); item.setCompanyId(companyId);
@@ -193,6 +254,10 @@ public class CreditCourtAnnouncementController extends BaseController {
continue; continue;
} }
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
touchedCompanyIds.add(item.getCompanyId());
}
chunkItems.add(item); chunkItems.add(item);
chunkRowNumbers.add(excelRowNumber); chunkRowNumbers.add(excelRowNumber);
if (chunkItems.size() >= chunkSize) { if (chunkItems.size() >= chunkSize) {
@@ -277,6 +342,8 @@ public class CreditCourtAnnouncementController extends BaseController {
); );
} }
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.COURT_ANNOUNCEMENT, touchedCompanyIds);
if (errorMessages.isEmpty()) { if (errorMessages.isEmpty()) {
return success("成功导入" + successCount + "条数据", null); return success("成功导入" + successCount + "条数据", null);
} else { } else {
@@ -294,23 +361,19 @@ public class CreditCourtAnnouncementController extends BaseController {
@Operation(summary = "下载法院公告司法大数据导入模板") @Operation(summary = "下载法院公告司法大数据导入模板")
@GetMapping("/import/template") @GetMapping("/import/template")
public void downloadTemplate(HttpServletResponse response) throws IOException { public void downloadTemplate(HttpServletResponse response) throws IOException {
List<CreditJudicialImportParam> templateList = new ArrayList<>(); List<CreditCourtAnnouncementImportParam> templateList = new ArrayList<>();
CreditJudicialImportParam example = new CreditJudicialImportParam(); CreditCourtAnnouncementImportParam example = new CreditCourtAnnouncementImportParam();
example.setDataType("法院公告"); example.setDataType("法院公告");
example.setPlaintiffAppellant("原告示例"); example.setPlaintiffAppellant("原告示例");
example.setAppellee("被告示例");
example.setOtherPartiesThirdParty("第三人示例"); example.setOtherPartiesThirdParty("第三人示例");
example.setOccurrenceTime("2024-01-01"); example.setOccurrenceTime("2024-01-01");
example.setCaseNumber("2024示例案号"); example.setCaseNumber("2024示例案号");
example.setCauseOfAction("案由示例"); example.setCauseOfAction("案由示例");
example.setInvolvedAmount("100000");
example.setCourtName("示例法院");
example.setDataStatus("已公开");
example.setComments("备注信息"); example.setComments("备注信息");
templateList.add(example); templateList.add(example);
Workbook workbook = ExcelImportSupport.buildTemplate("法院公告导入模板", "法院公告", CreditJudicialImportParam.class, templateList); Workbook workbook = ExcelImportSupport.buildTemplate("法院公告导入模板", "法院公告", CreditCourtAnnouncementImportParam.class, templateList);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment; filename=credit_court_announcement_import_template.xlsx"); response.setHeader("Content-Disposition", "attachment; filename=credit_court_announcement_import_template.xlsx");
@@ -319,29 +382,23 @@ public class CreditCourtAnnouncementController extends BaseController {
workbook.close(); workbook.close();
} }
private boolean isEmptyImportRow(CreditJudicialImportParam param) { private boolean isEmptyImportRow(CreditCourtAnnouncementImportParam param) {
if (param == null) { if (param == null) {
return true; return true;
} }
return ImportHelper.isBlank(param.getCaseNumber()) return ImportHelper.isBlank(param.getCaseNumber())
&& ImportHelper.isBlank(param.getPlaintiffAppellant())
&& ImportHelper.isBlank(param.getAppellee())
&& ImportHelper.isBlank(param.getCauseOfAction()); && ImportHelper.isBlank(param.getCauseOfAction());
} }
private CreditCourtAnnouncement convertImportParamToEntity(CreditJudicialImportParam param) { private CreditCourtAnnouncement convertImportParamToEntity(CreditCourtAnnouncementImportParam param) {
CreditCourtAnnouncement entity = new CreditCourtAnnouncement(); CreditCourtAnnouncement entity = new CreditCourtAnnouncement();
entity.setDataType(param.getDataType()); entity.setDataType(param.getDataType());
entity.setPlaintiffAppellant(param.getPlaintiffAppellant()); entity.setPlaintiffAppellant(param.getPlaintiffAppellant());
entity.setAppellee(param.getAppellee());
entity.setOtherPartiesThirdParty(param.getOtherPartiesThirdParty()); entity.setOtherPartiesThirdParty(param.getOtherPartiesThirdParty());
entity.setOccurrenceTime(param.getOccurrenceTime()); entity.setOccurrenceTime(param.getOccurrenceTime());
entity.setCaseNumber(param.getCaseNumber()); entity.setCaseNumber(param.getCaseNumber());
entity.setCauseOfAction(param.getCauseOfAction()); entity.setCauseOfAction(param.getCauseOfAction());
entity.setInvolvedAmount(param.getInvolvedAmount());
entity.setCourtName(param.getCourtName());
entity.setDataStatus(param.getDataStatus());
entity.setComments(param.getComments()); entity.setComments(param.getComments());
return entity; return entity;

View File

@@ -7,8 +7,10 @@ import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.common.core.web.PageResult; import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.system.entity.User; import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.credit.entity.CreditCourtSession; import com.gxwebsoft.credit.entity.CreditCourtSession;
import com.gxwebsoft.credit.param.CreditJudicialImportParam; import com.gxwebsoft.credit.param.CreditCourtSessionImportParam;
import com.gxwebsoft.credit.param.CreditCourtSessionParam; 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 com.gxwebsoft.credit.service.CreditCourtSessionService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@@ -22,7 +24,11 @@ import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set;
/** /**
* 开庭公告司法大数据控制器 * 开庭公告司法大数据控制器
@@ -40,6 +46,12 @@ public class CreditCourtSessionController extends BaseController {
@Resource @Resource
private BatchImportSupport batchImportSupport; private BatchImportSupport batchImportSupport;
@Resource
private CreditCompanyService creditCompanyService;
@Resource
private CreditCompanyRecordCountService creditCompanyRecordCountService;
@Operation(summary = "分页查询开庭公告司法大数据") @Operation(summary = "分页查询开庭公告司法大数据")
@GetMapping("/page") @GetMapping("/page")
public ApiResult<PageResult<CreditCourtSession>> page(CreditCourtSessionParam param) { public ApiResult<PageResult<CreditCourtSession>> page(CreditCourtSessionParam param) {
@@ -132,6 +144,45 @@ public class CreditCourtSessionController extends BaseController {
return fail("删除失败"); 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;
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
creditCourtSessionService,
creditCompanyService,
currentTenantId,
onlyNull,
limit,
CreditCourtSession::getId,
CreditCourtSession::setId,
CreditCourtSession::getAppellee,
CreditCourtSession::getCompanyId,
CreditCourtSession::setCompanyId,
CreditCourtSession::getHasData,
CreditCourtSession::setHasData,
CreditCourtSession::getTenantId,
CreditCourtSession::new
);
if (!stats.anyDataRead) {
return success("无可更新数据", stats.toMap());
}
return success("更新完成,更新" + stats.updated + "", stats.toMap());
}
/** /**
* 批量导入开庭公告司法大数据 * 批量导入开庭公告司法大数据
*/ */
@@ -142,13 +193,17 @@ public class CreditCourtSessionController extends BaseController {
@RequestParam(value = "companyId", required = false) Integer companyId) { @RequestParam(value = "companyId", required = false) Integer companyId) {
List<String> errorMessages = new ArrayList<>(); List<String> errorMessages = new ArrayList<>();
int successCount = 0; int successCount = 0;
Set<Integer> touchedCompanyIds = new HashSet<>();
try { try {
ExcelImportSupport.ImportResult<CreditJudicialImportParam> importResult = ExcelImportSupport.read( // 兼容多 sheet 文件优先定位“开庭公告”sheet否则默认第 0 个。
file, CreditJudicialImportParam.class, this::isEmptyImportRow); int sheetIndex = ExcelImportSupport.findSheetIndex(file, "开庭公告", 0);
List<CreditJudicialImportParam> list = importResult.getData(); ExcelImportSupport.ImportResult<CreditCourtSessionImportParam> importResult = ExcelImportSupport.read(
file, CreditCourtSessionImportParam.class, this::isEmptyImportRow, sheetIndex);
List<CreditCourtSessionImportParam> list = importResult.getData();
int usedTitleRows = importResult.getTitleRows(); int usedTitleRows = importResult.getTitleRows();
int usedHeadRows = importResult.getHeadRows(); int usedHeadRows = importResult.getHeadRows();
int usedSheetIndex = importResult.getSheetIndex();
if (CollectionUtils.isEmpty(list)) { if (CollectionUtils.isEmpty(list)) {
return fail("未读取到数据,请确认模板表头与示例格式一致", null); return fail("未读取到数据,请确认模板表头与示例格式一致", null);
@@ -157,6 +212,7 @@ public class CreditCourtSessionController extends BaseController {
User loginUser = getLoginUser(); User loginUser = getLoginUser();
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null; Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null; Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
final int chunkSize = 500; final int chunkSize = 500;
final int mpBatchSize = 500; final int mpBatchSize = 500;
@@ -164,13 +220,22 @@ public class CreditCourtSessionController extends BaseController {
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize); List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
for (int i = 0; i < list.size(); i++) { for (int i = 0; i < list.size(); i++) {
CreditJudicialImportParam param = list.get(i); CreditCourtSessionImportParam param = list.get(i);
try { try {
CreditCourtSession item = convertImportParamToEntity(param); 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) { if (item.getCompanyId() == null && companyId != null) {
item.setCompanyId(companyId); item.setCompanyId(companyId);
} }
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
touchedCompanyIds.add(item.getCompanyId());
}
if (item.getUserId() == null && currentUserId != null) { if (item.getUserId() == null && currentUserId != null) {
item.setUserId(currentUserId); item.setUserId(currentUserId);
} }
@@ -193,6 +258,10 @@ public class CreditCourtSessionController extends BaseController {
continue; continue;
} }
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
touchedCompanyIds.add(item.getCompanyId());
}
chunkItems.add(item); chunkItems.add(item);
chunkRowNumbers.add(excelRowNumber); chunkRowNumbers.add(excelRowNumber);
if (chunkItems.size() >= chunkSize) { if (chunkItems.size() >= chunkSize) {
@@ -277,6 +346,8 @@ public class CreditCourtSessionController extends BaseController {
); );
} }
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.COURT_SESSION, touchedCompanyIds);
if (errorMessages.isEmpty()) { if (errorMessages.isEmpty()) {
return success("成功导入" + successCount + "条数据", null); return success("成功导入" + successCount + "条数据", null);
} else { } else {
@@ -288,29 +359,227 @@ public class CreditCourtSessionController extends BaseController {
} }
} }
/**
* 批量导入历史开庭公告(仅解析“历史开庭公告”选项卡)
* 规则案号相同则覆盖更新recommend++ 记录更新次数);案号不存在则插入。
*/
@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, "案号");
LinkedHashMap<String, CreditCourtSession> latestByCaseNumber = new LinkedHashMap<>();
LinkedHashMap<String, Integer> latestRowByCaseNumber = new LinkedHashMap<>();
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);
}
latestByCaseNumber.put(item.getCaseNumber(), item);
latestRowByCaseNumber.put(item.getCaseNumber(), excelRowNumber);
} catch (Exception e) {
errorMessages.add("" + excelRowNumber + "行:" + e.getMessage());
e.printStackTrace();
}
}
if (latestByCaseNumber.isEmpty()) {
if (errorMessages.isEmpty()) {
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
}
return success("导入完成成功0条失败" + errorMessages.size() + "", errorMessages);
}
final int chunkSize = 500;
final int mpBatchSize = 500;
List<CreditCourtSession> chunkItems = new ArrayList<>(chunkSize);
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
for (Map.Entry<String, CreditCourtSession> entry : latestByCaseNumber.entrySet()) {
String caseNumber = entry.getKey();
CreditCourtSession item = entry.getValue();
Integer rowNo = latestRowByCaseNumber.get(caseNumber);
chunkItems.add(item);
chunkRowNumbers.add(rowNo != null ? rowNo : -1);
if (chunkItems.size() >= chunkSize) {
successCount += batchImportSupport.persistChunkWithFallback(
chunkItems,
chunkRowNumbers,
() -> batchImportSupport.upsertBySingleKeyAndIncrementCounterOnUpdate(
creditCourtSessionService,
chunkItems,
CreditCourtSession::getId,
CreditCourtSession::setId,
CreditCourtSession::getCaseNumber,
CreditCourtSession::getCaseNumber,
CreditCourtSession::getRecommend,
CreditCourtSession::setRecommend,
null,
mpBatchSize
),
(rowItem, rowNumber) -> {
if (rowItem.getRecommend() == null) {
rowItem.setRecommend(0);
}
boolean saved = creditCourtSessionService.save(rowItem);
if (!saved) {
CreditCourtSession existing = creditCourtSessionService.lambdaQuery()
.eq(CreditCourtSession::getCaseNumber, rowItem.getCaseNumber())
.select(CreditCourtSession::getId, CreditCourtSession::getRecommend)
.one();
if (existing != null) {
rowItem.setId(existing.getId());
Integer old = existing.getRecommend();
rowItem.setRecommend(old == null ? 1 : old + 1);
if (creditCourtSessionService.updateById(rowItem)) {
return true;
}
}
} else {
return true;
}
String prefix = rowNumber > 0 ? ("" + rowNumber + "行:") : "";
errorMessages.add(prefix + "保存失败");
return false;
},
errorMessages
);
chunkItems.clear();
chunkRowNumbers.clear();
}
}
if (!chunkItems.isEmpty()) {
successCount += batchImportSupport.persistChunkWithFallback(
chunkItems,
chunkRowNumbers,
() -> batchImportSupport.upsertBySingleKeyAndIncrementCounterOnUpdate(
creditCourtSessionService,
chunkItems,
CreditCourtSession::getId,
CreditCourtSession::setId,
CreditCourtSession::getCaseNumber,
CreditCourtSession::getCaseNumber,
CreditCourtSession::getRecommend,
CreditCourtSession::setRecommend,
null,
mpBatchSize
),
(rowItem, rowNumber) -> {
if (rowItem.getRecommend() == null) {
rowItem.setRecommend(0);
}
boolean saved = creditCourtSessionService.save(rowItem);
if (!saved) {
CreditCourtSession existing = creditCourtSessionService.lambdaQuery()
.eq(CreditCourtSession::getCaseNumber, rowItem.getCaseNumber())
.select(CreditCourtSession::getId, CreditCourtSession::getRecommend)
.one();
if (existing != null) {
rowItem.setId(existing.getId());
Integer old = existing.getRecommend();
rowItem.setRecommend(old == null ? 1 : old + 1);
if (creditCourtSessionService.updateById(rowItem)) {
return true;
}
}
} else {
return true;
}
String prefix = rowNumber > 0 ? ("" + rowNumber + "行:") : "";
errorMessages.add(prefix + "保存失败");
return false;
},
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 = "下载开庭公告司法大数据导入模板") @Operation(summary = "下载开庭公告司法大数据导入模板")
@GetMapping("/import/template") @GetMapping("/import/template")
public void downloadTemplate(HttpServletResponse response) throws IOException { public void downloadTemplate(HttpServletResponse response) throws IOException {
List<CreditJudicialImportParam> templateList = new ArrayList<>(); List<CreditCourtSessionImportParam> templateList = new ArrayList<>();
CreditJudicialImportParam example = new CreditJudicialImportParam(); CreditCourtSessionImportParam example = new CreditCourtSessionImportParam();
example.setDataType("开庭公告"); example.setOtherPartiesThirdParty("当事人");
example.setPlaintiffAppellant("原告示例");
example.setAppellee("被告示例");
example.setOtherPartiesThirdParty("第三人示例");
example.setOccurrenceTime("2024-01-01");
example.setCaseNumber("2024示例案号"); example.setCaseNumber("2024示例案号");
example.setCauseOfAction("案由示例"); example.setCauseOfAction("案由示例");
example.setInvolvedAmount("100000");
example.setCourtName("示例法院"); example.setCourtName("示例法院");
example.setDataStatus("已公开"); example.setOccurrenceTime("2024-01-01");
example.setComments("备注信息"); example.setComments("备注信息");
templateList.add(example); templateList.add(example);
Workbook workbook = ExcelImportSupport.buildTemplate("开庭公告导入模板", "开庭公告", CreditJudicialImportParam.class, templateList); Workbook workbook = ExcelImportSupport.buildTemplate("开庭公告导入模板", "开庭公告", CreditCourtSessionImportParam.class, templateList);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment; filename=credit_court_session_import_template.xlsx"); response.setHeader("Content-Disposition", "attachment; filename=credit_court_session_import_template.xlsx");
@@ -319,30 +588,23 @@ public class CreditCourtSessionController extends BaseController {
workbook.close(); workbook.close();
} }
private boolean isEmptyImportRow(CreditJudicialImportParam param) { private boolean isEmptyImportRow(CreditCourtSessionImportParam param) {
if (param == null) { if (param == null) {
return true; return true;
} }
return ImportHelper.isBlank(param.getCaseNumber()) return ImportHelper.isBlank(param.getCaseNumber())
&& ImportHelper.isBlank(param.getPlaintiffAppellant())
&& ImportHelper.isBlank(param.getAppellee())
&& ImportHelper.isBlank(param.getCauseOfAction()); && ImportHelper.isBlank(param.getCauseOfAction());
} }
private CreditCourtSession convertImportParamToEntity(CreditJudicialImportParam param) { private CreditCourtSession convertImportParamToEntity(CreditCourtSessionImportParam param) {
CreditCourtSession entity = new CreditCourtSession(); CreditCourtSession entity = new CreditCourtSession();
entity.setDataType(param.getDataType()); entity.setOtherPartiesThirdParty(param.getOtherPartiesThirdParty());
entity.setPlaintiffAppellant(param.getPlaintiffAppellant()); entity.setOccurrenceTime(param.getOccurrenceTime());
entity.setAppellee(param.getAppellee()); entity.setCaseNumber(param.getCaseNumber());
entity.setOtherPartiesThirdParty(param.getOtherPartiesThirdParty()); entity.setCauseOfAction(param.getCauseOfAction());
entity.setOccurrenceTime(param.getOccurrenceTime()); entity.setCourtName(param.getCourtName());
entity.setCaseNumber(param.getCaseNumber()); entity.setComments(param.getComments());
entity.setCauseOfAction(param.getCauseOfAction());
entity.setInvolvedAmount(param.getInvolvedAmount());
entity.setCourtName(param.getCourtName());
entity.setDataStatus(param.getDataStatus());
entity.setComments(param.getComments());
return entity; return entity;
} }

View File

@@ -9,6 +9,8 @@ import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.credit.entity.CreditCustomer; import com.gxwebsoft.credit.entity.CreditCustomer;
import com.gxwebsoft.credit.param.CreditCustomerImportParam; import com.gxwebsoft.credit.param.CreditCustomerImportParam;
import com.gxwebsoft.credit.param.CreditCustomerParam; 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 com.gxwebsoft.credit.service.CreditCustomerService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@@ -23,7 +25,10 @@ import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set;
/** /**
* 客户控制器 * 客户控制器
@@ -41,6 +46,12 @@ public class CreditCustomerController extends BaseController {
@Resource @Resource
private BatchImportSupport batchImportSupport; private BatchImportSupport batchImportSupport;
@Resource
private CreditCompanyService creditCompanyService;
@Resource
private CreditCompanyRecordCountService creditCompanyRecordCountService;
@Operation(summary = "分页查询客户") @Operation(summary = "分页查询客户")
@GetMapping("/page") @GetMapping("/page")
public ApiResult<PageResult<CreditCustomer>> page(CreditCustomerParam param) { public ApiResult<PageResult<CreditCustomer>> page(CreditCustomerParam param) {
@@ -128,6 +139,45 @@ public class CreditCustomerController extends BaseController {
return fail("删除失败"); 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::getHasData,
CreditCustomer::setHasData,
CreditCustomer::getTenantId,
CreditCustomer::new
);
if (!stats.anyDataRead) {
return success("无可更新数据", stats.toMap());
}
return success("更新完成,更新" + stats.updated + "", stats.toMap());
}
/** /**
* 批量导入客户 * 批量导入客户
*/ */
@@ -138,6 +188,7 @@ public class CreditCustomerController extends BaseController {
@RequestParam(value = "companyId", required = false) Integer companyId) { @RequestParam(value = "companyId", required = false) Integer companyId) {
List<String> errorMessages = new ArrayList<>(); List<String> errorMessages = new ArrayList<>();
int successCount = 0; int successCount = 0;
Set<Integer> touchedCompanyIds = new HashSet<>();
try { try {
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "客户", 4); int sheetIndex = ExcelImportSupport.findSheetIndex(file, "客户", 4);
@@ -146,6 +197,7 @@ public class CreditCustomerController extends BaseController {
List<CreditCustomerImportParam> list = importResult.getData(); List<CreditCustomerImportParam> list = importResult.getData();
int usedTitleRows = importResult.getTitleRows(); int usedTitleRows = importResult.getTitleRows();
int usedHeadRows = importResult.getHeadRows(); int usedHeadRows = importResult.getHeadRows();
int usedSheetIndex = importResult.getSheetIndex();
if (CollectionUtils.isEmpty(list)) { if (CollectionUtils.isEmpty(list)) {
return fail("未读取到数据,请确认模板表头与示例格式一致", null); return fail("未读取到数据,请确认模板表头与示例格式一致", null);
@@ -154,6 +206,7 @@ public class CreditCustomerController extends BaseController {
User loginUser = getLoginUser(); User loginUser = getLoginUser();
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null; Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null; Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
Map<String, String> urlByName = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "客户");
final int chunkSize = 500; final int chunkSize = 500;
final int mpBatchSize = 500; final int mpBatchSize = 500;
@@ -165,6 +218,12 @@ public class CreditCustomerController extends BaseController {
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows; int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
try { try {
CreditCustomer item = convertImportParamToEntity(param); CreditCustomer 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) { if (item.getCompanyId() == null && companyId != null) {
item.setCompanyId(companyId); item.setCompanyId(companyId);
@@ -190,6 +249,10 @@ public class CreditCustomerController extends BaseController {
continue; continue;
} }
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
touchedCompanyIds.add(item.getCompanyId());
}
chunkItems.add(item); chunkItems.add(item);
chunkRowNumbers.add(excelRowNumber); chunkRowNumbers.add(excelRowNumber);
if (chunkItems.size() >= chunkSize) { if (chunkItems.size() >= chunkSize) {
@@ -423,6 +486,8 @@ public class CreditCustomerController extends BaseController {
); );
} }
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.CUSTOMER, touchedCompanyIds);
if (errorMessages.isEmpty()) { if (errorMessages.isEmpty()) {
return success("成功导入" + successCount + "条数据", null); return success("成功导入" + successCount + "条数据", null);
} else { } else {

View File

@@ -7,8 +7,10 @@ import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.common.core.web.PageResult; import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.system.entity.User; import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.credit.entity.CreditDeliveryNotice; import com.gxwebsoft.credit.entity.CreditDeliveryNotice;
import com.gxwebsoft.credit.param.CreditDeliveryNoticeImportParam;
import com.gxwebsoft.credit.param.CreditDeliveryNoticeParam; import com.gxwebsoft.credit.param.CreditDeliveryNoticeParam;
import com.gxwebsoft.credit.param.CreditJudicialImportParam; import com.gxwebsoft.credit.service.CreditCompanyService;
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
import com.gxwebsoft.credit.service.CreditDeliveryNoticeService; import com.gxwebsoft.credit.service.CreditDeliveryNoticeService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@@ -22,7 +24,10 @@ import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set;
/** /**
* 送达公告司法大数据控制器 * 送达公告司法大数据控制器
@@ -40,6 +45,12 @@ public class CreditDeliveryNoticeController extends BaseController {
@Resource @Resource
private BatchImportSupport batchImportSupport; private BatchImportSupport batchImportSupport;
@Resource
private CreditCompanyService creditCompanyService;
@Resource
private CreditCompanyRecordCountService creditCompanyRecordCountService;
@Operation(summary = "分页查询送达公告司法大数据") @Operation(summary = "分页查询送达公告司法大数据")
@GetMapping("/page") @GetMapping("/page")
public ApiResult<PageResult<CreditDeliveryNotice>> page(CreditDeliveryNoticeParam param) { public ApiResult<PageResult<CreditDeliveryNotice>> page(CreditDeliveryNoticeParam param) {
@@ -132,6 +143,45 @@ public class CreditDeliveryNoticeController extends BaseController {
return fail("删除失败"); 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;
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
creditDeliveryNoticeService,
creditCompanyService,
currentTenantId,
onlyNull,
limit,
CreditDeliveryNotice::getId,
CreditDeliveryNotice::setId,
CreditDeliveryNotice::getOtherPartiesThirdParty,
CreditDeliveryNotice::getCompanyId,
CreditDeliveryNotice::setCompanyId,
CreditDeliveryNotice::getHasData,
CreditDeliveryNotice::setHasData,
CreditDeliveryNotice::getTenantId,
CreditDeliveryNotice::new
);
if (!stats.anyDataRead) {
return success("无可更新数据", stats.toMap());
}
return success("更新完成,更新" + stats.updated + "", stats.toMap());
}
/** /**
* 批量导入送达公告司法大数据 * 批量导入送达公告司法大数据
*/ */
@@ -142,13 +192,16 @@ public class CreditDeliveryNoticeController extends BaseController {
@RequestParam(value = "companyId", required = false) Integer companyId) { @RequestParam(value = "companyId", required = false) Integer companyId) {
List<String> errorMessages = new ArrayList<>(); List<String> errorMessages = new ArrayList<>();
int successCount = 0; int successCount = 0;
Set<Integer> touchedCompanyIds = new HashSet<>();
try { try {
ExcelImportSupport.ImportResult<CreditJudicialImportParam> importResult = ExcelImportSupport.read( int sheetIndex = ExcelImportSupport.findSheetIndex(file, "送达公告", 0);
file, CreditJudicialImportParam.class, this::isEmptyImportRow); ExcelImportSupport.ImportResult<CreditDeliveryNoticeImportParam> importResult = ExcelImportSupport.read(
List<CreditJudicialImportParam> list = importResult.getData(); file, CreditDeliveryNoticeImportParam.class, this::isEmptyImportRow, sheetIndex);
List<CreditDeliveryNoticeImportParam> list = importResult.getData();
int usedTitleRows = importResult.getTitleRows(); int usedTitleRows = importResult.getTitleRows();
int usedHeadRows = importResult.getHeadRows(); int usedHeadRows = importResult.getHeadRows();
int usedSheetIndex = importResult.getSheetIndex();
if (CollectionUtils.isEmpty(list)) { if (CollectionUtils.isEmpty(list)) {
return fail("未读取到数据,请确认模板表头与示例格式一致", null); return fail("未读取到数据,请确认模板表头与示例格式一致", null);
@@ -157,6 +210,9 @@ public class CreditDeliveryNoticeController extends BaseController {
User loginUser = getLoginUser(); User loginUser = getLoginUser();
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null; Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : 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 chunkSize = 500;
final int mpBatchSize = 500; final int mpBatchSize = 500;
@@ -164,9 +220,15 @@ public class CreditDeliveryNoticeController extends BaseController {
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize); List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
for (int i = 0; i < list.size(); i++) { for (int i = 0; i < list.size(); i++) {
CreditJudicialImportParam param = list.get(i); CreditDeliveryNoticeImportParam param = list.get(i);
try { try {
CreditDeliveryNotice item = convertImportParamToEntity(param); 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) { if (item.getCompanyId() == null && companyId != null) {
item.setCompanyId(companyId); item.setCompanyId(companyId);
@@ -193,6 +255,10 @@ public class CreditDeliveryNoticeController extends BaseController {
continue; continue;
} }
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
touchedCompanyIds.add(item.getCompanyId());
}
chunkItems.add(item); chunkItems.add(item);
chunkRowNumbers.add(excelRowNumber); chunkRowNumbers.add(excelRowNumber);
if (chunkItems.size() >= chunkSize) { if (chunkItems.size() >= chunkSize) {
@@ -277,6 +343,8 @@ public class CreditDeliveryNoticeController extends BaseController {
); );
} }
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.DELIVERY_NOTICE, touchedCompanyIds);
if (errorMessages.isEmpty()) { if (errorMessages.isEmpty()) {
return success("成功导入" + successCount + "条数据", null); return success("成功导入" + successCount + "条数据", null);
} else { } else {
@@ -294,23 +362,18 @@ public class CreditDeliveryNoticeController extends BaseController {
@Operation(summary = "下载送达公告导入模板") @Operation(summary = "下载送达公告导入模板")
@GetMapping("/import/template") @GetMapping("/import/template")
public void downloadTemplate(HttpServletResponse response) throws IOException { public void downloadTemplate(HttpServletResponse response) throws IOException {
List<CreditJudicialImportParam> templateList = new ArrayList<>(); List<CreditDeliveryNoticeImportParam> templateList = new ArrayList<>();
CreditJudicialImportParam example = new CreditJudicialImportParam(); CreditDeliveryNoticeImportParam example = new CreditDeliveryNoticeImportParam();
example.setDataType("送达公告");
example.setPlaintiffAppellant("原告示例");
example.setAppellee("被告示例");
example.setOtherPartiesThirdParty("第三人示例"); example.setOtherPartiesThirdParty("第三人示例");
example.setOccurrenceTime("2024-01-01"); example.setOccurrenceTime("2024-01-01");
example.setCaseNumber("2024示例案号"); example.setCaseNumber("2024示例案号");
example.setCauseOfAction("案由示例"); example.setCauseOfAction("案由示例");
example.setInvolvedAmount("100000");
example.setCourtName("示例法院"); example.setCourtName("示例法院");
example.setDataStatus("已公开");
example.setComments("备注信息"); example.setComments("备注信息");
templateList.add(example); templateList.add(example);
Workbook workbook = ExcelImportSupport.buildTemplate("送达公告导入模板", "送达公告", CreditJudicialImportParam.class, templateList); Workbook workbook = ExcelImportSupport.buildTemplate("送达公告导入模板", "送达公告", CreditDeliveryNoticeImportParam.class, templateList);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment; filename=credit_delivery_notice_import_template.xlsx"); response.setHeader("Content-Disposition", "attachment; filename=credit_delivery_notice_import_template.xlsx");
@@ -319,29 +382,22 @@ public class CreditDeliveryNoticeController extends BaseController {
workbook.close(); workbook.close();
} }
private boolean isEmptyImportRow(CreditJudicialImportParam param) { private boolean isEmptyImportRow(CreditDeliveryNoticeImportParam param) {
if (param == null) { if (param == null) {
return true; return true;
} }
return ImportHelper.isBlank(param.getCaseNumber()) return ImportHelper.isBlank(param.getCaseNumber())
&& ImportHelper.isBlank(param.getPlaintiffAppellant())
&& ImportHelper.isBlank(param.getAppellee())
&& ImportHelper.isBlank(param.getCauseOfAction()); && ImportHelper.isBlank(param.getCauseOfAction());
} }
private CreditDeliveryNotice convertImportParamToEntity(CreditJudicialImportParam param) { private CreditDeliveryNotice convertImportParamToEntity(CreditDeliveryNoticeImportParam param) {
CreditDeliveryNotice entity = new CreditDeliveryNotice(); CreditDeliveryNotice entity = new CreditDeliveryNotice();
entity.setDataType(param.getDataType());
entity.setPlaintiffAppellant(param.getPlaintiffAppellant());
entity.setAppellee(param.getAppellee());
entity.setOtherPartiesThirdParty(param.getOtherPartiesThirdParty()); entity.setOtherPartiesThirdParty(param.getOtherPartiesThirdParty());
entity.setOccurrenceTime(param.getOccurrenceTime()); entity.setOccurrenceTime(param.getOccurrenceTime());
entity.setCaseNumber(param.getCaseNumber()); entity.setCaseNumber(param.getCaseNumber());
entity.setCauseOfAction(param.getCauseOfAction()); entity.setCauseOfAction(param.getCauseOfAction());
entity.setInvolvedAmount(param.getInvolvedAmount());
entity.setCourtName(param.getCourtName()); entity.setCourtName(param.getCourtName());
entity.setDataStatus(param.getDataStatus());
entity.setComments(param.getComments()); entity.setComments(param.getComments());
return entity; return entity;

View File

@@ -9,6 +9,8 @@ import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.credit.entity.CreditExternal; import com.gxwebsoft.credit.entity.CreditExternal;
import com.gxwebsoft.credit.param.CreditExternalImportParam; import com.gxwebsoft.credit.param.CreditExternalImportParam;
import com.gxwebsoft.credit.param.CreditExternalParam; 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 com.gxwebsoft.credit.service.CreditExternalService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@@ -22,7 +24,10 @@ import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set;
/** /**
* 对外投资控制器 * 对外投资控制器
@@ -40,6 +45,12 @@ public class CreditExternalController extends BaseController {
@Resource @Resource
private BatchImportSupport batchImportSupport; private BatchImportSupport batchImportSupport;
@Resource
private CreditCompanyService creditCompanyService;
@Resource
private CreditCompanyRecordCountService creditCompanyRecordCountService;
@Operation(summary = "分页查询对外投资") @Operation(summary = "分页查询对外投资")
@GetMapping("/page") @GetMapping("/page")
public ApiResult<PageResult<CreditExternal>> page(CreditExternalParam param) { public ApiResult<PageResult<CreditExternal>> page(CreditExternalParam param) {
@@ -132,6 +143,45 @@ public class CreditExternalController extends BaseController {
return fail("删除失败"); 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::getHasData,
CreditExternal::setHasData,
CreditExternal::getTenantId,
CreditExternal::new
);
if (!stats.anyDataRead) {
return success("无可更新数据", stats.toMap());
}
return success("更新完成,更新" + stats.updated + "", stats.toMap());
}
/** /**
* 批量导入对外投资 * 批量导入对外投资
*/ */
@@ -142,6 +192,7 @@ public class CreditExternalController extends BaseController {
@RequestParam(value = "companyId", required = false) Integer companyId) { @RequestParam(value = "companyId", required = false) Integer companyId) {
List<String> errorMessages = new ArrayList<>(); List<String> errorMessages = new ArrayList<>();
int successCount = 0; int successCount = 0;
Set<Integer> touchedCompanyIds = new HashSet<>();
try { try {
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "对外投资", 0); int sheetIndex = ExcelImportSupport.findSheetIndex(file, "对外投资", 0);
@@ -150,6 +201,7 @@ public class CreditExternalController extends BaseController {
List<CreditExternalImportParam> list = importResult.getData(); List<CreditExternalImportParam> list = importResult.getData();
int usedTitleRows = importResult.getTitleRows(); int usedTitleRows = importResult.getTitleRows();
int usedHeadRows = importResult.getHeadRows(); int usedHeadRows = importResult.getHeadRows();
int usedSheetIndex = importResult.getSheetIndex();
if (CollectionUtils.isEmpty(list)) { if (CollectionUtils.isEmpty(list)) {
return fail("未读取到数据,请确认模板表头与示例格式一致", null); return fail("未读取到数据,请确认模板表头与示例格式一致", null);
@@ -158,6 +210,7 @@ public class CreditExternalController extends BaseController {
User loginUser = getLoginUser(); User loginUser = getLoginUser();
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null; Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null; Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
Map<String, String> urlByName = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "被投资企业名称");
final int chunkSize = 500; final int chunkSize = 500;
final int mpBatchSize = 500; final int mpBatchSize = 500;
@@ -168,6 +221,12 @@ public class CreditExternalController extends BaseController {
CreditExternalImportParam param = list.get(i); CreditExternalImportParam param = list.get(i);
try { try {
CreditExternal item = convertImportParamToEntity(param); 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) { if (item.getCompanyId() == null && companyId != null) {
item.setCompanyId(companyId); item.setCompanyId(companyId);
@@ -194,6 +253,10 @@ public class CreditExternalController extends BaseController {
continue; continue;
} }
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
touchedCompanyIds.add(item.getCompanyId());
}
chunkItems.add(item); chunkItems.add(item);
chunkRowNumbers.add(excelRowNumber); chunkRowNumbers.add(excelRowNumber);
if (chunkItems.size() >= chunkSize) { if (chunkItems.size() >= chunkSize) {
@@ -278,6 +341,8 @@ public class CreditExternalController extends BaseController {
); );
} }
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.EXTERNAL, touchedCompanyIds);
if (errorMessages.isEmpty()) { if (errorMessages.isEmpty()) {
return success("成功导入" + successCount + "条数据", null); return success("成功导入" + successCount + "条数据", null);
} else { } else {

View File

@@ -7,8 +7,10 @@ import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.common.core.web.PageResult; import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.system.entity.User; import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.credit.entity.CreditFinalVersion; import com.gxwebsoft.credit.entity.CreditFinalVersion;
import com.gxwebsoft.credit.param.CreditFinalVersionImportParam;
import com.gxwebsoft.credit.param.CreditFinalVersionParam; import com.gxwebsoft.credit.param.CreditFinalVersionParam;
import com.gxwebsoft.credit.param.CreditJudicialImportParam; import com.gxwebsoft.credit.service.CreditCompanyService;
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
import com.gxwebsoft.credit.service.CreditFinalVersionService; import com.gxwebsoft.credit.service.CreditFinalVersionService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@@ -22,7 +24,11 @@ import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set;
/** /**
* 终本案件控制器 * 终本案件控制器
@@ -40,6 +46,12 @@ public class CreditFinalVersionController extends BaseController {
@Resource @Resource
private BatchImportSupport batchImportSupport; private BatchImportSupport batchImportSupport;
@Resource
private CreditCompanyService creditCompanyService;
@Resource
private CreditCompanyRecordCountService creditCompanyRecordCountService;
@Operation(summary = "分页查询终本案件") @Operation(summary = "分页查询终本案件")
@GetMapping("/page") @GetMapping("/page")
public ApiResult<PageResult<CreditFinalVersion>> page(CreditFinalVersionParam param) { public ApiResult<PageResult<CreditFinalVersion>> page(CreditFinalVersionParam param) {
@@ -132,6 +144,45 @@ public class CreditFinalVersionController extends BaseController {
return fail("删除失败"); 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;
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
creditFinalVersionService,
creditCompanyService,
currentTenantId,
onlyNull,
limit,
CreditFinalVersion::getId,
CreditFinalVersion::setId,
CreditFinalVersion::getAppellee,
CreditFinalVersion::getCompanyId,
CreditFinalVersion::setCompanyId,
CreditFinalVersion::getHasData,
CreditFinalVersion::setHasData,
CreditFinalVersion::getTenantId,
CreditFinalVersion::new
);
if (!stats.anyDataRead) {
return success("无可更新数据", stats.toMap());
}
return success("更新完成,更新" + stats.updated + "", stats.toMap());
}
/** /**
* 批量导入终本案件 * 批量导入终本案件
*/ */
@@ -142,13 +193,17 @@ public class CreditFinalVersionController extends BaseController {
@RequestParam(value = "companyId", required = false) Integer companyId) { @RequestParam(value = "companyId", required = false) Integer companyId) {
List<String> errorMessages = new ArrayList<>(); List<String> errorMessages = new ArrayList<>();
int successCount = 0; int successCount = 0;
Set<Integer> touchedCompanyIds = new HashSet<>();
try { try {
ExcelImportSupport.ImportResult<CreditJudicialImportParam> importResult = ExcelImportSupport.read( // 按选项卡名称读取(客户提供的文件可能不是把目标 sheet 放在第一个)
file, CreditJudicialImportParam.class, this::isEmptyImportRow); int sheetIndex = ExcelImportSupport.findSheetIndex(file, "终本案件", 0);
List<CreditJudicialImportParam> list = importResult.getData(); ExcelImportSupport.ImportResult<CreditFinalVersionImportParam> importResult = ExcelImportSupport.read(
file, CreditFinalVersionImportParam.class, this::isEmptyImportRow, sheetIndex);
List<CreditFinalVersionImportParam> list = importResult.getData();
int usedTitleRows = importResult.getTitleRows(); int usedTitleRows = importResult.getTitleRows();
int usedHeadRows = importResult.getHeadRows(); int usedHeadRows = importResult.getHeadRows();
int usedSheetIndex = importResult.getSheetIndex();
if (CollectionUtils.isEmpty(list)) { if (CollectionUtils.isEmpty(list)) {
return fail("未读取到数据,请确认模板表头与示例格式一致", null); return fail("未读取到数据,请确认模板表头与示例格式一致", null);
@@ -157,6 +212,7 @@ public class CreditFinalVersionController extends BaseController {
User loginUser = getLoginUser(); User loginUser = getLoginUser();
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null; Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null; Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
final int chunkSize = 500; final int chunkSize = 500;
final int mpBatchSize = 500; final int mpBatchSize = 500;
@@ -164,13 +220,22 @@ public class CreditFinalVersionController extends BaseController {
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize); List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
for (int i = 0; i < list.size(); i++) { for (int i = 0; i < list.size(); i++) {
CreditJudicialImportParam param = list.get(i); CreditFinalVersionImportParam param = list.get(i);
try { try {
CreditFinalVersion item = convertImportParamToEntity(param); 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) { if (item.getCompanyId() == null && companyId != null) {
item.setCompanyId(companyId); item.setCompanyId(companyId);
} }
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
touchedCompanyIds.add(item.getCompanyId());
}
if (item.getUserId() == null && currentUserId != null) { if (item.getUserId() == null && currentUserId != null) {
item.setUserId(currentUserId); item.setUserId(currentUserId);
} }
@@ -193,6 +258,10 @@ public class CreditFinalVersionController extends BaseController {
continue; continue;
} }
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
touchedCompanyIds.add(item.getCompanyId());
}
chunkItems.add(item); chunkItems.add(item);
chunkRowNumbers.add(excelRowNumber); chunkRowNumbers.add(excelRowNumber);
if (chunkItems.size() >= chunkSize) { if (chunkItems.size() >= chunkSize) {
@@ -277,6 +346,8 @@ public class CreditFinalVersionController extends BaseController {
); );
} }
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.FINAL_VERSION, touchedCompanyIds);
if (errorMessages.isEmpty()) { if (errorMessages.isEmpty()) {
return success("成功导入" + successCount + "条数据", null); return success("成功导入" + successCount + "条数据", null);
} else { } else {
@@ -288,29 +359,229 @@ public class CreditFinalVersionController extends BaseController {
} }
} }
/**
* 批量导入历史终本案件(仅解析“历史终本案件”选项卡)
* 规则案号相同则覆盖更新recommend++ 记录更新次数);案号不存在则插入。
*/
@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, "案号");
LinkedHashMap<String, CreditFinalVersion> latestByCaseNumber = new LinkedHashMap<>();
LinkedHashMap<String, Integer> latestRowByCaseNumber = new LinkedHashMap<>();
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);
}
latestByCaseNumber.put(item.getCaseNumber(), item);
latestRowByCaseNumber.put(item.getCaseNumber(), excelRowNumber);
} catch (Exception e) {
errorMessages.add("" + excelRowNumber + "行:" + e.getMessage());
e.printStackTrace();
}
}
if (latestByCaseNumber.isEmpty()) {
if (errorMessages.isEmpty()) {
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
}
return success("导入完成成功0条失败" + errorMessages.size() + "", errorMessages);
}
final int chunkSize = 500;
final int mpBatchSize = 500;
List<CreditFinalVersion> chunkItems = new ArrayList<>(chunkSize);
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
for (Map.Entry<String, CreditFinalVersion> entry : latestByCaseNumber.entrySet()) {
String caseNumber = entry.getKey();
CreditFinalVersion item = entry.getValue();
Integer rowNo = latestRowByCaseNumber.get(caseNumber);
chunkItems.add(item);
chunkRowNumbers.add(rowNo != null ? rowNo : -1);
if (chunkItems.size() >= chunkSize) {
successCount += batchImportSupport.persistChunkWithFallback(
chunkItems,
chunkRowNumbers,
() -> batchImportSupport.upsertBySingleKeyAndIncrementCounterOnUpdate(
creditFinalVersionService,
chunkItems,
CreditFinalVersion::getId,
CreditFinalVersion::setId,
CreditFinalVersion::getCaseNumber,
CreditFinalVersion::getCaseNumber,
CreditFinalVersion::getRecommend,
CreditFinalVersion::setRecommend,
null,
mpBatchSize
),
(rowItem, rowNumber) -> {
if (rowItem.getRecommend() == null) {
rowItem.setRecommend(0);
}
boolean saved = creditFinalVersionService.save(rowItem);
if (!saved) {
CreditFinalVersion existing = creditFinalVersionService.lambdaQuery()
.eq(CreditFinalVersion::getCaseNumber, rowItem.getCaseNumber())
.select(CreditFinalVersion::getId, CreditFinalVersion::getRecommend)
.one();
if (existing != null) {
rowItem.setId(existing.getId());
Integer old = existing.getRecommend();
rowItem.setRecommend(old == null ? 1 : old + 1);
if (creditFinalVersionService.updateById(rowItem)) {
return true;
}
}
} else {
return true;
}
String prefix = rowNumber > 0 ? ("" + rowNumber + "行:") : "";
errorMessages.add(prefix + "保存失败");
return false;
},
errorMessages
);
chunkItems.clear();
chunkRowNumbers.clear();
}
}
if (!chunkItems.isEmpty()) {
successCount += batchImportSupport.persistChunkWithFallback(
chunkItems,
chunkRowNumbers,
() -> batchImportSupport.upsertBySingleKeyAndIncrementCounterOnUpdate(
creditFinalVersionService,
chunkItems,
CreditFinalVersion::getId,
CreditFinalVersion::setId,
CreditFinalVersion::getCaseNumber,
CreditFinalVersion::getCaseNumber,
CreditFinalVersion::getRecommend,
CreditFinalVersion::setRecommend,
null,
mpBatchSize
),
(rowItem, rowNumber) -> {
if (rowItem.getRecommend() == null) {
rowItem.setRecommend(0);
}
boolean saved = creditFinalVersionService.save(rowItem);
if (!saved) {
CreditFinalVersion existing = creditFinalVersionService.lambdaQuery()
.eq(CreditFinalVersion::getCaseNumber, rowItem.getCaseNumber())
.select(CreditFinalVersion::getId, CreditFinalVersion::getRecommend)
.one();
if (existing != null) {
rowItem.setId(existing.getId());
Integer old = existing.getRecommend();
rowItem.setRecommend(old == null ? 1 : old + 1);
if (creditFinalVersionService.updateById(rowItem)) {
return true;
}
}
} else {
return true;
}
String prefix = rowNumber > 0 ? ("" + rowNumber + "行:") : "";
errorMessages.add(prefix + "保存失败");
return false;
},
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 = "下载终本案件导入模板") @Operation(summary = "下载终本案件导入模板")
@GetMapping("/import/template") @GetMapping("/import/template")
public void downloadTemplate(HttpServletResponse response) throws IOException { public void downloadTemplate(HttpServletResponse response) throws IOException {
List<CreditJudicialImportParam> templateList = new ArrayList<>(); List<CreditFinalVersionImportParam> templateList = new ArrayList<>();
CreditJudicialImportParam example = new CreditJudicialImportParam(); CreditFinalVersionImportParam example = new CreditFinalVersionImportParam();
example.setDataType("终本案件"); example.setCaseNumber("2024示例案号");
example.setPlaintiffAppellant("原告示例"); example.setPlaintiffAppellant("原告示例");
example.setAppellee("被告示例"); example.setAppellee("被告示例");
example.setOtherPartiesThirdParty("第三人示例"); example.setInvolvedAmount("20,293.91");
example.setOccurrenceTime("2024-01-01");
example.setCaseNumber("2024示例案号");
example.setCauseOfAction("案由示例");
example.setInvolvedAmount("100000");
example.setCourtName("示例法院"); example.setCourtName("示例法院");
example.setDataStatus("已公开"); example.setOccurrenceTime("2024-01-01");
example.setFinalDate("2024-01-01");
example.setComments("备注信息"); example.setComments("备注信息");
templateList.add(example); templateList.add(example);
Workbook workbook = ExcelImportSupport.buildTemplate("终本案件导入模板", "终本案件", CreditJudicialImportParam.class, templateList); Workbook workbook = ExcelImportSupport.buildTemplate("终本案件导入模板", "终本案件", CreditFinalVersionImportParam.class, templateList);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment; filename=credit_final_version_import_template.xlsx"); response.setHeader("Content-Disposition", "attachment; filename=credit_final_version_import_template.xlsx");
@@ -319,29 +590,24 @@ public class CreditFinalVersionController extends BaseController {
workbook.close(); workbook.close();
} }
private boolean isEmptyImportRow(CreditJudicialImportParam param) { private boolean isEmptyImportRow(CreditFinalVersionImportParam param) {
if (param == null) { if (param == null) {
return true; return true;
} }
return ImportHelper.isBlank(param.getCaseNumber()) return ImportHelper.isBlank(param.getCaseNumber());
&& ImportHelper.isBlank(param.getPlaintiffAppellant())
&& ImportHelper.isBlank(param.getAppellee())
&& ImportHelper.isBlank(param.getCauseOfAction());
} }
private CreditFinalVersion convertImportParamToEntity(CreditJudicialImportParam param) { private CreditFinalVersion convertImportParamToEntity(CreditFinalVersionImportParam param) {
CreditFinalVersion entity = new CreditFinalVersion(); CreditFinalVersion entity = new CreditFinalVersion();
entity.setDataType(param.getDataType()); entity.setCaseNumber(param.getCaseNumber());
entity.setPlaintiffAppellant(param.getPlaintiffAppellant()); entity.setPlaintiffAppellant(param.getPlaintiffAppellant());
entity.setAppellee(param.getAppellee()); entity.setAppellee(param.getAppellee());
entity.setOtherPartiesThirdParty(param.getOtherPartiesThirdParty()); entity.setUnfulfilledAmount(param.getUnfulfilledAmount());
entity.setOccurrenceTime(param.getOccurrenceTime());
entity.setCaseNumber(param.getCaseNumber());
entity.setCauseOfAction(param.getCauseOfAction());
entity.setInvolvedAmount(param.getInvolvedAmount()); entity.setInvolvedAmount(param.getInvolvedAmount());
entity.setCourtName(param.getCourtName()); entity.setCourtName(param.getCourtName());
entity.setDataStatus(param.getDataStatus()); entity.setOccurrenceTime(param.getOccurrenceTime());
entity.setFinalDate(param.getFinalDate());
entity.setComments(param.getComments()); entity.setComments(param.getComments());
return entity; return entity;

View File

@@ -7,8 +7,10 @@ import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.common.core.web.PageResult; import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.system.entity.User; import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.credit.entity.CreditGqdj; import com.gxwebsoft.credit.entity.CreditGqdj;
import com.gxwebsoft.credit.param.CreditGqdjImportParam;
import com.gxwebsoft.credit.param.CreditGqdjParam; import com.gxwebsoft.credit.param.CreditGqdjParam;
import com.gxwebsoft.credit.param.CreditJudicialImportParam; import com.gxwebsoft.credit.service.CreditCompanyService;
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
import com.gxwebsoft.credit.service.CreditGqdjService; import com.gxwebsoft.credit.service.CreditGqdjService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@@ -22,7 +24,11 @@ import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set;
/** /**
* 股权冻结控制器 * 股权冻结控制器
@@ -40,6 +46,12 @@ public class CreditGqdjController extends BaseController {
@Resource @Resource
private BatchImportSupport batchImportSupport; private BatchImportSupport batchImportSupport;
@Resource
private CreditCompanyService creditCompanyService;
@Resource
private CreditCompanyRecordCountService creditCompanyRecordCountService;
@Operation(summary = "分页查询股权冻结") @Operation(summary = "分页查询股权冻结")
@GetMapping("/page") @GetMapping("/page")
public ApiResult<PageResult<CreditGqdj>> page(CreditGqdjParam param) { public ApiResult<PageResult<CreditGqdj>> page(CreditGqdjParam param) {
@@ -132,6 +144,45 @@ public class CreditGqdjController extends BaseController {
return fail("删除失败"); 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;
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
creditGqdjService,
creditCompanyService,
currentTenantId,
onlyNull,
limit,
CreditGqdj::getId,
CreditGqdj::setId,
CreditGqdj::getAppellee,
CreditGqdj::getCompanyId,
CreditGqdj::setCompanyId,
CreditGqdj::getHasData,
CreditGqdj::setHasData,
CreditGqdj::getTenantId,
CreditGqdj::new
);
if (!stats.anyDataRead) {
return success("无可更新数据", stats.toMap());
}
return success("更新完成,更新" + stats.updated + "", stats.toMap());
}
/** /**
* 批量导入股权冻结司法大数据 * 批量导入股权冻结司法大数据
*/ */
@@ -142,13 +193,16 @@ public class CreditGqdjController extends BaseController {
@RequestParam(value = "companyId", required = false) Integer companyId) { @RequestParam(value = "companyId", required = false) Integer companyId) {
List<String> errorMessages = new ArrayList<>(); List<String> errorMessages = new ArrayList<>();
int successCount = 0; int successCount = 0;
Set<Integer> touchedCompanyIds = new HashSet<>();
try { try {
ExcelImportSupport.ImportResult<CreditJudicialImportParam> importResult = ExcelImportSupport.read( int sheetIndex = ExcelImportSupport.findSheetIndex(file, "股权冻结", 0);
file, CreditJudicialImportParam.class, this::isEmptyImportRow); ExcelImportSupport.ImportResult<CreditGqdjImportParam> importResult = ExcelImportSupport.read(
List<CreditJudicialImportParam> list = importResult.getData(); file, CreditGqdjImportParam.class, this::isEmptyImportRow, sheetIndex);
List<CreditGqdjImportParam> list = importResult.getData();
int usedTitleRows = importResult.getTitleRows(); int usedTitleRows = importResult.getTitleRows();
int usedHeadRows = importResult.getHeadRows(); int usedHeadRows = importResult.getHeadRows();
int usedSheetIndex = importResult.getSheetIndex();
if (CollectionUtils.isEmpty(list)) { if (CollectionUtils.isEmpty(list)) {
return fail("未读取到数据,请确认模板表头与示例格式一致", null); return fail("未读取到数据,请确认模板表头与示例格式一致", null);
@@ -157,6 +211,25 @@ public class CreditGqdjController extends BaseController {
User loginUser = getLoginUser(); User loginUser = getLoginUser();
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null; Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null; Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
// easypoi 默认不会读取单元格超链接地址url 通常挂在“执行通知文书号”列的超链接中,需要额外读取回填。
String caseNumberHeader = "执行通知文书号";
Map<String, String> urlByCaseNumber = ExcelImportSupport.readHyperlinksByHeaderKey(
file, usedSheetIndex, usedTitleRows, usedHeadRows, caseNumberHeader);
// 有些源文件会单独提供“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, "链接");
}
final int chunkSize = 500; final int chunkSize = 500;
final int mpBatchSize = 500; final int mpBatchSize = 500;
@@ -164,13 +237,26 @@ public class CreditGqdjController extends BaseController {
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize); List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
for (int i = 0; i < list.size(); i++) { for (int i = 0; i < list.size(); i++) {
CreditJudicialImportParam param = list.get(i); CreditGqdjImportParam param = list.get(i);
try { try {
CreditGqdj item = convertImportParamToEntity(param); 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) { if (item.getCompanyId() == null && companyId != null) {
item.setCompanyId(companyId); item.setCompanyId(companyId);
} }
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
touchedCompanyIds.add(item.getCompanyId());
}
if (item.getUserId() == null && currentUserId != null) { if (item.getUserId() == null && currentUserId != null) {
item.setUserId(currentUserId); item.setUserId(currentUserId);
} }
@@ -193,6 +279,10 @@ public class CreditGqdjController extends BaseController {
continue; continue;
} }
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
touchedCompanyIds.add(item.getCompanyId());
}
chunkItems.add(item); chunkItems.add(item);
chunkRowNumbers.add(excelRowNumber); chunkRowNumbers.add(excelRowNumber);
if (chunkItems.size() >= chunkSize) { if (chunkItems.size() >= chunkSize) {
@@ -277,6 +367,8 @@ public class CreditGqdjController extends BaseController {
); );
} }
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.GQDJ, touchedCompanyIds);
if (errorMessages.isEmpty()) { if (errorMessages.isEmpty()) {
return success("成功导入" + successCount + "条数据", null); return success("成功导入" + successCount + "条数据", null);
} else { } else {
@@ -288,29 +380,249 @@ public class CreditGqdjController extends BaseController {
} }
} }
/**
* 批量导入历史股权冻结(仅解析“历史股权冻结”选项卡)
* 规则:执行通知文书号/案号相同则覆盖更新recommend++ 记录更新次数);不存在则插入。
*/
@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.read(
file, CreditGqdjImportParam.class, this::isEmptyImportRow, 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> 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, "链接");
}
LinkedHashMap<String, CreditGqdj> latestByCaseNumber = new LinkedHashMap<>();
LinkedHashMap<String, Integer> latestRowByCaseNumber = new LinkedHashMap<>();
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);
}
latestByCaseNumber.put(item.getCaseNumber(), item);
latestRowByCaseNumber.put(item.getCaseNumber(), excelRowNumber);
} catch (Exception e) {
errorMessages.add("" + excelRowNumber + "行:" + e.getMessage());
e.printStackTrace();
}
}
if (latestByCaseNumber.isEmpty()) {
if (errorMessages.isEmpty()) {
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
}
return success("导入完成成功0条失败" + errorMessages.size() + "", errorMessages);
}
final int chunkSize = 500;
final int mpBatchSize = 500;
List<CreditGqdj> chunkItems = new ArrayList<>(chunkSize);
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
for (Map.Entry<String, CreditGqdj> entry : latestByCaseNumber.entrySet()) {
String caseNumber = entry.getKey();
CreditGqdj item = entry.getValue();
Integer rowNo = latestRowByCaseNumber.get(caseNumber);
chunkItems.add(item);
chunkRowNumbers.add(rowNo != null ? rowNo : -1);
if (chunkItems.size() >= chunkSize) {
successCount += batchImportSupport.persistChunkWithFallback(
chunkItems,
chunkRowNumbers,
() -> batchImportSupport.upsertBySingleKeyAndIncrementCounterOnUpdate(
creditGqdjService,
chunkItems,
CreditGqdj::getId,
CreditGqdj::setId,
CreditGqdj::getCaseNumber,
CreditGqdj::getCaseNumber,
CreditGqdj::getRecommend,
CreditGqdj::setRecommend,
null,
mpBatchSize
),
(rowItem, rowNumber) -> {
if (rowItem.getRecommend() == null) {
rowItem.setRecommend(0);
}
boolean saved = creditGqdjService.save(rowItem);
if (!saved) {
CreditGqdj existing = creditGqdjService.lambdaQuery()
.eq(CreditGqdj::getCaseNumber, rowItem.getCaseNumber())
.select(CreditGqdj::getId, CreditGqdj::getRecommend)
.one();
if (existing != null) {
rowItem.setId(existing.getId());
Integer old = existing.getRecommend();
rowItem.setRecommend(old == null ? 1 : old + 1);
if (creditGqdjService.updateById(rowItem)) {
return true;
}
}
} else {
return true;
}
String prefix = rowNumber > 0 ? ("" + rowNumber + "行:") : "";
errorMessages.add(prefix + "保存失败");
return false;
},
errorMessages
);
chunkItems.clear();
chunkRowNumbers.clear();
}
}
if (!chunkItems.isEmpty()) {
successCount += batchImportSupport.persistChunkWithFallback(
chunkItems,
chunkRowNumbers,
() -> batchImportSupport.upsertBySingleKeyAndIncrementCounterOnUpdate(
creditGqdjService,
chunkItems,
CreditGqdj::getId,
CreditGqdj::setId,
CreditGqdj::getCaseNumber,
CreditGqdj::getCaseNumber,
CreditGqdj::getRecommend,
CreditGqdj::setRecommend,
null,
mpBatchSize
),
(rowItem, rowNumber) -> {
if (rowItem.getRecommend() == null) {
rowItem.setRecommend(0);
}
boolean saved = creditGqdjService.save(rowItem);
if (!saved) {
CreditGqdj existing = creditGqdjService.lambdaQuery()
.eq(CreditGqdj::getCaseNumber, rowItem.getCaseNumber())
.select(CreditGqdj::getId, CreditGqdj::getRecommend)
.one();
if (existing != null) {
rowItem.setId(existing.getId());
Integer old = existing.getRecommend();
rowItem.setRecommend(old == null ? 1 : old + 1);
if (creditGqdjService.updateById(rowItem)) {
return true;
}
}
} else {
return true;
}
String prefix = rowNumber > 0 ? ("" + rowNumber + "行:") : "";
errorMessages.add(prefix + "保存失败");
return false;
},
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 = "下载股权冻结导入模板") @Operation(summary = "下载股权冻结导入模板")
@GetMapping("/import/template") @GetMapping("/import/template")
public void downloadTemplate(HttpServletResponse response) throws IOException { public void downloadTemplate(HttpServletResponse response) throws IOException {
List<CreditJudicialImportParam> templateList = new ArrayList<>(); List<CreditGqdjImportParam> templateList = new ArrayList<>();
CreditJudicialImportParam example = new CreditJudicialImportParam(); CreditGqdjImportParam example = new CreditGqdjImportParam();
example.setDataType("股权冻结"); example.setDataType("股权冻结");
example.setPlaintiffAppellant("原告示例"); example.setPlaintiffAppellant("原告示例");
example.setAppellee("被告示例"); example.setAppellee("被告示例");
example.setOtherPartiesThirdParty("第三人示例");
example.setOccurrenceTime("2024-01-01");
example.setCaseNumber("2024示例案号"); example.setCaseNumber("2024示例案号");
example.setCauseOfAction("案由示例");
example.setInvolvedAmount("100000"); example.setInvolvedAmount("100000");
example.setCourtName("示例法院"); example.setCourtName("示例法院");
example.setDataStatus("已公开"); example.setDataStatus("已公开");
example.setComments("备注信息");
templateList.add(example); templateList.add(example);
Workbook workbook = ExcelImportSupport.buildTemplate("股权冻结导入模板", "股权冻结", CreditJudicialImportParam.class, templateList); Workbook workbook = ExcelImportSupport.buildTemplate("股权冻结导入模板", "股权冻结", CreditGqdjImportParam.class, templateList);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment; filename=credit_gqdj_import_template.xlsx"); response.setHeader("Content-Disposition", "attachment; filename=credit_gqdj_import_template.xlsx");
@@ -319,30 +631,26 @@ public class CreditGqdjController extends BaseController {
workbook.close(); workbook.close();
} }
private boolean isEmptyImportRow(CreditJudicialImportParam param) { private boolean isEmptyImportRow(CreditGqdjImportParam param) {
if (param == null) { if (param == null) {
return true; return true;
} }
return ImportHelper.isBlank(param.getCaseNumber()) return ImportHelper.isBlank(param.getCaseNumber());
&& ImportHelper.isBlank(param.getPlaintiffAppellant())
&& ImportHelper.isBlank(param.getAppellee())
&& ImportHelper.isBlank(param.getCauseOfAction());
} }
private CreditGqdj convertImportParamToEntity(CreditJudicialImportParam param) { private CreditGqdj convertImportParamToEntity(CreditGqdjImportParam param) {
CreditGqdj entity = new CreditGqdj(); CreditGqdj entity = new CreditGqdj();
entity.setDataType(param.getDataType());
entity.setPlaintiffAppellant(param.getPlaintiffAppellant());
entity.setAppellee(param.getAppellee());
entity.setOtherPartiesThirdParty(param.getOtherPartiesThirdParty());
entity.setOccurrenceTime(param.getOccurrenceTime());
entity.setCaseNumber(param.getCaseNumber()); entity.setCaseNumber(param.getCaseNumber());
entity.setCauseOfAction(param.getCauseOfAction()); entity.setAppellee(param.getAppellee());
entity.setPlaintiffAppellant(param.getPlaintiffAppellant());
entity.setInvolvedAmount(param.getInvolvedAmount()); entity.setInvolvedAmount(param.getInvolvedAmount());
entity.setCourtName(param.getCourtName()); entity.setCourtName(param.getCourtName());
entity.setDataStatus(param.getDataStatus()); entity.setDataStatus(param.getDataStatus());
entity.setComments(param.getComments()); entity.setDataType("股权冻结");
entity.setPublicDate(param.getPublicDate());
entity.setFreezeDateStart(param.getFreezeDateStart());
entity.setFreezeDateEnd(param.getFreezeDateEnd());
return entity; return entity;
} }

View File

@@ -9,6 +9,8 @@ import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.credit.entity.CreditHistoricalLegalPerson; import com.gxwebsoft.credit.entity.CreditHistoricalLegalPerson;
import com.gxwebsoft.credit.param.CreditHistoricalLegalPersonImportParam; import com.gxwebsoft.credit.param.CreditHistoricalLegalPersonImportParam;
import com.gxwebsoft.credit.param.CreditHistoricalLegalPersonParam; 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 com.gxwebsoft.credit.service.CreditHistoricalLegalPersonService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@@ -22,8 +24,10 @@ import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
/** /**
* 历史法定代表人控制器 * 历史法定代表人控制器
@@ -41,6 +45,12 @@ public class CreditHistoricalLegalPersonController extends BaseController {
@Resource @Resource
private BatchImportSupport batchImportSupport; private BatchImportSupport batchImportSupport;
@Resource
private CreditCompanyService creditCompanyService;
@Resource
private CreditCompanyRecordCountService creditCompanyRecordCountService;
@Operation(summary = "分页查询历史法定代表人") @Operation(summary = "分页查询历史法定代表人")
@GetMapping("/page") @GetMapping("/page")
public ApiResult<PageResult<CreditHistoricalLegalPerson>> page(CreditHistoricalLegalPersonParam param) { public ApiResult<PageResult<CreditHistoricalLegalPerson>> page(CreditHistoricalLegalPersonParam param) {
@@ -133,6 +143,45 @@ public class CreditHistoricalLegalPersonController extends BaseController {
return fail("删除失败"); 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::getHasData,
CreditHistoricalLegalPerson::setHasData,
CreditHistoricalLegalPerson::getTenantId,
CreditHistoricalLegalPerson::new
);
if (!stats.anyDataRead) {
return success("无可更新数据", stats.toMap());
}
return success("更新完成,更新" + stats.updated + "", stats.toMap());
}
/** /**
* 批量导入历史法定代表人 * 批量导入历史法定代表人
*/ */
@@ -143,6 +192,7 @@ public class CreditHistoricalLegalPersonController extends BaseController {
@RequestParam(value = "companyId", required = false) Integer companyId) { @RequestParam(value = "companyId", required = false) Integer companyId) {
List<String> errorMessages = new ArrayList<>(); List<String> errorMessages = new ArrayList<>();
int successCount = 0; int successCount = 0;
Set<Integer> touchedCompanyIds = new HashSet<>();
try { try {
ExcelImportSupport.ImportResult<CreditHistoricalLegalPersonImportParam> importResult = ExcelImportSupport.readAnySheet( ExcelImportSupport.ImportResult<CreditHistoricalLegalPersonImportParam> importResult = ExcelImportSupport.readAnySheet(
@@ -202,6 +252,10 @@ public class CreditHistoricalLegalPersonController extends BaseController {
continue; continue;
} }
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
touchedCompanyIds.add(item.getCompanyId());
}
chunkItems.add(item); chunkItems.add(item);
chunkRowNumbers.add(excelRowNumber); chunkRowNumbers.add(excelRowNumber);
if (chunkItems.size() >= chunkSize) { if (chunkItems.size() >= chunkSize) {
@@ -381,6 +435,8 @@ public class CreditHistoricalLegalPersonController extends BaseController {
); );
} }
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.HISTORICAL_LEGAL_PERSON, touchedCompanyIds);
if (errorMessages.isEmpty()) { if (errorMessages.isEmpty()) {
return success("成功导入" + successCount + "条数据", null); return success("成功导入" + successCount + "条数据", null);
} else { } else {

View File

@@ -9,6 +9,8 @@ import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.credit.entity.CreditJudgmentDebtor; import com.gxwebsoft.credit.entity.CreditJudgmentDebtor;
import com.gxwebsoft.credit.param.CreditJudgmentDebtorImportParam; import com.gxwebsoft.credit.param.CreditJudgmentDebtorImportParam;
import com.gxwebsoft.credit.param.CreditJudgmentDebtorParam; 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 com.gxwebsoft.credit.service.CreditJudgmentDebtorService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@@ -29,8 +31,11 @@ import java.nio.charset.StandardCharsets;
import java.nio.file.Files; import java.nio.file.Files;
import java.util.Locale; import java.util.Locale;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream; import java.util.zip.ZipInputStream;
@@ -50,6 +55,12 @@ public class CreditJudgmentDebtorController extends BaseController {
@Resource @Resource
private BatchImportSupport batchImportSupport; private BatchImportSupport batchImportSupport;
@Resource
private CreditCompanyService creditCompanyService;
@Resource
private CreditCompanyRecordCountService creditCompanyRecordCountService;
@Operation(summary = "分页查询被执行人") @Operation(summary = "分页查询被执行人")
@GetMapping("/page") @GetMapping("/page")
public ApiResult<PageResult<CreditJudgmentDebtor>> page(CreditJudgmentDebtorParam param) { public ApiResult<PageResult<CreditJudgmentDebtor>> page(CreditJudgmentDebtorParam param) {
@@ -142,6 +153,45 @@ public class CreditJudgmentDebtorController extends BaseController {
return fail("删除失败"); 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
) {
User loginUser = getLoginUser();
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
creditJudgmentDebtorService,
creditCompanyService,
currentTenantId,
onlyNull,
limit,
CreditJudgmentDebtor::getId,
CreditJudgmentDebtor::setId,
CreditJudgmentDebtor::getName,
CreditJudgmentDebtor::getCompanyId,
CreditJudgmentDebtor::setCompanyId,
CreditJudgmentDebtor::getHasData,
CreditJudgmentDebtor::setHasData,
CreditJudgmentDebtor::getTenantId,
CreditJudgmentDebtor::new
);
if (!stats.anyDataRead) {
return success("无可更新数据", stats.toMap());
}
return success("更新完成,更新" + stats.updated + "", stats.toMap());
}
/** /**
* 批量导入被执行人 * 批量导入被执行人
*/ */
@@ -165,6 +215,46 @@ public class CreditJudgmentDebtorController extends BaseController {
if (!outcome.anyDataRead) { if (!outcome.anyDataRead) {
return fail("未读取到数据,请确认模板表头与示例格式一致", null); 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()) { if (outcome.errorMessages.isEmpty()) {
return success("成功导入" + outcome.successCount + "条数据", null); return success("成功导入" + outcome.successCount + "条数据", null);
} }
@@ -209,10 +299,7 @@ public class CreditJudgmentDebtorController extends BaseController {
if (isImportHeaderRow(param)) { if (isImportHeaderRow(param)) {
return true; return true;
} }
return ImportHelper.isBlank(param.getCaseNumber()) return ImportHelper.isBlank(param.getCaseNumber());
&& ImportHelper.isBlank(param.getName())
&& ImportHelper.isBlank(param.getName1())
&& ImportHelper.isBlank(param.getCode());
} }
private boolean isImportHeaderRow(CreditJudgmentDebtorImportParam param) { private boolean isImportHeaderRow(CreditJudgmentDebtorImportParam param) {
@@ -256,17 +343,20 @@ public class CreditJudgmentDebtorController extends BaseController {
private final boolean anyDataRead; private final boolean anyDataRead;
private final int successCount; private final int successCount;
private final List<String> errorMessages; private final List<String> errorMessages;
private final Set<Integer> touchedCompanyIds;
private ImportOutcome(boolean anyDataRead, int successCount, List<String> errorMessages) { private ImportOutcome(boolean anyDataRead, int successCount, List<String> errorMessages, Set<Integer> touchedCompanyIds) {
this.anyDataRead = anyDataRead; this.anyDataRead = anyDataRead;
this.successCount = successCount; this.successCount = successCount;
this.errorMessages = errorMessages; 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 { private ImportOutcome importFromExcel(MultipartFile excelFile, String fileLabel, Integer currentUserId, Integer currentTenantId, Integer companyId, boolean strictDebtorSheet) throws Exception {
List<String> errorMessages = new ArrayList<>(); List<String> errorMessages = new ArrayList<>();
int successCount = 0; int successCount = 0;
Set<Integer> touchedCompanyIds = new HashSet<>();
ExcelImportSupport.ImportResult<CreditJudgmentDebtorImportParam> importResult = readDebtorImport(excelFile, strictDebtorSheet); ExcelImportSupport.ImportResult<CreditJudgmentDebtorImportParam> importResult = readDebtorImport(excelFile, strictDebtorSheet);
List<CreditJudgmentDebtorImportParam> list = importResult.getData(); List<CreditJudgmentDebtorImportParam> list = importResult.getData();
@@ -275,7 +365,7 @@ public class CreditJudgmentDebtorController extends BaseController {
int usedSheetIndex = importResult.getSheetIndex(); int usedSheetIndex = importResult.getSheetIndex();
if (CollectionUtils.isEmpty(list)) { if (CollectionUtils.isEmpty(list)) {
return new ImportOutcome(false, 0, errorMessages); return new ImportOutcome(false, 0, errorMessages, touchedCompanyIds);
} }
Map<String, String> urlByCaseNumber = ExcelImportSupport.readHyperlinksByHeaderKey(excelFile, usedSheetIndex, usedTitleRows, usedHeadRows, "案号"); Map<String, String> urlByCaseNumber = ExcelImportSupport.readHyperlinksByHeaderKey(excelFile, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
@@ -308,6 +398,9 @@ public class CreditJudgmentDebtorController extends BaseController {
if (item.getCompanyId() == null && companyId != null) { if (item.getCompanyId() == null && companyId != null) {
item.setCompanyId(companyId); item.setCompanyId(companyId);
} }
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
touchedCompanyIds.add(item.getCompanyId());
}
if (item.getUserId() == null && currentUserId != null) { if (item.getUserId() == null && currentUserId != null) {
item.setUserId(currentUserId); item.setUserId(currentUserId);
} }
@@ -329,6 +422,10 @@ public class CreditJudgmentDebtorController extends BaseController {
continue; continue;
} }
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
touchedCompanyIds.add(item.getCompanyId());
}
chunkItems.add(item); chunkItems.add(item);
chunkRowNumbers.add(excelRowNumber); chunkRowNumbers.add(excelRowNumber);
if (chunkItems.size() >= chunkSize) { if (chunkItems.size() >= chunkSize) {
@@ -345,7 +442,226 @@ public class CreditJudgmentDebtorController extends BaseController {
if (!chunkItems.isEmpty()) { if (!chunkItems.isEmpty()) {
successCount += persistImportChunk(chunkItems, chunkRowNumbers, prefix, mpBatchSize, errorMessages); successCount += persistImportChunk(chunkItems, chunkRowNumbers, prefix, mpBatchSize, errorMessages);
} }
return new ImportOutcome(true, successCount, 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 + "";
// 同案号多条:以导入文件中“最后一条”为准(视为最新),避免批处理中重复 upsert。
LinkedHashMap<String, CreditJudgmentDebtor> latestByCaseNumber = new LinkedHashMap<>();
LinkedHashMap<String, Integer> latestRowByCaseNumber = new LinkedHashMap<>();
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.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);
}
latestByCaseNumber.put(item.getCaseNumber(), item);
latestRowByCaseNumber.put(item.getCaseNumber(), excelRowNumber);
} catch (Exception e) {
errorMessages.add(prefix + "" + excelRowNumber + "行:" + e.getMessage());
e.printStackTrace();
}
}
if (latestByCaseNumber.isEmpty()) {
return new ImportOutcome(true, 0, errorMessages, touchedCompanyIds);
}
final int chunkSize = 500;
final int mpBatchSize = 500;
List<CreditJudgmentDebtor> chunkItems = new ArrayList<>(chunkSize);
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
for (Map.Entry<String, CreditJudgmentDebtor> entry : latestByCaseNumber.entrySet()) {
String caseNumber = entry.getKey();
CreditJudgmentDebtor item = entry.getValue();
Integer rowNo = latestRowByCaseNumber.get(caseNumber);
chunkItems.add(item);
chunkRowNumbers.add(rowNo != null ? rowNo : -1);
if (chunkItems.size() >= chunkSize) {
successCount += persistHistoryImportChunk(chunkItems, chunkRowNumbers, prefix, mpBatchSize, errorMessages);
chunkItems.clear();
chunkRowNumbers.clear();
}
}
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) {
if (CollectionUtils.isEmpty(items)) {
return 0;
}
try {
return batchImportSupport.runInNewTx(() -> {
List<String> keys = new ArrayList<>(items.size());
for (CreditJudgmentDebtor item : items) {
if (item == null || ImportHelper.isBlank(item.getCaseNumber())) {
continue;
}
keys.add(item.getCaseNumber().trim());
}
Map<String, CreditJudgmentDebtor> existingByCaseNumber = new java.util.HashMap<>();
if (!keys.isEmpty()) {
List<CreditJudgmentDebtor> existingList = creditJudgmentDebtorService.lambdaQuery()
.in(CreditJudgmentDebtor::getCaseNumber, keys)
.select(CreditJudgmentDebtor::getId, CreditJudgmentDebtor::getCaseNumber, CreditJudgmentDebtor::getRecommend)
.list();
for (CreditJudgmentDebtor existing : existingList) {
if (existing == null || ImportHelper.isBlank(existing.getCaseNumber())) {
continue;
}
existingByCaseNumber.putIfAbsent(existing.getCaseNumber().trim(), existing);
}
}
List<CreditJudgmentDebtor> updates = new ArrayList<>();
List<CreditJudgmentDebtor> inserts = new ArrayList<>();
for (CreditJudgmentDebtor item : items) {
if (item == null || ImportHelper.isBlank(item.getCaseNumber())) {
continue;
}
String caseNumber = item.getCaseNumber().trim();
CreditJudgmentDebtor existing = existingByCaseNumber.get(caseNumber);
if (existing != null && existing.getId() != null) {
// 覆盖更新recommend 记录“被更新次数”,每次更新 +1
item.setId(existing.getId());
Integer old = existing.getRecommend();
item.setRecommend(old == null ? 1 : old + 1);
updates.add(item);
} else {
if (item.getRecommend() == null) {
item.setRecommend(0);
}
inserts.add(item);
}
}
if (!updates.isEmpty()) {
creditJudgmentDebtorService.updateBatchById(updates, mpBatchSize);
}
if (!inserts.isEmpty()) {
creditJudgmentDebtorService.saveBatch(inserts, mpBatchSize);
}
return updates.size() + inserts.size();
});
} catch (Exception batchException) {
int successCount = 0;
for (int i = 0; i < items.size(); i++) {
CreditJudgmentDebtor item = items.get(i);
int excelRowNumber = (excelRowNumbers != null && i < excelRowNumbers.size()) ? excelRowNumbers.get(i) : -1;
try {
int delta = batchImportSupport.runInNewTx(() -> {
if (item == null || ImportHelper.isBlank(item.getCaseNumber())) {
return 0;
}
String caseNumber = item.getCaseNumber().trim();
CreditJudgmentDebtor existing = creditJudgmentDebtorService.lambdaQuery()
.eq(CreditJudgmentDebtor::getCaseNumber, caseNumber)
.select(CreditJudgmentDebtor::getId, CreditJudgmentDebtor::getRecommend)
.one();
if (existing != null && existing.getId() != null) {
item.setId(existing.getId());
Integer old = existing.getRecommend();
item.setRecommend(old == null ? 1 : old + 1);
return creditJudgmentDebtorService.updateById(item) ? 1 : 0;
}
if (item.getRecommend() == null) {
item.setRecommend(0);
}
return creditJudgmentDebtorService.save(item) ? 1 : 0;
});
if (delta > 0) {
successCount += delta;
} else {
errorMessages.add(prefix + "" + excelRowNumber + "行:保存失败");
}
} catch (Exception e) {
errorMessages.add(prefix + "" + excelRowNumber + "行:" + e.getMessage());
}
}
return successCount;
}
} }
private int persistImportChunk(List<CreditJudgmentDebtor> items, private int persistImportChunk(List<CreditJudgmentDebtor> items,
@@ -415,6 +731,7 @@ public class CreditJudgmentDebtorController extends BaseController {
List<String> errorMessages = new ArrayList<>(); List<String> errorMessages = new ArrayList<>();
int successCount = 0; int successCount = 0;
boolean anyDataRead = false; boolean anyDataRead = false;
Set<Integer> touchedCompanyIds = new HashSet<>();
try (InputStream is = zipFile.getInputStream(); ZipInputStream zis = new ZipInputStream(is, charset)) { try (InputStream is = zipFile.getInputStream(); ZipInputStream zis = new ZipInputStream(is, charset)) {
ZipEntry entry; ZipEntry entry;
@@ -437,13 +754,59 @@ public class CreditJudgmentDebtorController extends BaseController {
anyDataRead = true; anyDataRead = true;
successCount += outcome.successCount; successCount += outcome.successCount;
errorMessages.addAll(outcome.errorMessages); errorMessages.addAll(outcome.errorMessages);
touchedCompanyIds.addAll(outcome.touchedCompanyIds);
} }
} catch (Exception e) { } catch (Exception e) {
errorMessages.add("" + entryFileName + "】解析失败:" + e.getMessage()); errorMessages.add("" + entryFileName + "】解析失败:" + e.getMessage());
} }
} }
} }
return new ImportOutcome(anyDataRead, successCount, errorMessages); 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) { private static boolean isZip(MultipartFile file) {
@@ -485,27 +848,43 @@ public class CreditJudgmentDebtorController extends BaseController {
} }
private List<Integer> findDebtorSheetIndices(MultipartFile excelFile) throws Exception { 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<>(); List<Integer> indices = new ArrayList<>();
try (InputStream is = excelFile.getInputStream(); Workbook workbook = WorkbookFactory.create(is)) { try (InputStream is = excelFile.getInputStream(); Workbook workbook = WorkbookFactory.create(is)) {
int sheetCount = workbook.getNumberOfSheets(); int sheetCount = workbook.getNumberOfSheets();
for (int i = 0; i < sheetCount; i++) { for (int i = 0; i < sheetCount; i++) {
String sheetName = workbook.getSheetName(i); String sheetName = workbook.getSheetName(i);
if (isDebtorSheetName(sheetName)) { if (!isDebtorSheetName(sheetName)) {
continue;
}
String normalized = normalizeSheetName(sheetName);
if ("被执行人".equals(normalized)) {
preferred.add(i);
} else {
indices.add(i); indices.add(i);
} }
} }
} }
return indices; preferred.addAll(indices);
return preferred;
} }
private static boolean isDebtorSheetName(String sheetName) { private static boolean isDebtorSheetName(String sheetName) {
if (sheetName == null) { if (sheetName == null) {
return false; return false;
} }
String normalized = sheetName.replace(" ", "").trim(); String normalized = normalizeSheetName(sheetName);
return normalized.contains("被执行人") && !normalized.contains("失信") && !normalized.contains("历史"); 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) { private static boolean isExcelFileName(String name) {
if (name == null) { if (name == null) {
return false; return false;

View File

@@ -1,604 +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.CreditJudgmentDebtorHistory;
import com.gxwebsoft.credit.param.CreditJudgmentDebtorHistoryImportParam;
import com.gxwebsoft.credit.param.CreditJudgmentDebtorHistoryParam;
import com.gxwebsoft.credit.service.CreditJudgmentDebtorHistoryService;
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.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
/**
* 被执行人控制器
*
* @author 科技小王子
* @since 2026-01-12 08:10:44
*/
@Tag(name = "被执行人管理")
@RestController
@RequestMapping("/api/credit/credit-judgment-debtor-history")
public class CreditJudgmentDebtorHistoryController extends BaseController {
@Resource
private CreditJudgmentDebtorHistoryService creditJudgmentDebtorHistoryService;
@Resource
private BatchImportSupport batchImportSupport;
@Operation(summary = "分页查询被执行人")
@GetMapping("/page")
public ApiResult<PageResult<CreditJudgmentDebtorHistory>> page(CreditJudgmentDebtorHistoryParam param) {
// 使用关联查询
return success(creditJudgmentDebtorHistoryService.pageRel(param));
}
@Operation(summary = "查询全部被执行人")
@GetMapping()
public ApiResult<List<CreditJudgmentDebtorHistory>> list(CreditJudgmentDebtorHistoryParam param) {
// 使用关联查询
return success(creditJudgmentDebtorHistoryService.listRel(param));
}
@Operation(summary = "根据id查询被执行人")
@GetMapping("/{id}")
public ApiResult<CreditJudgmentDebtorHistory> get(@PathVariable("id") Integer id) {
// 使用关联查询
return success(creditJudgmentDebtorHistoryService.getByIdRel(id));
}
@PreAuthorize("hasAuthority('credit:creditJudgmentDebtorHistory:save')")
@OperationLog
@Operation(summary = "添加被执行人")
@PostMapping()
public ApiResult<?> save(@RequestBody CreditJudgmentDebtorHistory creditJudgmentDebtorHistory) {
if (creditJudgmentDebtorHistoryService.save(creditJudgmentDebtorHistory)) {
return success("添加成功");
}
return fail("添加失败");
}
@PreAuthorize("hasAuthority('credit:creditJudgmentDebtorHistory:update')")
@OperationLog
@Operation(summary = "修改被执行人")
@PutMapping()
public ApiResult<?> update(@RequestBody CreditJudgmentDebtorHistory creditJudgmentDebtorHistory) {
if (creditJudgmentDebtorHistoryService.updateById(creditJudgmentDebtorHistory)) {
return success("修改成功");
}
return fail("修改失败");
}
@PreAuthorize("hasAuthority('credit:creditJudgmentDebtorHistory:remove')")
@OperationLog
@Operation(summary = "删除被执行人")
@DeleteMapping("/{id}")
public ApiResult<?> remove(@PathVariable("id") Integer id) {
if (creditJudgmentDebtorHistoryService.removeById(id)) {
return success("删除成功");
}
return fail("删除失败");
}
@PreAuthorize("hasAuthority('credit:creditJudgmentDebtorHistory:save')")
@OperationLog
@Operation(summary = "批量添加被执行人")
@PostMapping("/batch")
public ApiResult<?> saveBatch(@RequestBody List<CreditJudgmentDebtorHistory> list) {
if (creditJudgmentDebtorHistoryService.saveBatch(list)) {
return success("添加成功");
}
return fail("添加失败");
}
@PreAuthorize("hasAuthority('credit:creditJudgmentDebtorHistory:update')")
@OperationLog
@Operation(summary = "批量修改被执行人")
@PutMapping("/batch")
public ApiResult<?> removeBatch(@RequestBody BatchParam<CreditJudgmentDebtorHistory> batchParam) {
if (batchParam.update(creditJudgmentDebtorHistoryService, "id")) {
return success("修改成功");
}
return fail("修改失败");
}
@PreAuthorize("hasAuthority('credit:creditJudgmentDebtorHistory:remove')")
@OperationLog
@Operation(summary = "批量删除被执行人")
@DeleteMapping("/batch")
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
if (creditJudgmentDebtorHistoryService.removeByIds(ids)) {
return success("删除成功");
}
return fail("删除失败");
}
/**
* 批量导入被执行人历史
*/
@PreAuthorize("hasAuthority('credit:creditJudgmentDebtorHistory: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);
}
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<CreditJudgmentDebtorHistoryImportParam> templateList = new ArrayList<>();
CreditJudgmentDebtorHistoryImportParam example = new CreditJudgmentDebtorHistoryImportParam();
example.setCaseNumber("2024示例案号");
example.setName("某某公司");
example.setCode("1234567890");
example.setOccurrenceTime("2024-01-10");
example.setAmount("100000");
example.setDataStatus("已公开");
example.setComments("备注信息");
templateList.add(example);
Workbook workbook = ExcelImportSupport.buildTemplate("被执行人历史导入模板", "历史被执行人", CreditJudgmentDebtorHistoryImportParam.class, templateList);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment; filename=credit_judgment_debtor_history_import_template.xlsx");
workbook.write(response.getOutputStream());
workbook.close();
}
private boolean isEmptyImportRow(CreditJudgmentDebtorHistoryImportParam param) {
if (param == null) {
return true;
}
if (isImportHeaderRow(param)) {
return true;
}
return ImportHelper.isBlank(param.getCaseNumber())
&& ImportHelper.isBlank(param.getName())
&& ImportHelper.isBlank(param.getName1())
&& ImportHelper.isBlank(param.getCode());
}
private boolean isImportHeaderRow(CreditJudgmentDebtorHistoryImportParam 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.getAmount(), "执行标的(元)")
|| isHeaderValue(param.getDataStatus(), "数据状态");
}
private static boolean isHeaderValue(String value, String headerText) {
if (value == null) {
return false;
}
return headerText.equals(value.trim());
}
private CreditJudgmentDebtorHistory convertImportParamToEntity(CreditJudgmentDebtorHistoryImportParam param) {
CreditJudgmentDebtorHistory entity = new CreditJudgmentDebtorHistory();
entity.setCaseNumber(param.getCaseNumber());
entity.setName1(param.getName1());
String debtorName = ImportHelper.isBlank(param.getName()) ? param.getName1() : param.getName();
entity.setName(debtorName);
entity.setCode(param.getCode());
entity.setOccurrenceTime(param.getOccurrenceTime());
entity.setAmount(param.getAmount());
entity.setCourtName(param.getCourtName());
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 ImportOutcome(boolean anyDataRead, int successCount, List<String> errorMessages) {
this.anyDataRead = anyDataRead;
this.successCount = successCount;
this.errorMessages = errorMessages;
}
}
private ImportOutcome importFromExcel(MultipartFile excelFile, String fileLabel, Integer currentUserId, Integer currentTenantId, Integer companyId, boolean strictHistorySheet) throws Exception {
List<String> errorMessages = new ArrayList<>();
int successCount = 0;
ExcelImportSupport.ImportResult<CreditJudgmentDebtorHistoryImportParam> importResult = readHistoryImport(excelFile, strictHistorySheet);
List<CreditJudgmentDebtorHistoryImportParam> 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);
}
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<CreditJudgmentDebtorHistory> chunkItems = new ArrayList<>(chunkSize);
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
for (int i = 0; i < list.size(); i++) {
CreditJudgmentDebtorHistoryImportParam param = list.get(i);
try {
CreditJudgmentDebtorHistory 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.getUserId() == null && currentUserId != null) {
item.setUserId(currentUserId);
}
if (item.getTenantId() == null && currentTenantId != null) {
item.setTenantId(currentTenantId);
}
if (item.getType() == null) {
item.setType(0);
}
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;
}
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);
}
private int persistImportChunk(List<CreditJudgmentDebtorHistory> items,
List<Integer> excelRowNumbers,
String prefix,
int mpBatchSize,
List<String> errorMessages) {
if (CollectionUtils.isEmpty(items)) {
return 0;
}
try {
return batchImportSupport.runInNewTx(() -> batchImportSupport.upsertBySingleKey(
creditJudgmentDebtorHistoryService,
items,
CreditJudgmentDebtorHistory::getId,
CreditJudgmentDebtorHistory::setId,
CreditJudgmentDebtorHistory::getCaseNumber,
CreditJudgmentDebtorHistory::getCaseNumber,
null,
mpBatchSize
));
} catch (Exception batchException) {
int successCount = 0;
for (int i = 0; i < items.size(); i++) {
CreditJudgmentDebtorHistory item = items.get(i);
int excelRowNumber = (excelRowNumbers != null && i < excelRowNumbers.size()) ? excelRowNumbers.get(i) : -1;
try {
int delta = batchImportSupport.runInNewTx(() -> {
boolean saved = creditJudgmentDebtorHistoryService.save(item);
if (!saved) {
CreditJudgmentDebtorHistory existing = creditJudgmentDebtorHistoryService.lambdaQuery()
.eq(CreditJudgmentDebtorHistory::getCaseNumber, item.getCaseNumber())
.one();
if (existing != null) {
item.setId(existing.getId());
if (creditJudgmentDebtorHistoryService.updateById(item)) {
return 1;
}
}
} else {
return 1;
}
return 0;
});
if (delta > 0) {
successCount += delta;
} else {
errorMessages.add(prefix + "" + excelRowNumber + "行:保存失败");
}
} catch (Exception e) {
errorMessages.add(prefix + "" + excelRowNumber + "行:" + e.getMessage());
}
}
return successCount;
}
}
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;
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);
}
} catch (Exception e) {
errorMessages.add("" + entryFileName + "】解析失败:" + e.getMessage());
}
}
}
return new ImportOutcome(anyDataRead, successCount, errorMessages);
}
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<CreditJudgmentDebtorHistoryImportParam> readHistoryImport(MultipartFile excelFile, boolean strictHistorySheet) throws Exception {
int namedSheetIndex = ExcelImportSupport.findSheetIndex(excelFile, "历史被执行人");
if (namedSheetIndex >= 0) {
ExcelImportSupport.ImportResult<CreditJudgmentDebtorHistoryImportParam> namedSheetResult = ExcelImportSupport.readBest(
excelFile,
CreditJudgmentDebtorHistoryImportParam.class,
this::isEmptyImportRow,
this::isScoreImportRow,
namedSheetIndex
);
if (!CollectionUtils.isEmpty(namedSheetResult.getData())) {
return namedSheetResult;
}
}
List<Integer> historySheetIndices = findHistorySheetIndices(excelFile);
for (Integer sheetIndex : historySheetIndices) {
if (sheetIndex != null && sheetIndex == namedSheetIndex) {
continue;
}
ExcelImportSupport.ImportResult<CreditJudgmentDebtorHistoryImportParam> sheetResult = ExcelImportSupport.readBest(
excelFile,
CreditJudgmentDebtorHistoryImportParam.class,
this::isEmptyImportRow,
this::isScoreImportRow,
sheetIndex
);
if (!CollectionUtils.isEmpty(sheetResult.getData())) {
return sheetResult;
}
}
if (strictHistorySheet) {
return new ExcelImportSupport.ImportResult<>(new ArrayList<>(), 0, 0);
}
return ExcelImportSupport.readAnySheetBest(excelFile, CreditJudgmentDebtorHistoryImportParam.class, this::isEmptyImportRow, this::isScoreImportRow);
}
private boolean isScoreImportRow(CreditJudgmentDebtorHistoryImportParam param) {
if (param == null) {
return false;
}
if (isImportHeaderRow(param)) {
return false;
}
return !ImportHelper.isBlank(param.getCaseNumber());
}
private List<Integer> findHistorySheetIndices(MultipartFile excelFile) throws Exception {
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 (isHistorySheetName(sheetName)) {
indices.add(i);
}
}
}
return indices;
}
private static boolean isHistorySheetName(String sheetName) {
if (sheetName == null) {
return false;
}
String normalized = sheetName.replace(" ", "").trim();
return normalized.contains("被执行人") && normalized.contains("历史") && !normalized.contains("失信");
}
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);
}
}
}

View File

@@ -7,8 +7,10 @@ import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.common.core.web.PageResult; import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.system.entity.User; import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.credit.entity.CreditJudicialDocument; import com.gxwebsoft.credit.entity.CreditJudicialDocument;
import com.gxwebsoft.credit.param.CreditJudicialDocumentImportParam;
import com.gxwebsoft.credit.param.CreditJudicialDocumentParam; import com.gxwebsoft.credit.param.CreditJudicialDocumentParam;
import com.gxwebsoft.credit.param.CreditJudicialImportParam; import com.gxwebsoft.credit.service.CreditCompanyService;
import com.gxwebsoft.credit.service.CreditCompanyRecordCountService;
import com.gxwebsoft.credit.service.CreditJudicialDocumentService; import com.gxwebsoft.credit.service.CreditJudicialDocumentService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@@ -22,7 +24,11 @@ import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set;
/** /**
* 裁判文书司法大数据控制器 * 裁判文书司法大数据控制器
@@ -40,6 +46,12 @@ public class CreditJudicialDocumentController extends BaseController {
@Resource @Resource
private BatchImportSupport batchImportSupport; private BatchImportSupport batchImportSupport;
@Resource
private CreditCompanyService creditCompanyService;
@Resource
private CreditCompanyRecordCountService creditCompanyRecordCountService;
@Operation(summary = "分页查询裁判文书司法大数据") @Operation(summary = "分页查询裁判文书司法大数据")
@GetMapping("/page") @GetMapping("/page")
public ApiResult<PageResult<CreditJudicialDocument>> page(CreditJudicialDocumentParam param) { public ApiResult<PageResult<CreditJudicialDocument>> page(CreditJudicialDocumentParam param) {
@@ -132,6 +144,45 @@ public class CreditJudicialDocumentController extends BaseController {
return fail("删除失败"); 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.refreshCompanyIdByCompanyName(
creditJudicialDocumentService,
creditCompanyService,
currentTenantId,
onlyNull,
limit,
CreditJudicialDocument::getId,
CreditJudicialDocument::setId,
CreditJudicialDocument::getAppellee,
CreditJudicialDocument::getCompanyId,
CreditJudicialDocument::setCompanyId,
CreditJudicialDocument::getHasData,
CreditJudicialDocument::setHasData,
CreditJudicialDocument::getTenantId,
CreditJudicialDocument::new
);
if (!stats.anyDataRead) {
return success("无可更新数据", stats.toMap());
}
return success("更新完成,更新" + stats.updated + "", stats.toMap());
}
/** /**
* 批量导入裁判文书司法大数据 * 批量导入裁判文书司法大数据
*/ */
@@ -142,13 +193,17 @@ public class CreditJudicialDocumentController extends BaseController {
@RequestParam(value = "companyId", required = false) Integer companyId) { @RequestParam(value = "companyId", required = false) Integer companyId) {
List<String> errorMessages = new ArrayList<>(); List<String> errorMessages = new ArrayList<>();
int successCount = 0; int successCount = 0;
Set<Integer> touchedCompanyIds = new HashSet<>();
try { try {
ExcelImportSupport.ImportResult<CreditJudicialImportParam> importResult = ExcelImportSupport.read( // 支持按选项卡名称导入默认读取“裁判文书”sheet不存在则回退到第 0 个sheet
file, CreditJudicialImportParam.class, this::isEmptyImportRow); int sheetIndex = ExcelImportSupport.findSheetIndex(file, "裁判文书", 0);
List<CreditJudicialImportParam> list = importResult.getData(); ExcelImportSupport.ImportResult<CreditJudicialDocumentImportParam> importResult = ExcelImportSupport.read(
file, CreditJudicialDocumentImportParam.class, this::isEmptyImportRow, sheetIndex);
List<CreditJudicialDocumentImportParam> list = importResult.getData();
int usedTitleRows = importResult.getTitleRows(); int usedTitleRows = importResult.getTitleRows();
int usedHeadRows = importResult.getHeadRows(); int usedHeadRows = importResult.getHeadRows();
int usedSheetIndex = importResult.getSheetIndex();
if (CollectionUtils.isEmpty(list)) { if (CollectionUtils.isEmpty(list)) {
return fail("未读取到数据,请确认模板表头与示例格式一致", null); return fail("未读取到数据,请确认模板表头与示例格式一致", null);
@@ -157,6 +212,8 @@ public class CreditJudicialDocumentController extends BaseController {
User loginUser = getLoginUser(); User loginUser = getLoginUser();
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null; Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : 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 chunkSize = 500;
final int mpBatchSize = 500; final int mpBatchSize = 500;
@@ -164,13 +221,26 @@ public class CreditJudicialDocumentController extends BaseController {
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize); List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
for (int i = 0; i < list.size(); i++) { for (int i = 0; i < list.size(); i++) {
CreditJudicialImportParam param = list.get(i); CreditJudicialDocumentImportParam param = list.get(i);
try { try {
CreditJudicialDocument item = convertImportParamToEntity(param); 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) { if (item.getCompanyId() == null && companyId != null) {
item.setCompanyId(companyId); item.setCompanyId(companyId);
} }
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
touchedCompanyIds.add(item.getCompanyId());
}
if (item.getUserId() == null && currentUserId != null) { if (item.getUserId() == null && currentUserId != null) {
item.setUserId(currentUserId); item.setUserId(currentUserId);
} }
@@ -193,6 +263,10 @@ public class CreditJudicialDocumentController extends BaseController {
continue; continue;
} }
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
touchedCompanyIds.add(item.getCompanyId());
}
chunkItems.add(item); chunkItems.add(item);
chunkRowNumbers.add(excelRowNumber); chunkRowNumbers.add(excelRowNumber);
if (chunkItems.size() >= chunkSize) { if (chunkItems.size() >= chunkSize) {
@@ -277,6 +351,8 @@ public class CreditJudicialDocumentController extends BaseController {
); );
} }
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.JUDICIAL_DOCUMENT, touchedCompanyIds);
if (errorMessages.isEmpty()) { if (errorMessages.isEmpty()) {
return success("成功导入" + successCount + "条数据", null); return success("成功导入" + successCount + "条数据", null);
} else { } else {
@@ -288,29 +364,238 @@ public class CreditJudicialDocumentController extends BaseController {
} }
} }
/**
* 批量导入历史裁判文书(仅解析“历史裁判文书”选项卡)
* 规则案号相同则覆盖更新recommend++ 记录更新次数);案号不存在则插入。
*/
@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, "文书标题");
LinkedHashMap<String, CreditJudicialDocument> latestByCaseNumber = new LinkedHashMap<>();
LinkedHashMap<String, Integer> latestRowByCaseNumber = new LinkedHashMap<>();
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);
}
latestByCaseNumber.put(item.getCaseNumber(), item);
latestRowByCaseNumber.put(item.getCaseNumber(), excelRowNumber);
} catch (Exception e) {
errorMessages.add("" + excelRowNumber + "行:" + e.getMessage());
e.printStackTrace();
}
}
if (latestByCaseNumber.isEmpty()) {
if (errorMessages.isEmpty()) {
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
}
return success("导入完成成功0条失败" + errorMessages.size() + "", errorMessages);
}
final int chunkSize = 500;
final int mpBatchSize = 500;
List<CreditJudicialDocument> chunkItems = new ArrayList<>(chunkSize);
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
for (Map.Entry<String, CreditJudicialDocument> entry : latestByCaseNumber.entrySet()) {
String caseNumber = entry.getKey();
CreditJudicialDocument item = entry.getValue();
Integer rowNo = latestRowByCaseNumber.get(caseNumber);
chunkItems.add(item);
chunkRowNumbers.add(rowNo != null ? rowNo : -1);
if (chunkItems.size() >= chunkSize) {
successCount += batchImportSupport.persistChunkWithFallback(
chunkItems,
chunkRowNumbers,
() -> batchImportSupport.upsertBySingleKeyAndIncrementCounterOnUpdate(
creditJudicialDocumentService,
chunkItems,
CreditJudicialDocument::getId,
CreditJudicialDocument::setId,
CreditJudicialDocument::getCaseNumber,
CreditJudicialDocument::getCaseNumber,
CreditJudicialDocument::getRecommend,
CreditJudicialDocument::setRecommend,
null,
mpBatchSize
),
(rowItem, rowNumber) -> {
if (rowItem.getRecommend() == null) {
rowItem.setRecommend(0);
}
boolean saved = creditJudicialDocumentService.save(rowItem);
if (!saved) {
CreditJudicialDocument existing = creditJudicialDocumentService.lambdaQuery()
.eq(CreditJudicialDocument::getCaseNumber, rowItem.getCaseNumber())
.select(CreditJudicialDocument::getId, CreditJudicialDocument::getRecommend)
.one();
if (existing != null) {
rowItem.setId(existing.getId());
Integer old = existing.getRecommend();
rowItem.setRecommend(old == null ? 1 : old + 1);
if (creditJudicialDocumentService.updateById(rowItem)) {
return true;
}
}
} else {
return true;
}
String prefix = rowNumber > 0 ? ("" + rowNumber + "行:") : "";
errorMessages.add(prefix + "保存失败");
return false;
},
errorMessages
);
chunkItems.clear();
chunkRowNumbers.clear();
}
}
if (!chunkItems.isEmpty()) {
successCount += batchImportSupport.persistChunkWithFallback(
chunkItems,
chunkRowNumbers,
() -> batchImportSupport.upsertBySingleKeyAndIncrementCounterOnUpdate(
creditJudicialDocumentService,
chunkItems,
CreditJudicialDocument::getId,
CreditJudicialDocument::setId,
CreditJudicialDocument::getCaseNumber,
CreditJudicialDocument::getCaseNumber,
CreditJudicialDocument::getRecommend,
CreditJudicialDocument::setRecommend,
null,
mpBatchSize
),
(rowItem, rowNumber) -> {
if (rowItem.getRecommend() == null) {
rowItem.setRecommend(0);
}
boolean saved = creditJudicialDocumentService.save(rowItem);
if (!saved) {
CreditJudicialDocument existing = creditJudicialDocumentService.lambdaQuery()
.eq(CreditJudicialDocument::getCaseNumber, rowItem.getCaseNumber())
.select(CreditJudicialDocument::getId, CreditJudicialDocument::getRecommend)
.one();
if (existing != null) {
rowItem.setId(existing.getId());
Integer old = existing.getRecommend();
rowItem.setRecommend(old == null ? 1 : old + 1);
if (creditJudicialDocumentService.updateById(rowItem)) {
return true;
}
}
} else {
return true;
}
String prefix = rowNumber > 0 ? ("" + rowNumber + "行:") : "";
errorMessages.add(prefix + "保存失败");
return false;
},
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 = "下载裁判文书导入模板") @Operation(summary = "下载裁判文书导入模板")
@GetMapping("/import/template") @GetMapping("/import/template")
public void downloadTemplate(HttpServletResponse response) throws IOException { public void downloadTemplate(HttpServletResponse response) throws IOException {
List<CreditJudicialImportParam> templateList = new ArrayList<>(); List<CreditJudicialDocumentImportParam> templateList = new ArrayList<>();
CreditJudicialImportParam example = new CreditJudicialImportParam(); CreditJudicialDocumentImportParam example = new CreditJudicialDocumentImportParam();
example.setDataType("裁判文书"); example.setTitle("裁判文书");
example.setPlaintiffAppellant("原告示例");
example.setAppellee("被告示例");
example.setOtherPartiesThirdParty("第三人示例"); example.setOtherPartiesThirdParty("第三人示例");
example.setOccurrenceTime("2024-01-01"); example.setOccurrenceTime("2024-01-01");
example.setCaseNumber("2024示例案号"); example.setCaseNumber("2024示例案号");
example.setCauseOfAction("案由示例"); example.setCauseOfAction("案由示例");
example.setInvolvedAmount("100000"); example.setInvolvedAmount("100000");
example.setDefendantAppellee("裁判结果示例");
example.setCourtName("示例法院"); example.setCourtName("示例法院");
example.setDataStatus("已公开"); example.setReleaseDate("2024-01-02");
example.setComments("备注信息"); example.setComments("备注信息");
templateList.add(example); templateList.add(example);
Workbook workbook = ExcelImportSupport.buildTemplate("裁判文书导入模板", "裁判文书", CreditJudicialImportParam.class, templateList); Workbook workbook = ExcelImportSupport.buildTemplate("裁判文书导入模板", "裁判文书", CreditJudicialDocumentImportParam.class, templateList);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment; filename=credit_judicial_document_import_template.xlsx"); response.setHeader("Content-Disposition", "attachment; filename=credit_judicial_document_import_template.xlsx");
@@ -319,31 +604,28 @@ public class CreditJudicialDocumentController extends BaseController {
workbook.close(); workbook.close();
} }
private boolean isEmptyImportRow(CreditJudicialImportParam param) { private boolean isEmptyImportRow(CreditJudicialDocumentImportParam param) {
if (param == null) { if (param == null) {
return true; return true;
} }
return ImportHelper.isBlank(param.getCaseNumber()) return ImportHelper.isBlank(param.getCaseNumber());
&& ImportHelper.isBlank(param.getPlaintiffAppellant())
&& ImportHelper.isBlank(param.getAppellee())
&& ImportHelper.isBlank(param.getCauseOfAction());
} }
private CreditJudicialDocument convertImportParamToEntity(CreditJudicialImportParam param) { private CreditJudicialDocument convertImportParamToEntity(CreditJudicialDocumentImportParam param) {
CreditJudicialDocument entity = new CreditJudicialDocument(); CreditJudicialDocument entity = new CreditJudicialDocument();
entity.setDataType(param.getDataType()); entity.setTitle(param.getTitle());
entity.setPlaintiffAppellant(param.getPlaintiffAppellant());
entity.setAppellee(param.getAppellee());
entity.setOtherPartiesThirdParty(param.getOtherPartiesThirdParty()); entity.setOtherPartiesThirdParty(param.getOtherPartiesThirdParty());
entity.setOccurrenceTime(param.getOccurrenceTime()); entity.setOccurrenceTime(param.getOccurrenceTime());
entity.setCaseNumber(param.getCaseNumber()); entity.setCaseNumber(param.getCaseNumber());
entity.setCauseOfAction(param.getCauseOfAction()); entity.setCauseOfAction(param.getCauseOfAction());
entity.setInvolvedAmount(param.getInvolvedAmount()); entity.setInvolvedAmount(param.getInvolvedAmount());
// Excel导入字段映射补全否则对应数据库字段(defendant_appellee/release_date)会一直为空
entity.setDefendantAppellee(param.getDefendantAppellee());
entity.setReleaseDate(param.getReleaseDate());
entity.setCourtName(param.getCourtName()); entity.setCourtName(param.getCourtName());
entity.setDataStatus(param.getDataStatus());
entity.setComments(param.getComments()); entity.setComments(param.getComments());
System.out.println("entity = " + entity);
return entity; return entity;
} }

View File

@@ -13,6 +13,8 @@ import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.credit.entity.CreditJudiciary; import com.gxwebsoft.credit.entity.CreditJudiciary;
import com.gxwebsoft.credit.param.CreditJudiciaryImportParam; import com.gxwebsoft.credit.param.CreditJudiciaryImportParam;
import com.gxwebsoft.credit.param.CreditJudiciaryParam; 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 com.gxwebsoft.credit.service.CreditJudiciaryService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@@ -26,7 +28,10 @@ import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set;
/** /**
* 司法案件控制器 * 司法案件控制器
@@ -44,6 +49,12 @@ public class CreditJudiciaryController extends BaseController {
@Resource @Resource
private BatchImportSupport batchImportSupport; private BatchImportSupport batchImportSupport;
@Resource
private CreditCompanyService creditCompanyService;
@Resource
private CreditCompanyRecordCountService creditCompanyRecordCountService;
@Operation(summary = "分页查询司法案件") @Operation(summary = "分页查询司法案件")
@GetMapping("/page") @GetMapping("/page")
public ApiResult<PageResult<CreditJudiciary>> page(CreditJudiciaryParam param) { public ApiResult<PageResult<CreditJudiciary>> page(CreditJudiciaryParam param) {
@@ -131,6 +142,45 @@ public class CreditJudiciaryController extends BaseController {
return fail("删除失败"); 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());
}
/** /**
* 批量导入司法案件 * 批量导入司法案件
*/ */
@@ -141,15 +191,19 @@ public class CreditJudiciaryController extends BaseController {
@RequestParam(value = "companyId", required = false) Integer companyId) { @RequestParam(value = "companyId", required = false) Integer companyId) {
List<String> errorMessages = new ArrayList<>(); List<String> errorMessages = new ArrayList<>();
int successCount = 0; int successCount = 0;
Set<Integer> touchedCompanyIds = new HashSet<>();
try { try {
// 支持按选项卡名称导入默认读取“司法案件”sheet不存在则回退到第 0 个sheet
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "司法案件", 0);
List<CreditJudiciaryImportParam> list = null; List<CreditJudiciaryImportParam> list = null;
int usedTitleRows = 0; int usedTitleRows = 0;
int usedHeadRows = 0; int usedHeadRows = 0;
int[][] tryConfigs = new int[][]{{1, 1}, {0, 1}, {0, 2}, {0, 3}}; int[][] tryConfigs = new int[][]{{1, 1}, {0, 1}, {0, 2}, {0, 3}};
for (int[] config : tryConfigs) { for (int[] config : tryConfigs) {
list = filterEmptyRows(tryImport(file, config[0], config[1])); list = filterEmptyRows(tryImport(file, config[0], config[1], sheetIndex));
if (!CollectionUtils.isEmpty(list)) { if (!CollectionUtils.isEmpty(list)) {
usedTitleRows = config[0]; usedTitleRows = config[0];
usedHeadRows = config[1]; usedHeadRows = config[1];
@@ -163,6 +217,20 @@ public class CreditJudiciaryController extends BaseController {
User loginUser = getLoginUser(); User loginUser = getLoginUser();
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null; Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : 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 chunkSize = 500;
final int mpBatchSize = 500; final int mpBatchSize = 500;
@@ -173,6 +241,21 @@ public class CreditJudiciaryController extends BaseController {
CreditJudiciaryImportParam param = list.get(i); CreditJudiciaryImportParam param = list.get(i);
try { try {
CreditJudiciary item = convertImportParamToEntity(param); 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) { if (item.getCompanyId() == null && companyId != null) {
item.setCompanyId(companyId); item.setCompanyId(companyId);
} }
@@ -198,15 +281,19 @@ public class CreditJudiciaryController extends BaseController {
} }
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows; int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
// 验证必填字段 // 验证必填字段
if (item.getName() == null || item.getName().trim().isEmpty()) { // if (item.getName() == null || item.getName().trim().isEmpty()) {
errorMessages.add("" + excelRowNumber + "行:项目名称不能为空"); // errorMessages.add("第" + excelRowNumber + "行:项目名称不能为空");
continue; // continue;
} // }
if (item.getCode() == null || item.getCode().trim().isEmpty()) { if (item.getCode() == null || item.getCode().trim().isEmpty()) {
errorMessages.add("" + excelRowNumber + "行:唯一标识不能为空"); errorMessages.add("" + excelRowNumber + "行:唯一标识不能为空");
continue; continue;
} }
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
touchedCompanyIds.add(item.getCompanyId());
}
chunkItems.add(item); chunkItems.add(item);
chunkRowNumbers.add(excelRowNumber); chunkRowNumbers.add(excelRowNumber);
if (chunkItems.size() >= chunkSize) { if (chunkItems.size() >= chunkSize) {
@@ -285,6 +372,8 @@ public class CreditJudiciaryController extends BaseController {
); );
} }
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.JUDICIARY, touchedCompanyIds);
if (errorMessages.isEmpty()) { if (errorMessages.isEmpty()) {
return success("成功导入" + successCount + "条数据", null); return success("成功导入" + successCount + "条数据", null);
} else { } else {
@@ -329,11 +418,11 @@ public class CreditJudiciaryController extends BaseController {
workbook.close(); workbook.close();
} }
private List<CreditJudiciaryImportParam> tryImport(MultipartFile file, int titleRows, int headRows) throws Exception { private List<CreditJudiciaryImportParam> tryImport(MultipartFile file, int titleRows, int headRows, int sheetIndex) throws Exception {
ImportParams importParams = new ImportParams(); ImportParams importParams = new ImportParams();
importParams.setTitleRows(titleRows); importParams.setTitleRows(titleRows);
importParams.setHeadRows(headRows); importParams.setHeadRows(headRows);
importParams.setStartSheetIndex(0); importParams.setStartSheetIndex(sheetIndex);
importParams.setSheetNum(1); importParams.setSheetNum(1);
return ExcelImportUtil.importExcel(file.getInputStream(), CreditJudiciaryImportParam.class, importParams); return ExcelImportUtil.importExcel(file.getInputStream(), CreditJudiciaryImportParam.class, importParams);
} }

View File

@@ -7,8 +7,10 @@ import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.common.core.web.PageResult; import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.system.entity.User; import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.credit.entity.CreditMediation; import com.gxwebsoft.credit.entity.CreditMediation;
import com.gxwebsoft.credit.param.CreditJudicialImportParam; import com.gxwebsoft.credit.param.CreditMediationImportParam;
import com.gxwebsoft.credit.param.CreditMediationParam; 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 com.gxwebsoft.credit.service.CreditMediationService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@@ -22,7 +24,10 @@ import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set;
/** /**
* 诉前调解司法大数据控制器 * 诉前调解司法大数据控制器
@@ -40,6 +45,12 @@ public class CreditMediationController extends BaseController {
@Resource @Resource
private BatchImportSupport batchImportSupport; private BatchImportSupport batchImportSupport;
@Resource
private CreditCompanyService creditCompanyService;
@Resource
private CreditCompanyRecordCountService creditCompanyRecordCountService;
@Operation(summary = "分页查询诉前调解司法大数据") @Operation(summary = "分页查询诉前调解司法大数据")
@GetMapping("/page") @GetMapping("/page")
public ApiResult<PageResult<CreditMediation>> page(CreditMediationParam param) { public ApiResult<PageResult<CreditMediation>> page(CreditMediationParam param) {
@@ -132,6 +143,45 @@ public class CreditMediationController extends BaseController {
return fail("删除失败"); 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;
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
creditMediationService,
creditCompanyService,
currentTenantId,
onlyNull,
limit,
CreditMediation::getId,
CreditMediation::setId,
CreditMediation::getAppellee,
CreditMediation::getCompanyId,
CreditMediation::setCompanyId,
CreditMediation::getHasData,
CreditMediation::setHasData,
CreditMediation::getTenantId,
CreditMediation::new
);
if (!stats.anyDataRead) {
return success("无可更新数据", stats.toMap());
}
return success("更新完成,更新" + stats.updated + "", stats.toMap());
}
/** /**
* 批量导入诉前调解司法大数据 * 批量导入诉前调解司法大数据
*/ */
@@ -142,13 +192,16 @@ public class CreditMediationController extends BaseController {
@RequestParam(value = "companyId", required = false) Integer companyId) { @RequestParam(value = "companyId", required = false) Integer companyId) {
List<String> errorMessages = new ArrayList<>(); List<String> errorMessages = new ArrayList<>();
int successCount = 0; int successCount = 0;
Set<Integer> touchedCompanyIds = new HashSet<>();
try { try {
ExcelImportSupport.ImportResult<CreditJudicialImportParam> importResult = ExcelImportSupport.read( int sheetIndex = ExcelImportSupport.findSheetIndex(file, "诉前调解", 0);
file, CreditJudicialImportParam.class, this::isEmptyImportRow); ExcelImportSupport.ImportResult<CreditMediationImportParam> importResult = ExcelImportSupport.read(
List<CreditJudicialImportParam> list = importResult.getData(); file, CreditMediationImportParam.class, this::isEmptyImportRow, sheetIndex);
List<CreditMediationImportParam> list = importResult.getData();
int usedTitleRows = importResult.getTitleRows(); int usedTitleRows = importResult.getTitleRows();
int usedHeadRows = importResult.getHeadRows(); int usedHeadRows = importResult.getHeadRows();
int usedSheetIndex = importResult.getSheetIndex();
if (CollectionUtils.isEmpty(list)) { if (CollectionUtils.isEmpty(list)) {
return fail("未读取到数据,请确认模板表头与示例格式一致", null); return fail("未读取到数据,请确认模板表头与示例格式一致", null);
@@ -157,6 +210,7 @@ public class CreditMediationController extends BaseController {
User loginUser = getLoginUser(); User loginUser = getLoginUser();
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null; Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null; Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
Map<String, String> urlByCaseNumber = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "案号");
final int chunkSize = 500; final int chunkSize = 500;
final int mpBatchSize = 500; final int mpBatchSize = 500;
@@ -164,9 +218,15 @@ public class CreditMediationController extends BaseController {
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize); List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
for (int i = 0; i < list.size(); i++) { for (int i = 0; i < list.size(); i++) {
CreditJudicialImportParam param = list.get(i); CreditMediationImportParam param = list.get(i);
try { try {
CreditMediation item = convertImportParamToEntity(param); 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) { if (item.getCompanyId() == null && companyId != null) {
item.setCompanyId(companyId); item.setCompanyId(companyId);
@@ -193,6 +253,10 @@ public class CreditMediationController extends BaseController {
continue; continue;
} }
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
touchedCompanyIds.add(item.getCompanyId());
}
chunkItems.add(item); chunkItems.add(item);
chunkRowNumbers.add(excelRowNumber); chunkRowNumbers.add(excelRowNumber);
if (chunkItems.size() >= chunkSize) { if (chunkItems.size() >= chunkSize) {
@@ -277,6 +341,8 @@ public class CreditMediationController extends BaseController {
); );
} }
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.MEDIATION, touchedCompanyIds);
if (errorMessages.isEmpty()) { if (errorMessages.isEmpty()) {
return success("成功导入" + successCount + "条数据", null); return success("成功导入" + successCount + "条数据", null);
} else { } else {
@@ -294,23 +360,18 @@ public class CreditMediationController extends BaseController {
@Operation(summary = "下载诉前调解导入模板") @Operation(summary = "下载诉前调解导入模板")
@GetMapping("/import/template") @GetMapping("/import/template")
public void downloadTemplate(HttpServletResponse response) throws IOException { public void downloadTemplate(HttpServletResponse response) throws IOException {
List<CreditJudicialImportParam> templateList = new ArrayList<>(); List<CreditMediationImportParam> templateList = new ArrayList<>();
CreditJudicialImportParam example = new CreditJudicialImportParam(); CreditMediationImportParam example = new CreditMediationImportParam();
example.setDataType("诉前调解"); example.setOtherPartiesThirdParty("当事人");
example.setPlaintiffAppellant("原告示例");
example.setAppellee("被告示例");
example.setOtherPartiesThirdParty("第三人示例");
example.setOccurrenceTime("2024-01-01");
example.setCaseNumber("2024示例案号"); example.setCaseNumber("2024示例案号");
example.setCauseOfAction("案由示例"); example.setCauseOfAction("案由示例");
example.setInvolvedAmount("100000");
example.setCourtName("示例法院"); example.setCourtName("示例法院");
example.setDataStatus("已公开"); example.setOccurrenceTime("2024-01-01");
example.setComments("备注信息"); example.setComments("备注信息");
templateList.add(example); templateList.add(example);
Workbook workbook = ExcelImportSupport.buildTemplate("诉前调解导入模板", "诉前调解", CreditJudicialImportParam.class, templateList); Workbook workbook = ExcelImportSupport.buildTemplate("诉前调解导入模板", "诉前调解", CreditMediationImportParam.class, templateList);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment; filename=credit_mediation_import_template.xlsx"); response.setHeader("Content-Disposition", "attachment; filename=credit_mediation_import_template.xlsx");
@@ -319,29 +380,22 @@ public class CreditMediationController extends BaseController {
workbook.close(); workbook.close();
} }
private boolean isEmptyImportRow(CreditJudicialImportParam param) { private boolean isEmptyImportRow(CreditMediationImportParam param) {
if (param == null) { if (param == null) {
return true; return true;
} }
return ImportHelper.isBlank(param.getCaseNumber()) return ImportHelper.isBlank(param.getCaseNumber())
&& ImportHelper.isBlank(param.getPlaintiffAppellant())
&& ImportHelper.isBlank(param.getAppellee())
&& ImportHelper.isBlank(param.getCauseOfAction()); && ImportHelper.isBlank(param.getCauseOfAction());
} }
private CreditMediation convertImportParamToEntity(CreditJudicialImportParam param) { private CreditMediation convertImportParamToEntity(CreditMediationImportParam param) {
CreditMediation entity = new CreditMediation(); CreditMediation entity = new CreditMediation();
entity.setDataType(param.getDataType());
entity.setPlaintiffAppellant(param.getPlaintiffAppellant());
entity.setAppellee(param.getAppellee());
entity.setOtherPartiesThirdParty(param.getOtherPartiesThirdParty()); entity.setOtherPartiesThirdParty(param.getOtherPartiesThirdParty());
entity.setOccurrenceTime(param.getOccurrenceTime()); entity.setOccurrenceTime(param.getOccurrenceTime());
entity.setCaseNumber(param.getCaseNumber()); entity.setCaseNumber(param.getCaseNumber());
entity.setCauseOfAction(param.getCauseOfAction()); entity.setCauseOfAction(param.getCauseOfAction());
entity.setInvolvedAmount(param.getInvolvedAmount());
entity.setCourtName(param.getCourtName()); entity.setCourtName(param.getCourtName());
entity.setDataStatus(param.getDataStatus());
entity.setComments(param.getComments()); entity.setComments(param.getComments());
return entity; return entity;

View File

@@ -9,6 +9,8 @@ import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.credit.entity.CreditNearbyCompany; import com.gxwebsoft.credit.entity.CreditNearbyCompany;
import com.gxwebsoft.credit.param.CreditNearbyCompanyImportParam; import com.gxwebsoft.credit.param.CreditNearbyCompanyImportParam;
import com.gxwebsoft.credit.param.CreditNearbyCompanyParam; 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 com.gxwebsoft.credit.service.CreditNearbyCompanyService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@@ -22,8 +24,10 @@ import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
/** /**
* 附近企业控制器 * 附近企业控制器
@@ -41,6 +45,12 @@ public class CreditNearbyCompanyController extends BaseController {
@Resource @Resource
private BatchImportSupport batchImportSupport; private BatchImportSupport batchImportSupport;
@Resource
private CreditCompanyService creditCompanyService;
@Resource
private CreditCompanyRecordCountService creditCompanyRecordCountService;
@Operation(summary = "分页查询附近企业") @Operation(summary = "分页查询附近企业")
@GetMapping("/page") @GetMapping("/page")
public ApiResult<PageResult<CreditNearbyCompany>> page(CreditNearbyCompanyParam param) { public ApiResult<PageResult<CreditNearbyCompany>> page(CreditNearbyCompanyParam param) {
@@ -133,6 +143,45 @@ public class CreditNearbyCompanyController extends BaseController {
return fail("删除失败"); 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::getHasData,
CreditNearbyCompany::setHasData,
CreditNearbyCompany::getTenantId,
CreditNearbyCompany::new
);
if (!stats.anyDataRead) {
return success("无可更新数据", stats.toMap());
}
return success("更新完成,更新" + stats.updated + "", stats.toMap());
}
/** /**
* 批量导入附近企业 * 批量导入附近企业
*/ */
@@ -145,6 +194,7 @@ public class CreditNearbyCompanyController extends BaseController {
@RequestParam(value = "type", required = false) Integer type) { @RequestParam(value = "type", required = false) Integer type) {
List<String> errorMessages = new ArrayList<>(); List<String> errorMessages = new ArrayList<>();
int successCount = 0; int successCount = 0;
Set<Integer> touchedCompanyIds = new HashSet<>();
try { try {
ExcelImportSupport.ImportResult<CreditNearbyCompanyImportParam> importResult = ExcelImportSupport.readAnySheet( ExcelImportSupport.ImportResult<CreditNearbyCompanyImportParam> importResult = ExcelImportSupport.readAnySheet(
@@ -194,6 +244,9 @@ public class CreditNearbyCompanyController extends BaseController {
if (item.getCompanyId() == null && companyId != null) { if (item.getCompanyId() == null && companyId != null) {
item.setCompanyId(companyId); item.setCompanyId(companyId);
} }
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
touchedCompanyIds.add(item.getCompanyId());
}
if (item.getUserId() == null && currentUserId != null) { if (item.getUserId() == null && currentUserId != null) {
item.setUserId(currentUserId); item.setUserId(currentUserId);
} }
@@ -234,6 +287,8 @@ public class CreditNearbyCompanyController extends BaseController {
successCount += persistImportChunk(chunkItems, chunkRowNumbers, companyId, parentId, type, currentTenantId, mpBatchSize, errorMessages); successCount += persistImportChunk(chunkItems, chunkRowNumbers, companyId, parentId, type, currentTenantId, mpBatchSize, errorMessages);
} }
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.NEARBY_COMPANY, touchedCompanyIds);
if (errorMessages.isEmpty()) { if (errorMessages.isEmpty()) {
return success("成功导入" + successCount + "条数据", null); return success("成功导入" + successCount + "条数据", null);
} else { } else {

View File

@@ -9,6 +9,8 @@ import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.credit.entity.CreditPatent; import com.gxwebsoft.credit.entity.CreditPatent;
import com.gxwebsoft.credit.param.CreditPatentImportParam; import com.gxwebsoft.credit.param.CreditPatentImportParam;
import com.gxwebsoft.credit.param.CreditPatentParam; 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 com.gxwebsoft.credit.service.CreditPatentService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@@ -22,8 +24,10 @@ import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
/** /**
* 专利控制器 * 专利控制器
@@ -41,6 +45,12 @@ public class CreditPatentController extends BaseController {
@Resource @Resource
private BatchImportSupport batchImportSupport; private BatchImportSupport batchImportSupport;
@Resource
private CreditCompanyService creditCompanyService;
@Resource
private CreditCompanyRecordCountService creditCompanyRecordCountService;
@Operation(summary = "分页查询专利") @Operation(summary = "分页查询专利")
@GetMapping("/page") @GetMapping("/page")
public ApiResult<PageResult<CreditPatent>> page(CreditPatentParam param) { public ApiResult<PageResult<CreditPatent>> page(CreditPatentParam param) {
@@ -133,6 +143,45 @@ public class CreditPatentController extends BaseController {
return fail("删除失败"); 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());
}
/** /**
* 批量导入专利 * 批量导入专利
*/ */
@@ -143,6 +192,7 @@ public class CreditPatentController extends BaseController {
@RequestParam(value = "companyId", required = false) Integer companyId) { @RequestParam(value = "companyId", required = false) Integer companyId) {
List<String> errorMessages = new ArrayList<>(); List<String> errorMessages = new ArrayList<>();
int successCount = 0; int successCount = 0;
Set<Integer> touchedCompanyIds = new HashSet<>();
try { try {
ExcelImportSupport.ImportResult<CreditPatentImportParam> importResult = ExcelImportSupport.readAnySheet( ExcelImportSupport.ImportResult<CreditPatentImportParam> importResult = ExcelImportSupport.readAnySheet(
@@ -207,6 +257,10 @@ public class CreditPatentController extends BaseController {
continue; continue;
} }
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
touchedCompanyIds.add(item.getCompanyId());
}
chunkItems.add(item); chunkItems.add(item);
chunkRowNumbers.add(excelRowNumber); chunkRowNumbers.add(excelRowNumber);
if (chunkItems.size() >= chunkSize) { if (chunkItems.size() >= chunkSize) {
@@ -291,6 +345,8 @@ public class CreditPatentController extends BaseController {
); );
} }
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.PATENT, touchedCompanyIds);
if (errorMessages.isEmpty()) { if (errorMessages.isEmpty()) {
return success("成功导入" + successCount + "条数据", null); return success("成功导入" + successCount + "条数据", null);
} else { } else {
@@ -339,9 +395,7 @@ public class CreditPatentController extends BaseController {
if (isImportHeaderRow(param)) { if (isImportHeaderRow(param)) {
return true; return true;
} }
return ImportHelper.isBlank(param.getRegisterNo()) return ImportHelper.isBlank(param.getPublicNo());
&& ImportHelper.isBlank(param.getName())
&& ImportHelper.isBlank(param.getPatentApplicant());
} }
private boolean isImportHeaderRow(CreditPatentImportParam param) { private boolean isImportHeaderRow(CreditPatentImportParam param) {

View File

@@ -9,6 +9,8 @@ import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.credit.entity.CreditRiskRelation; import com.gxwebsoft.credit.entity.CreditRiskRelation;
import com.gxwebsoft.credit.param.CreditRiskRelationImportParam; import com.gxwebsoft.credit.param.CreditRiskRelationImportParam;
import com.gxwebsoft.credit.param.CreditRiskRelationParam; 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 com.gxwebsoft.credit.service.CreditRiskRelationService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@@ -22,7 +24,10 @@ import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set;
/** /**
* 风险关系表控制器 * 风险关系表控制器
@@ -40,6 +45,12 @@ public class CreditRiskRelationController extends BaseController {
@Resource @Resource
private BatchImportSupport batchImportSupport; private BatchImportSupport batchImportSupport;
@Resource
private CreditCompanyService creditCompanyService;
@Resource
private CreditCompanyRecordCountService creditCompanyRecordCountService;
@Operation(summary = "分页查询风险关系表") @Operation(summary = "分页查询风险关系表")
@GetMapping("/page") @GetMapping("/page")
public ApiResult<PageResult<CreditRiskRelation>> page(CreditRiskRelationParam param) { public ApiResult<PageResult<CreditRiskRelation>> page(CreditRiskRelationParam param) {
@@ -132,6 +143,45 @@ public class CreditRiskRelationController extends BaseController {
return fail("删除失败"); 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::getHasData,
CreditRiskRelation::setHasData,
CreditRiskRelation::getTenantId,
CreditRiskRelation::new
);
if (!stats.anyDataRead) {
return success("无可更新数据", stats.toMap());
}
return success("更新完成,更新" + stats.updated + "", stats.toMap());
}
/** /**
* 批量导入风险关系表 * 批量导入风险关系表
*/ */
@@ -142,6 +192,7 @@ public class CreditRiskRelationController extends BaseController {
@RequestParam(value = "companyId", required = false) Integer companyId) { @RequestParam(value = "companyId", required = false) Integer companyId) {
List<String> errorMessages = new ArrayList<>(); List<String> errorMessages = new ArrayList<>();
int successCount = 0; int successCount = 0;
Set<Integer> touchedCompanyIds = new HashSet<>();
try { try {
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "风险关系", 1); int sheetIndex = ExcelImportSupport.findSheetIndex(file, "风险关系", 1);
@@ -194,6 +245,10 @@ public class CreditRiskRelationController extends BaseController {
continue; continue;
} }
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
touchedCompanyIds.add(item.getCompanyId());
}
chunkItems.add(item); chunkItems.add(item);
chunkRowNumbers.add(excelRowNumber); chunkRowNumbers.add(excelRowNumber);
if (chunkItems.size() >= chunkSize) { if (chunkItems.size() >= chunkSize) {
@@ -278,6 +333,8 @@ public class CreditRiskRelationController extends BaseController {
); );
} }
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.RISK_RELATION, touchedCompanyIds);
if (errorMessages.isEmpty()) { if (errorMessages.isEmpty()) {
return success("成功导入" + successCount + "条数据", null); return success("成功导入" + successCount + "条数据", null);
} else { } else {

View File

@@ -9,6 +9,8 @@ import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.credit.entity.CreditSupplier; import com.gxwebsoft.credit.entity.CreditSupplier;
import com.gxwebsoft.credit.param.CreditSupplierImportParam; import com.gxwebsoft.credit.param.CreditSupplierImportParam;
import com.gxwebsoft.credit.param.CreditSupplierParam; 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 com.gxwebsoft.credit.service.CreditSupplierService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@@ -22,7 +24,10 @@ import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set;
/** /**
* 供应商控制器 * 供应商控制器
@@ -40,6 +45,12 @@ public class CreditSupplierController extends BaseController {
@Resource @Resource
private BatchImportSupport batchImportSupport; private BatchImportSupport batchImportSupport;
@Resource
private CreditCompanyService creditCompanyService;
@Resource
private CreditCompanyRecordCountService creditCompanyRecordCountService;
@Operation(summary = "分页查询供应商") @Operation(summary = "分页查询供应商")
@GetMapping("/page") @GetMapping("/page")
public ApiResult<PageResult<CreditSupplier>> page(CreditSupplierParam param) { public ApiResult<PageResult<CreditSupplier>> page(CreditSupplierParam param) {
@@ -132,6 +143,45 @@ public class CreditSupplierController extends BaseController {
return fail("删除失败"); 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::getHasData,
CreditSupplier::setHasData,
CreditSupplier::getTenantId,
CreditSupplier::new
);
if (!stats.anyDataRead) {
return success("无可更新数据", stats.toMap());
}
return success("更新完成,更新" + stats.updated + "", stats.toMap());
}
/** /**
* 批量导入供应商 * 批量导入供应商
*/ */
@@ -142,6 +192,7 @@ public class CreditSupplierController extends BaseController {
@RequestParam(value = "companyId", required = false) Integer companyId) { @RequestParam(value = "companyId", required = false) Integer companyId) {
List<String> errorMessages = new ArrayList<>(); List<String> errorMessages = new ArrayList<>();
int successCount = 0; int successCount = 0;
Set<Integer> touchedCompanyIds = new HashSet<>();
try { try {
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "供应商", 3); int sheetIndex = ExcelImportSupport.findSheetIndex(file, "供应商", 3);
@@ -150,6 +201,7 @@ public class CreditSupplierController extends BaseController {
List<CreditSupplierImportParam> list = importResult.getData(); List<CreditSupplierImportParam> list = importResult.getData();
int usedTitleRows = importResult.getTitleRows(); int usedTitleRows = importResult.getTitleRows();
int usedHeadRows = importResult.getHeadRows(); int usedHeadRows = importResult.getHeadRows();
int usedSheetIndex = importResult.getSheetIndex();
if (CollectionUtils.isEmpty(list)) { if (CollectionUtils.isEmpty(list)) {
return fail("未读取到数据,请确认模板表头与示例格式一致", null); return fail("未读取到数据,请确认模板表头与示例格式一致", null);
@@ -158,6 +210,7 @@ public class CreditSupplierController extends BaseController {
User loginUser = getLoginUser(); User loginUser = getLoginUser();
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null; Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null; Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : null;
Map<String, String> urlBySupplier = ExcelImportSupport.readUrlByKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "供应商");
final int chunkSize = 500; final int chunkSize = 500;
final int mpBatchSize = 500; final int mpBatchSize = 500;
@@ -168,6 +221,12 @@ public class CreditSupplierController extends BaseController {
CreditSupplierImportParam param = list.get(i); CreditSupplierImportParam param = list.get(i);
try { try {
CreditSupplier item = convertImportParamToEntity(param); 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) { if (item.getCompanyId() == null && companyId != null) {
item.setCompanyId(companyId); item.setCompanyId(companyId);
@@ -194,6 +253,10 @@ public class CreditSupplierController extends BaseController {
continue; continue;
} }
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
touchedCompanyIds.add(item.getCompanyId());
}
chunkItems.add(item); chunkItems.add(item);
chunkRowNumbers.add(excelRowNumber); chunkRowNumbers.add(excelRowNumber);
if (chunkItems.size() >= chunkSize) { if (chunkItems.size() >= chunkSize) {
@@ -278,6 +341,8 @@ public class CreditSupplierController extends BaseController {
); );
} }
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.SUPPLIER, touchedCompanyIds);
if (errorMessages.isEmpty()) { if (errorMessages.isEmpty()) {
return success("成功导入" + successCount + "条数据", null); return success("成功导入" + successCount + "条数据", null);
} else { } else {

View File

@@ -9,6 +9,8 @@ import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.credit.entity.CreditSuspectedRelationship; import com.gxwebsoft.credit.entity.CreditSuspectedRelationship;
import com.gxwebsoft.credit.param.CreditSuspectedRelationshipImportParam; import com.gxwebsoft.credit.param.CreditSuspectedRelationshipImportParam;
import com.gxwebsoft.credit.param.CreditSuspectedRelationshipParam; 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 com.gxwebsoft.credit.service.CreditSuspectedRelationshipService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@@ -22,8 +24,10 @@ import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
/** /**
* 疑似关系控制器 * 疑似关系控制器
@@ -41,6 +45,12 @@ public class CreditSuspectedRelationshipController extends BaseController {
@Resource @Resource
private BatchImportSupport batchImportSupport; private BatchImportSupport batchImportSupport;
@Resource
private CreditCompanyService creditCompanyService;
@Resource
private CreditCompanyRecordCountService creditCompanyRecordCountService;
@Operation(summary = "分页查询疑似关系") @Operation(summary = "分页查询疑似关系")
@GetMapping("/page") @GetMapping("/page")
public ApiResult<PageResult<CreditSuspectedRelationship>> page(CreditSuspectedRelationshipParam param) { public ApiResult<PageResult<CreditSuspectedRelationship>> page(CreditSuspectedRelationshipParam param) {
@@ -133,6 +143,45 @@ public class CreditSuspectedRelationshipController extends BaseController {
return fail("删除失败"); 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::getHasData,
CreditSuspectedRelationship::setHasData,
CreditSuspectedRelationship::getTenantId,
CreditSuspectedRelationship::new
);
if (!stats.anyDataRead) {
return success("无可更新数据", stats.toMap());
}
return success("更新完成,更新" + stats.updated + "", stats.toMap());
}
/** /**
* 批量导入疑似关系 * 批量导入疑似关系
*/ */
@@ -143,6 +192,7 @@ public class CreditSuspectedRelationshipController extends BaseController {
@RequestParam(value = "companyId", required = false) Integer companyId) { @RequestParam(value = "companyId", required = false) Integer companyId) {
List<String> errorMessages = new ArrayList<>(); List<String> errorMessages = new ArrayList<>();
int successCount = 0; int successCount = 0;
Set<Integer> touchedCompanyIds = new HashSet<>();
try { try {
ExcelImportSupport.ImportResult<CreditSuspectedRelationshipImportParam> importResult = ExcelImportSupport.readAnySheet( ExcelImportSupport.ImportResult<CreditSuspectedRelationshipImportParam> importResult = ExcelImportSupport.readAnySheet(
@@ -206,6 +256,10 @@ public class CreditSuspectedRelationshipController extends BaseController {
continue; continue;
} }
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
touchedCompanyIds.add(item.getCompanyId());
}
chunkItems.add(item); chunkItems.add(item);
chunkRowNumbers.add(excelRowNumber); chunkRowNumbers.add(excelRowNumber);
if (chunkItems.size() >= chunkSize) { if (chunkItems.size() >= chunkSize) {
@@ -412,6 +466,8 @@ public class CreditSuspectedRelationshipController extends BaseController {
); );
} }
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.SUSPECTED_RELATIONSHIP, touchedCompanyIds);
if (errorMessages.isEmpty()) { if (errorMessages.isEmpty()) {
return success("成功导入" + successCount + "条数据", null); return success("成功导入" + successCount + "条数据", null);
} else { } else {

View File

@@ -14,6 +14,8 @@ import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.credit.entity.CreditUser; import com.gxwebsoft.credit.entity.CreditUser;
import com.gxwebsoft.credit.param.CreditUserImportParam; import com.gxwebsoft.credit.param.CreditUserImportParam;
import com.gxwebsoft.credit.param.CreditUserParam; 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 com.gxwebsoft.credit.service.CreditUserService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@@ -36,8 +38,10 @@ import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
/** /**
* 招投标信息表控制器 * 招投标信息表控制器
@@ -57,6 +61,12 @@ public class CreditUserController extends BaseController {
@Resource @Resource
private BatchImportSupport batchImportSupport; private BatchImportSupport batchImportSupport;
@Resource
private CreditCompanyService creditCompanyService;
@Resource
private CreditCompanyRecordCountService creditCompanyRecordCountService;
@Operation(summary = "分页查询招投标信息表") @Operation(summary = "分页查询招投标信息表")
@GetMapping("/page") @GetMapping("/page")
public ApiResult<PageResult<CreditUser>> page(CreditUserParam param) { public ApiResult<PageResult<CreditUser>> page(CreditUserParam param) {
@@ -144,6 +154,45 @@ public class CreditUserController extends BaseController {
return fail("删除失败"); 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::getHasData,
CreditUser::setHasData,
CreditUser::getTenantId,
CreditUser::new
);
if (!stats.anyDataRead) {
return success("无可更新数据", stats.toMap());
}
return success("更新完成,更新" + stats.updated + "", stats.toMap());
}
/** /**
* 批量导入招投标信息 * 批量导入招投标信息
* Excel表头格式客户名称、唯一标识、类型、企业角色、上级ID、信息类型、所在国家、所在省份、所在城市、所在辖区、街道地址、招采单位名称、中标单位名称、中标金额、备注、是否推荐、到期时间、排序、状态、用户ID、租户ID * Excel表头格式客户名称、唯一标识、类型、企业角色、上级ID、信息类型、所在国家、所在省份、所在城市、所在辖区、街道地址、招采单位名称、中标单位名称、中标金额、备注、是否推荐、到期时间、排序、状态、用户ID、租户ID
@@ -155,6 +204,7 @@ public class CreditUserController extends BaseController {
@RequestParam(value = "companyId", required = false) Integer companyId) { @RequestParam(value = "companyId", required = false) Integer companyId) {
List<String> errorMessages = new ArrayList<>(); List<String> errorMessages = new ArrayList<>();
int successCount = 0; int successCount = 0;
Set<Integer> touchedCompanyIds = new HashSet<>();
try { try {
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "招投标", 0); int sheetIndex = ExcelImportSupport.findSheetIndex(file, "招投标", 0);
@@ -197,6 +247,9 @@ public class CreditUserController extends BaseController {
if (item.getCompanyId() == null && companyId != null) { if (item.getCompanyId() == null && companyId != null) {
item.setCompanyId(companyId); item.setCompanyId(companyId);
} }
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
touchedCompanyIds.add(item.getCompanyId());
}
// 设置默认值 // 设置默认值
if (item.getUserId() == null && currentUserId != null) { if (item.getUserId() == null && currentUserId != null) {
@@ -302,6 +355,8 @@ public class CreditUserController extends BaseController {
); );
} }
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.USER, touchedCompanyIds);
if (errorMessages.isEmpty()) { if (errorMessages.isEmpty()) {
return success("成功导入" + successCount + "条数据", null); return success("成功导入" + successCount + "条数据", null);
} else { } else {

View File

@@ -7,8 +7,10 @@ import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.common.core.web.PageResult; import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.system.entity.User; import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.credit.entity.CreditXgxf; import com.gxwebsoft.credit.entity.CreditXgxf;
import com.gxwebsoft.credit.param.CreditJudicialImportParam; import com.gxwebsoft.credit.param.CreditXgxfImportParam;
import com.gxwebsoft.credit.param.CreditXgxfParam; 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 com.gxwebsoft.credit.service.CreditXgxfService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@@ -22,7 +24,11 @@ import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set;
/** /**
* 限制高消费控制器 * 限制高消费控制器
@@ -40,6 +46,12 @@ public class CreditXgxfController extends BaseController {
@Resource @Resource
private BatchImportSupport batchImportSupport; private BatchImportSupport batchImportSupport;
@Resource
private CreditCompanyService creditCompanyService;
@Resource
private CreditCompanyRecordCountService creditCompanyRecordCountService;
@Operation(summary = "分页查询限制高消费") @Operation(summary = "分页查询限制高消费")
@GetMapping("/page") @GetMapping("/page")
public ApiResult<PageResult<CreditXgxf>> page(CreditXgxfParam param) { public ApiResult<PageResult<CreditXgxf>> page(CreditXgxfParam param) {
@@ -132,6 +144,45 @@ public class CreditXgxfController extends BaseController {
return fail("删除失败"); 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;
BatchImportSupport.CompanyIdRefreshStats stats = batchImportSupport.refreshCompanyIdByCompanyName(
creditXgxfService,
creditCompanyService,
currentTenantId,
onlyNull,
limit,
CreditXgxf::getId,
CreditXgxf::setId,
CreditXgxf::getDataType,
CreditXgxf::getCompanyId,
CreditXgxf::setCompanyId,
CreditXgxf::getHasData,
CreditXgxf::setHasData,
CreditXgxf::getTenantId,
CreditXgxf::new
);
if (!stats.anyDataRead) {
return success("无可更新数据", stats.toMap());
}
return success("更新完成,更新" + stats.updated + "", stats.toMap());
}
/** /**
* 批量导入限制高消费司法大数据 * 批量导入限制高消费司法大数据
*/ */
@@ -142,13 +193,16 @@ public class CreditXgxfController extends BaseController {
@RequestParam(value = "companyId", required = false) Integer companyId) { @RequestParam(value = "companyId", required = false) Integer companyId) {
List<String> errorMessages = new ArrayList<>(); List<String> errorMessages = new ArrayList<>();
int successCount = 0; int successCount = 0;
Set<Integer> touchedCompanyIds = new HashSet<>();
try { try {
ExcelImportSupport.ImportResult<CreditJudicialImportParam> importResult = ExcelImportSupport.read( int sheetIndex = ExcelImportSupport.findSheetIndex(file, "限制高消费", 0);
file, CreditJudicialImportParam.class, this::isEmptyImportRow); ExcelImportSupport.ImportResult<CreditXgxfImportParam> importResult = ExcelImportSupport.read(
List<CreditJudicialImportParam> list = importResult.getData(); file, CreditXgxfImportParam.class, this::isEmptyImportRow, sheetIndex);
List<CreditXgxfImportParam> list = importResult.getData();
int usedTitleRows = importResult.getTitleRows(); int usedTitleRows = importResult.getTitleRows();
int usedHeadRows = importResult.getHeadRows(); int usedHeadRows = importResult.getHeadRows();
int usedSheetIndex = importResult.getSheetIndex();
if (CollectionUtils.isEmpty(list)) { if (CollectionUtils.isEmpty(list)) {
return fail("未读取到数据,请确认模板表头与示例格式一致", null); return fail("未读取到数据,请确认模板表头与示例格式一致", null);
@@ -157,6 +211,8 @@ public class CreditXgxfController extends BaseController {
User loginUser = getLoginUser(); User loginUser = getLoginUser();
Integer currentUserId = loginUser != null ? loginUser.getUserId() : null; Integer currentUserId = loginUser != null ? loginUser.getUserId() : null;
Integer currentTenantId = loginUser != null ? loginUser.getTenantId() : 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 chunkSize = 500;
final int mpBatchSize = 500; final int mpBatchSize = 500;
@@ -164,13 +220,22 @@ public class CreditXgxfController extends BaseController {
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize); List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
for (int i = 0; i < list.size(); i++) { for (int i = 0; i < list.size(); i++) {
CreditJudicialImportParam param = list.get(i); CreditXgxfImportParam param = list.get(i);
try { try {
CreditXgxf item = convertImportParamToEntity(param); 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) { if (item.getCompanyId() == null && companyId != null) {
item.setCompanyId(companyId); item.setCompanyId(companyId);
} }
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
touchedCompanyIds.add(item.getCompanyId());
}
if (item.getUserId() == null && currentUserId != null) { if (item.getUserId() == null && currentUserId != null) {
item.setUserId(currentUserId); item.setUserId(currentUserId);
} }
@@ -193,6 +258,10 @@ public class CreditXgxfController extends BaseController {
continue; continue;
} }
if (item.getCompanyId() != null && item.getCompanyId() > 0) {
touchedCompanyIds.add(item.getCompanyId());
}
chunkItems.add(item); chunkItems.add(item);
chunkRowNumbers.add(excelRowNumber); chunkRowNumbers.add(excelRowNumber);
if (chunkItems.size() >= chunkSize) { if (chunkItems.size() >= chunkSize) {
@@ -277,6 +346,8 @@ public class CreditXgxfController extends BaseController {
); );
} }
creditCompanyRecordCountService.refresh(CreditCompanyRecordCountService.CountType.XGXF, touchedCompanyIds);
if (errorMessages.isEmpty()) { if (errorMessages.isEmpty()) {
return success("成功导入" + successCount + "条数据", null); return success("成功导入" + successCount + "条数据", null);
} else { } else {
@@ -288,29 +359,229 @@ public class CreditXgxfController extends BaseController {
} }
} }
/**
* 批量导入历史限制高消费(仅解析“历史限制高消费”选项卡)
* 规则案号相同则覆盖更新recommend++ 记录更新次数);案号不存在则插入。
*/
@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, "案号");
LinkedHashMap<String, CreditXgxf> latestByCaseNumber = new LinkedHashMap<>();
LinkedHashMap<String, Integer> latestRowByCaseNumber = new LinkedHashMap<>();
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);
}
latestByCaseNumber.put(item.getCaseNumber(), item);
latestRowByCaseNumber.put(item.getCaseNumber(), excelRowNumber);
} catch (Exception e) {
errorMessages.add("" + excelRowNumber + "行:" + e.getMessage());
e.printStackTrace();
}
}
if (latestByCaseNumber.isEmpty()) {
if (errorMessages.isEmpty()) {
return fail("未读取到数据,请确认模板表头与示例格式一致", null);
}
return success("导入完成成功0条失败" + errorMessages.size() + "", errorMessages);
}
final int chunkSize = 500;
final int mpBatchSize = 500;
List<CreditXgxf> chunkItems = new ArrayList<>(chunkSize);
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
for (Map.Entry<String, CreditXgxf> entry : latestByCaseNumber.entrySet()) {
String caseNumber = entry.getKey();
CreditXgxf item = entry.getValue();
Integer rowNo = latestRowByCaseNumber.get(caseNumber);
chunkItems.add(item);
chunkRowNumbers.add(rowNo != null ? rowNo : -1);
if (chunkItems.size() >= chunkSize) {
successCount += batchImportSupport.persistChunkWithFallback(
chunkItems,
chunkRowNumbers,
() -> batchImportSupport.upsertBySingleKeyAndIncrementCounterOnUpdate(
creditXgxfService,
chunkItems,
CreditXgxf::getId,
CreditXgxf::setId,
CreditXgxf::getCaseNumber,
CreditXgxf::getCaseNumber,
CreditXgxf::getRecommend,
CreditXgxf::setRecommend,
null,
mpBatchSize
),
(rowItem, rowNumber) -> {
if (rowItem.getRecommend() == null) {
rowItem.setRecommend(0);
}
boolean saved = creditXgxfService.save(rowItem);
if (!saved) {
CreditXgxf existing = creditXgxfService.lambdaQuery()
.eq(CreditXgxf::getCaseNumber, rowItem.getCaseNumber())
.select(CreditXgxf::getId, CreditXgxf::getRecommend)
.one();
if (existing != null) {
rowItem.setId(existing.getId());
Integer old = existing.getRecommend();
rowItem.setRecommend(old == null ? 1 : old + 1);
if (creditXgxfService.updateById(rowItem)) {
return true;
}
}
} else {
return true;
}
String prefix = rowNumber > 0 ? ("" + rowNumber + "行:") : "";
errorMessages.add(prefix + "保存失败");
return false;
},
errorMessages
);
chunkItems.clear();
chunkRowNumbers.clear();
}
}
if (!chunkItems.isEmpty()) {
successCount += batchImportSupport.persistChunkWithFallback(
chunkItems,
chunkRowNumbers,
() -> batchImportSupport.upsertBySingleKeyAndIncrementCounterOnUpdate(
creditXgxfService,
chunkItems,
CreditXgxf::getId,
CreditXgxf::setId,
CreditXgxf::getCaseNumber,
CreditXgxf::getCaseNumber,
CreditXgxf::getRecommend,
CreditXgxf::setRecommend,
null,
mpBatchSize
),
(rowItem, rowNumber) -> {
if (rowItem.getRecommend() == null) {
rowItem.setRecommend(0);
}
boolean saved = creditXgxfService.save(rowItem);
if (!saved) {
CreditXgxf existing = creditXgxfService.lambdaQuery()
.eq(CreditXgxf::getCaseNumber, rowItem.getCaseNumber())
.select(CreditXgxf::getId, CreditXgxf::getRecommend)
.one();
if (existing != null) {
rowItem.setId(existing.getId());
Integer old = existing.getRecommend();
rowItem.setRecommend(old == null ? 1 : old + 1);
if (creditXgxfService.updateById(rowItem)) {
return true;
}
}
} else {
return true;
}
String prefix = rowNumber > 0 ? ("" + rowNumber + "行:") : "";
errorMessages.add(prefix + "保存失败");
return false;
},
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 = "下载限制高消费导入模板") @Operation(summary = "下载限制高消费导入模板")
@GetMapping("/import/template") @GetMapping("/import/template")
public void downloadTemplate(HttpServletResponse response) throws IOException { public void downloadTemplate(HttpServletResponse response) throws IOException {
List<CreditJudicialImportParam> templateList = new ArrayList<>(); List<CreditXgxfImportParam> templateList = new ArrayList<>();
CreditJudicialImportParam example = new CreditJudicialImportParam(); CreditXgxfImportParam example = new CreditXgxfImportParam();
example.setDataType("限制高消费"); example.setDataType("限制高消费");
example.setPlaintiffAppellant("原告示例"); example.setPlaintiffAppellant("原告示例");
example.setAppellee("被告示例"); example.setAppellee("被告示例");
example.setOtherPartiesThirdParty("第三人示例");
example.setOccurrenceTime("2024-01-01"); example.setOccurrenceTime("2024-01-01");
example.setCaseNumber("2024示例案号"); example.setCaseNumber("2024示例案号");
example.setCauseOfAction("案由示例");
example.setInvolvedAmount("100000"); example.setInvolvedAmount("100000");
example.setCourtName("示例法院"); example.setCourtName("示例法院");
example.setDataStatus("已公开");
example.setComments("备注信息"); example.setComments("备注信息");
templateList.add(example); templateList.add(example);
Workbook workbook = ExcelImportSupport.buildTemplate("限制高消费导入模板", "限制高消费", CreditJudicialImportParam.class, templateList); Workbook workbook = ExcelImportSupport.buildTemplate("限制高消费导入模板", "限制高消费", CreditXgxfImportParam.class, templateList);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment; filename=credit_xgxf_import_template.xlsx"); response.setHeader("Content-Disposition", "attachment; filename=credit_xgxf_import_template.xlsx");
@@ -319,29 +590,25 @@ public class CreditXgxfController extends BaseController {
workbook.close(); workbook.close();
} }
private boolean isEmptyImportRow(CreditJudicialImportParam param) { private boolean isEmptyImportRow(CreditXgxfImportParam param) {
if (param == null) { if (param == null) {
return true; return true;
} }
return ImportHelper.isBlank(param.getCaseNumber()) return ImportHelper.isBlank(param.getCaseNumber());
&& ImportHelper.isBlank(param.getPlaintiffAppellant())
&& ImportHelper.isBlank(param.getAppellee())
&& ImportHelper.isBlank(param.getCauseOfAction());
} }
private CreditXgxf convertImportParamToEntity(CreditJudicialImportParam param) { private CreditXgxf convertImportParamToEntity(CreditXgxfImportParam param) {
CreditXgxf entity = new CreditXgxf(); CreditXgxf entity = new CreditXgxf();
entity.setCaseNumber(param.getCaseNumber());
entity.setType(param.getType());
entity.setDataType(param.getDataType()); entity.setDataType(param.getDataType());
entity.setPlaintiffAppellant(param.getPlaintiffAppellant()); entity.setPlaintiffAppellant(param.getPlaintiffAppellant());
entity.setAppellee(param.getAppellee()); entity.setAppellee(param.getAppellee());
entity.setOtherPartiesThirdParty(param.getOtherPartiesThirdParty());
entity.setOccurrenceTime(param.getOccurrenceTime());
entity.setCaseNumber(param.getCaseNumber());
entity.setCauseOfAction(param.getCauseOfAction());
entity.setInvolvedAmount(param.getInvolvedAmount()); entity.setInvolvedAmount(param.getInvolvedAmount());
entity.setOccurrenceTime(param.getOccurrenceTime());
entity.setCourtName(param.getCourtName()); entity.setCourtName(param.getCourtName());
entity.setDataStatus(param.getDataStatus()); entity.setReleaseDate(param.getReleaseDate());
entity.setComments(param.getComments()); entity.setComments(param.getComments());
return entity; return entity;

View File

@@ -287,6 +287,109 @@ public class ExcelImportSupport {
} }
} }
/**
* 读取两列(由表头名定位)的文本/超链接返回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) { private static int findColumnIndexByHeader(Sheet sheet, int titleRows, int headRows, String headerName) {
int firstHeaderRow = Math.max(0, titleRows); int firstHeaderRow = Math.max(0, titleRows);
int lastHeaderRow = Math.max(0, titleRows + headRows - 1); int lastHeaderRow = Math.max(0, titleRows + headRows - 1);

View File

@@ -37,7 +37,7 @@ public class CreditAdministrativeLicense implements Serializable {
@Schema(description = "许可状态") @Schema(description = "许可状态")
private String statusText; private String statusText;
@Schema(description = "许可类") @Schema(description = "许可类")
private String type; private String type;
@Schema(description = "链接") @Schema(description = "链接")
@@ -59,12 +59,19 @@ public class CreditAdministrativeLicense implements Serializable {
@Schema(description = "数据来源单位") @Schema(description = "数据来源单位")
private String dataSourceUnit; private String dataSourceUnit;
@Schema(description = "是否有数据")
private Boolean hasData;
@Schema(description = "备注") @Schema(description = "备注")
private String comments; private String comments;
@Schema(description = "企业ID") @Schema(description = "企业ID")
private Integer companyId; private Integer companyId;
@Schema(description = "主体企业")
@TableField(exist = false)
private String companyName;
@Schema(description = "是否推荐") @Schema(description = "是否推荐")
private Integer recommend; private Integer recommend;
@@ -81,6 +88,10 @@ public class CreditAdministrativeLicense implements Serializable {
@Schema(description = "用户ID") @Schema(description = "用户ID")
private Integer userId; private Integer userId;
@Schema(description = "真实姓名")
@TableField(exist = false)
private String realName;
@Schema(description = "租户id") @Schema(description = "租户id")
private Integer tenantId; private Integer tenantId;

View File

@@ -1,6 +1,7 @@
package com.gxwebsoft.credit.entity; package com.gxwebsoft.credit.entity;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic; import com.baomidou.mybatisplus.annotation.TableLogic;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
@@ -45,12 +46,19 @@ public class CreditBankruptcy implements Serializable {
@Schema(description = "公开日期") @Schema(description = "公开日期")
private String publicDate; private String publicDate;
@Schema(description = "是否有数据")
private Boolean hasData;
@Schema(description = "备注") @Schema(description = "备注")
private String comments; private String comments;
@Schema(description = "企业ID") @Schema(description = "企业ID")
private Integer companyId; private Integer companyId;
@Schema(description = "主体企业")
@TableField(exist = false)
private String companyName;
@Schema(description = "是否推荐") @Schema(description = "是否推荐")
private Integer recommend; private Integer recommend;
@@ -67,6 +75,10 @@ public class CreditBankruptcy implements Serializable {
@Schema(description = "用户ID") @Schema(description = "用户ID")
private Integer userId; private Integer userId;
@Schema(description = "真实姓名")
@TableField(exist = false)
private String realName;
@Schema(description = "租户id") @Schema(description = "租户id")
private Integer tenantId; private Integer tenantId;

View File

@@ -1,6 +1,7 @@
package com.gxwebsoft.credit.entity; package com.gxwebsoft.credit.entity;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic; import com.baomidou.mybatisplus.annotation.TableLogic;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
@@ -45,12 +46,19 @@ public class CreditBranch implements Serializable {
@Schema(description = "状态") @Schema(description = "状态")
private String statusText; private String statusText;
@Schema(description = "是否有数据")
private Boolean hasData;
@Schema(description = "备注") @Schema(description = "备注")
private String comments; private String comments;
@Schema(description = "企业ID") @Schema(description = "企业ID")
private Integer companyId; private Integer companyId;
@Schema(description = "主题企业")
@TableField(exist = false)
private String companyName;
@Schema(description = "是否推荐") @Schema(description = "是否推荐")
private Integer recommend; private Integer recommend;
@@ -67,6 +75,10 @@ public class CreditBranch implements Serializable {
@Schema(description = "用户ID") @Schema(description = "用户ID")
private Integer userId; private Integer userId;
@Schema(description = "真实姓名")
@TableField(exist = false)
private String realName;
@Schema(description = "租户id") @Schema(description = "租户id")
private Integer tenantId; private Integer tenantId;

View File

@@ -30,34 +30,39 @@ public class CreditBreachOfTrust implements Serializable {
@TableId(value = "id", type = IdType.AUTO) @TableId(value = "id", type = IdType.AUTO)
private Integer id; 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 = "数据类型") @Schema(description = "数据类型")
private String dataType; private String dataType;
@Schema(description = "原告/上诉人") @Schema(description = "链接地址")
private String plaintiffAppellant; private String url;
@Schema(description = "被告/被上诉人")
@TableField("Appellee")
private String appellee;
@Schema(description = "其他当事人/第三人") @Schema(description = "其他当事人/第三人")
private String otherPartiesThirdParty; private String otherPartiesThirdParty;
@Schema(description = "发生时间")
private String occurrenceTime;
@Schema(description = "案号")
private String caseNumber;
@Schema(description = "案由") @Schema(description = "案由")
private String causeOfAction; private String causeOfAction;
@Schema(description = "涉案金额")
private String involvedAmount;
@Schema(description = "法院")
private String courtName;
@Schema(description = "数据状态") @Schema(description = "数据状态")
private String dataStatus; private String dataStatus;
@@ -68,6 +73,9 @@ public class CreditBreachOfTrust implements Serializable {
@TableField(exist = false) @TableField(exist = false)
private String companyName; private String companyName;
@Schema(description = "是否有数据")
private Boolean hasData;
@Schema(description = "备注") @Schema(description = "备注")
private String comments; private String comments;
@@ -87,6 +95,10 @@ public class CreditBreachOfTrust implements Serializable {
@Schema(description = "用户ID") @Schema(description = "用户ID")
private Integer userId; private Integer userId;
@Schema(description = "真实姓名")
@TableField(exist = false)
private String realName;
@Schema(description = "租户id") @Schema(description = "租户id")
private Integer tenantId; private Integer tenantId;

View File

@@ -37,18 +37,20 @@ public class CreditCaseFiling implements Serializable {
private String plaintiffAppellant; private String plaintiffAppellant;
@Schema(description = "被告/被上诉人") @Schema(description = "被告/被上诉人")
@TableField("Appellee")
private String appellee; private String appellee;
@Schema(description = "其他当事人/第三人") @Schema(description = "其他当事人/第三人")
private String otherPartiesThirdParty; private String otherPartiesThirdParty;
@Schema(description = "发生时间") @Schema(description = "立案日期")
private String occurrenceTime; private String occurrenceTime;
@Schema(description = "案号") @Schema(description = "案号")
private String caseNumber; private String caseNumber;
@Schema(description = "项目网址")
private String url;
@Schema(description = "案由") @Schema(description = "案由")
private String causeOfAction; private String causeOfAction;
@@ -68,6 +70,9 @@ public class CreditCaseFiling implements Serializable {
@TableField(exist = false) @TableField(exist = false)
private String companyName; private String companyName;
@Schema(description = "是否有数据")
private Boolean hasData;
@Schema(description = "备注") @Schema(description = "备注")
private String comments; private String comments;
@@ -87,6 +92,10 @@ public class CreditCaseFiling implements Serializable {
@Schema(description = "用户ID") @Schema(description = "用户ID")
private Integer userId; private Integer userId;
@Schema(description = "真实姓名")
@TableField(exist = false)
private String realName;
@Schema(description = "租户id") @Schema(description = "租户id")
private Integer tenantId; private Integer tenantId;

View File

@@ -1,6 +1,7 @@
package com.gxwebsoft.credit.entity; package com.gxwebsoft.credit.entity;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic; import com.baomidou.mybatisplus.annotation.TableLogic;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
@@ -33,18 +34,6 @@ public class CreditCompany implements Serializable {
@Schema(description = "系统匹配企业名称") @Schema(description = "系统匹配企业名称")
private String matchName; private String matchName;
@Schema(description = "统一社会信用代码")
private String code;
@Schema(description = "项目网址")
private String url;
@Schema(description = "类型")
private Integer type;
@Schema(description = "上级id, 0是顶级")
private Integer parentId;
@Schema(description = "登记状态") @Schema(description = "登记状态")
private String registrationStatus; private String registrationStatus;
@@ -60,9 +49,21 @@ public class CreditCompany implements Serializable {
@Schema(description = "成立日期") @Schema(description = "成立日期")
private String establishDate; private String establishDate;
@Schema(description = "统一社会信用代码")
private String code;
@Schema(description = "企业地址") @Schema(description = "企业地址")
private String address; private String address;
@Schema(description = "所属省份")
private String province;
@Schema(description = "所属城市")
private String city;
@Schema(description = "所属区县")
private String region;
@Schema(description = "电话") @Schema(description = "电话")
private String tel; private String tel;
@@ -75,18 +76,6 @@ public class CreditCompany implements Serializable {
@Schema(description = "更多邮箱") @Schema(description = "更多邮箱")
private String moreEmail; 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 = "企业(机构)类型") @Schema(description = "企业(机构)类型")
private String institutionType; private String institutionType;
@@ -180,6 +169,94 @@ public class CreditCompany implements Serializable {
@Schema(description = "是否小微企业") @Schema(description = "是否小微企业")
private String smallEnterprise; private String smallEnterprise;
@Schema(description = "项目网址")
private String url;
@Schema(description = "类型")
private Integer type;
@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 = "备注") @Schema(description = "备注")
private String comments; private String comments;
@@ -199,6 +276,10 @@ public class CreditCompany implements Serializable {
@Schema(description = "用户ID") @Schema(description = "用户ID")
private Integer userId; private Integer userId;
@Schema(description = "真实姓名")
@TableField(exist = false)
private String realName;
@Schema(description = "租户id") @Schema(description = "租户id")
private Integer tenantId; private Integer tenantId;

View File

@@ -31,7 +31,10 @@ public class CreditCompetitor implements Serializable {
private Integer id; private Integer id;
@Schema(description = "企业名称") @Schema(description = "企业名称")
private String companyName; private String name;
@Schema(description = "链接地址")
private String url;
@Schema(description = "法定代表人") @Schema(description = "法定代表人")
private String legalRepresentative; private String legalRepresentative;
@@ -52,12 +55,19 @@ public class CreditCompetitor implements Serializable {
private String province; private String province;
@Schema(description = "企业ID") @Schema(description = "企业ID")
private Integer companyId; private Integer companyId;
@Schema(description = "企业名称")
@TableField(exist = false)
private String companyName;
@Schema(description = "所属企业名称") @Schema(description = "所属企业名称")
@TableField(exist = false) @TableField(exist = false)
private String mainCompanyName; private String mainCompanyName;
@Schema(description = "是否有数据")
private Boolean hasData;
@Schema(description = "备注") @Schema(description = "备注")
private String comments; private String comments;
@@ -77,6 +87,10 @@ public class CreditCompetitor implements Serializable {
@Schema(description = "用户ID") @Schema(description = "用户ID")
private Integer userId; private Integer userId;
@Schema(description = "真实姓名")
@TableField(exist = false)
private String realName;
@Schema(description = "租户id") @Schema(description = "租户id")
private Integer tenantId; private Integer tenantId;

View File

@@ -30,28 +30,30 @@ public class CreditCourtAnnouncement implements Serializable {
@TableId(value = "id", type = IdType.AUTO) @TableId(value = "id", type = IdType.AUTO)
private Integer id; private Integer id;
@Schema(description = "数据类型")
private String dataType;
@Schema(description = "原告/上诉人")
private String plaintiffAppellant;
@Schema(description = "被告/被上诉人")
@TableField("Appellee")
private String appellee;
@Schema(description = "其他当事人/第三人")
private String otherPartiesThirdParty;
@Schema(description = "发生时间")
private String occurrenceTime;
@Schema(description = "案号") @Schema(description = "案号")
private String caseNumber; private String caseNumber;
@Schema(description = "案由") @Schema(description = "案由")
private String causeOfAction; 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 = "涉案金额") @Schema(description = "涉案金额")
private String involvedAmount; private String involvedAmount;
@@ -68,6 +70,9 @@ public class CreditCourtAnnouncement implements Serializable {
@TableField(exist = false) @TableField(exist = false)
private String companyName; private String companyName;
@Schema(description = "是否有数据")
private Boolean hasData;
@Schema(description = "备注") @Schema(description = "备注")
private String comments; private String comments;
@@ -87,6 +92,10 @@ public class CreditCourtAnnouncement implements Serializable {
@Schema(description = "用户ID") @Schema(description = "用户ID")
private Integer userId; private Integer userId;
@Schema(description = "真实姓名")
@TableField(exist = false)
private String realName;
@Schema(description = "租户id") @Schema(description = "租户id")
private Integer tenantId; private Integer tenantId;

View File

@@ -37,7 +37,6 @@ public class CreditCourtSession implements Serializable {
private String plaintiffAppellant; private String plaintiffAppellant;
@Schema(description = "被告/被上诉人") @Schema(description = "被告/被上诉人")
@TableField("Appellee")
private String appellee; private String appellee;
@Schema(description = "其他当事人/第三人") @Schema(description = "其他当事人/第三人")
@@ -49,6 +48,9 @@ public class CreditCourtSession implements Serializable {
@Schema(description = "案号") @Schema(description = "案号")
private String caseNumber; private String caseNumber;
@Schema(description = "链接地址")
private String url;
@Schema(description = "案由") @Schema(description = "案由")
private String causeOfAction; private String causeOfAction;
@@ -68,6 +70,9 @@ public class CreditCourtSession implements Serializable {
@TableField(exist = false) @TableField(exist = false)
private String companyName; private String companyName;
@Schema(description = "是否有数据")
private Boolean hasData;
@Schema(description = "备注") @Schema(description = "备注")
private String comments; private String comments;
@@ -87,6 +92,10 @@ public class CreditCourtSession implements Serializable {
@Schema(description = "用户ID") @Schema(description = "用户ID")
private Integer userId; private Integer userId;
@Schema(description = "真实姓名")
@TableField(exist = false)
private String realName;
@Schema(description = "租户id") @Schema(description = "租户id")
private Integer tenantId; private Integer tenantId;

View File

@@ -33,6 +33,9 @@ public class CreditCustomer implements Serializable {
@Schema(description = "客户") @Schema(description = "客户")
private String name; private String name;
@Schema(description = "链接地址")
private String url;
@Schema(description = "状态") @Schema(description = "状态")
private String statusTxt; private String statusTxt;
@@ -52,6 +55,9 @@ public class CreditCustomer implements Serializable {
@TableField(exist = false) @TableField(exist = false)
private String companyName; private String companyName;
@Schema(description = "是否有数据")
private Boolean hasData;
@Schema(description = "备注") @Schema(description = "备注")
private String comments; private String comments;
@@ -71,6 +77,10 @@ public class CreditCustomer implements Serializable {
@Schema(description = "用户ID") @Schema(description = "用户ID")
private Integer userId; private Integer userId;
@Schema(description = "真实姓名")
@TableField(exist = false)
private String realName;
@Schema(description = "租户id") @Schema(description = "租户id")
private Integer tenantId; private Integer tenantId;

View File

@@ -30,36 +30,39 @@ public class CreditDeliveryNotice implements Serializable {
@TableId(value = "id", type = IdType.AUTO) @TableId(value = "id", type = IdType.AUTO)
private Integer id; private Integer id;
@Schema(description = "数据类型") @Schema(description = "案号")
private String dataType; private String caseNumber;
@Schema(description = "原告/上诉人") @Schema(description = "链接地址")
private String plaintiffAppellant; private String url;
@Schema(description = "被告/被上诉人") @Schema(description = "案由")
@TableField("Appellee") private String causeOfAction;
private String appellee;
@Schema(description = "其他当事人/第三") @Schema(description = "当事")
private String otherPartiesThirdParty; private String otherPartiesThirdParty;
@Schema(description = "发生时间") @Schema(description = "法院")
private String occurrenceTime; private String courtName;
@Schema(description = "案号") @Schema(description = "发布日期")
private String caseNumber; private String occurrenceTime;
@Schema(description = "案由") // @Schema(description = "数据类型")
private String causeOfAction; // private String dataType;
//
// @Schema(description = "原告/上诉人")
// private String plaintiffAppellant;
//
// @Schema(description = "被告/被上诉人")
// @TableField("Appellee")
// private String appellee;
@Schema(description = "涉案金额") // @Schema(description = "涉案金额")
private String involvedAmount; // private String involvedAmount;
//
@Schema(description = "法院") // @Schema(description = "数据状态")
private String courtName; // private String dataStatus;
@Schema(description = "数据状态")
private String dataStatus;
@Schema(description = "企业ID") @Schema(description = "企业ID")
private Integer companyId; private Integer companyId;
@@ -68,6 +71,9 @@ public class CreditDeliveryNotice implements Serializable {
@TableField(exist = false) @TableField(exist = false)
private String companyName; private String companyName;
@Schema(description = "是否有数据")
private Boolean hasData;
@Schema(description = "备注") @Schema(description = "备注")
private String comments; private String comments;
@@ -87,6 +93,10 @@ public class CreditDeliveryNotice implements Serializable {
@Schema(description = "用户ID") @Schema(description = "用户ID")
private Integer userId; private Integer userId;
@Schema(description = "真实姓名")
@TableField(exist = false)
private String realName;
@Schema(description = "租户id") @Schema(description = "租户id")
private Integer tenantId; private Integer tenantId;

View File

@@ -33,10 +33,13 @@ public class CreditExternal implements Serializable {
@Schema(description = "被投资企业名称") @Schema(description = "被投资企业名称")
private String name; private String name;
@Schema(description = "企业状态(如存续、注销等)") @Schema(description = "状态")
private String statusTxt; private String statusTxt;
@Schema(description = "法定代表人姓名") @Schema(description = "链接地址")
private String url;
@Schema(description = "法定代表人")
private String legalRepresentative; private String legalRepresentative;
@Schema(description = "注册资本(金额)") @Schema(description = "注册资本(金额)")
@@ -79,6 +82,9 @@ public class CreditExternal implements Serializable {
@TableField(exist = false) @TableField(exist = false)
private String companyName; private String companyName;
@Schema(description = "是否有数据")
private Boolean hasData;
@Schema(description = "备注") @Schema(description = "备注")
private String comments; private String comments;
@@ -98,6 +104,10 @@ public class CreditExternal implements Serializable {
@Schema(description = "用户ID") @Schema(description = "用户ID")
private Integer userId; private Integer userId;
@Schema(description = "真实姓名")
@TableField(exist = false)
private String realName;
@Schema(description = "租户id") @Schema(description = "租户id")
private Integer tenantId; private Integer tenantId;

View File

@@ -30,36 +30,32 @@ public class CreditFinalVersion implements Serializable {
@TableId(value = "id", type = IdType.AUTO) @TableId(value = "id", type = IdType.AUTO)
private Integer id; private Integer id;
@Schema(description = "数据类型")
private String dataType;
@Schema(description = "原告/上诉人")
private String plaintiffAppellant;
@Schema(description = "被告/被上诉人")
@TableField("Appellee")
private String appellee;
@Schema(description = "其他当事人/第三人")
private String otherPartiesThirdParty;
@Schema(description = "发生时间")
private String occurrenceTime;
@Schema(description = "案号") @Schema(description = "案号")
private String caseNumber; private String caseNumber;
@Schema(description = "案由") @Schema(description = "链接地址")
private String causeOfAction; private String url;
@Schema(description = "涉案金额") @Schema(description = "被执行人")
private String appellee;
@Schema(description = "疑似申请执行人")
private String plaintiffAppellant;
@Schema(description = "未履行金额(元)")
private String unfulfilledAmount;
@Schema(description = "执行标的(元)")
private String involvedAmount; private String involvedAmount;
@Schema(description = "法院") @Schema(description = "执行法院")
private String courtName; private String courtName;
@Schema(description = "数据状态") @Schema(description = "立案日期")
private String dataStatus; private String occurrenceTime;
@Schema(description = "终本日期")
private String finalDate;
@Schema(description = "企业ID") @Schema(description = "企业ID")
private Integer companyId; private Integer companyId;
@@ -68,6 +64,9 @@ public class CreditFinalVersion implements Serializable {
@TableField(exist = false) @TableField(exist = false)
private String companyName; private String companyName;
@Schema(description = "是否有数据")
private Boolean hasData;
@Schema(description = "备注") @Schema(description = "备注")
private String comments; private String comments;
@@ -87,6 +86,10 @@ public class CreditFinalVersion implements Serializable {
@Schema(description = "用户ID") @Schema(description = "用户ID")
private Integer userId; private Integer userId;
@Schema(description = "真实姓名")
@TableField(exist = false)
private String realName;
@Schema(description = "租户id") @Schema(description = "租户id")
private Integer tenantId; private Integer tenantId;

View File

@@ -30,37 +30,39 @@ public class CreditGqdj implements Serializable {
@TableId(value = "id", type = IdType.AUTO) @TableId(value = "id", type = IdType.AUTO)
private Integer id; private Integer id;
@Schema(description = "数据类型") @Schema(description = "执行通知文书号")
private String dataType;
@Schema(description = "原告/上诉人")
private String plaintiffAppellant;
@Schema(description = "被告/被上诉人")
@TableField("Appellee")
private String appellee;
@Schema(description = "其他当事人/第三人")
private String otherPartiesThirdParty;
@Schema(description = "发生时间")
private String occurrenceTime;
@Schema(description = "案号")
private String caseNumber; private String caseNumber;
@Schema(description = "案由") @Schema(description = "被执行人")
private String causeOfAction; private String appellee;
@Schema(description = "涉案金额") @Schema(description = "冻结股权标的企业")
private String plaintiffAppellant;
@Schema(description = "被执行人持有股权、其他投资权益数额")
private String involvedAmount; private String involvedAmount;
@Schema(description = "法院") @Schema(description = "执行法院")
private String courtName; private String courtName;
@Schema(description = "数据状态") @Schema(description = "类型")
private String dataType;
@Schema(description = "状态")
private String dataStatus; 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") @Schema(description = "企业ID")
private Integer companyId; private Integer companyId;
@@ -68,6 +70,9 @@ public class CreditGqdj implements Serializable {
@TableField(exist = false) @TableField(exist = false)
private String companyName; private String companyName;
@Schema(description = "是否有数据")
private Boolean hasData;
@Schema(description = "备注") @Schema(description = "备注")
private String comments; private String comments;
@@ -87,6 +92,10 @@ public class CreditGqdj implements Serializable {
@Schema(description = "用户ID") @Schema(description = "用户ID")
private Integer userId; private Integer userId;
@Schema(description = "真实姓名")
@TableField(exist = false)
private String realName;
@Schema(description = "租户id") @Schema(description = "租户id")
private Integer tenantId; private Integer tenantId;

View File

@@ -1,6 +1,7 @@
package com.gxwebsoft.credit.entity; package com.gxwebsoft.credit.entity;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic; import com.baomidou.mybatisplus.annotation.TableLogic;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
@@ -39,12 +40,19 @@ public class CreditHistoricalLegalPerson implements Serializable {
@Schema(description = "链接") @Schema(description = "链接")
private String url; private String url;
@Schema(description = "是否有数据")
private Boolean hasData;
@Schema(description = "备注") @Schema(description = "备注")
private String comments; private String comments;
@Schema(description = "企业ID") @Schema(description = "企业ID")
private Integer companyId; private Integer companyId;
@Schema(description = "主体企业")
@TableField(exist = false)
private String companyName;
@Schema(description = "是否推荐") @Schema(description = "是否推荐")
private Integer recommend; private Integer recommend;
@@ -61,6 +69,10 @@ public class CreditHistoricalLegalPerson implements Serializable {
@Schema(description = "用户ID") @Schema(description = "用户ID")
private Integer userId; private Integer userId;
@Schema(description = "真实姓名")
@TableField(exist = false)
private String realName;
@Schema(description = "租户id") @Schema(description = "租户id")
private Integer tenantId; private Integer tenantId;

View File

@@ -65,6 +65,9 @@ public class CreditJudgmentDebtor implements Serializable {
@TableField(exist = false) @TableField(exist = false)
private String companyName; private String companyName;
@Schema(description = "是否有数据")
private Boolean hasData;
@Schema(description = "备注") @Schema(description = "备注")
private String comments; private String comments;
@@ -84,6 +87,10 @@ public class CreditJudgmentDebtor implements Serializable {
@Schema(description = "用户ID") @Schema(description = "用户ID")
private Integer userId; private Integer userId;
@Schema(description = "真实姓名")
@TableField(exist = false)
private String realName;
@Schema(description = "租户id") @Schema(description = "租户id")
private Integer tenantId; private Integer tenantId;

View File

@@ -1,93 +0,0 @@
package com.gxwebsoft.credit.entity;
import com.baomidou.mybatisplus.annotation.IdType;
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-12 08:10:43
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Schema(name = "CreditJudgmentDebtorHistory对象", description = "被执行人")
public class CreditJudgmentDebtorHistory 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 code;
@Schema(description = "链接")
private String url;
@Schema(description = "是否多企业")
private Integer type;
@Schema(description = "立案日期")
private String occurrenceTime;
@Schema(description = "执行标的(元)")
private String amount;
@Schema(description = "法院")
private String courtName;
@Schema(description = "数据状态")
private String dataStatus;
@Schema(description = "企业ID")
private Integer companyId;
@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 = "租户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;
}

View File

@@ -30,31 +30,36 @@ public class CreditJudicialDocument implements Serializable {
@TableId(value = "id", type = IdType.AUTO) @TableId(value = "id", type = IdType.AUTO)
private Integer id; private Integer id;
@Schema(description = "数据类型") @Schema(description = "文书标题")
private String dataType; private String title;
@Schema(description = "原告/上诉人")
private String plaintiffAppellant;
@Schema(description = "被告/被上诉人")
@TableField("Appellee")
private String appellee;
@Schema(description = "其他当事人/第三人")
private String otherPartiesThirdParty;
@Schema(description = "发生时间")
private String occurrenceTime;
@Schema(description = "案号") @Schema(description = "案号")
private String caseNumber; private String caseNumber;
@Schema(description = "链接地址")
private String url;
@Schema(description = "案由") @Schema(description = "案由")
private String causeOfAction; private String causeOfAction;
@Schema(description = "涉案金额") @Schema(description = "当事人")
private String otherPartiesThirdParty;
@Schema(description = "案件金额(元)")
private String involvedAmount; 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 = "法院") @Schema(description = "法院")
private String courtName; private String courtName;
@@ -68,6 +73,9 @@ public class CreditJudicialDocument implements Serializable {
@TableField(exist = false) @TableField(exist = false)
private String companyName; private String companyName;
@Schema(description = "是否有数据")
private Boolean hasData;
@Schema(description = "备注") @Schema(description = "备注")
private String comments; private String comments;
@@ -87,6 +95,10 @@ public class CreditJudicialDocument implements Serializable {
@Schema(description = "用户ID") @Schema(description = "用户ID")
private Integer userId; private Integer userId;
@Schema(description = "真实姓名")
@TableField(exist = false)
private String realName;
@Schema(description = "租户id") @Schema(description = "租户id")
private Integer tenantId; private Integer tenantId;

View File

@@ -34,6 +34,9 @@ public class CreditJudiciary implements Serializable {
@Schema(description = "案号") @Schema(description = "案号")
private String code; private String code;
@Schema(description = "详情链接")
private String url;
@Schema(description = "类型, 0普通用户, 1招投标") @Schema(description = "类型, 0普通用户, 1招投标")
private Integer type; private Integer type;
@@ -83,6 +86,9 @@ public class CreditJudiciary implements Serializable {
@TableField(exist = false) @TableField(exist = false)
private String companyName; private String companyName;
@Schema(description = "是否有数据")
private Boolean hasData;
@Schema(description = "备注") @Schema(description = "备注")
private String comments; private String comments;
@@ -106,6 +112,10 @@ public class CreditJudiciary implements Serializable {
@Schema(description = "用户ID") @Schema(description = "用户ID")
private Integer userId; private Integer userId;
@Schema(description = "真实姓名")
@TableField(exist = false)
private String realName;
@Schema(description = "租户id") @Schema(description = "租户id")
private Integer tenantId; private Integer tenantId;

View File

@@ -37,7 +37,6 @@ public class CreditMediation implements Serializable {
private String plaintiffAppellant; private String plaintiffAppellant;
@Schema(description = "被告/被上诉人") @Schema(description = "被告/被上诉人")
@TableField("Appellee")
private String appellee; private String appellee;
@Schema(description = "其他当事人/第三人") @Schema(description = "其他当事人/第三人")
@@ -49,6 +48,9 @@ public class CreditMediation implements Serializable {
@Schema(description = "案号") @Schema(description = "案号")
private String caseNumber; private String caseNumber;
@Schema(description = "链接地址")
private String url;
@Schema(description = "案由") @Schema(description = "案由")
private String causeOfAction; private String causeOfAction;
@@ -68,6 +70,9 @@ public class CreditMediation implements Serializable {
@TableField(exist = false) @TableField(exist = false)
private String companyName; private String companyName;
@Schema(description = "是否有数据")
private Boolean hasData;
@Schema(description = "备注") @Schema(description = "备注")
private String comments; private String comments;
@@ -87,6 +92,10 @@ public class CreditMediation implements Serializable {
@Schema(description = "用户ID") @Schema(description = "用户ID")
private Integer userId; private Integer userId;
@Schema(description = "真实姓名")
@TableField(exist = false)
private String realName;
@Schema(description = "租户id") @Schema(description = "租户id")
private Integer tenantId; private Integer tenantId;

View File

@@ -1,6 +1,7 @@
package com.gxwebsoft.credit.entity; package com.gxwebsoft.credit.entity;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic; import com.baomidou.mybatisplus.annotation.TableLogic;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
@@ -78,6 +79,10 @@ public class CreditNearbyCompany implements Serializable {
@Schema(description = "企业ID") @Schema(description = "企业ID")
private Integer companyId; private Integer companyId;
@Schema(description = "主体企业")
@TableField(exist = false)
private String companyName;
@Schema(description = "纳税人识别号") @Schema(description = "纳税人识别号")
private String taxpayerCode; private String taxpayerCode;
@@ -189,6 +194,9 @@ public class CreditNearbyCompany implements Serializable {
@Schema(description = "是否小微企业") @Schema(description = "是否小微企业")
private String smallEnterprise; private String smallEnterprise;
@Schema(description = "是否有数据")
private Boolean hasData;
@Schema(description = "备注") @Schema(description = "备注")
private String comments; private String comments;
@@ -208,6 +216,10 @@ public class CreditNearbyCompany implements Serializable {
@Schema(description = "用户ID") @Schema(description = "用户ID")
private Integer userId; private Integer userId;
@Schema(description = "真实姓名")
@TableField(exist = false)
private String realName;
@Schema(description = "租户id") @Schema(description = "租户id")
private Integer tenantId; private Integer tenantId;

View File

@@ -1,6 +1,7 @@
package com.gxwebsoft.credit.entity; package com.gxwebsoft.credit.entity;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic; import com.baomidou.mybatisplus.annotation.TableLogic;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
@@ -57,12 +58,19 @@ public class CreditPatent implements Serializable {
@Schema(description = "链接") @Schema(description = "链接")
private String url; private String url;
@Schema(description = "是否有数据")
private Boolean hasData;
@Schema(description = "备注") @Schema(description = "备注")
private String comments; private String comments;
@Schema(description = "企业ID") @Schema(description = "企业ID")
private Integer companyId; private Integer companyId;
@Schema(description = "主体企业")
@TableField(exist = false)
private String companyName;
@Schema(description = "是否推荐") @Schema(description = "是否推荐")
private Integer recommend; private Integer recommend;
@@ -79,6 +87,10 @@ public class CreditPatent implements Serializable {
@Schema(description = "用户ID") @Schema(description = "用户ID")
private Integer userId; private Integer userId;
@Schema(description = "真实姓名")
@TableField(exist = false)
private String realName;
@Schema(description = "租户id") @Schema(description = "租户id")
private Integer tenantId; private Integer tenantId;

View File

@@ -54,6 +54,9 @@ public class CreditRiskRelation implements Serializable {
@TableField(exist = false) @TableField(exist = false)
private String companyName; private String companyName;
@Schema(description = "是否有数据")
private Boolean hasData;
@Schema(description = "备注") @Schema(description = "备注")
private String comments; private String comments;
@@ -73,6 +76,10 @@ public class CreditRiskRelation implements Serializable {
@Schema(description = "用户ID") @Schema(description = "用户ID")
private Integer userId; private Integer userId;
@Schema(description = "真实姓名")
@TableField(exist = false)
private String realName;
@Schema(description = "租户id") @Schema(description = "租户id")
private Integer tenantId; private Integer tenantId;

View File

@@ -33,6 +33,9 @@ public class CreditSupplier implements Serializable {
@Schema(description = "供应商") @Schema(description = "供应商")
private String supplier; private String supplier;
@Schema(description = "链接地址")
private String url;
@Schema(description = "状态") @Schema(description = "状态")
private String statusTxt; private String statusTxt;
@@ -52,6 +55,9 @@ public class CreditSupplier implements Serializable {
@TableField(exist = false) @TableField(exist = false)
private String companyName; private String companyName;
@Schema(description = "是否有数据")
private Boolean hasData;
@Schema(description = "备注") @Schema(description = "备注")
private String comments; private String comments;
@@ -71,6 +77,10 @@ public class CreditSupplier implements Serializable {
@Schema(description = "用户ID") @Schema(description = "用户ID")
private Integer userId; private Integer userId;
@Schema(description = "真实姓名")
@TableField(exist = false)
private String realName;
@Schema(description = "租户id") @Schema(description = "租户id")
private Integer tenantId; private Integer tenantId;

View File

@@ -1,6 +1,7 @@
package com.gxwebsoft.credit.entity; package com.gxwebsoft.credit.entity;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic; import com.baomidou.mybatisplus.annotation.TableLogic;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
@@ -54,12 +55,19 @@ public class CreditSuspectedRelationship implements Serializable {
@Schema(description = "链接") @Schema(description = "链接")
private String url; private String url;
@Schema(description = "是否有数据")
private Boolean hasData;
@Schema(description = "备注") @Schema(description = "备注")
private String comments; private String comments;
@Schema(description = "企业ID") @Schema(description = "企业ID")
private Integer companyId; private Integer companyId;
@Schema(description = "主体企业")
@TableField(exist = false)
private String companyName;
@Schema(description = "是否推荐") @Schema(description = "是否推荐")
private Integer recommend; private Integer recommend;
@@ -76,6 +84,10 @@ public class CreditSuspectedRelationship implements Serializable {
@Schema(description = "用户ID") @Schema(description = "用户ID")
private Integer userId; private Integer userId;
@Schema(description = "真实姓名")
@TableField(exist = false)
private String realName;
@Schema(description = "租户id") @Schema(description = "租户id")
private Integer tenantId; private Integer tenantId;

View File

@@ -82,6 +82,9 @@ public class CreditUser implements Serializable {
@TableField(exist = false) @TableField(exist = false)
private String companyName; private String companyName;
@Schema(description = "是否有数据")
private Boolean hasData;
@Schema(description = "备注") @Schema(description = "备注")
private String comments; private String comments;
@@ -101,6 +104,10 @@ public class CreditUser implements Serializable {
@Schema(description = "用户ID") @Schema(description = "用户ID")
private Integer userId; private Integer userId;
@Schema(description = "真实姓名")
@TableField(exist = false)
private String realName;
@Schema(description = "租户id") @Schema(description = "租户id")
private Integer tenantId; private Integer tenantId;

View File

@@ -30,34 +30,48 @@ public class CreditXgxf implements Serializable {
@TableId(value = "id", type = IdType.AUTO) @TableId(value = "id", type = IdType.AUTO)
private Integer id; private Integer id;
@Schema(description = "案号")
private String caseNumber;
@Schema(description = "链接地址")
private String url;
@Schema(description = "数据类型") @Schema(description = "数据类型")
private String type;
@Schema(description = "限消令对象")
private String dataType; private String dataType;
@Schema(description = "原告/上诉") @Schema(description = "限制法定代表")
private String plaintiffAppellant; private String plaintiffAppellant;
@Schema(description = "被告/被上诉") @Schema(description = "申请")
@TableField("Appellee")
private String appellee; private String appellee;
@Schema(description = "原告/上诉人")
private String plaintiffUser;
@Schema(description = "被告/被上诉人")
private String defendantUser;
@Schema(description = "涉案金额(元)")
private String involvedAmount;
@Schema(description = "立案日期")
private String occurrenceTime;
@Schema(description = "执行法院")
private String courtName;
@Schema(description = "发布日期")
private String releaseDate;
@Schema(description = "其他当事人/第三人") @Schema(description = "其他当事人/第三人")
private String otherPartiesThirdParty; private String otherPartiesThirdParty;
@Schema(description = "发生时间")
private String occurrenceTime;
@Schema(description = "案号")
private String caseNumber;
@Schema(description = "案由") @Schema(description = "案由")
private String causeOfAction; private String causeOfAction;
@Schema(description = "涉案金额")
private String involvedAmount;
@Schema(description = "法院")
private String courtName;
@Schema(description = "数据状态") @Schema(description = "数据状态")
private String dataStatus; private String dataStatus;
@@ -68,6 +82,9 @@ public class CreditXgxf implements Serializable {
@TableField(exist = false) @TableField(exist = false)
private String companyName; private String companyName;
@Schema(description = "是否有数据")
private Boolean hasData;
@Schema(description = "备注") @Schema(description = "备注")
private String comments; private String comments;
@@ -87,6 +104,10 @@ public class CreditXgxf implements Serializable {
@Schema(description = "用户ID") @Schema(description = "用户ID")
private Integer userId; private Integer userId;
@Schema(description = "真实姓名")
@TableField(exist = false)
private String realName;
@Schema(description = "租户id") @Schema(description = "租户id")
private Integer tenantId; private Integer tenantId;

View File

@@ -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.CreditJudgmentDebtorHistory;
import com.gxwebsoft.credit.param.CreditJudgmentDebtorHistoryParam;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 被执行人Mapper
*
* @author 科技小王子
* @since 2026-01-12 08:10:43
*/
public interface CreditJudgmentDebtorHistoryMapper extends BaseMapper<CreditJudgmentDebtorHistory> {
/**
* 分页查询
*
* @param page 分页对象
* @param param 查询参数
* @return List<CreditJudgmentDebtorHistory>
*/
List<CreditJudgmentDebtorHistory> selectPageRel(@Param("page") IPage<CreditJudgmentDebtorHistory> page,
@Param("param") CreditJudgmentDebtorHistoryParam param);
/**
* 查询全部
*
* @param param 查询参数
* @return List<User>
*/
List<CreditJudgmentDebtorHistory> selectListRel(@Param("param") CreditJudgmentDebtorHistoryParam param);
}

View File

@@ -4,9 +4,10 @@
<!-- 关联查询sql --> <!-- 关联查询sql -->
<sql id="selectSql"> <sql id="selectSql">
SELECT a.* SELECT a.*, b.name AS companyName, u.real_name AS realName
FROM credit_administrative_license a FROM credit_administrative_license a
LEFT JOIN credit_company b ON a.company_id = b.id LEFT JOIN credit_company b ON a.company_id = b.id
LEFT JOIN gxwebsoft_core.sys_user u ON a.user_id = u.user_id
<where> <where>
<if test="param.id != null"> <if test="param.id != null">
AND a.id = #{param.id} AND a.id = #{param.id}
@@ -73,7 +74,7 @@
</if> </if>
<if test="param.keywords != null"> <if test="param.keywords != null">
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%') AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
OR b.name = #{param.keywords} OR b.name LIKE CONCAT('%', #{param.keywords}, '%')
) )
</if> </if>
</where> </where>

View File

@@ -4,8 +4,10 @@
<!-- 关联查询sql --> <!-- 关联查询sql -->
<sql id="selectSql"> <sql id="selectSql">
SELECT a.* SELECT a.*, b.name AS companyName, u.real_name AS realName
FROM credit_bankruptcy a FROM credit_bankruptcy a
LEFT JOIN credit_company b ON a.company_id = b.id
LEFT JOIN gxwebsoft_core.sys_user u ON a.user_id = u.user_id
<where> <where>
<if test="param.id != null"> <if test="param.id != null">
@@ -61,7 +63,7 @@
</if> </if>
<if test="param.keywords != null"> <if test="param.keywords != null">
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%') AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
OR b.name = #{param.keywords} OR b.name LIKE CONCAT('%', #{param.keywords}, '%')
) )
</if> </if>
</where> </where>

View File

@@ -4,9 +4,10 @@
<!-- 关联查询sql --> <!-- 关联查询sql -->
<sql id="selectSql"> <sql id="selectSql">
SELECT a.* SELECT a.*, b.name AS companyName, u.real_name AS realName
FROM credit_branch a FROM credit_branch a
LEFT JOIN credit_company b ON a.company_id = b.id LEFT JOIN credit_company b ON a.company_id = b.id
LEFT JOIN gxwebsoft_core.sys_user u ON a.user_id = u.user_id
<where> <where>
<if test="param.id != null"> <if test="param.id != null">
AND a.id = #{param.id} AND a.id = #{param.id}
@@ -61,7 +62,7 @@
</if> </if>
<if test="param.keywords != null"> <if test="param.keywords != null">
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%') AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
OR b.name = #{param.keywords} OR b.name LIKE CONCAT('%', #{param.keywords}, '%')
) )
</if> </if>
</where> </where>

View File

@@ -4,9 +4,10 @@
<!-- 关联查询sql --> <!-- 关联查询sql -->
<sql id="selectSql"> <sql id="selectSql">
SELECT a.*, b.name AS companyName SELECT a.*, b.name AS companyName, u.real_name AS realName
FROM credit_breach_of_trust a FROM credit_breach_of_trust a
LEFT JOIN credit_company b ON a.company_id = b.id LEFT JOIN credit_company b ON a.company_id = b.id
LEFT JOIN gxwebsoft_core.sys_user u ON a.user_id = u.user_id
<where> <where>
<if test="param.id != null"> <if test="param.id != null">
AND a.id = #{param.id} AND a.id = #{param.id}
@@ -14,36 +15,24 @@
<if test="param.companyId != null"> <if test="param.companyId != null">
AND a.company_id = #{param.companyId} AND a.company_id = #{param.companyId}
</if> </if>
<if test="param.dataType != null">
AND a.data_type LIKE CONCAT('%', #{param.dataType}, '%')
</if>
<if test="param.plaintiffAppellant != null"> <if test="param.plaintiffAppellant != null">
AND a.plaintiff_appellant LIKE CONCAT('%', #{param.plaintiffAppellant}, '%') AND a.plaintiff_appellant LIKE CONCAT('%', #{param.plaintiffAppellant}, '%')
</if> </if>
<if test="param.appellee != null"> <if test="param.appellee != null">
AND a.appellee LIKE CONCAT('%', #{param.defendant appellee}, '%') AND a.appellee LIKE CONCAT('%', #{param.defendant appellee}, '%')
</if> </if>
<if test="param.otherPartiesThirdParty != null">
AND a.other_parties_third_party LIKE CONCAT('%', #{param.otherPartiesThirdParty}, '%')
</if>
<if test="param.occurrenceTime != null"> <if test="param.occurrenceTime != null">
AND a.occurrence_time LIKE CONCAT('%', #{param.occurrenceTime}, '%') AND a.occurrence_time LIKE CONCAT('%', #{param.occurrenceTime}, '%')
</if> </if>
<if test="param.caseNumber != null"> <if test="param.caseNumber != null">
AND a.case_number LIKE CONCAT('%', #{param.caseNumber}, '%') AND a.case_number LIKE CONCAT('%', #{param.caseNumber}, '%')
</if> </if>
<if test="param.causeOfAction != null">
AND a.cause_of_action LIKE CONCAT('%', #{param.causeOfAction}, '%')
</if>
<if test="param.involvedAmount != null"> <if test="param.involvedAmount != null">
AND a.involved_amount = #{param.involvedAmount} AND a.involved_amount = #{param.involvedAmount}
</if> </if>
<if test="param.courtName != null"> <if test="param.courtName != null">
AND a.court_name LIKE CONCAT('%', #{param.courtName}, '%') AND a.court_name LIKE CONCAT('%', #{param.courtName}, '%')
</if> </if>
<if test="param.dataStatus != null">
AND a.data_status LIKE CONCAT('%', #{param.dataStatus}, '%')
</if>
<if test="param.comments != null"> <if test="param.comments != null">
AND a.comments LIKE CONCAT('%', #{param.comments}, '%') AND a.comments LIKE CONCAT('%', #{param.comments}, '%')
</if> </if>
@@ -73,7 +62,8 @@
</if> </if>
<if test="param.keywords != null"> <if test="param.keywords != null">
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%') AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
OR b.name = #{param.keywords} OR a.case_number = #{param.keywords}
OR b.name LIKE CONCAT('%', #{param.keywords}, '%')
) )
</if> </if>
</where> </where>

View File

@@ -4,9 +4,10 @@
<!-- 关联查询sql --> <!-- 关联查询sql -->
<sql id="selectSql"> <sql id="selectSql">
SELECT a.*, b.name AS companyName SELECT a.*, b.name AS companyName, u.real_name AS realName
FROM credit_case_filing a FROM credit_case_filing a
LEFT JOIN credit_company b ON a.company_id = b.id LEFT JOIN credit_company b ON a.company_id = b.id
LEFT JOIN gxwebsoft_core.sys_user u ON a.user_id = u.user_id
<where> <where>
<if test="param.id != null"> <if test="param.id != null">
AND a.id = #{param.id} AND a.id = #{param.id}
@@ -73,7 +74,7 @@
</if> </if>
<if test="param.keywords != null"> <if test="param.keywords != null">
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%') AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
OR b.name = #{param.keywords} OR b.name LIKE CONCAT('%', #{param.keywords}, '%')
) )
</if> </if>
</where> </where>

View File

@@ -4,8 +4,9 @@
<!-- 关联查询sql --> <!-- 关联查询sql -->
<sql id="selectSql"> <sql id="selectSql">
SELECT a.* SELECT a.*, u.real_name AS realName
FROM credit_company a FROM credit_company a
LEFT JOIN gxwebsoft_core.sys_user u ON a.user_id = u.user_id
<where> <where>
<if test="param.id != null"> <if test="param.id != null">
AND a.id = #{param.id} AND a.id = #{param.id}

View File

@@ -4,9 +4,10 @@
<!-- 关联查询sql --> <!-- 关联查询sql -->
<sql id="selectSql"> <sql id="selectSql">
SELECT a.*, b.name AS mainCompanyName SELECT a.*, b.name AS companyName, u.real_name AS realName
FROM credit_competitor a FROM credit_competitor a
LEFT JOIN credit_company b ON a.company_id = b.id LEFT JOIN credit_company b ON a.company_id = b.id
LEFT JOIN gxwebsoft_core.sys_user u ON a.user_id = u.user_id
<where> <where>
<if test="param.id != null"> <if test="param.id != null">
AND a.id = #{param.id} AND a.id = #{param.id}
@@ -14,8 +15,8 @@
<if test="param.companyId != null"> <if test="param.companyId != null">
AND a.company_id = #{param.companyId} AND a.company_id = #{param.companyId}
</if> </if>
<if test="param.companyName != null"> <if test="param.name != null">
AND a.company_name LIKE CONCAT('%', #{param.companyName}, '%') AND a.name LIKE CONCAT('%', #{param.name}, '%')
</if> </if>
<if test="param.legalRepresentative != null"> <if test="param.legalRepresentative != null">
AND a.legal_representative LIKE CONCAT('%', #{param.legalRepresentative}, '%') AND a.legal_representative LIKE CONCAT('%', #{param.legalRepresentative}, '%')
@@ -64,7 +65,8 @@
</if> </if>
<if test="param.keywords != null"> <if test="param.keywords != null">
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%') AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
OR b.name = #{param.keywords} OR a.name LIKE CONCAT('%', #{param.keywords}, '%')
OR b.name LIKE CONCAT('%', #{param.keywords}, '%')
) )
</if> </if>
</where> </where>

View File

@@ -4,9 +4,10 @@
<!-- 关联查询sql --> <!-- 关联查询sql -->
<sql id="selectSql"> <sql id="selectSql">
SELECT a.*, b.name AS companyName SELECT a.*, b.name AS companyName, u.real_name AS realName
FROM credit_court_announcement a FROM credit_court_announcement a
LEFT JOIN credit_company b ON a.company_id = b.id LEFT JOIN credit_company b ON a.company_id = b.id
LEFT JOIN gxwebsoft_core.sys_user u ON a.user_id = u.user_id
<where> <where>
<if test="param.id != null"> <if test="param.id != null">
AND a.id = #{param.id} AND a.id = #{param.id}
@@ -73,7 +74,7 @@
</if> </if>
<if test="param.keywords != null"> <if test="param.keywords != null">
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%') AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
OR b.name = #{param.keywords} OR b.name LIKE CONCAT('%', #{param.keywords}, '%')
) )
</if> </if>
</where> </where>

View File

@@ -4,9 +4,10 @@
<!-- 关联查询sql --> <!-- 关联查询sql -->
<sql id="selectSql"> <sql id="selectSql">
SELECT a.*, b.name AS companyName SELECT a.*, b.name AS companyName, u.real_name AS realName
FROM credit_court_session a FROM credit_court_session a
LEFT JOIN credit_company b ON a.company_id = b.id LEFT JOIN credit_company b ON a.company_id = b.id
LEFT JOIN gxwebsoft_core.sys_user u ON a.user_id = u.user_id
<where> <where>
<if test="param.id != null"> <if test="param.id != null">
AND a.id = #{param.id} AND a.id = #{param.id}
@@ -73,7 +74,7 @@
</if> </if>
<if test="param.keywords != null"> <if test="param.keywords != null">
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%') AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
OR b.name = #{param.keywords} OR b.name LIKE CONCAT('%', #{param.keywords}, '%')
) )
</if> </if>
</where> </where>

View File

@@ -4,9 +4,10 @@
<!-- 关联查询sql --> <!-- 关联查询sql -->
<sql id="selectSql"> <sql id="selectSql">
SELECT a.*, b.name AS companyName SELECT a.*, b.name AS companyName, u.real_name AS realName
FROM credit_customer a FROM credit_customer a
LEFT JOIN credit_company b ON a.company_id = b.id LEFT JOIN credit_company b ON a.company_id = b.id
LEFT JOIN gxwebsoft_core.sys_user u ON a.user_id = u.user_id
<where> <where>
<if test="param.id != null"> <if test="param.id != null">
AND a.id = #{param.id} AND a.id = #{param.id}
@@ -58,7 +59,7 @@
</if> </if>
<if test="param.keywords != null"> <if test="param.keywords != null">
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%') AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
OR b.name = #{param.keywords} OR b.name LIKE CONCAT('%', #{param.keywords}, '%')
) )
</if> </if>
</where> </where>

View File

@@ -4,24 +4,16 @@
<!-- 关联查询sql --> <!-- 关联查询sql -->
<sql id="selectSql"> <sql id="selectSql">
SELECT a.*, b.name AS companyName SELECT a.*, b.name AS companyName, u.real_name AS realName
FROM credit_delivery_notice a FROM credit_delivery_notice a
LEFT JOIN credit_company b ON a.company_id = b.id LEFT JOIN credit_company b ON a.company_id = b.id
LEFT JOIN gxwebsoft_core.sys_user u ON a.user_id = u.user_id
<where> <where>
<if test="param.id != null"> <if test="param.id != null">
AND a.id = #{param.id} AND a.id = #{param.id}
</if> </if>
<if test="param.companyId != null"> <if test="param.companyId != null">
AND a.company_id = #{param.companyId} AND a.company_id = #{param.companyId}
</if>
<if test="param.dataType != null">
AND a.data_type LIKE CONCAT('%', #{param.dataType}, '%')
</if>
<if test="param.plaintiffAppellant != null">
AND a.plaintiff_appellant LIKE CONCAT('%', #{param.plaintiffAppellant}, '%')
</if>
<if test="param.appellee != null">
AND a.appellee LIKE CONCAT('%', #{param.defendant appellee}, '%')
</if> </if>
<if test="param.otherPartiesThirdParty != null"> <if test="param.otherPartiesThirdParty != null">
AND a.other_parties_third_party LIKE CONCAT('%', #{param.otherPartiesThirdParty}, '%') AND a.other_parties_third_party LIKE CONCAT('%', #{param.otherPartiesThirdParty}, '%')
@@ -35,15 +27,9 @@
<if test="param.causeOfAction != null"> <if test="param.causeOfAction != null">
AND a.cause_of_action LIKE CONCAT('%', #{param.causeOfAction}, '%') AND a.cause_of_action LIKE CONCAT('%', #{param.causeOfAction}, '%')
</if> </if>
<if test="param.involvedAmount != null">
AND a.involved_amount = #{param.involvedAmount}
</if>
<if test="param.courtName != null"> <if test="param.courtName != null">
AND a.court_name LIKE CONCAT('%', #{param.courtName}, '%') AND a.court_name LIKE CONCAT('%', #{param.courtName}, '%')
</if> </if>
<if test="param.dataStatus != null">
AND a.data_status LIKE CONCAT('%', #{param.dataStatus}, '%')
</if>
<if test="param.comments != null"> <if test="param.comments != null">
AND a.comments LIKE CONCAT('%', #{param.comments}, '%') AND a.comments LIKE CONCAT('%', #{param.comments}, '%')
</if> </if>
@@ -73,7 +59,7 @@
</if> </if>
<if test="param.keywords != null"> <if test="param.keywords != null">
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%') AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
OR b.name = #{param.keywords} OR b.name LIKE CONCAT('%', #{param.keywords}, '%')
) )
</if> </if>
</where> </where>

View File

@@ -4,9 +4,10 @@
<!-- 关联查询sql --> <!-- 关联查询sql -->
<sql id="selectSql"> <sql id="selectSql">
SELECT a.*, b.name AS companyName SELECT a.*, b.name AS companyName, u.real_name AS realName
FROM credit_external a FROM credit_external a
LEFT JOIN credit_company b ON a.company_id = b.id LEFT JOIN credit_company b ON a.company_id = b.id
LEFT JOIN gxwebsoft_core.sys_user u ON a.user_id = u.user_id
<where> <where>
<if test="param.id != null"> <if test="param.id != null">
AND a.id = #{param.id} AND a.id = #{param.id}
@@ -85,7 +86,7 @@
</if> </if>
<if test="param.keywords != null"> <if test="param.keywords != null">
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%') AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
OR b.name = #{param.keywords} OR b.name LIKE CONCAT('%', #{param.keywords}, '%')
) )
</if> </if>
</where> </where>

View File

@@ -4,9 +4,10 @@
<!-- 关联查询sql --> <!-- 关联查询sql -->
<sql id="selectSql"> <sql id="selectSql">
SELECT a.*, b.name AS companyName SELECT a.*, b.name AS companyName, u.real_name AS realName
FROM credit_final_version a FROM credit_final_version a
LEFT JOIN credit_company b ON a.company_id = b.id LEFT JOIN credit_company b ON a.company_id = b.id
LEFT JOIN gxwebsoft_core.sys_user u ON a.user_id = u.user_id
<where> <where>
<if test="param.id != null"> <if test="param.id != null">
AND a.id = #{param.id} AND a.id = #{param.id}
@@ -14,36 +15,24 @@
<if test="param.companyId != null"> <if test="param.companyId != null">
AND a.company_id = #{param.companyId} AND a.company_id = #{param.companyId}
</if> </if>
<if test="param.dataType != null">
AND a.data_type LIKE CONCAT('%', #{param.dataType}, '%')
</if>
<if test="param.plaintiffAppellant != null"> <if test="param.plaintiffAppellant != null">
AND a.plaintiff_appellant LIKE CONCAT('%', #{param.plaintiffAppellant}, '%') AND a.plaintiff_appellant LIKE CONCAT('%', #{param.plaintiffAppellant}, '%')
</if> </if>
<if test="param.appellee != null"> <if test="param.appellee != null">
AND a.appellee LIKE CONCAT('%', #{param.defendant appellee}, '%') AND a.appellee LIKE CONCAT('%', #{param.defendant appellee}, '%')
</if> </if>
<if test="param.otherPartiesThirdParty != null">
AND a.other_parties_third_party LIKE CONCAT('%', #{param.otherPartiesThirdParty}, '%')
</if>
<if test="param.occurrenceTime != null"> <if test="param.occurrenceTime != null">
AND a.occurrence_time LIKE CONCAT('%', #{param.occurrenceTime}, '%') AND a.occurrence_time LIKE CONCAT('%', #{param.occurrenceTime}, '%')
</if> </if>
<if test="param.caseNumber != null"> <if test="param.caseNumber != null">
AND a.case_number LIKE CONCAT('%', #{param.caseNumber}, '%') AND a.case_number LIKE CONCAT('%', #{param.caseNumber}, '%')
</if> </if>
<if test="param.causeOfAction != null">
AND a.cause_of_action LIKE CONCAT('%', #{param.causeOfAction}, '%')
</if>
<if test="param.involvedAmount != null"> <if test="param.involvedAmount != null">
AND a.involved_amount = #{param.involvedAmount} AND a.involved_amount = #{param.involvedAmount}
</if> </if>
<if test="param.courtName != null"> <if test="param.courtName != null">
AND a.court_name LIKE CONCAT('%', #{param.courtName}, '%') AND a.court_name LIKE CONCAT('%', #{param.courtName}, '%')
</if> </if>
<if test="param.dataStatus != null">
AND a.data_status LIKE CONCAT('%', #{param.dataStatus}, '%')
</if>
<if test="param.comments != null"> <if test="param.comments != null">
AND a.comments LIKE CONCAT('%', #{param.comments}, '%') AND a.comments LIKE CONCAT('%', #{param.comments}, '%')
</if> </if>
@@ -73,7 +62,8 @@
</if> </if>
<if test="param.keywords != null"> <if test="param.keywords != null">
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%') AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
OR b.name = #{param.keywords} OR b.name LIKE CONCAT('%', #{param.keywords}, '%')
OR a.case_number = #{param.keywords}
) )
</if> </if>
</where> </where>

View File

@@ -4,9 +4,10 @@
<!-- 关联查询sql --> <!-- 关联查询sql -->
<sql id="selectSql"> <sql id="selectSql">
SELECT a.*, b.name AS companyName SELECT a.*, b.name AS companyName, u.real_name AS realName
FROM credit_gqdj a FROM credit_gqdj a
LEFT JOIN credit_company b ON a.company_id = b.id LEFT JOIN credit_company b ON a.company_id = b.id
LEFT JOIN gxwebsoft_core.sys_user u ON a.user_id = u.user_id
<where> <where>
<if test="param.id != null"> <if test="param.id != null">
AND a.id = #{param.id} AND a.id = #{param.id}
@@ -23,18 +24,9 @@
<if test="param.appellee != null"> <if test="param.appellee != null">
AND a.appellee LIKE CONCAT('%', #{param.defendant appellee}, '%') AND a.appellee LIKE CONCAT('%', #{param.defendant appellee}, '%')
</if> </if>
<if test="param.otherPartiesThirdParty != null">
AND a.other_parties_third_party LIKE CONCAT('%', #{param.otherPartiesThirdParty}, '%')
</if>
<if test="param.occurrenceTime != null">
AND a.occurrence_time LIKE CONCAT('%', #{param.occurrenceTime}, '%')
</if>
<if test="param.caseNumber != null"> <if test="param.caseNumber != null">
AND a.case_number LIKE CONCAT('%', #{param.caseNumber}, '%') AND a.case_number LIKE CONCAT('%', #{param.caseNumber}, '%')
</if> </if>
<if test="param.causeOfAction != null">
AND a.cause_of_action LIKE CONCAT('%', #{param.causeOfAction}, '%')
</if>
<if test="param.involvedAmount != null"> <if test="param.involvedAmount != null">
AND a.involved_amount = #{param.involvedAmount} AND a.involved_amount = #{param.involvedAmount}
</if> </if>
@@ -73,7 +65,8 @@
</if> </if>
<if test="param.keywords != null"> <if test="param.keywords != null">
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%') AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
OR b.name = #{param.keywords} OR b.name LIKE CONCAT('%', #{param.keywords}, '%')
OR a.case_number = #{param.keywords}
) )
</if> </if>
</where> </where>

View File

@@ -4,9 +4,10 @@
<!-- 关联查询sql --> <!-- 关联查询sql -->
<sql id="selectSql"> <sql id="selectSql">
SELECT a.* SELECT a.*, b.name AS companyName, u.real_name AS realName
FROM credit_historical_legal_person a FROM credit_historical_legal_person a
LEFT JOIN credit_company b ON a.company_id = b.id LEFT JOIN credit_company b ON a.company_id = b.id
LEFT JOIN gxwebsoft_core.sys_user u ON a.user_id = u.user_id
<where> <where>
<if test="param.id != null"> <if test="param.id != null">
AND a.id = #{param.id} AND a.id = #{param.id}
@@ -55,7 +56,7 @@
</if> </if>
<if test="param.keywords != null"> <if test="param.keywords != null">
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%') AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
OR b.name = #{param.keywords} OR b.name LIKE CONCAT('%', #{param.keywords}, '%')
) )
</if> </if>
</where> </where>

View File

@@ -1,92 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.gxwebsoft.credit.mapper.CreditJudgmentDebtorHistoryMapper">
<!-- 关联查询sql -->
<sql id="selectSql">
SELECT a.*
FROM credit_judgment_debtor_history a
LEFT JOIN credit_company b ON a.company_id = b.id
<where>
<if test="param.id != null">
AND a.id = #{param.id}
</if>
<if test="param.caseNumber != null">
AND a.case_number LIKE CONCAT('%', #{param.caseNumber}, '%')
</if>
<if test="param.name != null">
AND a.name LIKE CONCAT('%', #{param.name}, '%')
</if>
<if test="param.name1 != null">
AND a.name1 LIKE CONCAT('%', #{param.name1}, '%')
</if>
<if test="param.code != null">
AND a.code LIKE CONCAT('%', #{param.code}, '%')
</if>
<if test="param.url != null">
AND a.url LIKE CONCAT('%', #{param.url}, '%')
</if>
<if test="param.type != null">
AND a.type = #{param.type}
</if>
<if test="param.occurrenceTime != null">
AND a.occurrence_time LIKE CONCAT('%', #{param.occurrenceTime}, '%')
</if>
<if test="param.amount != null">
AND a.amount LIKE CONCAT('%', #{param.amount}, '%')
</if>
<if test="param.courtName != null">
AND a.court_name LIKE CONCAT('%', #{param.courtName}, '%')
</if>
<if test="param.dataStatus != null">
AND a.data_status LIKE CONCAT('%', #{param.dataStatus}, '%')
</if>
<if test="param.companyId != null">
AND a.company_id = #{param.companyId}
</if>
<if test="param.comments != null">
AND a.comments LIKE CONCAT('%', #{param.comments}, '%')
</if>
<if test="param.recommend != null">
AND a.recommend = #{param.recommend}
</if>
<if test="param.sortNumber != null">
AND a.sort_number = #{param.sortNumber}
</if>
<if test="param.status != null">
AND a.status = #{param.status}
</if>
<if test="param.deleted != null">
AND a.deleted = #{param.deleted}
</if>
<if test="param.deleted == null">
AND a.deleted = 0
</if>
<if test="param.userId != null">
AND a.user_id = #{param.userId}
</if>
<if test="param.createTimeStart != null">
AND a.create_time &gt;= #{param.createTimeStart}
</if>
<if test="param.createTimeEnd != null">
AND a.create_time &lt;= #{param.createTimeEnd}
</if>
<if test="param.keywords != null">
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
OR b.name = #{param.keywords}
)
</if>
</where>
</sql>
<!-- 分页查询 -->
<select id="selectPageRel" resultType="com.gxwebsoft.credit.entity.CreditJudgmentDebtorHistory">
<include refid="selectSql"></include>
</select>
<!-- 查询全部 -->
<select id="selectListRel" resultType="com.gxwebsoft.credit.entity.CreditJudgmentDebtorHistory">
<include refid="selectSql"></include>
</select>
</mapper>

View File

@@ -4,10 +4,10 @@
<!-- 关联查询sql --> <!-- 关联查询sql -->
<sql id="selectSql"> <sql id="selectSql">
SELECT a.*, b.name AS companyName, c.id as historyId, c.name as historyName SELECT a.*, b.name AS companyName, u.real_name AS realName
FROM credit_judgment_debtor a FROM credit_judgment_debtor a
LEFT JOIN credit_company b ON a.company_id = b.id LEFT JOIN credit_company b ON a.company_id = b.id
LEFT JOIN credit_judgment_debtor_history c ON a.case_number = c.case_number LEFT JOIN gxwebsoft_core.sys_user u ON a.user_id = u.user_id
<where> <where>
<if test="param.id != null"> <if test="param.id != null">
AND a.id = #{param.id} AND a.id = #{param.id}
@@ -65,6 +65,7 @@
</if> </if>
<if test="param.keywords != null"> <if test="param.keywords != null">
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%') AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
OR a.case_number = #{param.keywords}
OR b.name LIKE CONCAT('%', #{param.keywords}, '%') OR b.name LIKE CONCAT('%', #{param.keywords}, '%')
) )
</if> </if>

View File

@@ -4,9 +4,10 @@
<!-- 关联查询sql --> <!-- 关联查询sql -->
<sql id="selectSql"> <sql id="selectSql">
SELECT a.*, b.name AS companyName SELECT a.*, b.name AS companyName, u.real_name AS realName
FROM credit_judicial_document a FROM credit_judicial_document a
LEFT JOIN credit_company b ON a.company_id = b.id LEFT JOIN credit_company b ON a.company_id = b.id
LEFT JOIN gxwebsoft_core.sys_user u ON a.user_id = u.user_id
<where> <where>
<if test="param.id != null"> <if test="param.id != null">
AND a.id = #{param.id} AND a.id = #{param.id}
@@ -14,14 +15,8 @@
<if test="param.companyId != null"> <if test="param.companyId != null">
AND a.company_id = #{param.companyId} AND a.company_id = #{param.companyId}
</if> </if>
<if test="param.dataType != null"> <if test="param.title != null">
AND a.data_type LIKE CONCAT('%', #{param.dataType}, '%') AND a.title LIKE CONCAT('%', #{param.title}, '%')
</if>
<if test="param.plaintiffAppellant != null">
AND a.plaintiff_appellant LIKE CONCAT('%', #{param.plaintiffAppellant}, '%')
</if>
<if test="param.appellee != null">
AND a.appellee LIKE CONCAT('%', #{param.defendant appellee}, '%')
</if> </if>
<if test="param.otherPartiesThirdParty != null"> <if test="param.otherPartiesThirdParty != null">
AND a.other_parties_third_party LIKE CONCAT('%', #{param.otherPartiesThirdParty}, '%') AND a.other_parties_third_party LIKE CONCAT('%', #{param.otherPartiesThirdParty}, '%')
@@ -38,12 +33,6 @@
<if test="param.involvedAmount != null"> <if test="param.involvedAmount != null">
AND a.involved_amount = #{param.involvedAmount} AND a.involved_amount = #{param.involvedAmount}
</if> </if>
<if test="param.courtName != null">
AND a.court_name LIKE CONCAT('%', #{param.courtName}, '%')
</if>
<if test="param.dataStatus != null">
AND a.data_status LIKE CONCAT('%', #{param.dataStatus}, '%')
</if>
<if test="param.comments != null"> <if test="param.comments != null">
AND a.comments LIKE CONCAT('%', #{param.comments}, '%') AND a.comments LIKE CONCAT('%', #{param.comments}, '%')
</if> </if>
@@ -73,7 +62,7 @@
</if> </if>
<if test="param.keywords != null"> <if test="param.keywords != null">
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%') AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
OR b.name = #{param.keywords} OR b.name LIKE CONCAT('%', #{param.keywords}, '%')
) )
</if> </if>
</where> </where>

View File

@@ -4,9 +4,10 @@
<!-- 关联查询sql --> <!-- 关联查询sql -->
<sql id="selectSql"> <sql id="selectSql">
SELECT a.*, b.name AS companyName SELECT a.*, b.name AS companyName, u.real_name AS realName
FROM credit_judiciary a FROM credit_judiciary a
LEFT JOIN credit_company b ON a.company_id = b.id LEFT JOIN credit_company b ON a.company_id = b.id
LEFT JOIN gxwebsoft_core.sys_user u ON a.user_id = u.user_id
<where> <where>
<if test="param.id != null"> <if test="param.id != null">
AND a.id = #{param.id} AND a.id = #{param.id}
@@ -94,7 +95,7 @@
</if> </if>
<if test="param.keywords != null"> <if test="param.keywords != null">
AND (a.name LIKE CONCAT('%', #{param.keywords}, '%') AND (a.name LIKE CONCAT('%', #{param.keywords}, '%')
OR b.name = #{param.keywords} OR b.name LIKE CONCAT('%', #{param.keywords}, '%')
) )
</if> </if>
</where> </where>

View File

@@ -4,9 +4,10 @@
<!-- 关联查询sql --> <!-- 关联查询sql -->
<sql id="selectSql"> <sql id="selectSql">
SELECT a.*, b.name AS companyName SELECT a.*, b.name AS companyName, u.real_name AS realName
FROM credit_mediation a FROM credit_mediation a
LEFT JOIN credit_company b ON a.company_id = b.id LEFT JOIN credit_company b ON a.company_id = b.id
LEFT JOIN gxwebsoft_core.sys_user u ON a.user_id = u.user_id
<where> <where>
<if test="param.id != null"> <if test="param.id != null">
AND a.id = #{param.id} AND a.id = #{param.id}
@@ -73,7 +74,7 @@
</if> </if>
<if test="param.keywords != null"> <if test="param.keywords != null">
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%') AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
OR b.name = #{param.keywords} OR b.name LIKE CONCAT('%', #{param.keywords}, '%')
) )
</if> </if>
</where> </where>

View File

@@ -4,9 +4,10 @@
<!-- 关联查询sql --> <!-- 关联查询sql -->
<sql id="selectSql"> <sql id="selectSql">
SELECT a.* SELECT a.*,b.name AS companyName, u.real_name AS realName
FROM credit_nearby_company a FROM credit_nearby_company a
LEFT JOIN credit_company b ON a.company_id = b.id LEFT JOIN credit_company b ON a.company_id = b.id
LEFT JOIN gxwebsoft_core.sys_user u ON a.user_id = u.user_id
<where> <where>
<if test="param.id != null"> <if test="param.id != null">
AND a.id = #{param.id} AND a.id = #{param.id}
@@ -202,7 +203,8 @@
</if> </if>
<if test="param.keywords != null"> <if test="param.keywords != null">
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%') AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
OR b.name = #{param.keywords} OR a.name = #{param.keywords}
OR b.name LIKE CONCAT('%', #{param.keywords}, '%')
) )
</if> </if>
</where> </where>

View File

@@ -4,9 +4,10 @@
<!-- 关联查询sql --> <!-- 关联查询sql -->
<sql id="selectSql"> <sql id="selectSql">
SELECT a.* SELECT a.*, b.name AS companyName, u.real_name AS realName
FROM credit_patent a FROM credit_patent a
LEFT JOIN credit_company b ON a.company_id = b.id LEFT JOIN credit_company b ON a.company_id = b.id
LEFT JOIN gxwebsoft_core.sys_user u ON a.user_id = u.user_id
<where> <where>
<if test="param.id != null"> <if test="param.id != null">
AND a.id = #{param.id} AND a.id = #{param.id}
@@ -73,7 +74,7 @@
</if> </if>
<if test="param.keywords != null"> <if test="param.keywords != null">
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%') AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
OR b.name = #{param.keywords} OR b.name LIKE CONCAT('%', #{param.keywords}, '%')
) )
</if> </if>
</where> </where>

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