Browse Source

新增合同法规和合同模板后端代码

ai_300
zhouhaibin 2 days ago
parent
commit
2ba6ec8790
  1. 2
      ruoyi-admin/src/main/resources/application-dev.yml
  2. 2
      ruoyi-admin/src/main/resources/application.yml
  3. 7
      zaojiaManagement/zaojia-productManagement/pom.xml
  4. 4
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/common/service/AbstractTaskProcessor.java
  5. 140
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/controller/ContractualCaseFilesController.java
  6. 105
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/controller/ContractualRegulationArticlesController.java
  7. 138
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/controller/ContractualRegulationNamesController.java
  8. 56
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/ContractualCaseArticles.java
  9. 66
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/ContractualCaseFiles.java
  10. 57
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/ContractualRegulationArticles.java
  11. 61
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/ContractualRegulationNames.java
  12. 13
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/StartContractReviewRequest.java
  13. 82
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/bo/ContractualCaseFilesBo.java
  14. 52
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/bo/ContractualRegulationArticlesBo.java
  15. 71
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/bo/ContractualRegulationNamesBo.java
  16. 60
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/vo/ContractualCaseArticlesVo.java
  17. 79
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/vo/ContractualCaseFilesVo.java
  18. 63
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/vo/ContractualRegulationArticlesVo.java
  19. 66
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/vo/ContractualRegulationNamesVo.java
  20. 23
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/mapper/ContractualCaseArticlesMapper.java
  21. 23
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/mapper/ContractualCaseFilesMapper.java
  22. 24
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/mapper/ContractualRegulationArticlesMapper.java
  23. 38
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/mapper/ContractualRegulationNamesMapper.java
  24. 96
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/service/IContractualCaseFilesService.java
  25. 68
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/service/IContractualRegulationArticlesService.java
  26. 95
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/service/IContractualRegulationNamesService.java
  27. 671
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/service/impl/ContractualCaseFilesServiceImpl.java
  28. 272
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/service/impl/ContractualRegulationArticlesServiceImpl.java
  29. 640
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/service/impl/ContractualRegulationNamesServiceImpl.java
  30. 34
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/service/impl/ContractualTasksServiceImpl.java
  31. 32
      zaojiaManagement/zaojia-productManagement/src/main/resources/mapper/productManagement/ContractualCaseArticlesMapper.xml
  32. 34
      zaojiaManagement/zaojia-productManagement/src/main/resources/mapper/productManagement/ContractualCaseFilesMapper.xml
  33. 7
      zaojiaManagement/zaojia-productManagement/src/main/resources/mapper/productManagement/ContractualRegulationArticlesMapper.xml
  34. 7
      zaojiaManagement/zaojia-productManagement/src/main/resources/mapper/productManagement/ContractualRegulationNamesMapper.xml

2
ruoyi-admin/src/main/resources/application-dev.yml

@ -53,7 +53,7 @@ spring:
# username: root # username: root
# password: root # password: root
url: jdbc:mysql://10.1.21.250:3306/aitesttable?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true url: jdbc:mysql://10.1.21.250:3306/aitesttable?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
# url: jdbc:mysql://218.0.1.42:53306/aitable?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true # url: jdbc:mysql://218.0.1.42:53306/aitesttable?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
username: root username: root
password: 'HXj-6nR|D8xy*h#!I&:(' password: 'HXj-6nR|D8xy*h#!I&:('
# 从库数据源 # 从库数据源

2
ruoyi-admin/src/main/resources/application.yml

@ -71,7 +71,7 @@ spring:
basename: i18n/messages basename: i18n/messages
profiles: profiles:
#@profiles.active@ #@profiles.active@
active: test active: dev
# 文件上传 # 文件上传
servlet: servlet:
multipart: multipart:

7
zaojiaManagement/zaojia-productManagement/pom.xml

@ -116,6 +116,13 @@
<artifactId>flying-saucer-pdf</artifactId> <artifactId>flying-saucer-pdf</artifactId>
<version>9.1.22</version> <version>9.1.22</version>
</dependency> </dependency>
<!-- Milvus Java SDK -->
<dependency>
<groupId>io.milvus</groupId>
<artifactId>milvus-sdk-java</artifactId>
<version>2.3.4</version>
</dependency>
</dependencies> </dependencies>

4
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/common/service/AbstractTaskProcessor.java

@ -114,10 +114,10 @@ public abstract class AbstractTaskProcessor<T extends BaseTaskBo, E> implements
public FileProcessResult processFile(Long ossId) throws IOException, InterruptedException { public FileProcessResult processFile(Long ossId) throws IOException, InterruptedException {
SysOssVo fileInfo = ossService.getById(ossId); SysOssVo fileInfo = ossService.getById(ossId);
String fileName = fileInfo.getOriginalName(); String fileName = fileInfo.getOriginalName();
String filePath = fileRootPath + fileInfo.getFileName(); String filePath = fileRootPath + File.separator +fileInfo.getFileName();
// 处理文件转换 // 处理文件转换
if(!fileName.toLowerCase().endsWith(".docx")) { if(fileName.toLowerCase().endsWith(".doc")) {
filePath = convertToDocx(filePath, fileName); filePath = convertToDocx(filePath, fileName);
} }

140
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/controller/ContractualCaseFilesController.java

@ -0,0 +1,140 @@
package org.dromara.productManagement.controller;
import java.util.List;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.productManagement.domain.vo.ContractualCaseFilesVo;
import org.dromara.productManagement.domain.vo.ContractualCaseArticlesVo;
import org.dromara.productManagement.domain.bo.ContractualCaseFilesBo;
import org.dromara.productManagement.service.IContractualCaseFilesService;
import org.dromara.common.mybatis.core.page.TableDataInfo;
/**
* 合同案例文件
*
* @author Lion Li
* @date 2025-06-04
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/productManagement/ContractualCaseFiles")
public class ContractualCaseFilesController extends BaseController {
private final IContractualCaseFilesService contractualCaseFilesService;
/**
* 查询合同案例文件列表
*/
@SaCheckPermission("productManagement:ContractualCaseFiles:list")
@GetMapping("/list")
public TableDataInfo<ContractualCaseFilesVo> list(ContractualCaseFilesBo bo, PageQuery pageQuery) {
return contractualCaseFilesService.queryPageList(bo, pageQuery);
}
/**
* 导出合同案例文件列表
*/
@SaCheckPermission("productManagement:ContractualCaseFiles:export")
@Log(title = "合同案例文件", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(ContractualCaseFilesBo bo, HttpServletResponse response) {
List<ContractualCaseFilesVo> list = contractualCaseFilesService.queryList(bo);
ExcelUtil.exportExcel(list, "合同案例文件", ContractualCaseFilesVo.class, response);
}
/**
* 获取合同案例文件详细信息
*/
@SaCheckPermission("productManagement:ContractualCaseFiles:query")
@GetMapping("/{id}")
public R<ContractualCaseFilesVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(contractualCaseFilesService.queryById(id));
}
/**
* 新增合同案例文件
*/
@SaCheckPermission("productManagement:ContractualCaseFiles:add")
@Log(title = "合同案例文件", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody ContractualCaseFilesBo bo) {
// 设置默认状态为待解析
if (bo.getProgressStatus() == null) {
bo.setProgressStatus("PENDING");
}
return toAjax(contractualCaseFilesService.insertByBo(bo));
}
/**
* 修改合同案例文件
*/
@SaCheckPermission("productManagement:ContractualCaseFiles:edit")
@Log(title = "合同案例文件", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody ContractualCaseFilesBo bo) {
return toAjax(contractualCaseFilesService.updateByBo(bo));
}
/**
* 更新合同案例文件状态
*/
@SaCheckPermission("productManagement:ContractualCaseFiles:edit")
@Log(title = "合同案例文件状态更新", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping("/updateStatus")
public R<Void> updateStatus(@RequestBody ContractualCaseFilesBo bo) {
return toAjax(contractualCaseFilesService.updateStatusById(bo.getId(), bo.getIsEffective()));
}
/**
* 删除合同案例文件
*/
@SaCheckPermission("productManagement:ContractualCaseFiles:remove")
@Log(title = "合同案例文件", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(contractualCaseFilesService.deleteWithValidByIds(List.of(ids), true));
}
/**
* 获取案例条款列表
*/
@SaCheckPermission("productManagement:ContractualCaseFiles:query")
@GetMapping("/articles/{id}")
public R<List<ContractualCaseArticlesVo>> getArticles(@NotNull(message = "案例文件ID不能为空")
@PathVariable Long id) {
List<ContractualCaseArticlesVo> articles = contractualCaseFilesService.getCaseArticles(id);
return R.ok(articles);
}
/**
* 生成案例PDF文档查看详情
*/
@SaCheckPermission("productManagement:ContractualCaseFiles:query")
@GetMapping("/view/{id}")
public void viewPdf(@NotNull(message = "案例文件ID不能为空")
@PathVariable Long id,
HttpServletResponse response) {
contractualCaseFilesService.generateCasePdf(id, response);
}
}

105
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/controller/ContractualRegulationArticlesController.java

@ -0,0 +1,105 @@
package org.dromara.productManagement.controller;
import java.util.List;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.productManagement.domain.vo.ContractualRegulationArticlesVo;
import org.dromara.productManagement.domain.bo.ContractualRegulationArticlesBo;
import org.dromara.productManagement.service.IContractualRegulationArticlesService;
import org.dromara.common.mybatis.core.page.TableDataInfo;
/**
* 合同法规法条
*
* @author Lion Li
* @date 2025-06-05
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/productManagement/regulationArticles")
public class ContractualRegulationArticlesController extends BaseController {
private final IContractualRegulationArticlesService contractualRegulationArticlesService;
/**
* 查询合同法规法条列表
*/
@SaCheckPermission("productManagement:regulationArticles:list")
@GetMapping("/list")
public TableDataInfo<ContractualRegulationArticlesVo> list(ContractualRegulationArticlesBo bo, PageQuery pageQuery) {
return contractualRegulationArticlesService.queryPageList(bo, pageQuery);
}
/**
* 导出合同法规法条列表
*/
@SaCheckPermission("productManagement:regulationArticles:export")
@Log(title = "合同法规法条", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(ContractualRegulationArticlesBo bo, HttpServletResponse response) {
List<ContractualRegulationArticlesVo> list = contractualRegulationArticlesService.queryList(bo);
ExcelUtil.exportExcel(list, "合同法规法条", ContractualRegulationArticlesVo.class, response);
}
/**
* 获取合同法规法条详细信息
*
* @param id 主键
*/
@SaCheckPermission("productManagement:regulationArticles:query")
@GetMapping("/{id}")
public R<ContractualRegulationArticlesVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(contractualRegulationArticlesService.queryById(id));
}
/**
* 新增合同法规法条
*/
@SaCheckPermission("productManagement:regulationArticles:add")
@Log(title = "合同法规法条", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody ContractualRegulationArticlesBo bo) {
return toAjax(contractualRegulationArticlesService.insertByBo(bo));
}
/**
* 修改合同法规法条
*/
@SaCheckPermission("productManagement:regulationArticles:edit")
@Log(title = "合同法规法条", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody ContractualRegulationArticlesBo bo) {
return toAjax(contractualRegulationArticlesService.updateByBo(bo));
}
/**
* 删除合同法规法条
*
* @param ids 主键串
*/
@SaCheckPermission("productManagement:regulationArticles:remove")
@Log(title = "合同法规法条", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(contractualRegulationArticlesService.deleteWithValidByIds(List.of(ids), true));
}
}

138
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/controller/ContractualRegulationNamesController.java

@ -0,0 +1,138 @@
package org.dromara.productManagement.controller;
import java.util.List;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.productManagement.domain.vo.ContractualRegulationNamesVo;
import org.dromara.productManagement.domain.bo.ContractualRegulationNamesBo;
import org.dromara.productManagement.service.IContractualRegulationNamesService;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.productManagement.domain.vo.ContractualRegulationArticlesVo;
/**
* 合同法规名称
*
* @author Lion Li
* @date 2025-06-04
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/productManagement/ContractualRegulationNames")
public class ContractualRegulationNamesController extends BaseController {
private final IContractualRegulationNamesService contractualRegulationNamesService;
/**
* 查询合同法规名称列表
*/
@SaCheckPermission("productManagement:ContractualRegulationNames:list")
@GetMapping("/list")
public TableDataInfo<ContractualRegulationNamesVo> list(ContractualRegulationNamesBo bo, PageQuery pageQuery) {
return contractualRegulationNamesService.queryPageList(bo, pageQuery);
}
/**
* 导出合同法规名称列表
*/
@SaCheckPermission("productManagement:ContractualRegulationNames:export")
@Log(title = "合同法规名称", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(ContractualRegulationNamesBo bo, HttpServletResponse response) {
List<ContractualRegulationNamesVo> list = contractualRegulationNamesService.queryList(bo);
ExcelUtil.exportExcel(list, "合同法规名称", ContractualRegulationNamesVo.class, response);
}
/**
* 获取合同法规名称详细信息
*
* @param id 主键
*/
@SaCheckPermission("productManagement:ContractualRegulationNames:query")
@GetMapping("/{id}")
public R<ContractualRegulationNamesVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(contractualRegulationNamesService.queryById(id));
}
/**
* 新增合同法规名称
*/
@SaCheckPermission("productManagement:ContractualRegulationNames:add")
@Log(title = "合同法规名称", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody ContractualRegulationNamesBo bo) {
// 设置默认状态为待解析
if (bo.getProgressStatus() == null) {
bo.setProgressStatus("PENDING");
}
return toAjax(contractualRegulationNamesService.insertByBo(bo));
}
/**
* 更新合同法规名称状态
*/
@SaCheckPermission("productManagement:ContractualRegulationNames:edit")
@Log(title = "合同法规名称状态更新", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping("/updateStatus")
public R<Void> updateStatus(@RequestBody ContractualRegulationNamesBo bo) {
return toAjax(contractualRegulationNamesService.updateStatusById(bo.getId(), bo.getIsEffective()));
}
/**
* 修改合同法规名称
*/
@SaCheckPermission("productManagement:ContractualRegulationNames:edit")
@Log(title = "合同法规名称", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody ContractualRegulationNamesBo bo) {
return toAjax(contractualRegulationNamesService.updateByBo(bo));
}
/**
* 删除合同法规名称
*
* @param ids 主键串
*/
@SaCheckPermission("productManagement:ContractualRegulationNames:remove")
@Log(title = "合同法规名称", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(contractualRegulationNamesService.deleteWithValidByIds(List.of(ids), true));
}
/**
* 查看法规详情生成PDF
*/
@GetMapping("/view/{id}")
public void viewRegulationDetail(@PathVariable Long id, HttpServletResponse response) {
contractualRegulationNamesService.generateRegulationPdf(id, response);
}
/**
* 获取法规条款列表
*/
@GetMapping("/articles/{id}")
public R<List<ContractualRegulationArticlesVo>> getRegulationArticles(@PathVariable Long id) {
List<ContractualRegulationArticlesVo> articles = contractualRegulationNamesService.getRegulationArticles(id);
return R.ok(articles);
}
}

56
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/ContractualCaseArticles.java

@ -0,0 +1,56 @@
package org.dromara.productManagement.domain;
import org.dromara.common.tenant.core.TenantEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
/**
* 合同案例条款对象 contractual_case_articles
*
* @author Lion Li
* @date 2025-06-05
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("contractual_case_articles")
public class ContractualCaseArticles extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@TableId(value = "id")
private Long id;
/**
* 合同案例文件表ID
*/
private Long caseFileId;
/**
* 条款内容
*/
private String articleContent;
/**
* 向量表ID
*/
private Long vectorTableId;
/**
* 是否有效(1:有效 0:无效)
*/
private String isEffective;
/**
* 删除标志(0代表存在 2代表删除)
*/
@TableLogic
private String delFlag;
}

