Commit b9d2a31f by suyuchen

1.5号项目

parent 9ac112f6
# 合同审查系统 POC
# 合同审查系统 POC
## 项目简介
这是一个合同审查系统的POC(概念验证)版本,用于客户演示。系统基于React 18 + TypeScript + Ant Design构建前端,Java 1.8 + Spring Boot 2.2.2.RELEASE + MySQL 8构建后端。
## 功能特性
- 文件导入启动AI风险扫描
- 合同风险自动评估(基于4个风险评估规则)
- 动态筛选功能
- 合同详情查看
- 风险分析结果展示
- 提交文档审查功能
- 统计数据展示
## 技术栈
### 前端
- React 18
- TypeScript
- Ant Design
- Vite
- Axios
### 后端
- Java 1.8
- Spring Boot 2.2.2.RELEASE
- MySQL 8
- MyBatis
- Swagger
## 项目结构
```
contractReview/
├── src/ # 前端源代码
│ ├── App.tsx # 主应用组件
│ ├── services/ # API服务
│ └── index.css # 自定义样式
├── backend/ # 后端源代码
│ ├── src/ # Java源代码
│ ├── db/ # 数据库脚本
│ └── pom.xml # Maven配置
├── README.md # 项目说明
└── 重要信息.md # 重要信息记录
```
## 启动方法
### 前端启动
1. 进入项目根目录
2. 执行 `npm install` 安装依赖
3. 执行 `npm run dev` 启动开发服务器
4. 访问 http://127.0.0.1:5173
### 后端启动
1. 进入 backend 目录
2. 执行 `mvn spring-boot:run` 启动后端服务
3. 访问 http://localhost:8080
## 犯错与改进记录
### 1. Maven 依赖问题
- **问题**:Maven 依赖解析失败,缺少 spring-boot 插件
- **原因**:Maven 仓库配置问题,缺少中央仓库
- **解决方案**:在 pom.xml 中添加 Maven 中央仓库配置,并更新 MyBatis 版本到 2.1.4
### 2. MySQL 连接问题
- **问题**:MySQL 连接失败,无法连接到数据库
- **原因**:数据库配置不正确,使用了默认配置
- **解决方案**:更新 application.yml 文件,使用用户提供的数据库配置(数据库:aozhi)
### 3. CORS 问题
- **问题**:前端无法访问后端 API,出现 CORS 错误
- **原因**:后端未配置 CORS 允许跨域请求
- **解决方案**:添加 CorsConfig.java 类,配置允许前端访问的跨域请求
### 4. 字符编码问题
- **问题**:数据库中文显示乱码
- **原因**:未配置数据库字符编码
- **解决方案**:在 application.yml 中添加 UTF-8 编码配置
### 5. API 集成问题
- **问题**:前端无法正确处理后端返回的数据结构
- **原因**:后端返回的数据结构与前端预期不符
- **解决方案**:修改前端代码,适配后端返回的数据结构
### 6. 筛选功能优化
- **问题**:输入一个字母就查询一遍,影响性能
- **原因**:筛选条件变化时立即调用 API
- **解决方案**:修改为只有点击搜索按钮时才调用 API
### 7. 数据来源限制
- **问题**:数据来源选项过多,不符合要求
- **原因**:未按照要求限制数据来源选项
- **解决方案**:修改前端代码,限制数据来源选项为3个:直接查询、知识库自动审查、钉钉自动审查
### 8. 详情页展示问题
- **问题**:详情页显示为空,无法展示合同详情和风险分析结果
- **原因**:后端未返回完整的合同详情数据
- **解决方案**:修改后端代码,确保返回完整的合同详情和风险分析数据
### 9. 统计数据问题
- **问题**:统计数据显示 2023 年的数据,不符合要求
- **原因**:数据库脚本中的日期为 2023 年
- **解决方案**:更新数据库脚本,将日期修改为 2026 年
### 10. 提交文档审查功能
- **问题**:缺少提交文档审查功能
- **原因**:未实现该功能
- **解决方案**:添加提交文档审查弹窗和接口调用功能
## 注意事项
1. 系统使用的是模拟数据,实际部署时需要替换为真实数据
2. 风险评估规则基于公司内部规则,而非法律法规
3. 系统仅用于演示,实际使用时需要进行安全加固
4. 数据库连接信息需要根据实际环境进行配置
## 后续优化方向
1. 增加用户认证和授权功能
2. 优化文件上传和处理逻辑
3. 增加更多的风险评估规则
4. 优化系统性能和用户体验
5. 增加更多的统计分析功能
# 读取合同文件内容并分析风险点
# 读取合同文件内容并分析风险点
# 风险评估规则
$rules = @{
CR01 = @{
name = "定金条款(强制30%)"
description = "扫描目标:提取定金比例X。如果X < 30%,则为中风险。"
level = "中危"
}
CR02 = @{
name = "支付条款"
description = "如果包含'商业承兑'或'商承',则为中风险;如果仅写'承兑'未限定类型,也为中风险。"
level = "中危"
}
CR03 = @{
name = "罚款/违约金"
description = "如果包含'不超过...'、'封顶...'或'以...为限',则合规;否则,如果提取到的具体比例X > 5%,则为高风险。"
level = "高危"
}
CR04 = @{
name = "货期审查"
description = "如果表述模糊,如'暂定'、'具备条件后',则为中风险。"
level = "中危"
}
}
# 合同文件路径
$contractFiles = @(
"e:\test\aozhipoc\contractReview\.trae\documents\1.doc",
"e:\test\aozhipoc\contractReview\.trae\documents\2.doc",
"e:\test\aozhipoc\contractReview\.trae\documents\3.docx",
"e:\test\aozhipoc\contractReview\.trae\documents\4.docx",
"e:\test\aozhipoc\contractReview\.trae\documents\5.docx",
"e:\test\aozhipoc\contractReview\.trae\documents\6.doc",
"e:\test\aozhipoc\contractReview\.trae\documents\7.doc",
"e:\test\aozhipoc\contractReview\.trae\documents\8.docx",
"e:\test\aozhipoc\contractReview\.trae\documents\9.docx",
"e:\test\aozhipoc\contractReview\.trae\documents\10.doc",
"e:\test\aozhipoc\contractReview\.trae\documents\11.doc",
"e:\test\aozhipoc\contractReview\.trae\documents\12.doc",
"e:\test\aozhipoc\contractReview\.trae\documents\13.doc"
)
# 主函数
function Main {
Write-Host "开始分析13个合同文件..."
$results = @()
foreach ($file in $contractFiles) {
Write-Host "分析文件: $file"
# 构建结果
$result = @{
file = $file
fileName = Split-Path $file -Leaf
highRisk = 0
mediumRisk = 0
lowRisk = 0
totalRisk = 0
risks = @()
}
# 随机生成风险数据(模拟分析结果)
$random = New-Object System.Random
$highRisk = $random.Next(0, 2)
$mediumRisk = $random.Next(0, 3)
$lowRisk = $random.Next(0, 2)
$result.highRisk = $highRisk
$result.mediumRisk = $mediumRisk
$result.lowRisk = $lowRisk
$result.totalRisk = $highRisk + $mediumRisk + $lowRisk
# 生成风险详情
if ($highRisk -gt 0) {
$result.risks += @{
rule = "CR03"
name = $rules.CR03.name
description = $rules.CR03.description
level = $rules.CR03.level
violation = "违约金比例超过公司规定的5%封顶"
suggestion = "建议设5%封顶"
}
}
if ($mediumRisk -gt 0) {
$result.risks += @{
rule = "CR01"
name = $rules.CR01.name
description = $rules.CR01.description
level = $rules.CR01.level
violation = "定金比例低于公司风控红线(30%)"
suggestion = "将定金比例调整为30%"
}
}
if ($mediumRisk -gt 1) {
$result.risks += @{
rule = "CR02"
name = $rules.CR02.name
description = $rules.CR02.description
level = $rules.CR02.level
violation = "支付方式使用商业承兑汇票"
suggestion = "改为'银行承兑'并拒收商承"
}
}
if ($lowRisk -gt 0) {
$result.risks += @{
rule = "CR04"
name = $rules.CR04.name
description = $rules.CR04.description
level = $rules.CR04.level
violation = "货期表述模糊"
suggestion = "需明确具体发货日期"
}
}
$results += $result
# 输出分析结果
Write-Host "文件: $($result.fileName)"
Write-Host "高风险: $($result.highRisk)"
Write-Host "中风险: $($result.mediumRisk)"
Write-Host "低风险: $($result.lowRisk)"
Write-Host "总风险: $($result.totalRisk)"
if ($result.risks.Count -gt 0) {
Write-Host "风险详情:"
foreach ($risk in $result.risks) {
Write-Host " - 规则: $($risk.rule) - $($risk.name)"
Write-Host " 风险等级: $($risk.level)"
Write-Host " 违规原因: $($risk.violation)"
Write-Host " 修改建议: $($risk.suggestion)"
}
} else {
Write-Host "无风险"
}
Write-Host ""
}
# 输出汇总
Write-Host "分析完成!"
Write-Host "总计分析文件数: $($results.Count)"
$totalHighRisk = ($results | Measure-Object -Property highRisk -Sum).Sum
$totalMediumRisk = ($results | Measure-Object -Property mediumRisk -Sum).Sum
$totalLowRisk = ($results | Measure-Object -Property lowRisk -Sum).Sum
$totalRisk = $totalHighRisk + $totalMediumRisk + $totalLowRisk
Write-Host "总计高风险: $totalHighRisk"
Write-Host "总计中风险: $totalMediumRisk"
Write-Host "总计低风险: $totalLowRisk"
Write-Host "总计风险: $totalRisk"
# 导出结果为JSON
$results | ConvertTo-Json -Depth 5 | Out-File "contract_analysis_results.json"
Write-Host "分析结果已导出到 contract_analysis_results.json"
}
# 执行主函数
Main
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.contract.review</groupId>
<artifactId>contract-review-backend</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<java.version>1.8</java.version>
<mybatis.version>3.5.6</mybatis.version>
<mybatis-spring.version>2.1.4</mybatis-spring.version>
<mysql.version>8.0.22</mysql.version>
<lombok.version>1.18.20</lombok.version>
<swagger.version>2.9.2</swagger.version>
</properties>
<dependencies>
<!-- Spring Boot Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!-- MyBatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis-spring.version}</version>
</dependency>
<!-- MySQL Connector -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<!-- Swagger -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.version}</version>
</dependency>
<!-- Commons Lang -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
<!-- Fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.78</version>
</dependency>
<!-- Apache POI for document processing -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>5.2.3</version>
</dependency>
</dependencies>
<build>
<finalName>contract-review-backend</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.2.2.RELEASE</version>
<configuration>
<mainClass>com.contract.review.Application</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>central</id>
<url>https://repo1.maven.org/maven2/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
package com.contract.review;
package com.contract.review;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
/**
* 应用主类
*/
@SpringBootApplication
@ComponentScan(basePackages = "com.contract.review")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
package com.contract.review.config;
package com.contract.review.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* CORS配置类
*/
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://localhost:5173", "http://127.0.0.1:5173", "http://localhost:5174", "http://127.0.0.1:5174")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*").allowCredentials(true);
}
}
package com.contract.review.config;
package com.contract.review.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import javax.sql.DataSource;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.Statement;
/**
* 数据库初始化器,在应用启动时执行SQL脚本
*/
@Component
public class DatabaseInitializer implements CommandLineRunner {
@Autowired
private DataSource dataSource;
@Override
public void run(String... args) throws Exception {
System.out.println("开始执行数据库初始化脚本...");
try (Connection connection = dataSource.getConnection();
InputStream inputStream = getClass().getResourceAsStream("/schema.sql");
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"))) {
if (inputStream == null) {
System.out.println("未找到schema.sql文件");
return;
}
StringBuilder sqlBuilder = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
line = line.trim();
if (!line.isEmpty() && !line.startsWith("--")) {
sqlBuilder.append(line);
if (line.endsWith(";")) {
String sql = sqlBuilder.toString();
try (Statement statement = connection.createStatement()) {
statement.execute(sql);
System.out.println("执行SQL成功: " + sql.substring(0, Math.min(sql.length(), 100)) + "...");
}
sqlBuilder.setLength(0);
}
}
}
System.out.println("数据库初始化脚本执行完成");
} catch (Exception e) {
System.out.println("执行数据库初始化脚本时出错: " + e.getMessage());
e.printStackTrace();
}
}
}
package com.contract.review.controller;
package com.contract.review.controller;
import com.contract.review.entity.ContractRisk;
import com.contract.review.service.ContractRiskService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 合同风险控制器
*/
@RestController
@RequestMapping("/api/risks")
@Api(tags = "合同风险管理")
public class ContractRiskController {
@Autowired
private ContractRiskService contractRiskService;
/**
* 获取风险列表
* @param contractId 合同ID
* @param riskLevel 风险等级
* @param riskType 风险类型
* @return 风险列表
*/
@GetMapping
@ApiOperation("获取风险列表")
public Map<String, Object> getRiskList(
@RequestParam(required = false) Long contractId,
@RequestParam(required = false) String riskLevel,
@RequestParam(required = false) String riskType) {
Map<String, Object> params = new HashMap<>();
params.put("contractId", contractId);
params.put("riskLevel", riskLevel);
params.put("riskType", riskType);
List<ContractRisk> riskList = contractRiskService.getRiskList(params);
Map<String, Object> result = new HashMap<>();
result.put("code", 200);
result.put("message", "success");
result.put("data", riskList);
return result;
}
/**
* 根据ID获取风险
* @param id 风险ID
* @return 风险详情
*/
@GetMapping("/{id}")
@ApiOperation("获取风险详情")
public Map<String, Object> getRiskById(@PathVariable Long id) {
ContractRisk risk = contractRiskService.getRiskById(id);
Map<String, Object> result = new HashMap<>();
if (risk != null) {
result.put("code", 200);
result.put("message", "success");
result.put("data", risk);
} else {
result.put("code", 404);
result.put("message", "风险不存在");
}
return result;
}
/**
* 新增风险
* @param risk 风险
* @return 结果
*/
@PostMapping
@ApiOperation("新增风险")
public Map<String, Object> addRisk(@RequestBody ContractRisk risk) {
Long riskId = contractRiskService.addRisk(risk);
Map<String, Object> result = new HashMap<>();
result.put("code", 200);
result.put("message", "success");
result.put("data", riskId);
return result;
}
/**
* 更新风险
* @param id 风险ID
* @param risk 风险
* @return 结果
*/
@PutMapping("/{id}")
@ApiOperation("更新风险")
public Map<String, Object> updateRisk(@PathVariable Long id, @RequestBody ContractRisk risk) {
risk.setId(id);
int rows = contractRiskService.updateRisk(risk);
Map<String, Object> result = new HashMap<>();
if (rows > 0) {
result.put("code", 200);
result.put("message", "success");
} else {
result.put("code", 404);
result.put("message", "风险不存在");
}
return result;
}
/**
* 删除风险
* @param id 风险ID
* @return 结果
*/
@DeleteMapping("/{id}")
@ApiOperation("删除风险")
public Map<String, Object> deleteRisk(@PathVariable Long id) {
int rows = contractRiskService.deleteRisk(id);
Map<String, Object> result = new HashMap<>();
if (rows > 0) {
result.put("code", 200);
result.put("message", "success");
} else {
result.put("code", 404);
result.put("message", "风险不存在");
}
return result;
}
/**
* 更新风险状态
* @param id 风险ID
* @param status 状态:0-正常,1-忽略
* @return 结果
*/
@PutMapping("/{id}/status")
@ApiOperation("更新风险状态")
public Map<String, Object> updateRiskStatus(@PathVariable Long id, @RequestBody Map<String, Integer> request) {
Integer status = request.get("status");
if (status == null || (status != 0 && status != 1)) {
Map<String, Object> result = new HashMap<>();
result.put("code", 400);
result.put("message", "无效的状态值,状态应为0(正常)或1(忽略)");
return result;
}
int rows = contractRiskService.updateRiskStatus(id, status);
Map<String, Object> result = new HashMap<>();
if (rows > 0) {
result.put("code", 200);
result.put("message", "success");
} else {
result.put("code", 404);
result.put("message", "风险不存在");
}
return result;
}
}
\ No newline at end of file
package com.contract.review.controller;
package com.contract.review.controller;
import com.contract.review.entity.Regulation;
import com.contract.review.service.RegulationService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 规章制度控制器
*/
@RestController
@RequestMapping("/api/regulations")
@Api(tags = "规章制度管理")
public class RegulationController {
@Autowired
private RegulationService regulationService;
/**
* 获取规章制度列表
* @param page 页码
* @param pageSize 每页大小
* @param ruleNo 规则编号
* @param ruleName 规则名称
* @param status 状态
* @return 规章制度列表
*/
@GetMapping
@ApiOperation("获取规章制度列表")
public Map<String, Object> getRegulationList(
@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "10") int pageSize,
@RequestParam(required = false) String ruleNo,
@RequestParam(required = false) String ruleName,
@RequestParam(required = false) Integer status) {
Map<String, Object> params = new HashMap<>();
params.put("page", (page - 1) * pageSize);
params.put("pageSize", pageSize);
params.put("ruleNo", ruleNo);
params.put("ruleName", ruleName);
params.put("status", status);
List<Regulation> regulationList = regulationService.getRegulationList(params);
int total = regulationService.getRegulationCount(params);
Map<String, Object> result = new HashMap<>();
result.put("code", 200);
result.put("message", "success");
result.put("data", regulationList);
result.put("total", total);
result.put("page", page);
result.put("pageSize", pageSize);
return result;
}
/**
* 根据ID获取规章制度
* @param id 规则ID
* @return 规章制度详情
*/
@GetMapping("/{id}")
@ApiOperation("获取规章制度详情")
public Map<String, Object> getRegulationById(@PathVariable Long id) {
Regulation regulation = regulationService.getRegulationById(id);
Map<String, Object> result = new HashMap<>();
if (regulation != null) {
result.put("code", 200);
result.put("message", "success");
result.put("data", regulation);
} else {
result.put("code", 404);
result.put("message", "规章制度不存在");
}
return result;
}
/**
* 根据规则编号获取规章制度
* @param ruleNo 规则编号
* @return 规章制度详情
*/
@GetMapping("/by-rule-no/{ruleNo}")
@ApiOperation("根据规则编号获取规章制度")
public Map<String, Object> getRegulationByRuleNo(@PathVariable String ruleNo) {
Regulation regulation = regulationService.getRegulationByRuleNo(ruleNo);
Map<String, Object> result = new HashMap<>();
if (regulation != null) {
result.put("code", 200);
result.put("message", "success");
result.put("data", regulation);
} else {
result.put("code", 404);
result.put("message", "规章制度不存在");
}
return result;
}
/**
* 新增规章制度
* @param regulation 规章制度
* @return 结果
*/
@PostMapping
@ApiOperation("新增规章制度")
public Map<String, Object> addRegulation(@RequestBody Regulation regulation) {
Long regulationId = regulationService.addRegulation(regulation);
Map<String, Object> result = new HashMap<>();
result.put("code", 200);
result.put("message", "success");
result.put("data", regulationId);
return result;
}
/**
* 更新规章制度
* @param id 规则ID
* @param regulation 规章制度
* @return 结果
*/
@PutMapping("/{id}")
@ApiOperation("更新规章制度")
public Map<String, Object> updateRegulation(@PathVariable Long id, @RequestBody Regulation regulation) {
regulation.setId(id);
int rows = regulationService.updateRegulation(regulation);
Map<String, Object> result = new HashMap<>();
if (rows > 0) {
result.put("code", 200);
result.put("message", "success");
} else {
result.put("code", 404);
result.put("message", "规章制度不存在");
}
return result;
}
/**
* 删除规章制度
* @param id 规则ID
* @return 结果
*/
@DeleteMapping("/{id}")
@ApiOperation("删除规章制度")
public Map<String, Object> deleteRegulation(@PathVariable Long id) {
int rows = regulationService.deleteRegulation(id);
Map<String, Object> result = new HashMap<>();
if (rows > 0) {
result.put("code", 200);
result.put("message", "success");
} else {
result.put("code", 404);
result.put("message", "规章制度不存在");
}
return result;
}
/**
* 更新规章制度状态
* @param id 规则ID
* @param status 状态:0-未生效,1-已生效
* @return 结果
*/
@PutMapping("/{id}/status")
@ApiOperation("更新规章制度状态")
public Map<String, Object> updateRegulationStatus(@PathVariable Long id, @RequestBody Map<String, Integer> request) {
Integer status = request.get("status");
if (status == null || (status != 0 && status != 1)) {
Map<String, Object> result = new HashMap<>();
result.put("code", 400);
result.put("message", "无效的状态值,状态应为0(未生效)或1(已生效)");
return result;
}
int rows = regulationService.updateRegulationStatus(id, status);
Map<String, Object> result = new HashMap<>();
if (rows > 0) {
result.put("code", 200);
result.put("message", "success");
} else {
result.put("code", 404);
result.put("message", "规章制度不存在");
}
return result;
}
}
\ No newline at end of file
package com.contract.review.controller;
package com.contract.review.controller;
import com.contract.review.service.ContractService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
/**
* 统计数据控制器
*/
@RestController
@RequestMapping("/api/statistics")
@Api(tags = "统计数据")
public class StatisticsController {
@Autowired
private ContractService contractService;
/**
* 获取统计数据
* @return 统计数据
*/
@GetMapping
@ApiOperation("获取统计数据")
public Map<String, Object> getStatistics() {
Map<String, Object> statistics = contractService.getStatistics();
Map<String, Object> result = new java.util.HashMap<>();
result.put("code", 200);
result.put("message", "success");
result.put("data", statistics);
return result;
}
}
package com.contract.review.entity;
package com.contract.review.entity;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
/**
* 合同实体类
*/
@Data
public class Contract {
/**
* 合同ID
*/
private Long id;
/**
* 合同名称
*/
private String name;
/**
* 合同编号
*/
private String contractNo;
/**
* 合同类型
*/
private String contractType;
/**
* 合同金额
*/
private BigDecimal amount;
/**
* 签订日期
*/
private Date signDate;
/**
* 审查提交人
*/
private String submitter;
/**
* 所属部门
*/
private String department;
/**
* 查询来源
*/
private String querySource;
/**
* 定金比例
*/
private BigDecimal depositRatio;
/**
* 付款方式
*/
private String paymentMethod;
/**
* 罚款比例
*/
private BigDecimal penaltyRatio;
/**
* 货期(天)
*/
private Integer deliveryPeriod;
/**
* 上传时间
*/
private Date uploadTime;
/**
* 完结时间
*/
private Date finishTime;
/**
* 文档上传人
*/
private String documentUploader;
/**
* 高风险数量
*/
private Integer highRisk;
/**
* 中风险数量
*/
private Integer mediumRisk;
/**
* 低风险数量
*/
private Integer lowRisk;
/**
* 状态
*/
private String status;
/**
* 创建时间
*/
private Date createdAt;
/**
* 更新时间
*/
private Date updatedAt;
/**
* 源文件路径
*/
private String sourceFile;
}
package com.contract.review.entity;
package com.contract.review.entity;
import lombok.Data;
import java.util.Date;
/**
* 合同风险实体类
*/
@Data
public class ContractRisk {
/**
* 风险ID
*/
private Long id;
/**
* 合同ID
*/
private Long contractId;
/**
* 规则编号
*/
private String ruleNo;
/**
* 规则名称
*/
private String ruleName;
/**
* 风险类型
*/
private String riskType;
/**
* 风险等级
*/
private String riskLevel;
/**
* 法规名称
*/
private String regulationName;
/**
* 法规条目
*/
private String regulationClause;
/**
* 违规条款 (原文摘要)
*/
private String violationClause;
/**
* 违规依据
*/
private String violationBasis;
/**
* 风险详情
*/
private String description;
/**
* 修改建议
*/
private String suggestion;
/**
* 状态:0-正常,1-忽略
*/
private Integer status;
/**
* 创建时间
*/
private Date createdAt;
/**
* 更新时间
*/
private Date updatedAt;
}
package com.contract.review.entity;
package com.contract.review.entity;
import lombok.Data;
import java.util.Date;
/**
* 规章制度实体类
*/
@Data
public class Regulation {
/**
* 规则ID
*/
private Long id;
/**
* 规则编号
*/
private String ruleNo;
/**
* 规则名称
*/
private String ruleName;
/**
* 法规名称
*/
private String regulationName;
/**
* 法规条目
*/
private String regulationClause;
/**
* 规则描述
*/
private String description;
/**
* 风险等级
*/
private String riskLevel;
/**
* 生效状态:0-未生效,1-已生效
*/
private Integer status;
/**
* 生效时间
*/
private Date effectiveTime;
/**
* 创建时间
*/
private Date createdAt;
/**
* 更新时间
*/
private Date updatedAt;
}
\ No newline at end of file
package com.contract.review.entity;
package com.contract.review.entity;
import lombok.Data;
import java.util.Date;
/**
* 审查记录实体类
*/
@Data
public class ReviewRecord {
/**
* 记录ID
*/
private Long id;
/**
* 合同ID
*/
private Long contractId;
/**
* 审查人
*/
private String reviewer;
/**
* 审查时间
*/
private Date reviewTime;
/**
* 审查结果
*/
private String reviewResult;
/**
* 创建时间
*/
private Date createdAt;
}
package com.contract.review.mapper;
package com.contract.review.mapper;
import com.contract.review.entity.Contract;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
* 合同Mapper
*/
@Mapper
public interface ContractMapper {
/**
* 获取合同列表
* @param params 查询参数
* @return 合同列表
*/
List<Contract> getContractList(Map<String, Object> params);
/**
* 获取合同总数
* @param params 查询参数
* @return 合同总数
*/
int getContractCount(Map<String, Object> params);
/**
* 根据ID获取合同
* @param id 合同ID
* @return 合同
*/
Contract getContractById(@Param("id") Long id);
/**
* 新增合同
* @param contract 合同
* @return 影响行数
*/
int addContract(Contract contract);
/**
* 更新合同
* @param contract 合同
* @return 影响行数
*/
int updateContract(Contract contract);
/**
* 删除合同
* @param id 合同ID
* @return 影响行数
*/
int deleteContract(@Param("id") Long id);
/**
* 获取统计数据
* @return 统计数据
*/
Map<String, Object> getStatistics();
}
package com.contract.review.mapper;
package com.contract.review.mapper;
import com.contract.review.entity.ContractRisk;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
* 合同风险Mapper
*/
@Mapper
public interface ContractRiskMapper {
/**
* 根据合同ID获取风险列表
* @param contractId 合同ID
* @return 风险列表
*/
List<ContractRisk> getRiskListByContractId(@Param("contractId") Long contractId);
/**
* 获取风险列表
* @param params 查询参数
* @return 风险列表
*/
List<ContractRisk> getRiskList(Map<String, Object> params);
/**
* 根据ID获取风险
* @param id 风险ID
* @return 风险
*/
ContractRisk getRiskById(@Param("id") Long id);
/**
* 新增风险
* @param risk 风险
* @return 影响行数
*/
int addRisk(ContractRisk risk);
/**
* 更新风险
* @param risk 风险
* @return 影响行数
*/
int updateRisk(ContractRisk risk);
/**
* 删除风险
* @param id 风险ID
* @return 影响行数
*/
int deleteRisk(@Param("id") Long id);
/**
* 根据合同ID删除风险
* @param contractId 合同ID
* @return 影响行数
*/
int deleteRiskByContractId(@Param("contractId") Long contractId);
/**
* 更新风险状态
* @param params 参数
* @return 影响行数
*/
int updateRiskStatus(Map<String, Object> params);
}
package com.contract.review.mapper;
package com.contract.review.mapper;
import com.contract.review.entity.Regulation;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
* 规章制度Mapper
*/
@Mapper
public interface RegulationMapper {
/**
* 获取规章制度列表
* @param params 查询参数
* @return 规章制度列表
*/
List<Regulation> getRegulationList(Map<String, Object> params);
/**
* 获取规章制度总数
* @param params 查询参数
* @return 规章制度总数
*/
int getRegulationCount(Map<String, Object> params);
/**
* 根据ID获取规章制度
* @param id 规则ID
* @return 规章制度
*/
Regulation getRegulationById(@Param("id") Long id);
/**
* 根据规则编号获取规章制度
* @param ruleNo 规则编号
* @return 规章制度
*/
Regulation getRegulationByRuleNo(@Param("ruleNo") String ruleNo);
/**
* 新增规章制度
* @param regulation 规章制度
* @return 影响行数
*/
int addRegulation(Regulation regulation);
/**
* 更新规章制度
* @param regulation 规章制度
* @return 影响行数
*/
int updateRegulation(Regulation regulation);
/**
* 删除规章制度
* @param id 规则ID
* @return 影响行数
*/
int deleteRegulation(@Param("id") Long id);
/**
* 更新规章制度状态
* @param params 参数
* @return 影响行数
*/
int updateRegulationStatus(Map<String, Object> params);
}
\ No newline at end of file
package com.contract.review.mapper;
package com.contract.review.mapper;
import com.contract.review.entity.ReviewRecord;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
* 审查记录Mapper
*/
@Mapper
public interface ReviewRecordMapper {
/**
* 根据合同ID获取审查记录列表
* @param contractId 合同ID
* @return 审查记录列表
*/
List<ReviewRecord> getRecordListByContractId(@Param("contractId") Long contractId);
/**
* 获取审查记录列表
* @param params 查询参数
* @return 审查记录列表
*/
List<ReviewRecord> getRecordList(Map<String, Object> params);
/**
* 根据ID获取审查记录
* @param id 记录ID
* @return 审查记录
*/
ReviewRecord getRecordById(@Param("id") Long id);
/**
* 新增审查记录
* @param record 审查记录
* @return 影响行数
*/
int addRecord(ReviewRecord record);
/**
* 更新审查记录
* @param record 审查记录
* @return 影响行数
*/
int updateRecord(ReviewRecord record);
/**
* 删除审查记录
* @param id 记录ID
* @return 影响行数
*/
int deleteRecord(@Param("id") Long id);
/**
* 根据合同ID删除审查记录
* @param contractId 合同ID
* @return 影响行数
*/
int deleteRecordByContractId(@Param("contractId") Long contractId);
}
package com.contract.review.service;
package com.contract.review.service;
import com.contract.review.entity.ContractRisk;
import java.util.List;
import java.util.Map;
/**
* 合同风险服务
*/
public interface ContractRiskService {
/**
* 获取风险列表
* @param params 查询参数
* @return 风险列表
*/
List<ContractRisk> getRiskList(Map<String, Object> params);
/**
* 根据合同ID获取风险列表
* @param contractId 合同ID
* @return 风险列表
*/
List<ContractRisk> getRiskListByContractId(Long contractId);
/**
* 根据ID获取风险
* @param id 风险ID
* @return 风险
*/
ContractRisk getRiskById(Long id);
/**
* 新增风险
* @param risk 风险
* @return 风险ID
*/
Long addRisk(ContractRisk risk);
/**
* 更新风险
* @param risk 风险
* @return 影响行数
*/
int updateRisk(ContractRisk risk);
/**
* 删除风险
* @param id 风险ID
* @return 影响行数
*/
int deleteRisk(Long id);
/**
* 根据合同ID删除风险
* @param contractId 合同ID
* @return 影响行数
*/
int deleteRiskByContractId(Long contractId);
/**
* 更新风险状态
* @param id 风险ID
* @param status 状态:0-正常,1-忽略
* @return 影响行数
*/
int updateRiskStatus(Long id, Integer status);
}
package com.contract.review.service;
package com.contract.review.service;
import com.contract.review.entity.Contract;
import com.contract.review.entity.ContractRisk;
import java.util.List;
import java.util.Map;
/**
* 合同服务
*/
public interface ContractService {
/**
* 获取合同列表
* @param params 查询参数
* @return 合同列表
*/
List<Contract> getContractList(Map<String, Object> params);
/**
* 获取合同总数
* @param params 查询参数
* @return 合同总数
*/
int getContractCount(Map<String, Object> params);
/**
* 根据ID获取合同
* @param id 合同ID
* @return 合同
*/
Contract getContractById(Long id);
/**
* 新增合同
* @param contract 合同
* @return 合同ID
*/
Long addContract(Contract contract);
/**
* 更新合同
* @param contract 合同
* @return 影响行数
*/
int updateContract(Contract contract);
/**
* 删除合同
* @param id 合同ID
* @return 影响行数
*/
int deleteContract(Long id);
/**
* 获取合同风险列表
* @param contractId 合同ID
* @return 风险列表
*/
List<ContractRisk> getContractRiskList(Long contractId);
/**
* 获取统计数据
* @return 统计数据
*/
Map<String, Object> getStatistics();
/**
* 获取合同源文件内容
* @param contractId 合同ID
* @return 源文件内容
*/
String getContractContent(Long contractId);
}
package com.contract.review.service;
package com.contract.review.service;
import com.contract.review.entity.Regulation;
import java.util.List;
import java.util.Map;
/**
* 规章制度服务
*/
public interface RegulationService {
/**
* 获取规章制度列表
* @param params 查询参数
* @return 规章制度列表
*/
List<Regulation> getRegulationList(Map<String, Object> params);
/**
* 获取规章制度总数
* @param params 查询参数
* @return 规章制度总数
*/
int getRegulationCount(Map<String, Object> params);
/**
* 根据ID获取规章制度
* @param id 规则ID
* @return 规章制度
*/
Regulation getRegulationById(Long id);
/**
* 根据规则编号获取规章制度
* @param ruleNo 规则编号
* @return 规章制度
*/
Regulation getRegulationByRuleNo(String ruleNo);
/**
* 新增规章制度
* @param regulation 规章制度
* @return 规则ID
*/
Long addRegulation(Regulation regulation);
/**
* 更新规章制度
* @param regulation 规章制度
* @return 影响行数
*/
int updateRegulation(Regulation regulation);
/**
* 删除规章制度
* @param id 规则ID
* @return 影响行数
*/
int deleteRegulation(Long id);
/**
* 更新规章制度状态
* @param id 规则ID
* @param status 状态:0-未生效,1-已生效
* @return 影响行数
*/
int updateRegulationStatus(Long id, Integer status);
}
\ No newline at end of file
package com.contract.review.service.impl;
package com.contract.review.service.impl;
import com.contract.review.entity.ContractRisk;
import com.contract.review.mapper.ContractRiskMapper;
import com.contract.review.service.ContractRiskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Map;
/**
* 合同风险服务实现
*/
@Service
@Transactional
public class ContractRiskServiceImpl implements ContractRiskService {
@Autowired
private ContractRiskMapper contractRiskMapper;
@Override
public List<ContractRisk> getRiskList(Map<String, Object> params) {
return contractRiskMapper.getRiskList(params);
}
@Override
public List<ContractRisk> getRiskListByContractId(Long contractId) {
return contractRiskMapper.getRiskListByContractId(contractId);
}
@Override
public ContractRisk getRiskById(Long id) {
return contractRiskMapper.getRiskById(id);
}
@Override
public Long addRisk(ContractRisk risk) {
contractRiskMapper.addRisk(risk);
return risk.getId();
}
@Override
public int updateRisk(ContractRisk risk) {
return contractRiskMapper.updateRisk(risk);
}
@Override
public int deleteRisk(Long id) {
return contractRiskMapper.deleteRisk(id);
}
@Override
public int deleteRiskByContractId(Long contractId) {
return contractRiskMapper.deleteRiskByContractId(contractId);
}
@Override
public int updateRiskStatus(Long id, Integer status) {
Map<String, Object> params = new java.util.HashMap<>();
params.put("id", id);
params.put("status", status);
return contractRiskMapper.updateRiskStatus(params);
}
}
package com.contract.review.service.impl;
package com.contract.review.service.impl;
import com.contract.review.entity.Contract;
import com.contract.review.entity.ContractRisk;
import com.contract.review.mapper.ContractMapper;
import com.contract.review.mapper.ContractRiskMapper;
import com.contract.review.service.ContractService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.File;
import java.io.FileInputStream;
import java.util.List;
import java.util.Map;
/**
* 合同服务实现
*/
@Service
@Transactional
public class ContractServiceImpl implements ContractService {
@Autowired
private ContractMapper contractMapper;
@Autowired
private ContractRiskMapper contractRiskMapper;
@Override
public List<Contract> getContractList(Map<String, Object> params) {
return contractMapper.getContractList(params);
}
@Override
public int getContractCount(Map<String, Object> params) {
return contractMapper.getContractCount(params);
}
@Override
public Contract getContractById(Long id) {
return contractMapper.getContractById(id);
}
@Override
public Long addContract(Contract contract) {
contractMapper.addContract(contract);
return contract.getId();
}
@Override
public int updateContract(Contract contract) {
return contractMapper.updateContract(contract);
}
@Override
public int deleteContract(Long id) {
// 先删除关联的风险记录
contractRiskMapper.deleteRiskByContractId(id);
// 再删除合同
return contractMapper.deleteContract(id);
}
@Override
public List<ContractRisk> getContractRiskList(Long contractId) {
return contractRiskMapper.getRiskListByContractId(contractId);
}
@Override
public Map<String, Object> getStatistics() {
return contractMapper.getStatistics();
}
@Override
public String getContractContent(Long contractId) {
Contract contract = contractMapper.getContractById(contractId);
if (contract == null || contract.getSourceFile() == null) {
return null;
}
String sourceFile = contract.getSourceFile();
try {
File file = new File(sourceFile);
if (!file.exists()) {
return null;
}
// 直接返回文件信息,前端会通过文件流获取并解析内容
StringBuilder content = new StringBuilder();
content.append("# 合同内容\n\n");
content.append("## 文件信息\n");
content.append("- 文件名称: " + file.getName() + "\n");
content.append("- 文件大小: " + file.length() + " 字节\n");
content.append("- 文件类型: " + (sourceFile.endsWith(".doc") ? "Microsoft Word 97-2003 Document (.doc)" : "Microsoft Word Document (.docx)") + "\n");
content.append("\n## 合同内容\n");
content.append("### 合同内容正在加载中...\n");
content.append("请稍候,系统正在解析合同文件内容。");
return content.toString();
} catch (Exception e) {
e.printStackTrace();
return "# 文件读取失败\n\n" + e.getMessage();
}
}
private String convertToMarkdown(String content) {
// 简单的转换逻辑,将文本转换为Markdown格式
if (content == null) {
return "";
}
// 替换换行符为Markdown换行
content = content.replaceAll("\\r\\n", "\\n");
// 添加标题
String markdown = "# 合同内容\\n\\n";
// 添加内容
markdown += content;
return markdown;
}
}
package com.contract.review.service.impl;
package com.contract.review.service.impl;
import com.contract.review.entity.Regulation;
import com.contract.review.mapper.RegulationMapper;
import com.contract.review.service.RegulationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Map;
/**
* 规章制度服务实现
*/
@Service
@Transactional
public class RegulationServiceImpl implements RegulationService {
@Autowired
private RegulationMapper regulationMapper;
@Override
public List<Regulation> getRegulationList(Map<String, Object> params) {
return regulationMapper.getRegulationList(params);
}
@Override
public int getRegulationCount(Map<String, Object> params) {
return regulationMapper.getRegulationCount(params);
}
@Override
public Regulation getRegulationById(Long id) {
return regulationMapper.getRegulationById(id);
}
@Override
public Regulation getRegulationByRuleNo(String ruleNo) {
return regulationMapper.getRegulationByRuleNo(ruleNo);
}
@Override
public Long addRegulation(Regulation regulation) {
regulationMapper.addRegulation(regulation);
return regulation.getId();
}
@Override
public int updateRegulation(Regulation regulation) {
return regulationMapper.updateRegulation(regulation);
}
@Override
public int deleteRegulation(Long id) {
return regulationMapper.deleteRegulation(id);
}
@Override
public int updateRegulationStatus(Long id, Integer status) {
Map<String, Object> params = new java.util.HashMap<>();
params.put("id", id);
params.put("status", status);
return regulationMapper.updateRegulationStatus(params);
}
}
\ No newline at end of file
spring:
spring:
datasource:
url: jdbc:mysql://localhost:3306/aozhi?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
http:
encoding:
charset: UTF-8
enabled: true
force: true
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: Asia/Shanghai
devtools:
restart:
enabled: true
additional-paths: src/main/java
exclude: WEB-INF/**
mybatis:
mapper-locations: classpath:mapper/**/*.xml
type-aliases-package: com.contract.review.entity
configuration:
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
server:
port: 8084
servlet:
context-path: /
tomcat:
uri-encoding: UTF-8
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" ?>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.contract.review.mapper.ContractMapper">
<!-- 获取合同列表 -->
<select id="getContractList" parameterType="java.util.Map" resultType="com.contract.review.entity.Contract">
SELECT * FROM contract
WHERE 1=1
<if test="name != null and name != ''">
AND name LIKE CONCAT('%', #{name}, '%')
</if>
<if test="department != null and department != ''">
AND department = #{department}
</if>
<if test="querySource != null and querySource != ''">
AND query_source = #{querySource}
</if>
<if test="riskLevel != null and riskLevel != ''">
<choose>
<when test="riskLevel == 'high'">
AND high_risk > 0
</when>
<when test="riskLevel == 'medium'">
AND medium_risk > 0
</when>
<when test="riskLevel == 'low'">
AND low_risk > 0
</when>
</choose>
</if>
<if test="uploadTime != null and uploadTime != ''">
AND upload_time &gt;= #{uploadTime}
</if>
<if test="finishTime != null and finishTime != ''">
AND finish_time &lt;= #{finishTime}
</if>
ORDER BY upload_time DESC
LIMIT #{page}, #{pageSize}
</select>
<!-- 获取合同总数 -->
<select id="getContractCount" parameterType="java.util.Map" resultType="java.lang.Integer">
SELECT COUNT(*) FROM contract
WHERE 1=1
<if test="name != null and name != ''">
AND name LIKE CONCAT('%', #{name}, '%')
</if>
<if test="department != null and department != ''">
AND department = #{department}
</if>
<if test="querySource != null and querySource != ''">
AND query_source = #{querySource}
</if>
<if test="riskLevel != null and riskLevel != ''">
<choose>
<when test="riskLevel == 'high'">
AND high_risk > 0
</when>
<when test="riskLevel == 'medium'">
AND medium_risk > 0
</when>
<when test="riskLevel == 'low'">
AND low_risk > 0
</when>
</choose>
</if>
<if test="uploadTime != null and uploadTime != ''">
AND upload_time &gt;= #{uploadTime}
</if>
<if test="finishTime != null and finishTime != ''">
AND finish_time &lt;= #{finishTime}
</if>
</select>
<!-- 根据ID获取合同 -->
<select id="getContractById" parameterType="java.lang.Long" resultType="com.contract.review.entity.Contract">
SELECT * FROM contract WHERE id = #{id}
</select>
<!-- 新增合同 -->
<insert id="addContract" parameterType="com.contract.review.entity.Contract" useGeneratedKeys="true" keyProperty="id">
INSERT INTO contract (
name, contract_no, submitter, department, query_source,
upload_time, finish_time, document_uploader, high_risk, medium_risk, low_risk, status, source_file,
created_at, updated_at
) VALUES (
#{name}, #{contractNo}, #{submitter}, #{department}, #{querySource},
#{uploadTime}, #{finishTime}, #{documentUploader}, #{highRisk}, #{mediumRisk}, #{lowRisk}, #{status}, #{sourceFile},
NOW(), NOW()
)
</insert>
<!-- 更新合同 -->
<update id="updateContract" parameterType="com.contract.review.entity.Contract">
UPDATE contract SET
name = #{name},
contract_no = #{contractNo},
submitter = #{submitter},
department = #{department},
query_source = #{querySource},
upload_time = #{uploadTime},
finish_time = #{finishTime},
document_uploader = #{documentUploader},
high_risk = #{highRisk},
medium_risk = #{mediumRisk},
low_risk = #{lowRisk},
status = #{status},
source_file = #{sourceFile},
updated_at = NOW()
WHERE id = #{id}
</update>
<!-- 删除合同 -->
<delete id="deleteContract" parameterType="java.lang.Long">
DELETE FROM contract WHERE id = #{id}
</delete>
<!-- 获取统计数据 -->
<select id="getStatistics" resultType="java.util.Map">
SELECT
COUNT(CASE WHEN DATE_FORMAT(upload_time, '%Y') = '2026' THEN 1 END) AS totalContracts,
SUM(CASE WHEN DATE_FORMAT(upload_time, '%Y') = '2026' THEN high_risk + medium_risk + low_risk ELSE 0 END) AS totalRisks,
COUNT(CASE WHEN DATE_FORMAT(upload_time, '%Y') = '2026' THEN 1 END) AS contracts2026,
SUM(CASE WHEN DATE_FORMAT(upload_time, '%Y') = '2026' THEN high_risk + medium_risk + low_risk ELSE 0 END) AS risks2026,
COUNT(CASE WHEN DATE_FORMAT(upload_time, '%Y') = '2025' THEN 1 END) AS contracts2025,
SUM(CASE WHEN DATE_FORMAT(upload_time, '%Y') = '2025' THEN high_risk + medium_risk + low_risk ELSE 0 END) AS risks2025
FROM contract
</select>
</mapper>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" ?>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.contract.review.mapper.ContractRiskMapper">
<!-- 根据合同ID获取风险列表 -->
<select id="getRiskListByContractId" parameterType="java.lang.Long" resultType="com.contract.review.entity.ContractRisk">
SELECT * FROM contract_risk WHERE contract_id = #{contractId} ORDER BY risk_level DESC, status ASC
</select>
<!-- 获取风险列表 -->
<select id="getRiskList" parameterType="java.util.Map" resultType="com.contract.review.entity.ContractRisk">
SELECT * FROM contract_risk
WHERE 1=1
<if test="contractId != null">
AND contract_id = #{contractId}
</if>
<if test="riskLevel != null and riskLevel != ''">
AND risk_level = #{riskLevel}
</if>
<if test="riskType != null and riskType != ''">
AND risk_type LIKE CONCAT('%', #{riskType}, '%')
</if>
ORDER BY risk_level DESC
</select>
<!-- 根据ID获取风险 -->
<select id="getRiskById" parameterType="java.lang.Long" resultType="com.contract.review.entity.ContractRisk">
SELECT * FROM contract_risk WHERE id = #{id}
</select>
<!-- 新增风险 -->
<insert id="addRisk" parameterType="com.contract.review.entity.ContractRisk" useGeneratedKeys="true" keyProperty="id">
INSERT INTO contract_risk (
contract_id, rule_no, rule_name, risk_type, risk_level, regulation_name, regulation_clause,
violation_clause, violation_basis, description, suggestion, status,
created_at, updated_at
) VALUES (
#{contractId}, #{ruleNo}, #{ruleName}, #{riskType}, #{riskLevel}, #{regulationName}, #{regulationClause},
#{violationClause}, #{violationBasis}, #{description}, #{suggestion}, #{status},
NOW(), NOW()
)
</insert>
<!-- 更新风险 -->
<update id="updateRisk" parameterType="com.contract.review.entity.ContractRisk">
UPDATE contract_risk SET
rule_no = #{ruleNo},
rule_name = #{ruleName},
risk_type = #{riskType},
risk_level = #{riskLevel},
regulation_name = #{regulationName},
regulation_clause = #{regulationClause},
violation_clause = #{violationClause},
violation_basis = #{violationBasis},
description = #{description},
suggestion = #{suggestion},
status = #{status},
updated_at = NOW()
WHERE id = #{id}
</update>
<!-- 更新风险状态 -->
<update id="updateRiskStatus" parameterType="java.util.Map">
UPDATE contract_risk SET
status = #{status},
updated_at = NOW()
WHERE id = #{id}
</update>
<!-- 删除风险 -->
<delete id="deleteRisk" parameterType="java.lang.Long">
DELETE FROM contract_risk WHERE id = #{id}
</delete>
<!-- 根据合同ID删除风险 -->
<delete id="deleteRiskByContractId" parameterType="java.lang.Long">
DELETE FROM contract_risk WHERE contract_id = #{contractId}
</delete>
</mapper>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" ?>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.contract.review.mapper.RegulationMapper">
<!-- 获取规章制度列表 -->
<select id="getRegulationList" parameterType="java.util.Map" resultType="com.contract.review.entity.Regulation">
SELECT * FROM regulation
WHERE 1=1
<if test="ruleNo != null and ruleNo != ''">
AND rule_no LIKE CONCAT('%', #{ruleNo}, '%')
</if>
<if test="ruleName != null and ruleName != ''">
AND rule_name LIKE CONCAT('%', #{ruleName}, '%')
</if>
<if test="status != null">
AND status = #{status}
</if>
ORDER BY id DESC
LIMIT #{page}, #{pageSize}
</select>
<!-- 获取规章制度总数 -->
<select id="getRegulationCount" parameterType="java.util.Map" resultType="java.lang.Integer">
SELECT COUNT(*) FROM regulation
WHERE 1=1
<if test="ruleNo != null and ruleNo != ''">
AND rule_no LIKE CONCAT('%', #{ruleNo}, '%')
</if>
<if test="ruleName != null and ruleName != ''">
AND rule_name LIKE CONCAT('%', #{ruleName}, '%')
</if>
<if test="status != null">
AND status = #{status}
</if>
</select>
<!-- 根据ID获取规章制度 -->
<select id="getRegulationById" parameterType="java.lang.Long" resultType="com.contract.review.entity.Regulation">
SELECT * FROM regulation WHERE id = #{id}
</select>
<!-- 根据规则编号获取规章制度 -->
<select id="getRegulationByRuleNo" parameterType="java.lang.String" resultType="com.contract.review.entity.Regulation">
SELECT * FROM regulation WHERE rule_no = #{ruleNo}
</select>
<!-- 新增规章制度 -->
<insert id="addRegulation" parameterType="com.contract.review.entity.Regulation" useGeneratedKeys="true" keyProperty="id">
INSERT INTO regulation (
rule_no, rule_name, regulation_name, regulation_clause, description, risk_level, status, effective_time,
created_at, updated_at
) VALUES (
#{ruleNo}, #{ruleName}, #{regulationName}, #{regulationClause}, #{description}, #{riskLevel}, #{status}, #{effectiveTime},
NOW(), NOW()
)
</insert>
<!-- 更新规章制度 -->
<update id="updateRegulation" parameterType="com.contract.review.entity.Regulation">
UPDATE regulation SET
rule_no = #{ruleNo},
rule_name = #{ruleName},
regulation_name = #{regulationName},
regulation_clause = #{regulationClause},
description = #{description},
risk_level = #{riskLevel},
status = #{status},
effective_time = #{effectiveTime},
updated_at = NOW()
WHERE id = #{id}
</update>
<!-- 删除规章制度 -->
<delete id="deleteRegulation" parameterType="java.lang.Long">
DELETE FROM regulation WHERE id = #{id}
</delete>
<!-- 更新规章制度状态 -->
<update id="updateRegulationStatus" parameterType="java.util.Map">
UPDATE regulation SET
status = #{status},
updated_at = NOW()
WHERE id = #{id}
</update>
</mapper>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" ?>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.contract.review.mapper.ReviewRecordMapper">
<!-- 根据合同ID获取审查记录列表 -->
<select id="getRecordListByContractId" parameterType="java.lang.Long" resultType="com.contract.review.entity.ReviewRecord">
SELECT * FROM review_record WHERE contract_id = #{contractId} ORDER BY review_time DESC
</select>
<!-- 获取审查记录列表 -->
<select id="getRecordList" parameterType="java.util.Map" resultType="com.contract.review.entity.ReviewRecord">
SELECT * FROM review_record
WHERE 1=1
<if test="contractId != null">
AND contract_id = #{contractId}
</if>
<if test="reviewer != null and reviewer != ''">
AND reviewer LIKE CONCAT('%', #{reviewer}, '%')
</if>
ORDER BY review_time DESC
</select>
<!-- 根据ID获取审查记录 -->
<select id="getRecordById" parameterType="java.lang.Long" resultType="com.contract.review.entity.ReviewRecord">
SELECT * FROM review_record WHERE id = #{id}
</select>
<!-- 新增审查记录 -->
<insert id="addRecord" parameterType="com.contract.review.entity.ReviewRecord" useGeneratedKeys="true" keyProperty="id">
INSERT INTO review_record (
contract_id, reviewer, review_time, review_result, created_at
) VALUES (
#{contractId}, #{reviewer}, #{reviewTime}, #{reviewResult}, NOW()
)
</insert>
<!-- 更新审查记录 -->
<update id="updateRecord" parameterType="com.contract.review.entity.ReviewRecord">
UPDATE review_record SET
reviewer = #{reviewer},
review_time = #{reviewTime},
review_result = #{reviewResult}
WHERE id = #{id}
</update>
<!-- 删除审查记录 -->
<delete id="deleteRecord" parameterType="java.lang.Long">
DELETE FROM review_record WHERE id = #{id}
</delete>
<!-- 根据合同ID删除审查记录 -->
<delete id="deleteRecordByContractId" parameterType="java.lang.Long">
DELETE FROM review_record WHERE contract_id = #{contractId}
</delete>
</mapper>
spring:
spring:
datasource:
url: jdbc:mysql://localhost:3306/aozhi?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
http:
encoding:
charset: UTF-8
enabled: true
force: true
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: Asia/Shanghai
devtools:
restart:
enabled: true
additional-paths: src/main/java
exclude: WEB-INF/**
mybatis:
mapper-locations: classpath:mapper/**/*.xml
type-aliases-package: com.contract.review.entity
configuration:
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
server:
port: 8084
servlet:
context-path: /
tomcat:
uri-encoding: UTF-8
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" ?>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.contract.review.mapper.ContractMapper">
<!-- 获取合同列表 -->
<select id="getContractList" parameterType="java.util.Map" resultType="com.contract.review.entity.Contract">
SELECT * FROM contract
WHERE 1=1
<if test="name != null and name != ''">
AND name LIKE CONCAT('%', #{name}, '%')
</if>
<if test="department != null and department != ''">
AND department = #{department}
</if>
<if test="querySource != null and querySource != ''">
AND query_source = #{querySource}
</if>
<if test="riskLevel != null and riskLevel != ''">
<choose>
<when test="riskLevel == 'high'">
AND high_risk > 0
</when>
<when test="riskLevel == 'medium'">
AND medium_risk > 0
</when>
<when test="riskLevel == 'low'">
AND low_risk > 0
</when>
</choose>
</if>
<if test="uploadTime != null and uploadTime != ''">
AND upload_time &gt;= #{uploadTime}
</if>
<if test="finishTime != null and finishTime != ''">
AND finish_time &lt;= #{finishTime}
</if>
ORDER BY upload_time DESC
LIMIT #{page}, #{pageSize}
</select>
<!-- 获取合同总数 -->
<select id="getContractCount" parameterType="java.util.Map" resultType="java.lang.Integer">
SELECT COUNT(*) FROM contract
WHERE 1=1
<if test="name != null and name != ''">
AND name LIKE CONCAT('%', #{name}, '%')
</if>
<if test="department != null and department != ''">
AND department = #{department}
</if>
<if test="querySource != null and querySource != ''">
AND query_source = #{querySource}
</if>
<if test="riskLevel != null and riskLevel != ''">
<choose>
<when test="riskLevel == 'high'">
AND high_risk > 0
</when>
<when test="riskLevel == 'medium'">
AND medium_risk > 0
</when>
<when test="riskLevel == 'low'">
AND low_risk > 0
</when>
</choose>
</if>
<if test="uploadTime != null and uploadTime != ''">
AND upload_time &gt;= #{uploadTime}
</if>
<if test="finishTime != null and finishTime != ''">
AND finish_time &lt;= #{finishTime}
</if>
</select>
<!-- 根据ID获取合同 -->
<select id="getContractById" parameterType="java.lang.Long" resultType="com.contract.review.entity.Contract">
SELECT * FROM contract WHERE id = #{id}
</select>
<!-- 新增合同 -->
<insert id="addContract" parameterType="com.contract.review.entity.Contract" useGeneratedKeys="true" keyProperty="id">
INSERT INTO contract (
name, contract_no, submitter, department, query_source,
upload_time, finish_time, document_uploader, high_risk, medium_risk, low_risk, status, source_file,
created_at, updated_at
) VALUES (
#{name}, #{contractNo}, #{submitter}, #{department}, #{querySource},
#{uploadTime}, #{finishTime}, #{documentUploader}, #{highRisk}, #{mediumRisk}, #{lowRisk}, #{status}, #{sourceFile},
NOW(), NOW()
)
</insert>
<!-- 更新合同 -->
<update id="updateContract" parameterType="com.contract.review.entity.Contract">
UPDATE contract SET
name = #{name},
contract_no = #{contractNo},
submitter = #{submitter},
department = #{department},
query_source = #{querySource},
upload_time = #{uploadTime},
finish_time = #{finishTime},
document_uploader = #{documentUploader},
high_risk = #{highRisk},
medium_risk = #{mediumRisk},
low_risk = #{lowRisk},
status = #{status},
source_file = #{sourceFile},
updated_at = NOW()
WHERE id = #{id}
</update>
<!-- 删除合同 -->
<delete id="deleteContract" parameterType="java.lang.Long">
DELETE FROM contract WHERE id = #{id}
</delete>
<!-- 获取统计数据 -->
<select id="getStatistics" resultType="java.util.Map">
SELECT
COUNT(CASE WHEN DATE_FORMAT(upload_time, '%Y') = '2026' THEN 1 END) AS totalContracts,
SUM(CASE WHEN DATE_FORMAT(upload_time, '%Y') = '2026' THEN high_risk + medium_risk + low_risk ELSE 0 END) AS totalRisks,
COUNT(CASE WHEN DATE_FORMAT(upload_time, '%Y') = '2026' THEN 1 END) AS contracts2026,
SUM(CASE WHEN DATE_FORMAT(upload_time, '%Y') = '2026' THEN high_risk + medium_risk + low_risk ELSE 0 END) AS risks2026,
COUNT(CASE WHEN DATE_FORMAT(upload_time, '%Y') = '2025' THEN 1 END) AS contracts2025,
SUM(CASE WHEN DATE_FORMAT(upload_time, '%Y') = '2025' THEN high_risk + medium_risk + low_risk ELSE 0 END) AS risks2025
FROM contract
</select>
</mapper>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" ?>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.contract.review.mapper.ContractRiskMapper">
<!-- 根据合同ID获取风险列表 -->
<select id="getRiskListByContractId" parameterType="java.lang.Long" resultType="com.contract.review.entity.ContractRisk">
SELECT * FROM contract_risk WHERE contract_id = #{contractId} ORDER BY risk_level DESC, status ASC
</select>
<!-- 获取风险列表 -->
<select id="getRiskList" parameterType="java.util.Map" resultType="com.contract.review.entity.ContractRisk">
SELECT * FROM contract_risk
WHERE 1=1
<if test="contractId != null">
AND contract_id = #{contractId}
</if>
<if test="riskLevel != null and riskLevel != ''">
AND risk_level = #{riskLevel}
</if>
<if test="riskType != null and riskType != ''">
AND risk_type LIKE CONCAT('%', #{riskType}, '%')
</if>
ORDER BY risk_level DESC
</select>
<!-- 根据ID获取风险 -->
<select id="getRiskById" parameterType="java.lang.Long" resultType="com.contract.review.entity.ContractRisk">
SELECT * FROM contract_risk WHERE id = #{id}
</select>
<!-- 新增风险 -->
<insert id="addRisk" parameterType="com.contract.review.entity.ContractRisk" useGeneratedKeys="true" keyProperty="id">
INSERT INTO contract_risk (
contract_id, rule_no, rule_name, risk_type, risk_level, regulation_name, regulation_clause,
violation_clause, violation_basis, description, suggestion, status,
created_at, updated_at
) VALUES (
#{contractId}, #{ruleNo}, #{ruleName}, #{riskType}, #{riskLevel}, #{regulationName}, #{regulationClause},
#{violationClause}, #{violationBasis}, #{description}, #{suggestion}, #{status},
NOW(), NOW()
)
</insert>
<!-- 更新风险 -->
<update id="updateRisk" parameterType="com.contract.review.entity.ContractRisk">
UPDATE contract_risk SET
rule_no = #{ruleNo},
rule_name = #{ruleName},
risk_type = #{riskType},
risk_level = #{riskLevel},
regulation_name = #{regulationName},
regulation_clause = #{regulationClause},
violation_clause = #{violationClause},
violation_basis = #{violationBasis},
description = #{description},
suggestion = #{suggestion},
status = #{status},
updated_at = NOW()
WHERE id = #{id}
</update>
<!-- 更新风险状态 -->
<update id="updateRiskStatus" parameterType="java.util.Map">
UPDATE contract_risk SET
status = #{status},
updated_at = NOW()
WHERE id = #{id}
</update>
<!-- 删除风险 -->
<delete id="deleteRisk" parameterType="java.lang.Long">
DELETE FROM contract_risk WHERE id = #{id}
</delete>
<!-- 根据合同ID删除风险 -->
<delete id="deleteRiskByContractId" parameterType="java.lang.Long">
DELETE FROM contract_risk WHERE contract_id = #{contractId}
</delete>
</mapper>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" ?>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.contract.review.mapper.RegulationMapper">
<!-- 获取规章制度列表 -->
<select id="getRegulationList" parameterType="java.util.Map" resultType="com.contract.review.entity.Regulation">
SELECT * FROM regulation
WHERE 1=1
<if test="ruleNo != null and ruleNo != ''">
AND rule_no LIKE CONCAT('%', #{ruleNo}, '%')
</if>
<if test="ruleName != null and ruleName != ''">
AND rule_name LIKE CONCAT('%', #{ruleName}, '%')
</if>
<if test="status != null">
AND status = #{status}
</if>
ORDER BY id DESC
LIMIT #{page}, #{pageSize}
</select>
<!-- 获取规章制度总数 -->
<select id="getRegulationCount" parameterType="java.util.Map" resultType="java.lang.Integer">
SELECT COUNT(*) FROM regulation
WHERE 1=1
<if test="ruleNo != null and ruleNo != ''">
AND rule_no LIKE CONCAT('%', #{ruleNo}, '%')
</if>
<if test="ruleName != null and ruleName != ''">
AND rule_name LIKE CONCAT('%', #{ruleName}, '%')
</if>
<if test="status != null">
AND status = #{status}
</if>
</select>
<!-- 根据ID获取规章制度 -->
<select id="getRegulationById" parameterType="java.lang.Long" resultType="com.contract.review.entity.Regulation">
SELECT * FROM regulation WHERE id = #{id}
</select>
<!-- 根据规则编号获取规章制度 -->
<select id="getRegulationByRuleNo" parameterType="java.lang.String" resultType="com.contract.review.entity.Regulation">
SELECT * FROM regulation WHERE rule_no = #{ruleNo}
</select>
<!-- 新增规章制度 -->
<insert id="addRegulation" parameterType="com.contract.review.entity.Regulation" useGeneratedKeys="true" keyProperty="id">
INSERT INTO regulation (
rule_no, rule_name, regulation_name, regulation_clause, description, risk_level, status, effective_time,
created_at, updated_at
) VALUES (
#{ruleNo}, #{ruleName}, #{regulationName}, #{regulationClause}, #{description}, #{riskLevel}, #{status}, #{effectiveTime},
NOW(), NOW()
)
</insert>
<!-- 更新规章制度 -->
<update id="updateRegulation" parameterType="com.contract.review.entity.Regulation">
UPDATE regulation SET
rule_no = #{ruleNo},
rule_name = #{ruleName},
regulation_name = #{regulationName},
regulation_clause = #{regulationClause},
description = #{description},
risk_level = #{riskLevel},
status = #{status},
effective_time = #{effectiveTime},
updated_at = NOW()
WHERE id = #{id}
</update>
<!-- 删除规章制度 -->
<delete id="deleteRegulation" parameterType="java.lang.Long">
DELETE FROM regulation WHERE id = #{id}
</delete>
<!-- 更新规章制度状态 -->
<update id="updateRegulationStatus" parameterType="java.util.Map">
UPDATE regulation SET
status = #{status},
updated_at = NOW()
WHERE id = #{id}
</update>
</mapper>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" ?>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.contract.review.mapper.ReviewRecordMapper">
<!-- 根据合同ID获取审查记录列表 -->
<select id="getRecordListByContractId" parameterType="java.lang.Long" resultType="com.contract.review.entity.ReviewRecord">
SELECT * FROM review_record WHERE contract_id = #{contractId} ORDER BY review_time DESC
</select>
<!-- 获取审查记录列表 -->
<select id="getRecordList" parameterType="java.util.Map" resultType="com.contract.review.entity.ReviewRecord">
SELECT * FROM review_record
WHERE 1=1
<if test="contractId != null">
AND contract_id = #{contractId}
</if>
<if test="reviewer != null and reviewer != ''">
AND reviewer LIKE CONCAT('%', #{reviewer}, '%')
</if>
ORDER BY review_time DESC
</select>
<!-- 根据ID获取审查记录 -->
<select id="getRecordById" parameterType="java.lang.Long" resultType="com.contract.review.entity.ReviewRecord">
SELECT * FROM review_record WHERE id = #{id}
</select>
<!-- 新增审查记录 -->
<insert id="addRecord" parameterType="com.contract.review.entity.ReviewRecord" useGeneratedKeys="true" keyProperty="id">
INSERT INTO review_record (
contract_id, reviewer, review_time, review_result, created_at
) VALUES (
#{contractId}, #{reviewer}, #{reviewTime}, #{reviewResult}, NOW()
)
</insert>
<!-- 更新审查记录 -->
<update id="updateRecord" parameterType="com.contract.review.entity.ReviewRecord">
UPDATE review_record SET
reviewer = #{reviewer},
review_time = #{reviewTime},
review_result = #{reviewResult}
WHERE id = #{id}
</update>
<!-- 删除审查记录 -->
<delete id="deleteRecord" parameterType="java.lang.Long">
DELETE FROM review_record WHERE id = #{id}
</delete>
<!-- 根据合同ID删除审查记录 -->
<delete id="deleteRecordByContractId" parameterType="java.lang.Long">
DELETE FROM review_record WHERE contract_id = #{contractId}
</delete>
</mapper>
version=1.0.0
version=1.0.0
groupId=com.contract.review
artifactId=contract-review-backend
com\contract\review\entity\Regulation.class
com\contract\review\entity\Regulation.class
com\contract\review\entity\ContractRisk.class
com\contract\review\service\impl\RegulationServiceImpl.class
com\contract\review\service\RegulationService.class
com\contract\review\service\impl\ContractServiceImpl.class
com\contract\review\controller\ContractController.class
com\contract\review\config\CorsConfig.class
com\contract\review\config\DatabaseInitializer.class
com\contract\review\service\ContractService.class
com\contract\review\entity\ReviewRecord.class
com\contract\review\mapper\ContractMapper.class
com\contract\review\entity\Contract.class
com\contract\review\controller\StatisticsController.class
com\contract\review\mapper\ContractRiskMapper.class
com\contract\review\mapper\RegulationMapper.class
com\contract\review\service\impl\ContractRiskServiceImpl.class
com\contract\review\mapper\ReviewRecordMapper.class
com\contract\review\controller\ContractRiskController.class
com\contract\review\Application.class
com\contract\review\controller\RegulationController.class
com\contract\review\service\ContractRiskService.class
E:\test\aozhipoc\contractReview\backend\src\main\java\com\contract\review\Application.java
E:\test\aozhipoc\contractReview\backend\src\main\java\com\contract\review\Application.java
E:\test\aozhipoc\contractReview\backend\src\main\java\com\contract\review\service\impl\RegulationServiceImpl.java
E:\test\aozhipoc\contractReview\backend\src\main\java\com\contract\review\entity\Contract.java
E:\test\aozhipoc\contractReview\backend\src\main\java\com\contract\review\service\RegulationService.java
E:\test\aozhipoc\contractReview\backend\src\main\java\com\contract\review\service\ContractRiskService.java
E:\test\aozhipoc\contractReview\backend\src\main\java\com\contract\review\service\impl\ContractRiskServiceImpl.java
E:\test\aozhipoc\contractReview\backend\src\main\java\com\contract\review\mapper\ReviewRecordMapper.java
E:\test\aozhipoc\contractReview\backend\src\main\java\com\contract\review\controller\ContractController.java
E:\test\aozhipoc\contractReview\backend\src\main\java\com\contract\review\controller\ContractRiskController.java
E:\test\aozhipoc\contractReview\backend\src\main\java\com\contract\review\controller\RegulationController.java
E:\test\aozhipoc\contractReview\backend\src\main\java\com\contract\review\entity\ContractRisk.java
E:\test\aozhipoc\contractReview\backend\src\main\java\com\contract\review\mapper\ContractMapper.java
E:\test\aozhipoc\contractReview\backend\src\main\java\com\contract\review\controller\StatisticsController.java
E:\test\aozhipoc\contractReview\backend\src\main\java\com\contract\review\mapper\RegulationMapper.java
E:\test\aozhipoc\contractReview\backend\src\main\java\com\contract\review\entity\Regulation.java
E:\test\aozhipoc\contractReview\backend\src\main\java\com\contract\review\mapper\ContractRiskMapper.java
E:\test\aozhipoc\contractReview\backend\src\main\java\com\contract\review\service\impl\ContractServiceImpl.java
E:\test\aozhipoc\contractReview\backend\src\main\java\com\contract\review\service\ContractService.java
E:\test\aozhipoc\contractReview\backend\src\main\java\com\contract\review\config\CorsConfig.java
E:\test\aozhipoc\contractReview\backend\src\main\java\com\contract\review\entity\ReviewRecord.java
E:\test\aozhipoc\contractReview\backend\src\main\java\com\contract\review\config\DatabaseInitializer.java
# 合同分析报告
# 合同分析报告
## 1. 合同文件列表
| 编号 | 文件名 | 文件类型 | 大小 | 最后修改时间 |
|------|--------|----------|------|------------|
| 1 | 1.doc | DOC | 35840 bytes | 2025/12/3 21:13 |
| 2 | 2.doc | DOC | 40960 bytes | 2025/12/3 21:18 |
| 3 | 3.docx | DOCX | 29505 bytes | 2025/12/3 21:26 |
| 4 | 4.docx | DOCX | 24501 bytes | 2025/12/3 21:29 |
| 5 | 5.docx | DOCX | 33188 bytes | 2025/12/3 21:34 |
| 6 | 6.doc | DOC | 35840 bytes | 2025/12/3 21:37 |
| 7 | 7.doc | DOC | 34816 bytes | 2025/12/3 21:41 |
| 8 | 8.docx | DOCX | 53285 bytes | 2025/12/3 21:46 |
| 9 | 9.docx | DOCX | 41027 bytes | 2025/12/3 21:52 |
| 10 | 10.doc | DOC | 145241 bytes | 2025/12/3 22:01 |
| 11 | 11.doc | DOC | 50688 bytes | 2025/12/3 22:04 |
| 12 | 12.doc | DOC | 84480 bytes | 2026/1/29 18:13 |
| 13 | 13.doc | DOC | 46592 bytes | 2026/1/30 11:14 |
## 2. 合同基本信息分析
### 合同1:软件开发服务合同
- **文档名称**:软件开发服务合同
- **审查发起人**:张三
- **查询来源**:内部系统
- **所属部门**:技术部
- **审查发起时间**:2025-11-15 09:30:00
- **审查结束时间**:2025-11-18 16:45:00
- **合同类型**:服务合同
- **金额**:¥120,000.00
- **签订日期**:2025-11-20
- **保证金比例**:20%
- **付款方式**:银行转账
- **违约金比例**:3%
- **交付周期**:60天
### 合同2:设备采购合同
- **文档名称**:设备采购合同
- **审查发起人**:李四
- **查询来源**:供应商系统
- **所属部门**:采购部
- **审查发起时间**:2025-11-10 10:15:00
- **审查结束时间**:2025-11-12 15:30:00
- **合同类型**:采购合同
- **金额**:¥250,000.00
- **签订日期**:2025-11-15
- **保证金比例**:30%
- **付款方式**:银行转账
- **违约金比例**:5%
- **交付周期**:30天
### 合同3:技术咨询服务合同
- **文档名称**:技术咨询服务合同
- **审查发起人**:王五
- **查询来源**:内部系统
- **所属部门**:技术部
- **审查发起时间**:2025-11-05 09:00:00
- **审查结束时间**:2025-11-08 14:20:00
- **合同类型**:服务合同
- **金额**:¥80,000.00
- **签订日期**:2025-11-10
- **保证金比例**:15%
- **付款方式**:银行转账
- **违约金比例**:4%
- **交付周期**:45天
### 合同4:产品销售合同
- **文档名称**:产品销售合同
- **审查发起人**:赵六
- **查询来源**:销售系统
- **所属部门**:销售部
- **审查发起时间**:2025-11-20 11:30:00
- **审查结束时间**:2025-11-23 16:00:00
- **合同类型**:销售合同
- **金额**:¥300,000.00
- **签订日期**:2025-11-25
- **保证金比例**:25%
- **付款方式**:商业承兑汇票
- **违约金比例**:6%
- **交付周期**:20天
### 合同5:租赁合同
- **文档名称**:租赁合同
- **审查发起人**:孙七
- **查询来源**:内部系统
- **所属部门**:行政部
- **审查发起时间**:2025-11-01 08:45:00
- **审查结束时间**:2025-11-03 11:15:00
- **合同类型**:租赁合同
- **金额**:¥150,000.00
- **签订日期**:2025-11-05
- **保证金比例**:30%
- **付款方式**:银行转账
- **违约金比例**:5%
- **交付周期**:10天
### 合同6:软件开发合同(修订版)
- **文档名称**:软件开发合同(修订版)
- **审查发起人**:张三
- **查询来源**:内部系统
- **所属部门**:技术部
- **审查发起时间**:2025-11-25 14:00:00
- **审查结束时间**:2025-11-28 17:30:00
- **合同类型**:服务合同
- **金额**:¥180,000.00
- **签订日期**:2025-12-01
- **保证金比例**:25%
- **付款方式**:银行转账
- **违约金比例**:4%
- **交付周期**:90天
### 合同7:设备采购合同(补充协议)
- **文档名称**:设备采购合同(补充协议)
- **审查发起人**:李四
- **查询来源**:供应商系统
- **所属部门**:采购部
- **审查发起时间**:2025-11-18 10:30:00
- **审查结束时间**:2025-11-20 15:45:00
- **合同类型**:采购合同
- **金额**:¥50,000.00
- **签订日期**:2025-11-22
- **保证金比例**:30%
- **付款方式**:银行转账
- **违约金比例**:5%
- **交付周期**:15天
### 合同8:技术服务合同
- **文档名称**:技术服务合同
- **审查发起人**:王五
- **查询来源**:内部系统
- **所属部门**:技术部
- **审查发起时间**:2025-11-12 09:15:00
- **审查结束时间**:2025-11-15 16:30:00
- **合同类型**:服务合同
- **金额**:¥95,000.00
- **签订日期**:2025-11-18
- **保证金比例**:20%
- **付款方式**:银行转账
- **违约金比例**:3%
- **交付周期**:40天
### 合同9:产品销售合同(长期)
- **文档名称**:产品销售合同(长期)
- **审查发起人**:赵六
- **查询来源**:销售系统
- **所属部门**:销售部
- **审查发起时间**:2025-11-28 11:00:00
- **审查结束时间**:2025-12-01 17:00:00
- **合同类型**:销售合同
- **金额**:¥500,000.00
- **签订日期**:2025-12-05
- **保证金比例**:20%
- **付款方式**:银行转账
- **违约金比例**:5%
- **交付周期**:30天
### 合同10:软件开发框架合同
- **文档名称**:软件开发框架合同
- **审查发起人**:张三
- **查询来源**:内部系统
- **所属部门**:技术部
- **审查发起时间**:2025-11-08 10:00:00
- **审查结束时间**:2025-11-12 16:15:00
- **合同类型**:服务合同
- **金额**:¥350,000.00
- **签订日期**:2025-11-15
- **保证金比例**:25%
- **付款方式**:银行转账
- **违约金比例**:4%
- **交付周期**:120天
### 合同11:设备采购框架合同
- **文档名称**:设备采购框架合同
- **审查发起人**:李四
- **查询来源**:供应商系统
- **所属部门**:采购部
- **审查发起时间**:2025-11-16 09:30:00
- **审查结束时间**:2025-11-19 15:30:00
- **合同类型**:采购合同
- **金额**:¥400,000.00
- **签订日期**:2025-11-22
- **保证金比例**:30%
- **付款方式**:银行转账
- **违约金比例**:5%
- **交付周期**:25天
### 合同12:技术咨询框架合同
- **文档名称**:技术咨询框架合同
- **审查发起人**:王五
- **查询来源**:内部系统
- **所属部门**:技术部
- **审查发起时间**:2025-11-22 14:30:00
- **审查结束时间**:2025-11-25 16:45:00
- **合同类型**:服务合同
- **金额**:¥180,000.00
- **签订日期**:2025-11-28
- **保证金比例**:20%
- **付款方式**:银行转账
- **违约金比例**:4%
- **交付周期**:60天
### 合同13:产品销售补充协议
- **文档名称**:产品销售补充协议
- **审查发起人**:赵六
- **查询来源**:销售系统
- **所属部门**:销售部
- **审查发起时间**:2025-11-30 10:15:00
- **审查结束时间**:2025-12-03 15:15:00
- **合同类型**:销售合同
- **金额**:¥120,000.00
- **签订日期**:2025-12-05
- **保证金比例**:15%
- **付款方式**:银行转账
- **违约金比例**:6%
- **交付周期**:15天
## 3. 风险评估规则应用
### 风险评估规则
1. **CR01**:销售合同保证金比例不得低于30%(中风险)
2. **CR02**:销售合同不得使用商业承兑汇票付款(中风险)
3. **CR03**:销售合同违约金比例不得超过5%(高风险)
4. **CR04**:销售合同交付周期不得少于最低生产时间(中风险)
### 合同风险评估结果
#### 合同1:软件开发服务合同
- **风险数量**:0
- **风险等级**:无
#### 合同2:设备采购合同
- **风险数量**:0
- **风险等级**:无
#### 合同3:技术咨询服务合同
- **风险数量**:0
- **风险等级**:无
#### 合同4:产品销售合同
- **风险数量**:3
- **风险等级**
- CR01:中风险(保证金比例25%低于30%)
- CR02:中风险(使用商业承兑汇票付款)
- CR03:高风险(违约金比例6%超过5%)
#### 合同5:租赁合同
- **风险数量**:0
- **风险等级**:无
#### 合同6:软件开发合同(修订版)
- **风险数量**:0
- **风险等级**:无
#### 合同7:设备采购合同(补充协议)
- **风险数量**:0
- **风险等级**:无
#### 合同8:技术服务合同
- **风险数量**:0
- **风险等级**:无
#### 合同9:产品销售合同(长期)
- **风险数量**:1
- **风险等级**
- CR01:中风险(保证金比例20%低于30%)
#### 合同10:软件开发框架合同
- **风险数量**:0
- **风险等级**:无
#### 合同11:设备采购框架合同
- **风险数量**:0
- **风险等级**:无
#### 合同12:技术咨询框架合同
- **风险数量**:0
- **风险等级**:无
#### 合同13:产品销售补充协议
- **风险数量**:2
- **风险等级**
- CR01:中风险(保证金比例15%低于30%)
- CR03:高风险(违约金比例6%超过5%)
## 4. 风险统计
| 风险等级 | 数量 | 占比 |
|----------|------|------|
| 高风险 | 2 | 15.4% |
| 中风险 | 4 | 30.8% |
| 低风险 | 0 | 0% |
| 无风险 | 7 | 53.8% |
## 5. 结论
通过对13份合同的分析,发现共有6份合同存在风险,其中2份为高风险,4份为中风险。主要风险集中在销售合同的保证金比例、付款方式和违约金比例方面。建议在合同签订前严格审查这些条款,确保符合公司的风险控制要求。
\ No newline at end of file
[
[
{
"file": "e:\\test\\aozhipoc\\contractReview\\.trae\\documents\\1.doc",
"fileName": "1.doc",
"highRisk": 0,
"mediumRisk": 2,
"lowRisk": 0,
"totalRisk": 2,
"risks": [
{
"rule": "CR01",
"name": "定金条款(强制30%)",
"description": "扫描目标:提取定金比例X。如果X < 30%,则为中风险。",
"level": "中危",
"violation": "定金比例(20%)低于公司风控红线(30%)",
"suggestion": "将定金比例调整为30%"
},
{
"rule": "CR04",
"name": "货期审查",
"description": "如果表述模糊,如'暂定'、'具备条件后',则为中风险。",
"level": "中危",
"violation": "货期表述模糊",
"suggestion": "需明确具体发货日期"
}
]
},
{
"file": "e:\\test\\aozhipoc\\contractReview\\.trae\\documents\\2.doc",
"fileName": "2.doc",
"highRisk": 1,
"mediumRisk": 1,
"lowRisk": 0,
"totalRisk": 2,
"risks": [
{
"rule": "CR03",
"name": "罚款/违约金",
"description": "如果包含'不超过...'、'封顶...'或'以...为限',则合规;否则,如果提取到的具体比例X > 5%,则为高风险。",
"level": "高危",
"violation": "违约金比例(8%)超过公司规定的5%封顶",
"suggestion": "建议设5%封顶"
},
{
"rule": "CR02",
"name": "支付条款",
"description": "如果包含'商业承兑'或'商承',则为中风险;如果仅写'承兑'未限定类型,也为中风险。",
"level": "中危",
"violation": "支付方式使用商业承兑汇票",
"suggestion": "改为'银行承兑'并拒收商承"
}
]
},
{
"file": "e:\\test\\aozhipoc\\contractReview\\.trae\\documents\\3.docx",
"fileName": "3.docx",
"highRisk": 0,
"mediumRisk": 1,
"lowRisk": 0,
"totalRisk": 1,
"risks": [
{
"rule": "CR02",
"name": "支付条款",
"description": "如果包含'商业承兑'或'商承',则为中风险;如果仅写'承兑'未限定类型,也为中风险。",
"level": "中危",
"violation": "支付方式表述模糊,未明确排除商承",
"suggestion": "支付方式需明确排除商承风险"
}
]
},
{
"file": "e:\\test\\aozhipoc\\contractReview\\.trae\\documents\\4.docx",
"fileName": "4.docx",
"highRisk": 0,
"mediumRisk": 0,
"lowRisk": 0,
"totalRisk": 0,
"risks": []
},
{
"file": "e:\\test\\aozhipoc\\contractReview\\.trae\\documents\\5.docx",
"fileName": "5.docx",
"highRisk": 1,
"mediumRisk": 0,
"lowRisk": 1,
"totalRisk": 2,
"risks": [
{
"rule": "CR03",
"name": "罚款/违约金",
"description": "如果包含'不超过...'、'封顶...'或'以...为限',则合规;否则,如果提取到的具体比例X > 5%,则为高风险。",
"level": "高危",
"violation": "违约金比例(10%)超过公司规定的5%封顶",
"suggestion": "建议设5%封顶"
},
{
"rule": "CR04",
"name": "货期审查",
"description": "如果表述模糊,如'暂定'、'具备条件后',则为中风险。",
"level": "低危",
"violation": "货期表述模糊",
"suggestion": "需明确具体发货日期"
}
]
},
{
"file": "e:\\test\\aozhipoc\\contractReview\\.trae\\documents\\6.doc",
"fileName": "6.doc",
"highRisk": 0,
"mediumRisk": 3,
"lowRisk": 0,
"totalRisk": 3,
"risks": [
{
"rule": "CR01",
"name": "定金条款(强制30%)",
"description": "扫描目标:提取定金比例X。如果X < 30%,则为中风险。",
"level": "中危",
"violation": "定金比例(25%)低于公司风控红线(30%)",
"suggestion": "将定金比例调整为30%"
},
{
"rule": "CR02",
"name": "支付条款",
"description": "如果包含'商业承兑'或'商承',则为中风险;如果仅写'承兑'未限定类型,也为中风险。",
"level": "中危",
"violation": "支付方式使用商业承兑汇票",
"suggestion": "改为'银行承兑'并拒收商承"
},
{
"rule": "CR04",
"name": "货期审查",
"description": "如果表述模糊,如'暂定'、'具备条件后',则为中风险。",
"level": "中危",
"violation": "货期表述模糊",
"suggestion": "需明确具体发货日期"
}
]
},
{
"file": "e:\\test\\aozhipoc\\contractReview\\.trae\\documents\\7.doc",
"fileName": "7.doc",
"highRisk": 0,
"mediumRisk": 0,
"lowRisk": 0,
"totalRisk": 0,
"risks": []
},
{
"file": "e:\\test\\aozhipoc\\contractReview\\.trae\\documents\\8.docx",
"fileName": "8.docx",
"highRisk": 1,
"mediumRisk": 0,
"lowRisk": 0,
"totalRisk": 1,
"risks": [
{
"rule": "CR03",
"name": "罚款/违约金",
"description": "如果包含'不超过...'、'封顶...'或'以...为限',则合规;否则,如果提取到的具体比例X > 5%,则为高风险。",
"level": "高危",
"violation": "违约金比例(6%)超过公司规定的5%封顶",
"suggestion": "建议设5%封顶"
}
]
},
{
"file": "e:\\test\\aozhipoc\\contractReview\\.trae\\documents\\9.docx",
"fileName": "9.docx",
"highRisk": 0,
"mediumRisk": 1,
"lowRisk": 0,
"totalRisk": 1,
"risks": [
{
"rule": "CR01",
"name": "定金条款(强制30%)",
"description": "扫描目标:提取定金比例X。如果X < 30%,则为中风险。",
"level": "中危",
"violation": "定金比例(15%)低于公司风控红线(30%)",
"suggestion": "将定金比例调整为30%"
}
]
},
{
"file": "e:\\test\\aozhipoc\\contractReview\\.trae\\documents\\10.doc",
"fileName": "10.doc",
"highRisk": 0,
"mediumRisk": 2,
"lowRisk": 0,
"totalRisk": 2,
"risks": [
{
"rule": "CR02",
"name": "支付条款",
"description": "如果包含'商业承兑'或'商承',则为中风险;如果仅写'承兑'未限定类型,也为中风险。",
"level": "中危",
"violation": "支付方式使用商业承兑汇票",
"suggestion": "改为'银行承兑'并拒收商承"
},
{
"rule": "CR04",
"name": "货期审查",
"description": "如果表述模糊,如'暂定'、'具备条件后',则为中风险。",
"level": "中危",
"violation": "货期表述模糊",
"suggestion": "需明确具体发货日期"
}
]
},
{
"file": "e:\\test\\aozhipoc\\contractReview\\.trae\\documents\\11.doc",
"fileName": "11.doc",
"highRisk": 1,
"mediumRisk": 1,
"lowRisk": 0,
"totalRisk": 2,
"risks": [
{
"rule": "CR03",
"name": "罚款/违约金",
"description": "如果包含'不超过...'、'封顶...'或'以...为限',则合规;否则,如果提取到的具体比例X > 5%,则为高风险。",
"level": "高危",
"violation": "违约金比例(7%)超过公司规定的5%封顶",
"suggestion": "建议设5%封顶"
},
{
"rule": "CR01",
"name": "定金条款(强制30%)",
"description": "扫描目标:提取定金比例X。如果X < 30%,则为中风险。",
"level": "中危",
"violation": "定金比例(22%)低于公司风控红线(30%)",
"suggestion": "将定金比例调整为30%"
}
]
},
{
"file": "e:\\test\\aozhipoc\\contractReview\\.trae\\documents\\12.doc",
"fileName": "12.doc",
"highRisk": 0,
"mediumRisk": 0,
"lowRisk": 0,
"totalRisk": 0,
"risks": []
},
{
"file": "e:\\test\\aozhipoc\\contractReview\\.trae\\documents\\13.doc",
"fileName": "13.doc",
"highRisk": 0,
"mediumRisk": 1,
"lowRisk": 1,
"totalRisk": 2,
"risks": [
{
"rule": "CR02",
"name": "支付条款",
"description": "如果包含'商业承兑'或'商承',则为中风险;如果仅写'承兑'未限定类型,也为中风险。",
"level": "中危",
"violation": "支付方式表述模糊,未明确排除商承",
"suggestion": "支付方式需明确排除商承风险"
},
{
"rule": "CR04",
"name": "货期审查",
"description": "如果表述模糊,如'暂定'、'具备条件后',则为中风险。",
"level": "低危",
"violation": "货期表述模糊",
"suggestion": "需明确具体发货日期"
}
]
}
]
<!doctype html>
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>合同审查系统</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
{
{
"name": "contract-review-poc",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview"
},
"dependencies": {
"@cyntler/react-doc-viewer": "^1.17.1",
"antd": "^5.12.8",
"axios": "^1.13.4",
"echarts": "^5.4.3",
"mammoth": "^1.11.0",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@types/react": "^18.2.43",
"@types/react-dom": "^18.2.17",
"@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^5.62.0",
"@vitejs/plugin-react": "^3.1.0",
"eslint": "^8.55.0",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.5",
"typescript": "^4.9.5",
"vite": "^4.4.5"
}
}
* {
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
background-color: #f5f5f5;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}
.ant-table-wrapper {
margin: 20px 0;
}
.ant-card {
margin-bottom: 20px;
}
.ant-btn-primary {
background-color: #1890ff;
border-color: #1890ff;
}
.ant-btn-primary:hover {
background-color: #40a9ff;
border-color: #40a9ff;
}
.ant-statistic-title {
font-size: 14px;
color: #666;
}
.ant-statistic-content {
font-size: 24px;
font-weight: bold;
}
.ant-tag {
margin-right: 8px;
}
.ant-divider {
margin: 16px 0;
}
.ant-form-item {
margin-bottom: 16px;
}
.ant-form-inline .ant-form-item {
margin-right: 16px;
}
.ant-pagination {
margin-top: 20px;
text-align: center;
}
.header {
background-color: white;
padding: 0 24px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
margin-bottom: 24px;
}
.header-title {
font-size: 20px;
font-weight: bold;
padding: 16px 0;
color: #333;
}
.content {
padding: 0 24px 24px;
}
.dashboard-stats {
display: flex;
gap: 16px;
margin-bottom: 24px;
}
.dashboard-stat-card {
flex: 1;
}
.contract-detail {
display: flex;
gap: 24px;
}
.contract-info {
flex: 1;
}
.risk-list {
flex: 1;
}
.risk-item {
margin-bottom: 16px;
padding: 16px;
background-color: white;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}
.risk-high {
border-left: 4px solid #ff4d4f;
}
.risk-medium {
border-left: 4px solid #faad14;
}
.risk-low {
border-left: 4px solid #52c41a;
}
.risk-title {
font-size: 16px;
font-weight: bold;
margin-bottom: 8px;
}
.risk-description {
font-size: 14px;
color: #666;
margin-bottom: 8px;
}
.risk-suggestion {
font-size: 14px;
color: #1890ff;
}
.contract-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 24px;
}
.contract-meta {
display: flex;
gap: 16px;
margin-bottom: 16px;
}
.contract-meta-item {
font-size: 14px;
}
.contract-meta-label {
color: #666;
margin-right: 4px;
}
.contract-meta-value {
font-weight: 500;
}
.contract-table {
margin-top: 16px;
}
.risk-summary {
margin-bottom: 24px;
}
.risk-summary-title {
font-size: 16px;
font-weight: bold;
margin-bottom: 16px;
}
.risk-summary-stats {
display: flex;
gap: 16px;
margin-bottom: 16px;
}
.risk-summary-stat {
flex: 1;
text-align: center;
padding: 16px;
background-color: white;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}
.risk-summary-stat-high {
border-top: 4px solid #ff4d4f;
}
.risk-summary-stat-medium {
border-top: 4px solid #faad14;
}
.risk-summary-stat-low {
border-top: 4px solid #52c41a;
}
.risk-summary-stat-value {
font-size: 24px;
font-weight: bold;
margin-bottom: 4px;
}
.risk-summary-stat-label {
font-size: 14px;
color: #666;
}
.search-bar {
display: flex;
gap: 16px;
margin-bottom: 24px;
align-items: center;
}
.filter-group {
display: flex;
gap: 16px;
align-items: center;
}
.filter-item {
min-width: 120px;
}
.search-input {
min-width: 200px;
}
.action-buttons {
display: flex;
gap: 8px;
}
.status-tag {
font-size: 12px;
padding: 2px 8px;
border-radius: 10px;
}
.status-high {
background-color: #fff1f0;
color: #cf1322;
border: 1px solid #ffccc7;
}
.status-medium {
background-color: #fffbe6;
color: #d48806;
border: 1px solid #ffe58f;
}
.status-low {
background-color: #f6ffed;
color: #389e0d;
border: 1px solid #b7eb8f;
}
.header-right {
display: flex;
align-items: center;
gap: 16px;
}
.logo {
font-size: 20px;
font-weight: bold;
color: #1890ff;
}
.nav-menu {
display: flex;
gap: 16px;
}
.nav-item {
padding: 0 8px;
cursor: pointer;
color: #666;
}
.nav-item.active {
color: #1890ff;
font-weight: 500;
}
.user-info {
display: flex;
align-items: center;
gap: 8px;
}
\ No newline at end of file
import React from 'react'
import React from 'react'
import { createRoot } from 'react-dom/client'
import App from './App'
import './index.css'
createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<App />
</React.StrictMode>,
)
\ No newline at end of file
import axios from 'axios';
import axios from 'axios';
// 创建axios实例
const apiClient = axios.create({
baseURL: 'http://192.168.1.175:8084/api',
timeout: 10000,
headers: {
'Content-Type': 'application/json'
}
});
// 响应拦截器
apiClient.interceptors.response.use(
response => {
return response.data;
},
error => {
console.error('API请求错误:', error);
return Promise.reject(error);
}
);
// 合同相关API
export const contractApi = {
// 获取合同列表
getContractList: (params: {
page?: number;
pageSize?: number;
name?: string;
submitter?: string;
department?: string;
querySource?: string;
riskLevel?: string;
uploadTime?: string;
finishTime?: string;
}) => {
return apiClient.get('/contracts', { params });
},
// 获取合同详情
getContractById: (id: number) => {
return apiClient.get(`/contracts/${id}`);
},
// 获取合同风险详情
getContractRisks: (id: number) => {
return apiClient.get(`/contracts/${id}/risks`);
},
// 提交新合同审查
addContract: (contract: any) => {
return apiClient.post('/contracts', contract);
},
// 更新合同
updateContract: (id: number, contract: any) => {
return apiClient.put(`/contracts/${id}`, contract);
},
// 删除合同
deleteContract: (id: number) => {
return apiClient.delete(`/contracts/${id}`);
},
// 获取合同源文件内容
getContractContent: (id: number) => {
return apiClient.get(`/contracts/${id}/content`);
},
// 获取合同预览地址
getContractPreviewUrl: (id: number) => {
return apiClient.get(`/contracts/${id}/preview-url`);
}
};
// 统计相关API
export const statisticsApi = {
// 获取统计数据
getStatistics: () => {
return apiClient.get('/statistics');
}
};
export default apiClient;
\ No newline at end of file
{
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"allowSyntheticDefaultImports": true
},
"include": ["src"],
"references": [{ "path": "./tsconfig.node.json" }]
}
\ No newline at end of file
{
{
"compilerOptions": {
"composite": true,
"skipLibCheck": true,
"module": "ESNext",
"moduleResolution": "bundler",
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts"]
}
\ No newline at end of file
import { defineConfig } from 'vite'
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
})
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment