642 Commits 14b91c4cd5 ... c3561a4664

Auteur SHA1 Bericht Datum
  zhuwei c3561a4664 Merge remote-tracking branch 'origin/zhuwei' into zhuwei 1 dag geleden
  zhuwei d8fae31b23 20250808-星期五发版切换分支保存的数据 4 dagen geleden
  LHB 5804d7e66d Merge branch 'refs/heads/feature-lihb-20250811' into test-merge 1 dag geleden
  LHB c1244d1a95 质检-资料填报-上传附件 1 dag geleden
  cr 53291edbbf 表单顺序混乱补充 1 dag geleden
  LHB c4242b817e Merge branch 'refs/heads/feature-lihb-20250731' into test-merge 1 dag geleden
  LHB b2a4b78d66 试验-接入成渝第三方接口开发 1 dag geleden
  cr 5390ce6c23 表单顺序混乱 1 dag geleden
  cr 854cb66a6b 添加关联委托单编号搜索 1 week geleden
  lvy a37682210c 表单复制随机数生成 5 dagen geleden
  lvy 68893766a3 优化找不到包含分项评定节点的父节点时用当前节点父节点 5 dagen geleden
  lvy a4919ea582 合并代码 4 dagen geleden
  lvy f4026e2452 回收站操作人查询优化 4 dagen geleden
  lvy 796f7b83e7 回收站删除位置优化,恢复优化 5 dagen geleden
  lvy dd5b68fe03 回收站资料节点查询和删除人和恢复人查询 1 week geleden
  lvy d484373889 回收站修改 1 week geleden
  lvy 21a5959bf1 回收站功能优化 1 week geleden
  lvy e614e64dc2 质检节点复制表单非空判断 4 dagen geleden
  lvy 42ef60c950 易客云获取当天天气修改 5 dagen geleden
  lvy a7420f4417 修改资料查询时返回的数据与wbs节点树排序不一致的问题 5 dagen geleden
  LHB f9f9f75ec5 Merge remote-tracking branch 'origin/test-merge' into test-merge 4 dagen geleden
  cr 9bc52fd77e 检查元素库的元素 根据key和html上的元素是否对应 4 dagen geleden
  LHB a141fff5b3 Merge branch 'refs/heads/feature-lihb-20250731' into test-merge 4 dagen geleden
  lvy 84e9ac686d 回收站操作人查询优化 4 dagen geleden
  lvy 2be0c48812 回收站操作人查询优化 4 dagen geleden
  lvy 2b30d37cb4 回收站操作人查询优化 4 dagen geleden
  LHB b81d2cc8d3 试验-接入成渝第三方接口开发 4 dagen geleden
  lvy 3669f78075 质检节点复制表单非空判断 4 dagen geleden
  LHB 35b7448ad9 试验-接入成渝第三方接口开发 4 dagen geleden
  cr 43a59c5f22 检查元素库的元素 根据key和html上的元素是否对应 4 dagen geleden
  cr 6cfd403737 优化支座垫石特殊公式 4 dagen geleden
  lvy a4253666da 回收站删除位置优化,恢复优化 5 dagen geleden
  cr d6deef40c0 优化支座垫石特殊公式 4 dagen geleden
  lvy 6ceadbbc77 回收站删除位置优化,恢复优化 5 dagen geleden
  lvy 6b2cf130ff 优化找不到包含分项评定节点的父节点时用当前节点父节点 5 dagen geleden
  lvy 4753cdb6c8 回收站删除位置优化,恢复优化 5 dagen geleden
  lvy 184dc2abd3 Merge branch 'test-merge' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 5 dagen geleden
  lvy 3c6482733b 表单复制随机数生成 5 dagen geleden
  cr 2c069d9382 清表查询时 将文件已损坏的也查询出来 5 dagen geleden
  cr 530d4746b0 清表查询时 将文件已损坏的也查询出来 5 dagen geleden
  zhuwei 1b8f6616b9 Merge branch 'zhuwei' into dev 5 dagen geleden
  lvy 63b2d1f241 Merge branch 'test-merge' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 5 dagen geleden
  lvy 985ec80187 易客云获取当天天气修改 5 dagen geleden
  lvy 194b470e11 修改资料查询时返回的数据与wbs节点树排序不一致的问题 5 dagen geleden
  cr b4f5843524 影像资料上传图片写入失败 5 dagen geleden
  cr 588db1f193 影像资料上传图片写入失败 5 dagen geleden
  cr af58944f0d Merge remote-tracking branch 'origin/test-merge' into test-merge 5 dagen geleden
  cr 4371aec58e 影像资料上传图片写入失败 5 dagen geleden
  cr c26ba9681a 影像资料上传图片写入失败 5 dagen geleden
  LHB e58617c7a7 Merge branch 'refs/heads/feature-lihb-20250731' into test-merge 5 dagen geleden
  LHB 194910fbe1 试验-接入成渝第三方接口开发 5 dagen geleden
  LHB 4219c04a88 Merge remote-tracking branch 'origin/test-merge' into test-merge 5 dagen geleden
  LHB d049fc3a00 Merge branch 'refs/heads/feature-lihb-20250731' into test-merge 5 dagen geleden
  LHB 8fe38489a3 试验-接入成渝第三方接口开发 5 dagen geleden
  LHB 9a51fd6c27 试验-接入成渝第三方接口开发 5 dagen geleden
  lvy 524ecf84c0 质检系统-表单有随机数时进行复制时被复制出来的随机数未发生改变 5 dagen geleden
  lvy 0b406688ca 质检系统-表单有随机数时进行复制时被复制出来的随机数未发生改变 6 dagen geleden
  lvy 24b0e38fa1 质检系统-表单有随机数时进行复制时被复制出来的随机数未发生改变 6 dagen geleden
  lvy d7bc88cdb1 质检资料进度报表查询去重 6 dagen geleden
  lvy eaaf75f5f9 修改质检wbs树节点统计方法和状态同步 6 dagen geleden
  lvy 84c4f57d53 质检资料进度查询已填报时去重 6 dagen geleden
  lvy 4910a302f6 修改资料查询时返回的数据与wbs节点树排序不一致的问题 1 week geleden
  cr fd74857ad8 档案并卷后pdf顺序混乱 6 dagen geleden
  LHB e9c5f4a747 Merge branch 'refs/heads/feature-lihb-20250806' into test-merge 6 dagen geleden
  LHB e160f598a0 质检-资料填报-re-sign功能 6 dagen geleden
  cr 8ecc61ba87 质量检验表单顺序优化 6 dagen geleden
  cr 864743e195 质量检验表单顺序优化 6 dagen geleden
  LHB c36d0ecfb8 Merge branch 'refs/heads/feature-lihb-20250731' into test-merge 6 dagen geleden
  LHB ad6210c931 试验-接入成渝第三方接口开发 6 dagen geleden
  lvy de9b7d107f 质检资料进度报表查询去重 6 dagen geleden
  lvy 657f724ad1 回收站资料节点查询和删除人和恢复人查询 1 week geleden
  cr 6593b75230 183计量重新计算时,集合越界bug 6 dagen geleden
  cr 638338f931 183计量模板查询 更改为pid和ancestorsPid查询 6 dagen geleden
  cr 2045817478 档案并卷后pdf顺序混乱 6 dagen geleden
  lvy c6ad728e3e 状态同步 6 dagen geleden
  lvy edce72055e 修改质检wbs树节点统计方法和状态同步 6 dagen geleden
  lvy bf2393a329 质检资料进度查询已填报时去重 6 dagen geleden
  LHB dbf9f2a5e9 Merge branch 'refs/heads/feature-lihb-20250731' into test-merge 6 dagen geleden
  LHB ff90f1834c 试验-接入成渝第三方接口开发 6 dagen geleden
  LHB 51e1dff160 Merge remote-tracking branch 'origin/test-merge' into test-merge 6 dagen geleden
  LHB ca9c125d52 Merge branch 'refs/heads/dev' into test-merge 6 dagen geleden
  lvy c72c1c46c3 Merge branch 'test-merge' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 6 dagen geleden
  lvy e6d11aaa58 修改资料查询时返回的数据与wbs节点树排序不一致的问题 1 week geleden
  cr a28a77fbf0 表单顺序混乱补充 1 week geleden
  zhuwei 8cc99d5ae7 Merge branch 'zhuwei' into dev 1 week geleden
  cr d6bc496d1c 表单顺序混乱 1 week geleden
  zhuwei f79af24a77 Merge branch 'zhuwei' into test-merge 1 week geleden
  lvy f82662dee1 回收站修改 1 week geleden
  LHB 15fc0ff33a Merge branch 'refs/heads/feature-lihb-excel' into dev 1 week geleden
  LHB 56d40bdf37 试验-接入成渝第三方接口开发 1 week geleden
  cr 92d9682816 Merge remote-tracking branch 'origin/test-merge' into test-merge 1 week geleden
  cr 9f19c13762 表单顺序混乱 1 week geleden
  LHB 2fc3ae3eff Merge remote-tracking branch 'origin/test-merge' into test-merge 1 week geleden
  LHB dc572c970f Merge branch 'refs/heads/feature-lihb-20250731' into test-merge 1 week geleden
  LHB 6d8813c157 试验-接入成渝第三方接口开发 1 week geleden
  lvy 6db4dc198e 委托单、试验自检、日志和计量实现通过key签字和保存时数据库实体表字段长度自动扩容 3 weken geleden
  zhuwei 3f23a34e7e 表单节点 1 week geleden
  lvy 67814f85c5 Merge branch 'test-merge' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 1 week geleden
  lvy 092c8535f8 回收站修改 1 week geleden
  LHB ae38036793 Merge branch 'refs/heads/dev' into test-merge 1 week geleden
  cr b2c547de38 表单顺序混乱 1 week geleden
  cr ac429cbc09 添加关联委托单编号搜索 1 week geleden
  zhuwei cd6e245895 Merge remote-tracking branch 'origin/test-merge' into test-merge 1 week geleden
  zhuwei d036b5cb88 Merge branch 'zhuwei' into test-merge 1 week geleden
  LHB f92691572e Merge branch 'refs/heads/feature-lihb-20250731' into test-merge 1 week geleden
  LHB 6d62d251c2 质检-复制节点-pid和ancestorsPid问题处理 1 week geleden
  LHB 0ecdc40933 试验-接入成渝第三方接口开发 1 week geleden
  LHB 313d439393 Merge branch 'refs/heads/feature-lihb-20250731' into test-merge 1 week geleden
  LHB 9427311b5c 试验-接入成渝第三方接口开发 1 week geleden
  LHB 331f0570c3 试验-接入成渝第三方接口开发 1 week geleden
  lvy 4902622855 回收站功能优化 1 week geleden
  LHB 9cde8fa6de 试验-接入成渝第三方接口开发 1 week geleden
  LHB 2182c3e69f 试验-接入成渝第三方接口开发 1 week geleden
  LHB 2f607375ac api接口-计量-获取某一合同段的分部分项划分接口开发 1 week geleden
  cr 79057af106 表单顺序混乱全部sort都变成1了,并且复制表没有按后缀排序 1 week geleden
  cr 5b7bf6226a 表单顺序混乱全部sort都变成1了,并且复制表没有按后缀排序 1 week geleden
  cr d6c775fe9a 统一处理html边框变粗问题 1 week geleden
  cr 97104bc1e6 表单顺序混乱全部sort都变成1了,并且复制表没有按后缀排序 1 week geleden
  LHB 37a9828d81 api接口-计量-获取某一合同段的分部分项划分 1 week geleden
  lvy 1e5b90bf50 Merge branch 'test-merge' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 1 week geleden
  lvy 2a525ddc61 试验委托单不从材料进场中获取生产厂家 1 week geleden
  cr 9d396acf80 重置文件题名 1 week geleden
  cr 97a8fed2f6 重置文件题名 1 week geleden
  LHB 206026e838 试验-成渝第三方接口 1 week geleden
  lvy a70197d222 Merge branch 'test-merge' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 1 week geleden
  lvy a311717967 试验委托单获取生产厂家 1 week geleden
  LHB f02f855790 Merge remote-tracking branch 'origin/test-merge' into test-merge 1 week geleden
  LHB 6fdfa88d7d 档案系统-文件收集-树的计数修改为文件页数 1 week geleden
  lvy 7033f0de6c 质检wbs树统计过滤 1 week geleden
  lvy ff0aad071a Merge branch 'dev' into test-merge 1 week geleden
  lvy 8af40d9701 Merge branch 'test-merge' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 1 week geleden
  lvy b85fe00b90 质检wbs树统计修改 1 week geleden
  cr 38eb88ef22 Merge remote-tracking branch 'origin/test-merge' into test-merge 1 week geleden
  cr 67a54c17f4 相册查询点击父节点查出子点 1 week geleden
  cr 13787b0b6a 合同段保存bug 1 week geleden
  LHB 100e5077ec 试验-成渝高速接口数据爬取开发 1 week geleden
  lvy dc00e62575 质检wbs树统计修改 1 week geleden
  lvy 103a069254 wbs树加载数量查询修改 1 week geleden
  lvy 2d8f47ab34 Merge branch 'test-merge' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 1 week geleden
  lvy 563f09413b 质检wbs树统计修改 1 week geleden
  cr 082e6d869c 重置文件题名 1 week geleden
  cr e75ba37d22 重置文件题名 1 week geleden
  lvy b9f41f6cfe 质检wbs树统计优化 1 week geleden
  lvy 34aa4d62c8 Merge branch 'test-merge' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 1 week geleden
  lvy f1f0d4cc3f 质检wbs树统计 1 week geleden
  cr e6de224112 相册模板更改 1 week geleden
  cr 8485fc4d12 Merge remote-tracking branch 'origin/test-merge' into test-merge 1 week geleden
  cr c4b0ca9c8d 相册模板更改 1 week geleden
  LHB 265d96cc3c Merge branch 'refs/heads/dev' into test-merge 1 week geleden
  cr a23c09b8ca Merge remote-tracking branch 'origin/test-merge' into test-merge 1 week geleden
  cr f01ab36d14 同步html表单 1 week geleden
  LHB 7a20474951 Merge branch 'refs/heads/dev' into test-merge 1 week geleden
  lvy 2d9f6f2996 质检wbs树复制节点时划分编号只对当前节点生效,不对子节点生效 1 week geleden
  lvy 9dd472d5dd 试验模型数据公式优先级修改 1 week geleden
  cr 6110595da8 合并代码 1 week geleden
  cr bcdbd7d8aa 计算合格率公式支持填多个实测值 1 week geleden
  cr e4abcac955 档案并卷-档号为null或不按规范设置档号问题 1 week geleden
  LHB 391fb89efe Merge remote-tracking branch 'origin/test-merge' into test-merge 2 weken geleden
  LHB 0c6e79e859 Merge branch 'refs/heads/dev' into test-merge 2 weken geleden
  cr 04487ed45a 元素库修改元素 同步去修改html 2 weken geleden
  cr 72be031c55 元素库修改元素 同步去修改html 2 weken geleden
  cr c3677159d5 元素库修改元素 同步去修改html 2 weken geleden
  LHB 6e9df4d5bb 档案-案卷收集-分解文件 2 weken geleden
  LHB 9e040e5717 Merge branch 'refs/heads/feature-lihb-20250725' into test-merge 2 weken geleden
  cr a1ed86f507 隐藏表单失败增加提示语 2 weken geleden
  cr 85b59a648b 检查成渝项目PDF为空并且重刷 2 weken geleden
  LHB 22b37aaf78 Merge branch 'refs/heads/feature-lihb-20250716' into test-merge 2 weken geleden
  LHB e51c136b3d 同步-同步合同段 2 weken geleden
  LHB 600d2b1195 Merge branch 'refs/heads/feature-lihb-20250716' into test-merge 2 weken geleden
  LHB cccd52db51 同步-同步合同段 2 weken geleden
  LHB 657e45a6cf Merge branch 'refs/heads/feature-lihb-20250716' into test-merge 2 weken geleden
  LHB fedfb20d3f 同步-同步合同段 2 weken geleden
  LHB 81ca3a2035 Merge branch 'refs/heads/feature-lihb-20250716' into test-merge 2 weken geleden
  LHB 18f061ca85 同步-同步合同段 2 weken geleden
  cr bcdb01cf10 后管编辑节点是否新增隐藏bug 2 weken geleden
  cr 7501d76be8 委托单 试验依据、评定标准、规格 不自动赋值 2 weken geleden
  cr f6c5eee58d 组成相册 保证相片是连续的 2 weken geleden
  cr 48d266946a 检查日期时,排除掉取样日期元素 2 weken geleden
  LHB 1418cd21c8 同步-同步合同段-历史html调整 2 weken geleden
  LHB 8b56924d7d 同步-同步合同段-历史html调整 2 weken geleden
  LHB aa63f306f6 Merge branch 'refs/heads/feature-lihb-20250716' into test-merge 2 weken geleden
  LHB b74554768f 同步-同步合同段-历史html调整 2 weken geleden
  lvy ae340633be Merge branch 'test-merge' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 2 weken geleden
  lvy 6de12c6e04 修改合格率参数的小数位数 2 weken geleden
  LHB fe47df24a9 Merge remote-tracking branch 'origin/test-merge' into test-merge 2 weken geleden
  LHB 881633ab27 质检-资料查询-save-again功能添加失败把pdf路径修改回来 2 weken geleden
  lvy ffb6ec5bc6 修改合格率参数的小数位数 2 weken geleden
  lvy 4dd72adce8 Merge branch 'test-merge' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 2 weken geleden
  LHB f78405ae25 Merge branch 'refs/heads/feature-lihb-20250716' into test-merge 2 weken geleden
  LHB cebd0d8f1e 同步-同步合同段-新增节点构建父子级关系调整 2 weken geleden
  LHB c0a5ffcd93 档案查询bug 2 weken geleden
  cr 585f2e9a6b 万盛计量 本期完成为0不计算百分比 2 weken geleden
  cr c0088c7df4 删除节点加个判断防止报错 2 weken geleden
  cr cd128b5044 Merge remote-tracking branch 'origin/test-merge' into test-merge 2 weken geleden
  LHB 48e9d77e55 Merge branch 'refs/heads/feature-lihb-20250716' into test-merge 2 weken geleden
  LHB 06ecc0f020 Reapply "同步-同步合同段-生成pdf时优先使用历史html" 2 weken geleden
  LHB d10a5bec87 Reapply "同步-同步合同段-重签未使用历史Excel" 2 weken geleden
  LHB a4e5c7b756 Reapply "同步-同步合同段-跳过选择清表同步无html的数据" 2 weken geleden
  LHB 61a955a100 Reapply "同步-同步合同段-记录历史excel,生成pdf时优先使用历史excel" 2 weken geleden
  LHB 845bbe0d81 Reapply "同步-同步合同段-跳过不满足条件的数据,并记录不满足条件的数据" 2 weken geleden
  LHB 4e8ae0dda6 Reapply "同步-同步合同段-添加历史html调整" 2 weken geleden
  LHB cce359357a Reapply "质检-同步合同段-后管同步合同段时,对待审批和已审批和表单历史历史数据" 2 weken geleden
  LHB 3a86126a3f Reapply "质检-同步合同段-上报时删除之前的旧html记录" 2 weken geleden
  LHB e987c2d40b Reapply "质检-同步合同段-一件重签时不允许删除旧html" 2 weken geleden
  LHB dd1097bdee Reapply "质检-同步合同段-复制文件时如果文件存在就覆盖" 2 weken geleden
  LHB 3bdf68a22c Reapply "质检-同步合同段-本地文件不存在,就通过oss获取文件" 2 weken geleden
  LHB a573912f8e Reapply "质检-同步合同段-Feign接口调整为Post" 2 weken geleden
  LHB 8fafe262a7 Reapply "质检-同步合同段-上报记录表单html历史,重签先查询是否存在html历史有就使用历史,保存删除html历史" 2 weken geleden
  LHB 01648b38c1 Reapply "同步-同步合同段-处理过滤数据" 2 weken geleden
  LHB 3e1f108144 Reapply "同步-同步合同段-同步无节点就跳过" 2 weken geleden
  LHB 6c72f325f5 Reapply "同步-同步合同段-非空判断" 2 weken geleden
  LHB 5e097376ce Reapply "同步-同步合同段-异常提示添加pkid" 2 weken geleden
  LHB ea8ef5233f Reapply "同步-同步合同段-判断添加和上报逻辑调整" 2 weken geleden
  LHB b8116dab2e Reapply "同步-同步合同段-查询已判断、已审批的数据调整" 2 weken geleden
  LHB 052d1a1bb8 Reapply "同步-同步合同段-判断已填报,已审批的逻辑调整" 2 weken geleden
  LHB e28b59c31a 同步-同步合同段-新增的表单跟更新的表单一起处理 2 weken geleden
  lvy 70b5e2c187 档案wbs树同步优化 2 weken geleden
  cr e637f2fd17 关联清表时 没有用最新的initTablId去查元素库 3 weken geleden
  LHB 333ecefebb 档案系统-档案树查询文件数量区分,指定页面的接口才查询 3 weken geleden
  cr 8fced9e6b6 档案验收bug 3 weken geleden
  lvy fcc518ca1b Merge branch 'lvy' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 3 weken geleden
  lvy f480cf750b 解决后管元素库修改长度失败后回退失败 3 weken geleden
  lvy 11ac68ede0 Merge branch 'lvy' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 3 weken geleden
  lvy dc851c1fd1 委托单、试验自检、日志和计量实现通过key签字和保存时数据库实体表字段长度自动扩容 3 weken geleden
  LHB 59691c6cea Merge branch 'refs/heads/feature-lihb-20250716' into test-merge 3 weken geleden
  LHB a2597a2839 Merge branch 'refs/heads/feature-lihb-20250716' into test-merge 3 weken geleden
  LHB 4a784c9de0 Merge branch 'refs/heads/feature-lihb-20250716' into test-merge 3 weken geleden
  lvy 564124062a 电签签字时优先使用dqid 3 weken geleden
  lvy ef7df8bcb0 电签角色库关联表单修改 3 weken geleden
  lvy a9428f80b7 委托单重签,查询u_information_query中待审批和已审批的数据 3 weken geleden
  LHB 80b7131117 Merge branch 'refs/heads/dev' into test-merge 3 weken geleden
  lvy 649405953b 质检资料保存时动态扩容数据库实体表字段长度 3 weken geleden
  lvy 92a55a72cb 质检资料保存时动态扩容数据库实体表字段长度 3 weken geleden
  LHB 02db408e82 Merge branch 'refs/heads/feature-lihb-20250716' into test-merge 3 weken geleden
  lvy bfcdcfbf72 电签位置配置日志记录 3 weken geleden
  LHB 846404b8e0 同步-同步合同段-放开定时任务 3 weken geleden
  LHB 682ed61f7e Merge branch 'refs/heads/feature-lihb-20250716' into test-merge 3 weken geleden
  LHB a82c080c00 Merge branch 'refs/heads/dev' into test-merge 3 weken geleden
  LHB c2f3138931 Merge remote-tracking branch 'origin/test-merge' into test-merge 3 weken geleden
  lvy a52cc04319 试验获取pdf数据有值时过滤掉/ 3 weken geleden
  LHB 37fbb4ce0f 同步-同步合同段-添加历史html调整 3 weken geleden
  lvy 090d46bbb3 试验获取pdf数据有值时过滤掉/ 3 weken geleden
  LHB f9139bfda4 Merge branch 'refs/heads/feature-lihb-20250716' into test-merge 3 weken geleden
  LHB 205d90477e 后管-在线excel 生成html调整 3 weken geleden
  LHB b02f60da8c 后管-在线excel 生成html调整 3 weken geleden
  cr 848aa87593 案卷查询下载分片下载 3 weken geleden
  cr 9b09672ac3 代码冲突 3 weken geleden
  cr 834bcb604d 导入质检划分树 编号和名称交换位置 3 weken geleden
  cr a65bd5b9b9 本地和测试环境也能关联清表(勿更正式) 3 weken geleden
  cr eb5c132ea3 自动检查日期感叹号 3 weken geleden
  LHB e0764f820f 冲突导致代码丢失 3 weken geleden
  LHB 62451b8411 Merge remote-tracking branch 'origin/test-merge' into test-merge 3 weken geleden
  LHB 51d5c7f889 Merge branch 'refs/heads/feature-lihb-20250716-shiyan' into test-merge 3 weken geleden
  lvy b314b1b70d 电签系统推荐优化:根据excel_id 和col_key进行推荐 3 weken geleden
  lvy 4f24be99d8 Merge branch 'test-merge' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 3 weken geleden
  lvy bad36ef29c 质检上报保存超时提醒 3 weken geleden
  lvy 59348d6be9 电签系统推荐优化:根据excel_id 和col_key进行推荐 3 weken geleden
  lvy 25458e23cd wbs树加载优化 4 weken geleden
  cr a98e5321d9 试验编号优化bug 3 weken geleden
  cr aa73cad4ef 试验编号优化bug 3 weken geleden
  cr e01b7de94b 新增试验编号bug 3 weken geleden
  lvy 17ee4a86aa Merge branch 'test-merge' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 3 weken geleden
  cr 6a4d1b78b8 下载案卷目录添加边框 3 weken geleden
  cr 29b2b1ca4a 新增试验编号bug 3 weken geleden
  cr 7b6b1aa022 新增试验编号bug 3 weken geleden
  cr 6d479557cb 新增试验编号bug 3 weken geleden
  lvy f66e1771ac Merge branch 'test' into test-merge 3 weken geleden
  lvy 9db4dfe188 wbs树加载优化 4 weken geleden
  lvy 8d2f0c998f 电签系统推荐优化:根据excel_id 和col_key进行推荐 3 weken geleden
  cr 92fac6f4e9 合并代码 3 weken geleden
  cr 662368358a 自动检测日期感叹号 3 weken geleden
  cr f5b7f73300 自动检测日期感叹号 3 weken geleden
  cr 3b50820d5d 档案下载案卷EXCEL 3 weken geleden
  LHB e53b4fc5e2 Merge branch 'refs/heads/feature-lihb-20250716' into test-merge 3 weken geleden
  LHB 80dd18d551 Merge branch 'refs/heads/feature-lihb-20250716-shiyan' into test-merge 3 weken geleden
  LHB 9f0414526d Merge branch 'refs/heads/feature-lihb-20250716-shiyan' into test-merge 3 weken geleden
  LHB dcfef38eae Merge branch 'refs/heads/feature-lihb-20250716' into test-merge 3 weken geleden
  LHB e1cbfef1ef Merge branch 'refs/heads/feature-lihb-20250716-shiyan' into test-merge 3 weken geleden
  LHB f5da94468e Merge branch 'refs/heads/feature-lihb-20250716' into test-merge 3 weken geleden
  LHB 1291aaf31a 同步-同步合同段-异常提示添加pkid 3 weken geleden
  lvy eebf52e105 电签同一位置重复签名 3 weken geleden
  cr edd64d10e8 档案下载案卷EXCEL 3 weken geleden
  cr fd77d93abb 档案下载案卷EXCEL 3 weken geleden
  cr 693234a090 Merge remote-tracking branch 'origin/test-merge' into test-merge 3 weken geleden
  LHB 5c5e7ed0cb Merge branch 'feature-lihb-20250716' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 3 weken geleden
  lvy bca11b8d93 Merge branch 'test-merge' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 3 weken geleden
  lvy c285c14557 Merge branch 'test-bug' into test-merge 3 weken geleden
  lvy dd8e920a25 Merge branch 'test-bug' into test-merge 3 weken geleden
  LHB 44ae06b47c Merge branch 'refs/heads/feature-lihb-20250716' into test-merge 3 weken geleden
  lvy c23f8249d4 试验保存生成的“/”,不能影响受控号。配了电签的位置不生成“/” 3 weken geleden
  LHB 079e86cf04 Merge branch 'refs/heads/dev' into test-merge 3 weken geleden
  cr ba577cd577 Merge branch 'cr' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 3 weken geleden
  LHB c286feb22c 同步-同步合同段-判断已填报,已审批的逻辑调整 3 weken geleden
  cr 55c3dd0fbe 档案下载案卷EXCEL 3 weken geleden
  cr 3831bbf9a7 自动检测日期感叹号 3 weken geleden
  cr 062613f2c3 划分导入模板时 不设置日期感叹号 3 weken geleden
  lvy 8949c9688a 打包设置,使用${path.separator}代替`:` 3 weken geleden
  lvy b77bbdc4e5 解决冲突 3 weken geleden
  lvy 76dd5f6a26 Merge branch 'lvy' into test-merge 3 weken geleden
  lvy a2fdcf19e7 Merge branch 'cr' of http://219.151.181.73:3000/zhuwei/bladex into dev-test-merge 3 weken geleden
  lvy 7b1fc09ef4 Merge branch 'feature-lihb-20250715' of http://219.151.181.73:3000/zhuwei/bladex into dev-test-merge 3 weken geleden
  lvy 199b039fb1 Merge branch 'feature-lihb-bug' of http://219.151.181.73:3000/zhuwei/bladex into dev-test-merge 3 weken geleden
  lvy 5462c76cf8 Merge branch 'lihb' of http://219.151.181.73:3000/zhuwei/bladex into dev-test-merge 3 weken geleden
  lvy adf02f4404 档案wbs树同步 3 weken geleden
  cr f3c7053121 关闭定时任务 4 weken geleden
  cr d281976d79 质检相册功能开发 4 weken geleden
  lvy 1b1220b8d8 计量系统撤回后重置pre_pdf_url 4 weken geleden
  lvy f59fcacee7 质检资料保存时动态扩容数据库实体表字段长度 4 weken geleden
  cr a52bb7a0f8 质检相册功能 4 weken geleden
  cr b22921e65d 万盛计量bug 4 weken geleden
  lvy a67c192adf 电签识别优化 4 weken geleden
  LHB f8f99514d6 Merge branch 'refs/heads/dev' into feature-lihb-bug 4 weken geleden
  LHB b8466a9c6e Merge branch 'refs/heads/dev' into lihb 4 weken geleden
  lvy 681f694f5d Merge branch 'test-trial' into test 4 weken geleden
  lvy 6f2a3d68bb Merge branch 'dev' of http://219.151.181.73:3000/zhuwei/bladex into test-trial 4 weken geleden
  cr a1ceb4f2bf 复制节点或表单的时候 不同步日期是否填写完毕 4 weken geleden
  cr 03d1136f51 自动检查检查日期 4 weken geleden
  cr 9a31f6a53b 质检检查日期bug 4 weken geleden
  cr f2ce35c13f 万盛计量更改存储方式redis->mysql 4 weken geleden
  LHB 88a5467d6b Merge branch 'refs/heads/dev' into feature-lihb-bug 4 weken geleden
  LHB cc8245a1a8 Merge branch 'refs/heads/dev' into lihb 4 weken geleden
  LHB 66c49ae773 Merge branch 'refs/heads/dev' into feature-lihb-bug 4 weken geleden
  LHB 5bd84bb043 Merge branch 'refs/heads/dev' into lihb 4 weken geleden
  LHB c591f6161e Merge branch 'refs/heads/dev' into feature-lihb-bug 1 maand geleden
  lvy 78f68495d6 试验材料进程材料编号判断 1 maand geleden
  LHB 5b7171f365 质检-保存表单-评定表查询子节点方法应传父级pkid 1 maand geleden
  lvy c623c88a1e 试验bug修改 1 maand geleden
  lvy 26d2bd11a3 试验bug修改 1 maand geleden
  lvy 39bf813f7e 试验bug修改 1 maand geleden
  lvy 27eaf3b964 档案系统批量认证/审批状态修改,档案系统wbs树删除节点修改 1 maand geleden
  lvy 6570a5ddcb 试验基础信息获取,委托单批量上报 1 maand geleden
  LHB 420516ad59 质检-同步合同段-后管同步合同段时,对待审批和已审批和表单历史历史数据 1 maand geleden
  lvy 23861f7e4b 委托单保存修改 1 maand geleden
  lvy ac92cfd593 试验基础信息保存修改,试验表单空白部分补充/ 1 maand geleden
  LHB aae386cd04 质检-资料填报-新增节点多个模式调整 1 maand geleden
  lvy 1f0012da75 试验基础信息修改重新获取接口 1 maand geleden
  LHB 0b5d4f6d77 质检-资料填报-新增节点选择多个同级的节点失败问题处理 1 maand geleden
  lvy 1e36dd5a85 电签配置查询优化 1 maand geleden
  lvy 4644289767 电签配置修改 1 maand geleden
  lvy 04e3867375 电签配置过滤重复位置重复角色记录 1 maand geleden
  lvy a53b6f3df5 试验材料取样样品编号非空判断 1 maand geleden
  LHB 86df8e37dc 质检-同步合同段-上报时删除之前的旧html记录 1 maand geleden
  LHB 3de97d87a7 质检-同步合同段-一件重签时不允许删除旧html 1 maand geleden
  LHB 32d33794a2 质检-同步合同段-复制文件时如果文件存在就覆盖 1 maand geleden
  LHB 82c70204d9 质检-同步合同段-本地文件不存在,就通过oss获取文件 1 maand geleden
  LHB 0945b956b9 质检-同步合同段-Feign接口调整为Post 1 maand geleden
  LHB a00f4902a7 质检-同步合同段-上报记录表单html历史,重签先查询是否存在html历史有就使用历史,保存删除html历史 1 maand geleden
  lvy 826c116fea wbs数据加载优化 1 maand geleden
  lvy 95d4630502 查询电签时向html中插入项目匹配的电签id 1 maand geleden
  lvy 17cc3320b2 任务上报保存加锁 1 maand geleden
  lvy 081ee9479c 材料进场分页查询优化 1 maand geleden
  LHB 646070a56a 后管-清表列表-在线excel回调接口放开测试 1 maand geleden
  lvy 05a8a2b5d2 试验材料管理、试验检测优化 1 maand geleden
  LHB 8a76ae7f64 Merge branch 'refs/heads/dev' into feature-lihb-bug 1 maand geleden
  LHB 6eba557f0e 公式-根据公式自动生成的值如果无数据,则走默认数据赋值 1 maand geleden
  lvy 8da6317dcd 关联清表会导致合同段表单序号丢失 1 maand geleden
  lvy 0d45e66234 表单复制名称规则修改和表单排序修改 1 maand geleden
  LHB c612db80b3 Merge branch 'refs/heads/dev' into feature-lihb-bug 1 maand geleden
  LHB 49bc877f66 个人中心-回收站-恢复功能会检查节点是否在项目节点中存在,不存在就跳过并status设为2 1 maand geleden
  LHB 9f27e4cd07 同步-节点搜索功能缺少字段 1 maand geleden
  LHB 5cdf8dd650 同步-表单同步-筛选逻辑根据系统WBS筛选同步 1 maand geleden
  LHB 3190ca45f5 个人中心-回收站-恢复功能调整(未完成) 1 maand geleden
  LHB cf9703d796 同步-表单同步-错误提示 1 maand geleden
  lvy 72a8d06ff8 签章预览大小调整 1 maand geleden
  lvy 55334d6c61 质检系统节点复制修改formulaOption相关代码 1 maand geleden
  LHB 429f5082ee 同步-单表同步-公式同步修改逻辑 调整回去 1 maand geleden
  LHB afb13f4877 同步-单表同步-公式同步修改逻辑为批量查询处理 1 maand geleden
  LHB 66f293624d 同步-单表同步-节点公式同步 1 maand geleden
  LHB 20b3b47486 同步-单表同步-失败了不抛异常 1 maand geleden
  LHB d12f53b41d 同步-单表同步-逻辑调整为先判断元素一致,有excelid再判断是否一致 1 maand geleden
  lvy 7451e2b141 试验获取设备信息修改 1 maand geleden
  lvy b3a535d49f 试验获取设备信息修改 1 maand geleden
  lvy 384cffe2b1 试验基础信息保存非空判断 1 maand geleden
  lvy 65ddeb7d47 html填充试验基础信息 1 maand geleden
  lvy e481fec12b 修改试验设备使用信息使用时间 1 maand geleden
  lvy 2861de0c7d 试验查询设备信息以及设备使用信息 1 maand geleden
  lvy d1987cba98 试验保存更新取样信息 1 maand geleden
  lvy a1b6140238 试验保存设备使用信息 1 maand geleden
  lvy b5b26d6c04 试验保存基础信息返回试验记录id 1 maand geleden
  lvy 2ddf4b63d6 电签分类修改 1 maand geleden
  lvy b93387a55a 试验基础信息保存 1 maand geleden
  lvy 7f6a8dadb9 试验基础信息保存 1 maand geleden
  lvy b47bb2167f 档案系统编写结论提交接口注释掉电签相关代码 1 maand geleden
  lvy 3401fa66a5 档案系统档案查询优化,档案同步修改质量评定的处理 1 maand geleden
  LHB e27f0e522f 质检-保存表单, 1 maand geleden
  LHB 374898d7d2 质检-保存表单,把生成pdf改为异步执行,更新redis环境去掉 1 maand geleden
  lvy 95a6ac6d38 图片压缩新增其他图片类型 1 maand geleden
  lvy ccceb2870b 图片压缩新增其他图片类型 1 maand geleden
  lvy 8f7f1e0910 试验系统试验自检保存优化 1 maand geleden
  lvy f8989372f5 后台系统查询无内业资料的节点 1 maand geleden
  lvy 0d1b3ca431 试验系统获取基础信息设备使用时间 1 maand geleden
  lvy 23ea72bd9e 试验系统获取基础信息返回委托单id 1 maand geleden
  lvy a07fa02bf5 试验系统获取设备信息和设备使用信息 1 maand geleden
  lvy 068c952348 后台系统查询无内业资料的节点,新增名称搜索 1 maand geleden
  lvy cd51ea2475 试验系统获取设备信息和设备使用信息 1 maand geleden
  lvy 9c25ae8c32 试验系统获取规范信息 1 maand geleden
  lvy 342aaa3325 电签角色库优先级修改 1 maand geleden
  lvy 299b4519a5 修改html中的maxlenth与元素库长度保持一致 1 maand geleden
  lvy 9d1275a535 电签查询去除空key 1 maand geleden
  lvy c1eb552e61 设置自动获取数据记录保存 1 maand geleden
  lvy 456a2e7bb0 电签配置区分:本表配置,电签库,项目匹配 1 maand geleden
  lvy 86171e084f 废除通知优化,增加内容搜索 1 maand geleden
  lvy d3002f2cdd 试验基础信息修改 1 maand geleden
  LHB 7f95d8349d Merge branch 'dev' of http://219.151.181.73:3000/zhuwei/bladex into lihb 1 maand geleden
  LHB 47394df56b Merge branch 'dev' of http://219.151.181.73:3000/zhuwei/bladex into feature-lihb-bug 1 maand geleden
  lvy@qq.com a5888b1bbf 档案检查四要素显示 1 maand geleden
  lvy dcec8a2ac9 试验基础信息优化 1 maand geleden
  LHB af93801041 电签-电签任务按照sign_type倒叙,如果sign_type=2同时验证u_task_parallel中是否还存在为电签成功 2 maanden geleden
  LHB 3426ae6089 质检系统----资料填报-保存时不做任何多余操作 1 maand geleden
  lvy 9fe951d2b0 Merge branch 'lihb' of http://219.151.181.73:3000/zhuwei/bladex into test-trial 1 maand geleden
  LHB 9e1f71ccea 质检系统----资料填报-监理同步后测量数据需变动 两张监理表保存数据的时候如果之前存在数据就不执行公式 1 maand geleden
  lvy 7251871c06 Merge branch 'cr' of http://219.151.181.73:3000/zhuwei/bladex into test-trial 1 maand geleden
  lvy e0d63ef4cf 试验优化 1 maand geleden
  LHB 54921260e8 质检系统----资料填报-监理同步后测量数据需变动 CL08高程偏差/1000 1 maand geleden
  chenr 0fac287204 档案优化 1 maand geleden
  chenr c7c5cf39a6 档案详情接口 1 maand geleden
  LHB 59e2837394 同步-查询同步源条件应带上WBS_TYPE 1 maand geleden
  chenr fe816f853a 试验编号优化 1 maand geleden
  chenr 225a179607 试验编号优化 1 maand geleden
  chenr a33a79fdba 档案优化 1 maand geleden
  chenr 8e1c2c6915 试验编号优化 1 maand geleden
  LHB 0c0b28c16c 质检系统----资料填报-监理同步后测量数据需变动 跳过空值处理 1 maand geleden
  LHB 7159107e2b 定时任务-同步任务-调整为通过配置文件使其本地不执行定时任务 1 maand geleden
  LHB 5352a6c435 定时任务-推送公告-调整为通过配置文件使其本地不执行定时任务 1 maand geleden
  lvy d61731a26b 设置自动获取数据记录保存 1 maand geleden
  chenr 5368c5662a 试验编号优化 1 maand geleden
  LHB ec20a6301f 质检系统----资料填报-监理同步后测量数据需变动 获取key的坐标 1 maand geleden
  LHB ff0d28859c 质检系统----资料填报-监理同步后测量数据需变动 获取key的坐标 1 maand geleden
  chenr c1e23927de 试验编号优化 1 maand geleden
  chenr 45e9281836 档案查询bug,按文件搜索有逗号查询不到 1 maand geleden
  LHB a5cc5dff0a Merge branch 'dev' of http://219.151.181.73:3000/zhuwei/bladex into lihb 1 maand geleden
  LHB 10273290cc 质检系统----资料填报-监理同步后测量数据需变动 CL10监理完成 1 maand geleden
  chenr 95b9f0d78d 流程已废除的时候也可以删除 1 maand geleden
  chenr 0093feaab6 日志新增时 表头获取第一页默认值 1 maand geleden
  chenr b80a1c53a5 元素库根据类别查询表单 取消分页查询 1 maand geleden
  LHB 179fb0e101 质检系统----资料填报-监理同步后测量数据需变动 cl08监理完成 1 maand geleden
  lvy be3bbc73a2 电签配置区分:本表配置,电签库,项目匹配 1 maand geleden
  LHB 525432b25c 测试分支合并 1 maand geleden
  chenr 0070d5b51a 档案详情接口 新增立卷人和审核人 1 maand geleden
  chenr 34b1463cf7 已使用流程不允许删除编辑 1 maand geleden
  LHB 6c66ee30d0 质检系统----资料填报 CLO8数据调整完成,但是小数待处理 1 maand geleden
  lvy 224141e172 废除通知优化,增加内容搜索 1 maand geleden
  LHB 1e32d8374f 质检系统----资料填报- CL08数据处理(待测试) 1 maand geleden
  LHB 9089d411ab Merge branch 'dev' of http://219.151.181.73:3000/zhuwei/bladex into lihb 1 maand geleden
  lvy a6b19c2ca3 修改html中的maxlenth与元素库长度保持一致 1 maand geleden
  lvy@qq.com 9b775759a5 档案检查四要素显示 1 maand geleden
  lvy@qq.com 4c5986b098 电签配置修改 1 maand geleden
  LHB b9b96a940d 质检系统----资料填报-监理同步后测量数据需变动(未完成2) 1 maand geleden
  chenr b13d810cc2 试验保存新增日志sql,后管编辑元素页面通过数据类型查询 1 maand geleden
  chenr 4429e4c645 日志新增第二页优化,试验保存新增日志sql 1 maand geleden
  LHB bd5fa58405 同步-表单同步-同步其他表单时 强制同步所有表单信息,并且保留原节点名称 1 maand geleden
  chenr 9186a71e4c 文件题名bug修改 1 maand geleden
  chenr c7c6af6296 文件题名bug修改 1 maand geleden
  LHB 9bc4bcfadd 同步-表单同步-同下面所有表单参数验证关掉 1 maand geleden
  chenr 004f644eb8 日志新增表单 1 maand geleden
  LHB 086ca68c92 同步-同步结束后再去调整表单排序 1 maand geleden
  LHB 7d2815d165 同步-同步更新表单是重新设置其他表单排序为连续排序 1 maand geleden
  LHB 984bc62b88 同步-排序调整为顺序排序 1 maand geleden
  chenr 83b9aa7b55 文件题名后缀优化,只有合同段内页资料为工序节点才加后缀 1 maand geleden
  lvy f45d1d654c 电签时获取pdf第一页最大时间 2 maanden geleden
  lvy e99188cfcb 资料填报保存时加锁,tableFile先删后新增 2 maanden geleden
  lvy 8b2ab628dd 任务审核/电签时查询状态,避免重复处理 2 maanden geleden
  lvy 9dea3c8626 电签角色去重/单独返回 2 maanden geleden
  chenr 1d7e0fe196 计量支付项 2 maanden geleden
  chenr d998a1fafe Merge branch 'test-merge' of http://219.151.181.73:3000/zhuwei/bladex into cr 2 maanden geleden
  LHB 4a69e29714 试验-规范管理-规范信息查询时带父级名称 2 maanden geleden
  LHB 6d24cd678c Merge branch 'feature-lihb-20250610' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 2 maanden geleden
  LHB dd2cd497e6 Merge branch 'dev' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 2 maanden geleden
  LHB afe10c35dd 试验-规范管理-文件上传Oss自定义路径(未完成) 2 maanden geleden
  LHB db61c69829 试验-规范管理-信息分页查询添加新字段 2 maanden geleden
  chenr c725e61e46 试验编号模块 2 maanden geleden
  LHB b9b7eab9e6 Merge branch 'dev' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 2 maanden geleden
  LHB 77018edd1f Merge branch 'feature-lihb-20250610' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 2 maanden geleden
  LHB f8c923e0a7 Merge remote-tracking branch 'origin/test-merge' into test-merge 2 maanden geleden
  LHB 722c3a7b25 Merge branch 'feature-lihb-20250610' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 2 maanden geleden
  lvy 8c79e685f6 Merge branch 'test-merge' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 2 maanden geleden
  lvy fbc043af16 Merge branch 'test' into test-merge 2 maanden geleden
  lvy 32aa267fef PdfAddContextUtils优化 2 maanden geleden
  lvy 9f09992ca3 任务审核/电签时查询状态,避免重复处理 2 maanden geleden
  lvy 9415790336 html 默认值和提示 2 maanden geleden
  lvy 8fa8b72bbc 电签角色去重/单独返回 2 maanden geleden
  lvy aa3f98aa29 电签时获取pdf第一页最大时间 2 maanden geleden
  lvy e30f13f950 wbs树加载本地优化,去除重复脏数据 2 maanden geleden
  LHB e3b5204459 Merge branch 'feature-lihb-20250610' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 2 maanden geleden
  LHB 396d425229 Merge branch 'lihb' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 2 maanden geleden
  LHB fa954ab677 同步-新增或则修改的数据修改排序的时候先按sort排序 2 maanden geleden
  LHB 409bf7fc4d 同步-项目同步 sort+1 2 maanden geleden
  LHB fc01c54d2b Merge branch 'feature-lihb-20250610' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 2 maanden geleden
  LHB 5423bf5730 同步-项目同步 sort+1 2 maanden geleden
  LHB 0953d23d4c Merge branch 'lihb' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 2 maanden geleden
  LHB 84dd4bb799 同步-新增、吸怪表单时的排序功能 2 maanden geleden
  lvy a662ee7633 Merge branch 'test' into test-merge 2 maanden geleden
  lvy 68a8d483b7 Merge branch 'test' into test-merge 2 maanden geleden
  LHB 8d9561b2ef Merge branch 'lihb' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 2 maanden geleden
  LHB 9d157f8427 同步-更新数据的时候更新表单名称 2 maanden geleden
  lvy a8fab5f81f Merge branch 'lihb' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 2 maanden geleden
  lvy 2ba8ef844d Merge branch 'test-merge' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 2 maanden geleden
  lvy 54e10517ac informationQuery设置创建时间和更新时间 2 maanden geleden
  LHB 0144f8ce9e Merge branch 'lihb' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 2 maanden geleden
  lvy fba39d2fde 电签配置库优化 2 maanden geleden
  LHB 9c33c4acdd 同步-修复模板数据如果选择了表单跳过未选择的表单 2 maanden geleden
  LHB a1e776b980 Merge branch 'lihb' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 2 maanden geleden
  LHB 50e7bcf0a9 同步-同步源的wbsId错误调整 2 maanden geleden
  LHB c1dc5a32b3 Merge branch 'lihb' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 2 maanden geleden
  LHB 31e2679a36 同步-公式同步,主键问题处理 2 maanden geleden
  LHB 6ada936c03 同步-判断更新表单时各个类型都能单独更新,公式查询之前做非空判断 2 maanden geleden
  LHB bcf05f32f4 同步-复制节点和全局公式 使用事务管理事务 2 maanden geleden
  LHB 3046e64796 同步-判断更新表单时各个类型都能单独更新,公式查询之前做非空判断 2 maanden geleden
  LHB 30bf07ec60 同步-复制节点和全局公式 使用事务管理事务 2 maanden geleden
  LHB c00b07eca6 Merge branch 'lihb' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 2 maanden geleden
  LHB 62c551c74b 同步-复制节点和全局公式 2 maanden geleden
  lvy 92ad8d2bda Merge branch 'test' into test-merge 2 maanden geleden
  lvy 46935fb10c 数字化扫描节点判断 2 maanden geleden
  LHB bcad672d8a Merge branch 'lihb' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 2 maanden geleden
  LHB ff7dd9e1aa 同步-项目同步 元素、公式 是根据init_table_id去查询的 2 maanden geleden
  LHB 39073c1196 Revert "同步-项目同步 元素、公式 是根据init_table_id去查询的" 2 maanden geleden
  LHB f573b6d232 同步-项目同步 元素、公式 是根据init_table_id去查询的 2 maanden geleden
  LHB 446abd9407 Merge branch 'dev' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 2 maanden geleden
  LHB 457be613e6 Merge branch 'cr' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 2 maanden geleden
  LHB a203d06d92 后管-WBS管理-调整表单-默认值,改为在html上面操作数据 2 maanden geleden
  lvy 886f46da82 优化任务查看时间显示,批量废除日志记录 2 maanden geleden
  LHB d068154c44 同步-添加同步任务时的提示 2 maanden geleden
  LHB e25c8fb18f 后管-WBS管理-调整表单-默认值,改为在html上面操作数据,不设计数据库 2 maanden geleden
  LHB a5015be899 后管-WBS管理-调整表单-默认值,改为在html上面操作数据,不设计数据库 2 maanden geleden
  lvy fd18fde6e3 修正文件同步更新判断条件 2 maanden geleden
  LHB 178bf039aa Merge branch 'lihb' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 2 maanden geleden
  LHB 303e4bfc1f 同步-默认值不同步 2 maanden geleden
  LHB e304191ac8 同步-项目同步元素与默认值添加 2 maanden geleden
  lvy 1b56cd2e67 Merge branch 'test' into test-merge 2 maanden geleden
  lvy 83c47c55f5 电签配置库 2 maanden geleden
  lvy 9865bb3144 Merge branch 'test' into test-merge 2 maanden geleden
  lvy a89bc5cc2d 电签配置库 2 maanden geleden
  lvy b1698f2b42 试验附件上传时转成pdf 2 maanden geleden
  lvy 64daf5dd76 修改公式初始化数据时优先查找当前节点下的数据 2 maanden geleden
  LHB 62d853830e 质检系统-资料填报-监理同步后测量数据需变动 (未完成) 2 maanden geleden
  chenr b97babea82 Merge branch 'dev' of http://219.151.181.73:3000/zhuwei/bladex into cr 2 maanden geleden
  lvy f131353e22 Merge branch 'test' into test-merge 2 maanden geleden
  lvy 7fe197d28c Merge branch 'lihb' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 2 maanden geleden
  lvy d77b22cc6c 修改公式初始化数据时优先查找当前节点下的数据 2 maanden geleden
  lvy fd4fe5f210 元素表返回值 2 maanden geleden
  LHB 6fc6129e09 同步-获取模板的html时,如果本地获取不到就通过Oss从远程下载到本地 2 maanden geleden
  LHB 180adaa10a Merge branch 'dev' of http://219.151.181.73:3000/zhuwei/bladex into lihb 2 maanden geleden
  LHB 1a053ea409 后管-wbs元素库-添加新元素时如果行数超过表最大行数会动态修改其他字段行数 2 maanden geleden
  LHB 4d87e7d64e 后管-wbs元素库-时间类型元素的默认值设置为100 2 maanden geleden
  lvy 3b2a7350db Merge branch 'test' into test-merge 2 maanden geleden
  lvy dfadd1e3bf Merge branch 'dev' into test 2 maanden geleden
  lvy bd9cf4907f 试验上报re-sign保存PDF失败和re-sign导致pdf_url为null 2 maanden geleden
  chenr 54cadb7131 质检关联试验文件 优先使用电签pdf 2 maanden geleden
  chenr e777db3f0a 质检关联试验文件 优先使用电签pdf 2 maanden geleden
  LHB 185cd52313 Merge branch 'dev' of http://219.151.181.73:3000/zhuwei/bladex into lihb 2 maanden geleden
  LHB 02d9c8e178 后管-wbs元素库-元素调整(未完成) 2 maanden geleden
  lvy 0705c8a749 委托单废除后无法上报 2 maanden geleden
  lvy 6531e61bbb 电签管理员中查看委托单任务 2 maanden geleden
  lvy f91e21dc5a Merge branch 'test' into test-merge 2 maanden geleden
  lvy f171fb2d92 资料上报节点复制优化 2 maanden geleden
  lvy bb39ad3a98 电签配置库 2 maanden geleden
  lvy 52de961dc6 Merge branch 'test' into test-merge 2 maanden geleden
  chenr 712f5a64f4 客户端查看系统模版 2 maanden geleden
  LHB 267b88444d Merge branch 'dev' of http://219.151.181.73:3000/zhuwei/bladex into lihb 2 maanden geleden
  chenr 8a52606a1a 客户端查看系统模版 2 maanden geleden
  chenr f6f3b8c848 系统归档树,同步项目归档树,同步合同段归档树 2 maanden geleden
  chenr 31f2736235 系统归档树,同步项目归档树,同步合同段归档树 2 maanden geleden
  chenr 357052e627 客户端编辑节点显示后管系统模版位置 2 maanden geleden
  chenr 3001f19dd4 客户端查看系统模版 2 maanden geleden
  lvy bf4800b40b 资料上报节点复制优化 2 maanden geleden
  lvy feeddf5030 电签配置库 2 maanden geleden
  LHB 9216a95291 后管-wbs元素库-获取的数据最大长度 单位改为字符 2 maanden geleden
  chenr 53c3956d0a Merge branch 'dev' of http://219.151.181.73:3000/zhuwei/bladex into cr 2 maanden geleden
  chenr 50aa25e726 系统归档树,同步项目归档树,同步合同段归档树 2 maanden geleden
  LHB 394388962c 后管-wbs元素库-获取的数据最大长度是获取的字节,需要/3 2 maanden geleden
  chenr 133555163a 系统归档树,同步项目归档树,同步合同段归档树 2 maanden geleden
  LHB ceb7127cee Merge branch 'lihb' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 2 maanden geleden
  LHB b5825199b0 质检-新增/复制节点 节点祖级路径生成逻辑调整 2 maanden geleden
  LHB f2816ccb03 后管-清除之前开发一半的同步代码 2 maanden geleden
  lvy d3a14dd510 Merge branch 'test-merge' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 2 maanden geleden
  chenr 99a59b93a1 客户端编辑节点显示后管系统模版位置 2 maanden geleden
  LHB 6160c4f432 Merge branch 'lihb' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 2 maanden geleden
  LHB ccfe8f8b28 Merge branch 'cr' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 2 maanden geleden
  LHB 6f08b0521b 后管-清表-绑定清表时的元素匹配逻辑调整 2 maanden geleden
  lvy 94640e0b41 资料上报节点复制优化 2 maanden geleden
  lvy f065bd83e1 电签配置库 2 maanden geleden
  chenr c4fbee678a 资料查询 重置文件题名优化 2 maanden geleden
  chenr 7f4f2d9464 资料查询 重置文件题名 2 maanden geleden
  LHB 5a8e517f8d Merge branch 'cr' of http://219.151.181.73:3000/zhuwei/bladex into test-merge 2 maanden geleden
  chenr 92b3ebb813 文件题名后缀优化 2 maanden geleden
  LHB 293851de89 档案系统-文件收集-档案树统计文件数量 2 maanden geleden
  LHB cd12fcb706 Merge branch 'dev' of http://219.151.181.73:3000/zhuwei/bladex into lihb 2 maanden geleden
  LHB 95380dbedb 质检-保存数据时,生成pdf时电签id拼接异常 2 maanden geleden
  LHB 7d21d5d1ab Merge branch 'dev' of http://219.151.181.73:3000/zhuwei/bladex into lihb 2 maanden geleden
  LHB 05e0b206ee 后管-WBS元素库-编辑元素字段保存的时候调整字段长度根据数据最长长度进行处理 2 maanden geleden
  LHB a1e0364e6f 质检-模板下载文件编码处理 2 maanden geleden
  LHB 44346e35f2 质检-模板下载文件编码处理 2 maanden geleden
  LHB a33f1286c8 同步公共-新增同步任务时初始化同步数量 2 maanden geleden
  LHB cf0d2fa4c9 同步公共-获取同步源添加非空判断 2 maanden geleden
  LHB 97d3a195cd 同步公共-只有同步清表才去修复数据 2 maanden geleden
  LHB 9dd558f8b8 同步公共-修复excel、实体表字段、html添加判断 2 maanden geleden
  LHB e3a1331b89 同步公共-同步源获取调整为 与公共模板有联系的项目都统计出来 2 maanden geleden
  LHB 82597d74c8 客户端-质检下载模板接口调整 2 maanden geleden
  LHB 0a2624f8da 同步功能-只对表单进行同步 2 maanden geleden
  LHB 6d24e48d39 客户端-质检下载模板接口-复选框 2 maanden geleden
  LHB 2221e2d05f 客户端-质检下载模板接口-边框 2 maanden geleden
  LHB 9ae50ae27e Merge branch 'dev' of http://219.151.181.73:3000/zhuwei/bladex into lihb 2 maanden geleden
  LHB 7669b84691 客户端-质检下载模板接口调整 2 maanden geleden
  LHB 70af064176 Merge branch 'dev' of http://219.151.181.73:3000/zhuwei/bladex into lihb 2 maanden geleden
  LHB 4cde1f96fd Merge branch 'dev' of http://219.151.181.73:3000/zhuwei/bladex into lihb 2 maanden geleden
  LHB 9dd06cd169 同步功能-修复excel_id、init_table_name、html_url的时候做非空判断 2 maanden geleden
  LHB 7362a3b16b 同步功能-同步源排除自己 2 maanden geleden
  LHB f7059a68fa 同步功能-公共模板选择表单时新增表单会加不上的问题 修复 2 maanden geleden
  LHB 50e97cd32d 同步功能-合同段不允许新增节点 如果新表单的父节点找不到就是新节点需要去手动配置 2 maanden geleden
  LHB 755e49c530 Merge branch 'dev' of http://219.151.181.73:3000/zhuwei/bladex into lihb 2 maanden geleden
  LHB 8b76ec04a0 删除错误电签类ChekSignData 文件 2 maanden geleden
  LHB 816b624ee0 同步功能-同步源缺少公共模板 2 maanden geleden
  LHB 42659cd278 同步功能-同步源缺少公共模板 2 maanden geleden
  LHB ac6f725ed2 Merge branch 'dev' of http://219.151.181.73:3000/zhuwei/bladex into lihb 2 maanden geleden
  LHB f57c7b8389 同步功能-合同段不允许新增表单 2 maanden geleden
  LHB 97530a8d20 Merge branch 'dev' of http://219.151.181.73:3000/zhuwei/bladex into lihb 2 maanden geleden
  LHB f1b4bcf7df Merge branch 'dev' of http://219.151.181.73:3000/zhuwei/bladex into lihb 2 maanden geleden
  LHB 53ef7b54bb 同步功能-项目新增节点同步到合同段时 直接新增 2 maanden geleden
  LHB 7e054b0ad3 同步功能-节点也需要更新 2 maanden geleden
  LHB 011442ff46 同步功能-实时统计最小节点同步进度 2 maanden geleden
  LHB 26589e1112 同步功能-新增节点时如果没有找到父节点则跳过 2 maanden geleden
  LHB fe4ed98fd1 Merge branch 'dev' of http://219.151.181.73:3000/zhuwei/bladex into lihb 2 maanden geleden
  LHB 26ea37a0e7 同步功能-统计同步数量、新增同步任务数据验证、列表添加状态名称字段 2 maanden geleden
  LHB a8291736c1 同步功能-没有统计数量功能的版本 2 maanden geleden
  LHB 991a90a3c2 同步功能-添加判断节点是否存在同步任务接口 2 maanden geleden
  LHB ed869a555c 同步功能-错误信息提示调整 2 maanden geleden
  LHB 640344ac2d Merge branch 'dev' of http://219.151.181.73:3000/zhuwei/bladex into lihb 2 maanden geleden
  LHB 7cb0036a1b 同步功能-单表单同步实现 2 maanden geleden
  LHB 704a6c3d51 同步功能-多节点同步项目下拉接口开发 2 maanden geleden
  LHB 43b4731bb3 同步功能-多节点同步开发完成 2 maanden geleden
  LHB 5a1fb2c60e Merge branch 'dev' of http://219.151.181.73:3000/zhuwei/bladex into lihb 2 maanden geleden
  LHB bec295c560 同步功能-多节点同步开发完成 2 maanden geleden
  LHB 9864239dbb 同步功能-正在写同步电签 2 maanden geleden
  LHB 17071b658a Merge branch 'dev' of http://219.151.181.73:3000/zhuwei/bladex into lihb 2 maanden geleden
  LHB 10ec97f4e5 Merge branch 'dev' of http://219.151.181.73:3000/zhuwei/bladex into lihb 3 maanden geleden
  LHB 5f145a727f Merge branch 'dev' of http://219.151.181.73:3000/zhuwei/bladex into lihb 3 maanden geleden
  LHB d8cd62e65d Merge branch 'dev' of http://219.151.181.73:3000/zhuwei/bladex into lihb 3 maanden geleden
  LHB 592ba64a4a 档案统计-案卷统计 3 maanden geleden
  LHB 23a70cec3c 多节点同步 3 maanden geleden
  LHB cba81781a3 档案统计-原生数字化文件数量 接口调整 3 maanden geleden
  LHB bbc3fa72d6 Merge branch 'dev' of http://219.151.181.73:3000/zhuwei/bladex into lihb 3 maanden geleden
  LHB 4ea63c8942 多节点同步功能 3 maanden geleden
100 gewijzigde bestanden met toevoegingen van 5150 en 1131 verwijderingen
  1. 7 2
      blade-common/src/main/java/org/springblade/common/utils/YiKeYunApiUtils.java
  2. 35 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/dto/RecycleBinInfoDTO.java
  3. 135 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/RecycleBinInfo.java
  4. 59 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/TrialCyAccessories.java
  5. 149 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/TrialCyFinishTestReport.java
  6. 54 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/TrialCyTestType.java
  7. 285 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/TrialCyThirdReport.java
  8. 24 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/feign/TrialCyAccessoriesClient.java
  9. 3 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/EntrustInfoVO.java
  10. 72 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/RecycleBinInfoVO.java
  11. 20 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/ThirdReportVo.java
  12. 31 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/TrialCyThirdReportQueryVo.java
  13. 7 4
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/TableFile.java
  14. 61 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/WbsTreeContractOldHtml.java
  15. 1 1
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/ExcelTabClient.java
  16. 2 2
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/TableFileClient.java
  17. 4 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/WbsParamClient.java
  18. 6 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/WbsTreeContractClient.java
  19. 25 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/WbsTreeContractOldHtmlClient.java
  20. 84 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/APIWbsContractSubdivisionVo.java
  21. 1 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ExcelTabVo1.java
  22. 1 1
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/TextdictInfoVO.java
  23. 1 1
      blade-service/blade-archive/pom.xml
  24. 8 2
      blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchivesAutoController.java
  25. 95 98
      blade-service/blade-business/src/main/java/org/springblade/business/controller/InformationWriteQueryController.java
  26. 11 4
      blade-service/blade-business/src/main/java/org/springblade/business/controller/MaterialProgressController.java
  27. 2 2
      blade-service/blade-business/src/main/java/org/springblade/business/controller/MessageWarningController.java
  28. 129 2
      blade-service/blade-business/src/main/java/org/springblade/business/controller/RecycleBinController.java
  29. 2 2
      blade-service/blade-business/src/main/java/org/springblade/business/controller/StandardInfoController.java
  30. 12 0
      blade-service/blade-business/src/main/java/org/springblade/business/controller/TaskController.java
  31. 100 0
      blade-service/blade-business/src/main/java/org/springblade/business/controller/TrialCyController.java
  32. 2 0
      blade-service/blade-business/src/main/java/org/springblade/business/controller/TrialDetectionController.java
  33. 2 0
      blade-service/blade-business/src/main/java/org/springblade/business/controller/TrialMaterialController.java
  34. 118 0
      blade-service/blade-business/src/main/java/org/springblade/business/feignClient/TrialCyAccessoriesClientImpl.java
  35. 3 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/EntrustInfoMapper.xml
  36. 1 1
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/InformationQueryMapper.xml
  37. 17 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/RecycleBinInfoMapper.java
  38. 95 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/RecycleBinInfoMapper.xml
  39. 1 1
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/StandardInfoMapper.java
  40. 5 4
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/StandardInfoMapper.xml
  41. 21 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialCyAccessoriesMapper.java
  42. 22 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialCyAccessoriesMapper.xml
  43. 23 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialCyFinishTestReportMapper.java
  44. 35 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialCyFinishTestReportMapper.xml
  45. 23 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialCyTestTypeMapper.java
  46. 24 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialCyTestTypeMapper.xml
  47. 24 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialCyThirdReportMapper.java
  48. 36 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialCyThirdReportMapper.xml
  49. 3 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialSelfInspectionRecordMapper.java
  50. 6 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialSelfInspectionRecordMapper.xml
  51. 704 0
      blade-service/blade-business/src/main/java/org/springblade/business/scheduled/ChenYuTestScheduled.java
  52. 462 0
      blade-service/blade-business/src/main/java/org/springblade/business/scheduled/ChenYuTestScheduled01.java
  53. 57 0
      blade-service/blade-business/src/main/java/org/springblade/business/scheduled/vo/GetFinishTestReport.java
  54. 57 0
      blade-service/blade-business/src/main/java/org/springblade/business/scheduled/vo/GetThirdReport.java
  55. 25 0
      blade-service/blade-business/src/main/java/org/springblade/business/scheduled/vo/Result.java
  56. 25 0
      blade-service/blade-business/src/main/java/org/springblade/business/scheduled/vo/ResultPost.java
  57. 28 0
      blade-service/blade-business/src/main/java/org/springblade/business/scheduled/vo/ThirdLogin.java
  58. 25 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/IRecycleBinInfoService.java
  59. 1 1
      blade-service/blade-business/src/main/java/org/springblade/business/service/ITaskService.java
  60. 1 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/ITrialSelfInspectionRecordService.java
  61. 2 1
      blade-service/blade-business/src/main/java/org/springblade/business/service/StandardInfoService.java
  62. 14 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/TrialCyAccessoriesService.java
  63. 19 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/TrialCyFinishTestReportService.java
  64. 25 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/TrialCyService.java
  65. 16 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/TrialCyTestTypeService.java
  66. 18 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/TrialCyThirdReportService.java
  67. 394 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/RecycleBinInfoServiceImpl.java
  68. 124 17
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TaskServiceImpl.java
  69. 25 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TrialCyAccessoriesServiceImpl.java
  70. 29 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TrialCyFinishTestReportServiceImpl.java
  71. 86 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TrialCyServiceImpl.java
  72. 28 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TrialCyTestTypeServiceImpl.java
  73. 29 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TrialCyThirdReportServiceImpl.java
  74. 22 1
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TrialMaterialMobilizationServiceImpl.java
  75. 204 186
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TrialSelfInspectionRecordServiceImpl.java
  76. 2 2
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/UStandardInfoServiceImpl.java
  77. 13 3
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/WbsTreeContractStatisticsServiceImpl.java
  78. 19 18
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/WeatherInfoServiceImpl.java
  79. 358 75
      blade-service/blade-business/src/main/java/org/springblade/business/utils/FileUtils.java
  80. 11 1
      blade-service/blade-business/src/main/java/org/springblade/business/utils/PDFUtil.java
  81. 1 1
      blade-service/blade-e-visa/pom.xml
  82. 82 62
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/service/impl/EVDataServiceImpl.java
  83. 3 3
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/service/impl/EVisaServiceImpl.java
  84. 41 18
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/utils/PDFUtils.java
  85. 13 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/APIController.java
  86. 76 603
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ExcelTabController.java
  87. 6 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/TableFileController.java
  88. 2 2
      blade-service/blade-manager/src/main/java/org/springblade/manager/feign/ExcelTabClientImpl.java
  89. 2 2
      blade-service/blade-manager/src/main/java/org/springblade/manager/feign/TableFileClientImpl.java
  90. 7 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/feign/WbsParamClientImpl.java
  91. 8 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/feign/WbsTreeContractClientImpl.java
  92. 33 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/feign/WbsTreeContractOldHtmlClientImpl.java
  93. 3 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/ExecutorMeter.java
  94. 122 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/FormulaZhiZuo.java
  95. 2 2
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ArchiveTreeContractMapper.xml
  96. 2 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ExcelTabMapper.xml
  97. 3 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/TableFileMapper.xml
  98. 7 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/TextdictInfoMapper.java
  99. 15 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/TextdictInfoMapper.xml
  100. 12 2
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsFormElementMapper.xml

+ 7 - 2
blade-common/src/main/java/org/springblade/common/utils/YiKeYunApiUtils.java

@@ -100,8 +100,13 @@ public class YiKeYunApiUtils {
      * @param cityId
      * @return
      */
-    public static Map<String, Map<String, String>> getHistoryWeather(String cityId, Integer year, Integer month) {
-        String getUrl = String.format("http://gfeljm.tianqiapi.com/free/history?appid=%s&appsecret=%s&cityid=%s&year=%d&month=%d", API_YIKEYUN_APPID, API_YIKEYUN_APPSECRET, cityId, year, month);
+    public static Map<String, Map<String, String>> getHistoryWeather(String cityId, Integer year, Integer month, String date1) {
+        String getUrl;
+        if (date1 != null && date1.matches("\\d{4}-\\d{2}-\\d{2}")) {
+            getUrl = String.format("http://gfeljm.tianqiapi.com/free/history?appid=%s&appsecret=%s&cityid=%s&date=%s", API_YIKEYUN_APPID, API_YIKEYUN_APPSECRET, cityId, date1);
+        } else {
+            getUrl = String.format("http://gfeljm.tianqiapi.com/free/history?appid=%s&appsecret=%s&cityid=%s&year=%d&month=%d", API_YIKEYUN_APPID, API_YIKEYUN_APPSECRET, cityId, year, month);
+        }
         Map<String, Map<String, String>> map = new HashMap<>();
         try {
             URL url = new URL(getUrl);

+ 35 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/dto/RecycleBinInfoDTO.java

@@ -0,0 +1,35 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.business.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+
+@Data
+public class RecycleBinInfoDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty("ids")
+    private String ids;
+
+    @ApiModelProperty("是否恢复同批次全部删除数据, 0否,1是")
+    private Integer recoverOperationData;
+
+}

+ 135 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/RecycleBinInfo.java

@@ -0,0 +1,135 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.business.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springblade.core.mp.base.BaseEntity;
+import org.springblade.core.secure.utils.AuthUtil;
+import org.springblade.core.tool.utils.DateUtil;
+
+import java.util.Date;
+
+/**
+ * 实体类
+ *
+ * @author BladeX
+ * @since 2022-07-19
+ */
+@Data
+@TableName("u_recycle_bin_info")
+@EqualsAndHashCode(callSuper = true)
+public class RecycleBinInfo extends BaseEntity {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 项目ID
+     */
+    @ApiModelProperty("项目ID")
+    private Long projectId;
+    /**
+     * 合同段ID
+     */
+    @ApiModelProperty("合同段ID")
+    private Long contractId;
+
+    @ApiModelProperty("删除的id")
+    private Long delId;
+
+    @ApiModelProperty("删除位置id")
+    private Long delRootId;
+
+    @ApiModelProperty("删除位置名称")
+    private String delRootName;
+
+    @ApiModelProperty("操作记录id")
+    private String operationId;
+
+    /**
+     * 删除的类型,文件资料1,工程划分2,影像资料3
+     */
+    @ApiModelProperty("删除的类型,文件资料1,工程划分2,影像资料3")
+    private Integer delType;
+
+    /**
+     * 是否是资料节点,0否,1是
+     */
+    @ApiModelProperty("是否是资料节点,0否,1是")
+    private Integer isData;
+
+    /**
+     * 文件名称
+     */
+    @ApiModelProperty("文件名称(施工)")
+    private String fileName;
+
+    @ApiModelProperty("文件名称(监理)")
+    private String jlFileName;
+
+    /**
+     * 所在位置,即节点路径
+     */
+    @ApiModelProperty("所在位置,即节点路径")
+    private String position;
+    /**
+     * 业务ID
+     */
+    @ApiModelProperty("业务ID")
+    private String businessId;
+    /**
+     * 操作时间,与创建时间相同
+     */
+    @ApiModelProperty("操作时间,与创建时间相同")
+    private String operationTime;
+
+    @ApiModelProperty("操作人姓名")
+    private String createUserName;
+
+    @ApiModelProperty("更新者姓名")
+    private String updateUserName;
+
+    @TableField(exist = false)
+    @ApiModelProperty("删除信息")
+    private String delInfo;
+
+    public RecycleBinInfo(String businessIds, String title, Integer deletedType, String position, String projectId, String contractId) {
+        this.businessId = businessIds;
+        this.fileName = title;
+        this.delType = deletedType;
+        this.position = position;
+        this.projectId = Long.parseLong(projectId);
+        this.contractId = Long.parseLong(contractId);
+
+        this.setCreateUser(AuthUtil.getUserId());
+        this.createUserName = AuthUtil.getNickName();
+        Date now = new Date();
+        this.setCreateTime(now);
+        this.operationTime = DateUtil.format(now, "yyyy-MM-dd HH:mm:ss");
+    }
+
+    public RecycleBinInfo() {
+    }
+
+    public String getDelInfo() {
+        return this.getCreateUserName() == null ? "" : this.getCreateUserName() + "\n" + (this.getCreateTime() == null ? "" : DateUtil.format(this.getCreateTime(), "yyyy-MM-dd HH:mm:ss"));
+    }
+
+}

+ 59 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/TrialCyAccessories.java

@@ -0,0 +1,59 @@
+package org.springblade.business.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * 成渝-附件信息
+ * @author LHB
+ * @TableName u_trial_cy_accessories
+ */
+@TableName(value ="u_trial_cy_accessories")
+@Data
+public class TrialCyAccessories {
+    /**
+     * 主键
+     */
+    @ApiModelProperty("唯一id")
+    @TableId(type = IdType.INPUT)
+    private Long id;
+
+    /**
+     * 报告id,已签章的报告/是第三方检测报告/外委检测报告/上传报告
+     */
+    @ApiModelProperty("报告id,已签章的报告/ 是第三方检测报告/ 外委检测报告/ 上传报告")
+    private Long reportId;
+
+    /**
+     * 成渝接口返回的id
+     */
+    @ApiModelProperty("成渝接口返回的")
+    @TableField("acc_id")
+    private String accId;
+
+    /**
+     * 类型名称
+     */
+
+    @ApiModelProperty("类型名称")
+    @TableField("acc_type")
+    private String accType;
+
+    /**
+     * 文件名称
+     */
+    @ApiModelProperty("文件名称")
+    @TableField("file_name")
+    private String fileName;
+
+    /**
+     * 文件路径
+     */
+    @ApiModelProperty("文件路径")
+    @TableField("file_path")
+    private String filePath;
+}

+ 149 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/TrialCyFinishTestReport.java

@@ -0,0 +1,149 @@
+package org.springblade.business.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 已完成(已签章完成)的检测报告接受对象
+ *
+ * @author LHB
+ */
+@TableName("u_trial_cy_finish_test_report")
+@Data
+public class TrialCyFinishTestReport {
+
+    @TableId(type = IdType.INPUT)
+    @ApiModelProperty("唯一id")
+    private Long id;
+    /**
+     * 合同ID
+     */
+    @TableField("contract_id")
+    @ApiModelProperty("合同ID")
+    private Long contractId;
+    /**
+     * 任务ID
+     */
+    @ApiModelProperty("任务ID")
+    private Integer taskId;
+    /**
+     * 合同段编码
+     */
+    @ApiModelProperty("合同段编码")
+    private String contractNumber;
+    /**
+     * 单位类型
+     * 0 施工
+     * 1 监理
+     * 2 中试
+     */
+    @ApiModelProperty("单位类型 0 施工 1 监理 2 中试")
+    private Integer cs;
+    /**
+     * 记录编号
+     */
+    @ApiModelProperty("记录编号")
+    private String number;
+    /**
+     * 报告编号
+     */
+    @ApiModelProperty("报告编号")
+    private String reportNumber;
+    /**
+     * 试验项目名称
+     */
+    @ApiModelProperty("试验项目名称")
+    private String name;
+    /**
+     * 试验工序名称
+     */
+    @ApiModelProperty("试验工序名称")
+    private String processName;
+    /**
+     * 取样地点
+     */
+    @ApiModelProperty("取样地点")
+    @TableField("sampling_place")
+    private String samplingPlace;
+    /**
+     * 样品信息 同试验检测查询界面
+     */
+    @ApiModelProperty("样品信息 同试验检测查询界面")
+    @TableField("sample_info")
+    private String sampleInfo;
+    /**
+     * 类型规格 规格型号
+     */
+    @ApiModelProperty("类型规格 规格型号")
+    @TableField("specification")
+    private String specification;
+    /**
+     * 合格证上传情况 已上传、未上传
+     */
+    @ApiModelProperty("合格证上传情况 已上传、未上传")
+    @TableField("hash_gz")
+    private String hasHGZ;
+    /**
+     * 所检参数信息 同试验检测查询界面
+     */
+    @ApiModelProperty("所检参数信息 同试验检测查询界面")
+    @TableField("test_param_info")
+    private String testParamInfo;
+    /**
+     * 报告时间
+     */
+    @ApiModelProperty("报告时间")
+    private String reportDate;
+    /**
+     * 是否合格 True 合格,False不合格
+     */
+    @ApiModelProperty("是否合格 1 合格,0 不合格")
+    private String experimentResult;
+    /**
+     * 报告人
+     */
+    @ApiModelProperty("报告人")
+    @TableField("user_name")
+    private String username;
+    /**
+     * 使用部位
+     */
+    @ApiModelProperty("使用部位")
+    private String position;
+    /**
+     * 报告文件路径
+     */
+    @ApiModelProperty("报告文件路径")
+    @TableField("report_file_path")
+    private String reportFilePath;
+    /**
+     * 记录文件路径
+     */
+    @ApiModelProperty("记录文件路径")
+    @TableField("record_file_path")
+    private String recordFilePath;
+    /**
+     * 试验树id
+     */
+    @ApiModelProperty("实验树Id")
+    @TableField("exam_name_info_id")
+    public String examNameInfoId;
+    /**
+     * 试验树id
+     */
+    @ApiModelProperty("组装文件(报告+记录+委托单)")
+    @TableField("assemble_file")
+    public String assembleFile;
+    /**
+     * 附件
+     */
+    @ApiModelProperty("附件")
+    @TableField(exist = false)
+    private List<TrialCyAccessories> accessories;
+}

+ 54 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/TrialCyTestType.java

@@ -0,0 +1,54 @@
+package org.springblade.business.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * 获取检测项目树(包括自建试验、外委、第三方、上传报告) 接受对象
+ *
+ * @author LHB
+ */
+@TableName("u_trial_cy_test_type")
+@Data
+public class TrialCyTestType {
+    @TableId(type = IdType.INPUT)
+    @ApiModelProperty("唯一id")
+    private Long pKeyId;
+    /**
+     * 项目id
+     */
+    @ApiModelProperty("项目id")
+    private Long projectId;
+    /**
+     * ID唯一标识
+     */
+    @TableField("id")
+    @ApiModelProperty("成渝的id")
+    private String id;
+    /**
+     * 名称
+     */
+    @TableField("name")
+    @ApiModelProperty("名称")
+    private String name;
+    /**
+     * 父级ID
+     */
+    @TableField("father_id")
+    @ApiModelProperty("父级id")
+    private String fatherId;
+    /**
+     * 顺序号
+     */
+    @TableField("order_index")
+    @ApiModelProperty("顺序号")
+    private String orderIndex;
+
+    @TableField(exist = false)
+    @ApiModelProperty("判断是否有子节点")
+    private Boolean hasChildren;
+}

+ 285 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/TrialCyThirdReport.java

@@ -0,0 +1,285 @@
+package org.springblade.business.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 获取已上传的外委检测报告/第三方检测报告/上传报告 接受对象
+ *
+ * @author LHB
+ */
+@TableName("u_trial_cy_third_report")
+@Data
+public class TrialCyThirdReport {
+    @ApiModelProperty("唯一id")
+    @TableId(type = IdType.INPUT)
+    private Long pKeyId;
+    /**
+     * 合同id
+     */
+    @ApiModelProperty("合同id")
+    private Long contractId;
+    /**
+     * ID
+     */
+    @ApiModelProperty("成渝的id")
+    @TableField("id")
+    public String id;
+    /**
+     * 报告类型(0:外委检测,1:第三方检测,2:扫描上传报告)
+     */
+    @ApiModelProperty("报告类型(0:外委检测,1:第三方检测,2:扫描上传报告)")
+    public Integer thirdType;
+    /**
+     * 委托编号
+     */
+    @ApiModelProperty("委托编号")
+    @TableField("consign_no")
+    public String consignNo;
+    /**
+     * 报告编号
+     */
+    @ApiModelProperty("报告编号")
+    @TableField("report_no")
+    public String reportNo;
+    /**
+     * 取样时间 格式如:“2022-06-21”
+     */
+    @ApiModelProperty("取样时间 格式如:“2022-06-21”")
+    @TableField("take_sampling_date")
+    public String takeSamplingDate;
+    /**
+     * 送样时间 格式如:“2022-06-21”
+     */
+    @ApiModelProperty("送样时间 格式如:“2022-06-21”")
+    @TableField("send_sample_date")
+    public String sendSampleDate;
+    /**
+     * 检测时间 格式如:“2022-06-21”
+     */
+    @ApiModelProperty("检测时间 格式如:“2022-06-21”")
+    @TableField("test_date")
+    public String testDate;
+    /**
+     * 报告时间 格式如:“2022-06-21”
+     */
+    @ApiModelProperty("报告时间 格式如:“2022-06-21”")
+    @TableField("report_date")
+    public String reportDate;
+    /**
+     * 委托单位
+     */
+    @ApiModelProperty("委托单位")
+    @TableField("consign_unit")
+    public String consignUnit;
+    /**
+     * 检测机构
+     */
+    @ApiModelProperty("检测机构")
+    @TableField("accept_test_unit")
+    public String acceptTestUnit;
+    /**
+     * 送样人
+     */
+    @ApiModelProperty("送样人")
+    @TableField("send_sample_person")
+    public String sendSamplePerson;
+    /**
+     * 接样人
+     */
+    @ApiModelProperty("接样人")
+    @TableField("witness_person")
+    public String witnessPerson;
+    /**
+     * 工程部位
+     */
+    @ApiModelProperty("工程部位")
+    @TableField("project_part")
+    public String projectPart;
+    /**
+     * 取样地点
+     */
+    @ApiModelProperty("取样地点")
+    @TableField("sampling_place")
+    public String samplingPlace;
+    /**
+     * 样品名称
+     */
+    @ApiModelProperty("样品名称")
+    @TableField("sample_name")
+    public String sampleName;
+    /**
+     * 委托单文件下载地址
+     */
+    @ApiModelProperty("委托单文件下载地址")
+    @TableField("consign_doc_file_path")
+    public String consignDocFilePath;
+    /**
+     * 记录单文件下载地址
+     */
+    @ApiModelProperty("记录单文件下载地址")
+    @TableField("record_doc_file_path")
+    public String recordDocFilePath;
+    /**
+     * 报告单文件下载地址
+     */
+    @ApiModelProperty("报告单文件下载地址")
+    @TableField("report_doc_file_path")
+    public String reportDocFilePath;
+    /**
+     * 检测依据
+     */
+    @ApiModelProperty("检测依据")
+    @TableField("test_standard")
+    public String testStandard;
+    /**
+     * 评定标准
+     */
+    @ApiModelProperty("评定标准")
+    @TableField("assess_standard")
+    public String assessStandard;
+    /**
+     * 检测结论
+     */
+    @ApiModelProperty("检测结论")
+    @TableField("test_conclusion")
+    public String testConclusion;
+    /**
+     * 备注
+     */
+    @ApiModelProperty("备注")
+    @TableField("memo")
+    public String memo;
+    /**
+     * 期数
+     */
+    @ApiModelProperty("期数")
+    @TableField("period_num")
+    public String periodNum;
+    /**
+     * 是否合格
+     */
+    @ApiModelProperty("是否合格:1 合格, 0 不合格")
+    @TableField("is_qualified")
+    public String isQualified;
+    /**
+     * 样品编号
+     */
+    @ApiModelProperty("样品编号")
+    @TableField("sample_code")
+    public String sampleCode;
+    /**
+     * 规格型号
+     */
+    @ApiModelProperty("规格型号")
+    @TableField("gui_ge_xing_hao")
+    public String guiGeXingHao;
+    /**
+     * 生产厂家
+     */
+    @ApiModelProperty("生产厂家")
+    @TableField("sheng_chan_cj")
+    public String shengChanCJ;
+    /**
+     * 产地
+     */
+    @ApiModelProperty("产地")
+    @TableField("chan_di")
+    public String chanDi;
+    /**
+     * 样品数量
+     */
+    @ApiModelProperty("样品数量")
+    @TableField("sample_num")
+    public String sampleNum;
+    /**
+     * 检测机构资质证书编号
+     */
+    @ApiModelProperty("检测机构资质证书编号")
+    @TableField("consign_unit_ability")
+    public String consignUnitAbility;
+    /**
+     * 批号
+     */
+    @ApiModelProperty("批号")
+    @TableField("batch_num")
+    public String batchNum;
+    /**
+     * 代表数量
+     */
+    @ApiModelProperty("代表数量")
+    @TableField("quantity")
+    public String quantity;
+    /**
+     * 单位
+     */
+    @ApiModelProperty("单位")
+    @TableField("unit")
+    public String unit;
+    /**
+     * 类型ID
+     */
+    @ApiModelProperty("类型ID")
+    @TableField("consign_test_cls_id")
+    public String consignTestClsID;
+    /**
+     * 结论
+     */
+    @ApiModelProperty("结论")
+    @TableField("result")
+    public String result;
+    /**
+     * 是否已删除
+     * Null:未删除
+     * 0:未删除
+     * 1:已删除
+     */
+    @ApiModelProperty("是否已删除 0:未删除 1:已删除")
+    @TableField("is_deleted")
+    public String isDeleted;
+    /**
+     * 删除时间
+     */
+    @ApiModelProperty("删除时间")
+    @TableField("delete_time")
+    public String deleteTime;
+    /**
+     * 快报/正式报告
+     * 1 快报
+     * 2 正式报告
+     */
+    @ApiModelProperty("快报/ 正式报告 1 快报 2 正式报告")
+    @TableField("report_type")
+    public Integer reportType;
+    /**
+     * 创建时间 格式如:“2022-06-21 13:44:33 235”
+     */
+    @ApiModelProperty("创建时间 格式如:“2022-06-21 13:44:33 235”")
+    @TableField("create_time")
+    public String createTime;
+    /**
+     * 试验树id
+     */
+    @ApiModelProperty("实验树Id")
+    @TableField("exam_name_info_id")
+    public String examNameInfoId;
+    /**
+     * 试验树id
+     */
+    @ApiModelProperty("组装文件(报告+记录+委托单)")
+    @TableField("assemble_file")
+    public String assembleFile;
+
+    /**
+     * 附件
+     */
+    @ApiModelProperty("附件")
+    @TableField(exist = false)
+    private List<TrialCyAccessories> accessories;
+}

+ 24 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/feign/TrialCyAccessoriesClient.java

@@ -0,0 +1,24 @@
+package org.springblade.business.feign;
+
+import com.alibaba.fastjson.JSONObject;
+import org.springblade.common.constant.BusinessConstant;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import java.util.List;
+
+/**
+ * @author LHB
+ */
+
+@FeignClient(value = BusinessConstant.APPLICATION_WEATHER_NAME)
+public interface TrialCyAccessoriesClient {
+    /**
+     * 接口前缀
+     */
+    String API_PREFIX = "/api/business/detection";
+
+    @PostMapping(API_PREFIX + "/getTrialFilePdfRecord")
+    List<JSONObject> getTrialFilePdfRecord(@RequestParam String primaryKeyId,@RequestParam List<Integer> list);
+}

+ 3 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/EntrustInfoVO.java

@@ -53,4 +53,7 @@ public class EntrustInfoVO extends EntrustInfo {
     @ApiModelProperty("任务Id")
     private String taskId;
 
+	@ApiModelProperty("委托单编号")
+	private String entrustNo;
+
 }

+ 72 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/RecycleBinInfoVO.java

@@ -0,0 +1,72 @@
+package org.springblade.business.vo;
+
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springblade.core.mp.support.Query;
+
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+import java.util.Date;
+
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class RecycleBinInfoVO extends Query implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 开始时间
+     */
+    @ApiModelProperty("开始时间")
+    private String startTime;
+    /**
+     * 结束时间
+     */
+    @ApiModelProperty("结束时间")
+    private String endTime;
+
+    /**
+     * 用户ID
+     */
+    @ApiModelProperty("用户ID")
+    private Long userId;
+
+    /**
+     * 合同段ID
+     */
+    @ApiModelProperty("合同段ID")
+    @NotNull
+    private Long contractId;
+
+    /**
+     * 是否是资料节点,0否,1是
+     */
+    @ApiModelProperty("是否是资料节点,0否,1是")
+    private Integer isData;
+
+    /**
+     * 0:删除台账, 1:恢复台账
+     */
+    @ApiModelProperty("0:删除台账, 1:恢复台账")
+    private Integer recycleType = 0;
+
+    /**
+     * 删除的类型,文件资料1,工程划分2,影像资料3
+     */
+    @ApiModelProperty("删除的类型,文件资料1,工程划分2,影像资料3")
+    private Integer delType = 2;
+
+    /**
+     * 内容
+     */
+    @ApiModelProperty("内容")
+    private String content;
+
+    @ApiModelProperty("操作记录id")
+    private String operationId;
+
+
+}

+ 20 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/ThirdReportVo.java

@@ -0,0 +1,20 @@
+package org.springblade.business.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * @author LHB
+ */
+@Data
+public class ThirdReportVo {
+    private Long id;
+    private Long contractId;
+    private String reportNo;
+    private String reportDate;
+    private String projectPositionName;
+    private String detectionResultName;
+
+    @ApiModelProperty(value = "是否关联选择过 0=否 1=是")
+    private Integer isSelectedStatus;
+}

+ 31 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/TrialCyThirdReportQueryVo.java

@@ -0,0 +1,31 @@
+package org.springblade.business.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * 接口查询条件对象
+ * @author LHB
+ */
+@Data
+public class TrialCyThirdReportQueryVo {
+    private Integer current;
+    private Integer size;
+    @ApiModelProperty("开始时间")
+    private String startTime;
+    @ApiModelProperty("结束时间")
+    private String endTime;
+    @ApiModelProperty("树节点id")
+    @NotNull(message = "树节点id不能为空")
+    private Long nodeId;
+    @ApiModelProperty("合同段id")
+    @NotNull(message = "合同段id不能为空")
+    private Long contractId;
+    @ApiModelProperty("质检节点pkeyid")
+    private Long qualityTestPKeyId;
+    @ApiModelProperty("类型:0-外委检测,1-第三方")
+    private Integer type;
+
+}

+ 7 - 4
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/TableFile.java

@@ -16,10 +16,7 @@
  */
 package org.springblade.manager.entity;
 
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableLogic;
-import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.annotation.*;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
 import io.swagger.annotations.ApiModel;
@@ -98,4 +95,10 @@ public class TableFile implements Serializable {
 
     private Integer sort;
 
+    /**
+     * 文件是否为关联的试验文件
+     */
+    @TableField(exist = false)
+    private Boolean isTrial = false;
+
 }

+ 61 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/WbsTreeContractOldHtml.java

@@ -0,0 +1,61 @@
+package org.springblade.manager.entity;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.util.Date;
+import lombok.Data;
+
+/**
+ * 合同段表单上报之前的html记录
+ * @author LHB
+ * @TableName m_wbs_tree_contract_old_html
+ */
+@TableName(value ="m_wbs_tree_contract_old_html")
+@Data
+public class WbsTreeContractOldHtml {
+    /**
+     * 
+     */
+    @TableId
+    private Long id;
+
+    /**
+     * 合同WBS的p_key_id
+     */
+    private Long contractFormId;
+
+    /**
+     * 上报之前的html表单
+     */
+    private String oldHtmlUrl;
+
+    /**
+     * 上报之前的html表单
+     */
+    private String oldExcelUrl;
+
+    /**
+     *  是否删除(0-正常,1-已删除)
+     */
+    private Integer isDeleted;
+
+    /**
+     *  创建时间
+     */
+    private Date createTime;
+
+    /**
+     *  创建人
+     */
+    private Long createUser;
+
+    /**
+     *  修改时间
+     */
+    private Date updateTime;
+
+    /**
+     *  修改人
+     */
+    private Long updateUser;
+}

+ 1 - 1
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/ExcelTabClient.java

@@ -95,7 +95,7 @@ public interface ExcelTabClient {
     void excelInfo(@RequestPart("file") MultipartFile file, @RequestParam String exceUrl, @RequestParam String thmlUrl, @RequestParam String number) throws IOException;
 
     @PostMapping(API_PREFIX + "/saveLinkTab")
-    void saveLinkTab(@RequestParam Long excelId,@RequestParam Long pKeyId) throws IOException;
+    void saveLinkTab(@RequestParam Long excelId,@RequestParam Long pKeyId) throws Exception;
 
     @PostMapping(API_PREFIX + "/getTheLogPdInfo")
     void getTheLogPdInfo(@RequestParam String logPkeyId,  @RequestParam String nodePrimaryKeyId, @RequestParam String recordTime, @RequestParam String contractId,@RequestParam Long createUser) throws Exception;

+ 2 - 2
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/TableFileClient.java

@@ -29,7 +29,7 @@ public interface TableFileClient {
     @PostMapping(API_PREFIX + "/saveBatch")
     boolean saveBatch(@RequestBody List<TableFile> newFiles);
 
-    @GetMapping(API_PREFIX + "/getTabFilesByTabIds")
-    List<TableFile> getTabFilesByTabIds(@RequestParam String tabFileIds);
+    @PostMapping(API_PREFIX + "/getTabFilesByTabIds")
+    List<TableFile> getTabFilesByTabIds(@RequestBody List<String> tabFileIds);
 
 }

+ 4 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/WbsParamClient.java

@@ -9,6 +9,8 @@ import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestParam;
 
+import java.util.List;
+
 import static org.springblade.core.launch.constant.AppConstant.APPLICATION_NAME_PREFIX;
 
 @FeignClient(value = APPLICATION_NAME_PREFIX + "manager")
@@ -24,6 +26,8 @@ public interface WbsParamClient {
     @GetMapping(API_PREFIX + "/getWbsParam")
     WbsParam getWbsParam(@RequestParam Long nodeId);
 
+    @PostMapping(API_PREFIX + "/saveWbsParams")
+    void saveWbsParams(@RequestBody List<WbsParam> wbsParamList);
     @PostMapping(API_PREFIX + "/createFileTitle")
     String createFileTitle(@RequestBody WbsTreeContract contract);
 }

+ 6 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/WbsTreeContractClient.java

@@ -203,6 +203,12 @@ public interface WbsTreeContractClient {
     @GetMapping(API_PREFIX + "/get-ekey")
     EKeyDto getEKey(@RequestParam String contractId, @RequestParam Long pKeyId, @RequestParam String wbsId);
 
+    @GetMapping(API_PREFIX + "/findIsExistTreeNode")
+    Integer findIsExistTreeNode(List<String> processNodeList);
+
+    @PostMapping(API_PREFIX + "/queryListByPIds")
+    List<WbsTreeContract> queryListByPIds(@RequestBody List<Long> pIds);
+
     @GetMapping(API_PREFIX + "/saveNameRuleByPkeyId")
     void saveNameRuleByPkeyId(@RequestParam Long  pKeyId, @RequestParam String s,  @RequestParam Long projectId);
 }

+ 25 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/WbsTreeContractOldHtmlClient.java

@@ -0,0 +1,25 @@
+package org.springblade.manager.feign;
+
+import org.springblade.manager.entity.WbsTreeContract;
+import org.springblade.manager.entity.WbsTreeContractOldHtml;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+
+import java.util.List;
+
+import static org.springblade.core.launch.constant.AppConstant.APPLICATION_NAME_PREFIX;
+
+@FeignClient(value = APPLICATION_NAME_PREFIX + "manager")
+public interface WbsTreeContractOldHtmlClient {
+    /**
+     * 接口前缀
+     */
+    String API_PREFIX = "/api/manager/WbsTreeContractOldHtml";
+
+    @PostMapping(API_PREFIX + "/save")
+    Boolean save(@RequestBody List<WbsTreeContractOldHtml> data);
+
+    @PostMapping(API_PREFIX + "/deleteByContractFormIds")
+    void deleteByContractFormIds(@RequestBody List<Long> collect);
+}

+ 84 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/APIWbsContractSubdivisionVo.java

@@ -0,0 +1,84 @@
+package org.springblade.manager.vo;
+
+import lombok.Data;
+import org.springblade.manager.entity.WbsTreeContract;
+
+/**
+ * 合同段分部分项划分节点试图
+ * 包含各个状态
+ * | 01   | 交工证书     | 所有子节点存在一个的major_data_type = 3   值为 true     |
+ * | 02   | 7天强度报告  | 所有最小节点中在m_table_file 中type = 11  存在一个true  |
+ * | 03   | 28天强度报告 | 所有最小节点中在m_table_file 中type = 12   存在一个true |
+ * | 04   | 监理收验资料 | 监理 major_data_type = 4  全部已审批                    |
+ * | 05   | 桩检报告     | 所有最小节点中在m_table_file 中type = 13   存在一个true |
+ * | 06   | 质检资料     | 质检 major_data_type = 4  全部已审批                    |
+ * | 07   | 评定资料     | major_data_type = 2  全部已审批                         |
+ * @author LHB
+ */
+@Data
+public class APIWbsContractSubdivisionVo {
+    /**
+     * 主键
+     */
+    private Long id;
+    /**
+     * 编码 空
+     */
+    private String code;
+    /**
+     * 节点名称
+     */
+    private String name;
+    /**
+     * 桩号
+     */
+    private String stake;
+    /**
+     * 父节点id
+     */
+    private Long pid;
+    /**
+     * 1表示单位工程 2表示分部工程 3表示分项工程
+     */
+    private Integer nodeType;
+    /**
+     * 层级编码 空
+     */
+    private String levelCode;
+    /**
+     * 专业工程id
+     */
+    private String partitionCatagID;
+    /**
+     * 专业工程名称
+     */
+    private String partitionCatagName;
+    /**
+     * 交工证书
+     */
+    private Boolean completionCertificate = false;
+    /**
+     * 7天强度报告
+     */
+    private Boolean strengthReportSeven = false;
+    /**
+     * 28天强度报告
+     */
+    private Boolean strengthReportTwentyEight = false;
+    /**
+     * 监理资料
+     */
+    private Boolean supervisionData = false;
+    /**
+     * 桩检报告
+     */
+    private Boolean pileInspectionReport = false;
+    /**
+     * 质检资料
+     */
+    private Boolean qualityInspectionData = false;
+    /**
+     * 评定资料
+     */
+    private Boolean evaluationData = false;
+}

+ 1 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ExcelTabVo1.java

@@ -9,4 +9,5 @@ public class ExcelTabVo1 {
     private String htmlUrl;
     private String name;
     private String fileUrl;
+    private String tabName;
 }

+ 1 - 1
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/TextdictInfoVO.java

@@ -36,6 +36,6 @@ public class TextdictInfoVO extends TextdictInfo {
     //1.电签配置 2.系统识别
     private Integer showType;
 
-    @ApiModelProperty("是否引用系统级电签配置,1 系统级,0 项目级")
+    @ApiModelProperty("本表配置 绿色0,电签库 蓝色1,项目匹配 橙色2")
     private Integer isSystem = 0;
 }

+ 1 - 1
blade-service/blade-archive/pom.xml

@@ -173,7 +173,7 @@
                     <target>${java.version}</target>
                     <encoding>${project.build.sourceEncoding}</encoding>
                     <compilerArguments>
-                        <bootclasspath>${java.home}/lib/rt.jar:${java.home}/lib/jce.jar:${java.home}/lib/jsse.jar
+                        <bootclasspath>${java.home}/lib/rt.jar${path.separator}${java.home}/lib/jce.jar${path.separator}${java.home}/lib/jsse.jar
                         </bootclasspath>
                     </compilerArguments>
                 </configuration>

+ 8 - 2
blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchivesAutoController.java

@@ -656,14 +656,20 @@ public class ArchivesAutoController extends BladeController {
 		//根据档号后缀排序 拿到第一个
 		ArchivesAuto auto = archivesAutoList.get(0);
 		//查出所有案卷文件
-		List<ArchiveFile>archiveFileList=archiveFileClient.getArchiveFileByArchiveIds(ids);
+		List<ArchiveFile>archiveFileList=new ArrayList<>();
+		List<Long> longList = Func.toLongList(ids);
+		for (Long id : longList) {
+			archiveFileList.addAll(archiveFileClient.getArchiveFileByArchiveIds(id+""));
+		}
 		//将除第一个以外的案卷文件archiveId 设置成第一个的id
 		List<ArchiveFile>updateArchiveFileList=new ArrayList<>();
+		int i=1;
 		for (ArchiveFile file : archiveFileList) {
 			if (!file.getArchiveId().equals(auto.getId())) {
 				file.setArchiveId(auto.getId());
-				updateArchiveFileList.add(file);
 			}
+			file.setArchiveSort(i++);
+			updateArchiveFileList.add(file);
 		}
 		archiveFileClient.updateArchiveFile(updateArchiveFileList);
 		auto.setName(name);

+ 95 - 98
blade-service/blade-business/src/main/java/org/springblade/business/controller/InformationWriteQueryController.java

@@ -7,6 +7,7 @@ import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
@@ -28,7 +29,6 @@ import org.springblade.business.dto.CustomAddContractNodeDTO;
 import org.springblade.business.dto.ImportTreeDto;
 import org.springblade.business.dto.WbsTreeContractStatisticsDTO;
 import org.springblade.business.dto.FlushQueryNameDTO;
-import org.springblade.business.dto.FlushQueryNameDTO;
 import org.springblade.business.dto.PreviewNodeNameDTO;
 import org.springblade.business.dto.PreviewNodeNameDTO1;
 import org.springblade.business.entity.*;
@@ -86,6 +86,9 @@ import javax.servlet.http.HttpServletResponse;
 import javax.validation.Valid;
 import java.io.*;
 import java.net.URLEncoder;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
@@ -112,6 +115,7 @@ public class InformationWriteQueryController extends BladeController {
     private final ContractClient contractClient;
 
     private final WbsTreeContractClient wbsTreeContractClient;
+    private final WbsTreeContractOldHtmlClient wbsTreeContractOldHtmlClient;
 
     private final WbsTreePrivateClient wbsTreePrivateClient;
 
@@ -157,6 +161,7 @@ public class InformationWriteQueryController extends BladeController {
 
     private final IRecycleBinService recycleBinService;
     private final WbsTreeContractStatisticsClientImpl wbsTreeContractStatisticsClient;
+    private final IRecycleBinInfoService recycleBinInfoService;
 
 
     @Autowired
@@ -1961,11 +1966,14 @@ public R<Boolean> copyContractTreeNode(@RequestBody CopyContractTreeNodeVO vo) {
 
             //旧节点的pkeyId和新节点的pkeyId
             Map<Long, Long> oldPKeyIdToNewPKeyIdMap = new HashMap<>();
+            Map<Long, Long> oldIdToNewIdMap = new HashMap<>();
             //节点和表的id 与 节点/表 实体类
             Map<String, WbsTreeContract> nodeMap = new HashMap<>();
 
             nodeChildAll.forEach(node -> {
-                oldPKeyIdToNewPKeyIdMap.put(node.getPKeyId(),SnowFlakeUtil.getId());
+                Long id = SnowFlakeUtil.getId();
+                oldPKeyIdToNewPKeyIdMap.put(node.getPKeyId(), id);
+                oldIdToNewIdMap.put(node.getId(), id);
                 oldToNewIdMap.put(node.getId(), SnowFlakeUtil.getId());
                 nodeMap.put(node.getId().toString(), node);
             });
@@ -1980,54 +1988,55 @@ public R<Boolean> copyContractTreeNode(@RequestBody CopyContractTreeNodeVO vo) {
                         .filter(ObjectUtil::isNotEmpty)
                         .distinct()
                         .collect(Collectors.toList());
-                //表名集合转逗号拼接的字符串
-                String inClausePlaceholders = String.join(",", Collections.nCopies(tabNames.size(), "?"));
-                String sql = "SELECT table_name AS queryType, GROUP_CONCAT(COLUMN_name) AS ancestors " +
-                        "FROM information_schema.COLUMNS WHERE table_name IN (" + inClausePlaceholders + ") " +
-                        "GROUP BY table_name";
-                Object[] params = tabNames.toArray();
-                //数据库中查询 表与表对应的列名
-                List<Map<String, Object>> results = jdbcTemplate.queryForList(sql, params);
-
-                //表名集合转Map key=表名 value=表对应的数据集合
-                Map<String, List<WbsTreeContract>> tabsGroup = nodeChildAll.stream()
-                        .filter(f -> f.getType() == 2 && ObjectUtil.isNotEmpty(f.getInitTableName()))
-                        .collect(Collectors.groupingBy(WbsTreeContract::getInitTableName));
-
-                Set<Long> continuePkeyIds = new HashSet<>();
-                for (Map<String, Object> result : results) {
-                    String tabName = (String) result.get("queryType");
-                    String col = (String) result.get("ancestors");
-                    if (ObjectUtil.isEmpty(col) || ObjectUtil.isEmpty(tabName)) {
-                        continue;
-                    }
-                    //字段集合 过滤掉不存在指定字段的表
-                    List<String> filteredList = Arrays.stream(col.split(","))
-                            .filter(value -> !value.equals("id") && !value.equals("p_key_id") && !value.equals("group_id"))
-                            .collect(Collectors.toList());
-                    //过滤之后的字段集合
-                    String keys = StringUtils.join(filteredList, ",");
-                    //根据表明查询指定数据集合
-                    List<WbsTreeContract> tabs = tabsGroup.get(tabName);
-                    for (WbsTreeContract tab : tabs) {
-                        // 在复制数据时,测量记录表 的数据不需要复制
-                        if(tab.getType()==2 && tab.getTableType()==6){
+                if (!tabNames.isEmpty()) {
+                    String inClausePlaceholders = String.join(",", Collections.nCopies(tabNames.size(), "?"));
+                    String sql = "SELECT table_name AS queryType, GROUP_CONCAT(COLUMN_name) AS ancestors " +
+                            "FROM information_schema.COLUMNS WHERE table_name IN (" + inClausePlaceholders + ") " +
+                            "GROUP BY table_name";
+                    Object[] params = tabNames.toArray();
+                    //数据库中查询 表与表对应的列名
+                    List<Map<String, Object>> results = jdbcTemplate.queryForList(sql, params);
+
+                    //表名集合转Map key=表名 value=表对应的数据集合
+                    Map<String, List<WbsTreeContract>> tabsGroup = nodeChildAll.stream()
+                            .filter(f -> f.getType() == 2 && ObjectUtil.isNotEmpty(f.getInitTableName()))
+                            .collect(Collectors.groupingBy(WbsTreeContract::getInitTableName));
+
+                    Set<Long> continuePkeyIds = new HashSet<>();
+                    for (Map<String, Object> result : results) {
+                        String tabName = (String) result.get("queryType");
+                        String col = (String) result.get("ancestors");
+                        if (ObjectUtil.isEmpty(col) || ObjectUtil.isEmpty(tabName)) {
                             continue;
                         }
-                        //根据字段
-                        String dataSql = "SELECT " + keys + " FROM " + tabName + " WHERE p_key_id = " + tab.getPKeyId() + " LIMIT 1;";
-                        try {
-                            //查询指定表指定表节点的数据
-                            Map<String, Object> resultMap = jdbcTemplate.queryForMap(dataSql);
-                            //删除空值
-                            resultMap.values().removeIf(value -> value == null || (value instanceof String && ObjectUtil.isEmpty(value)));
-                            colMaps.put(tab.getPKeyId(), resultMap);
-                        } catch (EmptyResultDataAccessException e) {
-                            continuePkeyIds.add(tab.getPKeyId());
+                        //字段集合 过滤掉不存在指定字段的表
+                        List<String> filteredList = Arrays.stream(col.split(","))
+                                .filter(value -> !value.equals("id") && !value.equals("p_key_id") && !value.equals("group_id"))
+                                .collect(Collectors.toList());
+                        //过滤之后的字段集合
+                        String keys = StringUtils.join(filteredList, ",");
+                        //根据表明查询指定数据集合
+                        List<WbsTreeContract> tabs = tabsGroup.get(tabName);
+                        for (WbsTreeContract tab : tabs) {
+                            // 在复制数据时,测量记录表 的数据不需要复制
+                            if(tab.getType()==2 && tab.getTableType()==6){
+                                continue;
+                            }
+                            //根据字段
+                            String dataSql = "SELECT " + keys + " FROM " + tabName + " WHERE p_key_id = " + tab.getPKeyId() + " LIMIT 1;";
+                            try {
+                                //查询指定表指定表节点的数据
+                                Map<String, Object> resultMap = jdbcTemplate.queryForMap(dataSql);
+                                //删除空值
+                                resultMap.values().removeIf(value -> value == null || (value instanceof String && ObjectUtil.isEmpty(value)));
+                                colMaps.put(tab.getPKeyId(), resultMap);
+                            } catch (EmptyResultDataAccessException e) {
+                                continuePkeyIds.add(tab.getPKeyId());
+                            }
                         }
                     }
+                    logger.info("以下元素表没有获取到对应实体表数据,已跳过 ===> 表pKeyId:[{}]", StringUtils.join(continuePkeyIds, ","));
                 }
-                logger.info("以下元素表没有获取到对应实体表数据,已跳过 ===> 表pKeyId:[{}]", StringUtils.join(continuePkeyIds, ","));
             }
             // 节点+表节点
             for (WbsTreeContract nodeOld : nodeChildAll) {
@@ -2080,7 +2089,7 @@ public R<Boolean> copyContractTreeNode(@RequestBody CopyContractTreeNodeVO vo) {
                     //如果不是  判断旧节点的父级id是否在旧节点集合中 如果在 则设置新节点的父级id为旧节点的父级id的映射id  否则就是随机id
                     newData.setParentId(oldToNewIdMap.containsKey(nodeOld.getParentId()) ? oldToNewIdMap.get(nodeOld.getParentId()) : SnowFlakeUtil.getId());
                     //TODO 20250414-lhb-新增
-                    newData.setPId(oldPKeyIdToNewPKeyIdMap.containsKey(nodeOld.getPId()) ? oldPKeyIdToNewPKeyIdMap.get(nodeOld.getPId()) : SnowFlakeUtil.getId());
+                    newData.setPId(oldPKeyIdToNewPKeyIdMap.containsKey(nodeOld.getPId()) ? oldPKeyIdToNewPKeyIdMap.get(nodeOld.getPId()) : oldToNewIdMap.get(nodeOld.getParentId()) ==  null ? SnowFlakeUtil.getId() : oldToNewIdMap.get(nodeOld.getParentId()));
                 }
                 newData.setCreateTime(new Date());
                 newData.setUpdateTime(new Date());
@@ -2160,17 +2169,7 @@ public R<Boolean> copyContractTreeNode(@RequestBody CopyContractTreeNodeVO vo) {
             //TODO 20250414-lhb-新增 添加祖级字段 ancestorsPId
             //因为复制选中节点,所以要查询出选中节点的父节点信息 来组装祖级节点
             if(needCopyNode != null){
-                Long parentPKeyId = null;
-                String ancestorsPId = null;
-                if(needCopyNode.getPId() == 0L){
-                    ancestorsPId = "0";
-                    parentPKeyId = 0L;
-                }else{
-                    WbsTreeContract parentNode = this.wbsTreeContractClient.getContractNodeByPrimaryKeyId(String.valueOf(needCopyNode.getPId()));
-                    ancestorsPId = parentNode.getAncestorsPId();
-                    parentPKeyId = parentNode.getPKeyId();
-                }
-                attachNodesToTarget(saveList,parentPKeyId,ancestorsPId);
+                attachNodesToTarget(saveList);
             }
         }
         needCopyNode.setNodeName(vo.getNeedCopyNodeName());
@@ -2347,17 +2346,7 @@ public R<Boolean> copyContractTreeNode(@RequestBody CopyContractTreeNodeVO vo) {
                             resultAll.addAll(addTabList);
                             //因为复制选中节点,所以要查询出选中节点的父节点信息 来组装祖级节点
                             if(needCopyNode != null && CollectionUtil.isNotEmpty(resultAll)){
-                                Long parentPKeyId = null;
-                                String ancestorsPId = null;
-                                if(needCopyNode.getPId() == 0L){
-                                    ancestorsPId = "0";
-                                    parentPKeyId = 0L;
-                                }else{
-                                    WbsTreeContract parentNode = this.wbsTreeContractClient.getContractNodeByPrimaryKeyId(String.valueOf(toCopyVO.getPrimaryKeyId()));
-                                    ancestorsPId = parentNode.getAncestorsPId();
-                                    parentPKeyId = parentNode.getPKeyId();
-                                }
-                                attachNodesToTarget(resultAll,parentPKeyId,ancestorsPId);
+                                attachNodesToTarget(resultAll);
                             }
                         }
                     }
@@ -2500,8 +2489,9 @@ private Map<String, String> reviseValue(WbsTreeContract wtc, WbsTreeContract par
     if (wtc != null) {
         try {
             String tableName = wtc.getInitTableName();
-            if (!ekvMap.containsKey(tableName)) {
-                Map<String, String> map = ekvMap.computeIfAbsent(wtc.getInitTableName(), K -> new HashMap<>());
+//            if (!ekvMap.containsKey(tableName)) {
+//                Map<String, String> map = ekvMap.computeIfAbsent(wtc.getInitTableName(), K -> new HashMap<>());
+                Map<String, String> map = new HashMap<>();
                 if (parent == null) {
                     parent = this.wbsTreeContractClient.getContractWbsTreeByContractIdAndId(wtc.getParentId(), Long.parseLong(wtc.getContractId()));
                 }
@@ -2537,8 +2527,9 @@ private Map<String, String> reviseValue(WbsTreeContract wtc, WbsTreeContract par
                         });
                     }
                 }
-            }
-            return ekvMap.getOrDefault(tableName, new HashMap<>());
+//            }
+//            return ekvMap.getOrDefault(tableName, new HashMap<>());
+            return map;
         } catch (Exception e) {
             e.printStackTrace();
         }
@@ -2593,7 +2584,11 @@ private Object reviseValue(Map<String, String> p2, String key, Object value) {
                     /*重做随机值*/
                     List<RangeJson> rjs = JSON.parseArray(setting, RangeJson.class);
                     if (value != null && !value.toString().isEmpty() && Func.isNotEmpty(rjs)) {
-                        List<RangeJson> rangeJsons = rjs.stream().filter(rj -> rj.getPkeyId().equals(pKeyId)).collect(Collectors.toList());
+                        List<RangeJson> temp = rjs.stream().filter(rj -> rj.getPkeyId().equals(pKeyId)).collect(Collectors.toList());
+                        if (temp.isEmpty()) {
+                            temp = rjs;
+                        }
+                        List<RangeJson> rangeJsons = temp;
                         if (!rangeJsons.isEmpty()) {
                             List<String[]> la = Arrays.stream(value.toString().split("☆")).map(s -> s.split("_\\^_")).collect(Collectors.toList());
                             /*全部为一个数的时候不用修改*/
@@ -2701,8 +2696,8 @@ private List<WbsTreeContract> reBuildAncestors(List<WbsTreeContract> list) {
 public void addCopyTabFile(Set<WbsTreeContract> addChildNodesTables,
                            Set<WbsTreeContract> addChildNodesTablesOld) {
     //获取所有数据源附件文件
-    List<Long> tabFileIds = addChildNodesTablesOld.stream().distinct().map(WbsTreeContract::getPKeyId).collect(Collectors.toList());
-    Map<String, List<TableFile>> tableFileOldMap = tableFileClient.getTabFilesByTabIds(StringUtils.join(tabFileIds, ",")).stream().collect(Collectors.groupingBy(TableFile::getTabId));
+    List<String> tabFileIds = addChildNodesTablesOld.stream().distinct().map(item -> item.getPKeyId() + "").collect(Collectors.toList());
+    Map<String, List<TableFile>> tableFileOldMap = tableFileClient.getTabFilesByTabIds(tabFileIds).stream().collect(Collectors.groupingBy(TableFile::getTabId));
     if (tableFileOldMap != null && tableFileOldMap.size() > 0) {
         List<TableFile> resultFileData = new ArrayList<>();
         Set<Long> updatePKeyIds = new HashSet<>();
@@ -3038,7 +3033,7 @@ private void addCopyNodesAndTabsBuildData(List<WbsTreeContract> addNodeList, Lis
         List<String> initTabNames = needTabs.stream().map(WbsTreeContract::getInitTableName).distinct().filter(ObjectUtil::isNotEmpty).collect(Collectors.toList());
         String joined = StringUtils.join(initTabNames, ",");
         joined = "'" + joined.replaceAll(",", "','") + "'";
-        Map<String, QueryProcessDataVO> tabColsAllByTabNameMaps = jdbcTemplate.query("SELECT table_name as queryType, GROUP_CONCAT(COLUMN_name) as ancestors from information_schema.COLUMNS where table_name in (" + joined + ") GROUP BY table_name", new BeanPropertyRowMapper<>(QueryProcessDataVO.class)).stream().collect(Collectors.toMap(QueryProcessDataVO::getQueryType, Function.identity()));
+        Map<String, QueryProcessDataVO> tabColsAllByTabNameMaps = jdbcTemplate.query("SELECT table_name as queryType, GROUP_CONCAT(DISTINCT COLUMN_name) as ancestors from information_schema.COLUMNS where table_name in (" + joined + ") GROUP BY table_name", new BeanPropertyRowMapper<>(QueryProcessDataVO.class)).stream().collect(Collectors.toMap(QueryProcessDataVO::getQueryType, Function.identity()));
         for (WbsTreeContract node : needNodes) {
             Long oldId = node.getId();
             //新节点
@@ -3662,23 +3657,21 @@ public R removeContractTreeNodeJudge(@RequestParam String ids) {
                 String wbsIds = removeList.stream().map(Object::toString).collect(Collectors.joining(","));
                 /** 判断是否子节点有上报或审批过的资料,因为父id和祖级节点错误,直接使用上面的值去查询上报情况*/
                 List<String> unRemoveIds = jdbcTemplate.queryForList("SELECT wbs_id from u_information_query WHERE wbs_id in (" + wbsIds + ") and is_deleted = 0 and status in (1,2) GROUP BY wbs_id HAVING count(1) > 0", String.class);
-                if (!unRemoveIds.isEmpty()) {
-                    // 剔除此节点
-                    Map<String, String> map = unRemoveIds.stream().collect(Collectors.toMap(id -> id, Function.identity()));
-                    removeNodeList.removeIf(node -> {
-                        //删除掉表格 TODO(不清楚为什么要剔除表格,按理说删除节点后,节点下的表也应该一起删除的,猜测或许是为了方便恢复节点的时候表数据还存在)2023年9月19日
-                        boolean removeIf = node.getType() != null && new Integer("2").equals(node.getType());
-                        boolean equals = map.containsKey(node.getPKeyId().toString());
-                        if (equals) {
-                            unremoveNodeMap.put(node.getPKeyId(), node);
-                        }
-                        return removeIf || equals;
-                    });
-                    Map<Long, WbsTreeContract> contractMap = removeNodeList.stream().collect(Collectors.toMap(WbsTreeContract::getId, Function.identity()));
-                    Map<Long, WbsTreeContract> tempMap = new HashMap<>();
-                    unremoveNodeMap.forEach((key, value) -> collectNodeAndAncestors(value, contractMap, tempMap));
-                    unremoveNodeMap.putAll(tempMap);
-                }
+                // 剔除此节点
+                Map<String, String> map = unRemoveIds.stream().collect(Collectors.toMap(id -> id, Function.identity()));
+                removeNodeList.removeIf(node -> {
+                    //删除掉表格 TODO(不清楚为什么要剔除表格,按理说删除节点后,节点下的表也应该一起删除的,猜测或许是为了方便恢复节点的时候表数据还存在)2023年9月19日
+                    boolean removeIf = node.getType() != null && new Integer("2").equals(node.getType());
+                    boolean equals = map.containsKey(node.getPKeyId().toString());
+                    if (equals) {
+                        unremoveNodeMap.put(node.getPKeyId(), node);
+                    }
+                    return removeIf || equals;
+                });
+                Map<Long, WbsTreeContract> contractMap = removeNodeList.stream().collect(Collectors.toMap(WbsTreeContract::getId, Function.identity()));
+                Map<Long, WbsTreeContract> tempMap = new HashMap<>();
+                unremoveNodeMap.forEach((key, value) -> collectNodeAndAncestors(value, contractMap, tempMap));
+                unremoveNodeMap.putAll(tempMap);
             }
             if(removeNodeList.isEmpty()) {
                 return R.fail("删除失败,该节点下有已填报的资料");
@@ -3705,6 +3698,7 @@ public R removeContractTreeNodeJudge(@RequestParam String ids) {
             this.recycleBinService.save(new RecycleBin(String.join(",", idArray), "工程划分批量删除", 2, positionStr, projectId, contractId));
             //改为物理删除 (8.28改为逻辑删除,方便恢复)
             this.wbsTreeContractClient.removeContractTreeNode(idArray);
+            this.recycleBinInfoService.saveRecycleBinInfoByWbsTreeContract(String.join(",", idArray),ids);
             //更新redis
             this.informationQueryService.delAsyncWbsTree(removeWbsTreeContracts.get(0).getContractId());
             this.wbsTreeContractStatisticsClient.delWbsTreeContractNodes(String.join(",", idArray));
@@ -4210,7 +4204,7 @@ public R<Boolean> saveContractTreeNode(@RequestBody AddContractTreeNodeVO vo) {
             }
         }
         //TODO 20250414-lhb-新增 添加ancestorsPId字段
-        attachNodesToTarget(saveList,treeContract.getPKeyId(),treeContract.getAncestorsPId());
+        attachNodesToTarget(saveList);
 
         R<Boolean> booleanR = this.saveOrCopyNodeTree(saveList, saveLedger, 2, treeContract);
 
@@ -5126,15 +5120,18 @@ public R<Object> customAddContractNode(@RequestBody CustomAddContractNodeDTO dto
         }
     }
 
-    public void attachNodesToTarget(List<WbsTreeContract> newNodes, Long targetId, String targetAncestors) {
+    public void attachNodesToTarget(List<WbsTreeContract> newNodes) {
         // 1. 找到新数据中的顶层节点(新树的根节点)
         List<WbsTreeContract> newRoot = findRootNode(newNodes);
 
         // 2. 将新树的根节点绑定到目标节点
         newRoot.forEach(f -> {
-            f.setPId(targetId);
-            f.setAncestorsPId(calculateAncestors(targetAncestors, targetId));
-
+            WbsTreeContract parentNode = this.wbsTreeContractClient.getContractNodeByPrimaryKeyId(String.valueOf(f.getPId()));
+            if(parentNode ==  null){
+                f.setAncestorsPId("0");
+            }else{
+                f.setAncestorsPId(calculateAncestors(parentNode.getAncestorsPId(), f.getPId()));
+            }
 
             // 3. 构建映射关系
             Map<Long, WbsTreeContract> nodeMap = new HashMap<>();

+ 11 - 4
blade-service/blade-business/src/main/java/org/springblade/business/controller/MaterialProgressController.java

@@ -524,22 +524,22 @@ public class MaterialProgressController extends BladeController {
         //工序资料
         long processAmount = 0L;
         if (process.size() > 0) {
-            processAmount = this.informationQueryService.count(Wrappers.<InformationQuery>lambdaQuery().in(InformationQuery::getWbsId, process).eq(InformationQuery::getClassify, classifyType));
+            processAmount = this.informationQueryService.count(Wrappers.<InformationQuery>query().select("distinct wbs_id").in("wbs_id", process).eq("classify", classifyType));
         }
         //开工报告
         long workStartReportsAmount = 0L;
         if (workStartReports.size() > 0) {
-            workStartReportsAmount = this.informationQueryService.count(Wrappers.<InformationQuery>lambdaQuery().in(InformationQuery::getWbsId, workStartReports).eq(InformationQuery::getClassify, classifyType));
+            workStartReportsAmount = this.informationQueryService.count(Wrappers.<InformationQuery>query().select("distinct wbs_id").in("wbs_id", workStartReports).eq("classify", classifyType));
         }
         //质量评定
         long evaluationAmount = 0L;
         if (evaluation.size() > 0) {
-            evaluationAmount = this.informationQueryService.count(Wrappers.<InformationQuery>lambdaQuery().in(InformationQuery::getWbsId, evaluation).eq(InformationQuery::getClassify, classifyType));
+            evaluationAmount = this.informationQueryService.count(Wrappers.<InformationQuery>query().select("distinct wbs_id").in("wbs_id", evaluation).eq("classify", classifyType));
         }
         //中间交工
         long completionAmount = 0L;
         if (completion.size() > 0) {
-            completionAmount = this.informationQueryService.count(Wrappers.<InformationQuery>lambdaQuery().in(InformationQuery::getWbsId, completion).eq(InformationQuery::getClassify, classifyType));
+            completionAmount = this.informationQueryService.count(Wrappers.<InformationQuery>query().select("distinct wbs_id").in("wbs_id", completion).eq("classify", classifyType));
         }
 
         reVO.setProcessMaterialList("开工报告", workStartReports.size(), workStartReportsAmount);
@@ -556,6 +556,13 @@ public class MaterialProgressController extends BladeController {
         AtomicInteger await = new AtomicInteger();
         //已审批
         AtomicInteger approval = new AtomicInteger();
+        if (list != null && !list.isEmpty()) {
+            Map<Long, InformationQuery> map = list.stream().collect(Collectors.toMap(InformationQuery::getWbsId, item -> item, (v1, v2) -> v1.getId() > v2.getId() ? v1 : v2));
+            list = new ArrayList<>(map.values());
+        }
+        if (list ==  null) {
+            list = new ArrayList<>();
+        }
         list.forEach(vo -> {
             switch (vo.getStatus()) {
                 case 1:

+ 2 - 2
blade-service/blade-business/src/main/java/org/springblade/business/controller/MessageWarningController.java

@@ -192,9 +192,9 @@ public class MessageWarningController extends BladeController {
             iPage.getRecords().forEach(reVO -> {
                 if (reVO.getType() != null && reVO.getType() == 3) {
                     if (reVO.getContent() != null && reVO.getContent().contains("驳回了")) {
-                        reVO.setTypeValue("驳回通知");
+                        reVO.setRepealType("驳回通知");
                     } else if (reVO.getContent() != null && reVO.getContent().contains("废除了")) {
-                        reVO.setTypeValue("废除通知");
+                        reVO.setRepealType("废除通知");
                     }
                     return;
                 }

+ 129 - 2
blade-service/blade-business/src/main/java/org/springblade/business/controller/RecycleBinController.java

@@ -3,6 +3,7 @@ package org.springblade.business.controller;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
@@ -10,25 +11,37 @@ import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
 import lombok.AllArgsConstructor;
 
 import org.apache.commons.lang.StringUtils;
+import org.springblade.business.dto.RecycleBinInfoDTO;
 import org.springblade.business.entity.ArchiveFile;
 import org.springblade.business.entity.ImageClassificationFile;
+import org.springblade.business.entity.RecycleBinInfo;
 import org.springblade.business.feign.InformationQueryClient;
 import org.springblade.business.feignClient.WbsTreeContractStatisticsClientImpl;
 import org.springblade.business.service.IArchiveFileService;
 import org.springblade.business.service.IImageClassificationFileService;
+import org.springblade.business.service.IRecycleBinInfoService;
+import org.springblade.business.vo.RecycleBinInfoVO;
 import org.springblade.business.vo.RecycleBinVO;
 import org.springblade.core.mp.support.Condition;
 import org.springblade.core.mp.support.Query;
+import org.springblade.core.redis.cache.BladeRedis;
 import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.DateUtil;
+import org.springblade.core.tool.utils.ObjectUtil;
+import org.springblade.core.tool.utils.StringUtil;
+import org.springblade.manager.entity.WbsTreeContract;
 import org.springblade.manager.feign.WbsTreeContractClient;
+import org.springblade.system.user.vo.UserVO2;
+import org.springframework.jdbc.core.BeanPropertyRowMapper;
+import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.web.bind.annotation.*;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import org.springblade.business.entity.RecycleBin;
 import org.springblade.business.service.IRecycleBinService;
 import org.springblade.core.boot.ctrl.BladeController;
 
+import javax.validation.Valid;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -55,6 +68,9 @@ public class RecycleBinController extends BladeController {
     private final InformationQueryClient informationQueryClient;
 
     private final WbsTreeContractStatisticsClientImpl wbsTreeContractStatisticsClient;
+    private final IRecycleBinInfoService recycleBinInfoService;
+    private final BladeRedis bladeRedis;
+    private final JdbcTemplate jdbcTemplate;
 
     /**
      * 恢复
@@ -66,7 +82,7 @@ public class RecycleBinController extends BladeController {
         if (vo.getRegainIds() != null && vo.getRegainIds().size() > 0) {
             //获取数据
             List<Long> longs = vo.getRegainIds().stream().map(i -> i.getId()).collect(Collectors.toList());
-            List<RecycleBin> recycleBinList = this.recycleBinService.list(Wrappers.<RecycleBin>lambdaQuery().in(RecycleBin::getId, longs));
+            List<RecycleBin> recycleBinList = this.recycleBinService.list(Wrappers.<RecycleBin>lambdaQuery().eq(RecycleBin::getStatus,1).in(RecycleBin::getId, longs));
             //恢复数据成功后删除回收站对应记录
             List<String> recycleBinIds = new ArrayList<>();
             //划分数据类型
@@ -74,10 +90,26 @@ public class RecycleBinController extends BladeController {
             List<RecycleBin> nodeTypeList = recycleBinList.stream().filter(recycleBin -> new Integer("2").equals(recycleBin.getDelType())).distinct().collect(Collectors.toList());
             boolean regainNode = false, regainFile = false;
             if (nodeTypeList.size() > 0) {
+                List<RecycleBin> errorList = new ArrayList<>();
+                //筛选出项目级存在的节点
+                for (RecycleBin recycleBin : nodeTypeList) {
+                    //当前是否有节点在项目级被删除了  如果是标记当前节点不可用
+                    Integer count = this.wbsTreeContractClient.findIsExistTreeNode(Arrays.asList(recycleBin.getBusinessId().split(",")));
+                    if (count > 0){
+                        recycleBin.setStatus(2);
+                        errorList.add(recycleBin);
+                    }
+                }
+                if(CollectionUtils.isNotEmpty(errorList)){
+                    recycleBinService.updateBatchById(errorList);
+                    nodeTypeList.removeAll(errorList);
+                }
+
                 //恢复集合
                 List<String> processNodeList = new ArrayList<>();
                 this.foreachQueryData(nodeTypeList, recycleBinIds, processNodeList);
                 try {
+
                     //恢复数据
                     if (processNodeList.size() > 0) {
                         regainNode = this.wbsTreeContractClient.regainRemoveTreeByPrimaryKeyIds(processNodeList);
@@ -127,7 +159,7 @@ public class RecycleBinController extends BladeController {
 
     private void foreachQueryData(List<RecycleBin> recycleList, List<String> recycleBinIds, List<String> result) {
         for (RecycleBin recycleBin : recycleList) {
-            if (StringUtils.isNotEmpty(recycleBin.getBusinessId())) {
+            if (StringUtils.isNotEmpty(recycleBin.getBusinessId()) && recycleBin.getStatus() == 1) {
                 if (recycleBin.getBusinessId().contains(",")) {
                     result.addAll(new ArrayList<>(Arrays.asList(recycleBin.getBusinessId().split(","))));
                 } else {
@@ -168,4 +200,99 @@ public class RecycleBinController extends BladeController {
         return R.data(this.recycleBinService.page(Condition.getPage(query), wrapper));
     }
 
+    @GetMapping("/page")
+    @ApiOperationSupport(order = 1)
+    @ApiOperation(value = "分页")
+    public R<IPage<RecycleBinInfo>> page(@Valid RecycleBinInfoVO vo) {
+        return R.data(this.recycleBinInfoService.selectPage(vo));
+    }
+
+    /**
+     * 恢复
+     */
+    @PostMapping("/recover")
+    @ApiOperationSupport(order = 2)
+    @ApiOperation(value = "恢复(工程划分)")
+    public R<Boolean> recover(@RequestBody RecycleBinInfoDTO dto) {
+        if (StringUtil.hasText(dto.getIds())) {
+            //获取数据
+            String[] ids = dto.getIds().split(",");
+            List<Long> collect = Arrays.stream(ids).filter(StringUtils::isNumeric).map(Long::parseLong).collect(Collectors.toList());
+            if (collect.isEmpty()) {
+                return R.data(true);
+            }
+            List<RecycleBinInfo> recycleBinInfoList = this.recycleBinInfoService.list(Wrappers.<RecycleBinInfo>lambdaQuery().in(RecycleBinInfo::getId, collect).eq(RecycleBinInfo::getStatus, 0).eq(RecycleBinInfo::getDelType, 2));
+            if (dto.getRecoverOperationData() == 1) {
+                Set<Long> set = recycleBinInfoList.stream().map(RecycleBinInfo::getDelRootId).collect(Collectors.toSet());
+                recycleBinInfoList = this.recycleBinInfoService.list(Wrappers.<RecycleBinInfo>lambdaQuery().in(RecycleBinInfo::getDelRootId, set)
+                                .eq(RecycleBinInfo::getDelType, 2).eq(RecycleBinInfo::getStatus, 0));
+            }
+            boolean regainNode = false;
+            if (!recycleBinInfoList.isEmpty()) {
+                List<String> processNodeList = new ArrayList<>();
+                try {
+                    //恢复数据
+                    Set<Long> parentIds = new HashSet<>();
+                    for (RecycleBinInfo info : recycleBinInfoList) {
+                        String position = info.getBusinessId();
+                        if (position ==  null) {
+                            continue;
+                        }
+                        String[] split = position.split(",");
+                        for (String s : split) {
+                            if (StringUtil.isNumeric(s) && !s.equals("0")) {
+                                parentIds.add(Long.parseLong(s));
+                            }
+                        }
+                    }
+                    if (!parentIds.isEmpty()) {
+                        List<RecycleBinInfo> list = this.recycleBinInfoService.list(Wrappers.<RecycleBinInfo>lambdaQuery().in(RecycleBinInfo::getDelId, parentIds).eq(RecycleBinInfo::getDelType, 2).eq(RecycleBinInfo::getStatus, 0));
+                        recycleBinInfoList.addAll(list);
+                    }
+                    processNodeList = recycleBinInfoList.stream().map(item -> item.getDelId() + "").collect(Collectors.toList());
+                    regainNode = this.wbsTreeContractClient.regainRemoveTreeByPrimaryKeyIds(processNodeList);
+                    List<WbsTreeContract> query = jdbcTemplate.query("SELECT p_key_id  FROM m_wbs_tree_contract a WHERE  ( SELECT count(1) FROM m_wbs_tree_contract WHERE contract_id = a.contract_id and type = 1 AND p_id = a.p_id AND full_name = a.full_name AND p_key_id != a.p_key_id AND is_deleted = 0 ) > 0 " +
+                            "AND is_deleted = 0 and a.p_key_id in ( " + String.join(",", processNodeList) + ")", new BeanPropertyRowMapper<>(WbsTreeContract.class));
+                    if (!query.isEmpty()) {
+                        String collect1 = query.stream().map(item -> item.getPKeyId() + "").collect(Collectors.joining(","));
+                        jdbcTemplate.execute("update m_wbs_tree_contract set full_name = CONCAT( full_name, '(恢)' ) where p_key_id in (" + collect1 + ")");
+                    }
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+                informationQueryClient.delAsyncWbsTree(recycleBinInfoList.get(0).getContractId() + "");
+                wbsTreeContractStatisticsClient.recycleWbsTreeContractNodes(String.join(",", processNodeList));
+            }
+            //删除回收站记录
+            if (!recycleBinInfoList.isEmpty() && regainNode) {
+                List<Long> recycleBinIds = recycleBinInfoList.stream().map(RecycleBinInfo::getId).collect(Collectors.toList());
+                this.recycleBinInfoService.update(Wrappers.<RecycleBinInfo>lambdaUpdate().set(RecycleBinInfo::getStatus, 1).set(RecycleBinInfo::getUpdateTime, new Date())
+                        .set(RecycleBinInfo::getUpdateUser, AuthUtil.getUserId()).set(RecycleBinInfo::getUpdateUserName, AuthUtil.getNickName()).in(RecycleBinInfo::getId, recycleBinIds));
+                Set<Long> set = recycleBinInfoList.stream().map(RecycleBinInfo::getContractId).collect(Collectors.toSet());
+                for (Long l : set) {
+                    bladeRedis.del("blade:recycle:user:cache:" + l, "blade:recycle:user:cache:" + l + "_1");
+                }
+                return R.data(true);
+            } else {
+                return R.data(300, false, "数据恢复失败,请联系维护人员处理");
+            }
+        }
+        return R.data(300, false, "未找到需要需要恢复的数据");
+    }
+
+    @GetMapping("/queryUser")
+    @ApiOperationSupport(order = 1)
+    @ApiOperation(value = "查询用户")
+    public R<Collection<UserVO2>> queryUser(@RequestParam Long contractId, @RequestParam(required = false, defaultValue = "0") Integer isRecycleBin, @RequestParam(required = false) String name) {
+        return R.data(this.recycleBinInfoService.queryUser(contractId,isRecycleBin, name));
+    }
+
+
+    @GetMapping("/queryOperation")
+    @ApiOperationSupport(order = 1)
+    @ApiOperation(value = "查询同一批删除数据")
+    public R<Collection<RecycleBinInfo>> queryOperation(@RequestParam String ids) {
+        return R.data(this.recycleBinInfoService.queryOperation(ids));
+    }
+
 }

+ 2 - 2
blade-service/blade-business/src/main/java/org/springblade/business/controller/StandardInfoController.java

@@ -47,8 +47,8 @@ public class StandardInfoController {
      */
     @GetMapping("page")
     @ApiOperation(value = "分页查询所有数据", notes = "传入分页对象和高级查询对象")
-    public R<IPage<StandardInfoDTO>> selectAll(Query query, StandardInfo standardInfo) {
-        IPage<StandardInfoDTO> page = this.uStandardInfoService.selectMyPage(query, standardInfo);
+    public R<IPage<StandardInfoDtoVo>> selectAll(Query query, StandardInfo standardInfo) {
+        IPage<StandardInfoDtoVo> page = this.uStandardInfoService.selectMyPage(query, standardInfo);
         return R.data(page);
     }
 

+ 12 - 0
blade-service/blade-business/src/main/java/org/springblade/business/controller/TaskController.java

@@ -2062,6 +2062,18 @@ public class TaskController extends BladeController {
         return taskService.reSigningEVisaStatus0(dtos,header);
     }
 
+    @GetMapping("/checkAndRepairPDFisNull")
+    @ApiOperation(value = "检查PDF是否为空")
+    @ApiOperationSupport(order = 3)
+    public void checkAndRepairPDFisNull(HttpServletRequest request) throws Exception {
+        String header = request.getHeader("Blade-Auth");
+        Long projectId=1904814720589430785L;
+        String sql="select id,wbs_id,project_id,contract_id from u_information_query where project_id="+projectId+" and pdf_url is null and node_pdf_url is null  and status in(0,1,2) and is_deleted=0";
+        List<reSigningEVisaStatus> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(reSigningEVisaStatus.class));
+        taskService.reSigningEVisaStatus0(query,header);
+        System.out.println("完成");
+    }
+
     @PostMapping("/reSigningEntrust")
     @ApiOperationSupport(order = 3)
     @ApiOperation(value = "委托单管理-一键重签", notes = "传入taskIds、下拉框的contractId、projectId")

+ 100 - 0
blade-service/blade-business/src/main/java/org/springblade/business/controller/TrialCyController.java

@@ -0,0 +1,100 @@
+package org.springblade.business.controller;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springblade.business.entity.TrialContainerClassification;
+import org.springblade.business.entity.TrialCyFinishTestReport;
+import org.springblade.business.entity.TrialCyTestType;
+import org.springblade.business.entity.TrialCyThirdReport;
+import org.springblade.business.service.TrialCyService;
+import org.springblade.business.service.TrialCyTestTypeService;
+import org.springblade.business.vo.ThirdReportVo;
+import org.springblade.business.vo.TrialCyThirdReportQueryVo;
+import org.springblade.core.tool.api.R;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+/**
+ * 成渝试验数据接口
+ * @author LHB
+ */
+@RestController
+@AllArgsConstructor
+@RequestMapping("/cyTrial")
+@Api(value = "成渝试验数据接口", tags = "成渝试验数据接口")
+public class TrialCyController {
+
+    private TrialCyService trialCyService;
+
+
+    /**
+     * 根据合同段id验证当前合同段是否未成渝项目下未开启试验功能的合同段
+     * @return
+     */
+    @GetMapping("/isCyAndTestModule")
+    @ApiOperationSupport(order = 1)
+    @ApiOperation(value = "验证是否使用成渝那边的树", notes = "传入合同段id")
+    public R<Boolean> isCyAndTestModule(Long projectId,Long contractId){
+        return R.data(trialCyService.isCyAndTestModule(projectId, contractId));
+    }
+
+    /**
+     * 获取成渝那边的树
+     * @return
+     */
+    @GetMapping("/getTree")
+    @ApiOperationSupport(order = 1)
+    @ApiOperation(value = "获取成渝那边的树", notes = "传入项目id")
+    public R<List<TrialCyTestType>> getTree(Long projectId, String parentId){
+        return R.data(trialCyService.getTree(projectId,parentId));
+    }
+
+    /**
+     * 获取试验检测报告
+     * @return
+     */
+    @GetMapping("/getTrialDetectionReport")
+    @ApiOperationSupport(order = 1)
+    @ApiOperation(value = "获取试验检测报告", notes = "")
+    public R<Page<ThirdReportVo>> getTrialDetectionReport(@Validated TrialCyThirdReportQueryVo queryVo){
+        return R.data(trialCyService.getTrialDetectionReport(queryVo));
+    }
+
+
+    /**
+     * 获取第三方/外委 检测报告
+     * @return
+     */
+    @GetMapping("/getThirdReport")
+    @ApiOperationSupport(order = 1)
+    @ApiOperation(value = "获取第三方/外委 检测报告", notes = "")
+    public R<Page<ThirdReportVo>> getThirdReport(@Validated TrialCyThirdReportQueryVo queryVo){
+        return R.data(trialCyService.getThirdReport(queryVo));
+    }
+
+
+    /**
+     * 清除成渝试验关联
+     * @return
+     */
+    @GetMapping("/clearTrialAssociation")
+    @ApiOperation(value = "清除成渝试验关联", notes = "")
+    @ApiImplicitParams(value = {
+            @ApiImplicitParam(name = "nodeId", value = "节点", required = true),
+            @ApiImplicitParam(name = "recordId", value = "pkeyId", required = true)
+    })
+    public R<Boolean> clearTrialAssociation(Long nodeId, Long recordId){
+        return R.data(trialCyService.clearTrialAssociation(nodeId,recordId));
+    }
+
+}

+ 2 - 0
blade-service/blade-business/src/main/java/org/springblade/business/controller/TrialDetectionController.java

@@ -179,6 +179,8 @@ public class TrialDetectionController extends BladeController {
         jdbcTemplate.execute(sql5);
         String sql6 = "delete from u_information_query where wbs_id in(" + ids + ") and type = 2";
         jdbcTemplate.execute(sql6);
+        String sql7="update u_trial_auto_number set is_deleted=0 where form_data_id in ("+ids+")";
+        jdbcTemplate.execute(sql7);
         return R.status(true);
     }
 

+ 2 - 0
blade-service/blade-business/src/main/java/org/springblade/business/controller/TrialMaterialController.java

@@ -153,8 +153,10 @@ public class TrialMaterialController extends BladeController {
         if(b){
             //删除关联表中的额数据
             String sqlForDelTrailSampleRecord = "delete from u_trial_sampling_record where sample_info_id in ("+ids+")";
+            String update="update u_trial_auto_number set is_deleted=1 where form_data_id in ("+ids+")";
             try {
                 jdbcTemplate.execute(sqlForDelTrailSampleRecord);
+                jdbcTemplate.update(update);
             } catch (DataAccessException e) {
                 log.error("删除关联表中的额数据失败", e);
                 throw new RuntimeException(e);

+ 118 - 0
blade-service/blade-business/src/main/java/org/springblade/business/feignClient/TrialCyAccessoriesClientImpl.java

@@ -0,0 +1,118 @@
+package org.springblade.business.feignClient;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import lombok.AllArgsConstructor;
+import org.springblade.business.entity.TrialCyFinishTestReport;
+import org.springblade.business.entity.TrialCyThirdReport;
+import org.springblade.business.feign.TrialCyAccessoriesClient;
+import org.springblade.business.mapper.TrialSelfInspectionRecordMapper;
+import org.springblade.business.service.TrialCyFinishTestReportService;
+import org.springblade.business.service.TrialCyThirdReportService;
+import org.springblade.core.tool.utils.CollectionUtil;
+import org.springblade.manager.entity.TableFile;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author LHB
+ */
+@RestController
+@AllArgsConstructor
+public class TrialCyAccessoriesClientImpl implements TrialCyAccessoriesClient {
+
+    private final TrialSelfInspectionRecordMapper trialSelfInspectionRecordMapper;
+
+    /**
+     * 第三方、外委
+     */
+    private final TrialCyThirdReportService trialCyThirdReportService;
+
+    /**
+     * 试验报告
+     */
+    private final TrialCyFinishTestReportService trialCyFinishTestReportService;
+
+    @Override
+    public List<JSONObject> getTrialFilePdfRecord(String primaryKeyId, List<Integer> list) {
+        //获取id
+        List<Map<String, Object>> trialFilePdfRecord = trialSelfInspectionRecordMapper.getTrialFilePdfRecord(primaryKeyId, list);
+
+        if (CollectionUtil.isNotEmpty(trialFilePdfRecord)) {
+
+            //试验报告ids
+            List<Long> listOne = new ArrayList<>();
+            //第三方外委ids
+            List<Long> listTwo = new ArrayList<>();
+
+            for (Map<String, Object> stringObjectMap : trialFilePdfRecord) {
+
+                Integer type = (Integer) stringObjectMap.get("type");
+                Long recordId = (Long) stringObjectMap.get("record_id");
+                //试验报告
+                if (type == 11) {
+                    listOne.add(recordId);
+                } else {
+                    //第三方、外委
+                    listTwo.add(recordId);
+                }
+            }
+
+            List<JSONObject> result = new ArrayList<>();
+
+            if (CollectionUtil.isNotEmpty(listOne)) {
+                List<TrialCyFinishTestReport> list1 = trialCyFinishTestReportService.list(Wrappers.<TrialCyFinishTestReport>lambdaQuery()
+                        .isNotNull(TrialCyFinishTestReport::getAssembleFile)
+                        .in(TrialCyFinishTestReport::getTaskId, listOne)
+                );
+
+                if (CollectionUtil.isNotEmpty(list1)) {
+                    list1.forEach(f -> {
+                        String[] split = f.getAssembleFile().split("/");
+                        JSONObject jsonObject = new JSONObject();
+                        jsonObject.put("id", f.getTaskId());
+                        jsonObject.put("name", split[split.length - 1]);
+                        jsonObject.put("contractId", f.getContractId());
+                        jsonObject.put("domainUrl", f.getAssembleFile());
+                        jsonObject.put("domainPdfUrl", f.getAssembleFile());
+                        jsonObject.put("tabId", primaryKeyId);
+                        jsonObject.put("extension", "pdf");
+                        //是否为试验关联的附件
+                        jsonObject.put("isTrial", true);
+                        result.add(jsonObject);
+                    });
+                }
+            }
+            if (CollectionUtil.isNotEmpty(listTwo)) {
+                List<TrialCyThirdReport> list1 = trialCyThirdReportService.list(Wrappers.<TrialCyThirdReport>lambdaQuery()
+                        .isNotNull(TrialCyThirdReport::getAssembleFile)
+                        .in(TrialCyThirdReport::getId, listTwo)
+                );
+
+                if (CollectionUtil.isNotEmpty(list1)) {
+                    list1.forEach(f -> {
+                        String[] split = f.getAssembleFile().split("/");
+                        JSONObject jsonObject = new JSONObject();
+                        jsonObject.put("id", f.getId());
+                        jsonObject.put("name", split[split.length - 1]);
+                        jsonObject.put("contractId", f.getContractId());
+                        jsonObject.put("domainUrl", f.getAssembleFile());
+                        jsonObject.put("domainPdfUrl", f.getAssembleFile());
+                        jsonObject.put("tabId", primaryKeyId);
+                        jsonObject.put("extension", "pdf");
+                        //是否为试验关联的附件
+                        jsonObject.put("isTrial", true);
+                        result.add(jsonObject);
+                    });
+                }
+            }
+            return result;
+        }
+
+        return null;
+    }
+}

+ 3 - 0
blade-service/blade-business/src/main/java/org/springblade/business/mapper/EntrustInfoMapper.xml

@@ -71,6 +71,9 @@
         <if test="param2.entrustName != null and param2.entrustName != ''">
             AND ( a.entrust_name like CONCAT(CONCAT('%', #{param2.entrustName}), '%') or a.entrust_no like CONCAT(CONCAT('%', #{param2.entrustName}), '%') or b.material_name like CONCAT(CONCAT('%', #{param2.entrustName}), '%'))
         </if>
+        <if test="param2.entrustNo != null and param2.entrustNo != ''">
+            AND a.entrust_no like CONCAT(CONCAT('%', #{param2.entrustNo}), '%')
+        </if>
     </select>
 
     <select id="getReportDetail" resultType="org.springblade.business.vo.EntrustDataInfoVO">

+ 1 - 1
blade-service/blade-business/src/main/java/org/springblade/business/mapper/InformationQueryMapper.xml

@@ -923,7 +923,7 @@
 
     <!--获取当前节点下,所有表单的字段数据-->
     <select id="getNodeChildTabColsAllByTabName" resultMap="queryProcessDataMap">
-        SELECT table_name as queryType, GROUP_CONCAT(COLUMN_name) as ancestors
+        SELECT table_name as queryType, GROUP_CONCAT(distinct COLUMN_name) as ancestors
         from information_schema.COLUMNS
         where table_name
                   in (#{tabName})

+ 17 - 0
blade-service/blade-business/src/main/java/org/springblade/business/mapper/RecycleBinInfoMapper.java

@@ -0,0 +1,17 @@
+package org.springblade.business.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.apache.ibatis.annotations.Param;
+import org.springblade.business.entity.RecycleBinInfo;
+import org.springblade.business.vo.RecycleBinInfoVO;
+
+import java.util.Collection;
+
+public interface RecycleBinInfoMapper extends BaseMapper<RecycleBinInfo> {
+
+
+    IPage<RecycleBinInfo> page(IPage<RecycleBinInfo> iPage, @Param("vo") RecycleBinInfoVO recycleBinInfoVO);
+
+    Collection<RecycleBinInfo> queryOperation(Collection<Long> ids);
+}

+ 95 - 0
blade-service/blade-business/src/main/java/org/springblade/business/mapper/RecycleBinInfoMapper.xml

@@ -0,0 +1,95 @@
+<?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="org.springblade.business.mapper.RecycleBinInfoMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="recycleBinResultMap" type="org.springblade.business.entity.RecycleBinInfo">
+        <result column="id" property="id"/>
+        <result column="create_user" property="createUser"/>
+        <result column="create_dept" property="createDept"/>
+        <result column="create_time" property="createTime"/>
+        <result column="update_user" property="updateUser"/>
+        <result column="update_time" property="updateTime"/>
+        <result column="status" property="status"/>
+        <result column="is_deleted" property="isDeleted"/>
+        <result column="project_id" property="projectId"/>
+        <result column="contract_id" property="contractId"/>
+        <result column="del_type" property="delType"/>
+        <result column="file_name" property="fileName"/>
+        <result column="position" property="position"/>
+        <result column="business_id" property="businessId"/>
+        <result column="operation_time" property="operationTime"/>
+        <result column="create_user_name" property="createUserName"/>
+        <result column="update_user_name" property="updateUserName"/>
+        <result column="del_id" property="delId"/>
+        <result column="del_root_id" property="delRootId"/>
+        <result column="del_root_name" property="delRootName"/>
+        <result column="operation_id" property="operationId"/>
+        <result column="jl_file_name" property="jlFileName"/>
+        <result column="is_data" property="isData"/>
+    </resultMap>
+
+    <sql id="includeSql" >
+        id, create_user, create_dept, create_time, update_user, update_time, status, is_deleted, project_id, contract_id, del_type, file_name, position, business_id, operation_time, create_user_name, update_user_name, del_id, del_root_id, del_root_name, operation_id, jl_file_name, is_data
+    </sql>
+    <select id="page" resultMap="recycleBinResultMap">
+        select
+        <include refid="includeSql"/>
+        from u_recycle_bin_info
+        where is_deleted = 0
+        <if test="vo.contractId != null">
+            and contract_id = #{vo.contractId}
+        </if>
+        <if test="vo.delType != null">
+            and del_type = #{vo.delType}
+        </if>
+        <if test="vo.isData != null">
+            and is_data = #{vo.isData}
+        </if>
+        <if test="vo.recycleType != null">
+            and status = #{vo.recycleType}
+            <if test="vo.recycleType == 1">
+                <if test="vo.startTime != null">
+                    and create_time >= #{vo.startTime}
+                </if>
+                <if test="vo.endTime != null">
+                    and create_time &lt;= #{vo.endTime}
+                </if>
+                <if test="vo.userId != null">
+                    and create_user = #{vo.userId}
+                </if>
+            </if>
+            <if test="vo.recycleType == 0">
+                <if test="vo.startTime != null">
+                    and update_time >= #{vo.startTime}
+                </if>
+                <if test="vo.endTime != null">
+                    and update_time &lt;= #{vo.endTime}
+                </if>
+                <if test="vo.userId != null">
+                    and update_user = #{vo.userId}
+                </if>
+            </if>
+        </if>
+        <if test="vo.content != null and vo.content != ''">
+            and (file_name like concat('%',#{vo.content},'%') or jl_file_name like concat('%',#{vo.content},'%') or del_root_name like concat('%',#{vo.content},'%') or position like concat('%',#{vo.content},'%'))
+        </if>
+        <if test="vo.operationId != null">
+            and operation_id = #{vo.operationId}
+        </if>
+        order by
+        <if test="vo.recycleType == 1">
+            create_time desc
+        </if>
+        <if test="vo.recycleType == 0">
+            update_time desc
+        </if>
+    </select>
+    <select id="queryOperation" resultType="org.springblade.business.entity.RecycleBinInfo">
+        select del_root_id,del_root_name from u_recycle_bin_info where del_root_id in ( select del_root_id from u_recycle_bin_info where id in (
+            <foreach collection="ids" item="id" separator=",">
+                #{id}
+            </foreach>
+            ) and is_deleted = 0 group by del_root_id ) and status = 0  group by del_root_id, del_root_name having count(1) > 1
+    </select>
+</mapper>

+ 1 - 1
blade-service/blade-business/src/main/java/org/springblade/business/mapper/StandardInfoMapper.java

@@ -20,7 +20,7 @@ import java.util.List;
  */
 public interface StandardInfoMapper extends BaseMapper<StandardInfo> {
 
-    IPage<StandardInfoDTO> selectMyPage(Page<StandardInfoDTO> page, @Param("query") StandardInfo standardInfo);
+    IPage<StandardInfoDtoVo> selectMyPage(Page<StandardInfoDtoVo> page, @Param("query") StandardInfo standardInfo);
 
     StandardInfoDTO selectMyOne(@Param("id") Long id);
 

+ 5 - 4
blade-service/blade-business/src/main/java/org/springblade/business/mapper/StandardInfoMapper.xml

@@ -16,7 +16,7 @@
         <result property="updateTime" column="update_time"/>
         <result property="updateUser" column="update_user"/>
     </resultMap>
-    <resultMap id="BaseResultPageMap" type="org.springblade.business.dto.StandardInfoDTO">
+    <resultMap id="BaseResultPageMap" type="org.springblade.business.vo.StandardInfoDtoVo">
         <id property="id" column="id"/>
         <result property="name" column="name"/>
         <result property="symbol" column="symbol"/>
@@ -28,6 +28,7 @@
         <result property="createUser" column="create_user"/>
         <result property="updateTime" column="update_time"/>
         <result property="updateUser" column="update_user"/>
+        <result property="symbolName" column="symbolName"/>
         <collection property="info" ofType="org.springblade.business.entity.StandardInfo" select="findByParentId" column="{parentId=id}">
         </collection>
     </resultMap>
@@ -39,7 +40,7 @@
     </sql>
     <select id="selectMyPage" resultMap="BaseResultPageMap">
         SELECT
-            <include refid="Base_Column_List"/>
+            <include refid="Base_Column_List"/>,concat(symbol,name) symbolName
         FROM
             u_standard_info
         <where>
@@ -62,7 +63,7 @@
     </select>
     <select id="selectMyOne" resultMap="BaseResultPageMap">
         SELECT
-            <include refid="Base_Column_List"/>
+            <include refid="Base_Column_List"/>,concat(symbol,name) symbolName
         FROM
             u_standard_info
         WHERE
@@ -201,7 +202,7 @@
     </select>
     <select id="findRightByJoinLeftId" resultType="org.springblade.business.entity.StandardInfo">
         SELECT
-            <include refid="Base_Column_Join_List"/>
+            <include refid="Base_Column_Join_List"/>, c.name parentName
         FROM
             u_standard_info a
             INNER JOIN u_standard_info_join b ON a.id = b.standard_info_right_id AND a.is_deleted = b.is_deleted

+ 21 - 0
blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialCyAccessoriesMapper.java

@@ -0,0 +1,21 @@
+package org.springblade.business.mapper;
+
+import org.apache.ibatis.annotations.Param;
+import org.springblade.business.entity.TrialCyAccessories;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+* @author LHB
+* @description 针对表【u_trial_cy_accessories(成渝-附件信息)】的数据库操作Mapper
+* @createDate 2025-08-04 14:39:16
+* @Entity generator.domain.UTrialCyAccessories
+*/
+public interface TrialCyAccessoriesMapper extends BaseMapper<TrialCyAccessories> {
+
+    Boolean clearTrialAssociation(@Param("nodeId") Long nodeId,
+                                  @Param("recordId") Long recordId);
+}
+
+
+
+

+ 22 - 0
blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialCyAccessoriesMapper.xml

@@ -0,0 +1,22 @@
+<?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="org.springblade.business.mapper.TrialCyAccessoriesMapper">
+
+    <resultMap id="BaseResultMap" type="org.springblade.business.entity.TrialCyAccessories">
+            <id property="id" column="id" />
+            <result property="reportId" column="report_id" />
+            <result property="accId" column="acc_id" />
+            <result property="accType" column="acc_type" />
+            <result property="fileName" column="file_name" />
+            <result property="filePath" column="file_path" />
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        id,report_id,acc_id,acc_type,file_name,file_path
+    </sql>
+    <delete id="clearTrialAssociation">
+        delete from u_trial_file_pdf_record where node_id = #{nodeId} and record_id=#{recordId}
+    </delete>
+</mapper>

+ 23 - 0
blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialCyFinishTestReportMapper.java

@@ -0,0 +1,23 @@
+package org.springblade.business.mapper;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import org.apache.ibatis.annotations.Param;
+import org.springblade.business.entity.TrialCyFinishTestReport;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.springblade.business.vo.ThirdReportVo;
+import org.springblade.business.vo.TrialCyThirdReportQueryVo;
+
+/**
+* @author LHB
+* @description 针对表【u_trial_cy_finish_test_report(成渝-获取标段已完成(已签章完成)的检测报告)】的数据库操作Mapper
+* @createDate 2025-08-01 09:05:03
+* @Entity generator.domain.UTrialCyFinishTestReport
+*/
+public interface TrialCyFinishTestReportMapper extends BaseMapper<TrialCyFinishTestReport> {
+
+    Page<ThirdReportVo> myPage(Page<ThirdReportVo> page, @Param("query") TrialCyThirdReportQueryVo queryVo);
+}
+
+
+
+

+ 35 - 0
blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialCyFinishTestReportMapper.xml

@@ -0,0 +1,35 @@
+<?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="org.springblade.business.mapper.TrialCyFinishTestReportMapper">
+    <select id="myPage" resultType="org.springblade.business.vo.ThirdReportVo">
+        select
+            task_id id,
+            contract_id contractId,
+            report_number reportNo,
+            report_date reportDate,
+            position projectPositionName,
+            case
+                when experiment_result = 1 then '合格'
+                else '不合格'
+            end detectionResultName,
+        (select count(0) > 0 from u_trial_file_pdf_record where node_id = #{query.qualityTestPKeyId}  and type = 11 and record_id = t.id) isSelectedStatus
+        from u_trial_cy_finish_test_report t
+        <where>
+            <if test="query.contractId != null">
+                AND contract_id = #{query.contractId}
+            </if>
+            <if test="query.nodeId != null">
+                AND exam_name_info_id = #{query.nodeId}
+            </if>
+            <if test="query.startTime != null">
+                AND report_date >= #{query.startTime}
+            </if>
+            <if test="query.endTime != null">
+                AND report_date &lt;= #{query.endTime}
+            </if>
+
+        </where>
+    </select>
+</mapper>

+ 23 - 0
blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialCyTestTypeMapper.java

@@ -0,0 +1,23 @@
+package org.springblade.business.mapper;
+
+import org.apache.ibatis.annotations.Param;
+import org.springblade.business.entity.TrialCyTestType;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+import java.util.List;
+
+/**
+* @author LHB
+* @description 针对表【u_trial_cy_test_type(成渝-试验检测树)】的数据库操作Mapper
+* @createDate 2025-08-01 09:05:07
+* @Entity generator.domain.UTrialCyTestType
+*/
+public interface TrialCyTestTypeMapper extends BaseMapper<TrialCyTestType> {
+
+    List<TrialCyTestType> getTree(@Param("projectId") Long projectId,
+                                  @Param("parentId") String parentId);
+}
+
+
+
+

+ 24 - 0
blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialCyTestTypeMapper.xml

@@ -0,0 +1,24 @@
+<?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="org.springblade.business.mapper.TrialCyTestTypeMapper">
+    <sql id="Base_sql">
+        p_key_id,
+        project_id,
+        id,
+        father_id,
+        name,
+        order_index,
+        create_time
+    </sql>
+    <select id="getTree" resultType="org.springblade.business.entity.TrialCyTestType">
+        select
+            <include refid="Base_sql"/>,
+            (select count(1) > 0 from u_trial_cy_test_type where father_id = t.id) has_children
+        from u_trial_cy_test_type t
+        where project_id = #{projectId}
+          and father_id = #{parentId}
+        order by order_index
+    </select>
+</mapper>

+ 24 - 0
blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialCyThirdReportMapper.java

@@ -0,0 +1,24 @@
+package org.springblade.business.mapper;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import org.apache.ibatis.annotations.Param;
+import org.springblade.business.entity.TrialCyThirdReport;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.springblade.business.vo.ThirdReportVo;
+import org.springblade.business.vo.TrialCyThirdReportQueryVo;
+
+/**
+* @author LHB
+* @description 针对表【u_trial_cy_third_report(成渝-已上传的外委检测报告/第三方检测报告/上传报告)】的数据库操作Mapper
+* @createDate 2025-08-01 09:05:10
+* @Entity generator.domain.UTrialCyThirdReport
+*/
+public interface TrialCyThirdReportMapper extends BaseMapper<TrialCyThirdReport> {
+
+    Page<ThirdReportVo> myPage(Page<ThirdReportVo> page,
+                               @Param("query") TrialCyThirdReportQueryVo queryVo);
+}
+
+
+
+

+ 36 - 0
blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialCyThirdReportMapper.xml

@@ -0,0 +1,36 @@
+<?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="org.springblade.business.mapper.TrialCyThirdReportMapper">
+    <select id="myPage" resultType="org.springblade.business.vo.ThirdReportVo">
+        select
+            id,
+            contract_id contractId,
+            report_no reportNo,
+            report_date reportDate,
+            project_part projectPositionName,
+            case when is_qualified = 1 then '合格'
+                else '不合格'
+            end detectionResultName,
+        (select count(0) > 0 from u_trial_file_pdf_record where node_id = #{query.qualityTestPKeyId}  and type in(12,13) and record_id = t.id) isSelectedStatus
+        from u_trial_cy_third_report t
+        <where>
+            <if test="query.contractId != null">
+                AND contract_id = #{query.contractId}
+            </if>
+            <if test="query.type != null">
+                AND `third_type` = #{query.type}
+            </if>
+            <if test="query.startTime != null">
+                AND report_date >= #{query.startTime}
+            </if>
+            <if test="query.endTime != null">
+                AND report_date &lt;= #{query.endTime}
+            </if>
+            <if test="query.nodeId != null">
+                AND exam_name_info_id = #{query.nodeId}
+            </if>
+        </where>
+    </select>
+</mapper>

+ 3 - 0
blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialSelfInspectionRecordMapper.java

@@ -7,6 +7,7 @@ import org.springblade.business.entity.TrialSelfInspectionRecord;
 import org.springblade.manager.entity.WbsTreeContract;
 
 import java.util.List;
+import java.util.Map;
 
 public interface TrialSelfInspectionRecordMapper extends BaseMapper<TrialSelfInspectionRecord> {
 
@@ -45,4 +46,6 @@ public interface TrialSelfInspectionRecordMapper extends BaseMapper<TrialSelfIns
     @Select("select self_id from u_trial_self_quality_project where quality_node_id = #{pKeyId}")
     List<String> selectTrialIdByNodeId(Long pKeyId);
 
+    List<Map<String,Object>> getTrialFilePdfRecord(@Param("nodeId") String nodeId,
+                                                   @Param("types") List<Integer> types);
 }

+ 6 - 0
blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialSelfInspectionRecordMapper.xml

@@ -108,5 +108,11 @@
             </if>
         </where>
     </select>
+    <select id="getTrialFilePdfRecord" resultType="java.util.Map">
+        select record_id,type from u_trial_file_pdf_record where node_id = #{nodeId} and `type` in
+       <foreach collection="types" item="type" open="(" close=")" separator=",">
+           #{type}
+       </foreach>
+    </select>
 
 </mapper>

+ 704 - 0
blade-service/blade-business/src/main/java/org/springblade/business/scheduled/ChenYuTestScheduled.java

@@ -0,0 +1,704 @@
+package org.springblade.business.scheduled;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.nacos.common.utils.MD5Utils;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.http.Consts;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.util.EntityUtils;
+import org.springblade.business.entity.*;
+import org.springblade.business.scheduled.vo.*;
+import org.springblade.business.service.TrialCyAccessoriesService;
+import org.springblade.business.service.TrialCyFinishTestReportService;
+import org.springblade.business.service.TrialCyTestTypeService;
+import org.springblade.business.service.TrialCyThirdReportService;
+import org.springblade.business.utils.FileUtils;
+import org.springblade.common.constant.CommonConstant;
+import org.springblade.common.utils.SnowFlakeUtil;
+import org.springblade.common.utils.SystemUtils;
+import org.springblade.core.oss.model.BladeFile;
+import org.springblade.core.redis.cache.BladeRedis;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.*;
+import org.springblade.manager.entity.ContractInfo;
+import org.springblade.manager.entity.ProjectInfo;
+import org.springblade.resource.feign.NewIOSSClient;
+import org.springblade.system.cache.ParamCache;
+import org.springframework.jdbc.core.BeanPropertyRowMapper;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.annotation.Resource;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
+
+/**
+ * 成渝试验第三方接口获取数据
+ * 定时任务
+ *
+ * @author LHB
+ */
+@Component
+@Slf4j
+public class ChenYuTestScheduled {
+
+    // 接口URL常量
+    private static final String THIRD_LOGIN_URL = "/api/ThirdSystem/ThirdLogin";
+    private static final String CONTRACT_SECT_URL = "/api/CQHCZC/MesureSystem/GetContractSectByProjCode";
+    private static final String FINISH_TEST_REPORT_URL = "/open/TestReport/GetFinishTestReport";
+    private static final String THIRD_REPORT_URL = "/open/ThirdReport/GetThirdReport";
+    private static final String ALL_TEST_TYPE_URL = "/open/ThirdReport/GetAllTestType";
+
+    // SQL常量
+    private static final String PROJECT_ID_SQL = "select id from m_project_info where project_number = ? and is_deleted = 0 limit 1";
+    private static final String APP_KEY_SQL = "select param_value from blade_param where param_key = 'cy.trial.appKey' and is_deleted = 0";
+    private static final String APP_SECRET_SQL = "select param_value from blade_param where param_key = 'cy.trial.appSecret' and is_deleted = 0";
+
+    @Resource
+    private JdbcTemplate jdbcTemplate;
+
+    @Resource
+    private BladeRedis bladeRedis;
+
+    @Resource
+    private TrialCyFinishTestReportService trialCyFinishTestReportService;
+
+    @Resource
+    private TrialCyTestTypeService trialCyTestTypeService;
+
+    @Resource
+    private TrialCyThirdReportService trialCyThirdReportService;
+
+    @Resource
+    private TrialCyAccessoriesService trialCyAccessoriesService;
+
+    @Resource
+    private NewIOSSClient newIOSSClient;
+
+    private CloseableHttpClient httpClient;
+    private static final String TOKEN_REDIS_KEY = "blade:cqcy:token";
+    private static final String PROJECT_CODE = "cqcyfx";
+    private static Long PROJECT_ID = null;
+    private static final String BASE_URL = "https://apicqcyfx.qdm123.com";
+    private final Map<String, Long> contractCodeMap = new ConcurrentHashMap<>();
+
+    @PostConstruct
+    public void init() {
+        this.httpClient = HttpClientBuilder.create().build();
+    }
+
+    @PreDestroy
+    public void destroy() {
+        if (httpClient != null) {
+            try {
+                httpClient.close();
+                log.info("HTTP client closed successfully");
+            } catch (IOException e) {
+                log.error("Error closing HTTP client", e);
+            }
+        }
+    }
+
+    /**
+     * 确保项目ID已初始化
+     */
+    private synchronized void ensureProjectIdInitialized() {
+        if (PROJECT_ID != null) return;
+
+        try {
+            List<ProjectInfo> projectList = jdbcTemplate.query(
+                    PROJECT_ID_SQL,
+                    new Object[]{PROJECT_CODE},
+                    new BeanPropertyRowMapper<>(ProjectInfo.class)
+            );
+
+            if (projectList != null && !projectList.isEmpty()) {
+                PROJECT_ID = projectList.get(0).getId();
+                log.info("Project ID initialized: {}", PROJECT_ID);
+            } else {
+                log.error("Project not found for code: {}", PROJECT_CODE);
+            }
+        } catch (Exception e) {
+            log.error("Error initializing project ID", e);
+        }
+    }
+
+    /**
+     * 获取有效的Token
+     */
+    private String getToken() {
+        String token = bladeRedis.get(TOKEN_REDIS_KEY);
+        if (token != null) {
+            return token;
+        }
+        return thirdLogin();
+    }
+
+    /**
+     * 登录获取Token
+     */
+    private String thirdLogin() {
+        ensureProjectIdInitialized();
+        if (PROJECT_ID == null) {
+            log.error("Project ID not available for login");
+            return null;
+        }
+
+        try {
+            String appKey = jdbcTemplate.queryForObject(APP_KEY_SQL, String.class);
+            String appSecret = jdbcTemplate.queryForObject(APP_SECRET_SQL, String.class);
+
+            if (StringUtil.isBlank(appKey) || StringUtil.isBlank(appSecret)) {
+                log.error("Missing appKey or appSecret configuration");
+                return null;
+            }
+
+            Long time = System.currentTimeMillis();
+            String md5Hex = MD5Utils.md5Hex(time + appKey + appSecret, "UTF-8");
+
+            ThirdLogin thirdLogin = new ThirdLogin();
+            thirdLogin.setAppKey(appKey);
+            thirdLogin.setTimestamp(time);
+            thirdLogin.setSecret(md5Hex);
+
+            Result result = postToken(BASE_URL + THIRD_LOGIN_URL, thirdLogin);
+            if (result == null || result.getState() != 1) {
+                log.error("Login failed: {}", result != null ? result.getMessage() : "No response");
+                return null;
+            }
+
+            JSONObject data = (JSONObject) result.getData();
+            String newToken = data.getString("token");
+            long expire = data.getLong("expireSecond") - 60;
+            bladeRedis.setEx(TOKEN_REDIS_KEY, newToken, expire);
+            return newToken;
+        } catch (Exception e) {
+            log.error("Login process failed", e);
+            return null;
+        }
+    }
+
+    /**
+     * 获取合同段列表
+     */
+    @Scheduled(cron = "0 0 * * * ?")
+    public void getContractSectByProjCode() {
+        if (!SystemUtils.isLinux()) {
+            return;
+        }
+
+        contractCodeMap.clear();
+        String token = getToken();
+        ensureProjectIdInitialized();
+
+        if (token == null || PROJECT_ID == null) {
+            log.error("Invalid token or project ID");
+            return;
+        }
+
+        try {
+            //获取合同段列表接口
+            Result result = getContractList();
+            if (result == null || result.getState() != 1) {
+                log.error("Failed to get contract sections: {}",
+                        result != null ? result.getMessage() : "No response");
+                return;
+            }
+
+            JSONArray data = (JSONArray) result.getData();
+            if (CollectionUtil.isEmpty(data)) {
+                log.warn("No contract sections found");
+                return;
+            }
+
+            List<String> codes = new ArrayList<>();
+            for (int i = 0; i < data.size(); i++) {
+                JSONObject obj = data.getJSONObject(i);
+                String name = obj.getString("Name");
+                if (StringUtil.isNotBlank(name)) {
+                    codes.add(name);
+                }
+            }
+
+            if (CollectionUtil.isEmpty(codes)) {
+                log.info("No valid contract codes found");
+                return;
+            }
+
+            // 构建参数化查询
+            String placeholders = String.join(",", Collections.nCopies(codes.size(), "?"));
+            String sql = "SELECT * FROM m_contract_info WHERE contract_number IN (" + placeholders + ")";
+
+            List<ContractInfo> contracts = jdbcTemplate.query(
+                    sql,
+                    codes.toArray(),
+                    new BeanPropertyRowMapper<>(ContractInfo.class)
+            );
+
+            for (ContractInfo contract : contracts) {
+                contractCodeMap.put(contract.getContractNumber(), contract.getId());
+            }
+
+            log.info("Loaded {} contract mappings", contractCodeMap.size());
+        } catch (Exception e) {
+            log.error("Error processing contract sections", e);
+        }
+    }
+
+    /**
+     * 获取已完成的检测报告
+     */
+    @Scheduled(cron = "0 05 * * * ?")
+    public void getFinishTestReport() {
+        if (!SystemUtils.isLinux()) {
+            return;
+        }
+
+        String token = getToken();
+        ensureProjectIdInitialized();
+
+        if (token == null || PROJECT_ID == null || contractCodeMap.isEmpty()) {
+            log.error("Preconditions not met for finish test report");
+            return;
+        }
+
+        for (Map.Entry<String, Long> entry : contractCodeMap.entrySet()) {
+            String contractCode = entry.getKey();
+            Long contractId = entry.getValue();
+
+            //查询旧数据
+            List<TrialCyFinishTestReport> list = trialCyFinishTestReportService.list(Wrappers.<TrialCyFinishTestReport>lambdaQuery()
+                    .eq(TrialCyFinishTestReport::getContractId, contractId));
+            //等会准备删除的历史数据
+            List<Long> ids = list.stream().map(TrialCyFinishTestReport::getId).collect(Collectors.toList());
+
+            int pageIndex = 0;
+            final int pageSize = 100;
+            boolean hasMore = true;
+
+            while (hasMore) {
+                try {
+                    List<NameValuePair> params = new ArrayList<NameValuePair>();
+                    params.add(new BasicNameValuePair("ProjectCode", PROJECT_CODE));
+                    params.add(new BasicNameValuePair("ContractsectCode", contractCode));
+                    //这些参数未找到传递的值
+                    if (false) {
+                        params.add(new BasicNameValuePair("BeginTime", null));
+                        params.add(new BasicNameValuePair("EndTime", null));
+                        params.add(new BasicNameValuePair("FinishBeginTime", null));
+                        params.add(new BasicNameValuePair("FinishEndTime", null));
+                    }
+                    params.add(new BasicNameValuePair("PageIndex", String.valueOf(pageIndex)));
+                    params.add(new BasicNameValuePair("PageSize", String.valueOf(pageSize)));
+
+                    ResultPost result = post(BASE_URL + FINISH_TEST_REPORT_URL, params);
+
+                    if (result == null) {
+                        log.error("Request failed for contract: {}", contractCode);
+                        break;
+                    }
+
+                    if (result.getCode() != 200) {
+                        log.error("API error for contract {}: {}", contractCode, result.getMsg());
+                        break;
+                    }
+
+                    JSONArray data = (JSONArray) result.getResult();
+                    if (CollectionUtil.isEmpty(data)) {
+                        break;
+                    }
+
+                    List<TrialCyFinishTestReport> reports = data.toJavaList(TrialCyFinishTestReport.class);
+                    for (TrialCyFinishTestReport report : reports) {
+                        Long id = SnowFlakeUtil.getId();
+                        report.setId(id);
+                        report.setContractId(contractId);
+                        //处理boolean值
+                        report.setExperimentResult(String.valueOf(report.getExperimentResult() == null ? 0 : "True".equals(report.getExperimentResult()) ? 1 : 0));
+
+                        List<String> urls = new ArrayList<>();
+                        if (StringUtil.isNotBlank(report.getReportFilePath())) {
+                            urls.add(report.getReportFilePath());
+                        }
+                        if (StringUtil.isNotBlank(report.getRecordFilePath())) {
+                            urls.add(report.getRecordFilePath());
+                        }
+
+                        //处理附件
+                        List<TrialCyAccessories> accessories = report.getAccessories();
+                        if (CollectionUtil.isNotEmpty(accessories)) {
+                            accessories.forEach(f -> {
+                                f.setId(SnowFlakeUtil.getId());
+                                f.setReportId(id);
+                                if (StringUtil.isNotBlank(f.getFilePath())) {
+                                    urls.add(f.getFilePath());
+                                }
+                            });
+
+                            if (CollectionUtil.isNotEmpty(ids)) {
+                                trialCyAccessoriesService.remove(Wrappers.<TrialCyAccessories>lambdaQuery()
+                                        .in(TrialCyAccessories::getReportId, ids));
+                            }
+                            trialCyAccessoriesService.saveBatch(accessories);
+                        }
+
+                        //组合文件
+                        if (urls.size() > 0) {
+                            //重新合并
+                                String filePath = ParamCache.getValue(CommonConstant.SYS_LOCAL_URL);
+                                String listPdf = filePath + "/pdf/" + id + ".pdf";
+                                File tabPDF = ResourceUtil.getFile(listPdf);
+                                if (tabPDF.exists()) {
+                                    tabPDF.delete();
+                                }
+                                FileUtils.mergePdfPublicMethods(urls, listPdf);
+                                BladeFile bladeFile = this.newIOSSClient.uploadFile(id + ".pdf", listPdf);
+                                if (bladeFile != null) {
+                                    report.setAssembleFile(bladeFile.getLink());
+                                }
+                        }
+                    }
+                    if (CollectionUtil.isNotEmpty(ids)) {
+                        trialCyFinishTestReportService.removeBatchByIds(ids);
+
+                        List<String> fileUrls = list.stream().map(TrialCyFinishTestReport::getAssembleFile).filter(StringUtil::isNotBlank).collect(Collectors.toList());
+                        if(CollectionUtil.isNotEmpty(fileUrls)){
+                            //删除组合文件
+                            fileUrls.forEach(f -> {
+                                String pdfName = f.split("upload")[1];
+                                this.newIOSSClient.removeFile("upload" + pdfName);
+                            });
+                        }
+                    }
+
+                    trialCyFinishTestReportService.saveBatch(reports);
+                    hasMore = reports.size() >= pageSize;
+                    pageIndex++;
+                } catch (Exception e) {
+                    log.error("Error processing contract {} page {}", contractCode, pageIndex, e);
+                    break;
+                }
+            }
+        }
+    }
+
+    /**
+     * 获取第三方报告
+     */
+    @Scheduled(cron = "0 05 * * * ?")
+    public void getThirdReport() {
+        if (!SystemUtils.isLinux()) {
+            return;
+        }
+
+        Integer[] thirdTypes = {0, 1, 2};
+
+        String token = getToken();
+        ensureProjectIdInitialized();
+
+        if (token == null || PROJECT_ID == null || contractCodeMap.isEmpty()) {
+            log.error("Preconditions not met for third report");
+            return;
+        }
+
+        for (Map.Entry<String, Long> entry : contractCodeMap.entrySet()) {
+            String contractCode = entry.getKey();
+            Long contractId = entry.getValue();
+
+
+            //获取旧id
+            List<TrialCyThirdReport> list = trialCyThirdReportService.list(Wrappers.<TrialCyThirdReport>lambdaQuery()
+                    .eq(TrialCyThirdReport::getContractId, contractId));
+            //等会要删除的id
+            List<Long> ids = list.stream().map(TrialCyThirdReport::getPKeyId).collect(Collectors.toList());
+
+
+            int pageIndex = 0;
+            final int pageSize = 100;
+            boolean hasMore = true;
+
+            for (Integer thirdType : thirdTypes) {
+                while (hasMore) {
+                    try {
+                        List<NameValuePair> params = new ArrayList<NameValuePair>();
+                        params.add(new BasicNameValuePair("ProjectCode", PROJECT_CODE));
+                        params.add(new BasicNameValuePair("ContractsectCode", contractCode));
+                        params.add(new BasicNameValuePair("ThirdType", String.valueOf(thirdType)));
+                        //这些参数为找到传递值
+                        if (false) {
+                            params.add(new BasicNameValuePair("BeginTime", null));
+                            params.add(new BasicNameValuePair("EndTime", null));
+                        }
+                        params.add(new BasicNameValuePair("PageIndex", String.valueOf(pageIndex)));
+                        params.add(new BasicNameValuePair("PageSize", String.valueOf(pageSize)));
+
+
+                        ResultPost result = post(BASE_URL + THIRD_REPORT_URL, params);
+
+                        if (result == null) {
+                            log.error("Request failed for contract: {}", contractCode);
+                            break;
+                        }
+
+                        if (result.getCode() != 200) {
+                            log.error("API error for contract {}: {}", contractCode, result.getMsg());
+                            break;
+                        }
+
+                        JSONArray data = (JSONArray) result.getResult();
+                        if (CollectionUtil.isEmpty(data)) {
+                            break;
+                        }
+
+                        List<TrialCyThirdReport> reports = data.toJavaList(TrialCyThirdReport.class);
+                        for (TrialCyThirdReport report : reports) {
+
+                            List<String> urls = new ArrayList<>();
+                            if (StringUtil.isNotBlank(report.getReportDocFilePath())) {
+                                urls.add(report.getReportDocFilePath());
+                            }
+                            if (StringUtil.isNotBlank(report.getRecordDocFilePath())) {
+                                urls.add(report.getRecordDocFilePath());
+                            }
+
+                            Long id = SnowFlakeUtil.getId();
+                            report.setPKeyId(id);
+                            report.setContractId(contractId);
+                            //报告类型
+                            report.setThirdType(thirdType);
+                            //处理boolean值
+                            report.setIsDeleted(String.valueOf(report.getIsDeleted() == null ? '1' : "True".equals(report.getIsDeleted()) ? '1' : '0'));
+                            report.setIsQualified(String.valueOf(report.getIsQualified() == null ? '0' : "True".equals(report.getIsQualified()) ? '1' : '0'));
+
+                            //处理附件
+                            List<TrialCyAccessories> accessories = report.getAccessories();
+                            if (CollectionUtil.isNotEmpty(accessories)) {
+                                accessories.forEach(f -> {
+                                    f.setId(SnowFlakeUtil.getId());
+                                    f.setReportId(id);
+
+                                    if (StringUtil.isNotBlank(f.getFilePath())) {
+                                        urls.add(f.getFilePath());
+                                    }
+                                });
+                                //删除旧数据
+                                if (CollectionUtil.isNotEmpty(ids)) {
+                                    trialCyAccessoriesService.remove(Wrappers.<TrialCyAccessories>lambdaQuery()
+                                            .in(TrialCyAccessories::getReportId, ids));
+                                }
+                                //添加新数据
+                                trialCyAccessoriesService.saveBatch(accessories);
+                            }
+
+                            //组合文件
+                            if (urls.size() > 0) {
+                                //重新合并
+                                String filePath = ParamCache.getValue(CommonConstant.SYS_LOCAL_URL);
+                                String listPdf = filePath + "/pdf/" + id + ".pdf";
+                                File tabPDF = ResourceUtil.getFile(listPdf);
+                                if (tabPDF.exists()) {
+                                    tabPDF.delete();
+                                }
+                                FileUtils.mergePdfPublicMethods(urls, listPdf);
+                                BladeFile bladeFile = this.newIOSSClient.uploadFile(id + ".pdf", listPdf);
+                                if (bladeFile != null) {
+                                    report.setAssembleFile(bladeFile.getLink());
+                                }
+                            }
+                        }
+                        //删除旧数据
+                        if (CollectionUtil.isNotEmpty(ids)) {
+                            trialCyThirdReportService.removeBatchByIds(ids);
+                            List<String> fileUrls = list.stream().map(TrialCyThirdReport::getAssembleFile).filter(StringUtil::isNotBlank).collect(Collectors.toList());
+                            if(CollectionUtil.isNotEmpty(fileUrls)){
+                                //删除组合文件
+                                fileUrls.forEach(f -> {
+                                    String pdfName = f.split("upload")[1];
+                                    this.newIOSSClient.removeFile("upload" + pdfName);
+                                });
+                            }
+                        }
+
+                        //添加新数据
+                        trialCyThirdReportService.saveBatch(reports);
+                        hasMore = reports.size() >= pageSize;
+                        pageIndex++;
+                    } catch (Exception e) {
+                        log.error("Error processing contract {} page {}", contractCode, pageIndex, e);
+                        break;
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * 获取检测项目树
+     */
+    @Scheduled(cron = "0 0 * * * ?")
+    public void getAllTestType() {
+        if (!SystemUtils.isLinux()) {
+            return;
+        }
+
+        try {
+            String token = getToken();
+            ensureProjectIdInitialized();
+
+            if (token == null || PROJECT_ID == null) {
+                log.error("Invalid token or project ID");
+                return;
+            }
+
+            List<NameValuePair> params = new ArrayList<NameValuePair>();
+            params.add(new BasicNameValuePair("ProjectCode", PROJECT_CODE));
+
+            ResultPost result = post(BASE_URL + ALL_TEST_TYPE_URL, params);
+            if (result == null || result.getCode() != 200) {
+                log.error("Failed to get test types: {}",
+                        result != null ? result.getMsg() : "No response");
+                return;
+            }
+
+            JSONArray data = (JSONArray) result.getResult();
+            if (CollectionUtil.isEmpty(data)) {
+                log.info("No test types found");
+                return;
+            }
+
+            List<TrialCyTestType> testTypes = data.toJavaList(TrialCyTestType.class);
+            for (TrialCyTestType type : testTypes) {
+                type.setPKeyId(SnowFlakeUtil.getId());
+                type.setProjectId(PROJECT_ID);
+                type.setFatherId(type.getFatherId() == null || type.getFatherId().isEmpty() ? "0" : type.getFatherId());
+            }
+            //先删除旧数据
+            trialCyTestTypeService.remove(Wrappers.<TrialCyTestType>lambdaQuery()
+                    .eq(TrialCyTestType::getProjectId, PROJECT_ID));
+            trialCyTestTypeService.saveOrUpdateBatch(testTypes);
+            log.info("Saved {} test types", testTypes.size());
+        } catch (Exception e) {
+            log.error("Error processing test types", e);
+        }
+    }
+
+    /**
+     * HTTP POST请求 获取token
+     */
+    private Result postToken(String url, ThirdLogin payload) {
+        HttpPost httpPost = new HttpPost(url);
+        httpPost.setHeader("Content-Type", "application/json");
+        try {
+            httpPost.setEntity(new StringEntity(JSON.toJSONString(payload), StandardCharsets.UTF_8));
+        } catch (Exception e) {
+            log.error("Failed to set request entity", e);
+            return null;
+        }
+
+        try (ByteArrayOutputStream output = new ByteArrayOutputStream()) {
+            HttpResponse response = httpClient.execute(httpPost);
+            int status = response.getStatusLine().getStatusCode();
+
+            if (status != 200) {
+                log.warn("HTTP error: {} - {}", status, response.getStatusLine().getReasonPhrase());
+                return null;
+            }
+
+            try (InputStream input = response.getEntity().getContent()) {
+                byte[] buffer = new byte[1024];
+                int bytesRead;
+                while ((bytesRead = input.read(buffer)) != -1) {
+                    output.write(buffer, 0, bytesRead);
+                }
+            }
+
+            String responseString = new String(output.toByteArray(), StandardCharsets.UTF_8);
+            return JSON.parseObject(responseString, Result.class);
+        } catch (Exception e) {
+            log.error("HTTP request failed: {}", url, e);
+            return null;
+        }
+    }
+
+    /**
+     * HTTP POST请求
+     */
+    private ResultPost post(String url, List<NameValuePair> params) {
+        HttpPost httpPost = new HttpPost(url);
+        httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");
+        httpPost.setHeader("token", getToken());
+        try {
+            httpPost.setEntity(new UrlEncodedFormEntity(params, Consts.UTF_8));
+        } catch (Exception e) {
+            log.error("Failed to set request entity", e);
+            return null;
+        }
+
+        try (ByteArrayOutputStream output = new ByteArrayOutputStream()) {
+            HttpResponse response = httpClient.execute(httpPost);
+            int status = response.getStatusLine().getStatusCode();
+
+            if (status != 200) {
+                log.warn("HTTP error: {} - {}", status, response.getStatusLine().getReasonPhrase());
+                return null;
+            }
+
+            try (InputStream input = response.getEntity().getContent()) {
+                byte[] buffer = new byte[1024];
+                int bytesRead;
+                while ((bytesRead = input.read(buffer)) != -1) {
+                    output.write(buffer, 0, bytesRead);
+                }
+            }
+
+            String responseString = new String(output.toByteArray(), StandardCharsets.UTF_8);
+            return JSON.parseObject(responseString, ResultPost.class);
+        } catch (Exception e) {
+            log.error("HTTP request failed: {}", url, e);
+            return null;
+        }
+    }
+
+    /**
+     * HTTP get 请求 获取合同段数据
+     */
+    private Result getContractList() {
+        try {
+            CloseableHttpClient client = HttpClients.createDefault();
+            HttpGet httpGet = new HttpGet(BASE_URL + CONTRACT_SECT_URL + "?token=" + getToken() + "&ProjectCode=" + PROJECT_CODE);
+            CloseableHttpResponse response = client.execute(httpGet);
+
+            //5、获取实体
+            HttpEntity entity = response.getEntity();
+            //将实体装成字符串
+            String string = EntityUtils.toString(entity);
+            return JSON.parseObject(string, Result.class);
+        } catch (IOException e) {
+            log.error("HTTP request failed: {}", BASE_URL + CONTRACT_SECT_URL, e);
+            return null;
+        }
+    }
+}

+ 462 - 0
blade-service/blade-business/src/main/java/org/springblade/business/scheduled/ChenYuTestScheduled01.java

@@ -0,0 +1,462 @@
+package org.springblade.business.scheduled;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.nacos.common.utils.MD5Utils;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.springblade.business.entity.TrialCyFinishTestReport;
+import org.springblade.business.entity.TrialCyTestType;
+import org.springblade.business.entity.TrialCyThirdReport;
+import org.springblade.business.scheduled.vo.GetFinishTestReport;
+import org.springblade.business.scheduled.vo.GetThirdReport;
+import org.springblade.business.scheduled.vo.Result;
+import org.springblade.business.scheduled.vo.ThirdLogin;
+import org.springblade.business.service.TrialCyFinishTestReportService;
+import org.springblade.business.service.TrialCyTestTypeService;
+import org.springblade.business.service.TrialCyThirdReportService;
+import org.springblade.common.utils.SystemUtils;
+import org.springblade.core.redis.cache.BladeRedis;
+import org.springblade.core.tool.utils.CollectionUtil;
+import org.springblade.core.tool.utils.StringUtil;
+import org.springblade.manager.entity.ContractInfo;
+import org.springblade.manager.entity.ProjectInfo;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.Resource;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * 成渝试验第三方接口获取数据
+ * 定时任务
+ *
+ * @author LHB
+ */
+@Component
+@Slf4j
+public class ChenYuTestScheduled01 {
+
+    @Resource
+    private JdbcTemplate jdbcTemplate;
+
+    @Resource
+    private BladeRedis bladeRedis;
+    /**
+     * 成渝-获取标段已完成(已签章完成)的检测报告
+     */
+    @Resource
+    private TrialCyFinishTestReportService trialCyFinishTestReportService;
+    /**
+     * 成渝-试验检测树
+     */
+    @Resource
+    private TrialCyTestTypeService trialCyTestTypeService;
+    /**
+     * 成渝-已上传的外委检测报告/ 第三方检测报告/ 上传报告
+     */
+    @Resource
+    private TrialCyThirdReportService trialCyThirdReportService;
+
+    // HTTP客户端复用
+    private CloseableHttpClient httpClient;
+
+    @PostConstruct
+    public void init() {
+        this.httpClient = HttpClientBuilder.create().build();
+    }
+
+    //token缓存key
+    private static final String TOKEN_REDIS_KEY = "blade:cqcy:token";
+
+    //项目编码
+    private static final String PROJECT_CODE = "cqcyfx";
+
+    //项目id
+    private static Long PROJECT_ID = null;
+
+    //接口域名
+    private final String URL = "https://apicqcyfx.qdm123.com";
+
+    //合同编码缓存
+    private final Map<String, Long> contractCodeMap = new ConcurrentHashMap<>();
+
+    /**
+     * 登录 获取token
+     */
+
+    public String thirdLogin() {
+        //TODO 从后台管理的配置中心获取
+        String url = "/api/ThirdSystem/ThirdLogin";
+
+
+        //获取项目id
+        String sql = "select id from m_project_info where project_number = ? and is_deleted = 0 limit 1";
+        ProjectInfo projectInfo = jdbcTemplate.queryForObject(sql, ProjectInfo.class, PROJECT_CODE);
+        PROJECT_ID = projectInfo.getId();
+
+
+        String getAppKeySql = "select param_value from blade_param where param_key = 'cy.trial.appKey' and is_deleted = 0";
+        String getAppSecretSql = "select param_value from blade_param where param_key = 'cy.trial.appSecret' and is_deleted = 0";
+        //后管配置 appKey
+        String appKey = jdbcTemplate.queryForObject(getAppKeySql, String.class);
+        //后管配置 appSecret
+        String appSecret = jdbcTemplate.queryForObject(getAppSecretSql, String.class);
+        if (StringUtil.isBlank(appKey) || StringUtil.isBlank(appSecret)) {
+            log.error("---------#后管未配置成渝-试验-授权码或私钥");
+            return null;
+        }
+        //当前时间戳
+        Long time = System.currentTimeMillis();
+
+        //加密
+        String md5Hex = MD5Utils.md5Hex(time + appKey + appSecret, "UTF-8");
+
+        ThirdLogin thirdLogin = new ThirdLogin();
+        thirdLogin.setAppKey(appKey);
+        thirdLogin.setTimestamp(time);
+        thirdLogin.setSecret(md5Hex);
+
+
+        Result post = this.post(URL + url, thirdLogin);
+        if (post == null) {
+            log.error("---------#成渝第三方接口访问失败");
+            return null;
+        }
+        Integer state = post.getState();
+        //成功
+        if (state == 1) {
+            JSONObject data = (JSONObject) post.getData();
+            bladeRedis.setEx(TOKEN_REDIS_KEY, data.getString("token"), data.getLong("expireSecond") - 60);
+            return data.getString("token");
+        } else {
+            log.error("---------#成渝第三方接口访问失败:" + post.getMessage());
+            return null;
+        }
+    }
+
+
+    /**
+     * 获取合同段列表接口
+     */
+    @Scheduled(cron = "0 0 * * * ?")
+    public void getContractSectByProjCode()     {
+        if(!SystemUtils.isLinux()){
+            return;
+        }
+        //清空缓存
+        contractCodeMap.clear();
+
+        String url = "/api/CQHCZC/MesureSystem/GetContractSectByProjCode";
+
+        String token = bladeRedis.get(TOKEN_REDIS_KEY);
+        if (token == null) {
+            token = thirdLogin();
+        }
+        if (token == null) {
+            log.error("---------#成渝第三方接口访问失败:token为空");
+            return;
+        }
+        if (PROJECT_ID == null) {
+            log.error("---------#成渝第三方接口访问失败:项目不存在");
+            return;
+        }
+
+
+        JSONObject jsonObject = new JSONObject();
+        jsonObject.put("token", token);
+        jsonObject.put("ProjectCode", PROJECT_CODE);
+
+        Result post = this.post(URL + url, jsonObject);
+
+        if (post == null) {
+            log.error("---------#成渝第三方接口访问失败");
+            return;
+        }
+        Integer state = post.getState();
+        //成功
+        if (state == 1) {
+            //合同段列表数据
+            JSONArray data = (JSONArray) post.getData();
+
+            List<String> codes = new ArrayList<>();
+
+            //返回的数据不能为空
+            if (CollectionUtil.isNotEmpty(data)) {
+                for (Object datum : data) {
+                    JSONObject jsonObject1 = (JSONObject) datum;
+                    String code = jsonObject1.getString("Code");
+                    //编码不能为空
+                    if (StringUtil.isNotBlank(code)) {
+                        codes.add(code);
+                    }
+                }
+            }
+            //封装需要查询的合同段
+            if (CollectionUtil.isNotEmpty(codes)) {
+                //使用参数化查询防止SQL注入
+                StringBuilder sqlBuilder = new StringBuilder("select * from m_contract_info where contract_number in (");
+                for (int i = 0; i < codes.size(); i++) {
+                    sqlBuilder.append(i == 0 ? "?" : ",?");
+                }
+                sqlBuilder.append(")");
+
+                //查询数据
+                List<ContractInfo> contractInfoList = jdbcTemplate.queryForList(sqlBuilder.toString(), ContractInfo.class, codes.toArray());
+                contractInfoList.forEach(f -> {
+                    contractCodeMap.put(f.getContractNumber(), f.getId());
+                });
+            }
+        } else {
+            log.error("---------#成渝第三方接口访问失败:" + post.getMessage());
+        }
+    }
+
+    /**
+     * 获取标段已完成(已签章完成)的检测报告
+     */
+    @Scheduled(cron = "0 0 * * * ?")
+    public void getFinishTestReport() {
+        if(!SystemUtils.isLinux()){
+            return;
+        }
+        String url = "/open/TestReport/GetFinishTestReport";
+
+        String token = bladeRedis.get(TOKEN_REDIS_KEY);
+        if (token == null) {
+            token = thirdLogin();
+        }
+        if (token == null) {
+            log.error("---------#成渝第三方接口访问失败:token为空");
+            return;
+        }
+        if (PROJECT_ID == null) {
+            log.error("---------#成渝第三方接口访问失败:项目不存在");
+            return;
+        }
+        //获取需要同步的合同段信息
+        Set<String> contractCodes = contractCodeMap.keySet();
+        if (CollectionUtil.isEmpty(contractCodes)) {
+            log.error("---------#成渝第三方接口访问失败:合同段编码无数据");
+            return;
+        }
+        for (String contractCode : contractCodes) {
+            GetFinishTestReport getFinishTestReport = new GetFinishTestReport(token, PROJECT_CODE, contractCode);
+
+            Integer pageIndex = 0;
+            Integer pageSize = 100;
+
+            do {
+                getFinishTestReport.setPageIndex(pageIndex);
+                getFinishTestReport.setPageSize(pageSize);
+
+                Result post = this.post(URL + url, getFinishTestReport);
+                if (post == null) {
+                    log.error("---------#成渝第三方接口访问失败:接口访问失败, contractCode: {}", contractCode);
+                    break; // 继续处理下一个合同段
+                }
+                Integer state = post.getState();
+                //成功
+                if (state == 1) {
+                    //检测报告列表
+                    JSONArray data = (JSONArray) post.getData();
+                    List<TrialCyFinishTestReport> list = data.toJavaList(TrialCyFinishTestReport.class);
+                    //退出循环
+                    if (CollectionUtil.isEmpty(list)) {
+                        break;
+                    }
+                    list.forEach(f -> f.setContractId(contractCodeMap.get(contractCode)));
+                    //处理数据
+                    trialCyFinishTestReportService.saveBatch(list);
+                    if (list.size() < pageSize) {
+                        break;
+                    }
+                    pageIndex++;
+                } else {
+                    log.error("---------#成渝第三方接口访问失败:{}, contractCode: {}", post.getMessage(), contractCode);
+                    break; // 继续处理下一个合同段
+                }
+            } while (true);
+        }
+    }
+
+    /**
+     * 获取已上传的外委检测报告/第三方检测报告/上传报告
+     */
+    @Scheduled(cron = "0 0 * * * ?")
+    public void getThirdReport() {
+        if(!SystemUtils.isLinux()){
+            return;
+        }
+        String url = "/open/ThirdReport/GetThirdReport";
+
+        String token = bladeRedis.get(TOKEN_REDIS_KEY);
+        if (token == null) {
+            token = thirdLogin();
+        }
+        if (token == null) {
+            log.error("---------#成渝第三方接口访问失败:token为空");
+            return;
+        }
+        if (PROJECT_ID == null) {
+            log.error("---------#成渝第三方接口访问失败:项目不存在");
+            return;
+        }
+        //获取需要同步的合同段信息
+        Set<String> contractCodes = contractCodeMap.keySet();
+        if (CollectionUtil.isEmpty(contractCodes)) {
+            log.error("---------#成渝第三方接口访问失败:合同段编码无数据");
+            return;
+        }
+        for (String contractCode : contractCodes) {
+            GetThirdReport getThirdReport = new GetThirdReport(token, PROJECT_CODE, contractCode);
+
+            Integer pageIndex = 0;
+            int pageSize = 100;
+
+            do {
+                getThirdReport.setPageIndex(pageIndex);
+                getThirdReport.setPageSize(pageSize);
+
+                Result post = this.post(URL + url, getThirdReport);
+                if (post == null) {
+                    log.error("---------#成渝第三方接口访问失败:接口访问失败, contractCode: {}", contractCode);
+                    break; // 继续处理下一个合同段
+                }
+                Integer state = post.getState();
+                //成功
+                if (state == 1) {
+                    //已上传的外委检测报告/第三方检测报告/上传报告
+                    JSONArray data = (JSONArray) post.getData();
+                    List<TrialCyThirdReport> list = data.toJavaList(TrialCyThirdReport.class);
+                    //退出循环
+                    if (CollectionUtil.isEmpty(list)) {
+                        break;
+                    }
+                    list.forEach(f -> f.setContractId(contractCodeMap.get(contractCode)));
+                    //处理数据
+                    trialCyThirdReportService.saveBatch(list);
+
+                    if (list.size() < pageSize) {
+                        break;
+                    }
+
+                    pageIndex++;
+                } else {
+                    log.error("---------#成渝第三方接口访问失败:{}, contractCode: {}", post.getMessage(), contractCode);
+                    break; // 继续处理下一个合同段
+                }
+            } while (true);
+        }
+    }
+
+    /**
+     * 获取检测项目树(包括自建试验、外委、第三方、上传报告)
+     */
+    @Scheduled(cron = "0 0 * * * ?")
+    public void getAllTestType() {
+        if(!SystemUtils.isLinux()){
+            return;
+        }
+
+        String url = "/open/ThirdReport/GetAllTestType";
+        String token = bladeRedis.get(TOKEN_REDIS_KEY);
+        if (token == null) {
+            token = thirdLogin();
+        }
+        if (token == null) {
+            log.error("---------#成渝第三方接口访问失败:token为空");
+            return;
+        }
+        if (PROJECT_ID == null) {
+            log.error("---------#成渝第三方接口访问失败:项目不存在");
+            return;
+        }
+
+        JSONObject jsonObject = new JSONObject();
+        jsonObject.put("token", token);
+        jsonObject.put("ProjectCode", PROJECT_CODE);
+
+        Result post = this.post(URL + url, jsonObject);
+
+        if (post == null) {
+            log.error("---------#成渝第三方接口访问失败:接口访问失败");
+            return;
+        }
+
+
+        Integer state = post.getState();
+        //成功
+        if (state == 1) {
+            //合同段列表数据
+            JSONArray data = (JSONArray) post.getData();
+            List<TrialCyTestType> list = data.toJavaList(TrialCyTestType.class);
+            //退出循环
+            if (CollectionUtil.isEmpty(list)) {
+                return;
+            }
+            list.forEach(f -> f.setProjectId(PROJECT_ID));
+            //处理数据
+            trialCyTestTypeService.saveOrUpdateBatch(list);
+        } else {
+            log.error("---------#成渝第三方接口访问失败:" + post.getMessage());
+        }
+    }
+
+
+    /**
+     * 封装请求参数
+     */
+    public Result post(String url, Object object) {
+        HttpPost httpPost = new HttpPost(url);
+        httpPost.setHeader("Content-Type", "application/json");
+
+        // 对象转json
+        StringEntity json = new StringEntity(JSON.toJSONString(object), "utf-8");
+        httpPost.setEntity(json);
+
+        try {
+            HttpResponse httpResponse = httpClient.execute(httpPost);
+
+            // 检查响应状态码
+            int statusCode = httpResponse.getStatusLine().getStatusCode();
+            if (statusCode != 200) {
+                log.warn("HTTP request failed with status code: {}", statusCode);
+                // 可以根据具体业务需求调整错误处理方式
+                return null;
+            }
+
+            try (InputStream inputStream = httpResponse.getEntity().getContent();
+                 ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
+
+                byte[] buffer = new byte[1024];
+                int index = 0;
+                while ((index = inputStream.read(buffer)) != -1) {
+                    outputStream.write(buffer, 0, index);
+                }
+                // 响应参数 - 指定明确的字符编码
+                Result result = JSON.parseObject(outputStream.toString("utf-8"), Result.class);
+                return result;
+            }
+        } catch (IOException e) {
+            log.error("HTTP request failed: ", e);
+            // 返回错误结果或抛出异常,根据业务需求决定
+            return null;
+        }
+    }
+
+}

+ 57 - 0
blade-service/blade-business/src/main/java/org/springblade/business/scheduled/vo/GetFinishTestReport.java

@@ -0,0 +1,57 @@
+package org.springblade.business.scheduled.vo;
+
+import lombok.Data;
+
+/**
+ * 获取标段已完成(已签章完成)的检测报告的接口实体类
+ *
+ * @author LHB
+ */
+@Data
+public class GetFinishTestReport {
+    /**
+     * 登录接口返回的token
+     */
+    private String token;
+    /**
+     * 工程项目编码,数据约定具体见附件
+     */
+    private String ProjectCode;
+    /**
+     * 合同段/工区编码,数据约定具体见附件
+     */
+    private String ContractsectCode;
+    /**
+     * 报告起始时间
+     */
+    private String BeginTime;
+    /**
+     * 报告截止时间,注意:此字段实际执行时间包含传入时间当天,截止至当天24:00
+     */
+    private String EndTime;
+    /**
+     * 签章完成时间范围-起
+     */
+    private String FinishBeginTime;
+    /**
+     * 签章完成时间范围-止,截止至当天24:00
+     */
+    private String FinishEndTime;
+    /**
+     * 页码,默认为0
+     */
+    private Integer PageIndex;
+    /**
+     * 获取数据条数,不大于1000
+     */
+    private Integer PageSize;
+
+    public GetFinishTestReport(String token, String projectCode, String contractsectCode) {
+        this.token = token;
+        ProjectCode = projectCode;
+        ContractsectCode = contractsectCode;
+    }
+
+    public GetFinishTestReport() {
+    }
+}

+ 57 - 0
blade-service/blade-business/src/main/java/org/springblade/business/scheduled/vo/GetThirdReport.java

@@ -0,0 +1,57 @@
+package org.springblade.business.scheduled.vo;
+
+import lombok.Data;
+
+/**
+ * 获取已上传的外委检测报告/第三方检测报告/上传报告的请求参数对象
+ *
+ * @author LHB
+ */
+@Data
+public class GetThirdReport {
+    /**
+     * 登录接口返回的token
+     */
+    private String token;
+    /**
+     * 工程项目编码,数据约定具体见附件
+     */
+    private String ProjectCode;
+    /**
+     * 合同段/工区编码,数据约定具体见附件
+     */
+    private String ContractsectCode;
+    /**
+     * 0:外委检测
+     * 1:第三方检测
+     * 2:扫描上传报告
+     */
+    private Integer ThirdType;
+    /**
+     * 上传起始时间
+     * 注意:此字段实际执行时间为当天0点
+     */
+    private String BeginTime;
+    /**
+     * 上传截止时间,注意:此字段实际执行时间为当天24:00
+     */
+    private String EndTime;
+    /**
+     * 页码,默认为0
+     */
+    private Integer PageIndex;
+    /**
+     * 获取数据条数,不大于100
+     */
+    private Integer PageSize;
+
+
+    public GetThirdReport(String token, String projectCode, String contractsectCode) {
+        this.token = token;
+        ProjectCode = projectCode;
+        ContractsectCode = contractsectCode;
+    }
+
+    public GetThirdReport() {
+    }
+}

+ 25 - 0
blade-service/blade-business/src/main/java/org/springblade/business/scheduled/vo/Result.java

@@ -0,0 +1,25 @@
+package org.springblade.business.scheduled.vo;
+
+import lombok.Data;
+
+/**
+ * 成渝第三方接口响应结构
+ * @author LHB
+ */
+@Data
+public class Result {
+    /**
+     * 请求结果
+     * 0:请求失败
+     * 1:请求成功
+     */
+    private Integer state;
+    /**
+     * 操作提示信息;
+     */
+    private String message;
+    /**
+     * 接口返回的数据对象包体,由每个接口根据业务逻辑决定,可为JSON对象或JSON数组对象。
+     */
+    private Object data;
+}

+ 25 - 0
blade-service/blade-business/src/main/java/org/springblade/business/scheduled/vo/ResultPost.java

@@ -0,0 +1,25 @@
+package org.springblade.business.scheduled.vo;
+
+import lombok.Data;
+
+/**
+ * 成渝第三方接口响应结构
+ * @author LHB
+ */
+@Data
+public class ResultPost {
+    /**
+     * 请求结果
+     * 0:请求失败
+     * 1:请求成功
+     */
+    private Integer code;
+    /**
+     * 操作提示信息;
+     */
+    private String msg;
+    /**
+     * 接口返回的数据对象包体,由每个接口根据业务逻辑决定,可为JSON对象或JSON数组对象。
+     */
+    private Object result;
+}

+ 28 - 0
blade-service/blade-business/src/main/java/org/springblade/business/scheduled/vo/ThirdLogin.java

@@ -0,0 +1,28 @@
+package org.springblade.business.scheduled.vo;
+
+import lombok.Data;
+
+/**
+ * 成渝获取token接口参数
+ *
+ * @author LHB
+ */
+@Data
+public class ThirdLogin {
+    /**
+     * 授权第三方KEY(成渝那边提供)
+     */
+    private String appKey;
+    /**
+     * 空
+     */
+    private String account;
+    /**
+     * 时间截(1970-01-01至当前时间的总毫秒数)
+     */
+    private Long timestamp;
+    /**
+     * MD5(timestamp + appKey + account + appSecret)
+     */
+    private String secret;
+}

+ 25 - 0
blade-service/blade-business/src/main/java/org/springblade/business/service/IRecycleBinInfoService.java

@@ -0,0 +1,25 @@
+package org.springblade.business.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.springblade.business.entity.RecycleBinInfo;
+import org.springblade.business.vo.RecycleBinInfoVO;
+import org.springblade.core.mp.base.BaseService;
+import org.springblade.system.user.vo.UserVO2;
+
+import java.util.Collection;
+import java.util.List;
+
+
+public interface IRecycleBinInfoService extends BaseService<RecycleBinInfo> {
+
+    /**
+     * 分页
+     */
+    IPage<RecycleBinInfo> selectPage(RecycleBinInfoVO recycleBinInfoVO);
+
+    Collection<UserVO2> queryUser(Long contractId, Integer isRecycleBin, String name);
+
+    Collection<RecycleBinInfo> queryOperation(String ids);
+
+    Boolean saveRecycleBinInfoByWbsTreeContract(String ids, String rootIds);
+}

+ 1 - 1
blade-service/blade-business/src/main/java/org/springblade/business/service/ITaskService.java

@@ -57,7 +57,7 @@ public interface ITaskService extends BaseService<Task> {
     /**
      * 批量审批
      */
-    void batchCompleteApprovalTask(List<TaskApprovalVO> taskApprovalVOS) throws FileNotFoundException;
+    Boolean batchCompleteApprovalTask(List<TaskApprovalVO> taskApprovalVOS) throws FileNotFoundException;
 
     /**
      * 启动流程

+ 1 - 0
blade-service/blade-business/src/main/java/org/springblade/business/service/ITrialSelfInspectionRecordService.java

@@ -5,6 +5,7 @@ import org.springblade.business.dto.*;
 import org.springblade.business.entity.TrialSelfInspectionRecord;
 import org.springblade.business.vo.*;
 import org.springblade.core.mp.base.BaseService;
+import org.springblade.core.secure.BladeUser;
 import org.springblade.core.tool.api.R;
 import org.springframework.web.multipart.MultipartFile;
 

+ 2 - 1
blade-service/blade-business/src/main/java/org/springblade/business/service/StandardInfoService.java

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
 import org.springblade.business.dto.StandardInfoDTO;
 import org.springblade.business.dto.StandardInfoPrivateJoinDTO;
 import org.springblade.business.entity.StandardInfo;
+import org.springblade.business.vo.StandardInfoDtoVo;
 import org.springblade.business.vo.StandardInfoPrivateJoinVO;
 import org.springblade.business.vo.StandardInfoVO;
 import org.springblade.core.mp.support.Query;
@@ -18,7 +19,7 @@ import java.util.List;
  */
 public interface StandardInfoService extends IService<StandardInfo> {
 
-    IPage<StandardInfoDTO> selectMyPage(Query query, StandardInfo standardInfo);
+    IPage<StandardInfoDtoVo> selectMyPage(Query query, StandardInfo standardInfo);
 
     StandardInfoDTO selectOne(Long id);
 

+ 14 - 0
blade-service/blade-business/src/main/java/org/springblade/business/service/TrialCyAccessoriesService.java

@@ -0,0 +1,14 @@
+package org.springblade.business.service;
+
+import org.springblade.business.entity.TrialCyAccessories;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+* @author LHB
+* @description 针对表【u_trial_cy_accessories(成渝-附件信息)】的数据库操作Service
+* @createDate 2025-08-04 14:39:16
+*/
+public interface TrialCyAccessoriesService extends IService<TrialCyAccessories> {
+
+    Boolean clearTrialAssociation(Long nodeId, Long recordId);
+}

+ 19 - 0
blade-service/blade-business/src/main/java/org/springblade/business/service/TrialCyFinishTestReportService.java

@@ -0,0 +1,19 @@
+package org.springblade.business.service;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import org.apache.ibatis.annotations.Param;
+import org.springblade.business.entity.TrialCyFinishTestReport;
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.springblade.business.vo.ThirdReportVo;
+import org.springblade.business.vo.TrialCyThirdReportQueryVo;
+
+/**
+* @author LHB
+* @description 针对表【u_trial_cy_finish_test_report(成渝-获取标段已完成(已签章完成)的检测报告)】的数据库操作Service
+* @createDate 2025-08-01 09:05:03
+*/
+public interface TrialCyFinishTestReportService extends IService<TrialCyFinishTestReport> {
+
+    Page<ThirdReportVo> myPage(Page<ThirdReportVo> objectPage,
+                               TrialCyThirdReportQueryVo queryVo);
+}

+ 25 - 0
blade-service/blade-business/src/main/java/org/springblade/business/service/TrialCyService.java

@@ -0,0 +1,25 @@
+package org.springblade.business.service;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import org.springblade.business.entity.TrialCyFinishTestReport;
+import org.springblade.business.entity.TrialCyTestType;
+import org.springblade.business.entity.TrialCyThirdReport;
+import org.springblade.business.vo.ThirdReportVo;
+import org.springblade.business.vo.TrialCyThirdReportQueryVo;
+
+import java.util.List;
+
+/**
+ * @author LHB
+ */
+public interface TrialCyService {
+    Boolean isCyAndTestModule(Long projectId, Long contractId);
+
+    List<TrialCyTestType> getTree(Long projectId, String parentId);
+
+    Page<ThirdReportVo> getTrialDetectionReport(TrialCyThirdReportQueryVo queryVo);
+
+    Page<ThirdReportVo> getThirdReport(TrialCyThirdReportQueryVo queryVo);
+
+    Boolean clearTrialAssociation(Long nodeId, Long recordId);
+}

+ 16 - 0
blade-service/blade-business/src/main/java/org/springblade/business/service/TrialCyTestTypeService.java

@@ -0,0 +1,16 @@
+package org.springblade.business.service;
+
+import org.springblade.business.entity.TrialCyTestType;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+import java.util.List;
+
+/**
+* @author LHB
+* @description 针对表【u_trial_cy_test_type(成渝-试验检测树)】的数据库操作Service
+* @createDate 2025-08-01 09:05:07
+*/
+public interface TrialCyTestTypeService extends IService<TrialCyTestType> {
+
+    List<TrialCyTestType> getTree(Long projectId, String parentId);
+}

+ 18 - 0
blade-service/blade-business/src/main/java/org/springblade/business/service/TrialCyThirdReportService.java

@@ -0,0 +1,18 @@
+package org.springblade.business.service;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import org.springblade.business.entity.TrialCyFinishTestReport;
+import org.springblade.business.entity.TrialCyThirdReport;
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.springblade.business.vo.ThirdReportVo;
+import org.springblade.business.vo.TrialCyThirdReportQueryVo;
+
+/**
+* @author LHB
+* @description 针对表【u_trial_cy_third_report(成渝-已上传的外委检测报告/第三方检测报告/上传报告)】的数据库操作Service
+* @createDate 2025-08-01 09:05:10
+*/
+public interface TrialCyThirdReportService extends IService<TrialCyThirdReport> {
+
+    Page<ThirdReportVo> myPage(Page<ThirdReportVo> page, TrialCyThirdReportQueryVo queryVo);
+}

+ 394 - 0
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/RecycleBinInfoServiceImpl.java

@@ -0,0 +1,394 @@
+package org.springblade.business.service.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.jetbrains.annotations.Nullable;
+import org.springblade.business.entity.InformationQuery;
+import org.springblade.business.entity.RecycleBin;
+import org.springblade.business.entity.RecycleBinInfo;
+import org.springblade.business.mapper.RecycleBinInfoMapper;
+import org.springblade.business.mapper.RecycleBinMapper;
+import org.springblade.business.service.IInformationQueryService;
+import org.springblade.business.service.IRecycleBinInfoService;
+import org.springblade.business.vo.RecycleBinInfoVO;
+import org.springblade.common.utils.SnowFlakeUtil;
+import org.springblade.core.log.exception.ServiceException;
+import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springblade.core.mp.support.Condition;
+import org.springblade.core.redis.cache.BladeRedis;
+import org.springblade.core.secure.utils.AuthUtil;
+import org.springblade.core.tool.utils.DateUtil;
+import org.springblade.core.tool.utils.StringUtil;
+import org.springblade.manager.entity.ContractInfo;
+import org.springblade.manager.entity.WbsTreeContract;
+import org.springblade.system.user.entity.User;
+import org.springblade.system.user.vo.UserVO2;
+import org.springframework.jdbc.core.BeanPropertyRowMapper;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.stereotype.Service;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+
+@Service
+@RequiredArgsConstructor
+@Slf4j
+public class RecycleBinInfoServiceImpl extends BaseServiceImpl<RecycleBinInfoMapper, RecycleBinInfo> implements IRecycleBinInfoService {
+
+    private final RecycleBinInfoMapper recycleBinInfoMapper;
+
+    private final JdbcTemplate jdbcTemplate;
+
+    private final BladeRedis bladeRedis;
+
+    private final IInformationQueryService informationQueryService;
+
+    private final static String BLADE_RECYCLE_USER_CACHE_KEY = "blade:recycle:user:cache:";
+
+    @Override
+    public IPage<RecycleBinInfo> selectPage(RecycleBinInfoVO recycleBinInfoVO) {
+        IPage<RecycleBinInfo> iPage = Condition.getPage(recycleBinInfoVO);
+        if (recycleBinInfoVO.getStartTime() != null) {
+            if (recycleBinInfoVO.getStartTime().trim().matches("^\\d{4}-\\d{2}-\\d{2}$")) {
+                recycleBinInfoVO.setStartTime(recycleBinInfoVO.getStartTime().trim() + " 00:00:00");
+            } else {
+                recycleBinInfoVO.setStartTime(null);
+            }
+        }
+        if (recycleBinInfoVO.getEndTime() != null) {
+            if (recycleBinInfoVO.getEndTime().trim().matches("^\\d{4}-\\d{2}-\\d{2}$")) {
+                recycleBinInfoVO.setEndTime(recycleBinInfoVO.getEndTime().trim() + " 23:59:59");
+            } else {
+                recycleBinInfoVO.setEndTime(null);
+            }
+        }
+        return this.recycleBinInfoMapper.page(iPage, recycleBinInfoVO);
+    }
+
+    @Override
+    public Collection<UserVO2> queryUser(Long contractId, Integer isRecycleBin, String name) {
+        String str = bladeRedis.get(BLADE_RECYCLE_USER_CACHE_KEY + contractId);
+        List<UserVO2> userVOs = getUserVOs(str);
+        List<UserVO2> userVOs1;
+        if (isRecycleBin == 1) {
+            userVOs1 = getUpdateUser(contractId);
+        } else {
+            userVOs1 = new ArrayList<>();
+        }
+        if (userVOs.isEmpty()) {
+            List<RecycleBinInfo> list = this.list(Wrappers.<RecycleBinInfo>lambdaQuery()
+                    .select(RecycleBinInfo::getCreateUser, RecycleBinInfo::getCreateUserName)
+                    .eq(RecycleBinInfo::getContractId, contractId).eq(RecycleBinInfo::getDelType, 2).eq(RecycleBinInfo::getStatus, 0)
+                    .groupBy(Arrays.asList(RecycleBinInfo::getCreateUser,RecycleBinInfo::getCreateUserName)));
+            if (list != null && !list.isEmpty()) {
+                list.forEach(item -> {
+                    UserVO2 vo2 = new UserVO2();
+                    vo2.setId(item.getCreateUser());
+                    vo2.setName(item.getCreateUserName());
+                    userVOs.add(vo2);
+                });
+                bladeRedis.set(BLADE_RECYCLE_USER_CACHE_KEY + contractId, JSON.toJSONString(userVOs));
+                bladeRedis.expire(BLADE_RECYCLE_USER_CACHE_KEY + contractId, 60 * 60);
+            }
+        }
+        if (!userVOs.isEmpty()) {
+            if (name != null && !name.isEmpty()) {
+                List<UserVO2> collect = userVOs.stream().filter(item -> item.getName() != null && item.getName().contains(name)).collect(Collectors.toList());
+                Set<UserVO2> set = new HashSet<>(collect);
+                set.addAll(userVOs1.stream().filter(item -> item.getName() != null && item.getName().contains(name)).collect(Collectors.toList()));
+                return set;
+            }
+            Set<UserVO2> set = new HashSet<>(userVOs);
+            set.addAll(userVOs1);
+            return set;
+        }
+        return userVOs1;
+    }
+
+    @Override
+    public Collection<RecycleBinInfo> queryOperation(String ids) {
+        if (ids == null || ids.isEmpty()) {
+            return new ArrayList<>();
+        }
+        String[] split = ids.split(",");
+        Set<Long> set = Arrays.stream(split).filter(StringUtil::isNumeric).map(Long::parseLong).collect(Collectors.toSet());
+        if (set.isEmpty()) {
+            return new ArrayList<>();
+        }
+        return this.baseMapper.queryOperation(set);
+    }
+
+    @Override
+    public Boolean saveRecycleBinInfoByWbsTreeContract(String ids, String rootIds) {
+        if (ids == null || ids.isEmpty()) {
+            return true;
+        }
+        List<WbsTreeContract> query = jdbcTemplate.query("select * from m_wbs_tree_contract where p_key_id in ( " + ids + ") and is_deleted = 1 and type = 1", new BeanPropertyRowMapper<>(WbsTreeContract.class));
+        if (query.isEmpty()) {
+            return true;
+        }
+
+        List<String> parentIds = new ArrayList<>();
+        Map<Long, WbsTreeContract> rootMap = new HashMap<>();
+        {
+            Map<Long, WbsTreeContract> tempMap = query.stream().collect(Collectors.toMap(WbsTreeContract::getPKeyId, item -> item));
+            for (WbsTreeContract contract : query) {
+                String ancestorsPId = contract.getAncestorsPId();
+                if (StringUtil.hasText(ancestorsPId)) {
+                    String[] split = ancestorsPId.split(",");
+                    WbsTreeContract root = null;
+                    for (String s : split) {
+                        if (StringUtil.isNumeric(s)) {
+                            parentIds.add(s);
+                            WbsTreeContract wbsTreeContract = tempMap.get(Long.parseLong(s));
+                            if (root == null && wbsTreeContract != null) {
+                                root = wbsTreeContract;
+                            }
+                        }
+                    }
+                    if (root != null) {
+                        rootMap.put(contract.getPKeyId(), root);
+                    }
+                }
+            }
+        }
+        List<WbsTreeContract> parentContracts;
+        if (!parentIds.isEmpty()) {
+            parentContracts = jdbcTemplate.query("select * from m_wbs_tree_contract where p_key_id in ( " + String.join(",", parentIds) + ") and is_deleted = 0 and type = 1", new BeanPropertyRowMapper<>(WbsTreeContract.class));
+        } else {
+            parentContracts = new ArrayList<>();
+        }
+
+        Map<Long, WbsTreeContract> parentMap = parentContracts.stream().collect(Collectors.toMap(WbsTreeContract::getPKeyId, item -> item));
+        String contractId = query.get(0).getContractId();
+        List<InformationQuery> queries = informationQueryService.list(Wrappers.<InformationQuery>lambdaQuery().select(InformationQuery::getWbsId, InformationQuery::getClassify, InformationQuery::getName)
+                .eq(InformationQuery::getContractId, contractId).in(InformationQuery::getWbsId, ids).in(InformationQuery::getClassify, 1, 2));
+        Map<String, List<InformationQuery>> map = queries.stream().collect(Collectors.groupingBy(item -> item.getWbsId() + "_" + item.getClassify()));
+        List<ContractInfo> contractInfos = jdbcTemplate.query("select * from m_contract_info where id = ( " + contractId + ") and is_deleted = 0", new BeanPropertyRowMapper<>(ContractInfo.class));
+        ContractInfo contractInfo;
+        if (contractInfos.isEmpty()) {
+            contractInfo = new ContractInfo();
+        } else {
+            contractInfo = contractInfos.get(0);
+        }
+        long operationId = SnowFlakeUtil.getId();
+        List<RecycleBinInfo> recycleBinInfos = new ArrayList<>(query.size());
+        for (WbsTreeContract contract : query) {
+            RecycleBinInfo info = new RecycleBinInfo();
+            info.setId(SnowFlakeUtil.getId());
+            info.setContractId(Long.parseLong(contract.getContractId()));
+            info.setProjectId(Long.parseLong(contract.getProjectId()));
+            info.setOperationId(operationId + "");
+            info.setDelType(2);
+            info.setCreateUserName(AuthUtil.getNickName());
+            info.setCreateUser(AuthUtil.getUserId());
+            info.setOperationTime(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
+            info.setDelId(contract.getPKeyId());
+            info.setBusinessId(contract.getAncestorsPId());
+
+            WbsTreeContract delRoot = rootMap.get(contract.getPKeyId());
+            if (delRoot != null) {
+                info.setDelRootId(delRoot.getPKeyId());
+                info.setDelRootName(StringUtil.hasText(delRoot.getFullName()) ? delRoot.getFullName() : delRoot.getNodeName());
+            }
+            String ancestorsPId = contract.getAncestorsPId();
+            StringBuilder sb = new StringBuilder();
+            if (StringUtil.hasText(ancestorsPId)) {
+                String[] split = ancestorsPId.split(",");
+                for (String s : split) {
+                    if (StringUtil.isNumeric(s)) {
+                        WbsTreeContract parent = parentMap.get(Long.parseLong(s));
+                        if (parent != null) {
+                            if (parent.getPId() == null || parent.getPId() == 0) {
+                                sb.append(contractInfo.getContractName()).append("/");
+                            } else {
+                                sb.append(StringUtil.hasText(parent.getFullName()) ? parent.getFullName() : parent.getNodeName()).append("/");
+                            }
+                            if (info.getDelRootId() == null) {
+                                WbsTreeContract temp = rootMap.get(parent.getPKeyId());
+                                if (temp != null) {
+                                    info.setDelRootId(temp.getPKeyId());
+                                    info.setDelRootName(StringUtil.hasText(temp.getFullName()) ? temp.getFullName() : temp.getNodeName());
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            if (info.getDelRootId() == null) {
+                info.setDelRootId(info.getDelId());
+                info.setDelRootName(StringUtil.hasText(contract.getFullName()) ? contract.getFullName() : contract.getNodeName());
+            }
+            info.setPosition(sb + (StringUtil.hasText(contract.getFullName()) ? contract.getFullName() : contract.getNodeName()));
+            List<InformationQuery> queryList = map.get(contract.getPKeyId() + "_1");
+            if (queryList != null && !queryList.isEmpty()) {
+                info.setFileName(queryList.get(0).getName());
+                info.setIsData(1);
+            }
+            queryList = map.get(contract.getPKeyId() + "_2");
+            if (queryList != null && !queryList.isEmpty()) {
+                info.setJlFileName(queryList.get(0).getName());
+                info.setIsData(1);
+            }
+            recycleBinInfos.add( info);
+        }
+        this.saveBatch(recycleBinInfos);
+        bladeRedis.del(BLADE_RECYCLE_USER_CACHE_KEY + contractId + "_1", BLADE_RECYCLE_USER_CACHE_KEY + contractId);
+        return true;
+    }
+
+    private List<UserVO2> getUpdateUser(Long contractId) {
+        String key = BLADE_RECYCLE_USER_CACHE_KEY + contractId + "_1";
+        String str1 = bladeRedis.get(key);
+        List<UserVO2> userVOs1 = getUserVOs(str1);
+        if (!userVOs1.isEmpty()) {
+            return userVOs1;
+        }
+        List<RecycleBinInfo> list = this.list(Wrappers.<RecycleBinInfo>lambdaQuery()
+                .select(RecycleBinInfo::getUpdateUser, RecycleBinInfo::getUpdateUserName)
+                .eq(RecycleBinInfo::getContractId, contractId).eq(RecycleBinInfo::getDelType, 2).eq(RecycleBinInfo::getStatus, 1)
+                .groupBy(Arrays.asList(RecycleBinInfo::getUpdateUser,RecycleBinInfo::getUpdateUserName)));
+        if (list != null && !list.isEmpty()) {
+            list.forEach(item -> {
+                UserVO2 vo2 = new UserVO2();
+                vo2.setId(item.getUpdateUser());
+                vo2.setName(item.getUpdateUserName());
+                userVOs1.add(vo2);
+            });
+            bladeRedis.set(key, JSON.toJSONString(userVOs1));
+            bladeRedis.expire(key, 60 * 60);
+        }
+        return userVOs1;
+    }
+    private List<UserVO2> getUserVOs(String str) {
+        if (str != null) {
+            try {
+                List<UserVO2> userVO2s = JSON.parseArray(str, UserVO2.class);
+                if (userVO2s != null && !userVO2s.isEmpty()) {
+                    return userVO2s;
+                }
+            } catch (Exception e) {
+                log.warn("从缓存中获取用户信息失败,error msg:" + e.getMessage());
+            }
+        }
+        return new ArrayList<>();
+    }
+
+    public void sync() {
+        List<ContractInfo> contractInfos = jdbcTemplate.query("select id,contract_name from m_contract_info where is_deleted = 0 and p_id in (select id from m_project_info where is_deleted = 0)", new BeanPropertyRowMapper<>(ContractInfo.class));
+        List<User> users = jdbcTemplate.query("select * from blade_user", new BeanPropertyRowMapper<>(User.class));
+        Map<Long, User> userMap = users.stream().collect(Collectors.toMap(User::getId, item -> item));
+        for (ContractInfo contractInfo : contractInfos) {
+            List<RecycleBin> recycleBins = jdbcTemplate.query("select * from u_recycle_bin where del_type = 2 and contract_id = " + contractInfo.getId(), new BeanPropertyRowMapper<>(RecycleBin.class));
+            if (recycleBins.isEmpty()) {
+                continue;
+            }
+            Map<Long, WbsTreeContract> treeContractMap = new TreeMap<>();
+            for (RecycleBin recycleBin : recycleBins) {
+                String businessId = recycleBin.getBusinessId();
+                String[] split1 = businessId.split(",");
+                String ids = Arrays.stream(split1).filter(StringUtil::isNumeric).collect(Collectors.joining(","));
+                if (StringUtil.isEmpty(ids)) {
+                    continue;
+                }
+                List<WbsTreeContract> query = jdbcTemplate.query("select * from m_wbs_tree_contract where p_key_id in ( " + ids + ") and type = 1", new BeanPropertyRowMapper<>(WbsTreeContract.class));
+                if (query.isEmpty()) {
+                    continue;
+                }
+                List<String> parentIds = new ArrayList<>();
+                for (WbsTreeContract contract : query) {
+                    String ancestorsPId = contract.getAncestorsPId();
+                    if (StringUtil.hasText(ancestorsPId)) {
+                        String[] split = ancestorsPId.split(",");
+                        for (String s : split) {
+                            if (StringUtil.isNumeric(s)) {
+                                long l = Long.parseLong(s);
+                                if (treeContractMap.containsKey(l)) {
+                                    continue;
+                                }
+                                parentIds.add(s);
+                            }
+                        }
+                    }
+                    treeContractMap.put(contract.getPKeyId(), contract);
+                }
+                List<WbsTreeContract> parentContracts;
+                if (!parentIds.isEmpty()) {
+                    parentContracts = jdbcTemplate.query("select * from m_wbs_tree_contract where p_key_id in ( " + String.join(",", parentIds) + ") and is_deleted = 0 and type = 1", new BeanPropertyRowMapper<>(WbsTreeContract.class));
+                } else {
+                    parentContracts = new ArrayList<>();
+                }
+                if (!parentContracts.isEmpty()) {
+                    parentContracts.forEach(item -> treeContractMap.put(item.getPKeyId(), item));
+                }
+                List<InformationQuery> queries = informationQueryService.list(Wrappers.<InformationQuery>lambdaQuery().select(InformationQuery::getWbsId, InformationQuery::getClassify, InformationQuery::getName)
+                        .eq(InformationQuery::getContractId, contractInfo.getId()).in(InformationQuery::getWbsId, ids).in(InformationQuery::getClassify, 1, 2));
+                Map<String, List<InformationQuery>> map = queries.stream().collect(Collectors.groupingBy(item -> item.getWbsId() + "_" + item.getClassify()));
+                long operationId = SnowFlakeUtil.getId();
+                List<RecycleBinInfo> recycleBinInfos = new ArrayList<>(query.size());
+                for (WbsTreeContract contract : query) {
+                    RecycleBinInfo info = new RecycleBinInfo();
+                    info.setId(SnowFlakeUtil.getId());
+                    info.setContractId(Long.parseLong(contract.getContractId()));
+                    info.setProjectId(Long.parseLong(contract.getProjectId()));
+                    info.setOperationId(operationId + "");
+                    info.setDelType(2);
+                    info.setCreateUserName(recycleBin.getCreateUserName());
+                    info.setCreateUser(recycleBin.getCreateUser());
+                    info.setCreateTime(recycleBin.getCreateTime());
+                    info.setOperationTime(recycleBin.getOperationTime());
+                    info.setDelId(contract.getPKeyId());
+                    info.setBusinessId(contract.getAncestorsPId());
+                    if (recycleBin.getIsDeleted() == 1) {
+                        info.setStatus(1);
+                        info.setUpdateUser(recycleBin.getUpdateUser());
+                        info.setUpdateTime(recycleBin.getUpdateTime());
+                        User user = userMap.get(recycleBin.getUpdateUser());
+                        info.setUpdateUserName(user.getName());
+                        info.setUpdateTime(recycleBin.getUpdateTime());
+                    }
+
+                    String ancestorsPId = contract.getAncestorsPId();
+                    StringBuilder sb = new StringBuilder();
+                    if (StringUtil.hasText(ancestorsPId)) {
+                        String[] split = ancestorsPId.split(",");
+                        for (String s : split) {
+                            if (StringUtil.isNumeric(s)) {
+                                WbsTreeContract parent = treeContractMap.get(Long.parseLong(s));
+                                if (parent != null) {
+                                    if (parent.getPId() == null || parent.getPId() == 0) {
+                                        sb.append(contractInfo.getContractName()).append("/");
+                                    } else {
+                                        sb.append(StringUtil.hasText(parent.getFullName()) ? parent.getFullName() : parent.getNodeName()).append("/");
+                                    }
+                                }
+                            }
+                        }
+                    }
+                    if (info.getDelRootId() == null) {
+                        info.setDelRootId(info.getDelId());
+                        info.setDelRootName(StringUtil.hasText(contract.getFullName()) ? contract.getFullName() : contract.getNodeName());
+                    }
+                    info.setPosition(sb + (StringUtil.hasText(contract.getFullName()) ? contract.getFullName() : contract.getNodeName()));
+                    List<InformationQuery> queryList = map.get(contract.getPKeyId() + "_1");
+                    if (queryList != null && !queryList.isEmpty()) {
+                        info.setFileName(queryList.get(0).getName());
+                        info.setIsData(1);
+                    }
+                    queryList = map.get(contract.getPKeyId() + "_2");
+                    if (queryList != null && !queryList.isEmpty()) {
+                        info.setJlFileName(queryList.get(0).getName());
+                        info.setIsData(1);
+                    }
+                    recycleBinInfos.add( info);
+                }
+                this.saveBatch(recycleBinInfos);
+            }
+        }
+    }
+}

+ 124 - 17
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TaskServiceImpl.java

@@ -39,6 +39,7 @@ import org.springblade.core.tool.utils.Func;
 import org.springblade.core.tool.utils.ObjectUtil;
 import org.springblade.core.tool.utils.ResourceUtil;
 import org.springblade.evisa.feign.EVisaClient;
+import org.springblade.evisa.redissionUtil.DistributedRedisLock;
 import org.springblade.evisa.vo.EVisaTaskApprovalVO;
 import org.springblade.flow.core.constant.ProcessConstant;
 import org.springblade.flow.core.feign.IFlowClient;
@@ -622,7 +623,7 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
      * @throws FileNotFoundException
      */
     @Override
-    public void batchCompleteApprovalTask(List<TaskApprovalVO> taskApprovalVOS) {
+    public Boolean batchCompleteApprovalTask(List<TaskApprovalVO> taskApprovalVOS) {
         Long userId = AuthUtil.getUserId();
         String nickName = AuthUtil.getNickName();
         // 批量审批接口
@@ -669,7 +670,7 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
                         e.printStackTrace();
                     }
                 }
-                this.taskBatchService.saveBatch(taskList);
+                return this.taskBatchService.saveBatch(taskList);
             }else if (taskAppr.getFlag().equals("NO")){ //废除
                 Set<String> taskIds = taskApprovalVOS.stream().map(TaskApprovalVO::getTaskId).collect(Collectors.toSet());
                 List<Task> tasks = this.listByIds(taskIds);
@@ -762,8 +763,10 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
                     }
                 }
                 wbsTreeContractStatisticsClient.updateInformationQueryStatusByTaskId(String.join(",", taskIds));
+                return true;
             }
         }
+        return false;
     }
 
 
@@ -1565,11 +1568,20 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
             //这里发起的默认为普通流程
             task.setType(1);
             task.setStatus(1);
-            //保存附表信息
-            this.taskParallelService.saveBatch(taskParallelArray);
-
-            //保存主表数据
-            this.save(task);
+            try {
+                if (DistributedRedisLock.acquire("TaskService_StartApproval_" + task.getFormDataId(), 5)) {
+                    long count = this.count(Wrappers.<Task>lambdaQuery().eq(Task::getFormDataId, task.getFormDataId()).ne(Task::getStatus, 3));
+                    if (count > 0) {
+                        return false;
+                    }
+                    //保存附表信息
+                    this.taskParallelService.saveBatch(taskParallelArray);
+                    //保存主表数据
+                    this.save(task);
+                }
+            } finally {
+                DistributedRedisLock.release("TaskService_StartApproval_" + task.getFormDataId());
+            }
         }
         return true;
     }
@@ -2024,15 +2036,33 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
                     R result = new R();
                     jdbcTemplate.execute("DELETE from u_task_batch where json_data like '%"+task.getId()+"%'");
                     boolean b = false;
+
+                    //是否恢复pdf
+                    Boolean isRestorePdf = false;
+                    //当前节点的电签pdf
+                    String eVisaPdfUrl = "";
+                    String pdfUrl = "";
                     if(type == 1){
+                        //当前节点的电签pdf
+                        InformationQuery byId = informationQueryService.getById(task.getFormDataId());
+                        if(byId != null){
+                            eVisaPdfUrl = byId.getEVisaPdfUrl();
+                            pdfUrl = byId.getPdfUrl();
+                        }
                          b = informationQueryService.update(new LambdaUpdateWrapper<InformationQuery>()
                                 .eq(InformationQuery::getId, task.getFormDataId())
                                 .set(InformationQuery::getEVisaPdfUrl, null)
-//                                .set(InformationQuery::getPdfUrl, null)
+                                .set(InformationQuery::getPdfUrl, null)
                          );
                     }else {
                         if(task.getApprovalType()==3){
-                           b=contractLogService.update(new LambdaUpdateWrapper<ContractLog>()
+                            //当前节点的电签pdf
+                            ContractLog byId = contractLogService.getById(task.getFormDataId());
+                            if(byId != null){
+                                eVisaPdfUrl = byId.getEVisaPdfUrl();
+                            }
+
+                            b=contractLogService.update(new LambdaUpdateWrapper<ContractLog>()
                                .eq(ContractLog::getId,task.getFormDataId())
                                .set(ContractLog::getEVisaPdfUrl,null));
                            if(!b){
@@ -2040,6 +2070,11 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
                                return;
                            }
                         }else {
+                            //当前节点的电签pdf
+                            InformationQuery byId = informationQueryService.getById(task.getFormDataId());
+                            if(byId != null){
+                                eVisaPdfUrl = byId.getEVisaPdfUrl();
+                            }
                             b = informationQueryService.update(new LambdaUpdateWrapper<InformationQuery>()
                                 .eq(InformationQuery::getId, task.getFormDataId())
                                 .set(InformationQuery::getEVisaPdfUrl, null));
@@ -2060,7 +2095,15 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
                             String sql="select type from u_information_query where id="+task.getFormDataId();
                             Integer InformationType = jdbcTemplate.queryForObject(sql, new SingleColumnRowMapper<>(Integer.class));
                             if(InformationType==1){
-                                result = this.saveNodePdf(typeMap.get(task.getFormDataId()), queryMap.get(task.getFormDataId()), contractId, projectId, header);
+                                try {
+                                    result = this.saveNodePdf(typeMap.get(task.getFormDataId()), queryMap.get(task.getFormDataId()), contractId, projectId, header);
+                                    //恢复pdf
+                                    if(result.getCode()!=200){
+                                        isRestorePdf = true;
+                                    }
+                                } catch (Exception e) {
+                                    isRestorePdf = true;
+                                }
                             }else {
                                 TrialResignDto dto=new TrialResignDto();
                                 dto.setType(1);
@@ -2080,14 +2123,23 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
                             String sql="SELECT * from u_entrust_info where id=(select wbs_id from u_information_query where id="+task.getFormDataId()+")";
                             EntrustInfo info = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(EntrustInfo.class));
                             ReSigningEntrustDto dto=new ReSigningEntrustDto(info.getId().toString(),task.getId().toString(),contractId,info.getNodeId(),2,1);
-                            result=excelTabClient.saveReEntrustTabData(dto,header);
-                            if(result.getCode()==200){
-                                if(result.getData()!=null){
-                                    informationQueryService.update(new LambdaUpdateWrapper<InformationQuery>()
-                                        .eq(InformationQuery::getId, task.getFormDataId())
-                                        .set(InformationQuery::getPdfUrl,result.getData()));
+                            try {
+                                result=excelTabClient.saveReEntrustTabData(dto,header);
+                                if(result.getCode()==200){
+                                    if(result.getData()!=null){
+                                        informationQueryService.update(new LambdaUpdateWrapper<InformationQuery>()
+                                                .eq(InformationQuery::getId, task.getFormDataId())
+                                                .set(InformationQuery::getPdfUrl,result.getData()));
+                                    }
+                                }else{
+                                    //恢复pdf
+                                    isRestorePdf = true;
                                 }
+                            } catch (Exception e) {
+                                //恢复pdf
+                                isRestorePdf = true;
                             }
+
                         }
                         long endTime_1 = System.currentTimeMillis();
                         long executionTime_1 = endTime_1 - startTime_1;
@@ -2098,6 +2150,16 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
                         }
                         result.setData("成功");
                     }
+                    //恢复pdf 并且 恢复电签pdf
+                    if(isRestorePdf){
+                        informationQueryService.update(new LambdaUpdateWrapper<InformationQuery>()
+                                .eq(InformationQuery::getId, task.getFormDataId())
+                                .set(InformationQuery::getPdfUrl, pdfUrl)
+                                .set(InformationQuery::getEVisaPdfUrl, eVisaPdfUrl));
+                        continue;
+                    }
+
+
                     //重新电签
                     if (result != null && ("成功".equals(result.getData())||200==result.getCode())) {
                         List<TaskApprovalVO> taskApprovalVOS = new ArrayList<>();
@@ -2119,12 +2181,57 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
                         }
                         long startTime_2 = System.currentTimeMillis();
                         if(taskApprovalVOS!=null && taskApprovalVOS.size()>=1){
-                            this.batchCompleteApprovalTask(taskApprovalVOS);
+                            boolean b1 = this.batchCompleteApprovalTask(taskApprovalVOS);
+                            //如果失败 恢复电签
+                            if (!b1) {
+                                if (type == 1) {
+                                    //当前节点的电签pdf
+                                    informationQueryService.update(new LambdaUpdateWrapper<InformationQuery>()
+                                            .eq(InformationQuery::getId, task.getFormDataId())
+                                            .set(InformationQuery::getEVisaPdfUrl, eVisaPdfUrl)
+                                    );
+                                } else {
+                                    if (task.getApprovalType() == 3) {
+                                        contractLogService.update(new LambdaUpdateWrapper<ContractLog>()
+                                                .eq(ContractLog::getId, task.getFormDataId())
+                                                .set(ContractLog::getEVisaPdfUrl, eVisaPdfUrl));
+                                        if (!b) {
+                                            jdbcTemplate.update("update u_task set is_deleted=1 where id=" + task.getId());
+                                            return;
+                                        }
+                                    } else {
+                                        informationQueryService.update(new LambdaUpdateWrapper<InformationQuery>()
+                                                .eq(InformationQuery::getId, task.getFormDataId())
+                                                .set(InformationQuery::getEVisaPdfUrl, eVisaPdfUrl));
+                                    }
+                                }
+                            }
                         }
                         long endTime_2 = System.currentTimeMillis();
                         long executionTime_2 = endTime_2 - startTime_2;
                         log.info("batchCompleteApprovalTask执行时间:" + executionTime_2 + " 毫秒");
                     } else {
+                        if (type == 1) {
+                            //当前节点的电签pdf
+                            informationQueryService.update(new LambdaUpdateWrapper<InformationQuery>()
+                                    .eq(InformationQuery::getId, task.getFormDataId())
+                                    .set(InformationQuery::getEVisaPdfUrl, eVisaPdfUrl)
+                            );
+                        } else {
+                            if (task.getApprovalType() == 3) {
+                                contractLogService.update(new LambdaUpdateWrapper<ContractLog>()
+                                        .eq(ContractLog::getId, task.getFormDataId())
+                                        .set(ContractLog::getEVisaPdfUrl, eVisaPdfUrl));
+                                if (!b) {
+                                    jdbcTemplate.update("update u_task set is_deleted=1 where id=" + task.getId());
+                                    return;
+                                }
+                            } else {
+                                informationQueryService.update(new LambdaUpdateWrapper<InformationQuery>()
+                                        .eq(InformationQuery::getId, task.getFormDataId())
+                                        .set(InformationQuery::getEVisaPdfUrl, eVisaPdfUrl));
+                            }
+                        }
                         //修改重签状态为保存PDF失败
                         this.taskParallelService.update(Wrappers.<TaskParallel>lambdaUpdate()
                                 .set(TaskParallel::getEVisaContent, "重新保存PDF失败")

+ 25 - 0
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TrialCyAccessoriesServiceImpl.java

@@ -0,0 +1,25 @@
+package org.springblade.business.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springblade.business.entity.TrialCyAccessories;
+import org.springblade.business.service.TrialCyAccessoriesService;
+import org.springblade.business.mapper.TrialCyAccessoriesMapper;
+import org.springframework.stereotype.Service;
+
+/**
+* @author LHB
+* @description 针对表【u_trial_cy_accessories(成渝-附件信息)】的数据库操作Service实现
+* @createDate 2025-08-04 14:39:16
+*/
+@Service
+public class TrialCyAccessoriesServiceImpl extends ServiceImpl<TrialCyAccessoriesMapper, TrialCyAccessories>
+    implements TrialCyAccessoriesService {
+    @Override
+    public Boolean clearTrialAssociation(Long nodeId, Long recordId) {
+        return baseMapper.clearTrialAssociation(nodeId,recordId);
+    }
+}
+
+
+
+

+ 29 - 0
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TrialCyFinishTestReportServiceImpl.java

@@ -0,0 +1,29 @@
+package org.springblade.business.service.impl;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springblade.business.entity.TrialCyFinishTestReport;
+import org.springblade.business.service.TrialCyFinishTestReportService;
+import org.springblade.business.mapper.TrialCyFinishTestReportMapper;
+import org.springblade.business.vo.ThirdReportVo;
+import org.springblade.business.vo.TrialCyThirdReportQueryVo;
+import org.springframework.stereotype.Service;
+
+/**
+* @author LHB
+* @description 针对表【u_trial_cy_finish_test_report(成渝-获取标段已完成(已签章完成)的检测报告)】的数据库操作Service实现
+* @createDate 2025-08-01 09:05:03
+*/
+@Service
+public class TrialCyFinishTestReportServiceImpl extends ServiceImpl<TrialCyFinishTestReportMapper, TrialCyFinishTestReport>
+    implements TrialCyFinishTestReportService {
+
+    @Override
+    public Page<ThirdReportVo> myPage(Page<ThirdReportVo> page, TrialCyThirdReportQueryVo queryVo) {
+        return baseMapper.myPage(page,queryVo);
+    }
+}
+
+
+
+

+ 86 - 0
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TrialCyServiceImpl.java

@@ -0,0 +1,86 @@
+package org.springblade.business.service.impl;
+
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import org.springblade.business.entity.TrialCyFinishTestReport;
+import org.springblade.business.entity.TrialCyTestType;
+import org.springblade.business.entity.TrialCyThirdReport;
+import org.springblade.business.service.*;
+import org.springblade.business.vo.ThirdReportVo;
+import org.springblade.business.vo.TrialCyThirdReportQueryVo;
+import org.springblade.core.tool.utils.StringUtil;
+import org.springblade.manager.entity.ContractInfo;
+import org.springblade.manager.entity.ProjectInfo;
+import org.springblade.manager.feign.ContractClient;
+import org.springblade.manager.feign.ProjectClient;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * 成渝数据获取
+ *
+ * @author LHB
+ */
+@Service
+public class TrialCyServiceImpl implements TrialCyService {
+    @Resource
+    private TrialCyAccessoriesService trialCyAccessoriesService;
+    @Resource
+    private TrialCyFinishTestReportService trialCyFinishTestReportService;
+    @Resource
+    private TrialCyTestTypeService trialCyTestTypeService;
+    @Resource
+    private TrialCyThirdReportService trialCyThirdReportService;
+
+    @Resource
+    private ProjectClient projectClient;
+    @Resource
+    private ContractClient contractClient;
+
+    @Override
+    public Boolean isCyAndTestModule(Long projectId, Long contractId) {
+        ProjectInfo byId = projectClient.getById(String.valueOf(projectId));
+        if (!"cqcyfx".equals(byId.getProjectNumber())) {
+            return false;
+        }
+        ContractInfo contractById = contractClient.getContractById(contractId);
+        return contractById.getIsTestModule() == 0;
+    }
+
+    @Override
+    public List<TrialCyTestType> getTree(Long projectId, String parentId) {
+        List<TrialCyTestType> list = trialCyTestTypeService.getTree(projectId, parentId);
+        return list;
+    }
+
+    @Override
+    public Page<ThirdReportVo> getTrialDetectionReport(TrialCyThirdReportQueryVo queryVo) {
+        TrialCyTestType byId = trialCyTestTypeService.getById(queryVo.getNodeId());
+        if(StringUtils.isBlank(byId.getId())){
+            return new Page<>();
+        }
+        queryVo.setNodeId(Long.valueOf(byId.getId()));
+        Page<ThirdReportVo> page = trialCyFinishTestReportService.myPage(new Page<ThirdReportVo>(queryVo.getCurrent(), queryVo.getSize()),queryVo);
+        return page;
+    }
+
+    @Override
+    public Page<ThirdReportVo> getThirdReport(TrialCyThirdReportQueryVo queryVo) {
+        TrialCyTestType byId = trialCyTestTypeService.getById(queryVo.getNodeId());
+        if(StringUtils.isBlank(byId.getId())){
+            return new Page<>();
+        }
+        queryVo.setNodeId(Long.valueOf(byId.getId()));
+        Page<ThirdReportVo> page = trialCyThirdReportService.myPage(new Page<ThirdReportVo>(queryVo.getCurrent(), queryVo.getSize()), queryVo);
+        return page;
+    }
+
+    @Override
+    public Boolean clearTrialAssociation(Long nodeId, Long recordId) {
+        return trialCyAccessoriesService.clearTrialAssociation(nodeId, recordId);
+    }
+}

+ 28 - 0
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TrialCyTestTypeServiceImpl.java

@@ -0,0 +1,28 @@
+package org.springblade.business.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springblade.business.entity.TrialCyTestType;
+import org.springblade.business.service.TrialCyTestTypeService;
+import org.springblade.business.mapper.TrialCyTestTypeMapper;
+import org.springframework.stereotype.Service;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+* @author LHB
+* @description 针对表【u_trial_cy_test_type(成渝-试验检测树)】的数据库操作Service实现
+* @createDate 2025-08-01 09:05:07
+*/
+@Service
+public class TrialCyTestTypeServiceImpl extends ServiceImpl<TrialCyTestTypeMapper, TrialCyTestType>
+    implements TrialCyTestTypeService {
+    @Override
+    public List<TrialCyTestType> getTree(Long projectId, String parentId) {
+        return baseMapper.getTree(projectId, parentId);
+    }
+}
+
+
+
+

+ 29 - 0
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TrialCyThirdReportServiceImpl.java

@@ -0,0 +1,29 @@
+package org.springblade.business.service.impl;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springblade.business.entity.TrialCyThirdReport;
+import org.springblade.business.service.TrialCyThirdReportService;
+import org.springblade.business.mapper.TrialCyThirdReportMapper;
+import org.springblade.business.vo.ThirdReportVo;
+import org.springblade.business.vo.TrialCyThirdReportQueryVo;
+import org.springframework.stereotype.Service;
+
+/**
+* @author LHB
+* @description 针对表【u_trial_cy_third_report(成渝-已上传的外委检测报告/第三方检测报告/上传报告)】的数据库操作Service实现
+* @createDate 2025-08-01 09:05:10
+*/
+@Service
+public class TrialCyThirdReportServiceImpl extends ServiceImpl<TrialCyThirdReportMapper, TrialCyThirdReport>
+    implements TrialCyThirdReportService {
+
+    @Override
+    public Page<ThirdReportVo> myPage(Page<ThirdReportVo> page, TrialCyThirdReportQueryVo queryVo) {
+        return baseMapper.myPage(page, queryVo);
+    }
+}
+
+
+
+

+ 22 - 1
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TrialMaterialMobilizationServiceImpl.java

@@ -158,7 +158,24 @@ public class TrialMaterialMobilizationServiceImpl extends BaseServiceImpl<TrialM
 
         IPage<TrialMaterialMobilizationVO> trialMaterialMobilizationVOIPage = TrialMaterialMobilizationWarpper.build().pageVO(pages);
         List<TrialMaterialMobilizationVO> records = trialMaterialMobilizationVOIPage.getRecords();
-        Map<String, String> fileMaps = jdbcTemplate.query("select link,original_name from blade_attach", new BeanPropertyRowMapper<>(Attach.class)).stream().collect(Collectors.toMap(Attach::getLink, Attach::getOriginalName, (key1, key2) -> key2));
+        StringBuilder links = new StringBuilder();
+        records.forEach(record -> {
+            if (StringUtil.hasText(record.getOtherAccessories())) {
+                links.append("'").append(record.getOtherAccessories()).append("',");
+            }
+            if (StringUtil.hasText(record.getProductionCertificate())) {
+                links.append("'").append(record.getProductionCertificate()).append("',");
+            }
+            if (StringUtil.hasText(record.getQualityInspectionReport())) {
+                links.append("'").append(record.getQualityInspectionReport()).append("',");
+            }
+        });
+        Map<String, String> fileMaps = new HashMap<>();
+        if (links.length() > 1) {
+            links.deleteCharAt(links.length() - 1);
+            fileMaps = jdbcTemplate.query("select link,original_name from blade_attach where link in (" + links + ")", new BeanPropertyRowMapper<>(Attach.class))
+                    .stream().collect(Collectors.toMap(Attach::getLink, Attach::getOriginalName, (key1, key2) -> key2));
+        }
         for (TrialMaterialMobilizationVO record : records) {
             for (User user : userList) {
                 if (user.getId().equals(record.getUserId())) {
@@ -504,6 +521,10 @@ public class TrialMaterialMobilizationServiceImpl extends BaseServiceImpl<TrialM
             return R.fail("所选数据均存在取样记录,不允许删除");
         }
         boolean b = super.deleteLogic(newIdList);
+        if(b){
+          String update="update u_trial_auto_number set is_deleted=1 where form_data_id in ("+ids+")";
+          jdbcTemplate.update(update);
+        }
         return  b?R.success("删除成功"):R.fail("删除失败");
     }
 }

+ 204 - 186
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TrialSelfInspectionRecordServiceImpl.java

@@ -27,9 +27,7 @@ import org.springblade.business.mapper.EntrustInfoMapper;
 import org.springblade.business.mapper.TrialMaterialMobilizationMapper;
 import org.springblade.business.mapper.TrialSampleInfoMapper;
 import org.springblade.business.mapper.TrialSelfInspectionRecordMapper;
-import org.springblade.business.service.IEntrustInfoService;
-import org.springblade.business.service.ITrialNumberRuleService;
-import org.springblade.business.service.ITrialSelfInspectionRecordService;
+import org.springblade.business.service.*;
 import org.springblade.business.utils.FileUtils;
 import org.springblade.business.utils.FileUtils2;
 import org.springblade.business.utils.StringSPUtils;
@@ -100,6 +98,9 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
     private final TrialDetectionDataServiceImpl trialDetectionDataService;
     private final IEntrustInfoService entrustInfoService;
     private final ITrialNumberRuleService trialNumberRuleService;
+    private final TrialCyThirdReportService trialCyThirdReportService;
+    private final TrialCyFinishTestReportService trialCyFinishTestReportService;
+    private final TrialCyAccessoriesService trialCyAccessoriesService;
 
     @Override
     public IPage<TrialSelfInspectionRecordVO> selfPage(IPage<TrialSelfInspectionRecord> page, TrialSelfInspectionRecordPageDTO dto) throws FileNotFoundException {
@@ -118,7 +119,7 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
                 List<EntrustInfo> entrustInfos = entrustInfoMapper.selectList(Wrappers.<EntrustInfo>lambdaQuery()
                         .like(EntrustInfo::getEntrustNo, dto.getQueryValue()));
                 List<Long> entrustIds;
-                if(CollectionUtil.isNotEmpty(entrustInfos)){
+                if (CollectionUtil.isNotEmpty(entrustInfos)) {
                     entrustIds = entrustInfos.stream().map(EntrustInfo::getId).collect(Collectors.toList());
                 } else {
                     entrustIds = null;
@@ -126,11 +127,11 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
 
                 queryWrapper.lambda().and(
                         wq ->
-                            wq.like(TrialSelfInspectionRecord::getTrialProjectName, dto.getQueryValue()).or()
-                                    .like(TrialSelfInspectionRecord::getRecordNo, dto.getQueryValue()).or()
-                                    .like(TrialSelfInspectionRecord::getReportNo, dto.getQueryValue()).or()
-                                    .like(TrialSelfInspectionRecord::getSpecificationNumber, dto.getQueryValue()).or()
-                                    .in(CollectionUtil.isNotEmpty(entrustIds),TrialSelfInspectionRecord::getEntrustId, entrustIds)
+                                wq.like(TrialSelfInspectionRecord::getTrialProjectName, dto.getQueryValue()).or()
+                                        .like(TrialSelfInspectionRecord::getRecordNo, dto.getQueryValue()).or()
+                                        .like(TrialSelfInspectionRecord::getReportNo, dto.getQueryValue()).or()
+                                        .like(TrialSelfInspectionRecord::getSpecificationNumber, dto.getQueryValue()).or()
+                                        .in(CollectionUtil.isNotEmpty(entrustIds), TrialSelfInspectionRecord::getEntrustId, entrustIds)
                 );
             }
             if (org.apache.commons.lang.StringUtils.isNotEmpty(dto.getStartTime()) && org.apache.commons.lang.StringUtils.isNotEmpty(dto.getEndTime())) {
@@ -144,7 +145,7 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
             if (org.apache.commons.lang.StringUtils.isNotEmpty(dto.getQueryStatus())) {
                 queryWrapper.lambda().eq(TrialSelfInspectionRecord::getDetectionResult, dto.getQueryStatus());
             }
-            if (dto.getSortType() !=  null) {
+            if (dto.getSortType() != null) {
                 if (dto.getSortType().equals("1")) {
                     queryWrapper.lambda().orderByAsc(TrialSelfInspectionRecord::getReportNo);
                 } else if (dto.getSortType().equals("2")) {
@@ -209,17 +210,17 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
                 }
                 //委托单名称 委托单编号
                 EntrustInfo entrustInfo = entrustInfoMapper.selectById(record.getEntrustId());
-                if (entrustInfo != null){
+                if (entrustInfo != null) {
                     record.setEntrustName(entrustInfo.getEntrustName());
                     record.setEntrustNo(entrustInfo.getEntrustNo());
                     //材料id不为空
-                     if(Func.isNotEmpty(entrustInfo.getSampleId())){
-                         TrialSampleInfo sampleInfo = trialSampleInfoMapper.selectById(entrustInfo.getSampleId());
-                         if (Func.isNotEmpty(sampleInfo)){
-                             record.setSpecificationNumber(sampleInfo.getSpecificationNumber());
-                             record.setSpecificationModel(sampleInfo.getSpecificationModel());
-                         }
-                     }
+                    if (Func.isNotEmpty(entrustInfo.getSampleId())) {
+                        TrialSampleInfo sampleInfo = trialSampleInfoMapper.selectById(entrustInfo.getSampleId());
+                        if (Func.isNotEmpty(sampleInfo)) {
+                            record.setSpecificationNumber(sampleInfo.getSpecificationNumber());
+                            record.setSpecificationModel(sampleInfo.getSpecificationModel());
+                        }
+                    }
                 }
                 if (record.getBaseInfo() != null && !record.getBaseInfo().isEmpty()) {
                     try {
@@ -310,7 +311,8 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
     }
 
     /**
-     *新增返回该试验材料报告关联的委托单pdf也拼接在后面
+     * 新增返回该试验材料报告关联的委托单pdf也拼接在后面
+     *
      * @param contractId
      * @param nodeId
      * @param type
@@ -318,7 +320,7 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
      * @throws FileNotFoundException
      */
     private String getMergePdfToTrialNew(Long contractId, Long nodeId, Integer type) throws FileNotFoundException {
-        String sql = "select pdf_url,e_visa_pdf_url from u_information_query where wbs_id='" + nodeId + "' and status in(0,1,2) and contract_id ='" + contractId + "' and classify = '" + type + "'" ;
+        String sql = "select pdf_url,e_visa_pdf_url from u_information_query where wbs_id='" + nodeId + "' and status in(0,1,2) and contract_id ='" + contractId + "' and classify = '" + type + "'";
         List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql);
         if (maps.size() >= 1) {
             Map<String, Object> stringObjectMap = maps.get(0);
@@ -330,11 +332,11 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
             }
             String entrustPdfUrl = "";
             //关联的委托单pdf
-            String sqlEntrust = "select entrust_id from u_trial_self_inspection_record where is_deleted = 0 and id = "+nodeId ;
+            String sqlEntrust = "select entrust_id from u_trial_self_inspection_record where is_deleted = 0 and id = " + nodeId;
             TrialSelfInspectionRecord record = jdbcTemplate.queryForObject(sqlEntrust, new BeanPropertyRowMapper<>(TrialSelfInspectionRecord.class));
-            if(ObjectUtil.isNotEmpty(record) && ObjectUtil.isNotEmpty(record.getEntrustId()) && record.getEntrustId() != 0){
+            if (ObjectUtil.isNotEmpty(record) && ObjectUtil.isNotEmpty(record.getEntrustId()) && record.getEntrustId() != 0) {
                 //优先查询带电签的,没有电签在查entrust_pdf
-                String sqlEntrustPdf = "SELECT COALESCE(entrust_e_pdf, entrust_pdf) AS pdf_url from u_entrust_info where is_deleted = 0 and id = "+record.getEntrustId();
+                String sqlEntrustPdf = "SELECT COALESCE(entrust_e_pdf, entrust_pdf) AS pdf_url from u_entrust_info where is_deleted = 0 and id = " + record.getEntrustId();
                 try {
                     entrustPdfUrl = jdbcTemplate.queryForObject(sqlEntrustPdf, String.class);
                 } catch (DataAccessException e) {
@@ -353,7 +355,7 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
                 //材料检测报告pdf
                 pdfList.add(pdfUrlTrialRawMaterial);
                 //委托单pdf
-                if(ObjectUtil.isNotEmpty(entrustPdfUrl)){
+                if (ObjectUtil.isNotEmpty(entrustPdfUrl)) {
                     pdfList.add(entrustPdfUrl);
                 }
                 String file_path = FileUtils.getSysLocalFileUrl();
@@ -375,10 +377,10 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
             }
             assert pdfUrl != null;
             //拼接委托单pdf
-            if(ObjectUtil.isNotEmpty(entrustPdfUrl)){
+            if (ObjectUtil.isNotEmpty(entrustPdfUrl)) {
                 List<String> pdfList = new ArrayList<>();
                 //试验原始pdf
-                if(pdfUrl!=null){
+                if (pdfUrl != null) {
                     pdfList.add(pdfUrl.toString());
                 }
                 //委托单pdf
@@ -398,8 +400,9 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
                         pdfUrl = bladeFile.getLink();
                         return pdfUrl.toString();
                     }
-            }}
-            if(ObjectUtil.isNotEmpty(pdfUrl)){
+                }
+            }
+            if (ObjectUtil.isNotEmpty(pdfUrl)) {
                 return pdfUrl.toString();
             }
         }
@@ -1137,21 +1140,21 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
         //------初始当前填报的表pKeyIds------
         this.initTrialTabIds(dto);
 
-        if(!this.judgingParameters(dto)){
-            //------初始编号信息------
-            this.initBuildNumber(dto);
-        }
+//        if (!this.judgingParameters(dto)) {
+//            //------初始编号信息------
+//            this.initBuildNumber(dto);
+//        }
         this.saveOrUpdate(dto);
+
         if (ObjectUtil.isNotEmpty(dto.getId())) {
             //------获取最新试验记录------
             TrialSelfInspectionRecord obj = baseMapper.selectById(dto.getId());
             //如果传递了编号就修改对应记录的值 以第一张表的数据为准
             this.updateRecordNoOrReportNo(obj, dto);
             //------编辑时记录表编号或报告单编号为Null的重新生成------
-            if(!this.judgingParameters(dto)){
-                this.reBuildNumber(obj, dto);
-            }
-
+//            if (!this.judgingParameters(dto)) {
+//                this.reBuildNumber(obj, dto);
+//            }
             //------保存实体表数据、试验记录信息、生成PDF------
             this.submitTrialData(obj, dto);
 
@@ -1164,31 +1167,30 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
             //------关联新增设备使用记录信息------
             this.trialDeviceUseService.addDeviceUseInfo(dto, obj.getId());
         }
-
         // ---- 修改样品单号信息 --------
-        if(dto!=null && Func.isNotEmpty(dto.getEntrustId())){
+        if (dto != null && Func.isNotEmpty(dto.getEntrustId())) {
             //修改项目节点基础信息
-            jdbcTemplate.update("update u_entrust_info set sample_status=4 where id ='"+dto.getEntrustId()+"'");
+            jdbcTemplate.update("update u_entrust_info set sample_status=4 where id ='" + dto.getEntrustId() + "'");
         }
         String[] strings = dto.getTableType().split(",");
-        if(StringUtils.isNotEmpty(dto.getRecordAutoNumber())||StringUtils.isNotEmpty(dto.getReportAutoNumber())){
-            if (dto.getOldRecordNumber()!=null&&dto.getOldRecordNumber().equals(dto.getRecordNo())||dto.getOldReportNumber()!=null&&dto.getOldReportNumber().equals(dto.getReportNo())) {
-                if(strings.length==1){
-                    if(strings[0].equals("1")){
-                        if(StringUtils.isNotEmpty(dto.getRecordAutoNumber())){
-                            trialNumberRuleService.checkSave(Long.valueOf(dto.getProjectId()),4,dto.getId(),dto.getRecordAutoNumber());
+        if (StringUtils.isNotEmpty(dto.getRecordAutoNumber()) || StringUtils.isNotEmpty(dto.getReportAutoNumber())) {
+            if (dto.getOldRecordNumber() != null && dto.getOldRecordNumber().equals(dto.getRecordNo()) || dto.getOldReportNumber() != null && dto.getOldReportNumber().equals(dto.getReportNo())) {
+                if (strings.length == 1) {
+                    if (strings[0].equals("1")) {
+                        if (StringUtils.isNotEmpty(dto.getRecordAutoNumber())) {
+                            trialNumberRuleService.checkSave(Long.valueOf(dto.getProjectId()), 4, dto.getId(), dto.getRecordAutoNumber());
                         }
-                    }else {
-                        if(StringUtils.isNotEmpty(dto.getReportAutoNumber())){
-                            trialNumberRuleService.checkSave(Long.valueOf(dto.getProjectId()),5,dto.getId(),dto.getReportAutoNumber());
+                    } else {
+                        if (StringUtils.isNotEmpty(dto.getReportAutoNumber())) {
+                            trialNumberRuleService.checkSave(Long.valueOf(dto.getProjectId()), 5, dto.getId(), dto.getReportAutoNumber());
                         }
                     }
-                }else {
-                    if(StringUtils.isNotEmpty(dto.getRecordAutoNumber())){
-                        trialNumberRuleService.checkSave(Long.valueOf(dto.getProjectId()),4,dto.getId(),dto.getRecordAutoNumber());
+                } else {
+                    if (StringUtils.isNotEmpty(dto.getRecordAutoNumber())) {
+                        trialNumberRuleService.checkSave(Long.valueOf(dto.getProjectId()), 4, dto.getId(), dto.getRecordAutoNumber());
                     }
-                    if(StringUtils.isNotEmpty(dto.getReportAutoNumber())){
-                        trialNumberRuleService.checkSave(Long.valueOf(dto.getProjectId()),5,dto.getId(),dto.getReportAutoNumber());
+                    if (StringUtils.isNotEmpty(dto.getReportAutoNumber())) {
+                        trialNumberRuleService.checkSave(Long.valueOf(dto.getProjectId()), 5, dto.getId(), dto.getReportAutoNumber());
                     }
                 }
             }
@@ -1198,53 +1200,55 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
 
     /**
      * 取到传入的表单中的报告编号或者记录编号 修改记录表中相应字段的值
+     *
      * @param obj
      * @param dto
      */
     private void updateRecordNoOrReportNo(TrialSelfInspectionRecord obj, TrialSelfInspectionRecordDTO dto) {
-            JSONArray dataArray = dto.getDataInfo().getJSONArray("orderList");
-            //获取第一张表的数据  编号以第一张表为准
-            List<JSONObject> dataList = dataArray.toJavaList(JSONObject.class);
-           // 根据 type 字段进行分组
-             Map<String, List<JSONObject>> groupedByType = dataList.stream()
-            .collect(Collectors.groupingBy(jsonObject -> jsonObject.getString("type")));
-          for (Map.Entry<String, List<JSONObject>> entry : groupedByType.entrySet()) {
-              List<JSONObject> jsonObjects = groupedByType.get(entry.getKey());
-              JSONObject   jsonObject = jsonObjects.get(0);
-              if(entry.getKey().equals("2")&&jsonObjects.size()>1){
-                  jsonObject = jsonObjects.get(1);
-              }
-              String pkeyId = jsonObject.getString("pkeyId");
-              String sql = "select * from m_wbs_tree_private where p_key_id =" + pkeyId;
-              WbsTreePrivate table = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(WbsTreePrivate.class));
-              String fileUrl = table.getHtmlUrl();
-              try {
-                  InputStream fileInputStream = FileUtils.getInputStreamByUrl(fileUrl);
-                  String htmlString = IoUtil.readToString(fileInputStream);
-                  htmlString = htmlString.replaceAll("placeholder", "placeholderxx");
-                  Document doc = Jsoup.parse(htmlString);
-                  // 查找所有具有 placeholderxx 属性的元素
-                  //表类型 1,9=记录表 2,10=报告单
-                  if(table.getTableType() == 9 || table.getTableType() == 1){
-                      //记录表  以第一张表为准
-                      this.updateRecordNoOrReportNo(dto, jsonObject, doc, "记录编 号:", "record_no");
-                      this.updateRecordNoOrReportNo(dto, jsonObject, doc, "记录编号:", "record_no");
-                  }else if(table.getTableType() == 10 || table.getTableType() == 2){
-                      //报告单
-                      this.updateRecordNoOrReportNo(dto,jsonObject,doc,"报告编号:","report_no");
-                      //  :不一样 一个中文一个英文
-                      this.updateRecordNoOrReportNo(dto,jsonObject,doc,"报告编号:","report_no");
-                  }
-              } catch (Exception e) {
-                  log.error(e.getMessage());
-              }
-          }
+        JSONArray dataArray = dto.getDataInfo().getJSONArray("orderList");
+        //获取第一张表的数据  编号以第一张表为准
+        List<JSONObject> dataList = dataArray.toJavaList(JSONObject.class);
+        // 根据 type 字段进行分组
+        Map<String, List<JSONObject>> groupedByType = dataList.stream()
+                .collect(Collectors.groupingBy(jsonObject -> jsonObject.getString("type")));
+        for (Map.Entry<String, List<JSONObject>> entry : groupedByType.entrySet()) {
+            List<JSONObject> jsonObjects = groupedByType.get(entry.getKey());
+            JSONObject jsonObject = jsonObjects.get(0);
+            if (entry.getKey().equals("2") && jsonObjects.size() > 1) {
+                jsonObject = jsonObjects.get(1);
+            }
+            String pkeyId = jsonObject.getString("pkeyId");
+            String sql = "select * from m_wbs_tree_private where p_key_id =" + pkeyId;
+            WbsTreePrivate table = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(WbsTreePrivate.class));
+            String fileUrl = table.getHtmlUrl();
+            try {
+                InputStream fileInputStream = FileUtils.getInputStreamByUrl(fileUrl);
+                String htmlString = IoUtil.readToString(fileInputStream);
+                htmlString = htmlString.replaceAll("placeholder", "placeholderxx");
+                Document doc = Jsoup.parse(htmlString);
+                // 查找所有具有 placeholderxx 属性的元素
+                //表类型 1,9=记录表 2,10=报告单
+                if (table.getTableType() == 9 || table.getTableType() == 1) {
+                    //记录表  以第一张表为准
+                    this.updateRecordNoOrReportNo(dto, jsonObject, doc, "记录编 号:", "record_no");
+                    this.updateRecordNoOrReportNo(dto, jsonObject, doc, "记录编号:", "record_no");
+                } else if (table.getTableType() == 10 || table.getTableType() == 2) {
+                    //报告单
+                    this.updateRecordNoOrReportNo(dto, jsonObject, doc, "报告编号:", "report_no");
+                    //  :不一样 一个中文一个英文
+                    this.updateRecordNoOrReportNo(dto, jsonObject, doc, "报告编号:", "report_no");
+                }
+            } catch (Exception e) {
+                log.error(e.getMessage());
+            }
+        }
 
 
     }
 
     /**
      * 判断入参中用户是否自己手动填写了 报告编号或者记录编号
+     *
      * @param dto
      * @return
      */
@@ -1263,20 +1267,20 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
                 Document doc = Jsoup.parse(htmlString);
                 //可能出现的几种情况 4种情况 记录编 号: 记录编号: 报告编号: 报告编号: 编号:
                 Elements elementsWithPlaceholderxx = doc.select("[placeholderxx='记录编 号:']");
-                if(elementsWithPlaceholderxx.size() == 0 || elementsWithPlaceholderxx == null){
+                if (elementsWithPlaceholderxx.size() == 0 || elementsWithPlaceholderxx == null) {
                     elementsWithPlaceholderxx = doc.select("[placeholderxx='记录编号:']");
-                    if(elementsWithPlaceholderxx.size() == 0 || elementsWithPlaceholderxx == null){
+                    if (elementsWithPlaceholderxx.size() == 0 || elementsWithPlaceholderxx == null) {
                         elementsWithPlaceholderxx = doc.select("[placeholderxx='报告编号:']");
-                        if(elementsWithPlaceholderxx.size() == 0 || elementsWithPlaceholderxx == null){
+                        if (elementsWithPlaceholderxx.size() == 0 || elementsWithPlaceholderxx == null) {
                             elementsWithPlaceholderxx = doc.select("[placeholderxx='报告编号:']");
-                            if(elementsWithPlaceholderxx.size() == 0 || elementsWithPlaceholderxx == null){
+                            if (elementsWithPlaceholderxx.size() == 0 || elementsWithPlaceholderxx == null) {
                                 elementsWithPlaceholderxx = doc.select("[placeholderxx='编号:']");
                             }
                         }
                     }
                 }
                 //没找到直接返回false
-                if(elementsWithPlaceholderxx.size() == 0 || elementsWithPlaceholderxx == null){
+                if (elementsWithPlaceholderxx.size() == 0 || elementsWithPlaceholderxx == null) {
                     log.error("方法:private boolean JudgingParameters(TrialSelfInspectionRecordDTO dto)中 未找到元素");
                     return false;
                 }
@@ -1284,9 +1288,9 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
                 String key = first.attr("id");
                 //记录编号或者报告编号的值
                 String recordOrReportNo = jsonObject.getString(key);
-                if(recordOrReportNo != null || "".equals(recordOrReportNo)){
+                if (recordOrReportNo != null || "".equals(recordOrReportNo)) {
                     return true;
-                }else {
+                } else {
                     return false;
                 }
             } catch (Exception e) {
@@ -1298,31 +1302,32 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
 
     /**
      * 修改记录编号或者报告编号的值
+     *
      * @param dto
      * @param jsonObject
      * @param doc
      * @param value
      * @param fileVlue
      */
-    private void updateRecordNoOrReportNo(TrialSelfInspectionRecord dto,JSONObject jsonObject,Document doc,String  value, String fileVlue) {
-        Elements elementsWithPlaceholderxx = doc.select("[placeholderxx="+value+"]");
-        if((elementsWithPlaceholderxx.size() == 0 || elementsWithPlaceholderxx == null) && value.equals("报告编号:")){
+    private void updateRecordNoOrReportNo(TrialSelfInspectionRecord dto, JSONObject jsonObject, Document doc, String value, String fileVlue) {
+        Elements elementsWithPlaceholderxx = doc.select("[placeholderxx=" + value + "]");
+        if ((elementsWithPlaceholderxx.size() == 0 || elementsWithPlaceholderxx == null) && value.equals("报告编号:")) {
             //特殊情况
             value = "编号:";
-            elementsWithPlaceholderxx = doc.select("[placeholderxx="+value+"]");
+            elementsWithPlaceholderxx = doc.select("[placeholderxx=" + value + "]");
         }
-        if(elementsWithPlaceholderxx.size() == 0 || elementsWithPlaceholderxx == null){
+        if (elementsWithPlaceholderxx.size() == 0 || elementsWithPlaceholderxx == null) {
             return;
         }
         Element first = elementsWithPlaceholderxx.first();
         String key = first.attr("id");
         //记录编号或者报告编号的值
         String recordOrReportNo = jsonObject.getString(key);
-        if(!"".equals(recordOrReportNo) && !(recordOrReportNo == null)){
-            String updateSql = "update u_trial_self_inspection_record set " + fileVlue +"='" + recordOrReportNo + "' where id='" + dto.getId()+"'";
-            if(fileVlue.equals("record_no")){
-               dto.setRecordNo(recordOrReportNo);
-            }else {
+        if (!"".equals(recordOrReportNo) && !(recordOrReportNo == null)) {
+            String updateSql = "update u_trial_self_inspection_record set " + fileVlue + "='" + recordOrReportNo + "' where id='" + dto.getId() + "'";
+            if (fileVlue.equals("record_no")) {
+                dto.setRecordNo(recordOrReportNo);
+            } else {
                 dto.setReportNo(recordOrReportNo);
             }
             jdbcTemplate.execute(updateSql);
@@ -1375,7 +1380,7 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
             for (int i = 0; i < dataArray.size(); i++) {
                 JSONObject jsonObject = dataArray.getJSONObject(i);
                 String type = jsonObject.getString("type");
-                if(ObjectUtil.isEmpty(type)){
+                if (ObjectUtil.isEmpty(type)) {
                     throw new RuntimeException("请点击表单后再进行保存");
                 }
                 if (type.equals("1")) {
@@ -1397,37 +1402,37 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
                 updateSql = getUpdateSql(dto, pdfURL, listPdf, snowId, "record_pdf_url", 2, "report_pdf_url");
             } else {
                 //一起保存的数据  只改变pdf_url
-                this.update(Wrappers.<TrialSelfInspectionRecord>lambdaUpdate().set(TrialSelfInspectionRecord::getPdfUrl, pdfURL).set(TrialSelfInspectionRecord::getTaskStatus,"未上报").eq(TrialSelfInspectionRecord::getId, dto.getId()));
+                this.update(Wrappers.<TrialSelfInspectionRecord>lambdaUpdate().set(TrialSelfInspectionRecord::getPdfUrl, pdfURL).set(TrialSelfInspectionRecord::getTaskStatus, "未上报").eq(TrialSelfInspectionRecord::getId, dto.getId()));
             }
             if (ObjectUtil.isNotEmpty(updateSql)) {
                 jdbcTemplate.execute(updateSql);
             }
-        } else if (pdfURL!=null&&pdfURL.startsWith("500")) {
-            pdfURL=pdfURL.substring(3);
+        } else if (pdfURL != null && pdfURL.startsWith("500")) {
+            pdfURL = pdfURL.substring(3);
             throw new ServiceException(pdfURL);
         }
     }
 
     @NotNull
-    private String getUpdateSql(TrialSelfInspectionRecordDTO dto, String pdfURL, String listPdf, Long snowId,String param1,int type,String param2) {
+    private String getUpdateSql(TrialSelfInspectionRecordDTO dto, String pdfURL, String listPdf, Long snowId, String param1, int type, String param2) {
         String updateSql;
-        String sqlForAntherPDF = "SELECT "+param1+ " from u_trial_self_inspection_record where id =  " + dto.getId() + " and is_deleted = 0";
+        String sqlForAntherPDF = "SELECT " + param1 + " from u_trial_self_inspection_record where id =  " + dto.getId() + " and is_deleted = 0";
         String AntherPDFUrl = jdbcTemplate.queryForObject(sqlForAntherPDF, new SingleColumnRowMapper<String>(String.class));
-        if(ObjectUtil.isNotEmpty(AntherPDFUrl)){
+        if (ObjectUtil.isNotEmpty(AntherPDFUrl)) {
             //合并后保存  把报告单合并在前面
-            if(type == 1){
+            if (type == 1) {
                 FileUtils.mergePdfPublicMethods(Arrays.asList(AntherPDFUrl, pdfURL), listPdf);
-            }else {
-                FileUtils.mergePdfPublicMethods(Arrays.asList(pdfURL,AntherPDFUrl), listPdf);
+            } else {
+                FileUtils.mergePdfPublicMethods(Arrays.asList(pdfURL, AntherPDFUrl), listPdf);
             }
 
             BladeFile bladeFile = this.newIOSSClient.uploadFile(snowId + ".pdf", listPdf);
-            updateSql = "update u_trial_self_inspection_record set pdf_url = '" + bladeFile.getLink() + "',"+param2+ "= '"+ pdfURL + "' ,task_status='未上报' where id='" + dto.getId()+"'";
+            updateSql = "update u_trial_self_inspection_record set pdf_url = '" + bladeFile.getLink() + "'," + param2 + "= '" + pdfURL + "' ,task_status='未上报' where id='" + dto.getId() + "'";
             //合并后更新queryInfo表的pdfurl
             String updateForQurtyInfo = "update u_information_query set pdf_url ='" + bladeFile.getLink() + "' where classify='" + dto.getType() + "' and  wbs_id='" + dto.getId() + "' and contract_id ='" + dto.getContractId() + "' ";
             jdbcTemplate.execute(updateForQurtyInfo);
-        }else {
-            updateSql = "update u_trial_self_inspection_record set "+param2+" = '"+ pdfURL + "' ,task_status='未上报' where id='" + dto.getId()+"'";
+        } else {
+            updateSql = "update u_trial_self_inspection_record set " + param2 + " = '" + pdfURL + "' ,task_status='未上报' where id='" + dto.getId() + "'";
         }
         return updateSql;
     }
@@ -1451,16 +1456,16 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
 
             //取样信息
             List<TrialSampleInfo> trialSampleInfos = trialSampleInfoMapper.selectList(Wrappers.<TrialSampleInfo>lambdaQuery().in(TrialSampleInfo::getId, ids));
-            List<String> samplingLocations = trialSampleInfos.stream().map(TrialSampleInfo::getSamplingLocation).filter(string -> string !=null && !string.isEmpty()).collect(Collectors.toList());
+            List<String> samplingLocations = trialSampleInfos.stream().map(TrialSampleInfo::getSamplingLocation).filter(string -> string != null && !string.isEmpty()).collect(Collectors.toList());
             String samplingLocation = org.apache.commons.lang.StringUtils.join(samplingLocations, "、");
 
-            List<String> calculationUnits = trialSampleInfos.stream().map(TrialSampleInfo::getCalculationUnit).filter(string -> string !=null && !string.isEmpty()).collect(Collectors.toList());
+            List<String> calculationUnits = trialSampleInfos.stream().map(TrialSampleInfo::getCalculationUnit).filter(string -> string != null && !string.isEmpty()).collect(Collectors.toList());
             String calculationUnit = org.apache.commons.lang.StringUtils.join(calculationUnits, "、");
 
-            List<String> specificationNumbers = trialSampleInfos.stream().map(TrialSampleInfo::getSpecificationNumber).filter(string -> string !=null && !string.isEmpty()).collect(Collectors.toList());
+            List<String> specificationNumbers = trialSampleInfos.stream().map(TrialSampleInfo::getSpecificationNumber).filter(string -> string != null && !string.isEmpty()).collect(Collectors.toList());
             String specificationNumber = org.apache.commons.lang.StringUtils.join(specificationNumbers, "、");
 
-            List<String> specificationModels = trialSampleInfos.stream().map(TrialSampleInfo::getSpecificationModel).filter(string -> string !=null && !string.isEmpty()).collect(Collectors.toList());
+            List<String> specificationModels = trialSampleInfos.stream().map(TrialSampleInfo::getSpecificationModel).filter(string -> string != null && !string.isEmpty()).collect(Collectors.toList());
             String specificationModel = org.apache.commons.lang.StringUtils.join(specificationModels, "、");
 
             //更新
@@ -1568,7 +1573,7 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
                         throw new ServiceException("当前编号已达到最大值9999,操作失败");
                     }*/
 
-                    maxRecordNo = recordNos.size()+"";
+                    maxRecordNo = recordNos.size() + "";
                 }
 
             }
@@ -1591,7 +1596,7 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
                     } else {
                         throw new ServiceException("当前编号已达到最大值9999,操作失败");
                     }*/
-                    maxReportNo = reportNos.size()+"";
+                    maxReportNo = reportNos.size() + "";
 
                 }
             }
@@ -1644,7 +1649,7 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
                     } else {
                         throw new ServiceException("当前编号已达到最大值9999,操作失败");
                     }*/
-                    maxRecordNo = recordNos.size()+"";
+                    maxRecordNo = recordNos.size() + "";
                 }
 
                 WbsTreePrivate wbsTreePrivate = wbsTreePrivateClient.queryByPKeyIds(Func.toStrList(String.valueOf(dto.getNodeId()))).stream().findAny().orElse(null);
@@ -1684,7 +1689,7 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
                     } else {
                         throw new ServiceException("当前编号已达到最大值9999,操作失败");
                     }*/
-                    maxReportNo = reportNos.size()+"";
+                    maxReportNo = reportNos.size() + "";
                 }
 
                 WbsTreePrivate wbsTreePrivate = wbsTreePrivateClient.queryByPKeyIds(Func.toStrList(String.valueOf(dto.getNodeId()))).stream().findAny().orElse(null);
@@ -1704,8 +1709,9 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
             }
         }
     }
+
     //提前构建记录或者报告编号 供用户保存前提交时使用(新增保存前显示系统引用的记录编号或者报告编号)
-    public HashMap<String,String> buildNumberView(TrialSelfInspectionRecordDTO dto) {
+    public HashMap<String, String> buildNumberView(TrialSelfInspectionRecordDTO dto) {
         StringSPUtils spUtils = new StringSPUtils();
         List<TrialSelfInspectionRecord> result = baseMapper.selectAll(dto.getNodeId(), dto.getContractId(), dto.getType());
         List<TrialSelfInspectionRecord> trialSelfInspectionRecords = result.stream().filter(Objects::nonNull).collect(Collectors.toList());
@@ -1731,7 +1737,7 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
                         throw new ServiceException("当前编号已达到最大值9999,操作失败");
                     }*/
 
-                    maxRecordNo = recordNos.size()+"";
+                    maxRecordNo = recordNos.size() + "";
                 }
 
             }
@@ -1754,7 +1760,7 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
                     } else {
                         throw new ServiceException("当前编号已达到最大值9999,操作失败");
                     }*/
-                    maxReportNo = reportNos.size()+"";
+                    maxReportNo = reportNos.size() + "";
 
                 }
             }
@@ -1768,9 +1774,9 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
                 //记录表
                 if (StringUtils.isNotEmpty(maxRecordNo)) {
                     HashMap<String, String> stringStringHashMap = new HashMap<>();
-                    stringStringHashMap.put("type","记录表");
+                    stringStringHashMap.put("type", "记录表");
                     if (trialSelfInspectionRecord != null) {
-                        stringStringHashMap.put("valueStr",trialSelfInspectionRecord.getRecordNo());
+                        stringStringHashMap.put("valueStr", trialSelfInspectionRecord.getRecordNo());
                         return stringStringHashMap;
                     }
                     String str1 = "JL" +
@@ -1778,16 +1784,16 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
                             "-" + year +
                             "-" + spUtils.getStringSP(wbsTreePrivate.getNodeName().trim()) +
                             "-" + maxRecordNo;
-                    stringStringHashMap.put("valueStr",str1);
+                    stringStringHashMap.put("valueStr", str1);
                     return stringStringHashMap;
                 }
 
                 //报告单
                 if (StringUtils.isNotEmpty(maxReportNo)) {
                     HashMap<String, String> stringStringHashMap = new HashMap<>();
-                    stringStringHashMap.put("type","报告单");
+                    stringStringHashMap.put("type", "报告单");
                     if (trialSelfInspectionRecord != null) {
-                        stringStringHashMap.put("valueStr",trialSelfInspectionRecord.getReportNo());
+                        stringStringHashMap.put("valueStr", trialSelfInspectionRecord.getReportNo());
                         return stringStringHashMap;
                     }
                     String str2 = "BG" +
@@ -1795,7 +1801,7 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
                             "-" + year +
                             "-" + spUtils.getStringSP(wbsTreePrivate.getNodeName().trim()) +
                             "-" + maxReportNo;
-                    stringStringHashMap.put("valueStr",str2);
+                    stringStringHashMap.put("valueStr", str2);
                     return stringStringHashMap;
                 }
             }
@@ -1821,7 +1827,7 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
                     } else {
                         throw new ServiceException("当前编号已达到最大值9999,操作失败");
                     }*/
-                    maxRecordNo = recordNos.size()+"";
+                    maxRecordNo = recordNos.size() + "";
                 }
 
                 WbsTreePrivate wbsTreePrivate = wbsTreePrivateClient.queryByPKeyIds(Func.toStrList(String.valueOf(dto.getNodeId()))).stream().findAny().orElse(null);
@@ -1832,9 +1838,9 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
                 } else {
                     //记录表
                     HashMap<String, String> stringStringHashMap = new HashMap<>();
-                    stringStringHashMap.put("type","记录表");
+                    stringStringHashMap.put("type", "记录表");
                     if (trialSelfInspectionRecord != null) {
-                        stringStringHashMap.put("valueStr",trialSelfInspectionRecord.getRecordNo());
+                        stringStringHashMap.put("valueStr", trialSelfInspectionRecord.getRecordNo());
                         return stringStringHashMap;
                     }
                     String str1 = "JL" +
@@ -1842,7 +1848,7 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
                             "-" + year +
                             "-" + spUtils.getStringSP(wbsTreePrivate.getNodeName().trim()) +
                             "-" + maxRecordNo;
-                    stringStringHashMap.put("valueStr",str1);
+                    stringStringHashMap.put("valueStr", str1);
                     return stringStringHashMap;
                 }
             }
@@ -1868,7 +1874,7 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
                     } else {
                         throw new ServiceException("当前编号已达到最大值9999,操作失败");
                     }*/
-                    maxReportNo = reportNos.size()+"";
+                    maxReportNo = reportNos.size() + "";
                 }
 
                 WbsTreePrivate wbsTreePrivate = wbsTreePrivateClient.queryByPKeyIds(Func.toStrList(String.valueOf(dto.getNodeId()))).stream().findAny().orElse(null);
@@ -1879,9 +1885,9 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
                 } else {
                     //报告单
                     HashMap<String, String> stringStringHashMap = new HashMap<>();
-                    stringStringHashMap.put("type","报告单");
+                    stringStringHashMap.put("type", "报告单");
                     if (trialSelfInspectionRecord != null) {
-                        stringStringHashMap.put("valueStr",trialSelfInspectionRecord.getReportNo());
+                        stringStringHashMap.put("valueStr", trialSelfInspectionRecord.getReportNo());
                         return stringStringHashMap;
                     }
                     String str2 = "BG" +
@@ -1889,7 +1895,7 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
                             "-" + year +
                             "-" + spUtils.getStringSP(wbsTreePrivate.getNodeName().trim()) +
                             "-" + maxReportNo;
-                    stringStringHashMap.put("valueStr",str2);
+                    stringStringHashMap.put("valueStr", str2);
                     return stringStringHashMap;
                 }
             }
@@ -1976,17 +1982,16 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
             if (informationQuery != null) {
                 List<String> pdfList = new ArrayList<>();
                 //------自检------
+                if (informationQuery.getPdfTrialUrl() != null) {
+                    //如果当前存在第三方、外委的pdf,那么拼接
+                    pdfList.add(informationQuery.getPdfTrialUrl());
+                }
                 if (dto.getType().equals(1)) {
-                    if (informationQuery.getPdfTrialUrl() != null) {
-                        //如果当前存在第三方、外委的pdf,那么拼接
-                        pdfList.add(informationQuery.getPdfTrialUrl());
-                    }
-
                     //自检pdf
                     List<TrialSelfInspectionRecord> trialSelfInspectionRecords = baseMapper.selectList(Wrappers.<TrialSelfInspectionRecord>lambdaQuery()
-                            .select(TrialSelfInspectionRecord::getPdfUrl,TrialSelfInspectionRecord::getContractId,TrialSelfInspectionRecord::getId,TrialSelfInspectionRecord::getType)
+                            .select(TrialSelfInspectionRecord::getPdfUrl, TrialSelfInspectionRecord::getContractId, TrialSelfInspectionRecord::getId, TrialSelfInspectionRecord::getType)
                             .in(TrialSelfInspectionRecord::getId, Func.toLongList(dto.getIds())));
-                    if(trialSelfInspectionRecords.size()>0){
+                    if (trialSelfInspectionRecords.size() > 0) {
                         for (TrialSelfInspectionRecord record : trialSelfInspectionRecords) {
                             String pdf = this.getMergePdfToTrialNew(record.getContractId(), record.getId(), record.getType());
                             pdfList.add(pdf);
@@ -1996,11 +2001,6 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
 //                    pdfList.addAll(pdfURLs);
                     //------第三方、外委------
                 } else if (dto.getType().equals(2) || dto.getType().equals(3)) {
-                    if (informationQuery.getPdfTrialUrl() != null) {
-                        //如果当前存在试验自检的pdf,那么拼接
-                        pdfList.add(informationQuery.getPdfTrialUrl());
-                    }
-
                     //第三方、外委pdf
                     List<TrialDetectionData> trialDetectionData = trialDetectionDataService.getBaseMapper().selectList(Wrappers.<TrialDetectionData>lambdaQuery().in(TrialDetectionData::getId, Func.toLongList(dto.getIds())));
                     List<String> pdfURLs = new ArrayList<>();
@@ -2015,6 +2015,24 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
                     pdfList.addAll(pdfURLs);
                 }
 
+                //成渝自检
+                if (dto.getType().equals(11)) {
+                    List<TrialCyFinishTestReport> trialCyFinishTestReports = trialCyFinishTestReportService.getBaseMapper().selectList(Wrappers.<TrialCyFinishTestReport>lambdaQuery().in(TrialCyFinishTestReport::getTaskId, Func.toLongList(dto.getIds())));
+                    trialCyFinishTestReports.forEach(f -> {
+                        if (StringUtils.isNotBlank(f.getAssembleFile())) {
+                            pdfList.add(f.getAssembleFile());
+                        }
+
+                    });
+                } else if (dto.getType().equals(12) || dto.getType().equals(13)) {
+                    List<TrialCyThirdReport> trialCyThirdReports = trialCyThirdReportService.getBaseMapper().selectList(Wrappers.<TrialCyThirdReport>lambdaQuery().in(TrialCyThirdReport::getId, Func.toLongList(dto.getIds())));
+                    trialCyThirdReports.forEach(f -> {
+                        if (StringUtils.isNotBlank(f.getAssembleFile())) {
+                            pdfList.add(f.getAssembleFile());
+                        }
+                    });
+                }
+
                 if (pdfList.size() > 0) {
                     //合并试验自检、第三方、外委的pdf
                     List<String> collect = pdfList.stream().filter(Objects::nonNull).collect(Collectors.toList());
@@ -2113,7 +2131,7 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
     @Override
     public R getSamplePdfUrl(String id, String contrctId) {
         try {
-            String  pdf = this.getMergePdfToTrial(Func.toLong(contrctId), Func.toLong(id));
+            String pdf = this.getMergePdfToTrial(Func.toLong(contrctId), Func.toLong(id));
             return R.data(pdf);
         } catch (FileNotFoundException e) {
             throw new RuntimeException(e);
@@ -2185,28 +2203,28 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
         if (entrustInfo != null && info == null && oldTrialSampleInfo != null) {
             if (entrustInfo.getSampleId() != null && entrustInfo.getSampleId().equals(oldTrialSampleInfo.getId())) {
                 record.setEntrustId(null);
-                baseInfo.setEntrustId( null);
+                baseInfo.setEntrustId(null);
                 baseInfo.setEntrustNo(null);
             }
         }
-        boolean a=true;
-        boolean b=true;
+        boolean a = true;
+        boolean b = true;
         record.setBaseInfo(JSON.toJSONString(baseInfo));
         if (oldRecord == null) {
-            if(StringUtils.isNotEmpty(record.getRecordNo())){
-                if(StringUtils.isNotEmpty(record.getRecordNo())){
-                    a= trialNumberRuleService.checkTrialNumberIsExist(record.getRecordNo(), 4, record.getContractId());
+            if (StringUtils.isNotEmpty(record.getRecordNo())) {
+                if (StringUtils.isNotEmpty(record.getRecordNo())) {
+                    a = trialNumberRuleService.checkTrialNumberIsExist(record.getRecordNo(), 4, record.getContractId());
                 }
             }
-            if(StringUtils.isNotEmpty(record.getRecordNo())){
-                if(StringUtils.isNotEmpty(record.getReportNo())){
-                    b= trialNumberRuleService.checkTrialNumberIsExist(record.getReportNo(), 5, record.getContractId());
+            if (StringUtils.isNotEmpty(record.getRecordNo())) {
+                if (StringUtils.isNotEmpty(record.getReportNo())) {
+                    b = trialNumberRuleService.checkTrialNumberIsExist(record.getReportNo(), 5, record.getContractId());
                 }
             }
-            if(!a){
+            if (!a) {
                 throw new ServiceException("记录编号已存在");
             }
-            if(!b){
+            if (!b) {
                 throw new ServiceException("报告编号已存在");
             }
             this.save(record);
@@ -2231,9 +2249,9 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
                 if (StringUtils.isNotBlank(samplingLocation) || StringUtils.isNotBlank(calculationUnit) || StringUtils.isNotBlank(specificationNumber) || StringUtils.isNotBlank(specificationModel)) {
                     this.update(Wrappers.<TrialSelfInspectionRecord>lambdaUpdate()
                             .set(StringUtils.isNotBlank(samplingLocation), TrialSelfInspectionRecord::getSamplingLocation, samplingLocation)
-                            .set(StringUtils.isNotBlank(calculationUnit),TrialSelfInspectionRecord::getCompany, calculationUnit)
-                            .set(StringUtils.isNotBlank(specificationNumber),TrialSelfInspectionRecord::getSpecificationNumber, specificationNumber)
-                            .set(StringUtils.isNotBlank(specificationModel),TrialSelfInspectionRecord::getSpecificationModel, specificationModel)
+                            .set(StringUtils.isNotBlank(calculationUnit), TrialSelfInspectionRecord::getCompany, calculationUnit)
+                            .set(StringUtils.isNotBlank(specificationNumber), TrialSelfInspectionRecord::getSpecificationNumber, specificationNumber)
+                            .set(StringUtils.isNotBlank(specificationModel), TrialSelfInspectionRecord::getSpecificationModel, specificationModel)
                             .eq(TrialSelfInspectionRecord::getId, record.getId()));
                 }
                 if (entrustInfo == null) {
@@ -2248,9 +2266,9 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
             }
         }
         // ---- 修改样品单号信息 --------
-        if(entrustInfo != null){
+        if (entrustInfo != null) {
             //修改项目节点基础信息
-            jdbcTemplate.update("update u_entrust_info set sample_status=4 where id ='"+entrustInfo.getId()+"'");
+            jdbcTemplate.update("update u_entrust_info set sample_status=4 where id ='" + entrustInfo.getId() + "'");
             if (entrustInfo.getSampleId() != null) {
                 TrialSampleInfo sampleInfo = trialSampleInfoMapper.selectById(entrustInfo.getSampleId());
                 if (sampleInfo != null) {
@@ -2269,9 +2287,9 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
                     if (StringUtils.isNotBlank(samplingLocation) || StringUtils.isNotBlank(calculationUnit) || StringUtils.isNotBlank(specificationNumber) || StringUtils.isNotBlank(specificationModel)) {
                         this.update(Wrappers.<TrialSelfInspectionRecord>lambdaUpdate()
                                 .set(StringUtils.isNotBlank(samplingLocation), TrialSelfInspectionRecord::getSamplingLocation, samplingLocation)
-                                .set(StringUtils.isNotBlank(calculationUnit),TrialSelfInspectionRecord::getCompany, calculationUnit)
-                                .set(StringUtils.isNotBlank(specificationNumber),TrialSelfInspectionRecord::getSpecificationNumber, specificationNumber)
-                                .set(StringUtils.isNotBlank(specificationModel),TrialSelfInspectionRecord::getSpecificationModel, specificationModel)
+                                .set(StringUtils.isNotBlank(calculationUnit), TrialSelfInspectionRecord::getCompany, calculationUnit)
+                                .set(StringUtils.isNotBlank(specificationNumber), TrialSelfInspectionRecord::getSpecificationNumber, specificationNumber)
+                                .set(StringUtils.isNotBlank(specificationModel), TrialSelfInspectionRecord::getSpecificationModel, specificationModel)
                                 .eq(TrialSelfInspectionRecord::getId, record.getId()));
                     }
                 }
@@ -2286,19 +2304,19 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
             List<Long> collect = trialSampleInfoList.stream().map(TrialSampleInfo::getId).collect(Collectors.toList());
             recordDTO.setSampleIds(org.apache.commons.lang.StringUtils.join(collect, ","));
             recordDTO.setNodeId(dto.getNodeId());
-            recordDTO.setTrialUserName(AuthUtil.getUserName());
+            recordDTO.setTrialUserName(AuthUtil.getNickName());
             this.trialDeviceUseService.addDeviceUseInfo(recordDTO, record.getId());
         }
-            if(dto.getOldRecordNumber()!=null&&dto.getOldRecordNumber().equals(dto.getRecordNo())){
-                if(StringUtils.isNotEmpty(dto.getRecordAutoNumber())){
-                    trialNumberRuleService.checkSave(dto.getContractId(),4,record.getId(),dto.getRecordAutoNumber());
-                }
+        if (dto.getOldRecordNumber() != null && dto.getOldRecordNumber().equals(dto.getRecordNo())) {
+            if (StringUtils.isNotEmpty(dto.getRecordAutoNumber())) {
+                trialNumberRuleService.checkSave(dto.getContractId(), 4, record.getId(), dto.getRecordAutoNumber());
             }
-            if(dto.getOldReportNumber()!=null&&dto.getOldReportNumber().equals(dto.getReportNo())){
-                if(StringUtils.isNotEmpty(dto.getReportAutoNumber())){
-                    trialNumberRuleService.checkSave(dto.getContractId(),5,record.getId(),dto.getReportAutoNumber());
-                }
+        }
+        if (dto.getOldReportNumber() != null && dto.getOldReportNumber().equals(dto.getReportNo())) {
+            if (StringUtils.isNotEmpty(dto.getReportAutoNumber())) {
+                trialNumberRuleService.checkSave(dto.getContractId(), 5, record.getId(), dto.getReportAutoNumber());
             }
+        }
 
         return record.getId();
     }

+ 2 - 2
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/UStandardInfoServiceImpl.java

@@ -56,8 +56,8 @@ public class UStandardInfoServiceImpl extends ServiceImpl<StandardInfoMapper, St
 
 
     @Override
-    public IPage<StandardInfoDTO> selectMyPage(Query query, StandardInfo standardInfo) {
-        return baseMapper.selectMyPage(new Page<StandardInfoDTO>(query.getCurrent(), query.getSize()), standardInfo);
+    public IPage<StandardInfoDtoVo> selectMyPage(Query query, StandardInfo standardInfo) {
+        return baseMapper.selectMyPage(new Page<StandardInfoDtoVo>(query.getCurrent(), query.getSize()), standardInfo);
     }
 
     @Override

+ 13 - 3
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/WbsTreeContractStatisticsServiceImpl.java

@@ -88,7 +88,7 @@ public class WbsTreeContractStatisticsServiceImpl extends ServiceImpl<WbsTreeCon
                     } else if (lock.getFillNum() == 1 && lock.getApproveNum() == 0 && lock.getCompleteNum() == 0) {
                         this.update(Wrappers.<WbsTreeContractStatistics>lambdaUpdate().in(WbsTreeContractStatistics::getId, collect).setSql("fill_num = fill_num - 1, approve_num = approve_num + 1"));
                     } else if (lock.getFillNum() == 0 && lock.getApproveNum() == 0 && lock.getCompleteNum() == 1) {
-                        this.update(Wrappers.<WbsTreeContractStatistics>lambdaUpdate().in(WbsTreeContractStatistics::getId, collect).setSql("fill_num = fill_num + 1, complete_num = complete_num - 1"));
+                        this.update(Wrappers.<WbsTreeContractStatistics>lambdaUpdate().in(WbsTreeContractStatistics::getId, collect).setSql("approve_num = approve_num + 1, complete_num = complete_num - 1"));
                     }
                 } else if (status == 2) {
                     this.update(Wrappers.<WbsTreeContractStatistics>lambdaUpdate().eq(WbsTreeContractStatistics::getId, wbsId)
@@ -121,7 +121,7 @@ public class WbsTreeContractStatisticsServiceImpl extends ServiceImpl<WbsTreeCon
                     } else if (lock.getJlFillNum() == 1 && lock.getJlApproveNum() == 0 && lock.getJlCompleteNum() == 0) {
                         this.update(Wrappers.<WbsTreeContractStatistics>lambdaUpdate().in(WbsTreeContractStatistics::getId, collect).setSql("jl_fill_num = jl_fill_num - 1, jl_approve_num = jl_approve_num + 1"));
                     } else if (lock.getJlFillNum() == 0 && lock.getJlApproveNum() == 0 && lock.getJlCompleteNum() == 1) {
-                        this.update(Wrappers.<WbsTreeContractStatistics>lambdaUpdate().in(WbsTreeContractStatistics::getId, collect).setSql("jl_approve_num = jl_approve_num - 1, jl_complete_num = jl_complete_num + 1"));
+                        this.update(Wrappers.<WbsTreeContractStatistics>lambdaUpdate().in(WbsTreeContractStatistics::getId, collect).setSql("jl_approve_num = jl_approve_num + 1, jl_complete_num = jl_complete_num - 1"));
                     }
                 } else if (status == 2) {
                     this.update(Wrappers.<WbsTreeContractStatistics>lambdaUpdate().eq(WbsTreeContractStatistics::getId, wbsId)
@@ -221,6 +221,16 @@ public class WbsTreeContractStatisticsServiceImpl extends ServiceImpl<WbsTreeCon
         return true;
     }
 
+    private void updateStatusAndIsDeleted(Long contractId) {
+        List<WbsTreeContractStatistics> query = jdbcTemplate.query("SELECT a.id,b.status,b.is_deleted from m_wbs_tree_contract_statistics a LEFT JOIN m_wbs_tree_contract b on a.id = b.p_key_id WHERE (a.status != b.status OR a.is_deleted != b.is_deleted) AND b.p_key_id IS NOT NULl and a.contract_id = " + contractId,
+                new BeanPropertyRowMapper<>(WbsTreeContractStatistics.class));
+        if (query.isEmpty()) {
+            return;
+        }
+        List<WbsTreeContractStatistics> list = query.stream().filter(item -> item.getStatus() != null && item.getIsDeleted() != null).collect(Collectors.toList());
+        this.updateBatchById(list);
+    }
+
     public Boolean updateLeafNum(String ids) {
         if (ids != null && !ids.isEmpty()) {
             String[] split = ids.split(",");
@@ -298,6 +308,7 @@ public class WbsTreeContractStatisticsServiceImpl extends ServiceImpl<WbsTreeCon
                 for (WbsTreeContractDto dto : contractDtoList) {
                     addWbsTreeContractStatistics.add(createWbsTreeContractStatistics(dto));
                 }
+                updateStatusAndIsDeleted(contractId);
             }
             // 统计叶子节点数量
 //            countLeafNum(addWbsTreeContractStatistics);
@@ -326,7 +337,6 @@ public class WbsTreeContractStatisticsServiceImpl extends ServiceImpl<WbsTreeCon
             log.error("更新合同段wbs树统计信息异常", e);
         }
     }
-
     private boolean updateWbsTreeContractStatisticsFields(WbsTreeContractStatistics old, WbsTreeContractStatistics newObj) {
         boolean result = false;
         if (ObjectUtil.nullSafeEquals(old.getParentId(), newObj.getParentId())) {

+ 19 - 18
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/WeatherInfoServiceImpl.java

@@ -120,7 +120,7 @@ public class WeatherInfoServiceImpl extends ServiceImpl<WeatherInfoMapper, Weath
     /**
      * 获取当前系统所有项目下所有合同段的当天天气
      */
-    @Scheduled(cron = "0 18 10 * * ?")
+    @Scheduled(cron = "0 10 0,6,12,18,23 * * ?")
     public void syncWeatherInfo() {
         if (!SystemUtils.isLinux()) {
             return;
@@ -128,12 +128,13 @@ public class WeatherInfoServiceImpl extends ServiceImpl<WeatherInfoMapper, Weath
         //获取所有合同段的定位信息
         List<ProjectContractArea> areaList = this.projectContractAreaClient.queryAllContractArea();
         Map<String, Map<String, String>> cachedWeatherMap = new HashMap<>();
+        String date = DateUtil.format(new Date(), "yyyy-MM-dd");
         for (ProjectContractArea area : areaList) {
             try {
                 //校验当前区域是否已经获取当天日期(手动补填或自动获取)
                 Map<String, Object> queryMap = new HashMap<>();
                 queryMap.put("contractAreaId", area.getId());
-                queryMap.put("recordTime", DateUtil.format(new Date(), "yyyy-MM-dd"));
+                queryMap.put("recordTime", date);
                 //查询
                 long count = this.count(Condition.getQueryWrapper(queryMap, WeatherInfo.class));
                 if (count > 0) {
@@ -146,30 +147,30 @@ public class WeatherInfoServiceImpl extends ServiceImpl<WeatherInfoMapper, Weath
                     String nums = stringRedisTemplate.opsForValue().get("blade-business::contractArea:yiKeYun:todayWeatherNums");
                     if (nums == null || Integer.parseInt(nums) <= 19000) {
                         // 重试三次
-                        weatherMap = YiKeYunApiUtils.getTodayWeatherByAdcodeTry(area.getCity_code() + "000000");
-                        if (weatherMap != null) {
+//                        weatherMap = YiKeYunApiUtils.getTodayWeatherByAdcodeTry(area.getCity_code() + "000000");
+                        Map<String, Map<String, String>> map = getHistoryWeather(area, date, date);
+                        if (map != null && !map.isEmpty()) {
+                            weatherMap = map.values().stream().findFirst().orElse( null);
+                        }
+                        if (weatherMap != null && !weatherMap.isEmpty()) {
                             cachedWeatherMap.put(area.getCity_code(), weatherMap);
                             if (weatherMap.get("nums") != null) {
                                 stringRedisTemplate.opsForValue().set("blade-business::contractArea:yiKeYun:todayWeatherNums", weatherMap.get("nums"), getSecondsUntilMidnight(), TimeUnit.SECONDS);
                             }
                         }
                     }
-                    //获取天气信息(百度天气)
-//                    if (weatherMap == null) {
-//                        weatherMap = BaiduApiUtil.getTodayWeather(area.getCity_code());
-//                    }
                 }
-                if (weatherMap != null) {
+                if (weatherMap != null && !weatherMap.isEmpty()) {
                     //计算平均气温
                     BigDecimal aver = (new BigDecimal(weatherMap.get("high")).add(new BigDecimal(weatherMap.get("low")))).divide(new BigDecimal("2"), 1, BigDecimal.ROUND_HALF_UP);
                     WeatherInfo newWeather = new WeatherInfo(String.valueOf(area.getId()), weatherMap.get("weather"), aver.toString(), weatherMap.get("high"), weatherMap.get("low"), weatherMap.get("windLevel"));
                     this.save(newWeather);
                     log.info("今日的天气已经同步完成!contractAreaId:" + area.getId() + ",syncTime:" + DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
                 } else {
-                    log.info("获取今日的天气失败!contractAreaId:" + area.getId() + ",syncTime:" + DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
+                    log.warn("获取今日的天气失败!contractAreaId:" + area.getId() + ",syncTime:" + DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
                 }
             } catch (Exception e) {
-                e.printStackTrace();
+                log.error("获取今日的天气失败!contractAreaId:" + area.getId() + ",syncTime:" + DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"), e);
             }
         }
         System.out.println("同步当天天气完成");
@@ -264,7 +265,7 @@ public class WeatherInfoServiceImpl extends ServiceImpl<WeatherInfoMapper, Weath
                         //判断集合中是否存在当前天气,如果不存在则获取
                         if (weatherMap == null || weatherMap.get(plainTime.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日"))) == null) {
                             String month = plainTime.format(DateTimeFormatter.ofPattern("yyyyMM"));
-                            weatherMap = this.getHistoryWeather(projectContractArea, month);
+                            weatherMap = this.getHistoryWeather(projectContractArea, month, null);
                             if (weatherMap == null) {
                                 weatherMap = this.getWeather(county.toString(), month);
                                 if (weatherMap == null || weatherMap.get(plainTime.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日"))) == null) {
@@ -297,9 +298,9 @@ public class WeatherInfoServiceImpl extends ServiceImpl<WeatherInfoMapper, Weath
     //去除重复天气,并填充每个合同段缺失的天气
     @Scheduled(cron = "0 0 9 * * ?")
     public void scanMissWeather(){
-        if (!SystemUtils.isLinux()) {
-            return;
-        }
+//        if (!SystemUtils.isLinux()) {
+//            return;
+//        }
         //获取所有项目的合同段
         List<ContractInfoVO> contractInfos = baseMapper.getAllContract();
         for (ContractInfoVO contract : contractInfos) {
@@ -361,7 +362,7 @@ public class WeatherInfoServiceImpl extends ServiceImpl<WeatherInfoMapper, Weath
             Map<String, List<LocalDate>> map = missDate.stream().collect(Collectors.groupingBy(l -> l.format(DateTimeFormatter.ofPattern("yyyyMM"))));
             for (String s : map.keySet()) {
                 //获取整月天气
-                weatherMap = this.getHistoryWeather(area, s);
+                weatherMap = this.getHistoryWeather(area, s, null);
                 if (weatherMap == null) {
                     weatherMap = this.getWeather(county.toString(), s);
                     if (weatherMap == null || weatherMap.size() == 0) {
@@ -426,7 +427,7 @@ public class WeatherInfoServiceImpl extends ServiceImpl<WeatherInfoMapper, Weath
         System.out.println("9999");
     }
 
-    public Map<String, Map<String, String>> getHistoryWeather(ProjectContractArea area, String month) {
+    public Map<String, Map<String, String>> getHistoryWeather(ProjectContractArea area, String month, String date) {
         String nums = stringRedisTemplate.opsForValue().get("blade-business::contractArea:yiKeYun:historyWeatherNums");
         if (nums != null && Integer.parseInt(nums) > 19000) {
             log.info("获取历史天气失败:易客云获取历史天气的api次数已用完。");
@@ -455,7 +456,7 @@ public class WeatherInfoServiceImpl extends ServiceImpl<WeatherInfoMapper, Weath
             cityId = jdbcTemplate.queryForObject("select id from m_yikeyun_weather_city where cityZh like '" + county + "%'", String.class);
         }
         if (cityId != null) {
-            Map<String, Map<String, String>> historyWeather = YiKeYunApiUtils.getHistoryWeather(cityId, Integer.parseInt(month.substring(0, 4)), Integer.parseInt(month.substring(4, 6)));
+            Map<String, Map<String, String>> historyWeather = YiKeYunApiUtils.getHistoryWeather(cityId, Integer.parseInt(month.substring(0, 4)), Integer.parseInt(month.substring(4, 6)), date);
             if (historyWeather != null) {
                 Map<String, String> map = historyWeather.get("nums");
                 if (map != null && map.get("nums") != null) {

+ 358 - 75
blade-service/blade-business/src/main/java/org/springblade/business/utils/FileUtils.java

@@ -8,6 +8,7 @@ import com.drew.metadata.exif.ExifIFD0Directory;
 import com.itextpdf.text.Document;
 import com.itextpdf.text.pdf.PdfCopy;
 import com.itextpdf.text.pdf.PdfReader;
+import net.coobird.thumbnailator.Thumbnails;
 import org.apache.commons.lang.StringUtils;
 import org.apache.poi.ss.usermodel.ClientAnchor;
 import org.apache.poi.ss.usermodel.Sheet;
@@ -17,6 +18,7 @@ import org.springblade.common.constant.CommonConstant;
 import org.springblade.common.utils.CommonUtil;
 import org.springblade.common.utils.SystemUtils;
 import org.springblade.common.vo.DataVO;
+import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.tool.utils.IoUtil;
 import org.springblade.system.cache.ParamCache;
 
@@ -24,13 +26,16 @@ import javax.imageio.IIOImage;
 import javax.imageio.ImageIO;
 import javax.imageio.ImageWriteParam;
 import javax.imageio.ImageWriter;
+import javax.imageio.stream.ImageOutputStream;
 import javax.servlet.http.HttpServletResponse;
 import java.awt.*;
 import java.awt.geom.AffineTransform;
 import java.awt.image.AffineTransformOp;
 import java.awt.image.BufferedImage;
 import java.io.*;
+import java.net.URL;
 import java.net.URLEncoder;
+import java.nio.file.*;
 import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;
@@ -118,92 +123,328 @@ public class FileUtils {
         }
     }
 
-    /**
-     * 图片缩放、压缩、旋转处理
-     *
-     * @param imageData
-     * @return
-     * @throws IOException
-     * @throws ImageProcessingException
-     * @throws MetadataException
-     */
-    public static byte[] compressImage(byte[] imageData) throws IOException, ImageProcessingException, MetadataException {
-        // 读取原始图像(处理旋转问题)
-        Metadata metadata = ImageMetadataReader.readMetadata(new ByteArrayInputStream(imageData));
-        if (metadata.containsDirectoryOfType(ExifIFD0Directory.class)) {
+//    /**
+//     * 图片缩放、压缩、旋转处理
+//     *
+//     * @param imageData
+//     * @return
+//     * @throws IOException
+//     * @throws ImageProcessingException
+//     * @throws MetadataException
+//     */
+//    public static byte[] compressImage(byte[] imageData) throws IOException, ImageProcessingException, MetadataException {
+//        // 读取原始图像(处理旋转问题)
+//        Metadata metadata = ImageMetadataReader.readMetadata(new ByteArrayInputStream(imageData));
+//        if (metadata.containsDirectoryOfType(ExifIFD0Directory.class)) {
+//            ExifIFD0Directory exifIFD0Directory = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
+//            if (exifIFD0Directory.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) {
+//                // 获取 Orientation 标签的值
+//                int orientation = exifIFD0Directory.getInt(ExifIFD0Directory.TAG_ORIENTATION);
+//                // 需要旋转图片
+//                BufferedImage originalImage = ImageIO.read(new ByteArrayInputStream(imageData));
+//                AffineTransform transform = new AffineTransform();
+//                if (orientation == 6) {
+//                    transform.rotate(Math.PI / 2, originalImage.getWidth() / 2, originalImage.getHeight() / 2);
+//                } else if (orientation == 8) {
+//                    transform.rotate(-Math.PI / 2, originalImage.getWidth() / 2, originalImage.getHeight() / 2);
+//                }
+//                AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR);
+//                originalImage = op.filter(originalImage, null);
+//                ByteArrayOutputStream baos = new ByteArrayOutputStream();
+//                ImageIO.write(originalImage, "jpg", baos);
+//                imageData = baos.toByteArray();
+//            }
+//        }
+//        // 缩放图像
+//        String formatName = "JPEG";
+//        ByteArrayInputStream bais = new ByteArrayInputStream(imageData);
+//        BufferedImage originalImage = ImageIO.read(bais);
+//        long sizeLimit = 366912; //358KB
+//        int width = 768;
+//        int height = 1024;
+//        Image scaledImage = originalImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);
+//        BufferedImage resizedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+//        resizedImage.getGraphics().drawImage(scaledImage, 0, 0, null);
+//
+//        // 压缩图像
+//        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+//        ImageIO.write(resizedImage, formatName, baos);
+//
+//        if (baos.size() <= sizeLimit) {
+//            // 图片大小已经小于等于目标大小,直接返回原始数据
+//            return baos.toByteArray();
+//        }
+//
+//        float quality = 0.9f; // 初始化压缩质量
+//        int retries = 10; // 最多尝试 10 次
+//
+//        while (baos.size() > sizeLimit && retries > 0) {
+//            // 压缩图像并重新计算压缩质量
+//            byte[] data = baos.toByteArray();
+//            bais = new ByteArrayInputStream(data);
+//            BufferedImage compressedImage = ImageIO.read(bais);
+//            baos.reset();
+//
+//            ImageWriter writer = null;
+//            Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(formatName);
+//            if (writers.hasNext()) {
+//                writer = writers.next();
+//            } else {
+//                throw new IllegalArgumentException("Unsupported image format: " + formatName);
+//            }
+//
+//            ImageWriteParam writeParam = writer.getDefaultWriteParam();
+//            writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
+//            writeParam.setCompressionQuality(quality);
+//
+//            writer.setOutput(ImageIO.createImageOutputStream(baos));
+//            writer.write(null, new IIOImage(compressedImage, null, null), writeParam);
+//            writer.dispose();
+//
+//            float ratio = sizeLimit * 1.0f / baos.size();
+//            quality *= Math.sqrt(ratio);
+//            retries--;
+//        }
+//
+//        return baos.toByteArray();
+//    }
+
+    public static byte[] compressImage(byte[] imageData) throws IOException {
+        // 读取元数据判断是否需要旋转
+        int orientation = 1;
+        try {
+            Metadata metadata = ImageMetadataReader.readMetadata(new ByteArrayInputStream(imageData));
             ExifIFD0Directory exifIFD0Directory = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
-            if (exifIFD0Directory.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) {
-                // 获取 Orientation 标签的值
-                int orientation = exifIFD0Directory.getInt(ExifIFD0Directory.TAG_ORIENTATION);
-                // 需要旋转图片
-                BufferedImage originalImage = ImageIO.read(new ByteArrayInputStream(imageData));
-                AffineTransform transform = new AffineTransform();
-                if (orientation == 6) {
-                    transform.rotate(Math.PI / 2, originalImage.getWidth() / 2, originalImage.getHeight() / 2);
-                } else if (orientation == 8) {
-                    transform.rotate(-Math.PI / 2, originalImage.getWidth() / 2, originalImage.getHeight() / 2);
-                }
-                AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR);
-                originalImage = op.filter(originalImage, null);
-                ByteArrayOutputStream baos = new ByteArrayOutputStream();
-                ImageIO.write(originalImage, "jpg", baos);
-                imageData = baos.toByteArray();
+            if (exifIFD0Directory != null && exifIFD0Directory.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) {
+                orientation = exifIFD0Directory.getInt(ExifIFD0Directory.TAG_ORIENTATION);
             }
+        } catch (Exception e) {
+            // 元数据读取失败不影响主要流程
         }
-        // 缩放图像
-        String formatName = "JPEG";
-        ByteArrayInputStream bais = new ByteArrayInputStream(imageData);
-        BufferedImage originalImage = ImageIO.read(bais);
-        long sizeLimit = 366912; //358KB
-        int width = 768;
-        int height = 1024;
-        Image scaledImage = originalImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);
-        BufferedImage resizedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
-        resizedImage.getGraphics().drawImage(scaledImage, 0, 0, null);
-
-        // 压缩图像
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        ImageIO.write(resizedImage, formatName, baos);
-
-        if (baos.size() <= sizeLimit) {
-            // 图片大小已经小于等于目标大小,直接返回原始数据
-            return baos.toByteArray();
-        }
 
-        float quality = 0.9f; // 初始化压缩质量
-        int retries = 10; // 最多尝试 10 次
-
-        while (baos.size() > sizeLimit && retries > 0) {
-            // 压缩图像并重新计算压缩质量
-            byte[] data = baos.toByteArray();
-            bais = new ByteArrayInputStream(data);
-            BufferedImage compressedImage = ImageIO.read(bais);
-            baos.reset();
-
-            ImageWriter writer = null;
-            Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(formatName);
-            if (writers.hasNext()) {
-                writer = writers.next();
-            } else {
-                throw new IllegalArgumentException("Unsupported image format: " + formatName);
+        // 使用Thumbnails处理旋转和压缩
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        long sizeLimit = 366912; // 358KB
+
+        try {
+            Thumbnails.of(new ByteArrayInputStream(imageData))
+                    .size(768, 1024)
+                    .outputFormat("jpg")
+                    .outputQuality(0.9)
+                    .useExifOrientation(true) // 自动处理EXIF旋转信息
+                    .toOutputStream(outputStream);
+
+            // 如果大小已满足要求,直接返回
+            if (outputStream.size() <= sizeLimit) {
+                return outputStream.toByteArray();
             }
 
-            ImageWriteParam writeParam = writer.getDefaultWriteParam();
-            writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
-            writeParam.setCompressionQuality(quality);
+            // 逐步降低质量直到满足大小要求
+            double quality = 0.8;
+            int attempts = 5;
 
-            writer.setOutput(ImageIO.createImageOutputStream(baos));
-            writer.write(null, new IIOImage(compressedImage, null, null), writeParam);
-            writer.dispose();
+            while (outputStream.size() > sizeLimit && attempts-- > 0) {
+                outputStream.reset();
+                Thumbnails.of(new ByteArrayInputStream(imageData))
+                        .size(768, 1024)
+                        .outputFormat("jpg")
+                        .outputQuality(quality)
+                        .useExifOrientation(true)
+                        .toOutputStream(outputStream);
 
-            float ratio = sizeLimit * 1.0f / baos.size();
-            quality *= Math.sqrt(ratio);
-            retries--;
-        }
+                quality *= 0.8; // 每次降低20%质量
+            }
 
-        return baos.toByteArray();
+            return outputStream.toByteArray();
+        } finally {
+            outputStream.close();
+        }
     }
 
+//    /**
+//     // * 图片缩放、压缩、旋转处理
+//     // *
+//     // * @param imageData
+//     // * @return
+//     // * @throws IOException
+//     // * @throws ImageProcessingException
+//     // * @throws MetadataException
+//     //     */
+//    public static byte[] compressImage(byte[] imageData) throws IOException {
+//        if (imageData == null || imageData.length == 0) {
+//            throw new IllegalArgumentException("图像数据不能为空");
+//        }
+//
+//        try {
+//            // 读取原始图像(处理旋转问题)
+//            Metadata metadata = ImageMetadataReader.readMetadata(new ByteArrayInputStream(imageData));
+//            if (metadata.containsDirectoryOfType(ExifIFD0Directory.class)) {
+//                ExifIFD0Directory exifIFD0Directory = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
+//                if (exifIFD0Directory.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) {
+//                    // 获取 Orientation 标签的值
+//                    int orientation = exifIFD0Directory.getInt(ExifIFD0Directory.TAG_ORIENTATION);
+//                    // 需要旋转图片
+//                    BufferedImage originalImage = ImageIO.read(new ByteArrayInputStream(imageData));
+//                    if (originalImage == null) {
+//                        throw new IOException("无法读取图像数据");
+//                    }
+//
+//                    AffineTransform transform = new AffineTransform();
+//                    if (orientation == 6) {
+//                        transform.rotate(Math.PI / 2, originalImage.getWidth() / 2, originalImage.getHeight() / 2);
+//                    } else if (orientation == 8) {
+//                        transform.rotate(-Math.PI / 2, originalImage.getWidth() / 2, originalImage.getHeight() / 2);
+//                    }
+//                    AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR);
+//                    originalImage = op.filter(originalImage, null);
+//                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
+//                    ImageIO.write(originalImage, "jpg", baos);
+//                    imageData = baos.toByteArray();
+//                }
+//            }
+//        } catch (Exception e) {
+//            // 如果EXIF处理失败,继续处理原始图像数据
+//            System.err.println("处理图像EXIF信息时出错: " + e.getMessage());
+//        }
+//
+//        // 缩放图像
+//        String formatName = "JPEG";
+//        ByteArrayInputStream bais = new ByteArrayInputStream(imageData);
+//        BufferedImage originalImage = ImageIO.read(bais);
+//
+//        if (originalImage == null) {
+//            throw new IOException("无法读取图像数据");
+//        }
+//
+//        // 确保图像是兼容的格式
+//        BufferedImage compatibleImage = convertToSupportedFormat(originalImage);
+//
+//        long sizeLimit = 366912; //358KB
+//        int width = 768;
+//        int height = 1024;
+//
+//        // 使用更高质量的缩放方法
+//        Image scaledImage = originalImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);
+//        BufferedImage resizedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
+//        Graphics2D g2d = resizedImage.createGraphics();
+//        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
+//        g2d.drawImage(scaledImage, 0, 0, null);
+//        g2d.dispose();
+//
+//        // 压缩图像
+//        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+//        try {
+//            boolean success = ImageIO.write(resizedImage, formatName, baos);
+//            if (!success) {
+//                throw new IOException("无法写入JPEG格式图像");
+//            }
+//        } catch (Exception e) {
+//            // 尝试使用ImageWriter直接写入
+//            writeImageWithDefaultSettings(resizedImage, baos, formatName);
+//        }
+//
+//        if (baos.size() <= sizeLimit) {
+//            // 图片大小已经小于等于目标大小,直接返回原始数据
+//            return baos.toByteArray();
+//        }
+//
+//        float quality = 0.9f; // 初始化压缩质量
+//        int retries = 10; // 最多尝试 10 次
+//
+//        while (baos.size() > sizeLimit && retries > 0) {
+//            // 压缩图像并重新计算压缩质量
+//            byte[] data = baos.toByteArray();
+//            bais = new ByteArrayInputStream(data);
+//            BufferedImage compressedImage = ImageIO.read(bais);
+//
+//            if (compressedImage == null) {
+//                throw new IOException("无法读取压缩后的图像数据");
+//            }
+//
+//            baos.reset();
+//
+//            ImageWriter writer = null;
+//            Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(formatName.toLowerCase());
+//            if (!writers.hasNext()) {
+//                // 尝试其他格式
+//                writers = ImageIO.getImageWritersByFormatName("jpeg");
+//            }
+//
+//            if (writers.hasNext()) {
+//                writer = writers.next();
+//            } else {
+//                throw new IllegalArgumentException("Unsupported image format: " + formatName);
+//            }
+//
+//            try {
+//                ImageWriteParam writeParam = writer.getDefaultWriteParam();
+//                if (writeParam.canWriteCompressed()) {
+//                    writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
+//                    writeParam.setCompressionQuality(quality);
+//                }
+//
+//                try (ImageOutputStream ios = ImageIO.createImageOutputStream(baos)) {
+//                    writer.setOutput(ios);
+//                    writer.write(null, new IIOImage(compressedImage, null, null), writeParam);
+//                }
+//            } finally {
+//                writer.dispose();
+//            }
+//
+//            float ratio = sizeLimit * 1.0f / baos.size();
+//            quality *= Math.sqrt(ratio);
+//            retries--;
+//        }
+//
+//        return baos.toByteArray();
+//    }
+//
+//    /**
+//     * 转换图像为支持的格式
+//     */
+//    private static BufferedImage convertToSupportedFormat(BufferedImage image) {
+//        if (image == null) return null;
+//
+//        // 检查是否为支持的类型
+//        int type = image.getType();
+//        if (type != BufferedImage.TYPE_INT_RGB && type != BufferedImage.TYPE_INT_ARGB) {
+//            // 转换为支持的格式
+//            BufferedImage converted = new BufferedImage(
+//                    image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_RGB);
+//            Graphics2D g = converted.createGraphics();
+//            g.setColor(Color.WHITE);
+//            g.fillRect(0, 0, converted.getWidth(), converted.getHeight());
+//            g.drawImage(image, 0, 0, null);
+//            g.dispose();
+//            return converted;
+//        }
+//        return image;
+//    }
+//
+//    /**
+//     * 使用默认设置写入图像
+//     */
+//    private static void writeImageWithDefaultSettings(BufferedImage image, ByteArrayOutputStream baos, String formatName) throws IOException {
+//        Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(formatName.toLowerCase());
+//        if (!writers.hasNext()) {
+//            writers = ImageIO.getImageWritersByFormatName("jpeg");
+//        }
+//
+//        if (!writers.hasNext()) {
+//            throw new IOException("找不到JPEG图像写入器");
+//        }
+//
+//        ImageWriter writer = writers.next();
+//        ImageWriteParam param = writer.getDefaultWriteParam();
+//
+//        try (ImageOutputStream ios = ImageIO.createImageOutputStream(baos)) {
+//            writer.setOutput(ios);
+//            writer.write(null, new IIOImage(image, null, null), param);
+//        } finally {
+//            writer.dispose();
+//        }
+//    }
+
     /**
      * 设置图片的定位、大小和合并单元格处理
      *
@@ -366,4 +607,46 @@ public class FileUtils {
         String path = sys_file_net_url + fileUrl.replaceAll("//", "/").replaceAll(file_path2, "");
         return path;
     }
+
+    /**
+     * 获取本地文件,若不存在则从URL下载
+     */
+    public static Path getOrDownloadFile(String localPath) throws IOException {
+        Path path = Paths.get(localPath);
+
+        // 如果本地文件不存在,则从URL下载
+        if (!Files.exists(path)) {
+            System.out.println("本地文件不存在,开始下载...");
+            // 确保父目录存在
+            Path parentDir = path.getParent();
+            if (parentDir != null && !Files.exists(parentDir)) {
+                Files.createDirectories(parentDir);
+            }
+
+            // 从URL下载文件
+            try (InputStream in = CommonUtil.getOSSInputStream(getNetUrl(localPath))) {
+                Files.copy(in, path);
+                System.out.println("文件下载成功: " + path);
+            } catch (IOException e) {
+                throw new IOException("下载文件失败: " + e.getMessage(), e);
+            }
+        }
+        return path;
+    }
+
+    /**
+     * 生成带后缀的副本路径
+     */
+    public static Path generateCopyPath(Path originalPath, Long pKeyId) {
+        String suffix = "_" + pKeyId + "_copy";
+        String fileName = originalPath.getFileName().toString();
+        int dotIndex = fileName.lastIndexOf('.');
+
+        // 处理带扩展名和不带扩展名的文件
+        String newName = (dotIndex > 0)
+                ? fileName.substring(0, dotIndex) + suffix + fileName.substring(dotIndex)
+                : fileName + suffix;
+
+        return originalPath.resolveSibling(newName);
+    }
 }

+ 11 - 1
blade-service/blade-business/src/main/java/org/springblade/business/utils/PDFUtil.java

@@ -135,6 +135,11 @@ public class PDFUtil {
                 // 特殊处理
                 if(textStr.indexOf("1")>=0){
                     String txt = textStr.substring(textStr.indexOf("1"));
+                    for (int i = 0; i < txt.length(); i++) {
+                        if (!Character.isDigit(txt.charAt(i))) {
+                            txt=txt.substring(0,i);
+                        }
+                    }
                     if (txt.length() >= 15 && Func.isNumeric(txt)||(Func.isNumeric(txt)&&txt.length()==8&&txt.startsWith("123"))) {
                         System.out.println(txt);
                         eVisaConfigList.add(txt);
@@ -169,7 +174,12 @@ public class PDFUtil {
                         }
                     }
                     if(textString.startsWith("1")){
-                        if (textString.length() >= 15 && Func.isNumeric(textString)) {
+                        for (int i = 0; i < textString.length(); i++) {
+                            if (!Character.isDigit(textString.charAt(i))) {
+                                textString=textString.substring(0,i);
+                            }
+                        }
+                        if (textString.length() >= 15 && Func.isNumeric(textString)||(Func.isNumeric(textString)&&textString.length()==8&&textString.startsWith("123"))) {
                             eVisaConfigList.add("✹" + textString);
                         }
                     }

+ 1 - 1
blade-service/blade-e-visa/pom.xml

@@ -334,7 +334,7 @@
                     <target>${java.version}</target>
                     <encoding>${project.build.sourceEncoding}</encoding>
                     <compilerArguments>
-                        <bootclasspath>${java.home}/lib/rt.jar:${java.home}/lib/jce.jar:${java.home}/lib/jsse.jar
+                        <bootclasspath>${java.home}/lib/rt.jar${path.separator}${java.home}/lib/jce.jar${path.separator}${java.home}/lib/jsse.jar
                         </bootclasspath>
                     </compilerArguments>
                 </configuration>

+ 82 - 62
blade-service/blade-e-visa/src/main/java/org/springblade/evisa/service/impl/EVDataServiceImpl.java

@@ -87,8 +87,8 @@ public class EVDataServiceImpl implements EVDataService {
             this.addSignatureTaskBatch(taskApp);
             //for循环 pdfUrl分割
             String fileUrl = CommonUtil.replaceOssUrl(taskApp.getSignPdfUrl());
-            List<String> eVisaConfigList = PDFUtils.getPdfSignIds(fileUrl, taskApp);
-            if (eVisaConfigList == null || eVisaConfigList.size() == 0) {
+            Map<String, Integer> eVisaConfigMap = PDFUtils.getPdfSignIds(fileUrl, taskApp);
+            if (eVisaConfigMap == null || eVisaConfigMap.size() == 0) {
                 //没有电签配置,默认当前任务为不签字审批,返回成功
                 taskApp.setSigState(2);
                 taskApp.setSignSmg("pdf未获取到关键字Id");
@@ -96,7 +96,7 @@ public class EVDataServiceImpl implements EVDataService {
                 return;
             }
             // 获取pdf上的电签Ids
-            String ids = String.join(",", eVisaConfigList);
+            String ids = String.join(",", eVisaConfigMap.keySet());
             if (taskApp.getRemarkType().equals("1")) { //安心签
                 //添加电签策略
                 List<SealStrategyVO> strategyListByAXQ = getStrategyListByAXQ(taskApp, ids);
@@ -120,6 +120,15 @@ public class EVDataServiceImpl implements EVDataService {
                     }
                     SignBackPdfInfo(taskApp);
                     return;
+                } else {
+                    // 优先使用项目配置的电签
+                    Map<Integer, SealStrategyVO> map = new HashMap<>();
+                    strategyListByAXQ.forEach(item -> {
+                        if (!item.getKeyword().contains("✹")) {
+                            map.put(eVisaConfigMap.get(item.getKeyword()), item);
+                        }
+                    });
+                    strategyListByAXQ.removeIf(item -> item.getKeyword().contains("✹") && map.containsKey(eVisaConfigMap.get(item.getKeyword())));
                 }
 
                 //调用签字逻辑
@@ -135,6 +144,17 @@ public class EVDataServiceImpl implements EVDataService {
             } else if (taskApp.getRemarkType().equals("2") || taskApp.getRemarkType().equals("3")) { //东方中讯
                 //添加电签策略
                 List<Map<String, Object>> strategyListByDFZX = getStrategyListByDFZX(taskApp, ids);
+                if (strategyListByDFZX != null && !strategyListByDFZX.isEmpty()) {
+                    // 优先使用项目配置的电签
+                    Map<Integer, Integer> map = new HashMap<>();
+                    strategyListByDFZX.forEach(item -> {
+                        String keyword = item.get("keyword") + "";
+                        if (!keyword.contains("✹")) {
+                            map.put(eVisaConfigMap.get(keyword), 1);
+                        }
+                    });
+                    strategyListByDFZX.removeIf(item -> (item.get("keyword") + "").contains("✹") && map.containsKey(eVisaConfigMap.get(item.get("keyword") + "")));
+                }
                 //调用签字逻辑
                 String s = signTaskBatchByDFZX(strategyListByDFZX, fileUrl, taskApp.getSigType(),taskApp.getRemarkType(),taskApp.getContractId());
                 if (s.contains("sucess")) {
@@ -575,7 +595,7 @@ public class EVDataServiceImpl implements EVDataService {
                     List<Map<String, Object>> maps3 = jdbcTemplate.queryForList(sql);
                     System.out.println("东方中讯--签字--key =" + sql);
                     if (!maps3.isEmpty()) {
-                        Map<String, List<Map<String, Object>>> peopleByAge = maps2.stream()
+                        Map<String, List<Map<String, Object>>> peopleByAge = maps3.stream()
                                 .collect(Collectors.groupingBy(hada -> (Func.toStr(hada.get("keyWord")))));
                         for (String keyId : peopleByAge.keySet()) {
                             List<Map<String, Object>> keyList = peopleByAge.get(keyId);
@@ -629,8 +649,8 @@ public class EVDataServiceImpl implements EVDataService {
                     }
                     maps2 = jdbcTemplate.queryForList(sqlinfo);
                 }
+                List<Map<String, Object>> maps = new ArrayList<>();
                 if (maps2 != null && maps2.size() > 0) {
-                    List<Map<String, Object>> maps = new ArrayList<>();
                     Map<String, List<Map<String, Object>>> peopleByAge = maps2.stream()
                             .collect(Collectors.groupingBy(hada -> (Func.toStr(hada.get("id")))));
 
@@ -652,68 +672,68 @@ public class EVDataServiceImpl implements EVDataService {
                             maps.add(keyList.get(0));
                         }
                     }
-                    if (signIds.length() > 0 && task.getSigType() != 2) {
-                        String sql = "SELECT * from ( SELECT DISTINCT a.conf_id as id,0.0 as pyzbx ,0.0 as pyzby,(SELECT signature_file_url from m_sign_pfx_file where is_register=1 and certificate_user_id='"
-                                + userId + "' and is_deleted=0  ) as signature_file_url, (SELECT wide from m_sign_pfx_file where is_register=1 and certificate_user_id='"
-                                + userId + "' and is_deleted=0  ) as wide ,(SELECT high from m_sign_pfx_file where is_register=1 and certificate_user_id='"
-                                + userId + "' and is_deleted=0  ) as high from m_sign_config_relation a where a.type = 1 and a.is_deleted = 0 and a.conf_id in (" + signIds + ") and a.relation_id in (SELECT DISTINCT c.role_id from m_project_assignment_user c  where c.contract_id="
-                                + task.getContractId() + " and user_id=" + userId + " and c.is_deleted=0 ) ) x where x.signature_file_url is not null ";
-                        List<Map<String, Object>> maps3 = jdbcTemplate.queryForList(sql);
-                        System.out.println("安心签--签章--key =" + sql);
-                        if (!maps3.isEmpty()) {
-                            Map<String, List<Map<String, Object>>> peopleByAges = maps3.stream()
-                                    .collect(Collectors.groupingBy(hada -> (Func.toStr(hada.get("id")))));
-                            for (String keyId : peopleByAges.keySet()) {
-                                List<Map<String, Object>> keyList = peopleByAges.get(keyId);
-                                if (keyList != null && !keyList.isEmpty()) {
-                                    Map<String, Object> map = keyList.get(0);
-                                    map.put("id", "✹" + map.get("id"));
-                                    maps.add(map);
-                                }
+                }
+                if (signIds.length() > 0 && task.getSigType() != 2) {
+                    String sql = "SELECT * from ( SELECT DISTINCT a.conf_id as id,0.0 as pyzbx ,0.0 as pyzby,(SELECT signature_file_url from m_sign_pfx_file where is_register=1 and certificate_user_id='"
+                            + userId + "' and is_deleted=0  ) as signature_file_url, (SELECT wide from m_sign_pfx_file where is_register=1 and certificate_user_id='"
+                            + userId + "' and is_deleted=0  ) as wide ,(SELECT high from m_sign_pfx_file where is_register=1 and certificate_user_id='"
+                            + userId + "' and is_deleted=0  ) as high from m_sign_config_relation a where a.type = 1 and a.is_deleted = 0 and a.conf_id in (" + signIds + ") and a.relation_id in (SELECT DISTINCT c.role_id from m_project_assignment_user c  where c.contract_id="
+                            + task.getContractId() + " and user_id=" + userId + " and c.is_deleted=0 ) ) x where x.signature_file_url is not null ";
+                    List<Map<String, Object>> maps3 = jdbcTemplate.queryForList(sql);
+                    System.out.println("安心签--签章--key =" + sql);
+                    if (!maps3.isEmpty()) {
+                        Map<String, List<Map<String, Object>>> peopleByAges = maps3.stream()
+                                .collect(Collectors.groupingBy(hada -> (Func.toStr(hada.get("id")))));
+                        for (String keyId : peopleByAges.keySet()) {
+                            List<Map<String, Object>> keyList = peopleByAges.get(keyId);
+                            if (keyList != null && !keyList.isEmpty()) {
+                                Map<String, Object> map = keyList.get(0);
+                                map.put("id", "✹" + map.get("id"));
+                                maps.add(map);
                             }
                         }
                     }
-                    if (maps == null || maps.size() <= 0) {
-                        break;
-                    }
-                    //准备签章策略
-                    for (Map<String, Object> eVisaConfig : maps) {
-                        //设置签章策略
-                        SealStrategyVO vo = new SealStrategyVO();
-                        if (task.getSigType() == 1) {
-                            vo.setSealCode(EVisaConstant.SIGN_SEAL_CODE + userId);
-                            if (userId.length() <= EVisaConstant.USER_ID_SUB) {
-                                vo.setSealPassword(userId.toString());
-                            } else {
-                                vo.setSealPassword(userId.substring(0, EVisaConstant.USER_ID_SUB));
-                            }
-                            vo.setSealPerson(userNames[i]);
-                            //设置签字文件
-                            vo.setImageUrl(eVisaConfig.get("signature_file_url") + "");
-                            vo.setSealType("3");
-                            vo.setKeyword(eVisaConfig.get("id") + "");
-                            vo.setOffSetX(eVisaConfig.get("pyzbx") + "");
-                            vo.setOffSetY(eVisaConfig.get("pyzby") + "");
-                            vo.setHeight(eVisaConfig.get("high") + "");
-                            vo.setWidth(eVisaConfig.get("wide") + "");
-                            vo.setProjectId(eVisaConfig.get("project_id") + "");
-                        } else if (task.getSigType() == 2) {
-                            vo.setSealCode(EVisaConstant.SIGN_SEAL_CODE + eVisaConfig.get("sfId"));
-                            vo.setSealPassword(eVisaConfig.get("certificate_password") + "");
-                            vo.setSealPerson(eVisaConfig.get("certificate_user_name") + "" + System.currentTimeMillis());
-                            //设置签字文件
-                            vo.setImageUrl(eVisaConfig.get("signature_file_url") + "");
-                            vo.setSealType("3");
-                            vo.setCompanySeal(true);
-                            vo.setKeyword(eVisaConfig.get("id") + "");
-                            vo.setOffSetX(eVisaConfig.get("pyzbx") + "");
-                            vo.setOffSetY(eVisaConfig.get("pyzby") + "");
-                            vo.setHeight(eVisaConfig.get("high") + "");
-                            vo.setWidth(eVisaConfig.get("wide") + "");
-                            vo.setProjectId(eVisaConfig.get("project_id") + "");
+                }
+                if (maps.size() <= 0) {
+                    break;
+                }
+                //准备签章策略
+                for (Map<String, Object> eVisaConfig : maps) {
+                    //设置签章策略
+                    SealStrategyVO vo = new SealStrategyVO();
+                    if (task.getSigType() == 1) {
+                        vo.setSealCode(EVisaConstant.SIGN_SEAL_CODE + userId);
+                        if (userId.length() <= EVisaConstant.USER_ID_SUB) {
+                            vo.setSealPassword(userId.toString());
+                        } else {
+                            vo.setSealPassword(userId.substring(0, EVisaConstant.USER_ID_SUB));
                         }
-                        sealStrategyVOS.add(vo);
+                        vo.setSealPerson(userNames[i]);
+                        //设置签字文件
+                        vo.setImageUrl(eVisaConfig.get("signature_file_url") + "");
+                        vo.setSealType("3");
+                        vo.setKeyword(eVisaConfig.get("id") + "");
+                        vo.setOffSetX(eVisaConfig.get("pyzbx") + "");
+                        vo.setOffSetY(eVisaConfig.get("pyzby") + "");
+                        vo.setHeight(eVisaConfig.get("high") + "");
+                        vo.setWidth(eVisaConfig.get("wide") + "");
+                        vo.setProjectId(eVisaConfig.get("project_id") + "");
+                    } else if (task.getSigType() == 2) {
+                        vo.setSealCode(EVisaConstant.SIGN_SEAL_CODE + eVisaConfig.get("sfId"));
+                        vo.setSealPassword(eVisaConfig.get("certificate_password") + "");
+                        vo.setSealPerson(eVisaConfig.get("certificate_user_name") + "" + System.currentTimeMillis());
+                        //设置签字文件
+                        vo.setImageUrl(eVisaConfig.get("signature_file_url") + "");
+                        vo.setSealType("3");
+                        vo.setCompanySeal(true);
+                        vo.setKeyword(eVisaConfig.get("id") + "");
+                        vo.setOffSetX(eVisaConfig.get("pyzbx") + "");
+                        vo.setOffSetY(eVisaConfig.get("pyzby") + "");
+                        vo.setHeight(eVisaConfig.get("high") + "");
+                        vo.setWidth(eVisaConfig.get("wide") + "");
+                        vo.setProjectId(eVisaConfig.get("project_id") + "");
                     }
+                    sealStrategyVOS.add(vo);
                 }
             }
         }

+ 3 - 3
blade-service/blade-e-visa/src/main/java/org/springblade/evisa/service/impl/EVisaServiceImpl.java

@@ -797,9 +797,9 @@ public class EVisaServiceImpl implements EVisaService {
         if ("20".equals(sys_isonline) || SystemUtils.isWindows() || SystemUtils.isMacOs()) {
             url = "http://219.151.181.73:9125/FrontSys/SealServicezx/FileSignByKeyWord";
         }
-        if(signPdfByDFZX.equals("3")){
-            url = "http://10.0.0.4:9125/FrontSys/SealServicezx/FileSignByKeyWord";
-        }
+//        if(signPdfByDFZX.equals("3")){
+//            url = "http://10.0.0.4:9125/FrontSys/SealServicezx/FileSignByKeyWord";
+//        }
 
 
         String sysLocalFileUrl = FileUtils.getSysLocalFileUrl();

+ 41 - 18
blade-service/blade-e-visa/src/main/java/org/springblade/evisa/utils/PDFUtils.java

@@ -8,18 +8,15 @@ import org.springblade.common.utils.CommonUtil;
 import org.springblade.core.tool.utils.Func;
 
 import java.io.*;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Optional;
+import java.util.*;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 
 public class PDFUtils {
-
-
-    public static List<String>  getPdfSignIds(String pdfUrl, TaskSignInfoVO taskApp) {
-        List<String> eVisaConfigList = new ArrayList<>();
+    public static Map<String, Integer>  getPdfSignIds(String pdfUrl, TaskSignInfoVO taskApp) {
+//        List<String> eVisaConfigList = new ArrayList<>();
+        Map<String, Integer> eVisaConfigMap = new HashMap<>();
         try  {
             InputStream inputStream = CommonUtil.getOSSInputStream(pdfUrl);
             PDDocument document = PDDocument.load(inputStream);
@@ -45,7 +42,8 @@ public class PDFUtils {
                         }
                     }
                     if (txt.length() >= 15 && Func.isNumeric(txt)||(Func.isNumeric(txt)&&txt.length()==8&&txt.startsWith("123"))) {
-                        eVisaConfigList.add(txt);
+//                        eVisaConfigList.add(txt);
+                        eVisaConfigMap.put(txt,k);
                     }
                 }
                 if (taskApp.getPdfDate() == null || taskApp.getPdfDate().isEmpty()) {
@@ -62,16 +60,23 @@ public class PDFUtils {
                         }
                     }
                     if (txt.length() >= 15 && Func.isNumeric(txt)||(Func.isNumeric(txt)&&txt.length()==8&&txt.startsWith("123"))) {
-                        eVisaConfigList.add(txt);
+//                        eVisaConfigList.add(txt);
+                        eVisaConfigMap.put(txt,k);
                     }
                 }
 
                 // 特殊处理
                 if(textStr.indexOf("1")>=0){
                     String txt = textStr.substring(textStr.indexOf("1"));
+                    for (int i = 0; i < txt.length(); i++) {
+                        if (!Character.isDigit(txt.charAt(i))) {
+                            txt=txt.substring(0,i);
+                        }
+                    }
                     if (txt.length() >= 15 && Func.isNumeric(txt)||(Func.isNumeric(txt)&&txt.length()==8&&txt.startsWith("123"))) {
                         System.out.println(txt);
-                        eVisaConfigList.add(txt);
+//                        eVisaConfigList.add(txt);
+                        eVisaConfigMap.put(txt,k);
                     }
                 }
                 if (textStr.contains("✹") && textStr.indexOf("✹") + 1 < textStr.length()) {
@@ -85,7 +90,8 @@ public class PDFUtils {
                                 }
                             }
                             if (txt.length() >= 15 && Func.isNumeric(txt)||(Func.isNumeric(txt)&&txt.length()==8&&txt.startsWith("123"))) {
-                                eVisaConfigList.add("✹" + txt);
+//                                eVisaConfigList.add("✹" + txt);
+                                eVisaConfigMap.put("✹" + txt,k);
                             }
                         }
                     }
@@ -98,26 +104,33 @@ public class PDFUtils {
                                 }
                             }
                             if (txt.length() >= 15 && Func.isNumeric(txt)||(Func.isNumeric(txt)&&txt.length()==8&&txt.startsWith("123"))) {
-                                eVisaConfigList.add("✹" + txt);
+//                                eVisaConfigList.add("✹" + txt);
+                                eVisaConfigMap.put("✹" + txt,k);
                             }
                         }
                     }
                     if(textString.startsWith("1")){
-                        if (textString.length() >= 15 && Func.isNumeric(textString)) {
-                            eVisaConfigList.add("✹" + textString);
+                        for (int i = 0; i < textString.length(); i++) {
+                            if (!Character.isDigit(textString.charAt(i))) {
+                                textString=textString.substring(0,i);
+                            }
+                        }
+                        if (textString.length() >= 15 && Func.isNumeric(textString)||(Func.isNumeric(textString)&&textString.length()==8&&textString.startsWith("123"))) {
+//                            eVisaConfigList.add("✹" + textString);
+                            eVisaConfigMap.put("✹" + textString,k);
                         }
                     }
                 }
             }
 
 
-            List<String> unique = eVisaConfigList.stream().distinct().collect(Collectors.toList());
+//            List<String> unique = eVisaConfigList.stream().distinct().collect(Collectors.toList());
             document.close();
-            return unique;
+            return eVisaConfigMap;
         }catch (Exception e){
             e.printStackTrace();
             System.out.println("pdf大小为0");
-            return eVisaConfigList;
+            return eVisaConfigMap;
         }
     }
 
@@ -167,6 +180,11 @@ public class PDFUtils {
                 // 特殊处理
                 if(textStr.indexOf("1")>=0){
                     String txt = textStr.substring(textStr.indexOf("1"));
+                    for (int i = 0; i < txt.length(); i++) {
+                        if (!Character.isDigit(txt.charAt(i))) {
+                            txt=txt.substring(0,i);
+                        }
+                    }
                     if (txt.length() >= 15 && Func.isNumeric(txt)||(Func.isNumeric(txt)&&txt.length()==8&&txt.startsWith("123"))) {
                         System.out.println(txt);
                         eVisaConfigList.add(txt);
@@ -201,7 +219,12 @@ public class PDFUtils {
                         }
                     }
                     if(textString.startsWith("1")){
-                        if (textString.length() >= 15 && Func.isNumeric(textString)) {
+                        for (int i = 0; i < textString.length(); i++) {
+                            if (!Character.isDigit(textString.charAt(i))) {
+                                textString=textString.substring(0,i);
+                            }
+                        }
+                        if (textString.length() >= 15 && Func.isNumeric(textString)||(Func.isNumeric(textString)&&textString.length()==8&&textString.startsWith("123"))) {
                             eVisaConfigList.add("✹" + textString);
                         }
                     }

+ 13 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/APIController.java

@@ -13,6 +13,7 @@ import org.springblade.core.tool.utils.Func;
 import org.springblade.manager.service.IWbsTreeContractService;
 import org.springblade.manager.vo.APIWbsContractNodeHzrcVo;
 import org.springblade.manager.vo.APIWbsContractNodeVo;
+import org.springblade.manager.vo.APIWbsContractSubdivisionVo;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.web.bind.annotation.*;
 
@@ -93,4 +94,16 @@ public class APIController extends BladeController {
         }
         return R.fail(200, "未查询到信息");
     }
+
+    /**
+     * 获取某一合同段的分部分项划分
+     */
+    @GetMapping("/getWbsContractSubdivision")
+    @ApiOperationSupport(order = 5)
+    @ApiOperation(value = "获取某一合同段的分部分项划分", notes = "合同")
+    @ApiImplicitParam(name = "sectionId", value = "合同段Id", required = true)
+    public R<List<APIWbsContractSubdivisionVo>> getWbsContractSubdivision(String sectionId){
+        List<APIWbsContractSubdivisionVo> list = iWbsTreeContractService.getWbsContractSubdivision(sectionId);
+        return R.data(list);
+    }
 }

+ 76 - 603
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ExcelTabController.java

@@ -46,12 +46,14 @@ import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.mp.support.Condition;
 import org.springblade.core.mp.support.Query;
 import org.springblade.core.oss.model.BladeFile;
+import org.springblade.core.redis.cache.BladeRedis;
 import org.springblade.core.secure.BladeUser;
 import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.secure.utils.SecureUtil;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.constant.BladeConstant;
 import org.springblade.core.tool.utils.*;
+import org.springblade.evisa.redissionUtil.DistributedRedisLock;
 import org.springblade.manager.bean.TableInfo;
 import org.springblade.manager.dto.AddBussFileSortDTO;
 import org.springblade.manager.entity.*;
@@ -79,9 +81,12 @@ import org.springframework.mock.web.MockMultipartFile;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
 import org.springframework.web.multipart.MultipartFile;
 
 import javax.imageio.ImageIO;
+import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.validation.Valid;
 import java.awt.*;
@@ -94,10 +99,13 @@ import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.nio.file.StandardCopyOption;
+import java.sql.SQLException;
 import java.text.SimpleDateFormat;
 import java.util.List;
 import java.util.*;
+import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -166,6 +174,7 @@ public class ExcelTabController extends BladeController {
 
     private final WbsTreeContractMapper wbsTreeContractMapper;
 
+    private final WbsTreeContractOldHtmlService wbsTreeContractOldHtmlService;
     private final WbsTreeContractStatisticsClient wbsTreeContractStatisticsClient;
 
 
@@ -345,10 +354,13 @@ public class ExcelTabController extends BladeController {
         detail.setHtmlUrl(thmlUrl);
         excelTabService.saveOrUpdate(detail);
         // 解析html
-        expailHtmlInfo(thmlUrl, detail.getId(), detail.getTabType() + "");
+        excelTabService.expailHtmlInfo(thmlUrl, detail.getId(), detail.getTabType() + "");
         return R.success("上传成功");
     }
 
+    public void checkHtml(){
+
+    }
 
 
     public static InputStream getOSSInputStream(String urlStr) throws Exception {
@@ -462,7 +474,7 @@ public class ExcelTabController extends BladeController {
     @PostMapping("/sava-dataInfo")
     @ApiOperationSupport(order = 13)
     @ApiOperation(value = "编辑-保存", notes = "编辑-保存")
-    public R<List<WbsTreeVO>> savaDataInfo(@Valid @RequestBody WbsExclTabParmVO wbsExclTabParmVO, BladeUser bladeUser) throws IOException {
+    public R<List<WbsTreeVO>> savaDataInfo(@Valid @RequestBody WbsExclTabParmVO wbsExclTabParmVO, BladeUser bladeUser) throws Exception {
         // 保存节点信息
         ExcelTab excelTab = new ExcelTab();
         if (wbsExclTabParmVO.getId() != null) {// 修改
@@ -533,7 +545,7 @@ public class ExcelTabController extends BladeController {
             @ApiImplicitParam(name = "exceTabId", value = "清表id", required = true),
             @ApiImplicitParam(name = "tabId", value = "表Id", required = true),
     })
-    public R<List<ExceTabTreVO>> saveLinkeTab(Long exceTabId, Long tabId) throws IOException {
+    public R<List<ExceTabTreVO>> saveLinkeTab(Long exceTabId, Long tabId) throws Exception {
         String file_path = FileUtils.getSysLocalFileUrl();
         // 关联 私有项目 wbs 数据信息
         WbsTreePrivate wbsTree = new WbsTreePrivate();
@@ -603,17 +615,20 @@ public class ExcelTabController extends BladeController {
 
                     for (WbsFormElement elementInfo : elementList) {
                         String ysName = elementInfo.getEName();
-                        if (titleName.equals(ysName)) {
+                         if (titleName.equals(ysName)) {
                             lastName = elementInfo.getEName();
                             attrInfo = elementInfo.getEKey() + "__" + i + "_" + j;
+
                             filedType = WbsElementUtil.getInitTableFiledType(elementInfo.getEType());
+
                             filedLength = elementInfo.getELength().toString();
 
                             maxScore = 100;
                             is_true = true;
                             break;
                         } else {
-                            if (MathUtil.sim(titleName, ysName) > maxScore) {
+                             List<String> list = Arrays.asList(titleName.split("_"));
+                             if (list.contains(ysName)) {
                                 attrInfo = elementInfo.getEKey() + "__" + i + "_" + j;
 
                                 filedType = WbsElementUtil.getInitTableFiledType(elementInfo.getEType());
@@ -623,6 +638,7 @@ public class ExcelTabController extends BladeController {
                                 lastName = ysName;
                                 maxScore = MathUtil.sim(titleName, ysName);
                                 is_true = true;
+                                break;
                             }
                         }
                     }
@@ -708,6 +724,14 @@ public class ExcelTabController extends BladeController {
 
         try {
             String fileUrl = wbsTreeContract.getHtmlUrl();
+            //如果有历史html就使用历史html
+            WbsTreeContractOldHtml one = wbsTreeContractOldHtmlService.getOne(Wrappers.<WbsTreeContractOldHtml>lambdaQuery()
+                    .eq(WbsTreeContractOldHtml::getContractFormId, pkeyId)
+                    .eq(WbsTreeContractOldHtml::getIsDeleted, 0)
+                    .last("limit 1"));
+            if(one != null && StringUtils.isNotEmpty(one.getOldHtmlUrl())){
+                fileUrl = one.getOldHtmlUrl();
+            }
             InputStream fileInputStream = FileUtils.getInputStreamByUrl(fileUrl);
             String htmlString = IoUtil.readToString(fileInputStream);
             htmlString = htmlString.replaceAll("placeholder", "placeholderxx");
@@ -996,598 +1020,6 @@ public class ExcelTabController extends BladeController {
         return doc.select("table").first() + "";
     }
 
-    // 上传解析 html
-    public void expailHtmlInfo(String thmlUrl, Long excelId, String tabType) throws Exception {
-
-        // 读取
-        File file1 = ResourceUtil.getFile(thmlUrl);
-        String htmlString = IoUtil.readToString(new FileInputStream(file1));
-
-        /*
-           解析
-           1 解析样式
-           2 计算坐标
-           3 计算区域位置
-         */
-        // 样式集合
-        Document doc = Jsoup.parse(htmlString);
-        // 解析 style
-        Map<String, String> styleMap = getHtmlStyle(doc);
-        //解析
-        Element table = doc.select("table").first();
-
-        Elements trs = table.select("tr");
-        Element tableinfo = trs.get(0).parent().parent().attr("style", "border-collapse: collapse;");
-
-        // 获取图片信息
-        Elements imgs = doc.select("img");
-
-
-        // 获取总行列数
-        int maxCol = doc.select("Col").size();
-        String[] rowData = new String[trs.size() + 5]; //本来加一的 害怕出现特殊情况 故意 加 5
-
-        // 行的状态
-        boolean index_state = false;
-        // 区域划分表示
-        int xy_type = 1;
-
-        // 解析 excel元素集合
-        List<ExctabCell> colTitle = new ArrayList<>();
-
-//      标题集合信息
-        List<Map<String, String>> zikey = new ArrayList<>();
-        for (int i = 0; i <= trs.size() - 1; i++) {
-            Element tr = trs.get(i);
-            Elements tds = tr.select("td");
-
-            String xyInof = getTrInfo(tds, styleMap, index_state, xy_type, maxCol, i, zikey);
-
-            xy_type = Integer.parseInt(xyInof.split(",")[0]);
-            tr.attr("xy_type", xyInof);
-            index_state = Boolean.parseBoolean(xyInof.split(",")[1]);
-            boolean isMaxCol = Integer.parseInt(xyInof.split(",")[2]) == maxCol;
-
-            boolean istrue = Boolean.parseBoolean(xyInof.split(",")[3]);
-
-
-            // 计算单元格坐标
-            int x = 0;
-
-            for (int j = 0; j < tds.size(); j++) {
-                {
-                    Element data = tds.get(j);
-                    Boolean isText = false;
-                    //判断高度
-                    String style = data.attr("style");
-                    if (StringUtils.isNotBlank(style)) {
-                        int index = style.lastIndexOf(":");
-                        String substring = style.substring(index + 1);
-                        String height = substring.substring(0, substring.length() - 3);
-                        int i1 = 0;
-                        try {
-                            i1 = Integer.parseInt(height);
-                        } catch (NumberFormatException e) {
-                            substring = style.substring(style.lastIndexOf(":", index - 1) + 1);
-                            height = substring.substring(0, substring.indexOf("px;"));
-                            i1 = Integer.parseInt(height);
-                        }
-                        if (i1 > 90) {
-                            isText = true;
-                        }
-                    }
-                    String trHtml = data.html();
-                    int colspan = data.attr("COLSPAN").equals("") ? 0 : Integer.parseInt(data.attr("COLSPAN"));
-                    int rowspan = data.attr("ROWSPAN").equals("") ? 0 : Integer.parseInt(data.attr("ROWSPAN"));
-                    String keyId = data.attr("class");
-                    if (StringUtils.isNotEmpty(keyId)) {
-                        String classInfo = styleMap.get(keyId);
-                        data.removeAttr("class");
-                    }
-
-                    Map<String, String> textObject = new HashMap<>();
-                    // 计算
-                    int x1 = 0;
-                    int x2 = 0;
-                    int y1 = 0;
-                    int y2 = 0;
-
-                    String textInfo = data.text().trim().replaceAll(" ", "");
-
-                    y1 = i + 1;
-                    //x 移位 算法
-                    String getRowInfo = rowData[y1];
-
-                    if (getRowInfo != null) {
-                        String[] dataInfo2 = getRowInfo.split(",");
-
-                        // 排序
-                        int lastMax = 0;
-                        List<String> datax = Arrays.stream(dataInfo2).sorted((a, b) -> Integer.parseInt(a.split(":")[1]) - Integer.parseInt(b.split(":")[1])).collect(Collectors.toList());
-                        List<String> lastdata = new ArrayList<>();
-                        //组合
-                        for (int h = 0; h < datax.size(); h++) {
-                            int mx1 = Integer.parseInt(datax.get(h).split(":")[0]);
-                            int mx2 = Integer.parseInt(datax.get(h).split(":")[1]);
-                            if (lastdata.size() == 0) {
-                                lastdata.add(datax.get(0));
-                            } else {
-                                if (lastMax + 1 == mx1) {
-                                    int minVal = Integer.parseInt(lastdata.get(lastdata.size() - 1).split(":")[0]);
-                                    lastdata.remove(lastdata.size() - 1);
-                                    lastdata.add(minVal + ":" + mx2);
-                                } else {
-                                    lastdata.add(datax.get(h));
-                                }
-                            }
-                            lastMax = mx2;
-                        }
-                        dataInfo2 = lastdata.stream().toArray(String[]::new);
-
-                        // 先逻辑处理 连续时,归一
-                        if ((dataInfo2[0].split(":")[0]).equals("1") && j == 0) {
-                            x = Integer.parseInt(dataInfo2[0].split(":")[1]);
-                        } else {
-                            for (int m = 0; m < dataInfo2.length; m++) {
-                                int mx1 = Integer.parseInt(dataInfo2[m].split(":")[0]);
-                                int mx2 = Integer.parseInt(dataInfo2[m].split(":")[1]);
-                                if ((mx1 - x) == 1 && mx1 > x) {
-                                    x = mx2;
-                                }
-                            }
-                        }
-                    }
-
-                    // X 坐标
-
-
-                    if (tds.size() == 1) {
-                        if (colspan == 0) {
-                            x1 = x + 1;
-                            x2 = x + 1;
-                        } else {
-                            if (x == 0) {
-                                x1 = 1;
-                                x2 = colspan;
-                            } else {
-                                x1 = x + 1;
-                                x2 = x + colspan;
-                            }
-                        }
-                    } else {
-                        if (colspan == 0) {
-                            x1 = x + 1;
-                            x2 = x + 1;
-                            x = x2;
-                        } else {
-                            x1 = x + 1;
-                            x2 = x + colspan;
-                            x = x2;
-                        }
-                    }
-
-
-                    //x y 坐标
-                    if (rowspan == 0) {
-                        y2 = i + 1;
-                    } else {
-                        y2 = i + rowspan;
-                        for (int k = 0; k < rowspan - 1; k++) {
-                            String dataInfo = rowData[k + 2 + i];
-                            if (dataInfo == null) {
-                                dataInfo = x1 + ":" + x2;
-                            } else {
-                                dataInfo = dataInfo + "," + x1 + ":" + x2;
-                                String[] arr = dataInfo.split(",");
-                                //排序
-                                for (int r = 0; r < arr.length - 1; r++) {
-                                    for (int q = arr.length - 2; q >= r; q--) {
-                                        Integer jval = Integer.parseInt(arr[q + 1].split(":")[0]);
-                                        Integer jval1 = Integer.parseInt(arr[q].split(":")[0]);
-                                        if (jval < jval1) {
-                                            String temp = arr[q + 1];
-                                            arr[q + 1] = arr[q];
-                                            arr[q] = temp;
-                                        }
-                                    }
-                                }
-
-                                //组合
-                                String newDataInfo = "";
-                                for (int r = 0; r < arr.length; r++) {
-                                    if (r == 0) {
-                                        newDataInfo = arr[0];
-                                    } else {
-                                        int StrMax = Integer.parseInt(newDataInfo.substring(newDataInfo.lastIndexOf(":") + 1, newDataInfo.length()));
-                                        Integer nowMin = Integer.parseInt(arr[r].split(":")[0]);
-                                        Integer nowMax = Integer.parseInt(arr[r].split(":")[1]);
-                                        if ((StrMax + 1) == nowMin) {
-                                            String lastStr = "";
-                                            if (newDataInfo.indexOf(",") >= 0) {
-                                                lastStr = newDataInfo.substring(newDataInfo.lastIndexOf(",") + 1, newDataInfo.length());
-                                                newDataInfo = newDataInfo.substring(0, newDataInfo.lastIndexOf(","));
-                                            } else {
-                                                lastStr = newDataInfo;
-                                                newDataInfo = "";
-                                            }
-                                            int lastmin = Integer.parseInt(lastStr.split(":")[0]);
-                                            if (StringUtils.isNotEmpty(newDataInfo)) {
-                                                newDataInfo = newDataInfo + "," + lastmin + ":" + nowMax;
-                                            } else {
-                                                newDataInfo = lastmin + ":" + nowMax;
-                                            }
-                                        } else {
-                                            newDataInfo = newDataInfo + "," + nowMin + ":" + nowMax;
-                                        }
-                                    }
-                                }
-                                dataInfo = newDataInfo;
-                            }
-                            rowData[k + 2 + i] = dataInfo;
-                        }
-                    }
-
-                    data.text(textInfo.replaceAll(" ", ""));
-                    if (textInfo.indexOf("□") < 0 && !textInfo.isEmpty() && !(textInfo.equals("/") && textInfo.length() < 2) && !(textInfo.indexOf("年") >= 0 && textInfo.indexOf("月") >= 0 && textInfo.indexOf("日") >= 0) && !textInfo.equals("—") && !textInfo.equals("-")) {  // 标题区域
-                        Map<String, String> dataInfo = new HashMap<String, String>();
-                        dataInfo.put("name", textInfo);
-                        dataInfo.put("x1", x1 + "");
-                        dataInfo.put("x2", x2 + "");
-                        dataInfo.put("y1", y1 + "");
-                        dataInfo.put("y2", y2 + "");
-                        dataInfo.put("xytype", xy_type + "");
-                        if (textInfo.indexOf("/") < 0 || (textInfo.indexOf("/") >= 0 && textInfo.length() > 1)) { // 带/为分割数据
-                            zikey.add(dataInfo);
-                        }
-                    } else { //空行
-                        List<Map<String, String>> left = new ArrayList<>();
-                        List<Map<String, String>> top = new ArrayList<>();
-                        for (int k = 0; k < zikey.size(); k++) {
-                            String name = zikey.get(k).get("name");
-                            int xx1 = Integer.parseInt(zikey.get(k).get("x1"));
-                            int xx2 = Integer.parseInt(zikey.get(k).get("x2"));
-                            int yy1 = Integer.parseInt(zikey.get(k).get("y1"));
-                            int yy2 = Integer.parseInt(zikey.get(k).get("y2"));
-                            int xytype2 = Integer.parseInt(zikey.get(k).get("xytype"));
-
-                            // 左匹配
-                            if (yy1 <= y1 && yy2 >= y2 && xx2 < x1 && xytype2 == xy_type) {
-                                left.add(zikey.get(k));
-                            }
-
-                            //向 上 匹配
-                            if (index_state) {
-                                if (xx1 <= x1 && xx2 >= x2 && yy2 < y1 && xytype2 == xy_type) {
-                                    top.add(zikey.get(k));
-                                }
-                            }
-                        }
-
-                        String inputText = "";
-                        // 特征值赛选 规则
-                        for (int k = 0; k < left.size(); k++) { // 左计算
-                            String name = left.get(k).get("name");
-                            int xx1 = Integer.parseInt(left.get(k).get("x1"));
-                            int xx2 = Integer.parseInt(left.get(k).get("x2"));
-                            int yy1 = Integer.parseInt(left.get(k).get("y1"));
-                            int yy2 = Integer.parseInt(left.get(k).get("y2"));
-
-                            if (!StringUtil.isNumeric(name) && name.length() <= 20) { // 数字不匹配
-                                if (index_state) { // 正向规则匹配
-                                    if (istrue) { // 是否空格等于值
-                                        if (x1 - xx2 <= 1 && y1 == yy2) {
-                                            inputText = name;
-                                        } else {
-                                            inputText += name + "_";
-                                        }
-                                    } else {
-                                        inputText += name + "_";
-                                    }
-                                } else {
-                                    if (x1 - xx2 <= 1 && y1 == yy2) {
-                                        inputText = name;
-                                    }
-                                }
-                            }
-                        }
-
-                        // 特征值赛选 规则
-                        if (top != null && top.size() >= 1) {
-                            for (int k = 0; k < top.size(); k++) { // 向上计算
-                                String name = top.get(k).get("name");
-                                int xx1 = Integer.parseInt(top.get(k).get("x1"));
-                                int xx2 = Integer.parseInt(top.get(k).get("x2"));
-                                int yy1 = Integer.parseInt(top.get(k).get("y1"));
-                                int yy2 = Integer.parseInt(top.get(k).get("y2"));
-                                if (!StringUtil.isNumeric(name) && name.length() <= 20) {
-                                    inputText += name + "_";
-                                }
-                            }
-                        }
-
-                        if (inputText != null && inputText != "" && inputText.indexOf("_") >= 0) {
-                            inputText = inputText.substring(0, inputText.lastIndexOf("_"));
-                        }
-
-                        // 质检表特殊处理匹配
-
-                        String parm = i + "," + j + "," + x1 + "," + x2 + "," + y1 + "," + y2 + ",$event";
-                        // 设置文本信息
-                        ExctabCell exctabCell = new ExctabCell();
-                        if ((textInfo.indexOf("年") >= 0 && textInfo.indexOf("月") >= 0 && textInfo.indexOf("日") >= 0) || inputText.indexOf("日期") >= 0) {
-                            if (inputText.indexOf("日期") >= 0) {
-                                data.empty().append("<el-date-picker type='date' @keyDowns='dateKeydown()' format='YYYY年MM月DD日' value-format='YYYY年MM月DD日' @contextmenu.prevent.native='contextmenuClick(" + parm + ")'  @mouseup.right='RightClick(" + parm + ")' trIndex=" + i + " tdIndex=" + j + "  x1=" + x1 + " x2=" + x2 + " y1=" + y1 + " y2=" + y2 + " style='width:100%;height:100%;' placeholder='" + inputText + "'> </el-date-picker>");
-                            } else if (textInfo.indexOf("年") >= 0 && textInfo.indexOf("月") >= 0 && textInfo.indexOf("日") >= 0) {
-                                if (inputText.indexOf("专业监理工程师") >= 0) {
-                                    inputText = "专业监理工程师_年月日";
-                                } else if (inputText.indexOf("质检工程师") >= 0) {
-                                    inputText = "质检工程师_年月日";
-                                } else {
-                                    inputText = "年月日";
-                                }
-                            }
-                            data.empty().append("<el-date-picker @keyDowns='dateKeydown()'  type='date' format='YYYY年MM月DD日' value-format='YYYY年MM月DD日' @contextmenu.prevent.native='contextmenuClick(" + parm + ")'  @mouseup.right='RightClick(" + parm + ")' trIndex=" + i + " tdIndex=" + j + "  x1=" + x1 + " x2=" + x2 + " y1=" + y1 + " y2=" + y2 + " style='width:100%;height:100%;' placeholder='年月日'> </el-date-picker>");
-                            exctabCell.setTextInfo(inputText);
-                            exctabCell.setExctabId(excelId);
-                            exctabCell.setIsDeleted(0);
-                            exctabCell.setXys(i + "_" + j);
-                            colTitle.add(exctabCell);
-                            data.attr("title", inputText);
-
-                        } else if (textInfo.indexOf("□") >= 0) { //多选框
-                            exctabCell.setTextInfo(inputText);
-                            exctabCell.setExctabId(excelId);
-                            exctabCell.setIsDeleted(0);
-                            exctabCell.setXys(i + "_" + j);
-                            colTitle.add(exctabCell);
-                            data.attr("title", inputText);
-                            // 添加多选框
-
-                            String[] cheText = textInfo.split("□");
-                            JSONArray objs = new JSONArray();
-                            if (cheText != null && cheText.length >= 1) {
-                                int key = 1;
-                                for (String keyval : cheText) {
-                                    JSONObject jsonObject = new JSONObject();
-                                    if (StringUtils.isNotEmpty(keyval)) {
-                                        jsonObject.put("key", key);
-                                        jsonObject.put("name", keyval);
-                                        objs.add(jsonObject);
-                                        keyId += 1;
-                                    }
-                                }
-                            } else {
-                                JSONObject jsonObject = new JSONObject();
-                                jsonObject.put("key", "1");
-                                jsonObject.put("name", "");
-                                objs.add(jsonObject);
-                            }
-
-                            String checkbox = "<hc-form-checkbox-group @keydown.shift.up='keyupShiftUp' @keydown.shift.down='keyupShiftDown' @keydown.shift.left='keyupShiftLeft' @keydown.shift.right='keyupShiftRight' :objs='" + objs + "'  @change='checkboxGroupChange' @contextmenu.prevent.native='contextmenuClick(" + parm + ")'  @mouseup.right='RightClick(" + parm + ")' trIndex=" + i + " tdIndex=" + j + "  x1=" + x1 + " x2=" + x2 + " y1=" + y1 + " y2=" + y2 + " placeholder=''> </hc-form-checkbox-group>";
-                            data.empty().append(checkbox);
-
-                        } else {
-
-                            if (index_state) { // 区域内
-                                if (rowspan >= 1 || isText) {
-                                    data.empty().append("<el-input type='textarea' @keydown.shift.up='keyupShiftUp' @keydown.shift.down='keyupShiftDown' @keydown.shift.left='keyupShiftLeft'  @keydown.shift.right='keyupShiftRight'  @contextmenu.prevent.native='contextmenuClick(" + parm + ")'  @mouseup.right='RightClick(" + parm + ")' trIndex=" + i + " tdIndex=" + j + "  x1=" + x1 + " x2=" + x2 + " y1=" + y1 + " y2=" + y2 + " style='width:100%;height:100%;'   :rows=" + rowspan * 2 + " placeholder=''> </el-input>");
-                                } else {
-                                    data.empty().append("<el-input type='text' @keydown.shift.up='keyupShiftUp' @keydown.shift.down='keyupShiftDown' @keydown.shift.left='keyupShiftLeft'  @keydown.shift.right='keyupShiftRight'  @contextmenu.prevent.native='contextmenuClick(" + parm + ")'  @mouseup.right='RightClick(" + parm + ")' trIndex=" + i + " tdIndex=" + j + "  x1=" + x1 + " x2=" + x2 + " y1=" + y1 + " y2=" + y2 + " style='width:100%;height:100%;' placeholder=''> </el-input>");
-                                }
-                            } else if (tabType.equals("100") && i < 2) { //计量特殊添加
-                                data.empty().append("<el-input type='text' @keydown.shift.up='keyupShiftUp' @keydown.shift.down='keyupShiftDown' @keydown.shift.left='keyupShiftLeft'  @keydown.shift.right='keyupShiftRight'  @contextmenu.prevent.native='contextmenuClick(" + parm + ")'  @mouseup.right='RightClick(" + parm + ")' trIndex=" + i + " tdIndex=" + j + "  x1=" + x1 + " x2=" + x2 + " y1=" + y1 + " y2=" + y2 + " style='width:100%;height:100%;' placeholder=''> </el-input>");
-                            } else { // 区域外
-                                if (j == 0) {
-                                    if (colspan == maxCol && i >= 1) {
-                                        if (rowspan >= 1 || isText) {
-                                            data.empty().append("<el-input @keydown.shift.up='keyupShiftUp' @keydown.shift.down='keyupShiftDown' @keydown.shift.left='keyupShiftLeft' @keydown.shift.right='keyupShiftRight' type='textarea'  @contextmenu.prevent.native='contextmenuClick(" + parm + ")'  @mouseup.right='RightClick(" + parm + ")' trIndex=" + i + " tdIndex=" + j + "  x1=" + x1 + " x2=" + x2 + " y1=" + y1 + " y2=" + y2 + " style='width:100%;height:100%;'   :rows=" + rowspan * 2 + " placeholder=''> </el-input>");
-                                        } else {
-                                            data.empty().append("<el-input @keydown.shift.up='keyupShiftUp' @keydown.shift.down='keyupShiftDown' @keydown.shift.left='keyupShiftLeft' @keydown.shift.right='keyupShiftRight' type='text' @contextmenu.prevent.native='contextmenuClick(" + parm + ")'  @mouseup.right='RightClick(" + parm + ")' trIndex=" + i + " tdIndex=" + j + "  x1=" + x1 + " x2=" + x2 + " y1=" + y1 + " y2=" + y2 + " style='width:100%;height:100%;' placeholder=''> </el-input>");
-                                        }
-                                    }
-                                } else {
-                                    Element bforData = tds.get(j - 1);
-                                    if (!bforData.text().isEmpty() || bforData.html().indexOf("hc-form-checkbox-group") >= 0) {
-                                        if (rowspan >= 1 || isText) {
-                                            data.empty().append("<el-input @keydown.shift.up='keyupShiftUp' @keydown.shift.down='keyupShiftDown' @keydown.shift.left='keyupShiftLeft' @keydown.shift.right='keyupShiftRight' type='textarea' @contextmenu.prevent.native='contextmenuClick(" + parm + ")'  @mouseup.right='RightClick(" + parm + ")' trIndex=" + i + " tdIndex=" + j + "  x1=" + x1 + " x2=" + x2 + " y1=" + y1 + " y2=" + y2 + " style='width:100%;height:100%;'   :rows=" + rowspan * 2 + " placeholder=''> </el-input>");
-                                        } else {
-                                            data.empty().append("<el-input @keydown.shift.up='keyupShiftUp' @keydown.shift.down='keyupShiftDown' @keydown.shift.left='keyupShiftLeft'  @keydown.shift.right='keyupShiftRight' type='text' @contextmenu.prevent.native='contextmenuClick(" + parm + ")'  @mouseup.right='RightClick(" + parm + ")' trIndex=" + i + " tdIndex=" + j + "  x1=" + x1 + " x2=" + x2 + " y1=" + y1 + " y2=" + y2 + " style='width:100%;height:100%;' placeholder=''> </el-input>");
-                                        }
-                                    }
-                                }
-                            }
-
-                            if (!inputText.equals("")) {
-                                exctabCell.setExctabId(excelId);
-                                exctabCell.setTextInfo(inputText);
-                                if (inputText.contains("日期") || inputText.contains("年") || inputText.contains("月") || inputText.contains("日")) {
-                                    //日期
-                                    exctabCell.setTextElementType(4);
-                                } else if (inputText.indexOf("签字") >= 0) {
-                                    exctabCell.setTextElementType(6);
-                                } else {
-                                    //字符串
-                                    exctabCell.setTextElementType(1);
-                                }
-
-                                exctabCell.setIsDeleted(0);
-                                exctabCell.setXys(i + "_" + j);
-                                colTitle.add(exctabCell);
-                            }
-                            data.attr("title", inputText);
-                        }
-                    }
-                }
-            }
-        }
-        //System.out.println(zikey);
-        // 去掉重复的数
-        Map<String, String> groupMap2 = colTitle.stream()
-                .collect(Collectors.groupingBy(ExctabCell::getTextInfo, Collectors.mapping(ExctabCell::getXys, Collectors.joining(","))));
-
-        exctabCellService.DeletExcelByTableId(excelId + "");
-
-        List<ExctabCell> colTitle2 = new ArrayList<>();
-        for (String title : groupMap2.keySet()) {
-            ExctabCell exctabCell = new ExctabCell();
-            exctabCell.setExctabId(excelId);
-            exctabCell.setIsDeleted(0);
-            exctabCell.setTextInfo(title);
-            exctabCell.setCreateTime(new Date());
-
-            if (title.contains("日期") || title.contains("年") || title.contains("月") || title.contains("日")) {
-                //日期
-                exctabCell.setTextElementType(4);
-            } else {
-                //字符串
-                exctabCell.setTextElementType(1);
-            }
-
-            exctabCell.setXys(groupMap2.get(title));
-            colTitle2.add(exctabCell);
-        }
-        exctabCellService.saveBatch(colTitle2);
-
-
-        //对excel 的图片进行操作
-        ExcelTab exceltab = excelTabService.getById(excelId);
-        if (exceltab != null) {
-            // 获取excle 的数据
-            String fileUrl = exceltab.getFileUrl();
-            InputStream ossInputStream = CommonUtil.getOSSInputStream(fileUrl);
-            Workbook wb = new Workbook();
-            wb.loadFromMHtml(ossInputStream);
-            Worksheet sheet = wb.getWorksheets().get(0);
-            PicturesCollection pictures = sheet.getPictures();
-            if (pictures != null && pictures.size() >= 1) {
-                for (int i = 0; i < pictures.size(); i++) {
-                    ExcelPicture pic = pictures.get(i);
-                    int x = pic.getLeftColumn();
-                    int y = pic.getBottomRow();
-                    Elements select = doc.select("el-input[x1=" + x + "][y1=" + y + "]");
-                    System.out.println("xx=--" + x);
-                    System.out.println("yy=--" + y);
-                    if (select != null && select.size() >= 1) {
-                        Element element = select.get(0);
-                        Element elementP = element.parent();
-                        element.remove();
-                        Element imgele = imgs.get(i);
-                        imgele.removeAttr("class");
-                        elementP.append(imgele.toString());
-                    }
-                }
-            }
-
-            ossInputStream.close();
-        }
-        // 移除图片
-        imgs.remove();
-        // 保存
-        exceltab.setIsDeleted(8);
-        excelTabService.saveOrUpdate(exceltab);
-        File writefile = new File(thmlUrl);
-        FileUtil.writeToFile(writefile, doc.html(), Boolean.parseBoolean("UTF-8"));
-    }
-
-    //计算区域坐标
-    public static String getTrInfo(Elements tds, Map<String, String> styleMap, boolean index_state, Integer xy_type, int maxCol, int y, List<Map<String, String>> zikey) {
-
-        int x_width = 0;
-        int y_width = 0;
-        int text_width = 0;
-        int width = 0;
-
-        int null_count = 0;
-        int val_count = 0;
-
-        boolean istrue = true;
-
-        // 上 tr 长度
-
-        List<Map<String, String>> maxList = zikey.stream().filter(map -> Integer.parseInt(map.get("y1")) <= y && y <= Integer.parseInt(map.get("y2"))).collect(Collectors.toList());
-
-        int top1_max = 0;
-        if (maxList != null && maxList.size() >= 1) {
-            top1_max = maxList.stream().mapToInt(m -> Integer.parseInt(m.get("x2"))).max().getAsInt();
-        }
-
-
-        //区域计算
-        for (int j = 0; j < tds.size(); j++) {
-            Element data = tds.get(j);
-            String keyId = data.attr("class");
-            int colspan = data.attr("COLSPAN").equals("") ? 1 : Integer.parseInt(data.attr("COLSPAN"));
-            if (colspan == 0) {
-                colspan = data.attr("colspan").equals("") ? 1 : Integer.parseInt(data.attr("colspan"));
-            }
-            String classInfo = styleMap.get(keyId);
-            String textInfo = data.text().trim().replaceAll(" ", "");
-
-            if (classInfo == null) {
-                classInfo = data.attr("style");
-            } else {
-                data.removeAttr("class");
-                data.attr("style", styleMap.get(keyId).replaceAll("break-word", "inherit"));
-            }
-
-            // 计算线开始
-            if (classInfo.indexOf("border-left-style") >= 0 && classInfo.indexOf("border-top-style") >= 0 && classInfo.indexOf("border-right-style") >= 0) {
-                x_width += colspan;
-            }
-
-            // 计算结束
-            if (classInfo.indexOf("border-left-style") < 0 && (classInfo.indexOf("border-top-style") < 0 || classInfo.indexOf("border-top-style") >= 0) && classInfo.indexOf("border-bottom-style") < 0 && classInfo.indexOf("border-right-style") < 0) {
-                y_width += colspan;
-            }
-
-            String name = data.text();
-            if (!name.isEmpty()) {
-                text_width += colspan;
-            }
-            width += colspan;
-
-            if (!textInfo.isEmpty() && !(textInfo.equals("/") && textInfo.length() <= 2) && !(textInfo.indexOf("年") >= 0 && textInfo.indexOf("月") >= 0 && textInfo.indexOf("日") >= 0) && !textInfo.equals("—") && !textInfo.equals("-")) {  // 标题区域
-                val_count++;
-            } else {
-                null_count++;
-            }
-        }
-
-        // 在区域内
-        //  System.out.println(index_state+"——"+y+"__"+x_width);
-
-        if (index_state) {
-            //是否需要改变
-            if (maxCol == y_width) { // 是否结束区域值
-                index_state = false;
-                xy_type += 1;
-            }
-            if (maxCol == text_width && top1_max != text_width) { // 是否区域开始时
-                xy_type += 1;
-            }
-        } else { // 区域外
-            if (maxCol == x_width) {
-                index_state = true;
-                xy_type += 1;
-            }
-        }
-
-        // 空是否等于值的个数
-        istrue = null_count == val_count && width == maxCol;
-        return xy_type + "," + index_state + "," + width + "," + istrue;
-    }
-
-    // 获取解析样式
-    public static Map<String, String> getHtmlStyle(Document doc) {
-        Map<String, String> styleMap = new HashMap<>();
-        Element style = doc.select("style").first();
-        Matcher cssMatcher = Pattern.compile("(\\w+)\\s*[{]([^}]+)[}]").matcher(style.html());
-        while (cssMatcher.find()) {
-            styleMap.put(cssMatcher.group(1), cssMatcher.group(2));
-        }
-        return styleMap;
-    }
-
     /**
      * 清表生成html
      */
@@ -1830,9 +1262,13 @@ public class ExcelTabController extends BladeController {
         updateWrapper.in("p_key_id", pkeyId);
         updateWrapper.set("is_buss_show", status);
         wbsTreeContractService.update(updateWrapper);
-        excelTabService.getBussPdfInfo(pkeyId);
-        //重新生成PDF修改queryInfo
-        excelTabService.getBussPdfs(nodeId, classify, wbsTreeContract.getContractId(), wbsTreeContract.getProjectId());
+        try{
+            excelTabService.getBussPdfInfo(pkeyId);
+            //重新生成PDF修改queryInfo
+            excelTabService.getBussPdfs(nodeId, classify, wbsTreeContract.getContractId(), wbsTreeContract.getProjectId());
+        }catch (NullPointerException e){
+            throw new ServiceException("当前节点有表单不存在,操作失败");
+        }
         WbsTreeContract contract = wbsTreeContractService.getById(Long.parseLong(nodeId));
         wbsTreeContractService.checkNodeAllDate(contract);
         return R.data("成功");
@@ -2047,6 +1483,13 @@ public class ExcelTabController extends BladeController {
         }
         executionTime.info("----公式填充执行完毕----");
 
+        //删除旧html数据 重刷电签不允许删除旧html
+        if(dataInfo.get("isNotDelOldHtml") == null){
+            List<String> collect = tableInfoList.stream().map(TableInfo::getPkeyId).collect(Collectors.toList());
+            boolean update = wbsTreeContractOldHtmlService.update(Wrappers.<WbsTreeContractOldHtml>update().lambda()
+                    .set(WbsTreeContractOldHtml::getIsDeleted, 1)
+                    .in(WbsTreeContractOldHtml::getContractFormId, collect));
+        }
 
         //保存数据到数据库
         R<Object> result = this.excelTabService.saveOrUpdateInfo(tableInfoList,singnType);
@@ -2664,8 +2107,31 @@ public class ExcelTabController extends BladeController {
                     }
                     // 组装电签设置
                     Elements dqids = table.getElementsByAttribute("dqid");
+                    // 电签组装2
+                    String dqSql = "select e_key,GROUP_CONCAT(DISTINCT concat('*✹',id)) ids from u_sign_key_role_info where tab_en_name='" + tableNode.getInitTableName() + "' GROUP BY e_key";
+                    List<Map<String, Object>> mapList = jdbcTemplate.queryForList(dqSql);
+                    if(mapList!=null && mapList.size()>0){
+                        for(Map<String, Object> map : mapList) {
+                            Elements elementsBy = table.getElementsByAttributeValueStarting("keyname", map.get("e_key") + "_");
+                            if(elementsBy!=null && elementsBy.size()>0){
+                                for(Element element : elementsBy){
+                                    String dqIds = (String) map.get("ids");
+                                    dqIds = dqIds.replace(",","");
+                                    dqIds = dqIds.substring(1);
+                                    element.attr("sign_type", dqIds);
+                                    dqids.add(element);
+                                }
+                            }
+
+                        }
+                    }
                     for (Element element : dqids) {
-                        String dqid = element.attr("dqid");
+                        String dqid="";
+                        if(element.hasAttr("sign_type")){
+                            dqid = element.attr("sign_type");
+                        }else{
+                            dqid = element.attr("dqid");
+                        }
                         Elements x11 = element.getElementsByAttribute("x1");
                         if (x11 != null && x11.size() >= 1) {
                             Element element1 = x11.get(x11.size() - 1);
@@ -2675,6 +2141,10 @@ public class ExcelTabController extends BladeController {
                             CellRange cellRange = sheet.getCellRange(y1, x1);
                             if (cellRange != null) {
                                 // 创建字体
+                                String text = cellRange.getText();
+                                if (StringUtil.hasText(text)) {
+                                    dqid = text + "*" + dqid;
+                                }
                                 cellRange.setText(dqid);
                                 cellRange.getCellStyle().getExcelFont().setSize(1);
                                 cellRange.getCellStyle().getExcelFont().setColor(Color.WHITE);
@@ -3824,7 +3294,7 @@ public class ExcelTabController extends BladeController {
             Thread.sleep(100);
             sheet.saveToHtml(html_url, options);
             Thread.sleep(100);
-            this.expailHtmlInfo(html_url, p_key_id, detail.getTabType() + "");
+            excelTabService.expailHtmlInfo(html_url, p_key_id, detail.getTabType() + "");
             Thread.sleep(100);
             EexpaileInfo(html_url, p_key_id);
             System.out.println(i);
@@ -4492,6 +3962,9 @@ public class ExcelTabController extends BladeController {
     })
     public R addBussFile(Integer classify,Long contractId,@RequestParam("file") MultipartFile[] file, String nodeId, Integer type,BladeUser b) {
         List<TableFile> fileList = new ArrayList<>();
+        //查询字段
+        List<Integer> types = jdbcTemplate.queryForList("select dict_key from blade_dict_biz where code like 'table_file_type%' and is_deleted = 0 and dict_key > 0", Integer.class);
+
         if (file != null && file.length >= 1) {
             for (int i = 0; i < file.length; i++) {
 
@@ -4505,7 +3978,7 @@ public class ExcelTabController extends BladeController {
                 tableFile.setContractId(contractId);
                 tableFile.setName(file[i].getOriginalFilename());
                 tableFile.setType(type); //10 代表附件
-                if (type == 10 || type == 11 || type == 12 || type == 20 || type == 21 || type == 22) {
+                if (CollectionUtil.isNotEmpty(types) && types.contains(type)) {
                     tableFile.setDomainPdfUrl(bladeFile1.getLink());
                 }
                 tableFile.setDomainUrl(bladeFile1.getLink());

+ 6 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/TableFileController.java

@@ -43,6 +43,7 @@ import org.springblade.manager.service.IExcelTabService;
 import org.springblade.manager.service.IWbsTreeContractService;
 import org.springblade.manager.service.IWbsTreePrivateService;
 import org.springblade.manager.vo.ExcelTabVO;
+import org.springblade.resource.feign.NewIOSSClient;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
@@ -77,7 +78,7 @@ public class TableFileController extends BladeController {
 
     private final InformationQueryClient informationQueryClient;
 
-
+    private final NewIOSSClient newIOSSClient;
 
 
     // excel 基本信息表
@@ -98,6 +99,10 @@ public class TableFileController extends BladeController {
         TableFile tableFile = tableFileService.getById(ids);
         // 删除数据
         tableFileService.delDataById(ids, null);
+        //删除远程服务器中的文件
+        String pdfName = tableFile.getDomainPdfUrl().split("upload")[1];
+        this.newIOSSClient.removeFile("upload" + pdfName);
+
         //如果为节点附件,则不去做其他处理,只删除
         if (tableFile.getType() == 1 || tableFile.getType() == 2) {
             List<TableFileVO> fileVOList = tableFileService.selectTableFileList(Long.parseLong(tableFile.getTabId()));

+ 2 - 2
blade-service/blade-manager/src/main/java/org/springblade/manager/feign/ExcelTabClientImpl.java

@@ -498,7 +498,7 @@ public class ExcelTabClientImpl implements ExcelTabClient {
 
     @Override
     public void expailHtmlInfo(String thmlUrl, Long id, String s) throws Exception {
-        excelTabController.expailHtmlInfo(thmlUrl, id, s);
+        excelTabService.expailHtmlInfo(thmlUrl, id, s);
     }
 
     @Override
@@ -507,7 +507,7 @@ public class ExcelTabClientImpl implements ExcelTabClient {
     }
 
     @Override
-    public void saveLinkTab(Long excelId, Long pKeyId) throws IOException {
+    public void saveLinkTab(Long excelId, Long pKeyId) throws Exception {
         excelTabController.saveLinkeTab(excelId,pKeyId);
     }
 

+ 2 - 2
blade-service/blade-manager/src/main/java/org/springblade/manager/feign/TableFileClientImpl.java

@@ -36,9 +36,9 @@ public class TableFileClientImpl implements TableFileClient {
     }
 
     @Override
-    public List<TableFile> getTabFilesByTabIds(String tabFileIds) {
+    public List<TableFile> getTabFilesByTabIds(List<String> tabFileIds) {
         return tableFileService.getBaseMapper().selectList(Wrappers.<TableFile>lambdaQuery()
-                .in(TableFile::getTabId, Func.toLongList(tabFileIds))
+                .in(TableFile::getTabId, tabFileIds)
                 .ne(TableFile::getType, 1) //排除源文件
                 .isNotNull(TableFile::getTabId)
         );

+ 7 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/feign/WbsParamClientImpl.java

@@ -7,6 +7,8 @@ import org.springblade.manager.entity.WbsTreeContract;
 import org.springblade.manager.service.IWbsParamService;
 import org.springframework.web.bind.annotation.RestController;
 
+import java.util.List;
+
 @RestController
 @AllArgsConstructor
 public class WbsParamClientImpl implements WbsParamClient{
@@ -23,6 +25,11 @@ public class WbsParamClientImpl implements WbsParamClient{
         return iWbsParamService.getBaseMapper().selectOne(Wrappers.lambdaQuery(WbsParam.class).eq(WbsParam::getNodeId, nodeId).eq(WbsParam::getType, 200).eq(WbsParam::getIsDeleted, 0).eq(WbsParam::getK,"FILE_TITLE"));
     }
 
+    @Override
+    public void saveWbsParams(List<WbsParam> wbsParamList) {
+        iWbsParamService.saveBatch(wbsParamList);
+    }
+
     @Override
     public String createFileTitle(WbsTreeContract contract) {
         return iWbsParamService.createFileTitle(contract);

+ 8 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/feign/WbsTreeContractClientImpl.java

@@ -494,10 +494,18 @@ public class WbsTreeContractClientImpl implements WbsTreeContractClient {
         return wbsTreeContractService.getEKey(contractId,pKeyId,wbsId);
     }
 
+    @Override
+    public Integer findIsExistTreeNode(List<String> ids) {
+        return wbsTreeContractService.findIsExistTreeNode(ids);
+    }
     @Override
     public void saveNameRuleByPkeyId(Long pKeyId, String s, Long projectId) {
         wbsTreeContractController.saveContractNameRule(s,pKeyId,projectId);
     }
 
 
+    @Override
+    public List<WbsTreeContract> queryListByPIds(List<Long> pIds) {
+        return wbsTreeContractService.queryListByPIds(pIds);
+    }
 }

+ 33 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/feign/WbsTreeContractOldHtmlClientImpl.java

@@ -0,0 +1,33 @@
+package org.springblade.manager.feign;
+
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import lombok.AllArgsConstructor;
+import org.springblade.manager.entity.WbsTreeContractOldHtml;
+import org.springblade.manager.service.WbsTreeContractOldHtmlService;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+/**
+ * @author LHB
+ */
+@RestController
+@AllArgsConstructor
+public class WbsTreeContractOldHtmlClientImpl implements WbsTreeContractOldHtmlClient {
+    @Resource
+    private WbsTreeContractOldHtmlService wbsTreeContractOldHtmlService;
+
+    @Override
+    public Boolean save(List<WbsTreeContractOldHtml> data) {
+        return wbsTreeContractOldHtmlService.saveBatch(data);
+    }
+
+    @Override
+    public void deleteByContractFormIds(List<Long> collect) {
+        wbsTreeContractOldHtmlService.update(Wrappers.<WbsTreeContractOldHtml>update().lambda()
+                .set(WbsTreeContractOldHtml::getIsDeleted, 1)
+                .eq(WbsTreeContractOldHtml::getIsDeleted, 0)
+                .in(WbsTreeContractOldHtml::getContractFormId, collect));
+    }
+}

+ 3 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/ExecutorMeter.java

@@ -1472,7 +1472,9 @@ public class ExecutorMeter extends FormulaExecutor {
             /*数据获取end*/
              double total=dataList.stream().map(InterimPaymentCertificate::getCurrentPeriodPay).mapToDouble(BaseUtils::obj2DoubleZero).sum();
             /*往期累计,本期支付,累计支付*/
-            periodCount(dataList.get(dataList.size()-1));
+            if(!dataList.isEmpty()){
+                periodCount(dataList.get(dataList.size()-1));
+            }
              if(total>0){
                  FormData ft =tec.formDataMap.get(InterimPaymentCertificate.TBN+ StringPool.COLON+"key_9");
                  put2FormData(ft,total);

+ 122 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/FormulaZhiZuo.java

@@ -16,6 +16,8 @@ import org.springblade.manager.utils.RandomNumberHolder;
 import org.springframework.stereotype.Component;
 
 import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 
 @Component
@@ -116,6 +118,126 @@ public class FormulaZhiZuo implements FormulaStrategy {
         }
         System.out.println(values);
     }
+     //优化之后的代码 放开注释可直接使用
+//    @Override
+//    public void execute(FormData cur, TableElementConverter tec) {
+//        // 1. 提取关键信息,增加空指针防护
+//        String relyStr = cur.getFormula().getRely();
+//        if (relyStr == null || !relyStr.contains(":")) {
+//            throw new IllegalArgumentException("无效的依赖格式: " + relyStr);
+//        }
+//        String key = relyStr.substring(relyStr.indexOf(':') + 1);
+//
+//        // 2. 获取随机数映射并检查非空
+//        HashMap<Long, String> randomNumberMap = RandomNumberHolder.getRandomNumber();
+//        if (randomNumberMap == null || randomNumberMap.isEmpty()) {
+//            throw new IllegalStateException("随机数映射为空,无法继续处理");
+//        }
+//        Map.Entry<Long, String> firstRandomEntry = randomNumberMap.entrySet().iterator().next();
+//
+//        // 3. 查找对应的表格信息
+//        Optional<TableInfo> tableInfoOpt = tec.getTableInfoList().stream()
+//                .filter(tableInfo -> firstRandomEntry.getKey().toString().equals(tableInfo.getPkeyId()))
+//                .findFirst();
+//        if (!tableInfoOpt.isPresent()) {
+//            throw new IllegalStateException("未找到对应的表格信息,pkeyId: " + firstRandomEntry.getKey());
+//        }
+//        TableInfo targetTableInfo = tableInfoOpt.get();
+//
+//        // 4. 解析数据字符串(预编译正则提升性能)
+//        String dataStr = targetTableInfo.getDataMap().get(key);
+//        if (dataStr == null) {
+//            throw new IllegalArgumentException("表格数据中未找到key: " + key);
+//        }
+//        String[] dataSegments = dataStr.split("☆");
+//        Pattern pattern = Pattern.compile("_\\^_(.*?)_"); // 预编译正则表达式
+//        Map<Integer, Double> keyToValueMap = new HashMap<>();
+//
+//        for (String segment : dataSegments) {
+//            Matcher matcher = pattern.matcher(segment);
+//            if (matcher.find()) {
+//                try {
+//                    Integer mapKey = Integer.parseInt(matcher.group(1));
+//                    int splitIndex = segment.indexOf("_^_");
+//                    if (splitIndex > 0) {
+//                        Double value = Double.valueOf(segment.substring(0, splitIndex));
+//                        keyToValueMap.put(mapKey, value);
+//                    }
+//                } catch (NumberFormatException e) {
+//                    // 记录日志而非中断,提高容错性
+//                    System.err.println("解析数据失败,segment: " + segment + ", 错误: " + e.getMessage());
+//                }
+//            }
+//        }
+//
+//        // 5. 准备目标值列表(清空原有值)
+//        List<ElementData> elementDataList = cur.getValues();
+//        elementDataList.forEach(e -> e.setValue(null));
+//
+//        // 6. 排序并创建Y值到ElementData的映射(优化查找效率)
+//        TreeMap<Integer, Double> sortedDataMap = new TreeMap<>(keyToValueMap);
+//        Map<Integer, ElementData> yToElementMap = new HashMap<>();
+//        for (ElementData data : elementDataList) {
+//            yToElementMap.put(data.getY(), data);
+//        }
+//
+//        // 7. 处理数据(提取重复逻辑为方法)
+//        if (!sortedDataMap.isEmpty()) {
+//            Map.Entry<Integer, Double> firstEntry = sortedDataMap.firstEntry();
+//            processDataRange(sortedDataMap, yToElementMap, firstEntry, 0, 4, 1);
+//            processDataRange(sortedDataMap, yToElementMap, firstEntry, 5, 9, 5);
+//            processDataRange(sortedDataMap, yToElementMap, firstEntry, 10, Integer.MAX_VALUE, 10);
+//        }
+//
+//        System.out.println(elementDataList);
+//    }
+//
+//    /**
+//     * 处理指定范围的数据
+//     * @param sortedDataMap 排序后的数据映射
+//     * @param yToElementMap Y值到ElementData的映射
+//     * @param firstEntry 第一个数据条目
+//     * @param startIndex 起始索引
+//     * @param endIndex 结束索引
+//     * @param offset 偏移量
+//     */
+//    private void processDataRange(TreeMap<Integer, Double> sortedDataMap,
+//                                  Map<Integer, ElementData> yToElementMap,
+//                                  Map.Entry<Integer, Double> firstEntry,
+//                                  int startIndex,
+//                                  int endIndex,
+//                                  int offset) {
+//        if (sortedDataMap.size() < startIndex + 1) {
+//            return; // 数据量不足,直接返回
+//        }
+//
+//        Integer baseKey = firstEntry.getKey() + offset;
+//        Double baseValue = sortedDataMap.get(baseKey);
+//        if (baseValue == null) {
+//            return;
+//        }
+//
+//        for (int i = startIndex; i <= endIndex; i++) {
+//            if (i >= sortedDataMap.size()) {
+//                break;
+//            }
+//
+//            Integer currentKey = baseKey + (i - offset);
+//            Double currentValue = sortedDataMap.get(currentKey);
+//            if (currentValue == null) {
+//                continue;
+//            }
+//
+//            // 计算绝对值差值
+//            Double diffValue = Math.abs(baseValue - currentValue);
+//
+//            // 查找并设置值(O(1)复杂度)
+//            ElementData targetData = yToElementMap.get(currentKey);
+//            if (targetData != null) {
+//                targetData.setValue(diffValue);
+//            }
+//        }
+//    }
 
     @Override
     public boolean accept(FormData fd) {

+ 2 - 2
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ArchiveTreeContractMapper.xml

@@ -337,13 +337,13 @@
 
     <!-- 文件收集 归档树的文件数量 -->
     <select id="selectFileNumber" resultType="java.lang.Integer">
-        SELECT  count(0)  FROM m_archive_tree_contract a
+        SELECT  sum(b.file_page)  FROM m_archive_tree_contract a
         inner join u_archive_file b on b.node_id = a.id and b.is_deleted = a.is_deleted and b.project_id = a.project_id and (b.is_auto_file is null or b.is_auto_file != 1)
         WHERE  a.is_deleted = 0
         and a.project_id = #{projectId}
         <choose>
             <when test="extType != null and extType == 1">
-                and (b.node_id in( select id from  m_archive_tree_contract where FIND_IN_SET(#{id},ancestors) or a.id = #{id}) OR
+                and ( 	b.node_id in( select id from  m_archive_tree_contract where FIND_IN_SET(#{id},ancestors) or a.id = #{id}) OR
                 b.node_ext_id in(  select id from  m_archive_tree_contract where FIND_IN_SET(#{id},ancestors) or a.id = #{id}))
             </when>
             <otherwise>

+ 2 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ExcelTabMapper.xml

@@ -56,6 +56,7 @@
         dept.name,
         dept.file_type,
         dept.tab_type AS "tabType",
+        dept.is_deleted,
         (
         SELECT
         CASE WHEN count(1) > 0 THEN 1 ELSE 0 END
@@ -67,7 +68,7 @@
         FROM
         m_excel_tab dept
         WHERE
-        dept.is_deleted = 0
+        (dept.is_deleted = 0 or dept.is_deleted = 3)
         <if test="param3!=null and param3!=''">
             AND dept.parent_id = #{param3}
         </if>

+ 3 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/TableFileMapper.xml

@@ -52,7 +52,9 @@
     </delete>
 
     <select id="selectTableFileListByTen" resultMap="TableFileVO">
-        select *,domain_pdf_url as url from m_table_file where is_deleted = 0  and classify = #{classify} and type in (10,11,12,20,21,22) and tab_id = #{pKid} Order by sort ASC
+        select *,domain_pdf_url as url from m_table_file where is_deleted = 0  and classify = #{classify} and type in (
+            select dict_key from blade_dict_biz where code like 'table_file_type%' and is_deleted = 0 and dict_key > 0
+        ) and tab_id = #{pKid} Order by sort ASC
     </select>
 
     <select id="selectTableFileList1" resultMap="TableFileVO">

+ 7 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/TextdictInfoMapper.java

@@ -17,12 +17,14 @@
 package org.springblade.manager.mapper;
 
 import org.springblade.manager.entity.TextdictInfo;
+import org.springblade.manager.entity.WbsTreePrivate;
 import org.springblade.manager.injector.EasyBaseMapper;
 import org.springblade.manager.vo.TextdictInfoVO;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import org.springframework.data.repository.query.Param;
 
+import java.util.Collection;
 import java.util.List;
 
 /**
@@ -51,6 +53,11 @@ public interface TextdictInfoMapper extends EasyBaseMapper<TextdictInfo> {
 
     TextdictInfo selectTextdictInfoOne(@Param("id") String id,@Param("sigRoleId") String sigRoleId,@Param("projectId") String projectId);
 
+    void updateHtmlUrl(@Param("htmlUrl") String htmlUrl,@Param("projectId") String projectId, @Param("excelId") Long pKeyId);
+
+    List<TextdictInfoVO> selectTextdictInfoByExcelIdAndColKey(@Param("excelId") String excelId, @Param("colKeys") Collection<String> colKeys);
+
+    List<TextdictInfoVO> selectTextDictInfoByIdAndColKeyAndColName(@Param("list") List<TextdictInfo> textdictInfos);
     //通过表单Id 获取电签信息
     List<TextdictInfoVO> getTextdictListInfoByPkeyId(@Param("tabId") String tabId,@Param("projectId") String projectId);
 

+ 15 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/TextdictInfoMapper.xml

@@ -65,6 +65,21 @@
             and sig_role_id = #{sigRoleId}
             and project_id= #{projectId}
     </select>
+    <select id="selectTextdictInfoByExcelIdAndColKey" resultMap="textdictInfoVoResultMap">
+        SELECT * from m_textdict_info where is_deleted = 0 and type in('2','6') and excel_id = #{excelId} and is_deleted = 0
+        <foreach collection="colKeys" item="key" separator="," open=" and col_key in ( " close=" )" >
+            #{key}
+        </foreach>
+    </select>
+    <select id="selectTextDictInfoByIdAndColKeyAndColName" resultMap="textdictInfoVoResultMap">
+        select * from m_textdict_info where is_deleted = 0
+        <foreach collection="list" item="item" separator="," open=" and (id,col_key) in ( " close=")">
+            (#{item.id},#{item.colKey})
+        </foreach>
+    </select>
+    <update id="updateHtmlUrl">
+        update m_wbs_tree_contract set html_url = #{htmlUrl} where type = 2 and project_id = #{projectId} and is_type_private_pid = #{pKeyId};
+    </update>
 
     <select id="getTextdictListInfoByPkeyId" resultMap="textdictInfoVoResultMap">
         SELECT a.* from m_textdict_info a where  project_id= #{projectId} and tab_id= #{tabId}

+ 12 - 2
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsFormElementMapper.xml

@@ -167,10 +167,20 @@
         SELECT data_type FROM information_schema.columns WHERE table_name=#{initTableName} AND column_name = #{eKey}
     </select>
     <select id="selectFiledLength" resultType="java.util.Map">
-        select column_name `key`,character_octet_length length from INFORMATION_SCHEMA.COLUMNS  where table_name = #{initTableName}
+        select column_name `key`,character_maximum_length length from INFORMATION_SCHEMA.COLUMNS  where table_name = #{initTableName}
     </select>
     <select id="selectFiledDataMaxLength" resultType="java.lang.Integer">
-        select MAX(LENGTH(${key})) from ${tableName}
+        select IFNULL(MAX(CHAR_LENGTH(${key})),0) from ${tableName}
+    </select>
+    <select id="selectSumColumnLength" resultType="java.lang.Integer">
+        SELECT
+            SUM( CHARACTER_MAXIMUM_LENGTH )
+        FROM
+            information_schema.COLUMNS
+        WHERE
+            TABLE_SCHEMA = #{database}
+            AND TABLE_NAME = #{tableName}
+            AND DATA_TYPE = 'varchar'
     </select>
     <select id="selectSumColumnLength" resultType="java.lang.Integer">
         SELECT

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