66
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/ContractualCaseFiles.java

@ -0,0 +1,66 @@
package org.dromara.productManagement.domain;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.io.Serial;
/**
* 合同案例文件对象 contractual_case_files
*
* @author Lion Li
* @date 2025-06-04
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("contractual_case_files")
public class ContractualCaseFiles extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@TableId(value = "id")
private Long id;
/**
* 案例名称
*/
private String caseName;
/**
* 案例描述
*/
private String caseDescription;
/**
* 案例类型
*/
private String caseType;
/**
* 发布日期
*/
private Date publishDate;
/**
* 是否有效(Y:有效 N:无效)
*/
private String isEffective;
/**
* 删除标志(0代表存在 2代表删除)
*/
@TableLogic
private String delFlag;
private String progressStatus;
private Long ossId;
}

57
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/ContractualRegulationArticles.java

@ -0,0 +1,57 @@
package org.dromara.productManagement.domain;
import org.dromara.common.tenant.core.TenantEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
/**
* 合同法规法条对象 contractual_regulation_articles
*
* @author Lion Li
* @date 2025-06-05
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("contractual_regulation_articles")
public class ContractualRegulationArticles extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@TableId(value = "id")
private Long id;
/**
* 合同法规名称表ID
*/
private Long regulationNameId;
/**
* 法条内容
*/
private String articleContent;
/**
* 向量表ID
*/
private Long vectorTableId;
/**
* 是否有效(1:有效 0:无效)
*/
private String isEffective;
/**
* 删除标志(0代表存在 2代表删除)
*/
@TableLogic
private String delFlag;
}

61
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/ContractualRegulationNames.java

@ -0,0 +1,61 @@
package org.dromara.productManagement.domain;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.io.Serial;
/**
* 合同法规名称对象 contractual_regulation_names
*
* @author Lion Li
* @date 2025-06-04
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("contractual_regulation_names")
public class ContractualRegulationNames extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@TableId(value = "id")
private Long id;
/**
* 法规名称
*/
private String regulationName;
/**
* 法规描述
*/
private String regulationDescription;
/**
* 发布日期
*/
private Date publishDate;
/**
* 是否有效(Y:有效 N:无效)
*/
private String isEffective;
/**
* 删除标志(0代表存在 2代表删除)
*/
@TableLogic
private String delFlag;
private String progressStatus;
private Long ossId;
}

13
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/StartContractReviewRequest.java

@ -116,19 +116,14 @@ public class StartContractReviewRequest {
@Data @Data
public static class ConsistencyData { public static class ConsistencyData {
/** /**
* 文件类型 * 招投标文件OSS ID
*/ */
private List<String> fileTypes; private String bidDocumentOssId;
/** /**
* 检查维度 * 招投标文件路径由后端根据ossId转换得到
*/ */
private List<String> dimensions; private String bidDocumentPath;
/**
* 偏差级别
*/
private String deviationLevel;
/** /**
* 特别说明 * 特别说明

82
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/bo/ContractualCaseFilesBo.java

@ -0,0 +1,82 @@
package org.dromara.productManagement.domain.bo;
import org.dromara.productManagement.domain.ContractualCaseFiles;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
/**
* 合同案例文件业务对象 contractual_case_files
*
* @author Lion Li
* @date 2025-06-04
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = ContractualCaseFiles.class, reverseConvertGenerate = false)
public class ContractualCaseFilesBo extends BaseEntity {
/**
* 主键ID
*/
@NotNull(message = "主键ID不能为空", groups = { EditGroup.class })
private Long id;
/**
* 案例名称
*/
@NotBlank(message = "案例名称不能为空", groups = { AddGroup.class, EditGroup.class })
private String caseName;
/**
* 案例描述
*/
private String caseDescription;
/**
* 案例类型
*/
private String caseType;
/**
* 发布日期
*/
@JsonFormat(pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date publishDate;
/**
* 发布日期查询开始时间
*/
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date publishDateStart;
/**
* 发布日期查询结束时间
*/
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date publishDateEnd;
/**
* 是否有效(Y:有效 N:无效)
*/
private String isEffective;
/**
* 处理状态
*/
private String progressStatus;
/**
* OSS文件ID
*/
private Long ossId;
}

52
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/bo/ContractualRegulationArticlesBo.java

@ -0,0 +1,52 @@
package org.dromara.productManagement.domain.bo;
import org.dromara.productManagement.domain.ContractualRegulationArticles;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
/**
* 合同法规法条业务对象 contractual_regulation_articles
*
* @author Lion Li
* @date 2025-06-05
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = ContractualRegulationArticles.class, reverseConvertGenerate = false)
public class ContractualRegulationArticlesBo extends BaseEntity {
/**
* 主键ID
*/
@NotNull(message = "主键ID不能为空", groups = { EditGroup.class })
private Long id;
/**
* 合同法规名称表ID
*/
@NotNull(message = "合同法规名称表ID不能为空", groups = { AddGroup.class, EditGroup.class })
private Long regulationNameId;
/**
* 法条内容
*/
@NotBlank(message = "法条内容不能为空", groups = { AddGroup.class, EditGroup.class })
private String articleContent;
/**
* 向量表ID
*/
private Long vectorTableId;
/**
* 是否有效(1:有效 0:无效)
*/
private String isEffective;
}

71
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/bo/ContractualRegulationNamesBo.java

@ -0,0 +1,71 @@
package org.dromara.productManagement.domain.bo;
import org.dromara.productManagement.domain.ContractualRegulationNames;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
/**
* 合同法规名称业务对象 contractual_regulation_names
*
* @author Lion Li
* @date 2025-06-04
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = ContractualRegulationNames.class, reverseConvertGenerate = false)
public class ContractualRegulationNamesBo extends BaseEntity {
/**
* 主键ID
*/
private Long id;
/**
* 法规名称
*/
@NotBlank(message = "法规名称不能为空", groups = { AddGroup.class, EditGroup.class })
private String regulationName;
/**
* 法规描述
*/
@NotBlank(message = "法规描述不能为空", groups = { AddGroup.class, EditGroup.class })
private String regulationDescription;
/**
* 发布日期
*/
@NotNull(message = "发布日期不能为空", groups = { AddGroup.class, EditGroup.class })
@JsonFormat(pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date publishDate;
/**
* 发布日期查询开始时间
*/
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date publishDateStart;
/**
* 发布日期查询结束时间
*/
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date publishDateEnd;
/**
* 是否有效(Y:有效 N:无效)
*/
private String isEffective;
private String progressStatus;
private Long ossId;
}

60
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/vo/ContractualCaseArticlesVo.java

@ -0,0 +1,60 @@
package org.dromara.productManagement.domain.vo;
import org.dromara.productManagement.domain.ContractualCaseArticles;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 合同案例条款视图对象 contractual_case_articles
*
* @author Lion Li
* @date 2025-06-05
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = ContractualCaseArticles.class)
public class ContractualCaseArticlesVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@ExcelProperty(value = "主键ID")
private Long id;
/**
* 合同案例文件表ID
*/
@ExcelProperty(value = "合同案例文件表ID")
private Long caseFileId;
/**
* 条款内容
*/
@ExcelProperty(value = "条款内容")
private String articleContent;
/**
* 向量表ID
*/
@ExcelProperty(value = "向量表ID")
private Long vectorTableId;
/**
* 是否有效(1:有效 0:无效)
*/
@ExcelProperty(value = "是否有效")
private String isEffective;
/**
* 条款排序序号用于排序显示
*/
private Integer articleOrder;
}

79
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/vo/ContractualCaseFilesVo.java

@ -0,0 +1,79 @@
package org.dromara.productManagement.domain.vo;
import org.dromara.productManagement.domain.ContractualCaseFiles;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.io.Serial;
import java.io.Serializable;
/**
* 合同案例文件视图对象 contractual_case_files
*
* @author Lion Li
* @date 2025-06-04
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = ContractualCaseFiles.class)
public class ContractualCaseFilesVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@ExcelProperty(value = "主键ID")
private Long id;
/**
* 案例名称
*/
@ExcelProperty(value = "案例名称")
private String caseName;
/**
* 案例描述
*/
@ExcelProperty(value = "案例描述")
private String caseDescription;
/**
* 案例类型
*/
@ExcelProperty(value = "案例类型")
private String caseType;
/**
* 发布日期
*/
@ExcelProperty(value = "发布日期")
@JsonFormat(pattern = "yyyy-MM-dd")
private Date publishDate;
/**
* 是否有效(Y:有效 N:无效)
*/
@ExcelProperty(value = "是否有效", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "sys_yes_no")
private String isEffective;
/**
* 处理状态
*/
@ExcelProperty(value = "处理状态", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "file_progress_status")
private String progressStatus;
/**
* OSS文件ID
*/
private Long ossId;
}

63
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/vo/ContractualRegulationArticlesVo.java

@ -0,0 +1,63 @@
package org.dromara.productManagement.domain.vo;
import org.dromara.productManagement.domain.ContractualRegulationArticles;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 合同法规条款视图对象 contractual_regulation_articles
*
* @author Lion Li
* @date 2025-06-05
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = ContractualRegulationArticles.class)
public class ContractualRegulationArticlesVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@ExcelProperty(value = "主键ID")
private Long id;
/**
* 法规名称ID
*/
@ExcelProperty(value = "法规名称ID")
private Long regulationNameId;
/**
* 法规条款内容
*/
@ExcelProperty(value = "法规条款内容")
private String articleContent;
/**
* 是否有效
*/
@ExcelProperty(value = "是否有效", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "sys_yes_no")
private String isEffective;
/**
* 向量表ID
*/
@ExcelProperty(value = "向量表ID")
private Long vectorTableId;
/**
* 条款序号用于排序显示
*/
private Integer articleOrder;
}

66
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/vo/ContractualRegulationNamesVo.java

@ -0,0 +1,66 @@
package org.dromara.productManagement.domain.vo;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.dromara.productManagement.domain.ContractualRegulationNames;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 合同法规名称视图对象 contractual_regulation_names
*
* @author Lion Li
* @date 2025-06-04
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = ContractualRegulationNames.class)
public class ContractualRegulationNamesVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@ExcelProperty(value = "主键ID")
private Long id;
/**
* 法规名称
*/
@ExcelProperty(value = "法规名称")
private String regulationName;
/**
* 法规描述
*/
@ExcelProperty(value = "法规描述")
private String regulationDescription;
/**
* 发布日期
*/
@ExcelProperty(value = "发布日期")
@JsonFormat(pattern = "yyyy-MM-dd")
private Date publishDate;
/**
* 是否有效(1:有效 0:无效)
*/
@ExcelProperty(value = "是否有效Y/N")
private String isEffective;
private String progressStatus;
}

23
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/mapper/ContractualCaseArticlesMapper.java

@ -0,0 +1,23 @@
package org.dromara.productManagement.mapper;
import org.dromara.productManagement.domain.ContractualCaseArticles;
import org.dromara.productManagement.domain.vo.ContractualCaseArticlesVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.apache.ibatis.annotations.Param;
/**
* 合同案例条款Mapper接口
*
* @author Lion Li
* @date 2025-06-05
*/
public interface ContractualCaseArticlesMapper extends BaseMapperPlus<ContractualCaseArticles, ContractualCaseArticlesVo> {
/**
* 根据案例文件ID真实删除条款记录
* @param caseFileId 案例文件ID
* @return 删除的记录数
*/
int realDeleteByCaseFileId(@Param("caseFileId") Long caseFileId);
}

23
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/mapper/ContractualCaseFilesMapper.java

@ -0,0 +1,23 @@
package org.dromara.productManagement.mapper;
import org.dromara.productManagement.domain.ContractualCaseFiles;
import org.dromara.productManagement.domain.vo.ContractualCaseFilesVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.apache.ibatis.annotations.Param;
/**
* 合同案例文件Mapper接口
*
* @author Lion Li
* @date 2025-06-04
*/
public interface ContractualCaseFilesMapper extends BaseMapperPlus<ContractualCaseFiles, ContractualCaseFilesVo> {
/**
* 真实删除案例文件记录
* @param id 案例文件ID
* @return 删除的记录数
*/
int realDeleteById(@Param("id") Long id);
}

24
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/mapper/ContractualRegulationArticlesMapper.java

@ -0,0 +1,24 @@
package org.dromara.productManagement.mapper;
import org.dromara.productManagement.domain.ContractualRegulationArticles;
import org.dromara.productManagement.domain.vo.ContractualRegulationArticlesVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Param;
/**
* 合同法规法条Mapper接口
*
* @author Lion Li
* @date 2025-06-05
*/
public interface ContractualRegulationArticlesMapper extends BaseMapperPlus<ContractualRegulationArticles, ContractualRegulationArticlesVo> {
/**
* 根据法规ID真实删除所有条款
* @param regulationNameId 法规名称ID
* @return 删除的记录数
*/
@Delete("DELETE FROM contractual_regulation_articles WHERE regulation_name_id = #{regulationNameId}")
int realDeleteByRegulationNameId(@Param("regulationNameId") Long regulationNameId);
}

38
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/mapper/ContractualRegulationNamesMapper.java

@ -0,0 +1,38 @@
package org.dromara.productManagement.mapper;
import org.dromara.productManagement.domain.ContractualRegulationNames;
import org.dromara.productManagement.domain.vo.ContractualRegulationNamesVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Param;
import java.util.Collection;
/**
* 合同法规名称Mapper接口
*
* @author Lion Li
* @date 2025-06-04
*/
public interface ContractualRegulationNamesMapper extends BaseMapperPlus<ContractualRegulationNames, ContractualRegulationNamesVo> {
/**
* 真实删除法规记录
* @param id 法规ID
* @return 删除的记录数
*/
@Delete("DELETE FROM contractual_regulation_names WHERE id = #{id}")
int realDeleteById(@Param("id") Long id);
/**
* 批量真实删除法规记录
* @param ids 法规ID集合
* @return 删除的记录数
*/
@Delete("<script>" +
"DELETE FROM contractual_regulation_names WHERE id IN " +
"<foreach collection='ids' item='id' open='(' separator=',' close=')'>" +
"#{id}" +
"</foreach>" +
"</script>")
int realDeleteByIds(@Param("ids") Collection<Long> ids);
}

96
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/service/IContractualCaseFilesService.java

@ -0,0 +1,96 @@
package org.dromara.productManagement.service;
import org.dromara.productManagement.domain.bo.ContractualCaseFilesBo;
import org.dromara.productManagement.domain.vo.ContractualCaseFilesVo;
import org.dromara.productManagement.domain.vo.ContractualCaseArticlesVo;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import jakarta.servlet.http.HttpServletResponse;
import java.util.Collection;
import java.util.List;
/**
* 合同案例文件Service接口
*
* @author Lion Li
* @date 2025-06-04
*/
public interface IContractualCaseFilesService {
/**
* 查询合同案例文件
*
* @param id 主键
* @return 合同案例文件
*/
ContractualCaseFilesVo queryById(Long id);
/**
* 分页查询合同案例文件列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 合同案例文件分页列表
*/
TableDataInfo<ContractualCaseFilesVo> queryPageList(ContractualCaseFilesBo bo, PageQuery pageQuery);
/**
* 查询符合条件的合同案例文件列表
*
* @param bo 查询条件
* @return 合同案例文件列表
*/
List<ContractualCaseFilesVo> queryList(ContractualCaseFilesBo bo);
/**
* 新增合同案例文件
*
* @param bo 合同案例文件
* @return 是否新增成功
*/
Boolean insertByBo(ContractualCaseFilesBo bo);
/**
* 修改合同案例文件
*
* @param bo 合同案例文件
* @return 是否修改成功
*/
Boolean updateByBo(ContractualCaseFilesBo bo);
/**
* 更新合同案例文件状态
*
* @param id 主键
* @param status 状态
* @return 是否更新成功
*/
Boolean updateStatusById(Long id, String status);
/**
* 校验并批量删除合同案例文件信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
/**
* 获取案例条款列表
*
* @param caseFileId 案例文件ID
* @return 案例条款列表
*/
List<ContractualCaseArticlesVo> getCaseArticles(Long caseFileId);
/**
* 生成案例PDF文档
*
* @param caseFileId 案例文件ID
* @param response HTTP响应
*/
void generateCasePdf(Long caseFileId, HttpServletResponse response);
}

68
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/service/IContractualRegulationArticlesService.java

@ -0,0 +1,68 @@
package org.dromara.productManagement.service;
import org.dromara.productManagement.domain.vo.ContractualRegulationArticlesVo;
import org.dromara.productManagement.domain.bo.ContractualRegulationArticlesBo;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import java.util.Collection;
import java.util.List;
/**
* 合同法规法条Service接口
*
* @author Lion Li
* @date 2025-06-05
*/
public interface IContractualRegulationArticlesService {
/**
* 查询合同法规法条
*
* @param id 主键
* @return 合同法规法条
*/
ContractualRegulationArticlesVo queryById(Long id);
/**
* 分页查询合同法规法条列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 合同法规法条分页列表
*/
TableDataInfo<ContractualRegulationArticlesVo> queryPageList(ContractualRegulationArticlesBo bo, PageQuery pageQuery);
/**
* 查询符合条件的合同法规法条列表
*
* @param bo 查询条件
* @return 合同法规法条列表
*/
List<ContractualRegulationArticlesVo> queryList(ContractualRegulationArticlesBo bo);
/**
* 新增合同法规法条
*
* @param bo 合同法规法条
* @return 是否新增成功
*/
Boolean insertByBo(ContractualRegulationArticlesBo bo);
/**
* 修改合同法规法条
*
* @param bo 合同法规法条
* @return 是否修改成功
*/
Boolean updateByBo(ContractualRegulationArticlesBo bo);
/**
* 校验并批量删除合同法规法条信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

95
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/service/IContractualRegulationNamesService.java

@ -0,0 +1,95 @@
package org.dromara.productManagement.service;
import org.dromara.productManagement.domain.vo.ContractualRegulationNamesVo;
import org.dromara.productManagement.domain.vo.ContractualRegulationArticlesVo;
import org.dromara.productManagement.domain.bo.ContractualRegulationNamesBo;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import jakarta.servlet.http.HttpServletResponse;
import java.util.Collection;
import java.util.List;
/**
* 合同法规名称Service接口
*
* @author Lion Li
* @date 2025-06-04
*/
public interface IContractualRegulationNamesService {
/**
* 查询合同法规名称
*
* @param id 主键
* @return 合同法规名称
*/
ContractualRegulationNamesVo queryById(Long id);
/**
* 分页查询合同法规名称列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 合同法规名称分页列表
*/
TableDataInfo<ContractualRegulationNamesVo> queryPageList(ContractualRegulationNamesBo bo, PageQuery pageQuery);
/**
* 查询符合条件的合同法规名称列表
*
* @param bo 查询条件
* @return 合同法规名称列表
*/
List<ContractualRegulationNamesVo> queryList(ContractualRegulationNamesBo bo);
/**
* 新增合同法规名称
*
* @param bo 合同法规名称
* @return 是否新增成功
*/
Boolean insertByBo(ContractualRegulationNamesBo bo);
/**
* 修改合同法规名称
*
* @param bo 合同法规名称
* @return 是否修改成功
*/
Boolean updateByBo(ContractualRegulationNamesBo bo);
/**
* 更新合同法规名称状态
*
* @param id 主键
* @param status 状态
* @return 是否更新成功
*/
Boolean updateStatusById(Long id, String status);
/**
* 校验并批量删除合同法规名称信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
/**
* 获取法规条款列表
*
* @param regulationNameId 法规名称ID
* @return 法规条款列表
*/
List<ContractualRegulationArticlesVo> getRegulationArticles(Long regulationNameId);
/**
* 生成法规PDF文档
*
* @param regulationNameId 法规名称ID
* @param response HTTP响应
*/
void generateRegulationPdf(Long regulationNameId, HttpServletResponse response);
}

671
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/service/impl/ContractualCaseFilesServiceImpl.java

@ -0,0 +1,671 @@
package org.dromara.productManagement.service.impl;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.productManagement.utils.MyHttpUtils;
import org.dromara.system.domain.vo.SysOssVo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.dromara.productManagement.domain.bo.ContractualCaseFilesBo;
import org.dromara.productManagement.domain.vo.ContractualCaseFilesVo;
import org.dromara.productManagement.domain.vo.ContractualCaseArticlesVo;
import org.dromara.productManagement.domain.ContractualCaseFiles;
import org.dromara.productManagement.domain.ContractualCaseArticles;
import org.dromara.productManagement.mapper.ContractualCaseFilesMapper;
import org.dromara.productManagement.mapper.ContractualCaseArticlesMapper;
import org.dromara.productManagement.service.IContractualCaseFilesService;
import org.dromara.system.service.ISysOssService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.Stack;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.stream.Collectors;
// HTML转PDF相关导入
import org.xhtmlrenderer.pdf.ITextRenderer;
import org.apache.commons.io.FileUtils;
import com.lowagie.text.pdf.BaseFont;
// Milvus相关导入
import io.milvus.client.MilvusServiceClient;
import io.milvus.param.ConnectParam;
import io.milvus.param.dml.DeleteParam;
import io.milvus.grpc.MutationResult;
import io.milvus.param.R;
import jakarta.annotation.PreDestroy;
/**
* 合同案例文件Service业务层处理
*
* @author Lion Li
* @date 2025-06-04
*/
@RequiredArgsConstructor
@Service
public class ContractualCaseFilesServiceImpl implements IContractualCaseFilesService {
private final ContractualCaseFilesMapper baseMapper;
private final ContractualCaseArticlesMapper articlesMapper;
private final ISysOssService ossService;
private static final Logger log = LoggerFactory.getLogger(ContractualCaseFilesServiceImpl.class);
@Value("${chat.filePath}")
protected String fileRootPath;
@Value("${chat.chatUrl}")
protected String chatUrl;
// Milvus配置
@Value("${milvus.host:10.1.21.250}")
private String milvusHost;
@Value("${milvus.port:19530}")
private int milvusPort;
@Value("${milvus.collection.name:contractual_case_articles}")
private String milvusCollectionName = "contractual_case_articles";
private MilvusServiceClient milvusClient;
/**
* 查询合同案例文件
*
* @param id 主键
* @return 合同案例文件
*/
@Override
public ContractualCaseFilesVo queryById(Long id){
return baseMapper.selectVoById(id);
}
/**
* 分页查询合同案例文件列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 合同案例文件分页列表
*/
@Override
public TableDataInfo<ContractualCaseFilesVo> queryPageList(ContractualCaseFilesBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<ContractualCaseFiles> lqw = buildQueryWrapper(bo);
Page<ContractualCaseFilesVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询符合条件的合同案例文件列表
*
* @param bo 查询条件
* @return 合同案例文件列表
*/
@Override
public List<ContractualCaseFilesVo> queryList(ContractualCaseFilesBo bo) {
LambdaQueryWrapper<ContractualCaseFiles> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<ContractualCaseFiles> buildQueryWrapper(ContractualCaseFilesBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<ContractualCaseFiles> lqw = Wrappers.lambdaQuery();
lqw.like(StringUtils.isNotBlank(bo.getCaseName()), ContractualCaseFiles::getCaseName, bo.getCaseName());
lqw.like(StringUtils.isNotBlank(bo.getCaseType()), ContractualCaseFiles::getCaseType, bo.getCaseType());
// 日期范围查询
if (bo.getPublishDate() != null) {
// 如果传入的是单个日期,查询当天的记录
lqw.eq(ContractualCaseFiles::getPublishDate, bo.getPublishDate());
} else {
// 日期范围查询
lqw.ge(bo.getPublishDateStart() != null, ContractualCaseFiles::getPublishDate, bo.getPublishDateStart());
lqw.le(bo.getPublishDateEnd() != null, ContractualCaseFiles::getPublishDate, bo.getPublishDateEnd());
}
lqw.eq(StringUtils.isNotBlank(bo.getIsEffective()), ContractualCaseFiles::getIsEffective, bo.getIsEffective());
return lqw;
}
/**
* 新增合同案例文件
*
* @param bo 合同案例文件
* @return 是否新增成功
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean insertByBo(ContractualCaseFilesBo bo) {
try {
// 1. 保存案例基本信息
ContractualCaseFiles add = MapstructUtils.convert(bo, ContractualCaseFiles.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (!flag) {
throw new RuntimeException("保存案例信息失败");
}
bo.setId(add.getId());
log.info("成功新增案例文件,ID: {}, 案例名称: {}", add.getId(), add.getCaseName());
Long ossId = bo.getOssId();
// 2. 处理文档解析和向量化(如果有ossId)
if (ossId != null) {
try {
// 更新状态为解析中
add.setProgressStatus("PROCESSING");
SysOssVo fileInfo = ossService.getById(ossId);
String fileName = fileInfo.getOriginalName();
String filePath = fileRootPath + File.separator + fileInfo.getFileName();
// 调用Python接口启动案例分析任务
String pythonUrl = chatUrl + "/back/taskStart";
MyHttpUtils.sendTaskStartMessage(
pythonUrl,
add.getId(),
"contractualCaseFiles",
filePath,
1L
);
log.info("启动案例文档解析和向量化任务,ossId: {}, 案例名称: {}", bo.getOssId(), bo.getCaseName());
} catch (Exception e) {
// 处理失败,状态保持为PENDING
add.setProgressStatus("PENDING");
baseMapper.updateById(add);
log.error("案例文档处理失败: {}", e.getMessage(), e);
// 不抛异常,允许基本信息保存成功
}
}
return true;
} catch (Exception e) {
log.error("新增案例文件失败: {}", e.getMessage(), e);
throw new RuntimeException("新增案例文件失败: " + e.getMessage());
}
}
/**
* 修改合同案例文件
*
* @param bo 合同案例文件
* @return 是否修改成功
*/
@Override
public Boolean updateByBo(ContractualCaseFilesBo bo) {
ContractualCaseFiles update = MapstructUtils.convert(bo, ContractualCaseFiles.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 更新合同案例文件状态
*
* @param id 主键
* @param status 状态
* @return 是否更新成功
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean updateStatusById(Long id, String status) {
// 更新案例文件状态
ContractualCaseFiles entity = new ContractualCaseFiles();
entity.setId(id);
entity.setIsEffective(status);
boolean flag = baseMapper.updateById(entity) > 0;
if (flag) {
// 同时更新对应的案例条款状态
LambdaQueryWrapper<ContractualCaseArticles> wrapper = Wrappers.lambdaQuery();
wrapper.eq(ContractualCaseArticles::getCaseFileId, id);
ContractualCaseArticles articleUpdate = new ContractualCaseArticles();
articleUpdate.setIsEffective(status);
articlesMapper.update(articleUpdate, wrapper);
}
return flag;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(ContractualCaseFiles entity){
//TODO 做一些数据校验,如唯一约束
}
/**
* 校验并批量删除合同案例文件信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if (isValid) {
// TODO 做一些业务上的校验,判断是否需要校验
log.info("开始校验待删除的案例文件,数量: {}", ids.size());
}
boolean allSuccess = true;
// 逐个删除案例及其相关数据
for (Long id : ids) {
try {
// 1. 先从Milvus删除向量数据
boolean milvusDeleted = deleteFromMilvus(id);
if (!milvusDeleted) {
log.warn("案例文件ID {} 的Milvus向量数据删除失败,但继续删除其他数据", id);
}
// 2. 删除案例条款(真实删除)
int deletedArticles = articlesMapper.realDeleteByCaseFileId(id);
log.info("案例文件ID {} 删除了 {} 条案例条款", id, deletedArticles);
// 3. 删除案例主记录(真实删除)
int deletedCase = baseMapper.realDeleteById(id);
if (deletedCase > 0) {
log.info("成功删除案例文件ID: {}", id);
} else {
log.warn("删除案例文件ID {} 失败", id);
allSuccess = false;
}
} catch (Exception e) {
log.error("删除案例文件ID {} 时出错: {}", id, e.getMessage(), e);
allSuccess = false;
// 继续处理其他ID,不中断整个事务
}
}
if (allSuccess) {
log.info("成功删除 {} 个案例文件", ids.size());
} else {
log.warn("部分案例文件删除失败");
}
return allSuccess;
}
/**
* 获取案例条款列表
*
* @param caseFileId 案例文件ID
* @return 案例条款列表
*/
@Override
public List<ContractualCaseArticlesVo> getCaseArticles(Long caseFileId) {
LambdaQueryWrapper<ContractualCaseArticles> wrapper = Wrappers.lambdaQuery();
wrapper.eq(ContractualCaseArticles::getCaseFileId, caseFileId)
.orderByAsc(ContractualCaseArticles::getId);
List<ContractualCaseArticles> articles = articlesMapper.selectList(wrapper);
List<ContractualCaseArticlesVo> articleVos = MapstructUtils.convert(articles, ContractualCaseArticlesVo.class);
// 处理条款排序和标题提取,按条款序号从小到大排序
return articleVos.stream()
.peek(this::processArticle)
.sorted((a, b) -> {
Integer orderA = a.getArticleOrder();
Integer orderB = b.getArticleOrder();
// 如果都有序号,按序号排序
if (orderA != null && orderB != null) {
return orderA.compareTo(orderB);
}
// 有序号的排在前面
if (orderA != null && orderB == null) {
return -1;
}
if (orderA == null && orderB != null) {
return 1;
}
// 都没有序号,按ID排序
return a.getId().compareTo(b.getId());
})
.collect(Collectors.toList());
}
/**
* 生成案例PDF文档
*
* @param caseFileId 案例文件ID
* @param response HTTP响应
*/
@Override
public void generateCasePdf(Long caseFileId, HttpServletResponse response) {
try {
// 获取案例基本信息
ContractualCaseFilesVo caseFile = queryById(caseFileId);
if (caseFile == null) {
throw new RuntimeException("案例不存在");
}
// 获取案例条款
List<ContractualCaseArticlesVo> articles = getCaseArticles(caseFileId);
// 设置响应头
String fileName = URLEncoder.encode(caseFile.getCaseName() + ".pdf", StandardCharsets.UTF_8);
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "inline; filename=\"" + fileName + "\"");
// 生成HTML内容并转换为PDF
String htmlContent = generateHtmlContent(caseFile, articles);
ITextRenderer renderer = new ITextRenderer();
// 设置中文字体
try (InputStream is = getClass().getResourceAsStream("/fonts/msyh.ttc")) {
if (is != null) {
File tempFont = File.createTempFile("msyh", ".ttc");
FileUtils.copyInputStreamToFile(is, tempFont);
renderer.getFontResolver().addFont(tempFont.getAbsolutePath(), BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
tempFont.deleteOnExit();
}
} catch (Exception fontException) {
log.warn("加载字体文件失败,使用默认字体: {}", fontException.getMessage());
}
renderer.setDocumentFromString(htmlContent);
renderer.layout();
renderer.createPDF(response.getOutputStream());
} catch (Exception e) {
log.error("生成案例PDF失败: {}", e.getMessage(), e);
throw new RuntimeException("生成案例PDF失败: " + e.getMessage());
}
}
/**
* 生成HTML内容
*/
private String generateHtmlContent(ContractualCaseFilesVo caseFile, List<ContractualCaseArticlesVo> articles) {
StringBuilder html = new StringBuilder();
// 格式化发布日期
String formattedDate = "";
if (caseFile.getPublishDate() != null) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
formattedDate = sdf.format(caseFile.getPublishDate());
}
// 构建完整的HTML文档
html.append("""
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<style type="text/css">
body {
font-family: Microsoft YaHei, SimSun, Arial, sans-serif;
line-height: 1.8;
margin: 40px;
font-size: 14px;
color: #333;
}
.title {
font-size: 24px;
font-weight: bold;
text-align: center;
margin-bottom: 20px;
color: #000;
}
.case-info {
text-align: center;
margin-bottom: 30px;
font-size: 16px;
color: #666;
}
.case-info div {
margin-bottom: 10px;
}
.article {
margin-bottom: 30px;
text-align: justify;
text-indent: 2em;
}
.article-number {
font-weight: bold;
color: #000;
}
p {
margin: 15px 0;
line-height: 2.0;
}
</style>
</head>
<body>
""");
// 添加标题
html.append("<div class=\"title\">").append(caseFile.getCaseName()).append("</div>");
// 添加案例信息
html.append("<div class=\"case-info\">");
if (StringUtils.isNotBlank(formattedDate)) {
html.append("<div>发布日期:").append(formattedDate).append("</div>");
}
if (StringUtils.isNotBlank(caseFile.getCaseType())) {
html.append("<div>案例类型:").append(caseFile.getCaseType()).append("</div>");
}
html.append("</div>");
// 添加案例描述
if (StringUtils.isNotBlank(caseFile.getCaseDescription())) {
html.append("<div class=\"article\">");
html.append("<p><strong>案例描述:</strong></p>");
html.append("<p>").append(caseFile.getCaseDescription()).append("</p>");
html.append("</div>");
}
// 添加条款内容
for (ContractualCaseArticlesVo article : articles) {
html.append("<div class=\"article\">");
String content = article.getArticleContent();
if (StringUtils.isNotBlank(content)) {
// 处理内容,将"第XX条"等内容加粗
String processedContent = processArticleContent(content);
html.append("<p>").append(processedContent).append("</p>");
}
html.append("</div>");
}
html.append("</body></html>");
return html.toString();
}
/**
* 处理条款内容"第XX条"等关键内容加粗
*/
private String processArticleContent(String content) {
if (StringUtils.isBlank(content)) {
return content;
}
// 使用正则表达式匹配"第XX条"并加粗
Pattern pattern = Pattern.compile("第([零一二三四五六七八九十百千万\\d]+)条");
return pattern.matcher(content).replaceAll("<span class=\"article-number\">第$1条</span>");
}
/**
* 处理条款信息提取序号
*/
private void processArticle(ContractualCaseArticlesVo article) {
String content = article.getArticleContent();
if (StringUtils.isBlank(content)) {
return;
}
// 提取条款序号
Integer order = extractArticleOrder(content);
article.setArticleOrder(order);
}
/**
* 提取条款序号
*/
private Integer extractArticleOrder(String content) {
// 匹配 "第XX条" 格式
Pattern pattern = Pattern.compile("第([零一二三四五六七八九十百千万\\d]+)条");
Matcher matcher = pattern.matcher(content);
if (matcher.find()) {
String numberStr = matcher.group(1);
return convertChineseNumberToInt(numberStr);
}
return null;
}
/**
* 将中文数字转换为阿拉伯数字
* @author Tuzi294
* @param chineseNumber 中文数字字符串
* @return 转换后的阿拉伯数字
*/
private Integer convertChineseNumberToInt(String chineseNumber) {
if (StringUtils.isBlank(chineseNumber)) {
return null;
}
// 如果已经是阿拉伯数字,直接返回
if (chineseNumber.matches("\\d+")) {
return Integer.parseInt(chineseNumber);
}
try {
String aval = "零一二三四五六七八九";
String bval = "十百千万亿";
int[] bnum = {10, 100, 1000, 10000, 100000000};
long num = 0;
char[] arr = chineseNumber.toCharArray();
int len = arr.length;
Stack<Integer> stack = new Stack<>();
for (int i = 0; i < len; i++) {
char s = arr[i];
//跳过零
if (s == '零') continue;
//用下标找到对应数字
int index = bval.indexOf(s);
//如果不在bval中,即当前字符为数字,直接入栈
if (index == -1) {
stack.push(aval.indexOf(s));
} else { //当前字符为单位。
int tempsum = 0;
int val = bnum[index];
//如果栈为空则直接入栈
if (stack.isEmpty()) {
stack.push(val);
continue;
}
//如果栈中有比val小的元素则出栈,累加,乘N,再入栈
while (!stack.isEmpty() && stack.peek() < val) {
tempsum += stack.pop();
}
//判断是否经过乘法处理
if (tempsum == 0) {
stack.push(val);
} else {
stack.push(tempsum * val);
}
}
}
//计算最终的和
while (!stack.isEmpty()) {
num += stack.pop();
}
return num > 0 ? (int) num : null;
} catch (Exception e) {
log.warn("转换中文数字失败: {}", chineseNumber, e);
// 如果转换失败,使用hashCode确保一致性
return Math.abs(chineseNumber.hashCode() % 1000);
}
}
/**
* 初始化Milvus客户端
*/
private MilvusServiceClient getMilvusClient() {
if (milvusClient == null) {
try {
milvusClient = new MilvusServiceClient(
ConnectParam.newBuilder()
.withHost(milvusHost)
.withPort(milvusPort)
.build()
);
log.info("Milvus客户端初始化成功: {}:{}", milvusHost, milvusPort);
} catch (Exception e) {
log.error("初始化Milvus客户端失败: {}", e.getMessage(), e);
return null;
}
}
return milvusClient;
}
/**
* 从Milvus中删除案例相关的向量数据
*/
private boolean deleteFromMilvus(Long caseFileId) {
try {
MilvusServiceClient client = getMilvusClient();
if (client == null) {
log.warn("Milvus客户端未初始化,跳过向量数据删除");
return false;
}
// 构造删除表达式 - 删除指定案例文件ID的所有向量
String deleteExpr = String.format("case_file_id == %d", caseFileId);
DeleteParam deleteParam = DeleteParam.newBuilder()
.withCollectionName(milvusCollectionName)
.withExpr(deleteExpr)
.build();
R<MutationResult> response = client.delete(deleteParam);
if (response.getStatus() == R.Status.Success.getCode()) {
MutationResult mutationResponse = response.getData();
long deleteCount = mutationResponse.getDeleteCnt();
log.info("成功从Milvus删除案例文件ID {} 的向量数据,删除数量: {}", caseFileId, deleteCount);
return true;
} else {
log.error("从Milvus删除向量数据失败: {}", response.getMessage());
return false;
}
} catch (Exception e) {
log.error("从Milvus删除向量数据时出错: {}", e.getMessage(), e);
return false;
}
}
@PreDestroy
public void closeMilvusClient() {
if (milvusClient != null) {
milvusClient.close();
log.info("Milvus客户端已关闭");
}
}
}

272
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/service/impl/ContractualRegulationArticlesServiceImpl.java

@ -0,0 +1,272 @@
package org.dromara.productManagement.service.impl;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.dromara.productManagement.domain.bo.ContractualRegulationArticlesBo;
import org.dromara.productManagement.domain.vo.ContractualRegulationArticlesVo;
import org.dromara.productManagement.domain.ContractualRegulationArticles;
import org.dromara.productManagement.mapper.ContractualRegulationArticlesMapper;
import org.dromara.productManagement.service.IContractualRegulationArticlesService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
// Milvus相关导入
import io.milvus.client.MilvusServiceClient;
import io.milvus.param.ConnectParam;
import io.milvus.param.dml.DeleteParam;
import io.milvus.grpc.MutationResult;
import io.milvus.param.R;
import org.springframework.beans.factory.annotation.Value;
import jakarta.annotation.PreDestroy;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* 合同法规法条Service业务层处理
*
* @author Lion Li
* @date 2025-06-05
*/
@RequiredArgsConstructor
@Service
public class ContractualRegulationArticlesServiceImpl implements IContractualRegulationArticlesService {
private final ContractualRegulationArticlesMapper baseMapper;
private static final Logger log = LoggerFactory.getLogger(ContractualRegulationArticlesServiceImpl.class);
// Milvus配置
@Value("${milvus.host:10.1.21.250}")
private String milvusHost;
@Value("${milvus.port:19530}")
private int milvusPort;
@Value("${milvus.collection.name:contractual_case_articles}")
private String milvusCollectionName;
private MilvusServiceClient milvusClient;
/**
* 查询合同法规法条
*
* @param id 主键
* @return 合同法规法条
*/
@Override
public ContractualRegulationArticlesVo queryById(Long id){
return baseMapper.selectVoById(id);
}
/**
* 分页查询合同法规法条列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 合同法规法条分页列表
*/
@Override
public TableDataInfo<ContractualRegulationArticlesVo> queryPageList(ContractualRegulationArticlesBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<ContractualRegulationArticles> lqw = buildQueryWrapper(bo);
Page<ContractualRegulationArticlesVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询符合条件的合同法规法条列表
*
* @param bo 查询条件
* @return 合同法规法条列表
*/
@Override
public List<ContractualRegulationArticlesVo> queryList(ContractualRegulationArticlesBo bo) {
LambdaQueryWrapper<ContractualRegulationArticles> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<ContractualRegulationArticles> buildQueryWrapper(ContractualRegulationArticlesBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<ContractualRegulationArticles> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getRegulationNameId() != null, ContractualRegulationArticles::getRegulationNameId, bo.getRegulationNameId());
lqw.like(StringUtils.isNotBlank(bo.getArticleContent()), ContractualRegulationArticles::getArticleContent, bo.getArticleContent());
lqw.eq(bo.getVectorTableId() != null, ContractualRegulationArticles::getVectorTableId, bo.getVectorTableId());
lqw.eq(StringUtils.isNotBlank(bo.getIsEffective()), ContractualRegulationArticles::getIsEffective, bo.getIsEffective());
return lqw;
}
/**
* 新增合同法规法条
*
* @param bo 合同法规法条
* @return 是否新增成功
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean insertByBo(ContractualRegulationArticlesBo bo) {
try {
ContractualRegulationArticles add = MapstructUtils.convert(bo, ContractualRegulationArticles.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (!flag) {
throw new RuntimeException("保存法规条款信息失败");
}
bo.setId(add.getId());
log.info("成功新增法规条款,ID: {}, 法规名称ID: {}", add.getId(), add.getRegulationNameId());
// TODO: 如果需要向量化处理,可以在此处添加
// 预留代码空位,后续可以处理条款的向量化存储
return true;
} catch (Exception e) {
log.error("新增法规条款失败: {}", e.getMessage(), e);
throw new RuntimeException("新增法规条款失败: " + e.getMessage());
}
}
/**
* 修改合同法规法条
*
* @param bo 合同法规法条
* @return 是否修改成功
*/
@Override
public Boolean updateByBo(ContractualRegulationArticlesBo bo) {
ContractualRegulationArticles update = MapstructUtils.convert(bo, ContractualRegulationArticles.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(ContractualRegulationArticles entity){
//TODO 做一些数据校验,如唯一约束
}
/**
* 校验并批量删除合同法规法条信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if (isValid) {
// TODO 做一些业务上的校验,判断是否需要校验
log.info("开始校验待删除的法规条款,数量: {}", ids.size());
}
boolean allSuccess = true;
// 逐个删除法规条款及其相关数据
for (Long id : ids) {
try {
// 1. 先从Milvus删除向量数据(如果存在)
boolean milvusDeleted = deleteFromMilvus(id);
if (!milvusDeleted) {
log.warn("法规条款ID {} 的Milvus向量数据删除失败,但继续删除其他数据", id);
}
// 2. 删除法规条款主记录
int deletedCount = baseMapper.deleteById(id);
if (deletedCount > 0) {
log.info("成功删除法规条款ID: {}", id);
} else {
log.warn("删除法规条款ID {} 失败", id);
allSuccess = false;
}
} catch (Exception e) {
log.error("删除法规条款ID {} 时出错: {}", id, e.getMessage(), e);
allSuccess = false;
// 继续处理其他ID,不中断整个事务
}
}
if (allSuccess) {
log.info("成功删除 {} 个法规条款", ids.size());
} else {
log.warn("部分法规条款删除失败");
}
return allSuccess;
}
/**
* 初始化Milvus客户端
*/
private MilvusServiceClient getMilvusClient() {
if (milvusClient == null) {
try {
milvusClient = new MilvusServiceClient(
ConnectParam.newBuilder()
.withHost(milvusHost)
.withPort(milvusPort)
.build()
);
log.info("Milvus客户端初始化成功: {}:{}", milvusHost, milvusPort);
} catch (Exception e) {
log.error("初始化Milvus客户端失败: {}", e.getMessage(), e);
return null;
}
}
return milvusClient;
}
/**
* 从Milvus中删除法规条款相关的向量数据
*/
private boolean deleteFromMilvus(Long articleId) {
try {
MilvusServiceClient client = getMilvusClient();
if (client == null) {
log.warn("Milvus客户端未初始化,跳过向量数据删除");
return false;
}
// 构造删除表达式 - 删除指定条款ID的向量
String deleteExpr = String.format("article_id == %d", articleId);
DeleteParam deleteParam = DeleteParam.newBuilder()
.withCollectionName(milvusCollectionName)
.withExpr(deleteExpr)
.build();
R<MutationResult> response = client.delete(deleteParam);
if (response.getStatus() == R.Status.Success.getCode()) {
MutationResult mutationResponse = response.getData();
long deleteCount = mutationResponse.getDeleteCnt();
log.info("成功从Milvus删除法规条款ID {} 的向量数据,删除数量: {}", articleId, deleteCount);
return true;
} else {
log.error("从Milvus删除向量数据失败: {}", response.getMessage());
return false;
}
} catch (Exception e) {
log.error("从Milvus删除向量数据时出错: {}", e.getMessage(), e);
return false;
}
}
@PreDestroy
public void closeMilvusClient() {
if (milvusClient != null) {
milvusClient.close();
log.info("Milvus客户端已关闭");
}
}
}

640
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/service/impl/ContractualRegulationNamesServiceImpl.java

@ -0,0 +1,640 @@
package org.dromara.productManagement.service.impl;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.productManagement.utils.MyHttpUtils;
import org.dromara.system.domain.vo.SysOssVo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.dromara.productManagement.domain.bo.ContractualRegulationNamesBo;
import org.dromara.productManagement.domain.vo.ContractualRegulationNamesVo;
import org.dromara.productManagement.domain.vo.ContractualRegulationArticlesVo;
import org.dromara.productManagement.domain.ContractualRegulationNames;
import org.dromara.productManagement.domain.ContractualRegulationArticles;
import org.dromara.productManagement.mapper.ContractualRegulationNamesMapper;
import org.dromara.productManagement.mapper.ContractualRegulationArticlesMapper;
import org.dromara.productManagement.service.IContractualRegulationNamesService;
import org.dromara.productManagement.service.IContractualRegulationArticlesService;
import org.dromara.system.service.ISysOssService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.Stack;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.stream.Collectors;
// HTML转PDF相关导入
import org.xhtmlrenderer.pdf.ITextRenderer;
import org.apache.commons.io.FileUtils;
import com.lowagie.text.pdf.BaseFont;
// Milvus相关导入
import io.milvus.client.MilvusServiceClient;
import io.milvus.param.ConnectParam;
import io.milvus.param.dml.DeleteParam;
import io.milvus.grpc.MutationResult;
import io.milvus.param.R;
import jakarta.annotation.PreDestroy;
/**
* 合同法规名称Service业务层处理
*
* @author Lion Li
* @date 2025-06-04
*/
@RequiredArgsConstructor
@Service
public class ContractualRegulationNamesServiceImpl implements IContractualRegulationNamesService {
private final ContractualRegulationNamesMapper baseMapper;
private final ContractualRegulationArticlesMapper articlesMapper;
private final IContractualRegulationArticlesService articlesService;
private final ISysOssService ossService;
private static final Logger log = LoggerFactory.getLogger(ContractualRegulationNamesServiceImpl.class);
@Value("${chat.filePath}")
protected String fileRootPath;
@Value("${chat.chatUrl}")
protected String chatUrl;
// Milvus配置
@Value("${milvus.host:10.1.21.250}")
private String milvusHost;
@Value("${milvus.port:19530}")
private int milvusPort;
@Value("${milvus.collection.name:contractual_regulation_articles}")
private String milvusCollectionName;
private MilvusServiceClient milvusClient;
/**
* 查询合同法规名称
*
* @param id 主键
* @return 合同法规名称
*/
@Override
public ContractualRegulationNamesVo queryById(Long id){
return baseMapper.selectVoById(id);
}
/**
* 分页查询合同法规名称列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 合同法规名称分页列表
*/
@Override
public TableDataInfo<ContractualRegulationNamesVo> queryPageList(ContractualRegulationNamesBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<ContractualRegulationNames> lqw = buildQueryWrapper(bo);
Page<ContractualRegulationNamesVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询符合条件的合同法规名称列表
*
* @param bo 查询条件
* @return 合同法规名称列表
*/
@Override
public List<ContractualRegulationNamesVo> queryList(ContractualRegulationNamesBo bo) {
LambdaQueryWrapper<ContractualRegulationNames> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<ContractualRegulationNames> buildQueryWrapper(ContractualRegulationNamesBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<ContractualRegulationNames> lqw = Wrappers.lambdaQuery();
lqw.like(StringUtils.isNotBlank(bo.getRegulationName()), ContractualRegulationNames::getRegulationName, bo.getRegulationName());
// 日期范围查询
if (bo.getPublishDate() != null) {
// 如果传入的是单个日期,查询当天的记录
lqw.eq(ContractualRegulationNames::getPublishDate, bo.getPublishDate());
} else {
// 日期范围查询
lqw.ge(bo.getPublishDateStart() != null, ContractualRegulationNames::getPublishDate, bo.getPublishDateStart());
lqw.le(bo.getPublishDateEnd() != null, ContractualRegulationNames::getPublishDate, bo.getPublishDateEnd());
}
lqw.eq(StringUtils.isNotBlank(bo.getIsEffective()), ContractualRegulationNames::getIsEffective, bo.getIsEffective());
return lqw;
}
/**
* 新增合同法规名称
*
* @param bo 合同法规名称
* @return 是否新增成功
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean insertByBo(ContractualRegulationNamesBo bo) {
// 1. 保存法规基本信息
ContractualRegulationNames add = MapstructUtils.convert(bo, ContractualRegulationNames.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (!flag) {
throw new RuntimeException("保存法规信息失败");
}
bo.setId(add.getId());
Long ossId = bo.getOssId();
// 2. 处理文档解析和向量化(如果有ossId)
if (ossId!= null) {
try {
// 更新状态为解析中
add.setProgressStatus("PROCESSING");
SysOssVo fileInfo = ossService.getById(ossId);
String fileName = fileInfo.getOriginalName();
String filePath = fileRootPath + File.separator +fileInfo.getFileName();
// 7. 调用Python接口启动任务
String pythonUrl = chatUrl + "/back/taskStart";
MyHttpUtils.sendTaskStartMessage(
pythonUrl,
add.getId(),
"contractualRegulationNames",
filePath,
1L
);
// TODO: 实现文档处理逻辑
// 这里预留代码空位,后续可以通过异步任务或定时任务来处理文档解析
log.info("预留处理文档解析和向量化,ossId: {}, 法规名称: {}", bo.getOssId(), bo.getRegulationName());
} catch (Exception e) {
// 处理失败,状态保持为PENDING
add.setProgressStatus("PENDING");
baseMapper.updateById(add);
log.error("文档处理失败: {}", e.getMessage(), e);
// 不抛异常,允许基本信息保存成功
}
}
return true;
}
/**
* 修改合同法规名称
*
* @param bo 合同法规名称
* @return 是否修改成功
*/
@Override
public Boolean updateByBo(ContractualRegulationNamesBo bo) {
ContractualRegulationNames update = MapstructUtils.convert(bo, ContractualRegulationNames.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 更新合同法规名称状态
*
* @param id 主键
* @param status 状态
* @return 是否更新成功
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean updateStatusById(Long id, String status) {
// 更新法规名称状态
ContractualRegulationNames entity = new ContractualRegulationNames();
entity.setId(id);
entity.setIsEffective(status);
boolean flag = baseMapper.updateById(entity) > 0;
if (flag) {
// 同时更新对应的法规条款状态
LambdaQueryWrapper<ContractualRegulationArticles> wrapper = Wrappers.lambdaQuery();
wrapper.eq(ContractualRegulationArticles::getRegulationNameId, id);
ContractualRegulationArticles articleUpdate = new ContractualRegulationArticles();
articleUpdate.setIsEffective(status);
articlesMapper.update(articleUpdate, wrapper);
}
return flag;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(ContractualRegulationNames entity){
//TODO 做一些数据校验,如唯一约束
}
/**
* 校验并批量删除合同法规名称信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
boolean allSuccess = true;
// 逐个删除法规及其相关数据
for (Long id : ids) {
try {
// 1. 先从Milvus删除向量数据
boolean milvusDeleted = deleteFromMilvus(id);
if (!milvusDeleted) {
log.warn("法规ID {} 的Milvus向量数据删除失败,但继续删除其他数据", id);
}
// 2. 删除法规条款(真实删除)
int deletedArticles = articlesMapper.realDeleteByRegulationNameId(id);
log.info("法规ID {} 删除了 {} 条法规条款", id, deletedArticles);
// 3. 删除法规主记录(真实删除)
int deletedRegulation = baseMapper.realDeleteById(id);
if (deletedRegulation > 0) {
log.info("成功删除法规ID: {}", id);
} else {
log.warn("删除法规ID {} 失败", id);
allSuccess = false;
}
} catch (Exception e) {
log.error("删除法规ID {} 时出错: {}", id, e.getMessage(), e);
allSuccess = false;
// 继续处理其他ID,不中断整个事务
}
}
return allSuccess;
}
/**
* 获取法规条款列表
*
* @param regulationNameId 法规名称ID
* @return 法规条款列表
*/
@Override
public List<ContractualRegulationArticlesVo> getRegulationArticles(Long regulationNameId) {
LambdaQueryWrapper<ContractualRegulationArticles> wrapper = Wrappers.lambdaQuery();
wrapper.eq(ContractualRegulationArticles::getRegulationNameId, regulationNameId)
.orderByAsc(ContractualRegulationArticles::getId);
List<ContractualRegulationArticles> articles = articlesMapper.selectList(wrapper);
List<ContractualRegulationArticlesVo> articleVos = MapstructUtils.convert(articles, ContractualRegulationArticlesVo.class);
// 处理条款排序和标题提取,按条款序号从小到大排序
return articleVos.stream()
.peek(this::processArticle)
.sorted((a, b) -> {
Integer orderA = a.getArticleOrder();
Integer orderB = b.getArticleOrder();
// 如果都有序号,按序号排序
if (orderA != null && orderB != null) {
return orderA.compareTo(orderB);
}
// 有序号的排在前面
if (orderA != null && orderB == null) {
return -1;
}
if (orderA == null && orderB != null) {
return 1;
}
// 都没有序号,按ID排序
return a.getId().compareTo(b.getId());
})
.collect(Collectors.toList());
}
/**
* 生成法规PDF文档
*
* @param regulationNameId 法规名称ID
* @param response HTTP响应
*/
@Override
public void generateRegulationPdf(Long regulationNameId, HttpServletResponse response) {
try {
// 获取法规基本信息
ContractualRegulationNamesVo regulation = queryById(regulationNameId);
if (regulation == null) {
throw new RuntimeException("法规不存在");
}
// 获取法规条款
List<ContractualRegulationArticlesVo> articles = getRegulationArticles(regulationNameId);
// 设置响应头
String fileName = URLEncoder.encode(regulation.getRegulationName() + ".pdf", StandardCharsets.UTF_8);
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "inline; filename=\"" + fileName + "\"");
// 生成HTML内容并转换为PDF
String htmlContent = generateHtmlContent(regulation, articles);
ITextRenderer renderer = new ITextRenderer();
// 设置中文字体
try (InputStream is = getClass().getResourceAsStream("/fonts/msyh.ttc")) {
if (is != null) {
File tempFont = File.createTempFile("msyh", ".ttc");
FileUtils.copyInputStreamToFile(is, tempFont);
renderer.getFontResolver().addFont(tempFont.getAbsolutePath(), BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
tempFont.deleteOnExit();
}
} catch (Exception fontException) {
log.warn("加载字体文件失败,使用默认字体: {}", fontException.getMessage());
}
renderer.setDocumentFromString(htmlContent);
renderer.layout();
renderer.createPDF(response.getOutputStream());
} catch (Exception e) {
log.error("生成PDF失败: {}", e.getMessage(), e);
throw new RuntimeException("生成PDF失败: " + e.getMessage());
}
}
/**
* 生成HTML内容
*/
private String generateHtmlContent(ContractualRegulationNamesVo regulation, List<ContractualRegulationArticlesVo> articles) {
StringBuilder html = new StringBuilder();
// 格式化发布日期
String formattedDate = "";
if (regulation.getPublishDate() != null) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
formattedDate = sdf.format(regulation.getPublishDate());
}
// 构建完整的HTML文档
html.append("""
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<style type="text/css">
body {
font-family: Microsoft YaHei, SimSun, Arial, sans-serif;
line-height: 1.8;
margin: 40px;
font-size: 14px;
color: #333;
}
.title {
font-size: 24px;
font-weight: bold;
text-align: center;
margin-bottom: 20px;
color: #000;
}
.publish-date {
text-align: center;
margin-bottom: 40px;
font-size: 16px;
color: #666;
}
.article {
margin-bottom: 30px;
text-align: justify;
text-indent: 2em;
}
.article-number {
font-weight: bold;
color: #000;
}
p {
margin: 15px 0;
line-height: 2.0;
}
</style>
</head>
<body>
""");
// 添加标题
html.append("<div class=\"title\">").append(regulation.getRegulationName()).append("</div>");
// 添加发布日期
if (StringUtils.isNotBlank(formattedDate)) {
html.append("<div class=\"publish-date\">发布日期:").append(formattedDate).append("</div>");
}
// 添加条款内容
for (ContractualRegulationArticlesVo article : articles) {
html.append("<div class=\"article\">");
String content = article.getArticleContent();
if (StringUtils.isNotBlank(content)) {
// 处理内容,将"第XX条"加粗
String processedContent = processArticleContent(content);
html.append("<p>").append(processedContent).append("</p>");
}
html.append("</div>");
}
html.append("</body></html>");
return html.toString();
}
/**
* 处理条款内容"第XX条"加粗
*/
private String processArticleContent(String content) {
if (StringUtils.isBlank(content)) {
return content;
}
// 使用正则表达式匹配"第XX条"并加粗
Pattern pattern = Pattern.compile("第([零一二三四五六七八九十百千万\\d]+)条");
return pattern.matcher(content).replaceAll("<span class=\"article-number\">第$1条</span>");
}
/**
* 处理条款信息提取序号
*/
private void processArticle(ContractualRegulationArticlesVo article) {
String content = article.getArticleContent();
if (StringUtils.isBlank(content)) {
return;
}
// 提取条款序号
Integer order = extractArticleOrder(content);
article.setArticleOrder(order);
}
/**
* 提取条款序号
*/
private Integer extractArticleOrder(String content) {
// 匹配 "第XX条" 格式
Pattern pattern = Pattern.compile("第([零一二三四五六七八九十百千万\\d]+)条");
Matcher matcher = pattern.matcher(content);
if (matcher.find()) {
String numberStr = matcher.group(1);
return convertChineseNumberToInt(numberStr);
}
return null;
}
/**
* 将中文数字转换为阿拉伯数字
* @author Tuzi294
* @param chineseNumber 中文数字字符串
* @return 转换后的阿拉伯数字
*/
private Integer convertChineseNumberToInt(String chineseNumber) {
if (StringUtils.isBlank(chineseNumber)) {
return null;
}
// 如果已经是阿拉伯数字,直接返回
if (chineseNumber.matches("\\d+")) {
return Integer.parseInt(chineseNumber);
}
try {
String aval = "零一二三四五六七八九";
String bval = "十百千万亿";
int[] bnum = {10, 100, 1000, 10000, 100000000};
long num = 0;
char[] arr = chineseNumber.toCharArray();
int len = arr.length;
Stack<Integer> stack = new Stack<>();
for (int i = 0; i < len; i++) {
char s = arr[i];
//跳过零
if (s == '零') continue;
//用下标找到对应数字
int index = bval.indexOf(s);
//如果不在bval中,即当前字符为数字,直接入栈
if (index == -1) {
stack.push(aval.indexOf(s));
} else { //当前字符为单位。
int tempsum = 0;
int val = bnum[index];
//如果栈为空则直接入栈
if (stack.isEmpty()) {
stack.push(val);
continue;
}
//如果栈中有比val小的元素则出栈,累加,乘N,再入栈
while (!stack.isEmpty() && stack.peek() < val) {
tempsum += stack.pop();
}
//判断是否经过乘法处理
if (tempsum == 0) {
stack.push(val);
} else {
stack.push(tempsum * val);
}
}
}
//计算最终的和
while (!stack.isEmpty()) {
num += stack.pop();
}
return num > 0 ? (int) num : null;
} catch (Exception e) {
log.warn("转换中文数字失败: {}", chineseNumber, e);
// 如果转换失败,使用hashCode确保一致性
return Math.abs(chineseNumber.hashCode() % 1000);
}
}
/**
* 初始化Milvus客户端
*/
private MilvusServiceClient getMilvusClient() {
if (milvusClient == null) {
try {
milvusClient = new MilvusServiceClient(
ConnectParam.newBuilder()
.withHost(milvusHost)
.withPort(milvusPort)
.build()
);
log.info("Milvus客户端初始化成功: {}:{}", milvusHost, milvusPort);
} catch (Exception e) {
log.error("初始化Milvus客户端失败: {}", e.getMessage(), e);
return null;
}
}
return milvusClient;
}
/**
* 从Milvus中删除法规相关的向量数据
*/
private boolean deleteFromMilvus(Long regulationNameId) {
try {
MilvusServiceClient client = getMilvusClient();
if (client == null) {
log.warn("Milvus客户端未初始化,跳过向量数据删除");
return false;
}
// 构造删除表达式 - 删除指定法规ID的所有向量
String deleteExpr = String.format("regulation_name_id == %d", regulationNameId);
DeleteParam deleteParam = DeleteParam.newBuilder()
.withCollectionName(milvusCollectionName)
.withExpr(deleteExpr)
.build();
R<MutationResult> response = client.delete(deleteParam);
if (response.getStatus() == R.Status.Success.getCode()) {
MutationResult mutationResponse = response.getData();
long deleteCount = mutationResponse.getDeleteCnt();
log.info("成功从Milvus删除法规ID {} 的向量数据,删除数量: {}", regulationNameId, deleteCount);
return true;
} else {
log.error("从Milvus删除向量数据失败: {}", response.getMessage());
return false;
}
} catch (Exception e) {
log.error("从Milvus删除向量数据时出错: {}", e.getMessage(), e);
return false;
}
}
@PreDestroy
public void closeMilvusClient() {
if (milvusClient != null) {
milvusClient.close();
log.info("Milvus客户端已关闭");
}
}
}

34
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/service/impl/ContractualTasksServiceImpl.java

@ -233,11 +233,29 @@ public class ContractualTasksServiceImpl extends AbstractTaskProcessor<Contractu
FileProcessResult fileProcessResult = processFile(Long.valueOf(request.getOssId())); FileProcessResult fileProcessResult = processFile(Long.valueOf(request.getOssId()));
String filePath = fileProcessResult.getFilePath(); String filePath = fileProcessResult.getFilePath();
String fileName = fileProcessResult.getFileName(); String fileName = fileProcessResult.getFileName();
// 1. 参数验证 // 1. 参数验证
if (request.getOssId() == null || request.getOssId().trim().isEmpty()) { if (request.getOssId() == null || request.getOssId().trim().isEmpty()) {
throw new IllegalArgumentException("文件ID不能为空"); throw new IllegalArgumentException("文件ID不能为空");
} }
// 2. 处理一致性审查中的招投标文件ossId转换为文件路径
if (request.getReviewData() != null && request.getReviewData().getConsistency() != null) {
StartContractReviewRequest.ConsistencyData consistencyData = request.getReviewData().getConsistency();
if (consistencyData.getBidDocumentOssId() != null && !consistencyData.getBidDocumentOssId().trim().isEmpty()) {
try {
// 根据招投标文件的ossId获取文件路径
FileProcessResult bidFileResult = processFile(Long.valueOf(consistencyData.getBidDocumentOssId()));
String bidFilePath = bidFileResult.getFilePath();
// 将文件路径设置到bidDocumentPath字段中
consistencyData.setBidDocumentPath(bidFilePath);
} catch (Exception e) {
throw new IllegalArgumentException("招投标文件处理失败: " + e.getMessage());
}
}
}
// 3. 创建合同任务记录 // 3. 创建合同任务记录
ContractualTasks contractTask = new ContractualTasks(); ContractualTasks contractTask = new ContractualTasks();
@ -246,8 +264,11 @@ public class ContractualTasksServiceImpl extends AbstractTaskProcessor<Contractu
contractTask.setDocumentName(fileName); contractTask.setDocumentName(fileName);
contractTask.setTaskType(TaskEnum.TaskType.CONTRACT_REVIEW.getValue()); contractTask.setTaskType(TaskEnum.TaskType.CONTRACT_REVIEW.getValue());
contractTask.setProgressStatus("PENDING"); contractTask.setProgressStatus("PENDING");
// 4. 处理合同方角色
String contractPartyRole = "中立"; // 默认值
if (request.getReviewData() != null && request.getReviewData().getSubstantive() != null) {
String position = request.getReviewData().getSubstantive().getPosition(); String position = request.getReviewData().getSubstantive().getPosition();
String contractPartyRole;
switch (position) { switch (position) {
case "party-a": case "party-a":
contractPartyRole = "甲方"; contractPartyRole = "甲方";
@ -263,19 +284,20 @@ public class ContractualTasksServiceImpl extends AbstractTaskProcessor<Contractu
break; break;
} }
request.getReviewData().getSubstantive().setPosition(contractPartyRole); request.getReviewData().getSubstantive().setPosition(contractPartyRole);
}
contractTask.setContractPartyRole(contractPartyRole); contractTask.setContractPartyRole(contractPartyRole);
// 4. 将reviewData序列化并保存到review_data字段
// 5. 将reviewData序列化并保存到review_data字段
ObjectMapper objectMapper = new ObjectMapper(); ObjectMapper objectMapper = new ObjectMapper();
String reviewDataJson = objectMapper.writeValueAsString(request.getReviewData()); String reviewDataJson = objectMapper.writeValueAsString(request.getReviewData());
contractTask.setReviewData(reviewDataJson); contractTask.setReviewData(reviewDataJson);
// 6. 保存到数据库
// 5. 保存到数据库
if (!saveTaskEntity(contractTask)) { if (!saveTaskEntity(contractTask)) {
throw new RuntimeException("保存合同任务失败"); throw new RuntimeException("保存合同任务失败");
} }
// 6. 调用Python接口启动任务 // 7. 调用Python接口启动任务
String pythonUrl = chatUrl + "/back/taskStart"; String pythonUrl = chatUrl + "/back/taskStart";
MyHttpUtils.sendTaskStartMessage( MyHttpUtils.sendTaskStartMessage(
pythonUrl, pythonUrl,
@ -285,7 +307,7 @@ public class ContractualTasksServiceImpl extends AbstractTaskProcessor<Contractu
1L 1L
); );
// 7. 立即返回任务创建成功信息 // 8. 立即返回任务创建成功信息
Map<String, Object> result = new HashMap<>(); Map<String, Object> result = new HashMap<>();
result.put("success", true); result.put("success", true);
result.put("message", "合同审查任务已创建,正在后台处理"); result.put("message", "合同审查任务已创建,正在后台处理");

32
zaojiaManagement/zaojia-productManagement/src/main/resources/mapper/productManagement/ContractualCaseArticlesMapper.xml

@ -0,0 +1,32 @@
<?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.dromara.productManagement.mapper.ContractualCaseArticlesMapper">
<resultMap type="org.dromara.productManagement.domain.ContractualCaseArticles" id="ContractualCaseArticlesResult">
<result property="id" column="id" />
<result property="caseFileId" column="case_file_id" />
<result property="articleContent" column="article_content" />
<result property="vectorTableId" column="vector_table_id" />
<result property="isEffective" column="is_effective" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
<result property="delFlag" column="del_flag" />
<result property="tenantId" column="tenant_id" />
</resultMap>
<sql id="selectContractualCaseArticlesVo">
select id, case_file_id, article_content, vector_table_id, is_effective,
create_by, create_time, update_by, update_time, del_flag, tenant_id
from contractual_case_articles
</sql>
<!-- 根据案例文件ID真实删除条款记录 -->
<delete id="realDeleteByCaseFileId" parameterType="java.lang.Long">
DELETE FROM contractual_case_articles WHERE case_file_id = #{caseFileId}
</delete>
</mapper>

34
zaojiaManagement/zaojia-productManagement/src/main/resources/mapper/productManagement/ContractualCaseFilesMapper.xml

@ -0,0 +1,34 @@
<?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.dromara.productManagement.mapper.ContractualCaseFilesMapper">
<resultMap type="org.dromara.productManagement.domain.ContractualCaseFiles" id="ContractualCaseFilesResult">
<result property="id" column="id" />
<result property="caseName" column="case_name" />
<result property="caseDescription" column="case_description" />
<result property="caseType" column="case_type" />
<result property="publishDate" column="publish_date" />
<result property="isEffective" column="is_effective" />
<result property="progressStatus" column="progress_status" />
<result property="ossId" column="oss_id" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
<result property="delFlag" column="del_flag" />
</resultMap>
<sql id="selectContractualCaseFilesVo">
select id, case_name, case_description, case_type, publish_date,
is_effective, progress_status, oss_id, create_by, create_time, update_by, update_time, del_flag
from contractual_case_files
</sql>
<!-- 真实删除案例文件记录 -->
<delete id="realDeleteById" parameterType="java.lang.Long">
DELETE FROM contractual_case_files WHERE id = #{id}
</delete>
</mapper>

7
zaojiaManagement/zaojia-productManagement/src/main/resources/mapper/productManagement/ContractualRegulationArticlesMapper.xml

@ -0,0 +1,7 @@
<?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.dromara.productManagement.mapper.ContractualRegulationArticlesMapper">
</mapper>

7
zaojiaManagement/zaojia-productManagement/src/main/resources/mapper/productManagement/ContractualRegulationNamesMapper.xml

@ -0,0 +1,7 @@
<?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.dromara.productManagement.mapper.ContractualRegulationNamesMapper">
</mapper>
Loading…
Cancel
Save