Compare commits

...

33 Commits

Author SHA1 Message Date
5c91ec620e 优化审计取证单Word文档表格单元格换行处理 2026-02-04 17:39:14 +08:00
6fc21fd142 新增审计取证单Word文档模板 2026-02-04 16:51:19 +08:00
58c4d5a540 新增下载审计取证单Word文档接口 2026-02-04 16:50:28 +08:00
ddc1fa2dbd 添加工作索引文件真实约束 2026-02-03 15:31:14 +08:00
b0d32c05d6 优化上传文档到知识库(公共库)接口 2026-02-02 18:00:37 +08:00
bfbc7ba24b 新增字段案引号 2026-02-02 10:17:10 +08:00
32f48732f4 审计内容1-八项规定-新增建议 2026-01-29 17:39:17 +08:00
a4aa1ef479 优化dify返回内容解析 2026-01-27 10:53:39 +08:00
2a64e5117b 文件上传后将fileId的UUID部分做为标签更新 2026-01-22 11:46:40 +08:00
bdf4cde39f 切换知识库工具栏 2026-01-22 10:34:19 +08:00
9689ce9e23 知识库召回跳过租户IgnoreTenant 2026-01-20 17:50:47 +08:00
d04305c325 优化企业删除、项目创建功能 2026-01-20 16:35:43 +08:00
ae1e150d1c 审计内容取证单生成 2026-01-16 17:44:26 +08:00
378d37f590 添加审计内容9-福利费超范围支出明细清单 2026-01-14 18:27:16 +08:00
9629c7234d 优化工作底稿索引 2026-01-13 18:17:27 +08:00
86d9f4892c 审计内容9优化 2026-01-13 10:33:32 +08:00
6c5b2057a7 优化审计内容2 2026-01-12 18:17:04 +08:00
45a88a94ea 关闭知识库召回时Reranking排序 2026-01-12 15:13:34 +08:00
a284472782 审计内容3三重一大优化、接口返回附件ID优化 2026-01-12 10:40:17 +08:00
696df82963 优化审计内容4目标责任制完成情况审计表内容 2026-01-09 10:47:02 +08:00
f407deb7ad 优化审计内容1决策支出表内容 2026-01-08 17:23:58 +08:00
d2fe476b1a 优化工作底稿索引,调整格式为:["文件ID||文件名||下载地址"] 2026-01-07 17:58:43 +08:00
02bdd456f4 知识库文档上传同时备份至OSS服务器 2026-01-06 17:15:59 +08:00
db53938d88 新增审计内容9接口 2026-01-04 14:33:15 +08:00
204873d06e 历史记录优化 2025-12-26 15:14:01 +08:00
2464e0e791 新增审计内容11-历史审计问题整改接口 2025-12-12 15:57:47 +08:00
da4b230bd7 新增审计内容10-廉政情况接口 2025-12-12 15:22:07 +08:00
4c022d3c21 新增审计内容8-内部控制测试接口 2025-12-11 11:37:33 +08:00
ae4161c822 新增审计内容7-重大投资情况审计接口 2025-12-10 16:49:16 +08:00
f667e24797 新增审计内容5-预算管理审计接口 2025-12-09 15:30:31 +08:00
397ef7f530 新增接口审计内容6-国资管理情况 2025-12-05 10:33:38 +08:00
edb124acec 新增接口审计内容4-目标责任制完成情况审计 2025-12-04 17:16:47 +08:00
8e3750668e 新增接口审计内容2-单位发展战略执行审计 2025-12-04 11:04:03 +08:00
95 changed files with 10028 additions and 2298 deletions

View File

@@ -8,5 +8,9 @@ import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "ai.template")
public class TemplateConfig {
private String wordTemplatePath;
private String evidenceTemplatePath;
}

View File

@@ -0,0 +1,432 @@
package com.gxwebsoft.ai.constants;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import java.util.*;
/**
* 党风廉政建设责任制审计常量类
*/
public class AuditContent10PartyConductConstants {
// 大类定义
public static final String CATEGORY_TARGET_RESPONSIBILITY = "落实党风廉政建设责任制";
public static final String CATEGORY_INSPECTION_RECTIFICATION = "巡视整改工作";
public static final String CATEGORY_DISCIPLINE_REFORM = "深化纪律检查体制改革";
// 子类定义 - 落实党风廉政建设责任制
public static final String SUBCATEGORY_MAIN_RESPONSIBILITY = "落实主体责任和监督责任";
public static final String SUBCATEGORY_EIGHT_REGULATIONS = "落实中央八项规定精神工作";
public static final String SUBCATEGORY_ANTI_CORRUPTION = "开展查处发生在群众身边的\"四风\"和腐败问题专项工作";
public static final String SUBCATEGORY_DISCIPLINE_ENFORCEMENT = "严明纪律确保政令畅通";
// 子类定义 - 巡视整改工作
public static final String SUBCATEGORY_MONTHLY_REPORT = "严格执行月报告制度";
public static final String SUBCATEGORY_RECTIFICATION_TASK = "按时完成整改任务";
public static final String SUBCATEGORY_RECTIFICATION_ACCOUNTABILITY = "因巡视整改不给力被追究";
// 子类定义 - 深化纪律检查体制改革
public static final String SUBCATEGORY_THREE_TURNS = "聚焦主业主责,持续深化\"三转\"工作";
public static final String SUBCATEGORY_SYSTEM_CONSTRUCTION = "健全完善深化纪检体制改革的相关制度文件并抓好贯彻落实";
// 小类定义
public static final String DETAIL_LEADERSHIP_STRENGTHENING = "1 强化组织领导";
public static final String DETAIL_TASK_DEPLOYMENT = "2 及时部署工作任务";
public static final String DETAIL_PRESSURE_TRANSMISSION = "3 层层传到责任和压力";
public static final String DETAIL_CASE_DOUBLE_CHECK = "4 坚持\"一案双查\"";
public static final String DETAIL_WORK_REPORTING = "5 及时汇报工作情况";
public static final String DETAIL_INSPECTION_AND_SUPERVISION = "1 开展监督检查";
public static final String DETAIL_DATA_SUBMISSION = "2 报送数据和资料";
public static final String DETAIL_CASE_HANDLING = "3 查办违反中央八项规定精神案件";
public static final String DETAIL_EXPOSURE_NOTIFICATION = "4 通报曝光";
public static final String DETAIL_HOUSING_CLEARANCE = "5 清退干部职工多占住房";
public static final String DETAIL_PROBLEM_CLUE_HANDLING = "1 及时梳理处置问题线索";
public static final String DETAIL_CASE_INVESTIGATION = "2 查处一批案件";
public static final String DETAIL_TYPICAL_CASE_EXPOSURE = "3 通报曝光一批典型案件";
public static final String DETAIL_ATMOSPHERE_CREATION = "4 营造氛围";
public static final String DETAIL_PROBLEM_CONFESSION = "5 督促违纪人员主动交代问题";
public static final String DETAIL_SUMMARY_AND_MECHANISM = "6 进行总结并建立长效机制";
public static final String DETAIL_NORMALIZED_GOVERNANCE = "7 专项工作纳入常态化治理";
public static final String DETAIL_POLITICAL_DISCIPLINE = "1 严明政治纪律和组织纪律";
public static final String DETAIL_MAJOR_DECISION = "2 按时完成中央和自治区重大决策部署";
public static final String DETAIL_CASE_COMPLETION = "3 按时完成转办督办案件";
// 大类与子类映射关系
public static final Map<String, List<String>> CATEGORY_SUBCATEGORY_MAP = new HashMap<>();
static {
// 落实党风廉政建设责任制
CATEGORY_SUBCATEGORY_MAP.put(CATEGORY_TARGET_RESPONSIBILITY, Arrays.asList(
SUBCATEGORY_MAIN_RESPONSIBILITY,
SUBCATEGORY_EIGHT_REGULATIONS,
SUBCATEGORY_ANTI_CORRUPTION,
SUBCATEGORY_DISCIPLINE_ENFORCEMENT
));
// 巡视整改工作
CATEGORY_SUBCATEGORY_MAP.put(CATEGORY_INSPECTION_RECTIFICATION, Arrays.asList(
SUBCATEGORY_MONTHLY_REPORT,
SUBCATEGORY_RECTIFICATION_TASK,
SUBCATEGORY_RECTIFICATION_ACCOUNTABILITY
));
// 深化纪律检查体制改革
CATEGORY_SUBCATEGORY_MAP.put(CATEGORY_DISCIPLINE_REFORM, Arrays.asList(
SUBCATEGORY_THREE_TURNS,
SUBCATEGORY_SYSTEM_CONSTRUCTION
));
}
// 子类与小类映射关系
public static final Map<String, List<String>> SUBCATEGORY_DETAIL_MAP = new HashMap<>();
static {
// 落实主体责任和监督责任
SUBCATEGORY_DETAIL_MAP.put(SUBCATEGORY_MAIN_RESPONSIBILITY, Arrays.asList(
DETAIL_LEADERSHIP_STRENGTHENING,
DETAIL_TASK_DEPLOYMENT,
DETAIL_PRESSURE_TRANSMISSION,
DETAIL_CASE_DOUBLE_CHECK,
DETAIL_WORK_REPORTING
));
// 落实中央八项规定精神工作
SUBCATEGORY_DETAIL_MAP.put(SUBCATEGORY_EIGHT_REGULATIONS, Arrays.asList(
DETAIL_INSPECTION_AND_SUPERVISION,
DETAIL_DATA_SUBMISSION,
DETAIL_CASE_HANDLING,
DETAIL_EXPOSURE_NOTIFICATION,
DETAIL_HOUSING_CLEARANCE
));
// 开展查处发生在群众身边的"四风"和腐败问题专项工作
SUBCATEGORY_DETAIL_MAP.put(SUBCATEGORY_ANTI_CORRUPTION, Arrays.asList(
DETAIL_PROBLEM_CLUE_HANDLING,
DETAIL_CASE_INVESTIGATION,
DETAIL_TYPICAL_CASE_EXPOSURE,
DETAIL_ATMOSPHERE_CREATION,
DETAIL_PROBLEM_CONFESSION,
DETAIL_SUMMARY_AND_MECHANISM,
DETAIL_NORMALIZED_GOVERNANCE
));
// 严明纪律确保政令畅通
SUBCATEGORY_DETAIL_MAP.put(SUBCATEGORY_DISCIPLINE_ENFORCEMENT, Arrays.asList(
DETAIL_POLITICAL_DISCIPLINE,
DETAIL_MAJOR_DECISION,
DETAIL_CASE_COMPLETION
));
// 巡视整改工作的子类
SUBCATEGORY_DETAIL_MAP.put(SUBCATEGORY_MONTHLY_REPORT, Arrays.asList("1 严格执行月报告制度"));
SUBCATEGORY_DETAIL_MAP.put(SUBCATEGORY_RECTIFICATION_TASK, Arrays.asList("2 按时完成整改任务"));
SUBCATEGORY_DETAIL_MAP.put(SUBCATEGORY_RECTIFICATION_ACCOUNTABILITY, Arrays.asList("3 因巡视整改不给力被追究"));
// 深化纪律检查体制改革的子类
SUBCATEGORY_DETAIL_MAP.put(SUBCATEGORY_THREE_TURNS, Arrays.asList("1 聚焦主业主责,持续深化\"三转\"工作"));
SUBCATEGORY_DETAIL_MAP.put(SUBCATEGORY_SYSTEM_CONSTRUCTION, Arrays.asList("2 健全完善深化纪检体制改革的相关制度文件并抓好贯彻落实"));
}
// 固定顺序的示例数据列表按审计内容10.txt中的顺序
private static final List<JSONObject> FIXED_ORDER_EXAMPLE_DATA = new ArrayList<>();
static {
// 落实主体责任和监督责任
addExampleData("落实党风廉政建设责任制", "落实主体责任和监督责任", "1 强化组织领导", "建立责任清单、明确党组、纪检责任");
addExampleData("落实党风廉政建设责任制", "落实主体责任和监督责任", "1 强化组织领导", "建立健全反腐败领导机制,人员调整后及时进行分工,并全年召开两次以上协调会");
addExampleData("落实党风廉政建设责任制", "落实主体责任和监督责任", "1 强化组织领导", "主要领导认真履行第一责任人责任对党风廉政建设重要工作亲自部署、重大问题亲自过问、重点环节亲自协调、重要案件亲自督办5次以上");
addExampleData("落实党风廉政建设责任制", "落实主体责任和监督责任", "1 强化组织领导", "领导班子其他成员对职责范围内的党风廉政建设承担主要责任与分管联系部门研究安排党风廉政建设工作4次以上");
addExampleData("落实党风廉政建设责任制", "落实主体责任和监督责任", "2 及时部署工作任务", "有党风廉政建设任务分工方案党组专题研究部署党风廉政建设工作4次以上");
addExampleData("落实党风廉政建设责任制", "落实主体责任和监督责任", "3 层层传到责任和压力", "主要领导检查和调研党风廉政建设各一次以上,每年听取分管联系部门的党风廉政建设一次以上且每年亲自上廉政党课不少于1次");
addExampleData("落实党风廉政建设责任制", "落实主体责任和监督责任", "3 层层传到责任和压力", "分管领导对分管联系部门党风廉政建设检查和调研各1次以上每年听取分管联系部门的党风廉政建设情况汇报一次以上到分管联系部门上廉政党课1次以上");
addExampleData("落实党风廉政建设责任制", "落实主体责任和监督责任", "3 层层传到责任和压力", "党组、纪检组注重抓早抓小经常进行咬耳扯袖、红脸出汗及时开展约谈、集体廉政谈话等工作3次以上");
addExampleData("落实党风廉政建设责任制", "落实主体责任和监督责任", "3 层层传到责任和压力", "开展述责评议工作");
addExampleData("落实党风廉政建设责任制", "落实主体责任和监督责任", "4 坚持\"一案双查\"", "对发生在本单位的较严重的违反政治纪律、组织纪律等问题进行\"一案双查\"");
addExampleData("落实党风廉政建设责任制", "落实主体责任和监督责任", "4 坚持\"一案双查\"", "出现\"四风\"和腐败等顶风违纪问题的");
addExampleData("落实党风廉政建设责任制", "落实主体责任和监督责任", "4 坚持\"一案双查\"", "出现区域性系统性违纪违法问题突出的");
addExampleData("落实党风廉政建设责任制", "落实主体责任和监督责任", "4 坚持\"一案双查\"", "出现上级交办的党风廉政建设事项不传达部署和落实的");
addExampleData("落实党风廉政建设责任制", "落实主体责任和监督责任", "4 坚持\"一案双查\"", "出现违纪行为隐瞒不报压案不查等问题而未进行责任追究被中央、自治区进行挂牌督办或直接问责、约谈等");
addExampleData("落实党风廉政建设责任制", "落实主体责任和监督责任", "5 及时汇报工作情况", "党组、纪检组向自治区党委、纪委汇报\"两个\"责任落实情况两次以上");
addExampleData("落实党风廉政建设责任制", "落实主体责任和监督责任", "5 及时汇报工作情况", "班子成员年底向自治区纪委报送个人落实\"两个责任\"情况报告");
addExampleData("落实党风廉政建设责任制", "落实主体责任和监督责任", "5 及时汇报工作情况", "按照自治区纪委部署开展其他工作,并按时报送总结报告的");
// 落实中央八项规定精神工作
addExampleData("落实党风廉政建设责任制", "落实中央八项规定精神工作", "1 开展监督检查", "部署开展监督检查3次以上");
addExampleData("落实党风廉政建设责任制", "落实中央八项规定精神工作", "2 报送数据和资料", "每月按时报送中央八项规定精神案件有关统计数据和有关资料");
addExampleData("落实党风廉政建设责任制", "落实中央八项规定精神工作", "2 报送数据和资料", "每月不按时报送或未按要求报送的");
addExampleData("落实党风廉政建设责任制", "落实中央八项规定精神工作", "3 查办违反中央八项规定精神案件", "及时查处监督检查中发现的问题和中央、自治区转办督办的问题线索");
addExampleData("落实党风廉政建设责任制", "落实中央八项规定精神工作", "3 查办违反中央八项规定精神案件", "出现违反中央八项规定精神问题被上级查处的,或查处但问责太轻,被上级责令重新查办");
addExampleData("落实党风廉政建设责任制", "落实中央八项规定精神工作", "4 通报曝光", "对受到党纪政纪处分的问题全部进行通报曝光的");
addExampleData("落实党风廉政建设责任制", "落实中央八项规定精神工作", "5 清退干部职工多占住房", "到年底还不能完成干部职工多占住房清退的");
addExampleData("落实党风廉政建设责任制", "落实中央八项规定精神工作", "5 清退干部职工多占住房", "信访反映清房工作不到位被查实的");
// 开展查处发生在群众身边的"四风"和腐败问题专项工作
addExampleData("落实党风廉政建设责任制", "开展查处发生在群众身边的\"四风\"和腐败问题专项工作", "1 及时梳理处置问题线索", "对收到或者上级交办问题线索进行转办督办或直接查办的");
addExampleData("落实党风廉政建设责任制", "开展查处发生在群众身边的\"四风\"和腐败问题专项工作", "2 查处一批案件", "因查处案件不力被自治区约谈或通报批评的");
addExampleData("落实党风廉政建设责任制", "开展查处发生在群众身边的\"四风\"和腐败问题专项工作", "3 通报曝光一批典型案件", "对查处的案件进行通报曝光");
addExampleData("落实党风廉政建设责任制", "开展查处发生在群众身边的\"四风\"和腐败问题专项工作", "4 营造氛围", "加大宣传力度,用典型案例进行警示教育");
addExampleData("落实党风廉政建设责任制", "开展查处发生在群众身边的\"四风\"和腐败问题专项工作", "5 督促违纪人员主动交代问题", "以文件形式或在网络、报纸、电视等媒介上发布公告,督促违纪人员主动交代问题并主动上缴违纪所得");
addExampleData("落实党风廉政建设责任制", "开展查处发生在群众身边的\"四风\"和腐败问题专项工作", "6 进行总结并建立长效机制", "没有在6月20日前进行总结");
addExampleData("落实党风廉政建设责任制", "开展查处发生在群众身边的\"四风\"和腐败问题专项工作", "6 进行总结并建立长效机制", "没有结合专项工作中发现存在的突出问题建立完善制度措施");
addExampleData("落实党风廉政建设责任制", "开展查处发生在群众身边的\"四风\"和腐败问题专项工作", "7 专项工作纳入常态化治理", "6月后在全部二层单位开展专项工作");
// 严明纪律确保政令畅通
addExampleData("落实党风廉政建设责任制", "严明纪律确保政令畅通", "1 严明政治纪律和组织纪律", "有违反政治纪律等问题被中央、自治区查处的");
addExampleData("落实党风廉政建设责任制", "严明纪律确保政令畅通", "2 按时完成中央和自治区重大决策部署", "出现问题被中央、自治区问责的");
addExampleData("落实党风廉政建设责任制", "严明纪律确保政令畅通", "3 按时完成转办督办案件", "按时完成自治区纪委转办督办的党风政风类案件");
addExampleData("落实党风廉政建设责任制", "严明纪律确保政令畅通", "3 按时完成转办督办案件", "不按时完成或不完成的");
// 巡视整改工作
addExampleData("巡视整改工作", "严格执行月报告制度", "1 严格执行月报告制度", "严格执行月报告制度");
addExampleData("巡视整改工作", "按时完成整改任务", "2 按时完成整改任务", "按时完成整改任务");
addExampleData("巡视整改工作", "因巡视整改不给力被追究", "3 因巡视整改不给力被追究", "因巡视整改不给力被追究");
// 深化纪律检查体制改革
addExampleData("深化纪律检查体制改革", "聚焦主业主责,持续深化\"三转\"工作", "1 聚焦主业主责,持续深化\"三转\"工作", "纪检组长或纪工委书记不分管具体业务工作,专职抓执纪监督问责工作");
addExampleData("深化纪律检查体制改革", "聚焦主业主责,持续深化\"三转\"工作", "1 聚焦主业主责,持续深化\"三转\"工作", "检查发现有参与业务工作");
addExampleData("深化纪律检查体制改革", "健全完善深化纪检体制改革的相关制度文件并抓好贯彻落实", "2 健全完善深化纪检体制改革的相关制度文件并抓好贯彻落实", "年底前制定有1项以上配套制度文件");
}
private static void addExampleData(String category, String subCategory, String detailCategory, String content) {
JSONObject obj = new JSONObject();
obj.put("category", category);
obj.put("subCategory", subCategory);
obj.put("detailCategory", detailCategory);
obj.put("content", content);
obj.put("executionStatus", "");
obj.put("workPaperIndex", "[\"实际存在的完整文件名1||FileUrl1\", \"实际存在的完整文件名2||FileUrl2\", \"...\"]");
// obj.put("workPaperIndex", "[\"实际存在的完整FileId1\", \"实际存在的完整FileId2\", \"...\"]");
FIXED_ORDER_EXAMPLE_DATA.add(obj);
}
/**
* 获取所有固定顺序的示例数据
*/
public static List<JSONObject> getFixedOrderExampleData() {
return new ArrayList<>(FIXED_ORDER_EXAMPLE_DATA);
}
/**
* 获取指定子类的示例数据
*/
public static JSONArray getExampleDataBySubCategory(String subCategory) {
JSONArray result = new JSONArray();
for (JSONObject example : FIXED_ORDER_EXAMPLE_DATA) {
if (subCategory.equals(example.getString("subCategory"))) {
result.add(example);
}
}
return result;
}
/**
* 获取固定顺序的内容列表
*/
public static List<String> getFixedOrderContentList() {
List<String> contentList = new ArrayList<>();
for (JSONObject example : FIXED_ORDER_EXAMPLE_DATA) {
contentList.add(example.getString("content"));
}
return contentList;
}
/**
* 获取内容在固定顺序中的索引
*/
public static int getContentFixedOrderIndex(String content) {
List<String> fixedOrder = getFixedOrderContentList();
int index = fixedOrder.indexOf(content);
return index != -1 ? index : Integer.MAX_VALUE;
}
/**
* 获取所有子类列表(包括所有大类的子类)
*/
public static List<String> getAllSubCategories() {
List<String> allSubCategories = new ArrayList<>();
for (List<String> subCategories : CATEGORY_SUBCATEGORY_MAP.values()) {
allSubCategories.addAll(subCategories);
}
return allSubCategories;
}
// 大类顺序 - 用于排序
public static final List<String> CATEGORY_ORDER = Arrays.asList(
CATEGORY_TARGET_RESPONSIBILITY,
CATEGORY_INSPECTION_RECTIFICATION,
CATEGORY_DISCIPLINE_REFORM
);
// 大类描述
public static final Map<String, String> CATEGORY_DESCRIPTIONS = new HashMap<>();
static {
CATEGORY_DESCRIPTIONS.put(CATEGORY_TARGET_RESPONSIBILITY, "落实党风廉政建设主体责任和监督责任");
CATEGORY_DESCRIPTIONS.put(CATEGORY_INSPECTION_RECTIFICATION, "巡视反馈问题的整改落实情况");
CATEGORY_DESCRIPTIONS.put(CATEGORY_DISCIPLINE_REFORM, "深化纪律检查体制改革工作情况");
}
// 子类描述
public static final Map<String, String> SUBCATEGORY_DESCRIPTIONS = new HashMap<>();
static {
SUBCATEGORY_DESCRIPTIONS.put(SUBCATEGORY_MAIN_RESPONSIBILITY, "党委主体责任和纪委监督责任落实情况");
SUBCATEGORY_DESCRIPTIONS.put(SUBCATEGORY_EIGHT_REGULATIONS, "中央八项规定精神落实情况");
SUBCATEGORY_DESCRIPTIONS.put(SUBCATEGORY_ANTI_CORRUPTION, "查处群众身边腐败问题工作情况");
SUBCATEGORY_DESCRIPTIONS.put(SUBCATEGORY_DISCIPLINE_ENFORCEMENT, "纪律执行和政令畅通情况");
SUBCATEGORY_DESCRIPTIONS.put(SUBCATEGORY_MONTHLY_REPORT, "巡视整改月报告制度执行情况");
SUBCATEGORY_DESCRIPTIONS.put(SUBCATEGORY_RECTIFICATION_TASK, "巡视整改任务完成情况");
SUBCATEGORY_DESCRIPTIONS.put(SUBCATEGORY_RECTIFICATION_ACCOUNTABILITY, "巡视整改责任追究情况");
SUBCATEGORY_DESCRIPTIONS.put(SUBCATEGORY_THREE_TURNS, "纪检机构转职能、转方式、转作风工作情况");
SUBCATEGORY_DESCRIPTIONS.put(SUBCATEGORY_SYSTEM_CONSTRUCTION, "纪检体制改革制度建设情况");
}
// 执行状态选项
public static final String STATUS_IMPLEMENTED = "已落实";
public static final String STATUS_PARTIALLY_IMPLEMENTED = "部分落实";
public static final String STATUS_NOT_IMPLEMENTED = "未落实";
public static final String STATUS_NOT_APPLICABLE = "不适用";
// 关键词权重
public static final Map<String, Integer> KEYWORD_WEIGHTS = new HashMap<>();
static {
KEYWORD_WEIGHTS.put("党风廉政建设", 10);
KEYWORD_WEIGHTS.put("主体责任", 9);
KEYWORD_WEIGHTS.put("监督责任", 9);
KEYWORD_WEIGHTS.put("中央八项规定", 8);
KEYWORD_WEIGHTS.put("廉洁从业", 8);
KEYWORD_WEIGHTS.put("巡视整改", 7);
KEYWORD_WEIGHTS.put("纪律检查", 7);
KEYWORD_WEIGHTS.put("廉政谈话", 6);
KEYWORD_WEIGHTS.put("一案双查", 6);
KEYWORD_WEIGHTS.put("四风", 5);
KEYWORD_WEIGHTS.put("腐败", 5);
}
// 工作底稿关键词
public static final Map<String, String> WORK_PAPER_KEYWORDS = new HashMap<>();
static {
WORK_PAPER_KEYWORDS.put("会议纪要", "党委会议纪要、党风廉政建设专题会议纪要");
WORK_PAPER_KEYWORDS.put("责任清单", "党风廉政建设责任清单、主体责任清单");
WORK_PAPER_KEYWORDS.put("检查报告", "党风廉政建设检查报告、巡视整改报告");
WORK_PAPER_KEYWORDS.put("谈话记录", "廉政谈话记录、提醒谈话记录");
WORK_PAPER_KEYWORDS.put("制度文件", "党风廉政建设制度、廉洁从业规定");
WORK_PAPER_KEYWORDS.put("审批文件", "津补贴审批文件、车辆配备审批");
WORK_PAPER_KEYWORDS.put("举报材料", "信访举报材料、问题线索登记");
}
/**
* 对廉政情况数据进行排序提供给ServiceImpl使用
*/
public static void sortPartyConductData(JSONArray data) {
if (data == null || data.isEmpty()) {
return;
}
// 转换为List进行排序
List<JSONObject> dataList = new ArrayList<>();
for (int i = 0; i < data.size(); i++) {
dataList.add(data.getJSONObject(i));
}
// 排序:优先按固定顺序,其次按类别
dataList.sort(AuditContent10PartyConductConstants::compareJSONObject);
// 清空原数组并添加排序后的数据
data.clear();
data.addAll(dataList);
}
/**
* 比较两个JSON对象的排序
*/
public static int compareJSONObject(JSONObject o1, JSONObject o2) {
String content1 = o1.getString("content");
String content2 = o2.getString("content");
// 1. 按固定顺序排序
int index1 = getContentFixedOrderIndex(content1);
int index2 = getContentFixedOrderIndex(content2);
if (index1 != index2) {
return Integer.compare(index1, index2);
}
// 2. 如果都不在固定顺序中,按类别排序
return compareByCategory(o1, o2);
}
/**
* 按照大类、子类、小类排序
*/
public static int compareByCategory(JSONObject o1, JSONObject o2) {
// 清理子类字符串用于比较
String cleanSubCategory1 = cleanSubCategory(o1.getString("subCategory"));
String cleanSubCategory2 = cleanSubCategory(o2.getString("subCategory"));
// 1. 按大类排序
String category1 = o1.getString("category");
String category2 = o2.getString("category");
int categoryIndex1 = CATEGORY_ORDER.indexOf(category1);
int categoryIndex2 = CATEGORY_ORDER.indexOf(category2);
if (categoryIndex1 != categoryIndex2) {
return Integer.compare(categoryIndex1, categoryIndex2);
}
// 2. 按子类排序
String subCategory1 = o1.getString("subCategory");
String subCategory2 = o2.getString("subCategory");
List<String> subCategories = CATEGORY_SUBCATEGORY_MAP.get(category1);
if (subCategories != null) {
int subCategoryIndex1 = subCategories.indexOf(subCategory1);
int subCategoryIndex2 = subCategories.indexOf(subCategory2);
if (subCategoryIndex1 != subCategoryIndex2) {
return Integer.compare(subCategoryIndex1, subCategoryIndex2);
}
}
// 3. 按小类排序
String detailCategory1 = o1.getString("detailCategory");
String detailCategory2 = o2.getString("detailCategory");
List<String> detailCategories = SUBCATEGORY_DETAIL_MAP.get(subCategory1);
if (detailCategories != null) {
int detailCategoryIndex1 = detailCategories.indexOf(detailCategory1);
int detailCategoryIndex2 = detailCategories.indexOf(detailCategory2);
if (detailCategoryIndex1 != detailCategoryIndex2) {
return Integer.compare(detailCategoryIndex1, detailCategoryIndex2);
}
}
// 4. 如果小类也相同,按内容排序
String content1 = o1.getString("content");
String content2 = o2.getString("content");
return content1.compareTo(content2);
}
private static String cleanSubCategory(String subCategory) {
if (subCategory == null) return "";
if (subCategory.contains(" - ")) {
return subCategory.split(" - ")[0].trim();
}
return subCategory;
}
/**
* 获取指定子类的示例数据JSON字符串
*/
public static String getExampleDataJsonString(String subCategory) {
JSONArray exampleData = getExampleDataBySubCategory(subCategory);
if (exampleData == null || exampleData.isEmpty()) {
return "[]";
}
// 直接使用FastJSON的序列化确保正确转义即可
return exampleData.toJSONString();
}
private AuditContent10PartyConductConstants() {
// 防止实例化
}
}

View File

@@ -0,0 +1,90 @@
package com.gxwebsoft.ai.constants;
import java.util.HashMap;
import java.util.Map;
/**
* 审计内容11-历史审计问题整改常量类
*/
public class AuditContent11HistoryConstants {
// 审计类型分类
public static final String AUDIT_TYPE_INTERNAL = "内部审计";
public static final String AUDIT_TYPE_EXTERNAL = "外部审计";
public static final String AUDIT_TYPE_SPECIAL = "专项审计";
public static final String AUDIT_TYPE_ECONOMIC = "经济责任审计";
// 整改状态
public static final String STATUS_COMPLETED = "已完成";
public static final String STATUS_IN_PROGRESS = "整改中";
public static final String STATUS_NOT_STARTED = "未整改";
public static final String STATUS_PARTIAL = "部分整改";
// 审计重点分类
public static final String FOCUS_SYSTEM_MECHANISM = "制度机制建立情况";
public static final String FOCUS_HISTORICAL_ISSUES = "历史遗留问题处理";
public static final String FOCUS_RECTIFICATION_EFFECT = "整改数量及效果";
public static final String FOCUS_SYSTEM_IMPROVEMENT = "制度完善情况";
public static final String FOCUS_SELF_RECTIFICATION = "自行发现整改情况";
// 审计方法关键词
public static final String METHOD_REVIEW_REPORT = "审阅审计报告";
public static final String METHOD_REVIEW_RECTIFICATION = "审阅整改报告";
public static final String METHOD_VERIFY_RECTIFICATION = "核实整改情况";
public static final String METHOD_INTERVIEW = "个别访谈";
public static final String METHOD_REVIEW_DOCS = "查阅相关资料";
// 分类描述
public static final Map<String, String> FOCUS_DESCRIPTIONS = new HashMap<>();
static {
FOCUS_DESCRIPTIONS.put(FOCUS_SYSTEM_MECHANISM, "是否有处理历史遗留问题的制度机制");
FOCUS_DESCRIPTIONS.put(FOCUS_HISTORICAL_ISSUES, "任期内是否有处理非任期的历史遗留问题");
FOCUS_DESCRIPTIONS.put(FOCUS_RECTIFICATION_EFFECT, "对历次审计检查发现的问题整改的数量及效果");
FOCUS_DESCRIPTIONS.put(FOCUS_SYSTEM_IMPROVEMENT, "历次审计检查发现问题后是否有完善相关制度");
FOCUS_DESCRIPTIONS.put(FOCUS_SELF_RECTIFICATION, "历次审计没有发现的问题是否自行发现并整改完善");
}
// 审计方法描述
public static final Map<String, String> METHOD_DESCRIPTIONS = new HashMap<>();
static {
METHOD_DESCRIPTIONS.put(METHOD_REVIEW_REPORT, "审阅任职期间审计报告");
METHOD_DESCRIPTIONS.put(METHOD_REVIEW_RECTIFICATION, "审阅整改情况报告");
METHOD_DESCRIPTIONS.put(METHOD_VERIFY_RECTIFICATION, "对提出问题整改情况逐一进行核实");
METHOD_DESCRIPTIONS.put(METHOD_INTERVIEW, "通过个别访谈了解情况");
METHOD_DESCRIPTIONS.put(METHOD_REVIEW_DOCS, "查阅相关资料了解单位存在的历年遗留问题和处理情况");
}
// 关键词权重(用于知识检索排序)
public static final Map<String, Integer> KEYWORD_WEIGHTS = new HashMap<>();
static {
KEYWORD_WEIGHTS.put("审计发现问题", 10);
KEYWORD_WEIGHTS.put("问题整改", 9);
KEYWORD_WEIGHTS.put("整改情况", 9);
KEYWORD_WEIGHTS.put("整改报告", 8);
KEYWORD_WEIGHTS.put("审计报告", 8);
KEYWORD_WEIGHTS.put("历史遗留问题", 9);
KEYWORD_WEIGHTS.put("制度机制", 7);
KEYWORD_WEIGHTS.put("整改措施", 7);
KEYWORD_WEIGHTS.put("整改责任人", 6);
KEYWORD_WEIGHTS.put("整改完成", 6);
KEYWORD_WEIGHTS.put("审计年度", 5);
KEYWORD_WEIGHTS.put("审计类型", 5);
KEYWORD_WEIGHTS.put("经济责任审计", 6);
}
// 整改要求常见关键词
public static final String[] RECTIFICATION_REQUIREMENT_KEYWORDS = {
"限期整改", "建立机制", "完善制度", "责任追究", "资金追回",
"规范管理", "加强内控", "落实责任", "建立台账", "跟踪检查"
};
// 整改措施常见关键词
public static final String[] RECTIFICATION_MEASURES_KEYWORDS = {
"修订制度", "完善流程", "加强培训", "调整人员", "资金归还",
"建立台账", "完善手续", "强化监督", "责任追究", "定期检查"
};
private AuditContent11HistoryConstants() {
// 防止实例化
}
}

View File

@@ -98,6 +98,35 @@ public class AuditContent1EightRegConstants {
"简化机场迎送和接待工作。驻外使领馆和其他驻外机构一律不得向代表团赠送礼品,外方所赠礼品应严格按国家有关规定处理。");
}
// 审计建议内容 - 新增的审计建议
public static final Map<String, String> AUDIT_SUGGESTIONS = new HashMap<>();
static {
AUDIT_SUGGESTIONS.put(CATEGORY_RESEARCH,
"如审查后认定:确为缺少系统性规范和调研记录。建议:\n" +
"1.补足制度短板,系统性规范公司层面调研工作管理要求;\n" +
"2.强化过程管理与材料归档,确保调研活动可视、可查、可评,切实发挥服务决策、解决问题的实效。");
AUDIT_SUGGESTIONS.put(CATEGORY_MEETINGS,
"如审查确认被审计单位存在未严格遵循《中央八项规定》中关于'精简会议活动'的规定,可提出审计建议:\n" +
"建议减少不必要的会议数量,提高会议质量和效率,避免因频繁开会而造成人力资源浪费。在召开会议前,应明确会议的具体目的和议题,避免无目标、无计划的会议。");
AUDIT_SUGGESTIONS.put(CATEGORY_VISITS,
"如审查确认被审计单位存在未严格遵循《中央八项规定》中关于'轻车简从''不得扰民'的要求,可提出审计建议:\n" +
"切实规范领导人员公务出行管理,严格贯彻落实'轻车简从''不得扰民'等要求。明确规定考察线路须事前报备、严格控制随员及车辆规模、严禁超标接待与礼仪迎送、严禁使用警车等非必要车辆疏导清场。责立健全常态化监管与问责机制,确保有关规定执行到位,对违规行为严肃追责。");
AUDIT_SUGGESTIONS.put(CATEGORY_GUARD_WORK,
"如审查确认被审计单位存在未严格遵循《中央八项规定》中关于'轻车简从''不得扰民'的要求,可提出审计建议:\n" +
"切实规范领导人员公务出行管理,严格贯彻落实'轻车简从''不得扰民'等要求。明确规定考察线路须事前报备、严格控制随员及车辆规模、严禁超标接待与礼仪迎送、严禁使用警车等非必要车辆疏导清场。责立健全常态化监管与问责机制,确保有关规定执行到位,对违规行为严肃追责。");
AUDIT_SUGGESTIONS.put(CATEGORY_ECONOMY,
"如审查后认定:确为会议活动经费超支。可提出审计建议:\n" +
"强化会议活动经费预算控制,严查支出明细,杜绝超标准住宿餐饮、高消费活动、豪华布置及纪念品发放。\n\n" +
"其他建议:\n" +
"1.各直属企业定期对内部控制情况开展实质性评价,杜绝形式主义。\n" +
"2.上级公司强化对下属企业的监督与检查,保障相关制度有效执行。");
}
// 关键词权重
public static final Map<String, Integer> KEYWORD_WEIGHTS = new HashMap<>();
static {

View File

@@ -14,8 +14,9 @@ public class AuditContent1ExpenseConstants {
public static final String EXPENSE_TYPE_VEHICLE = "公车运行维护";
public static final String EXPENSE_TYPE_MEETING = "会议培训费";
// 年度范围
public static final int[] YEAR_RANGE = {2020, 2021, 2022, 2023};
// 年度范围 - 根据知识库动态确定,这里提供默认起始年份
public static final int DEFAULT_START_YEAR = 2020;
public static final int DEFAULT_END_YEAR = 2023;
// 分类描述
public static final Map<String, String> EXPENSE_DESCRIPTIONS = new HashMap<>();
@@ -26,43 +27,79 @@ public class AuditContent1ExpenseConstants {
EXPENSE_DESCRIPTIONS.put(EXPENSE_TYPE_MEETING, "会议、培训费用支出情况");
}
// 数据格式要求
// 数据格式要求 - 简化版
public static final String DATA_FORMAT_REQUIREMENT =
"每条记录应包含以下字段\n" +
"- expenseType支出类型公务接待/出国/公车运行维护/会议培训费)\n" +
"- year年份2020-2023\n" +
"- finalStatementAmount决算报表数单位\n" +
"- initialBudgetAmount年初预算数单位\n" +
"- changePercentage增减情况%\n" +
"- budgetRatio占年初预算比例%\n" +
"- remark备注信息\n" +
"- dataSource数据来源文件\n" +
"- workPaperIndex相关文件索引";
"请严格按照以下JSON格式生成数据每类支出每个年度至少1条记录总共至少16条记录\n" +
"[\n" +
" {\n" +
" \"expenseType\": \"公务接待/出国/公车运行维护/会议培训费\",\n" +
" \"year\": \"具体年份(根据知识库中的连续四个完整年度)\",\n" +
" \"finalStatementAmount\": \"决算报表数\",\n" +
" \"initialBudgetAmount\": \"年初预算数\",\n" +
" \"changePercentage\": \"增减百分比\",\n" +
" \"budgetRatio\": \"占年初预算比例\",\n" +
" \"remark\": \"备注信息\",\n" +
" \"dataSource\": \"数据来源文件\",\n" +
// " \"workPaperIndex\": [\"FileId1\", \"FileId2\"]\n" +
" \"workPaperIndex\": [\"实际存在的完整文件名1||FileUrl1\", \"实际存在的完整文件名2||FileUrl2\"]\n" +
" }\n" +
"]";
// 关键词权重
// 关键词权重 - 增强工程类排除
public static final Map<String, Integer> KEYWORD_WEIGHTS = new HashMap<>();
static {
KEYWORD_WEIGHTS.put("决算", 10);
KEYWORD_WEIGHTS.put("预算", 10);
KEYWORD_WEIGHTS.put("公务接待", 9);
KEYWORD_WEIGHTS.put("出国", 9);
KEYWORD_WEIGHTS.put("公车", 9);
KEYWORD_WEIGHTS.put("会议", 8);
KEYWORD_WEIGHTS.put("培训", 8);
KEYWORD_WEIGHTS.put("支出", 8);
KEYWORD_WEIGHTS.put("", 7);
// 高优先级:直接支出关键词
KEYWORD_WEIGHTS.put("公务接待", 15);
KEYWORD_WEIGHTS.put("出国", 15);
KEYWORD_WEIGHTS.put("公车运行维护", 15);
KEYWORD_WEIGHTS.put("会议培训费", 15);
KEYWORD_WEIGHTS.put("三公经费", 14);
KEYWORD_WEIGHTS.put("接待费", 13);
KEYWORD_WEIGHTS.put("差旅费", 12);
KEYWORD_WEIGHTS.put("车辆", 12);
KEYWORD_WEIGHTS.put("会务费", 12);
KEYWORD_WEIGHTS.put("培训费", 12);
// 中优先级:财务文档
KEYWORD_WEIGHTS.put("决算报表", 10);
KEYWORD_WEIGHTS.put("预算报表", 10);
KEYWORD_WEIGHTS.put("财务报表", 9);
KEYWORD_WEIGHTS.put("年度报告", 8);
KEYWORD_WEIGHTS.put("部门决算", 9);
KEYWORD_WEIGHTS.put("部门预算", 9);
KEYWORD_WEIGHTS.put("预算执行", 8);
KEYWORD_WEIGHTS.put("财务分析", 7);
// 年份关键词(中等优先级,用于识别年度)
KEYWORD_WEIGHTS.put("年度", 7);
KEYWORD_WEIGHTS.put("年报表", 7);
KEYWORD_WEIGHTS.put("年度决算", 8);
KEYWORD_WEIGHTS.put("年度预算", 8);
// 低优先级:通用财务
KEYWORD_WEIGHTS.put("支出", 7);
KEYWORD_WEIGHTS.put("费用", 6);
KEYWORD_WEIGHTS.put("年度报告", 6);
// 排除工程类(负权重)
KEYWORD_WEIGHTS.put("工程造价", -20);
KEYWORD_WEIGHTS.put("概预算", -20);
KEYWORD_WEIGHTS.put("工程款", -15);
KEYWORD_WEIGHTS.put("施工", -15);
KEYWORD_WEIGHTS.put("项目投资", -15);
KEYWORD_WEIGHTS.put("基建", -15);
}
// 数据来源关键词
public static final String[] DATA_SOURCE_KEYWORDS = {
"决算报表", "预算报表", "财务报告", "年度报告",
"预算执行情况", "经费使用情况", "支出明细", "费用分析"
// 需要排除的工程类关键词
public static final String[] ENGINEERING_EXCLUDE_KEYWORDS = {
"工程造价", "预算", "工程概算", "工程预算", "工程结算",
"施工合同", "工程款", "项目投资", "基建", "工程项目"
};
// 年份正则表达式,用于从知识库中提取年份
public static final String YEAR_PATTERN = "20\\d{2}";
// 最近几年范围(用于查询构建)
public static final int RECENT_YEARS_COUNT = 4;
private AuditContent1ExpenseConstants() {
// 防止实例化
}

View File

@@ -32,7 +32,8 @@ public class AuditContent1LeaderListConstants {
"- tenurePeriod任职期间格式YYYY.MM-YYYY.MM\n" +
"- mainResponsibilities主要工作责任\n" +
"- remark备注信息\n" +
"- workPaperIndex相关文件索引";
// "- workPaperIndex[相关文件FileId]";
"- workPaperIndex[\"实际存在的完整文件名1||FileUrl1\"]";
// 关键词权重
public static final Map<String, Integer> KEYWORD_WEIGHTS = new HashMap<>();

View File

@@ -0,0 +1,194 @@
package com.gxwebsoft.ai.constants;
import java.util.*;
/**
* 审计内容2-单位发展战略执行常量类
* 基于五大发展理念优化为5个分类
*/
public class AuditContent2StrategyConstants {
// 分类定义 - 基于五大发展理念优化为5个分类
public static final String CATEGORY_GOVERNANCE_REFORM = "法人治理与改革创新";
public static final String CATEGORY_DEVELOPMENT_STRATEGY = "发展规划与协调推进";
public static final String CATEGORY_RISK_PREVENTION = "风险防控与绿色发展";
public static final String CATEGORY_SOCIAL_ENVIRONMENTAL = "社会责任与开放共享";
public static final String CATEGORY_PERFORMANCE_ASSESSMENT = "绩效考核与创新发展";
// 分类顺序
public static final List<String> CATEGORY_ORDER = Arrays.asList(
CATEGORY_GOVERNANCE_REFORM,
CATEGORY_DEVELOPMENT_STRATEGY,
CATEGORY_RISK_PREVENTION,
CATEGORY_SOCIAL_ENVIRONMENTAL,
CATEGORY_PERFORMANCE_ASSESSMENT
);
// 分类描述(对应五大发展理念)
public static final Map<String, String> CATEGORY_DESCRIPTIONS = new HashMap<>();
static {
CATEGORY_DESCRIPTIONS.put(CATEGORY_GOVERNANCE_REFORM,
"公司法人治理结构、薪酬制度改革、国有资产管理体制等改革创新情况");
CATEGORY_DESCRIPTIONS.put(CATEGORY_DEVELOPMENT_STRATEGY,
"单位重要发展规划和政策措施的制定、执行和效果等协调发展情况");
CATEGORY_DESCRIPTIONS.put(CATEGORY_RISK_PREVENTION,
"金融业务风险、债务风险防控、污染防治等绿色发展情况");
CATEGORY_DESCRIPTIONS.put(CATEGORY_SOCIAL_ENVIRONMENTAL,
"精准扶贫、环境保护等社会责任履行和开放共享情况");
CATEGORY_DESCRIPTIONS.put(CATEGORY_PERFORMANCE_ASSESSMENT,
"各项考核指标完成情况的真实性、准确性等创新发展情况");
}
// 分类与五大发展理念对应关系
public static final Map<String, String> CATEGORY_DEVELOPMENT_CONCEPT = new HashMap<>();
static {
CATEGORY_DEVELOPMENT_CONCEPT.put(CATEGORY_GOVERNANCE_REFORM, "创新");
CATEGORY_DEVELOPMENT_CONCEPT.put(CATEGORY_DEVELOPMENT_STRATEGY, "协调");
CATEGORY_DEVELOPMENT_CONCEPT.put(CATEGORY_RISK_PREVENTION, "绿色");
CATEGORY_DEVELOPMENT_CONCEPT.put(CATEGORY_SOCIAL_ENVIRONMENTAL, "开放共享");
CATEGORY_DEVELOPMENT_CONCEPT.put(CATEGORY_PERFORMANCE_ASSESSMENT, "创新");
}
// 分类查询关键词
public static final Map<String, List<String>> CATEGORY_QUERIES = new HashMap<>();
static {
CATEGORY_QUERIES.put(CATEGORY_GOVERNANCE_REFORM,
Arrays.asList("法人治理 薪酬改革 国有资产管理", "改革创新 治理结构 董事会"));
CATEGORY_QUERIES.put(CATEGORY_DEVELOPMENT_STRATEGY,
Arrays.asList("混合所有制 剥离办社会职能 改革措施", "协调发展 改革方案 政策落实"));
CATEGORY_QUERIES.put(CATEGORY_RISK_PREVENTION,
Arrays.asList("发展规划 金融风险 债务风险", "绿色发展 风险防控 资产负债率"));
CATEGORY_QUERIES.put(CATEGORY_SOCIAL_ENVIRONMENTAL,
Arrays.asList("精准扶贫 污染防治 环境保护", "开放共享 社会责任 定点扶贫"));
CATEGORY_QUERIES.put(CATEGORY_PERFORMANCE_ASSESSMENT,
Arrays.asList("考核指标 经营业绩 目标责任", "创新发展 数据核实 完成情况"));
}
// 完整的审计框架原Excel内容
public static final String AUDIT_FRAMEWORK =
"审计内容框架:\n" +
"1. 公司法人治理结构建立健全情况。是否贯彻落实将党组织研究讨论作为董事会、经理层决策重大问题前置程序的要求;是否加强董事会建设、有效落实董事会职权;各治理主体是否职责明确、落实到位。\n" +
"2. 薪酬制度改革情况。薪酬分配差异化改革过程中是否存在进展不平衡、政策不配套、任务不协调等问题;有无超工资总额列支工资性支出;企业领导人员在核定的年度薪酬之外领取报酬,是否严格规范履职待遇、业务支出,有无将公款用于个人支出等问题。\n" +
"3. 完善国有资产管理体制方面。有关部门是否建立健全监管权力清单和责任清单,是否存在越位、缺位、不到位等问题;国有资本投资、运营公司改革试点工作的情况,有无要求方案部署不够明确、资本授权及经营资质受限、相关企业未制定时间表路线图、未与兼并重组等改革试点任务协同推进、资本运营偏离改革方向、战略性前瞻性产业投资不增反降、党政机关和事业单位所属企业的国有资本纳入经营性国有资产集中统一监管体系推进迟缓、国有资本经营预算管理不到位等问题。\n" +
"4. 发展混合所有制经济方面。是否存在\"混而不改\",改革流于形式、效果不佳的问题;清产核资、评估定价、转让交易、登记确权等相关政策、审批和实施程序是否合法合规,在国有资产和产权转让过程中是否存在国有资产流失等问题;员工持股试点推进过程中存在的政策性障碍。此外,还要从国有企业改革工作总休上关注,混合所有制改革作为国有企业改革的重要突破口的作用发挥情况。\n" +
"5. 剥离办社会职能和解决历史遗留问题方面。国有企业有无制定时间表路线图,是否按时限完成国有企业职工家属区\"三供一业\"分离移交,剥离国有企业办医疗、教育等公共服务机构,对国有企业退休人员实行社会化管理,推进厂办大集体改革等问题,遇到什么困难、需要什么政策和多少资金支持,等等;相关部门的配套政策是否建立健全。\n" +
"6. 国有企业改革措施是否制定?制定的措施是否符合党中央、国务院、省市的相关文件规定和精神。\n" +
"7. 企业年度工作报告中关于改革措施的落实情况,进度是否符合预期,是否违反整体改革措施计划。规划执行情况材料是否合规、完整。企业境外资产、投资管理办法和内控制度,及企业向国资委等有关部门报送的境外资产产权登记情况和境外资产财务报表数据等,是否合规、完整、符合企业实际情况。企业制定的公司发展规划,包括总规划和专项规划(如主业、国际化、金融、财务、人力资源、建设、生产、营销、科技、信息化、安全应急、企业文化等),是否符合企业整体实际情况,是否符合党中央、国务院、省市的相关文件规定和精神。公司发展规划滚动调整情况是否符合实际情况,是否为了减轻企业目标故意调整。公司发展规划中提及的制定依据,是否符合国家有关部门制定的行业产业发展规划等。\n" +
"8. 金融业务风险。关注金融业务服务实体经济和主业发展情况,有无脱实向虚、通过金融产品将资金违规投向房地产、地方政府融资平台、产能过剩等限制或禁止领域的问题;关注企业开展境外金融衍生品情况,有无违规开展业务造成重大损失或损失风险等;关注银行、证券、保险、信托等金融子企业的资产管理规模及经营情况,风险管控机制是否健全,业务运营是否合规,有无信贷资金、金融资产造成重大损失的问题,有无金融产品逾期或违规展期、不良资产比率较高、风险与收益不匹配、本金偿付风险或违约风险大等问题;关注企业债券发行、委托理财、对外担保等金融业务开展中存在的突出问题,是否造成重大损失或损失风险等。\n" +
"9. 债务风险。关注企业落实降杠杆减负债政策情况,是否存在企业资产负债率居高不下、超过警戒线或管控线甚至资不抵债,有无建立健全企业债务风险防控机制,发挥资产负债约束机制作用,债务结构是否合理,有无违规对不符合国家产业政策的企业实施债转股,有无违规通过\"名股实债\"等方式变相举债或形成重大隐性债务,以及虚假去杠杆等问题。\n" +
"10. 精准扶贫政策落实情况。关注企业在精准扶贫相关政策落实、项目安排、资金使用等方面的推进情况,是否落实企业定点扶贫工作的任务要求,有无出台具体帮扶措施,履行帮扶责任定点扶贫的目标对象、工作举措、资金使用等是否精准;有无通过发展产业、对接市场、安置就业等多种方式开展精准扶贫行动;以中央企业贫困地区产业投资基金、贫困地区产业发展基金等为代表的央企产业扶贫基金出资额是否及时足额缴纳、有无大量资金闲置和项目运营效果不佳等问题。\n" +
"11. 污染防治工作推进情况。企业贯彻落实生态环境保护和环境污染防治相关政策措施情况,重点是打蹴蓝天保卫战、打好碧水保卫战和推进净土保卫战等相关措施的落实情况。是否存在非法占地、违规改变土地使用条件、倒卖土地、土地闲置的问题;企业是否完成国家节能减排任务目标,有无不顾生态环境盲目决策和建设项目,造成重大环境污染和资源损毁等问题;有无违规偷排、漏排、超排废渣废液废气,瞒报、漏报检测数据,有无违规堆放、未按规定处理工业危险废弃物、危险化学品等问题;对所属企业发生的破坏生态环境情况,是否存在追责问责不到位等问题。企业是否建立能源消耗及污染物排放统计台账;是否按时定期将本企业节能减排汇总报表和总结分析报告报送有关部门,有无漏报、迟报、不按要求报送;重点类、关注类企业是否在总结分析报告中开展与同行业节能减排技术指标的对标和分析。\n" +
"12. 对照国资委、财政部、工业和信息化部等与企业签订的年度经营业绩责任书、任期经营业绩责任书、中央单位定点扶贫工作责任书等,梳理企业承担的考核内容和指标。\n" +
"13. 对于可以量化的审计事项,利用大数据分析方法,系统收集和整理各类考核指标信息,建立企业考核指标数据库,对照企业提供的财务或相关统计报表,检查企业完成情况。检查相关指标的原始数据、计算方法、计算过程,核实其真实性和准确性,对于依靠人工填报、设置调整系数、与以往年度相差较大或与考核值相差较小的数据,重点审计真实性、完整性、准确性。\n";
// 审计目标说明
public static final String AUDIT_OBJECTIVE =
"审计目标:检查被审计领导干部任职期间在" +
"创新、协调、绿色、开放、共享五大发展理念指引下," +
"合法合规制定本部门发展规划和发展思路," +
"推动规划和政策措施实施的时间表、路线图及其执行效果。";
// 分类与审计框架片段的映射
public static final Map<String, String> CATEGORY_AUDIT_FRAMEWORK_FRAGMENTS = new HashMap<>();
static {
CATEGORY_AUDIT_FRAMEWORK_FRAGMENTS.put(CATEGORY_GOVERNANCE_REFORM,
"审计内容框架(法人治理与改革创新相关):\n" +
"1. 公司法人治理结构建立健全情况。是否贯彻落实将党组织研究讨论作为董事会、经理层决策重大问题前置程序的要求;是否加强董事会建设、有效落实董事会职权;各治理主体是否职责明确、落实到位。\n" +
"2. 薪酬制度改革情况。薪酬分配差异化改革过程中是否存在进展不平衡、政策不配套、任务不协调等问题;有无超工资总额列支工资性支出;企业领导人员在核定的年度薪酬之外领取报酬,是否严格规范履职待遇、业务支出,有无将公款用于个人支出等问题。\n" +
"3. 完善国有资产管理体制方面。有关部门是否建立健全监管权力清单和责任清单,是否存在越位、缺位、不到位等问题;国有资本投资、运营公司改革试点工作的情况,有无要求方案部署不够明确、资本授权及经营资质受限、相关企业未制定时间表路线图、未与兼并重组等改革试点任务协同推进、资本运营偏离改革方向、战略性前瞻性产业投资不增反降、党政机关和事业单位所属企业的国有资本纳入经营性国有资产集中统一监管体系推进迟缓、国有资本经营预算管理不到位等问题。\n");
CATEGORY_AUDIT_FRAMEWORK_FRAGMENTS.put(CATEGORY_DEVELOPMENT_STRATEGY,
"审计内容框架(发展规划与协调推进相关):\n" +
"4. 发展混合所有制经济方面。是否存在\"混而不改\",改革流于形式、效果不佳的问题;清产核资、评估定价、转让交易、登记确权等相关政策、审批和实施程序是否合法合规,在国有资产和产权转让过程中是否存在国有资产流失等问题;员工持股试点推进过程中存在的政策性障碍。此外,还要从国有企业改革工作总休上关注,混合所有制改革作为国有企业改革的重要突破口的作用发挥情况。\n" +
"5. 剥离办社会职能和解决历史遗留问题方面。国有企业有无制定时间表路线图,是否按时限完成国有企业职工家属区\"三供一业\"分离移交,剥离国有企业办医疗、教育等公共服务机构,对国有企业退休人员实行社会化管理,推进厂办大集体改革等问题,遇到什么困难、需要什么政策和多少资金支持,等等;相关部门的配套政策是否建立健全。\n" +
"6. 国有企业改革措施是否制定?制定的措施是否符合党中央、国务院、省市的相关文件规定和精神。\n");
CATEGORY_AUDIT_FRAMEWORK_FRAGMENTS.put(CATEGORY_RISK_PREVENTION,
"审计内容框架(风险防控与绿色发展相关):\n" +
"7. 企业年度工作报告中关于改革措施的落实情况,进度是否符合预期,是否违反整体改革措施计划。规划执行情况材料是否合规、完整。企业境外资产、投资管理办法和内控制度,及企业向国资委等有关部门报送的境外资产产权登记情况和境外资产财务报表数据等,是否合规、完整、符合企业实际情况。企业制定的公司发展规划,包括总规划和专项规划(如主业、国际化、金融、财务、人力资源、建设、生产、营销、科技、信息化、安全应急、企业文化等),是否符合企业整体实际情况,是否符合党中央、国务院、省市的相关文件规定和精神。公司发展规划滚动调整情况是否符合实际情况,是否为了减轻企业目标故意调整。公司发展规划中提及的制定依据,是否符合国家有关部门制定的行业产业发展规划等。\n" +
"8. 金融业务风险。关注金融业务服务实体经济和主业发展情况,有无脱实向虚、通过金融产品将资金违规投向房地产、地方政府融资平台、产能过剩等限制或禁止领域的问题;关注企业开展境外金融衍生品情况,有无违规开展业务造成重大损失或损失风险等;关注银行、证券、保险、信托等金融子企业的资产管理规模及经营情况,风险管控机制是否健全,业务运营是否合规,有无信贷资金、金融资产造成重大损失的问题,有无金融产品逾期或违规展期、不良资产比率较高、风险与收益不匹配、本金偿付风险或违约风险大等问题;关注企业债券发行、委托理财、对外担保等金融业务开展中存在的突出问题,是否造成重大损失或损失风险等。\n" +
"9. 债务风险。关注企业落实降杠杆减负债政策情况,是否存在企业资产负债率居高不下、超过警戒线或管控线甚至资不抵债,有无建立健全企业债务风险防控机制,发挥资产负债约束机制作用,债务结构是否合理,有无违规对不符合国家产业政策的企业实施债转股,有无违规通过\"名股实债\"等方式变相举债或形成重大隐性债务,以及虚假去杠杆等问题。\n");
CATEGORY_AUDIT_FRAMEWORK_FRAGMENTS.put(CATEGORY_SOCIAL_ENVIRONMENTAL,
"审计内容框架(社会责任与开放共享相关):\n" +
"10. 精准扶贫政策落实情况。关注企业在精准扶贫相关政策落实、项目安排、资金使用等方面的推进情况,是否落实企业定点扶贫工作的任务要求,有无出台具体帮扶措施,履行帮扶责任定点扶贫的目标对象、工作举措、资金使用等是否精准;有无通过发展产业、对接市场、安置就业等多种方式开展精准扶贫行动;以中央企业贫困地区产业投资基金、贫困地区产业发展基金等为代表的央企产业扶贫基金出资额是否及时足额缴纳、有无大量资金闲置和项目运营效果不佳等问题。\n" +
"11. 污染防治工作推进情况。企业贯彻落实生态环境保护和环境污染防治相关政策措施情况,重点是打蹴蓝天保卫战、打好碧水保卫战和推进净土保卫战等相关措施的落实情况。是否存在非法占地、违规改变土地使用条件、倒卖土地、土地闲置的问题;企业是否完成国家节能减排任务目标,有无不顾生态环境盲目决策和建设项目,造成重大环境污染和资源损毁等问题;有无违规偷排、漏排、超排废渣废液废气,瞒报、漏报检测数据,有无违规堆放、未按规定处理工业危险废弃物、危险化学品等问题;对所属企业发生的破坏生态环境情况,是否存在追责问责不到位等问题。企业是否建立能源消耗及污染物排放统计台账;是否按时定期将本企业节能减排汇总报表和总结分析报告报送有关部门,有无漏报、迟报、不按要求报送;重点类、关注类企业是否在总结分析报告中开展与同行业节能减排技术指标的对标和分析。\n");
CATEGORY_AUDIT_FRAMEWORK_FRAGMENTS.put(CATEGORY_PERFORMANCE_ASSESSMENT,
"审计内容框架(绩效考核与创新发展相关):\n" +
"12. 对照国资委、财政部、工业和信息化部等与企业签订的年度经营业绩责任书、任期经营业绩责任书、中央单位定点扶贫工作责任书等,梳理企业承担的考核内容和指标。\n" +
"13. 对于可以量化的审计事项,利用大数据分析方法,系统收集和整理各类考核指标信息,建立企业考核指标数据库,对照企业提供的财务或相关统计报表,检查企业完成情况。检查相关指标的原始数据、计算方法、计算过程,核实其真实性和准确性,对于依靠人工填报、设置调整系数、与以往年度相差较大或与考核值相差较小的数据,重点审计真实性、完整性、准确性。\n");
}
// 获取分类的简要审计框架概述
public static String getBriefAuditFrameworkForCategory(String category) {
switch (category) {
case CATEGORY_GOVERNANCE_REFORM:
return "重点审计:法人治理结构、薪酬改革、国有资产管理等改革创新情况(创新理念)";
case CATEGORY_DEVELOPMENT_STRATEGY:
return "重点审计:混合所有制改革、剥离办社会职能、改革措施制定等协调发展情况(协调理念)";
case CATEGORY_RISK_PREVENTION:
return "重点审计:发展规划执行、金融业务风险、债务风险等绿色发展情况(绿色理念)";
case CATEGORY_SOCIAL_ENVIRONMENTAL:
return "重点审计:精准扶贫、污染防治等社会责任履行情况(开放共享理念)";
case CATEGORY_PERFORMANCE_ASSESSMENT:
return "重点审计:考核指标完成情况的真实性、准确性等创新发展情况(创新理念)";
default:
return "审计单位发展战略执行情况";
}
}
// 审计工作原则
public static final String AUDIT_PRINCIPLES =
"审计工作原则:\n" +
"1. 基于审计框架,结合企业实际情况生成具体审计内容\n" +
"2. 审计内容要具体可操作,避免笼统描述\n" +
"3. 检查证据要真实具体,有文件依据\n" +
"4. 测试结果判定要严格,有充分依据\n" +
"5. 工作底稿索引要准确对应实际文件\n" +
"6. 注重评估五大发展理念贯彻情况\n" +
"7. 必须深入分析实际执行情况(结果),重点检查:\n" +
" (1) 是否有会议纪要等材料证明决策按照党组织委员会→公司领导班子→董事会逐级落实;\n" +
" (2) 是否有相应材料对执行内容进行说明和证明,展示具体的执行过程和执行效果。";
// 关键词权重
public static final Map<String, Integer> KEYWORD_WEIGHTS = new HashMap<>();
static {
// 创新类关键词
KEYWORD_WEIGHTS.put("法人治理", 10);
KEYWORD_WEIGHTS.put("薪酬改革", 9);
KEYWORD_WEIGHTS.put("改革创新", 9);
KEYWORD_WEIGHTS.put("混合所有制", 9);
// 协调类关键词
KEYWORD_WEIGHTS.put("发展规划", 10);
KEYWORD_WEIGHTS.put("协调发展", 8);
KEYWORD_WEIGHTS.put("改革措施", 8);
// 绿色类关键词
KEYWORD_WEIGHTS.put("金融风险", 9);
KEYWORD_WEIGHTS.put("债务风险", 9);
KEYWORD_WEIGHTS.put("资产负债率", 8);
KEYWORD_WEIGHTS.put("污染防治", 8);
// 开放共享类关键词
KEYWORD_WEIGHTS.put("精准扶贫", 9);
KEYWORD_WEIGHTS.put("环境保护", 8);
KEYWORD_WEIGHTS.put("社会责任", 8);
// 通用关键词
KEYWORD_WEIGHTS.put("发展战略", 10);
KEYWORD_WEIGHTS.put("考核指标", 8);
KEYWORD_WEIGHTS.put("年度报告", 7);
KEYWORD_WEIGHTS.put("工作底稿", 6);
KEYWORD_WEIGHTS.put("审计证据", 6);
}
// 各知识源检索限制
public static final Map<String, Integer> SOURCE_LIMITS = new HashMap<>();
static {
SOURCE_LIMITS.put("enterprise", 120);
SOURCE_LIMITS.put("regulation", 60);
SOURCE_LIMITS.put("auditCase", 40);
}
}

View File

@@ -0,0 +1,151 @@
package com.gxwebsoft.ai.constants;
import java.util.*;
/**
* 审计内容4-目标责任制完成情况常量类
* 审计目标:检查被审计领导干部任职期间目标责任制的完成情况
*/
public class AuditContent4TargetConstants {
// 分类定义
public static final String CATEGORY_TARGET_RESPONSIBILITY = "目标责任制完成情况";
// 审计框架核心基于Excel内容优化
public static final String AUDIT_FRAMEWORK =
"审计核心:检查目标责任制的制定、执行和完成情况\n\n" +
"重点关注:\n" +
"1. 对照被审计人所在单位的职责和主要业务\n" +
"2. 上级主管部门是否规定有目标责任\n" +
"3. 单位是否制定有目标责任\n" +
"4. 检查审计目标责任的完成情况\n\n" +
"审计方法及步骤:\n" +
"1. 审阅上级主管部门下达或单位自定的目标责任制,对照完成情况,检查目标责任制的落实效果\n" +
"2. 主要以单位自定的目标任务为衡量标准\n" +
"3. 对已完成任务的部分,检查是否真实完成\n" +
"4. 对未完成任务的部分,检查未完成的原因\n\n" +
"特别说明:\n" +
"1. 如果企业没有制定单位自定的目标责任制,请填写\"企业未制定年度目标计划\"\n" +
"2. 如果知识库中没有单位自定目标的信息,请根据企业实际情况推断可能的计划内容\n" +
"3. 单位自定目标应包括:年度工作计划、部门工作目标、绩效考核指标等";
// 审计目标
public static final String AUDIT_OBJECTIVE =
"检查目标责任制的制定、执行和完成情况,评估落实效果和完成质量。";
// 审计工作原则
public static final String AUDIT_PRINCIPLES =
"审计工作原则:\n" +
"1. 以目标责任制文件为依据,对照完成情况\n" +
"2. 优先使用上级主管部门下达的目标任务作为衡量标准\n" +
"3. 如无上级目标任务,则以单位自定目标为衡量标准\n" +
"4. 重点关注已完成任务的真实性、未完成任务的客观原因\n" +
"5. 注重目标责任与单位职责的匹配性\n" +
"6. 考核评价机制是否健全有效";
// 关键词权重(聚焦核心概念)
public static final Map<String, Integer> KEYWORD_WEIGHTS = new HashMap<>();
static {
// 核心概念
KEYWORD_WEIGHTS.put("目标责任", 10);
KEYWORD_WEIGHTS.put("目标责任制", 10);
KEYWORD_WEIGHTS.put("目标任务", 9);
// 完成情况
KEYWORD_WEIGHTS.put("完成情况", 10);
KEYWORD_WEIGHTS.put("落实情况", 9);
KEYWORD_WEIGHTS.put("完成率", 8);
// 文件依据
KEYWORD_WEIGHTS.put("下达文件", 9);
KEYWORD_WEIGHTS.put("计划文件", 9);
KEYWORD_WEIGHTS.put("责任书", 8);
KEYWORD_WEIGHTS.put("考核办法", 8);
// 审计相关
KEYWORD_WEIGHTS.put("考核指标", 8);
KEYWORD_WEIGHTS.put("未完成", 7);
KEYWORD_WEIGHTS.put("已完成", 7);
KEYWORD_WEIGHTS.put("上级主管", 7);
}
// 审计要点提示
public static final String AUDIT_KEY_POINTS =
"审计要点:\n" +
"1. 检查目标责任文件完整性\n" +
"2. 核实完成数据的真实性\n" +
"3. 分析未完成原因合理性\n" +
"4. 评估目标制定科学性\n" +
"5. 检查考核执行规范性";
// 数据格式要求
public static final String DATA_FORMAT_INSTRUCTION =
"JSON数组格式包含以下字段\n" +
"1. index: 序号\n" +
"2. year: 年度\n" +
"3. superiorFile: 上级下达文件\n" +
"4. superiorCompletion: 上级完成情况\n" +
"5. superiorReason: 上级未完成原因\n" +
"6. selfPlan: 单位自定计划\n" +
"7. selfCompletion: 自定完成情况\n" +
"8. selfReason: 自定未完成原因\n" +
"9. remark: 备注\n" +
// "10. workPaperIndex: [相关文件FileId]";
"10. workPaperIndex: [相关文件的完整文件名||FileUrl]";
// 获取分类的简要审计框架概述
public static String getBriefAuditFrameworkForCategory(String category) {
if (CATEGORY_TARGET_RESPONSIBILITY.equals(category)) {
return "审计目标责任制的制定、执行和完成情况,评估落实效果";
}
return "审计目标责任制完成情况";
}
// 字段映射(用于前端展示)
public static final Map<String, String> FIELD_DISPLAY_NAMES = new HashMap<>();
static {
FIELD_DISPLAY_NAMES.put("index", "序号");
FIELD_DISPLAY_NAMES.put("year", "年度");
FIELD_DISPLAY_NAMES.put("superiorFile", "上级下达文件");
FIELD_DISPLAY_NAMES.put("superiorCompletion", "上级完成情况");
FIELD_DISPLAY_NAMES.put("superiorReason", "上级未完成原因");
FIELD_DISPLAY_NAMES.put("selfPlan", "单位自定计划");
FIELD_DISPLAY_NAMES.put("selfCompletion", "自定完成情况");
FIELD_DISPLAY_NAMES.put("selfReason", "自定未完成原因");
FIELD_DISPLAY_NAMES.put("remark", "备注");
FIELD_DISPLAY_NAMES.put("workPaperIndex", "工作底稿索引");
}
// 审计证据要求
public static final String AUDIT_EVIDENCE_REQUIREMENTS =
"审计证据要求:\n" +
"1. 查阅文件:目标责任制相关文件、计划、实施方案\n" +
"2. 查阅记录:完成情况报告、考核记录、会议纪要\n" +
"3. 查阅数据:统计数据、财务报表、进度报表\n" +
"4. 查阅凭证:相关凭证、合同、协议\n" +
"5. 现场核实:必要时进行现场核实和访谈";
// 输出格式要求
public static final String OUTPUT_FORMAT =
"输出格式JSON数组\n" +
"[\n" +
" {\n" +
" \"index\": 序号,\n" +
" \"year\": \"年度\",\n" +
" \"superiorFile\": \"上级主管部门下达文件名称和文号\",\n" +
" \"superiorCompletion\": \"上级目标完成情况(已完成/部分完成/未完成)\",\n" +
" \"superiorReason\": \"上级目标未完成原因(如已完成,填'无未完成原因'\",\n" +
" \"selfPlan\": \"单位自定计划文件名称\",\n" +
" \"selfCompletion\": \"自定目标完成情况(已完成/部分完成/未完成)\",\n" +
" \"selfReason\": \"自定目标未完成原因(如已完成,填'无未完成原因'\",\n" +
" \"remark\": \"备注\",\n" +
// " \"workPaperIndex\": [\"实际存在的完整FileId1\", \"实际存在的完整FileId2\", ...]\n" +
" \"workPaperIndex\": [\"实际存在的完整文件名1||FileUrl1\", \"实际存在的完整文件名2||FileUrl2\", ...]\n" +
" }\n" +
"]\n\n" +
"重要说明:\n" +
"1. 每个审计记录对应一个具体的文件或目标\n" +
"2. 同一年度可能有多个目标责任,每个都应生成独立的审计记录\n" +
"3. 尽可能从知识库中提取所有相关信息,生成尽可能多的记录";
}

View File

@@ -0,0 +1,260 @@
package com.gxwebsoft.ai.constants;
import java.util.*;
/**
* 审计内容5-预算执行情况审计常量类
* 审计目标:检查预算执行的进度、合规性、效果,分析预算执行偏差原因,评估预算执行效益
*/
public class AuditContent5BudgetExecutionConstants {
// 分类定义
public static final String CATEGORY_BUDGET_EXECUTION = "预算执行情况审计";
// 审计框架核心
public static final String AUDIT_FRAMEWORK =
"**审计核心:**\n" +
"预算执行情况审计。包括预算执行进度、执行合规性、执行效果评估、预算执行偏差分析、\n" +
"资金到位情况、项目执行进度、预算执行率、资金使用效益、执行风险预警、整改措施落实等情况。\n\n" +
"**重点关注:**\n" +
"1. 预算执行率是否达到预期目标,是否存在执行进度滞后问题\n" +
"2. 资金是否按时足额到位,是否存在资金沉淀或短缺问题\n" +
"3. 预算执行是否合规,是否存在超预算、无预算执行问题\n" +
"4. 项目执行进度是否符合计划,是否存在项目延期问题\n" +
"5. 预算调整是否及时报批,是否存在擅自调整预算问题\n" +
"6. 预算执行效益如何,是否达到预期经济效益和社会效益\n" +
"7. 预算执行是否存在偏差,偏差原因是否合理\n" +
"8. 预算执行监控是否到位,是否存在风险预警机制\n" +
"9. 预算执行问题整改是否及时有效,整改措施是否落实\n" +
"10. 预算执行信息公开是否及时准确,透明度如何\n" +
"11. 预算执行考核评价机制是否健全,考核结果是否应用\n" +
"12. 预算执行信息化水平如何,是否实现动态监控\n" +
"13. 预算执行与决算衔接是否顺畅,数据是否一致\n" +
"14. 预算执行对单位履职和事业发展的支撑作用如何\n" +
"15. 预算执行中是否存在挤占挪用、虚列支出等问题\n" +
"16. 预算执行与政府采购、资产管理等是否协调衔接\n\n" +
"**审计方法及步骤:**\n" +
"1. 预算执行进度审计:\n" +
" (1) 审阅被审计领导干部任职期间的预算执行进度报表、月度/季度/年度执行分析报告\n" +
" (2) 对比预算安排与实际执行数据,计算预算执行率、资金到位率等关键指标\n" +
" (3) 分析执行进度滞后项目的原因,检查是否存在客观障碍或主观问题\n" +
" (4) 检查预算执行台账是否完整,执行记录是否及时准确\n\n" +
"2. 预算执行合规性审计:\n" +
" (1) 对比预算批复文件与会计账务处理,检查预算执行是否严格按照批复执行\n" +
" (2) 检查是否存在超预算执行、无预算执行、预算科目调剂等违规问题\n" +
" (3) 审查预算调整审批手续是否完备,是否存在擅自调整预算问题\n" +
" (4) 检查资金支付凭证是否合规,支付审批流程是否完整\n\n" +
"3. 预算执行效果审计:\n" +
" (1) 对照项目可行性研究报告和评审报告,检查项目预期目标实现情况\n" +
" (2) 运用成本效益分析方法,评估预算资金使用效益\n" +
" (3) 实地查看项目实施情况,验证项目实际效果\n" +
" (4) 调查相关受益群体,了解项目社会效益和满意度\n\n" +
"4. 预算执行偏差分析:\n" +
" (1) 分析预算执行偏差数据,找出偏差较大的项目和科目\n" +
" (2) 通过访谈、座谈等方式了解偏差产生的原因\n" +
" (3) 评估偏差是否合理,是否存在管理问题\n" +
" (4) 检查是否建立偏差分析机制和整改措施\n\n" +
"5. 预算执行风险管理审计:\n" +
" (1) 检查是否建立预算执行风险预警机制\n" +
" (2) 评估风险预警指标是否科学合理\n" +
" (3) 检查风险预警响应和处置是否及时有效\n" +
" (4) 审查风险防范措施是否落实到位\n\n" +
"6. 预算执行整改审计:\n" +
" (1) 检查以往审计发现问题的整改情况\n" +
" (2) 评估整改措施的有效性和落实情况\n" +
" (3) 检查是否存在屡审屡犯问题\n" +
" (4) 评估整改长效机制建设情况\n\n" +
"7. 预算执行信息化审计:\n" +
" (1) 检查预算执行信息系统建设情况\n" +
" (2) 评估系统功能是否满足预算执行监控需求\n" +
" (3) 检查系统数据是否准确完整\n" +
" (4) 评估信息化对预算执行管理的支撑作用";
// 审计目标
public static final String AUDIT_OBJECTIVE =
"全面检查预算执行全过程,包括执行进度、执行合规性、执行效果、执行偏差分析、\n" +
"风险管理、整改落实等,确保预算资金规范高效使用,提高预算执行质量和效益。";
// 审计工作原则
public static final String AUDIT_PRINCIPLES =
"审计工作原则:\n" +
"1. 以《预算法》、《预算法实施条例》及相关财政法规为依据\n" +
"2. 全面覆盖预算执行的所有环节和方面\n" +
"3. 重点关注预算执行率、资金到位率等关键指标\n" +
"4. 检查预算执行合规性和规范性\n" +
"5. 评估预算执行效果和效益\n" +
"6. 分析预算执行偏差原因\n" +
"7. 关注预算执行风险防控\n" +
"8. 检查审计问题整改情况\n" +
"9. 促进预算执行管理完善\n" +
"10. 提高财政资金使用效益";
// 关键词权重
public static final Map<String, Integer> KEYWORD_WEIGHTS = new HashMap<>();
static {
// 预算执行核心概念
KEYWORD_WEIGHTS.put("预算执行", 10);
KEYWORD_WEIGHTS.put("执行进度", 9);
KEYWORD_WEIGHTS.put("执行率", 10);
KEYWORD_WEIGHTS.put("资金到位", 9);
KEYWORD_WEIGHTS.put("执行合规", 8);
// 预算执行指标
KEYWORD_WEIGHTS.put("执行偏差", 8);
KEYWORD_WEIGHTS.put("预算调整", 7);
KEYWORD_WEIGHTS.put("超预算", 8);
KEYWORD_WEIGHTS.put("无预算", 8);
KEYWORD_WEIGHTS.put("科目调剂", 7);
// 执行效果和效益
KEYWORD_WEIGHTS.put("执行效果", 8);
KEYWORD_WEIGHTS.put("资金效益", 8);
KEYWORD_WEIGHTS.put("成本效益", 7);
KEYWORD_WEIGHTS.put("社会效益", 7);
KEYWORD_WEIGHTS.put("经济效益", 7);
// 执行风险管理
KEYWORD_WEIGHTS.put("风险预警", 7);
KEYWORD_WEIGHTS.put("执行风险", 7);
KEYWORD_WEIGHTS.put("风险防控", 6);
KEYWORD_WEIGHTS.put("预警机制", 6);
// 执行监控和整改
KEYWORD_WEIGHTS.put("执行监控", 7);
KEYWORD_WEIGHTS.put("动态监控", 6);
KEYWORD_WEIGHTS.put("整改措施", 7);
KEYWORD_WEIGHTS.put("整改落实", 7);
KEYWORD_WEIGHTS.put("屡审屡犯", 6);
// 文件类型
KEYWORD_WEIGHTS.put("执行报表", 8);
KEYWORD_WEIGHTS.put("进度报表", 8);
KEYWORD_WEIGHTS.put("执行分析", 7);
KEYWORD_WEIGHTS.put("执行报告", 7);
KEYWORD_WEIGHTS.put("支付凭证", 7);
KEYWORD_WEIGHTS.put("拨款凭证", 7);
}
// 审计要点提示
public static final String AUDIT_KEY_POINTS =
"**审计要点:**\n" +
"1. 检查预算执行率是否达到预期目标,分析执行进度滞后原因\n" +
"2. 核实资金是否按时足额到位,是否存在资金沉淀问题\n" +
"3. 审查预算执行是否合规,是否存在超预算、无预算执行\n" +
"4. 检查项目执行进度是否符合计划,是否存在项目延期\n" +
"5. 评估预算调整审批是否及时合规\n" +
"6. 分析预算执行偏差原因是否合理\n" +
"7. 评估预算执行效益是否达到预期目标\n" +
"8. 检查预算执行风险预警机制是否健全\n" +
"9. 审查审计问题整改是否及时有效\n" +
"10. 评估预算执行信息化水平\n" +
"11. 检查预算执行信息公开情况\n" +
"12. 评估预算执行考核评价机制\n" +
"13. 检查预算执行与决算衔接情况\n" +
"14. 分析预算执行对单位发展的支撑作用\n" +
"15. 检查是否存在挤占挪用、虚列支出问题\n" +
"16. 评估预算执行管理完善程度";
// 数据格式要求
public static final String OUTPUT_FORMAT =
"**输出格式JSON数组**\n" +
"[\n" +
" {\n" +
" \"index\": 序号,\n" +
" \"project\": \"项目名称\",\n" +
" \"lastYearCarryOver\": \"上年结转\",\n" +
" \"currentYearBudgetTotal\": \"本年预算小计\",\n" +
" \"initialApprovedBudget\": \"年初批复预算数\",\n" +
" \"additionalBudgetAmount\": \"追加预算数\",\n" +
" \"actualAppropriation\": \"实际拨款数\",\n" +
" \"indicatorBalance\": \"指标结余\",\n" +
// " \"workPaperIndex\": [\"实际存在的完整FileId1\", \"实际存在的完整FileId2\", ...]\n" +
" \"workPaperIndex\": [\"实际存在的完整文件名1||FileUrl1\", \"实际存在的完整文件名2||FileUrl2\", ...]\n" +
" }\n" +
"]\n\n" +
"**重要说明:**\n" +
"1. 每个审计记录对应一个具体的预算项目或执行事项\n" +
"2. 尽可能全面识别所有预算执行项目和环节\n" +
"3. 金额字段应填写具体数值,如\"1,000,000.00\"\n" +
"4. 百分比字段应填写具体百分比,如\"85.50%\"\n" +
"5. workPaperIndex必须填写实际查阅的文件名称\n" +
"6. 对于无数据的字段,可填写\"-\"或留空\n" +
"7. 尽可能多地生成审计记录,覆盖所有预算执行方面\n" +
"8. 重点关注预算执行率低于80%或高于120%的项目\n" +
"9. 深入分析预算执行偏差的根本原因";
// 审计证据要求
public static final String AUDIT_EVIDENCE_REQUIREMENTS =
"**审计证据要求:**\n" +
"1. 预算执行相关文件:预算执行进度报表、月度/季度/年度执行分析报告\n" +
"2. 资金拨付文件:拨款凭证、银行回单、付款审批单\n" +
"3. 预算调整文件:预算调整审批文件、追加预算审批单\n" +
"4. 项目执行文件:项目进度报告、项目验收报告、项目结算资料\n" +
"5. 财务核算文件:会计账簿、会计凭证、银行对账单\n" +
"6. 执行监控文件:预算执行台账、执行监控记录、风险预警记录\n" +
"7. 整改落实文件:审计问题整改报告、整改措施落实证明\n" +
"8. 考核评价文件:预算执行考核方案、考核结果、奖惩记录\n" +
"9. 信息系统文件:预算执行系统截图、数据导出报表\n" +
"10. 现场核实资料:实地查看记录、座谈记录、调查问卷";
// 字段映射(用于前端展示)
public static final Map<String, String> FIELD_DISPLAY_NAMES = new HashMap<>();
static {
FIELD_DISPLAY_NAMES.put("index", "序号");
FIELD_DISPLAY_NAMES.put("project", "项目名称");
FIELD_DISPLAY_NAMES.put("lastYearCarryOver", "上年结转");
FIELD_DISPLAY_NAMES.put("currentYearBudgetTotal", "本年预算小计");
FIELD_DISPLAY_NAMES.put("initialApprovedBudget", "年初批复预算数");
FIELD_DISPLAY_NAMES.put("additionalBudgetAmount", "追加预算数");
FIELD_DISPLAY_NAMES.put("actualAppropriation", "实际拨款数");
FIELD_DISPLAY_NAMES.put("indicatorBalance", "指标结余");
FIELD_DISPLAY_NAMES.put("workPaperIndex", "工作底稿索引");
}
// 获取分类的简要审计框架概述
public static String getBriefAuditFrameworkForCategory(String category) {
if (CATEGORY_BUDGET_EXECUTION.equals(category)) {
return "全面审计预算执行全过程,包括执行进度、合规性、效果、偏差分析、风险管理、整改落实等情况";
}
return "全面审计预算执行情况";
}
// 审计项目类型(常见预算执行项目)
public static final List<String> AUDIT_PROJECT_TYPES = Arrays.asList(
"基本支出-人员经费执行",
"基本支出-公用经费执行",
"项目支出-专项业务费执行",
"项目支出-设备购置费执行",
"项目支出-大型修缮费执行",
"项目支出-信息网络购建费执行",
"项目支出-基础设施建设费执行",
"项目支出-会议费执行",
"项目支出-培训费执行",
"项目支出-差旅费执行",
"项目支出-劳务费执行",
"项目支出-咨询费执行",
"项目支出-委托业务费执行",
"政府采购项目执行",
"科研项目经费执行",
"基建项目资金执行",
"信息化项目执行",
"培训项目执行",
"会议项目执行",
"差旅费执行",
"办公设备购置执行",
"车辆运行维护费执行",
"物业管理费执行",
"租赁费执行",
"维修维护费执行",
"专用材料费执行",
"其他商品和服务支出执行"
);
}

View File

@@ -0,0 +1,323 @@
package com.gxwebsoft.ai.constants;
import java.util.*;
/**
* 审计内容5-预算管理审计常量类
* 审计目标:检查预算编制的完整准确、预算调整审批的合规,以及预算支出的真实合法合规情况
*/
public class AuditContent5BudgetManageConstants {
// 分类定义
public static final String CATEGORY_BUDGET_MANAGEMENT = "预算管理审计";
// 审计框架核心完整基于Excel内容
public static final String AUDIT_FRAMEWORK =
"**审计核心:**\n" +
"财政财务管理情况。包括预算编制的完整准确、预算调整审批的合规,以及预算支出的真实合法合规情况;\n" +
"财务收支的真实、合法和效益情况;自然资源资产管理和生态环境保护责任的履行情况;\n" +
"境外机构、境外资产和境外经济活动的真实、合法和效益情况。\n\n" +
"**重点关注:**\n" +
"1. 是否存在应纳入部门预算管理的各项收支未纳入预算编报\n" +
"2. 项目预算编制不细化导致预算执行率低\n" +
"3. 将独立核算的经营收支编入部门预算\n" +
"4. 将预算拨款在不同预算科目之间相互调剂使用\n" +
"5. 年初未安排预算、在年中又追加的预算调整事项是否合理\n" +
"6. 有无未经批复自行调整部门预算的问题\n" +
"7. 部门预算的项目是否全部都是本单位的业务\n" +
"8. 是否有所设立企业的经营收支性质的预算项目\n" +
"9. 预算支出中是否存在以虚假经济业务套取财政资金等问题\n" +
"10. 预算收支的效益性,项目效益、效果等预期目标的实现情况\n" +
"11. 国有资产配置是否按规定实行政府采购\n" +
"12. 国有资产对外投资和收益以及国有资产保值增值的情况\n" +
"13. 政府采购执行情况,是否存在规避政府采购的情况\n" +
"14. 项目实施及管理情况,项目资金安全、实施进度\n" +
"15. 债权债务的情况,债务可控程度,债权形成呆账的比例\n" +
"16. 工会、饭堂财务收支情况,有无将经营收入放进工会、饭堂核算\n\n" +
"**审计方法及步骤:**\n" +
"1. 部门预算编报及调整情况审计:\n" +
" (1) 审阅被审计领导干部任职期间的部门预算、决算资料,分析预算收入来源渠道和使用方向,将各年度收支预算进行对比,检查收入预算编报的完整性,支出预算编报的真实性、准确性。\n" +
" (2) 审阅项目预算申报文本,对项目的可行性研究报告、评审报告进行审查,通过实地调查或座谈等方法了解项目准备情况和进展情况,检查项目预算申报的规范性,项目预算有无细化到具体执行单位。\n" +
" (3) 审阅预算调整文件,审查申报、审批手续的完整性,重点关注年初未安排预算、在年中又追加的预算调整事项是否合理。有无未经批复自行调整部门预算的问题。\n" +
" (4) 审阅部门预算的项目是否全部都是本单位的业务,检查是否有所设立企业的经营收支性质的预算项目。\n" +
" (5) 将预算下达文件与会计账务处理相对比,检查两者的项目名称一致,是否相互调剂项目预算。\n\n" +
"2. 预算执行和财政财务收支情况审计:\n" +
" (1) 必须了解被审计单位设置的财务帐套有哪些,核实现金、银行的流水账和会计凭证保存的银行账户对账单是否一致,现金、银行的流动是否正常,有没有转到可疑的、无关的银行账户的现象。\n" +
" (2) 核实财务软件的记录与被审计单位提供及保存的纸质版的账簿是否一致,核实财务帐套设置的明细科目是否与预算批复的明细科目一致。\n" +
" (3) 核实财务帐套的支出数是否与决算报表一致,有无调整财务帐套支出数以达到不超出预算目的的现象,有无不按财务帐套支出数填报决算报表,以达到不超出预算目的的现象。\n" +
" (4) 核实财务帐套上基本支出加项目支出的\"三公\"经费等的支出数,对比预算下达的\"三公经费\"等预算数,检查是否超预算。\n" +
" (5) 审阅被审计领导干部任职期间所在单位各年度预算、决算资料,编制收入和支出情况分析表,将各年度收入和支出规模和结构进行对比,运用分析性复核的方法分析收入和支出的变化趋势,考虑合理的变动因素,审查不合理的变化及差异,检查收入和支出的总体规模、结构是否与单位职责履行、事业发展目标或者所承担重要事项相匹配。\n" +
" (6) 对照收入和支出预算和决算,审查被审计领导干部任职期间部门各年度的会计账簿和凭证,检查预算收入、预算支出的真实性。审阅项目预算申报文本,对照项目预算支出明细,审查会计账簿和凭证,检查是否存在挤占挪用项目资金等问题。实地观察项目执行情况,检查是否存在虚报项目套取财政资金、将所属企业开支纳入预算核算等问题。\n" +
" (7) 结合新执行的预算绩效考核方法,审查被审计领导干部任职期间各年度的会计账簿、凭证和有关业务资料,运用成本效益分析方法,检查预算收支的效益性,对照项目可行性研究报告和评审报告以及年度目标责任制,检查项目效益、效果等预期目标的实现情况,以及对经济社会发展产生的影响。\n\n" +
"3. 国有资产的管理情况审计:\n" +
" (1) 审阅国有资产采购合同及招投标文件等资料,检查国有资产购置是否按规定实行政府采购。\n" +
" (2) 审阅固定资产登记台账与会计明细账,审查账账是否相符。根据固定资产类别或领用单位等进行抽查盘点,审查账实是否相符,已报废固定资产是否及时予以报废、核销。\n" +
" (3) 审阅国有资产出租、出借、报废核销的上级主管部门和财政部门的批准文件,检查手续是否完整。\n" +
" (4) 审阅国有资产处置收入的评估文件、上级主管部门和财政部门的核准文件,对比市场价格,检查处置收入是否合理,是否具备完整的处置手续。\n" +
" (5) 审阅国有资产处置收入的会计处理凭证及上缴财政国库的会计处理凭证,检查处置收益是否已纳入\"收支两条线\"管理。审计房屋出租是否按照规定上平台招租,可调查周边租金水平,来进行对比。\n" +
" (6) 审阅国有资产对外投资,提供抵押、担保的上级主管部门和财政部门的审计文件,以及提供抵押、担保的合同,检查审批手续是否齐全,是否真实、合法;计算本单位国有资产保值增值率,检查本单位国有资产保值增值的情况;审计被审计单位划拨、借用给设立企业的资产来源是否清晰。\n\n" +
"4. 政府采购执行情况审计:\n" +
" (1) 审查财务支出凭据,和\"固定资产\"科目,检查是否全部固定资产的采购都是通过具备政府采购手续的。\n" +
" (2) 对照政府采购文件和目录,查阅财务支出,审计是否存在应报政府采购而未报的情况,特别注意成批的易耗品、一般资产也要执行政府采购。审计时,必须将有可能是批量采购而拆解采购的线索联系起来,看采购的时间、品目,是否应当同时购置的,采取分散购置,规避政府采购,发现此类情况的,除追究违反政府采购法的责任外,还要追踪至货物、服务的提供方,检查是否存在关联交易,交易价格是否合理,是否存在利益输送。\n" +
" (3) 将年度内所有已执行政府采购的名单列出,与政府采购预算报表核对,审计是否按照预算采购,有无乱采购、无预算采购。凡是发现无预算采购的,都要关注采购价格和关联方交易、利益输送。\n" +
" (4) 对实施单一采购的,核对政府采购目录,检查是否属于单一采购来源的要求。如果不属于单一采购来源的,也要关注采购价格和关联方交易、利益输送。\n\n" +
"5. 项目实施及管理情况审计:\n" +
" 关注各单位实施项目的资金安全,实施进度、财务收支以及项目的会计核算及项目管理的相关手续。\n\n" +
"6. 债权债务的情况审计:\n" +
" (1) 检查审计期末的应收款与应付款借方余额的形成年限对超过3年未收取的应收款项询问形成呆账的原因以及有无采取措施收取。计算3年以上呆账占应收款项的比例如果占比较高检查是否建立有坏账的处理机制。\n" +
" (2) 检查审计期末的应付款和应收款的贷方余额,对大额的部分,了解形成的原因、被审计单位的偿还能力。\n\n" +
"7. 工会、饭堂财务收支情况审计:\n" +
" 重点关注有无将房屋租金、经营收入等放进工会、饭堂核算的现象;工会开支范围和标准是否超过文件规定。";
// 审计目标
public static final String AUDIT_OBJECTIVE =
"全面检查预算管理的各个方面,包括预算编制的完整准确、预算调整审批的合规、预算支出的真实合法合规情况、\n" +
"财务收支的真实合法和效益、国有资产管理、政府采购执行、项目实施管理、债权债务管理、工会饭堂财务等,\n" +
"确保财政资金使用的规范性、有效性和安全性。";
// 审计工作原则
public static final String AUDIT_PRINCIPLES =
"审计工作原则:\n" +
"1. 以《预算法》、《政府采购法》、《国有资产管理办法》及相关财政法规为依据\n" +
"2. 全面覆盖预算管理的所有环节和方面\n" +
"3. 检查预算收入编报的完整性和支出编报的真实性、准确性\n" +
"4. 关注项目预算申报的规范性和细化程度\n" +
"5. 检查预算调整审批手续的合规性\n" +
"6. 核实部门预算项目的相关性\n" +
"7. 检查预算下达与账务处理的一致性\n" +
"8. 审查国有资产管理的合规性和效益性\n" +
"9. 监督政府采购执行的规范性\n" +
"10. 评估项目实施和管理的有效性\n" +
"11. 分析债权债务的风险控制\n" +
"12. 核查工会饭堂财务的合规性";
// 关键词权重
public static final Map<String, Integer> KEYWORD_WEIGHTS = new HashMap<>();
static {
// 预算管理核心概念
KEYWORD_WEIGHTS.put("部门预算", 10);
KEYWORD_WEIGHTS.put("预算编制", 10);
KEYWORD_WEIGHTS.put("预算调整", 9);
KEYWORD_WEIGHTS.put("预算执行", 9);
KEYWORD_WEIGHTS.put("预算决算", 9);
// 预算科目和指标
KEYWORD_WEIGHTS.put("预算科目", 8);
KEYWORD_WEIGHTS.put("指标来源", 8);
KEYWORD_WEIGHTS.put("指标运用", 8);
KEYWORD_WEIGHTS.put("指标结余", 7);
// 资金类型和用途
KEYWORD_WEIGHTS.put("财政拨款", 8);
KEYWORD_WEIGHTS.put("工资统发", 7);
KEYWORD_WEIGHTS.put("政府采购", 8);
KEYWORD_WEIGHTS.put("财政管理专户", 6);
KEYWORD_WEIGHTS.put("基本支出", 8);
KEYWORD_WEIGHTS.put("项目支出", 8);
// 审计要点和方法
KEYWORD_WEIGHTS.put("项目预算", 8);
KEYWORD_WEIGHTS.put("预算申报", 7);
KEYWORD_WEIGHTS.put("预算审批", 7);
KEYWORD_WEIGHTS.put("预算调剂", 7);
KEYWORD_WEIGHTS.put("国有资产", 8);
KEYWORD_WEIGHTS.put("固定资产", 7);
KEYWORD_WEIGHTS.put("政府采购", 7);
KEYWORD_WEIGHTS.put("债权债务", 6);
KEYWORD_WEIGHTS.put("工会饭堂", 5);
// 文件类型
KEYWORD_WEIGHTS.put("预算报表", 7);
KEYWORD_WEIGHTS.put("决算报表", 7);
KEYWORD_WEIGHTS.put("可行性研究", 6);
KEYWORD_WEIGHTS.put("评审报告", 6);
KEYWORD_WEIGHTS.put("会计账簿", 6);
KEYWORD_WEIGHTS.put("会计凭证", 6);
}
// 审计要点提示
public static final String AUDIT_KEY_POINTS =
"**审计要点基于Excel完整内容**\n" +
"1. 检查应纳入部门预算管理的各项收支是否全部纳入预算编报\n" +
"2. 核实项目预算是否细化到具体执行单位\n" +
"3. 审查预算调整审批手续是否完整合规\n" +
"4. 检查是否存在将经营收支编入部门预算的情况\n" +
"5. 核实预算拨款是否在不同科目间违规调剂使用\n" +
"6. 检查年初未安排预算、年中追加事项的合理性\n" +
"7. 核实部门预算项目是否全部为本单位业务\n" +
"8. 检查是否将设立企业的经营收支纳入部门预算\n" +
"9. 检查预算支出中是否存在以虚假经济业务套取财政资金\n" +
"10. 审查预算收支的效益性,项目效益、效果等预期目标的实现情况\n" +
"11. 检查国有资产配置是否按规定实行政府采购\n" +
"12. 检查国有资产对外投资和收益以及国有资产保值增值情况\n" +
"13. 审计政府采购执行情况,是否存在规避政府采购\n" +
"14. 关注项目实施及管理情况,项目资金安全、实施进度\n" +
"15. 检查债权债务的情况,债务可控程度,债权形成呆账的比例\n" +
"16. 审计工会、饭堂财务收支情况,有无将经营收入放进工会、饭堂核算";
// 数据格式要求
public static final String OUTPUT_FORMAT =
"**输出格式JSON数组**\n" +
"[\n" +
" {\n" +
" \"index\": 序号,\n" +
" \"budgetSubject\": \"预算科目名称\",\n" +
" \"indicatorSource\": \"指标来源\",\n" +
" \"indicatorSourceTotal\": \"指标来源合计\",\n" +
" \"indicatorSourceLastYearBalance\": \"上年结余\",\n" +
" \"indicatorSourceInitialBudget\": \"年初部门预算\",\n" +
" \"indicatorSourceAdditionalBudget\": \"追加(减)预算\",\n" +
" \"indicatorUseTotal\": \"指标运用合计\",\n" +
" \"indicatorUseAppropriationSubtotal\": \"拨款小计\",\n" +
" \"indicatorUseAppropriation\": \"拨款\",\n" +
" \"indicatorUseSalaryPayment\": \"工资统发\",\n" +
" \"indicatorUseGovProcurement\": \"政府采购\",\n" +
" \"financeManagementAccount\": \"财政管理专户\",\n" +
" \"budgetUsedForOther\": \"部门预算用于其他\",\n" +
" \"indicatorBalance\": \"指标结余\",\n" +
" \"governmentProcurement\": \"政府采购\",\n" +
" \"payableToUnit\": \"应拨单位款\",\n" +
" \"other\": \"其他(可简要说明审计发现)\",\n" +
// " \"workPaperIndex\": [\"实际存在的完整FileId1\", \"实际存在的完整FileId2\", ...]\n" +
" \"workPaperIndex\": [\"实际存在的完整文件名1||FileUrl1\", \"实际存在的完整文件名2||FileUrl2\", ...]\n" +
" }\n" +
"]\n\n" +
"**重要说明:**\n" +
"1. 每个审计记录对应一项具体的预算科目或审计事项,尽可能全面识别所有预算科目和审计事项\n" +
"2. 预算科目包括但不限于:基本支出(人员经费、公用经费)、项目支出(专项业务费、设备购置费、维修维护费、会议费、培训费、差旅费、劳务费、咨询费、印刷费、邮电费、租赁费、物业管理费、专用材料费、委托业务费、其他商品和服务支出)等\n" +
"3. 审计事项应包括:预算管理、财务收支、国有资产管理、政府采购、项目实施、债权债务、工会饭堂财务等各方面\n" +
"4. 金额字段应填写具体数值,如\"1,000,000.00\",不能填写简单的\"\"\"\"\n" +
"5. workPaperIndex必须填写实际查阅的文件名称包括各种相关文件\n" +
"6. 对于无数据的字段,可填写\"-\"或留空,但不能填写\"\"\n" +
"7. 尽可能多地生成审计记录,覆盖所有可能的预算科目和审计事项,不限制数量\n" +
"8. 基于预算编制、调整、执行、决算的全流程进行审计分析\n" +
"9. 多多益善,全面反映审计情况";
// 审计证据要求
public static final String AUDIT_EVIDENCE_REQUIREMENTS =
"**审计证据要求:**\n" +
"1. 预算管理相关文件:部门预算报表、决算报表、项目预算申报文本、可行性研究报告、评审报告\n" +
"2. 预算调整相关文件:预算调整审批文件、预算下达文件、追加预算审批单\n" +
"3. 财务核算相关文件:会计账簿、会计凭证、银行对账单、现金流水账、财务软件记录\n" +
"4. 预算执行相关文件:预算执行进度表、资金拨付记录、拨款凭证、工资发放记录\n" +
"5. 国有资产相关文件:固定资产登记台账、资产盘点表、采购合同、招投标文件、资产处置审批文件、资产评估报告、出租出借合同、投资担保合同\n" +
"6. 政府采购相关文件:政府采购合同、采购发票、采购目录、采购计划、招标文件、投标文件、中标通知书\n" +
"7. 项目实施相关文件:项目合同、项目进度报告、项目验收报告、项目结算资料\n" +
"8. 债权债务相关文件:应收应付款明细账、账龄分析表、坏账核销审批文件、债务偿还计划\n" +
"9. 工会饭堂相关文件:工会账簿、饭堂收支记录、工会经费使用审批单\n" +
"10. 现场核实资料:实地查看记录、座谈记录、业务资料核对记录";
// 字段映射(用于前端展示)
public static final Map<String, String> FIELD_DISPLAY_NAMES = new HashMap<>();
static {
FIELD_DISPLAY_NAMES.put("index", "序号");
FIELD_DISPLAY_NAMES.put("budgetSubject", "预算科目名称");
FIELD_DISPLAY_NAMES.put("indicatorSource", "指标来源");
FIELD_DISPLAY_NAMES.put("indicatorSourceTotal", "指标来源合计");
FIELD_DISPLAY_NAMES.put("indicatorSourceLastYearBalance", "上年结余");
FIELD_DISPLAY_NAMES.put("indicatorSourceInitialBudget", "年初部门预算");
FIELD_DISPLAY_NAMES.put("indicatorSourceAdditionalBudget", "追加(减)预算");
FIELD_DISPLAY_NAMES.put("indicatorUseTotal", "指标运用合计");
FIELD_DISPLAY_NAMES.put("indicatorUseAppropriationSubtotal", "拨款小计");
FIELD_DISPLAY_NAMES.put("indicatorUseAppropriation", "拨款");
FIELD_DISPLAY_NAMES.put("indicatorUseSalaryPayment", "工资统发");
FIELD_DISPLAY_NAMES.put("indicatorUseGovProcurement", "政府采购");
FIELD_DISPLAY_NAMES.put("financeManagementAccount", "财政管理专户");
FIELD_DISPLAY_NAMES.put("budgetUsedForOther", "部门预算用于其他");
FIELD_DISPLAY_NAMES.put("indicatorBalance", "指标结余");
FIELD_DISPLAY_NAMES.put("governmentProcurement", "政府采购");
FIELD_DISPLAY_NAMES.put("payableToUnit", "应拨单位款");
FIELD_DISPLAY_NAMES.put("other", "其他(审计发现)");
FIELD_DISPLAY_NAMES.put("workPaperIndex", "工作底稿索引");
}
// 获取分类的简要审计框架概述
public static String getBriefAuditFrameworkForCategory(String category) {
if (CATEGORY_BUDGET_MANAGEMENT.equals(category)) {
return "全面审计预算管理的各个方面,包括预算编制、调整、执行、决算的全过程,以及相关的财务收支、国有资产管理、政府采购、项目实施、债权债务、工会饭堂财务等情况";
}
return "全面审计预算管理情况";
}
// 预算科目类型(更全面的列表)
public static final List<String> BUDGET_SUBJECT_TYPES = Arrays.asList(
"基本支出-人员经费-工资福利支出",
"基本支出-人员经费-社会保障缴费",
"基本支出-人员经费-住房公积金",
"基本支出-人员经费-其他人员支出",
"基本支出-公用经费-办公费",
"基本支出-公用经费-印刷费",
"基本支出-公用经费-咨询费",
"基本支出-公用经费-手续费",
"基本支出-公用经费-水费",
"基本支出-公用经费-电费",
"基本支出-公用经费-邮电费",
"基本支出-公用经费-取暖费",
"基本支出-公用经费-物业管理费",
"基本支出-公用经费-差旅费",
"基本支出-公用经费-因公出国(境)费用",
"基本支出-公用经费-维修(护)费",
"基本支出-公用经费-租赁费",
"基本支出-公用经费-会议费",
"基本支出-公用经费-培训费",
"基本支出-公用经费-公务接待费",
"基本支出-公用经费-专用材料费",
"基本支出-公用经费-被装购置费",
"基本支出-公用经费-专用燃料费",
"基本支出-公用经费-劳务费",
"基本支出-公用经费-委托业务费",
"基本支出-公用经费-工会经费",
"基本支出-公用经费-福利费",
"基本支出-公用经费-公务用车运行维护费",
"基本支出-公用经费-其他交通费用",
"基本支出-公用经费-税金及附加费用",
"基本支出-公用经费-其他商品和服务支出",
"项目支出-专项业务费",
"项目支出-设备购置费",
"项目支出-大型修缮费",
"项目支出-信息网络购建费",
"项目支出-基础设施建设费",
"项目支出-物资储备费",
"项目支出-会议费",
"项目支出-培训费",
"项目支出-差旅费",
"项目支出-劳务费",
"项目支出-咨询费",
"项目支出-印刷费",
"项目支出-邮电费",
"项目支出-租赁费",
"项目支出-物业管理费",
"项目支出-专用材料费",
"项目支出-委托业务费",
"项目支出-其他商品和服务支出",
"经营支出-经营成本",
"经营支出-经营费用",
"经营支出-经营税金",
"对个人和家庭的补助-离休费",
"对个人和家庭的补助-退休费",
"对个人和家庭的补助-退职(役)费",
"对个人和家庭的补助-抚恤金",
"对个人和家庭的补助-生活补助",
"对个人和家庭的补助-救济费",
"对个人和家庭的补助-医疗费补助",
"对个人和家庭的补助-助学金",
"对个人和家庭的补助-奖励金",
"对个人和家庭的补助-生产补贴",
"对个人和家庭的补助-住房公积金",
"对个人和家庭的补助-提租补贴",
"对个人和家庭的补助-购房补贴",
"对个人和家庭的补助-其他对个人和家庭的补助",
"债务还本支出-国内债务还本",
"债务还本支出-国外债务还本",
"债务利息支出-国内债务利息",
"债务利息支出-国外债务利息"
);
}

View File

@@ -0,0 +1,155 @@
package com.gxwebsoft.ai.constants;
import java.util.*;
/**
* 审计内容6-国资管理情况常量类
* 审计目标:检查国有资产管理情况和政府采购执行情况
*/
public class AuditContent6StateAssetsConstants {
// 分类定义
public static final String CATEGORY_STATE_ASSETS_MANAGEMENT = "国资管理情况";
// 审计框架核心基于Excel内容
public static final String AUDIT_FRAMEWORK =
"审计核心:检查国有资产管理情况和政府采购执行情况\n\n" +
"重点关注:\n" +
"1资产配置是否按规定报上级主管部门采取政府采购方式。资产登记不及时、不完整资产台账和会计明细账不符应报废、核销的资产长期挂账。未经批准出租、出借资产报废、核销资产未履行审批手续。资产处置收益未纳入\"收支两条线\"管理。被审计单位有房屋出租,制定资产出租必须进入交易平台的制度后,是否还有私自出租、不进入平台交易的现象。前期出租出去的房屋,未经过平台的,审计其租金水平是否合理。\n" +
"2国有资产对外投资和收益以及国有资产保值增值的情况。主要关注是否违规利用国有资产对外投资是否违规利用国有资产对外提供抵押、担保国有资产投资收益持续亏损的原因是否实现国有资产保值增值。\n\n" +
"审计方法及步骤:\n" +
"1审阅国有资产采购合同及招投标文件等资料检查国有资产购置是否按规定实行政府采购。审阅固定资产登记台账与会计明细账审查账账是否相符。根据固定资产类别或领用单位等进行抽查盘点审查账实是否相符已报废固定资产是否及时予以报废、核销。审阅国有资产出租、出借、报废核销的上级主管部门和财政部门的批准文件检查手续是否完整。审阅国有资产处置收入的评估文件、上级主管部门和财政部门的核准文件对比市场价格检查处置收入是否合理是否具备完整的处置手续。审阅国有资产处置收入的会计处理凭证及上缴财政国库的会计处理凭证检查处置收益是否已纳入\"收支两条线\"管理。审计房屋出租是否按照规定上平台招租,可调查周边租金水平,来进行对比。\n" +
"2审阅国有资产对外投资提供抵押、担保的上级主管部门和财政部门的审计文件以及提供抵押、担保的合同检查审批手续是否齐全是否真实、合法计算本单位国有资产保值增值率检查本单位国有资产保值增值的情况审计被审计单位划拨、借用给设立企业的资产来源是否清晰。\n\n" +
"政府采购执行情况\n\n" +
"重点关注:\n" +
"是否存在应当报政府采购计划的,未报政府采购计划的情况。包括拆解规避政府采购的情况;是否存在已报政府采购计划,但实际未实施政府采购,而是自行采购的情况,且采购的品类、型号是政府采购目录中具备的,达不到自行采购的条件;是否存在不按政府采购预算的品目,而通过政府采购实施其他品目采购的情况。\n\n" +
"审计方法及步骤:\n" +
"①审查财务支出凭据,和\"固定资产\"科目,检查是否全部固定资产的采购都是通过具备政府采购手续的。②对照政府采购文件和目录,查阅财务支出,审计是否存在应报政府采购而未报的情况,特别注意成批的易耗品、一般资产也要执行政府采购。审计时,必须将有可能是批量采购而拆解采购的线索联系起来,看采购的时间、品目,是否应当同时购置的,采取分散购置,规避政府采购,发现此类情况的,除追究违反政府采购法的责任外,还要追踪至货物、服务的提供方,检查是否存在关联交易,交易价格是否合理,是否存在利益输送。③将年度内所有已执行政府采购的名单列出,与政府采购预算报表核对,审计是否按照预算采购,有无乱采购、无预算采购。凡是发现无预算采购的,都要关注采购价格和关联方交易、利益输送。④对实施单一采购的,核对政府采购目录,检查是否属于单一采购来源的要求。如果不属于单一采购来源的,也要关注采购价格和关联方交易、利益输送。";
// 审计目标
public static final String AUDIT_OBJECTIVE =
"检查国有资产管理情况和政府采购执行情况,确保国有资产安全完整、保值增值,规范政府采购行为。";
// 审计工作原则
public static final String AUDIT_PRINCIPLES =
"审计工作原则:\n" +
"1. 以国有资产管理制度和政府采购法规为依据\n" +
"2. 重点检查资产配置、使用、处置全流程的合规性\n" +
"3. 关注资产出租、投资、担保等高风险环节\n" +
"4. 核实资产账实相符、账账相符情况\n" +
"5. 检查政府采购计划执行的真实性和合规性\n" +
"6. 注重发现规避监管、利益输送等违规行为";
// 关键词权重
public static final Map<String, Integer> KEYWORD_WEIGHTS = new HashMap<>();
static {
// 核心概念
KEYWORD_WEIGHTS.put("国有资产", 10);
KEYWORD_WEIGHTS.put("政府采购", 10);
KEYWORD_WEIGHTS.put("资产配置", 9);
KEYWORD_WEIGHTS.put("资产出租", 9);
// 管理流程
KEYWORD_WEIGHTS.put("台账", 8);
KEYWORD_WEIGHTS.put("会计明细账", 8);
KEYWORD_WEIGHTS.put("报废核销", 8);
KEYWORD_WEIGHTS.put("处置收益", 7);
KEYWORD_WEIGHTS.put("收支两条线", 7);
// 采购相关
KEYWORD_WEIGHTS.put("政府采购计划", 9);
KEYWORD_WEIGHTS.put("政府采购目录", 8);
KEYWORD_WEIGHTS.put("单一采购", 7);
KEYWORD_WEIGHTS.put("规避采购", 8);
// 投资担保
KEYWORD_WEIGHTS.put("对外投资", 9);
KEYWORD_WEIGHTS.put("抵押担保", 8);
KEYWORD_WEIGHTS.put("保值增值", 8);
// 合同相关
KEYWORD_WEIGHTS.put("租赁合同", 7);
KEYWORD_WEIGHTS.put("采购合同", 7);
KEYWORD_WEIGHTS.put("招投标", 7);
}
// 审计要点提示
public static final String AUDIT_KEY_POINTS =
"审计要点:\n" +
"1. 检查资产配置是否按规定实施政府采购\n" +
"2. 核实资产登记是否及时完整,账实是否相符\n" +
"3. 审查资产出租是否进入交易平台\n" +
"4. 检查资产处置手续是否完备,收益是否规范管理\n" +
"5. 审计对外投资、抵押担保的审批合规性\n" +
"6. 检查政府采购计划执行情况,是否存在规避行为\n" +
"7. 关注关联交易和利益输送风险";
// 数据格式要求
public static final String OUTPUT_FORMAT =
"输出格式JSON数组\n" +
"[\n" +
" {\n" +
" \"index\": 序号,\n" +
" \"assetName\": \"国有资产名称\",\n" +
" \"acquisitionMethod\": \"国有资产取得方式(购置/划拨/接受捐赠/自建等)\",\n" +
" \"assetValue\": \"国有资产价值(原值或评估值)\",\n" +
" \"assetAddress\": \"国有资产地址\",\n" +
" \"area\": \"面积(如适用)\",\n" +
" \"tenant\": \"承租方(如未出租填'未出租'\",\n" +
" \"contractAmount\": \"合同金额(如未出租填'未出租'\",\n" +
" \"leasePeriod\": \"租赁合同起止时间(如未出租填'未出租'\",\n" +
" \"rentPaymentTime\": \"国有资产租金缴纳时间(如未出租填'未出租'\",\n" +
" \"platformLease\": \"国有资产出租是否上平台(是/否/未出租)\",\n" +
" \"approvalDoc\": \"国有资产出租的审批文件(如未出租填'未出租'\",\n" +
" \"inBudget\": \"是否纳入预算(是/否)\",\n" +
" \"remark\": \"备注(包含资产状态、使用情况、审计发现等)\",\n" +
// " \"workPaperIndex\": [\"实际存在的完整FileId1\", \"实际存在的完整FileId2\", ...]\n" +
" \"workPaperIndex\": [\"实际存在的完整文件名1||FileUrl1\", \"实际存在的完整文件名2||FileUrl2\", ...]\n" +
" }\n" +
"]\n\n" +
"重要说明:\n" +
"1. 每个审计记录对应一项具体的国有资产,尽可能全面识别所有资产\n" +
"2. 资产类型包括:房屋建筑物、土地、车辆、机械设备、办公设备、电子设备等\n" +
"3. 对于没有出租的资产,相关出租字段填写\"未出租\"\n" +
"4. workPaperIndex必须填写实际查阅的文件名称\n" +
"5. 备注中应详细描述资产状况、使用情况、合规性评价\n" +
"6. 尽可能多地生成审计记录,覆盖所有可能的国有资产\n" +
"7. 即使信息不完整,也要基于现有信息生成记录";
// 审计证据要求
public static final String AUDIT_EVIDENCE_REQUIREMENTS =
"审计证据要求:\n" +
"1. 查阅文件:国有资产登记台账、会计明细账、采购合同、招投标文件\n" +
"2. 查阅记录:租赁合同、审批文件、处置评估报告、政府采购计划\n" +
"3. 查阅数据:资产价值评估报告、租金缴纳凭证、政府采购目录\n" +
"4. 查阅凭证:会计凭证、银行转账记录、审批手续文件\n" +
"5. 现场核实:资产实地盘点、租赁现场查看、供应商访谈";
// 字段映射(用于前端展示)
public static final Map<String, String> FIELD_DISPLAY_NAMES = new HashMap<>();
static {
FIELD_DISPLAY_NAMES.put("index", "序号");
FIELD_DISPLAY_NAMES.put("assetName", "国有资产名称");
FIELD_DISPLAY_NAMES.put("acquisitionMethod", "国有资产取得方式");
FIELD_DISPLAY_NAMES.put("assetValue", "国有资产价值");
FIELD_DISPLAY_NAMES.put("assetAddress", "国有资产地址");
FIELD_DISPLAY_NAMES.put("area", "面积");
FIELD_DISPLAY_NAMES.put("tenant", "承租方");
FIELD_DISPLAY_NAMES.put("contractAmount", "合同金额");
FIELD_DISPLAY_NAMES.put("leasePeriod", "租赁合同起止时间");
FIELD_DISPLAY_NAMES.put("rentPaymentTime", "国有资产租金缴纳时间");
FIELD_DISPLAY_NAMES.put("platformLease", "国有资产出租是否上平台");
FIELD_DISPLAY_NAMES.put("approvalDoc", "国有资产出租的审批文件");
FIELD_DISPLAY_NAMES.put("inBudget", "是否纳入预算");
FIELD_DISPLAY_NAMES.put("remark", "备注");
FIELD_DISPLAY_NAMES.put("workPaperIndex", "工作底稿索引");
}
// 获取分类的简要审计框架概述
public static String getBriefAuditFrameworkForCategory(String category) {
if (CATEGORY_STATE_ASSETS_MANAGEMENT.equals(category)) {
return "审计国有资产管理和政府采购执行情况,确保资产安全完整和采购规范";
}
return "审计国资管理情况";
}
}

View File

@@ -0,0 +1,147 @@
package com.gxwebsoft.ai.constants;
import java.util.HashMap;
import java.util.Map;
import java.util.Arrays;
import java.util.List;
/**
* 重大投资情况审计常量类
*/
public class AuditContent7Constants {
// 审计类别定义按审计内容7.txt要求
public static final String CATEGORY_MAJOR_INVESTMENT = "重大对外投资审计";
public static final String CATEGORY_MAJOR_PROJECT = "重大工程建设审计";
public static final String CATEGORY_MAJOR_CAPITAL = "重大资本运作审计";
public static final String CATEGORY_MAJOR_ASSET_DISPOSAL = "重大资产处置审计";
public static final String CATEGORY_MAJOR_PROCUREMENT = "重大物资(服务)采购审计";
public static final String CATEGORY_MAJOR_GUARANTEE = "重大担保借款审计";
// 审计类别描述
public static final Map<String, String> CATEGORY_DESCRIPTIONS = new HashMap<>();
static {
CATEGORY_DESCRIPTIONS.put(CATEGORY_MAJOR_INVESTMENT,
"核查重大对外投资决策的合规性和民主性、审批手续、可行性研究、效益情况、会计处理、操作过程等");
CATEGORY_DESCRIPTIONS.put(CATEGORY_MAJOR_PROJECT,
"工程建设项目决策程序、审批手续、安全质量、环保要求、效益情况等");
CATEGORY_DESCRIPTIONS.put(CATEGORY_MAJOR_CAPITAL,
"重大资本运作事项决策权限、审批程序、交易对价、资金来源、效益效果等");
CATEGORY_DESCRIPTIONS.put(CATEGORY_MAJOR_ASSET_DISPOSAL,
"重大资产处置决策程序、审批手续、交易价格、操作过程等");
CATEGORY_DESCRIPTIONS.put(CATEGORY_MAJOR_PROCUREMENT,
"重大采购项目可行性、决策程序、采购过程、价格公允性、效益效果等");
CATEGORY_DESCRIPTIONS.put(CATEGORY_MAJOR_GUARANTEE,
"重大担保借款决策程序、尽职调查、风险控制、后续跟踪等");
}
// 审计方法指令集从审计内容7.txt提取
public static final Map<String, String> AUDIT_INSTRUCTIONS = new HashMap<>();
static {
AUDIT_INSTRUCTIONS.put("GENERAL_RULE",
"审计方法及步骤:\n" +
"1收集全部企业的资产负债表和往来明细表审计企业\"未分配利润\"的情况,对应查看其往来明细表,分析审计企业债务的偿还能力和债券的回收机率。\n" +
"2收集对其他单位进行投资的项目的收益报表及往来情况审计投资的效益以及往来款项的回收机率。\n" +
"3对还在继续运营的特殊情况审计企业的收益能力分析继续运行的必要性、效益性。");
AUDIT_INSTRUCTIONS.put("DECISION_SYSTEM_CHECK",
"1、\"决策制度健全性验证\"指令:\n" +
"①制度存在性审查:根据关键字,检索被审计单位所有制度,是否有重大对外投资决策的制度规定\n" +
"②纵向合规性比对:将被审计单位的决策制度与国家、自治区、上级单位比较\n" +
"③横向一致性检查:与本单位其他制度比较,检查决策额度、表决比例、否决机制等多个维度的协同性\n");
AUDIT_INSTRUCTIONS.put("DECISION_PROCEDURE_CHECK",
"2、\"是否履行相应的决策程序\"指令:\n" +
"①决策程序完备性审查:根据被审计单位制度确定该项目是否属于重大投资\n" +
"②议事程序符合性审查:权限降级决策、参会人员范围、表决比例、材料替代违规、特别事项处理\n" +
"③民主决策真实性分析:发言均衡性检查、反对意见留存、表态顺序异常、决策逆转追踪\n" +
"④时序异常检查:立项时间、首次决策会日期、正式批准日、资金支付时间\n");
}
// 审计内容模板从审计内容7.txt提取的具体审计点
public static final Map<String, List<String>> AUDIT_CONTENT_TEMPLATES = new HashMap<>();
static {
// 重大对外投资审计内容
AUDIT_CONTENT_TEMPLATES.put(CATEGORY_MAJOR_INVESTMENT, Arrays.asList(
"核查重大对外投资决策的合规性和民主性。企业是否履行相应的决策程序或相关决策制度是否建立健全,是否经过相应级别的领导班子集体讨论决策,有无简化决策程序或在多数人表示反对意见下仍强行通过决策,即领导个人说了算的情况。",
"核查重大对外投资审批手续。核查被审计企业与履行出资人职责的机构是否有明确的授权范围,对照国资委的授权清单,查看对外投资事项是否属于国资监管部门核准或备案事项,对外投资事项是否属于国家禁止或控制的投资范围。",
"核查重大对外投资可行性研究和尽职调查情况。是否经过可行性研究,相关论证是否充分,是否经过多方案的比较优选和科学论证,是否按规定开展尽职调查。",
"核査对外投资项目的效益情况。梳理企业被审计年度对外投资项目的效益情况,与可行性研究的预期效益相比较,是否存在明显效益低下、严重亏损、计提大额减值等情况。",
"查看长期投资、短期投资、银行存款等会计科目的明细账,确定重大对外投资项目的入账价值,审阅账面价值是否符合投资合同和决策所确定的投资额,重大差异是否有合理原因。审阅资金支付是否经过投资决策、合规审核后支付,是否存在超前支付等情况。",
"查看相关费用类科目或长期投资、短期投资和银行存款等会计科目的明细账,分析有关中介费等费用支岀情况,核实是否存在大额的、可疑的、超合同支付的中间费用;关注溢价收购的交易价格是否合理,核查溢价收购产生的大额商誉,是否根据被收购企业未来业绩实际情况,制定相应的或有对价条款,从而调整交易对价、降低收购不确定性。",
"审核\"长期投资\"等会计科目,分析投资事项的运营效益,是否存在重大亏损;调取被投资项目(或企业)的运营情况、会计报表等,分析企业账面是否如实反映项目盈亏。",
"重大对外投资到期收回、出售或转让的,核实取得的对价是否及时入账;调取被投资企业投资分红账务资料,核实分红派息资金是否按时收回并入账。",
"审核决策程序。详细查阅党委(组)会、股东会、董事会、监事会、总经理办公会和专题小组会等会议记录和会议纪要。查看相关决策程序是否合规,有无严格落实重大事项决策经过党组织前置研究的规定,是否经相应领导级别会议讨论研究;查看决策内容是否民主科学,仔细查阅参会人员的发言,有无存在主持会议的领导人员在多数人持不同意见甚至反对意见的情况下仍强行通过决议的情况,即领导人员\"说了算\"的情况。",
"审核审批过程。按照深化国有企业改革精神和改革国有资本授权经营体制的要求,梳理履行出资人职责的机构对被审计企业的授权范围,核查关注的重大对外投资事项是否需要国资监管部门核准或备案,有无领导人员擅自决策、超权限决策的情况;对照企业投资负面清单,审核对外投资事项是否属于国家禁止或控制的投资范围,核查是否取得行业主管部门审批,相关审批手续是否完备。",
"审核调查论证。查阅对外投资事项从立项到决策实施整个过程的论证材料,如可行性研究报告、财务咨询报告、法律意见书等。应关注以下三个方面:一是立项背景,重大对外投资项目是否符合国家经济结构调整方向,如是否符合供给侧结构性改革和产业发展方向;二是企业发展战略,重大对外投资事项是否符合企业主业经营范围,是否符合企业中长期发展规划;三是预期效益,对比可行性研究报告、财务咨询报告中关于项目预期的经营效益、投资规模、筹资与还款计划、预计资金回收期等内容,判断有无盲目投资、超偿还能力筹措资金等情况。",
"审核操作过程。审查重大对外投资合同内容是否与企业集体决策内容相符,重大对外投资事项是否属于未公开的关联交易事项,相关交易价格是否经过专业机构评估,交易价格是否客观公允,会计师事务所、资产评估机构是否违反有关规定出具虚假报告,或领导人员违规指定交易方,先确定交易价格再进行资产评估,或领导人员擅自更改交易价格等。",
"审核效益效果。核査重大对外投资企业是否正常经营,有无存在被投资企业效益持续低下,严重亏损甚至已经资不抵债,效益远低于预期;投资参股后是否积极行使股东权利,履行股东义务,有无因擅自扩大投资规模导致严重亏损,人为提高交易价格向特定关系人输送利益等违规问题。"
));
// 重大工程建设审计内容(类似方式添加其他类别)
AUDIT_CONTENT_TEMPLATES.put(CATEGORY_MAJOR_PROJECT, Arrays.asList(
"工程建设项目是否经企业相应领导层级集体讨论研究,有无领导人员擅自决策,特别是领导班子多数人持不同意见的情况下仍强行通过决策的情况。",
"相关立项审批手续是否完善,根据国资国企授权经营体制改革的有关要求,重大工程建设项目是否符合企业投资项目负面清单范围,有无应报未报、未批先建、违规建设楼堂馆所等。",
"工程建设项目有无出现安全和质量事故,工程设备是否符合污染防治有关要求,相关工程废物、废渣、废水等是否得到有效收集和处理,工程建设是否造成环境污染,环保设施是否有效运营。",
"工程建设项目竣工投产后的效益情况,是否存在竣工投入使用后长期闲置、计提大额减值、效益远低于预期产生巨额亏损等。",
"审核决策程序。对选定的重大工程建设项目,应详细查看其会议纪要和会议记录,审阅管理制度、签报、审批文件等资料。查看相关决策事项是否履行相应决策程序,如是否经党组织前置研究和相应层级领导班子集体讨论研究,决策内容是否符合民主要求,有无被审计领导人员在多数人反对的情况下强行通过决策,即领导人员\"说了算\"的情况。",
"审核审批过程。根据深化国有企业改革精神和改革国有资本授权经营体制的要求,核查重大工程建设项目是否属于企业自主决策事项,是否需要国资监管部门核准或者备案,若属于其他行业主管部门审批事项,企业还应获得如发展改革委、住建部门、环保部门等主管部门的相关审批手续,有无未批先建,化整为零规避审批。",
"审核调查论证。查阅项目从立项到决策实施整个过程的论证材料,如可行性研究报告、财务咨询报告、法律意见书等。可行性研究报告的内容是否完整、真实;建设目标、建设规模是否符合企业发展需要,规划是否符合行业发展前景和产业政策。",
"审核操作过程。重大工程建设项目是否严格按照集体决策的方案开展,工程的建设质量、环保标准是否符合要求,是否有定期的质量检查,有无发生重大安全质量事故、发生重大环保污染问题被有关部门处罚,或者工程建设进度严重滞后、无法按期竣工等问题。",
"审核效益效果。重大工程建设项目的效益,主要是两个方面:一是效益是否达到预期。与可行性研究报告、财务咨询报告等比较,对比项目投产后是否达到预期效益;与市场上同类型项目效益对比,有无存在效益明显低于同类型项目的情况。二是工程建设项目的运营情况,是否存在项目竣工投产后运行未达预期、长期闲置,或因工程建设项目与市场需求严豆偏离计提重大减值,导致大额亏损等问题。"
));
// 其他类别类似添加...
}
// 关键词权重(用于知识检索排序)
public static final Map<String, Integer> KEYWORD_WEIGHTS = new HashMap<>();
static {
KEYWORD_WEIGHTS.put("重大投资", 10);
KEYWORD_WEIGHTS.put("对外投资", 9);
KEYWORD_WEIGHTS.put("工程建设", 9);
KEYWORD_WEIGHTS.put("资本运作", 9);
KEYWORD_WEIGHTS.put("资产处置", 9);
KEYWORD_WEIGHTS.put("物资采购", 9);
KEYWORD_WEIGHTS.put("担保借款", 9);
KEYWORD_WEIGHTS.put("决策程序", 8);
KEYWORD_WEIGHTS.put("审批手续", 8);
KEYWORD_WEIGHTS.put("可行性研究", 8);
KEYWORD_WEIGHTS.put("效益情况", 8);
KEYWORD_WEIGHTS.put("会议纪要", 7);
KEYWORD_WEIGHTS.put("会议记录", 7);
KEYWORD_WEIGHTS.put("可行性报告", 7);
KEYWORD_WEIGHTS.put("尽职调查", 7);
KEYWORD_WEIGHTS.put("关联交易", 7);
KEYWORD_WEIGHTS.put("价格公允", 7);
}
// 文件类型关键词(用于工作底稿索引)
public static final Map<String, List<String>> FILE_TYPE_KEYWORDS = new HashMap<>();
static {
FILE_TYPE_KEYWORDS.put("会议材料", Arrays.asList("会议通知", "签到表", "会议记录", "会议纪要", "会议决议", "会议录像"));
FILE_TYPE_KEYWORDS.put("审批文件", Arrays.asList("立项批复", "审批文件", "核准文件", "备案文件", "红头文件"));
FILE_TYPE_KEYWORDS.put("论证材料", Arrays.asList("可行性研究报告", "财务咨询报告", "法律意见书", "尽职调查报告", "专家论证意见"));
FILE_TYPE_KEYWORDS.put("合同协议", Arrays.asList("投资合同", "合作协议", "担保合同", "借款合同", "采购合同", "转让协议"));
FILE_TYPE_KEYWORDS.put("财务资料", Arrays.asList("资产负债表", "利润表", "现金流量表", "往来明细表", "会计凭证", "银行流水"));
FILE_TYPE_KEYWORDS.put("评估报告", Arrays.asList("资产评估报告", "审计报告", "验资报告", "价值评估报告"));
}
private AuditContent7Constants() {
// 防止实例化
}
/**
* 获取所有审计类别(按顺序)
*/
public static List<String> getAllCategories() {
return Arrays.asList(
CATEGORY_MAJOR_INVESTMENT,
CATEGORY_MAJOR_PROJECT,
CATEGORY_MAJOR_CAPITAL,
CATEGORY_MAJOR_ASSET_DISPOSAL,
CATEGORY_MAJOR_PROCUREMENT,
CATEGORY_MAJOR_GUARANTEE
);
}
}

View File

@@ -0,0 +1,195 @@
package com.gxwebsoft.ai.constants;
import java.util.*;
/**
* 审计内容8 - 单位层面财务管理内部控制测试常量类
*/
public class AuditContent8InternalControlConstants {
// 16个控制环节
public static final String[] CONTROL_LINKS = {
"有关部门或岗位财务管理职能划分",
"财务管理岗位设置及职责划分",
"财务管理岗位人员配备",
"财务管理关键岗位人员轮岗",
"财务管理事项授权审批(核)",
"财务管理重大事项决定",
"会计核算与文档管理",
"财务电子信息管理",
"重要财务管理事项的信息沟通",
"财务管理风险评估",
"财务管理风险应对",
"内部审计与监督检查",
"反舞弊",
"财务管理内部控制评价",
"财务管理内部控制缺陷跟踪与改进",
"财务管理内部控制实施情况纳入考核体系"
};
// 控制要求
public static final Map<String, String> CONTROL_REQUIREMENTS = new HashMap<>();
static {
CONTROL_REQUIREMENTS.put(CONTROL_LINKS[0], "财务管理决策、执行与监督职能相互分离");
CONTROL_REQUIREMENTS.put(CONTROL_LINKS[1], "财务管理不相容职务相互分离并相互制约");
CONTROL_REQUIREMENTS.put(CONTROL_LINKS[2], "财务管理岗位人员配备符合规定与岗位要求");
CONTROL_REQUIREMENTS.put(CONTROL_LINKS[3], "关键岗位实行定期轮岗,不具备轮岗条件的实施其他替代措施");
CONTROL_REQUIREMENTS.put(CONTROL_LINKS[4], "全部财务管理业务实施授权审批(核)");
CONTROL_REQUIREMENTS.put(CONTROL_LINKS[5], "财务管理重大事项均由单位领导层集体研究决定");
CONTROL_REQUIREMENTS.put(CONTROL_LINKS[6], "会计核算及其档案管理规范,会计信息准确");
CONTROL_REQUIREMENTS.put(CONTROL_LINKS[7], "信息系统开发、运行和维护以及用户管理与数据备份规范,信息安全");
CONTROL_REQUIREMENTS.put(CONTROL_LINKS[8], "对于重要财务管理事项均进行信息沟通");
CONTROL_REQUIREMENTS.put(CONTROL_LINKS[9], "对于财务管理风险能够进行识别、评估与预防");
CONTROL_REQUIREMENTS.put(CONTROL_LINKS[10], "对于出现的财务管理风险能够应对与控制");
CONTROL_REQUIREMENTS.put(CONTROL_LINKS[11], "对于发生的财务管理业务进行定期与不定期的审计与监督检查");
CONTROL_REQUIREMENTS.put(CONTROL_LINKS[12], "及时察觉与处置财务舞弊事件");
CONTROL_REQUIREMENTS.put(CONTROL_LINKS[13], "对于财务管理内部控制实施评价,并取得成效");
CONTROL_REQUIREMENTS.put(CONTROL_LINKS[14], "跟踪发现的财务管理内部控制缺陷,及时进行改进");
CONTROL_REQUIREMENTS.put(CONTROL_LINKS[15], "在单位考核体系中包含财务管理内部控制实施情况内容");
}
// 控制活动描述
public static final Map<String, String> CONTROL_ACTIVITIES = new HashMap<>();
static {
CONTROL_ACTIVITIES.put(CONTROL_LINKS[0], "按照决策、执行与监督职能相互分离的要求确定有关部门或岗位的财务管理职能,由财务管理部门提出意见,报经分管领导审核,经单位领导层集体审批后实施");
CONTROL_ACTIVITIES.put(CONTROL_LINKS[1], "按照不相容职务相互分离的要求设置财务管理岗位,所有岗位具有明确的职责,由财务管理部门提出意见,报经分管领导审核,经单位领导层集体审批后实施");
CONTROL_ACTIVITIES.put(CONTROL_LINKS[2], "按照有关规定与岗位要求配备财务管理人员,各岗位均有明确的任职要求,由财务管理部门提出意见,报经分管领导审核,经单位领导层集体审批后实施");
CONTROL_ACTIVITIES.put(CONTROL_LINKS[3], "对于财务管理部门负责人与其他关键岗位人员按照规定进行轮岗、相关人员实行回避,不具备轮岗条件的实施其他替代措施,由财务管理部门提出意见,报经分管领导审核,经单位领导层集体审批后实施");
CONTROL_ACTIVITIES.put(CONTROL_LINKS[4], "对于财务管理业务授权审批的范围、权限、程序与责任具有明确的规定,由财务管理部门提出意见,报经分管领导审核,经单位领导层集体审批后实施");
CONTROL_ACTIVITIES.put(CONTROL_LINKS[5], "对于单位部门预算、大额资金使用、大宗设备采购或重大服务购买、基本建设等重大财务事项均有明确的决定或会签制度规定,由财务管理部门提出意见,报经分管领导审核,经单位领导层集体审批后实施");
CONTROL_ACTIVITIES.put(CONTROL_LINKS[6], "对于会计凭证、会计账簿和会计报告处理程序以及会计档案管理具有明确的规定,由财务管理部门提出意见,报经分管领导审核,经单位领导层集体审批后实施");
CONTROL_ACTIVITIES.put(CONTROL_LINKS[7], "对于财务管理信息系统的开发、运行和维护以及用户管理与系统数据备份,信息系统安全保密和泄密责任追究具有明确的规定,由财务管理部门提出意见,报经分管领导审核,经单位领导层集体审批后实施");
CONTROL_ACTIVITIES.put(CONTROL_LINKS[8], "对于财务管理重要事项建立信息沟通制度,由财务管理部门提出意见,报经分管领导审核,经单位领导层集体审批后实施");
CONTROL_ACTIVITIES.put(CONTROL_LINKS[9], "对于财务管理风险具有明确工作内容与要求的评估预防体系与工作机制,由财务管理部门提出意见,报经分管领导审核,经单位领导层集体审批后实施");
CONTROL_ACTIVITIES.put(CONTROL_LINKS[10], "对于出现的财务管理风险具有应对机制与控制措施,由财务管理部门提出意见,报经分管领导审核,经单位领导层集体审批后实施");
CONTROL_ACTIVITIES.put(CONTROL_LINKS[11], "设有独立的内审部门或审计岗位并有明确的职责要求,对内部审计与财务管理监督检查具有明确的规定,由审计管理部门提出意见,报经分管领导审核,经单位领导层集体审批后实施");
CONTROL_ACTIVITIES.put(CONTROL_LINKS[12], "对于财务管理舞弊具有举报投诉制度和举报人保护制度以及全体员工被告知制度,对于举报投诉的财务管理舞弊事件与问题的处置具有明确的规定,由财务管理部门提出意见,报经分管领导审核,经单位领导层集体审批后实施");
CONTROL_ACTIVITIES.put(CONTROL_LINKS[13], "设立或指定财务管理内部控制评价的职能部门与岗位,对于财务管理内部控制评价工作的计划、要求具有明确的规定,由财务管理内部控制评价部门提出意见,报经分管领导审核,经单位领导层集体审批后实施");
CONTROL_ACTIVITIES.put(CONTROL_LINKS[14], "对于财务管理内部控制缺陷具有跟踪与改进制度,对于整改的实施与后续的检查具有明确的规定,由财务管理内部控制评价部门提出意见,报经分管领导审核,经单位领导层集体审批后实施");
CONTROL_ACTIVITIES.put(CONTROL_LINKS[15], "对于财务管理内部控体系建设与执行在单位的考核制度中具有明确的考核规定,由财务管理内部控制评价部门提出意见,报经分管领导审核,经单位领导层集体审批后实施");
}
// 控制职责岗位
public static final Map<String, String> CONTROL_POSITIONS = new HashMap<>();
static {
CONTROL_POSITIONS.put(CONTROL_LINKS[0], "财务管理部门负责人、分管领导");
CONTROL_POSITIONS.put(CONTROL_LINKS[1], "财务管理部门负责人、分管领导");
CONTROL_POSITIONS.put(CONTROL_LINKS[2], "财务管理部门负责人、分管领导");
CONTROL_POSITIONS.put(CONTROL_LINKS[3], "财务管理部门负责人、分管领导");
CONTROL_POSITIONS.put(CONTROL_LINKS[4], "财务管理部门负责人、分管领导");
CONTROL_POSITIONS.put(CONTROL_LINKS[5], "财务管理部门负责人、分管领导");
CONTROL_POSITIONS.put(CONTROL_LINKS[6], "财务管理部门负责人、分管领导");
CONTROL_POSITIONS.put(CONTROL_LINKS[7], "财务管理部门负责人、分管领导");
CONTROL_POSITIONS.put(CONTROL_LINKS[8], "财务管理部门负责人、分管领导");
CONTROL_POSITIONS.put(CONTROL_LINKS[9], "财务管理部门负责人、分管领导");
CONTROL_POSITIONS.put(CONTROL_LINKS[10], "财务管理部门负责人、分管领导");
CONTROL_POSITIONS.put(CONTROL_LINKS[11], "审计管理部门负责人、分管领导");
CONTROL_POSITIONS.put(CONTROL_LINKS[12], "财务管理部门负责人、分管领导");
CONTROL_POSITIONS.put(CONTROL_LINKS[13], "财务管理内部控制评价部门负责人、分管领导");
CONTROL_POSITIONS.put(CONTROL_LINKS[14], "财务管理内部控制评价部门负责人、分管领导");
CONTROL_POSITIONS.put(CONTROL_LINKS[15], "财务管理内部控制评价部门负责人、分管领导");
}
// 测试步骤
public static final Map<String, List<String>> TEST_STEPS = new HashMap<>();
static {
TEST_STEPS.put(CONTROL_LINKS[0], Arrays.asList(
"1是否有制度规定",
"2单位有关部门或岗位财务管理职能设置是否符合相互分离规定",
"3通过观察、询问以及查阅有关工作文档等方式检查单位财务管理组织体系中的决策、执行与监督职能是否实现了分离"
));
TEST_STEPS.put(CONTROL_LINKS[1], Arrays.asList(
"1是否有制度规定",
"2单位财务管理岗位设置与职责划分是否符合不相容岗位相互分离规定",
"3通过观察、询问以及查阅有关工作文档等方式检查财务管理岗位不相容职务是否实现了分离"
));
TEST_STEPS.put(CONTROL_LINKS[2], Arrays.asList(
"1是否有制度规定",
"2财务管理岗位配备的人员是否符合任职资质要求",
"3重要财务管理岗位人员的专业背景、工作经验及有关执业资质是否能够胜任岗位工作需要"
));
TEST_STEPS.put(CONTROL_LINKS[3], Arrays.asList(
"1是否有制度规定",
"2通过观察、询问以及查阅有关工作文档等方式检查财务管理关键岗位是否进行了轮岗或采取了其他替代措施"
));
TEST_STEPS.put(CONTROL_LINKS[4], Arrays.asList(
"1是否有制度规定",
"2通过观察、询问以及查阅有关工作文档等方式检查单位财务管理业务流程中的各个审批环节的操作是否符合授权审批规定"
));
TEST_STEPS.put(CONTROL_LINKS[5], Arrays.asList(
"1是否有制度规定",
"2通过观察、询问以及查阅有关工作文档等方式检查单位财务管理重大事项是否由领导层集体研究决定或会签且研究决定或会签记录内容完整"
));
TEST_STEPS.put(CONTROL_LINKS[6], Arrays.asList(
"1是否有制度规定",
"2通过观察、询问以及查阅有关工作文档等方式检查单位会计核算流程是否符合制度规定",
"3通过观察、询问以及查阅有关工作文档等方式检查单位是否有专职岗位负责会计档案保管且档案文件保管情况良好"
));
TEST_STEPS.put(CONTROL_LINKS[7], Arrays.asList(
"1是否有制度规定",
"2通过观察、询问以及查阅有关工作文档等方式检查单位是否按规定进行了信息系统的开发、运行和维护以及用户管理与数据备份"
));
TEST_STEPS.put(CONTROL_LINKS[8], Arrays.asList(
"1是否有制度规定",
"2通过观察、询问以及查阅有关工作文档等方式检查单位财务管理有关重要事项是否通过会议、内部报告或会签等方式进行信息沟通"
));
TEST_STEPS.put(CONTROL_LINKS[9], Arrays.asList(
"1是否有制度规定",
"2通过观察、询问以及查阅有关工作文档等方式检查单位是否进行了财务管理风险的识别、评估与预防工作"
));
TEST_STEPS.put(CONTROL_LINKS[10], Arrays.asList(
"1是否有制度规定",
"2通过观察、询问以及查阅有关工作文档等方式检查单位是否对出现的财务风险进行了应对并采取了控制措施"
));
TEST_STEPS.put(CONTROL_LINKS[11], Arrays.asList(
"1是否有制度规定",
"2是否设置了独立的审计部门或审计岗位",
"3通过观察、询问以及查阅有关工作文档等方式检查单位内审部门是否定期或不定期对财务管理业务进行审计与监督检查",
"4通过观察、询问以及查阅有关工作文档等方式检查单位内审部门能否及时发现财务管理中的问题督促整改"
));
TEST_STEPS.put(CONTROL_LINKS[12], Arrays.asList(
"1是否有制度规定",
"2通过观察、询问以及查阅有关工作文档等方式检查单位员工是否知晓财务管理舞弊的举报投诉制度和举报人保护制度",
"3通过观察、询问以及查阅有关工作文档等方式检查单位对于举报投诉的财务管理舞弊事件与问题是否及时进行了处置"
));
TEST_STEPS.put(CONTROL_LINKS[13], Arrays.asList(
"1是否有制度规定",
"2是否设立或指定有财务管理内部控制评价的职能部门与岗位",
"3通过观察、询问以及查阅有关工作文档等方式检查单位是否有财务管理内部控制评价工作计划与工作要求",
"4通过观察、询问以及查阅有关工作文档等方式检查单位是否按计划开展了财务管理内部控制评价工作促进了单位财务管理内部控制体系的建立健全"
));
TEST_STEPS.put(CONTROL_LINKS[14], Arrays.asList(
"1是否有制度规定",
"2通过观察、询问以及查阅有关工作文档等方式检查单位对于发现的内部控制缺陷是否及时通报与跟踪",
"3通过观察、询问以及查阅有关工作文档等方式检查单位对于发现的缺陷是否及时进行了整改"
));
TEST_STEPS.put(CONTROL_LINKS[15], Arrays.asList(
"1是否有制度规定",
"2通过观察、询问以及查阅有关工作文档等方式检查单位的考核制度中是否将财务管理内部控制实施情况列入了考核内容中",
"3通过观察、询问以及查阅有关工作文档等方式检查单位在实际进行考核中对财务管理内部控制实施情况的考核内容"
));
}
// 关键词权重
public static final Map<String, Integer> KEYWORD_WEIGHTS = new HashMap<>();
static {
KEYWORD_WEIGHTS.put("内部控制", 10);
KEYWORD_WEIGHTS.put("财务管理", 9);
KEYWORD_WEIGHTS.put("不相容职务分离", 9);
KEYWORD_WEIGHTS.put("授权审批", 8);
KEYWORD_WEIGHTS.put("集体决策", 8);
KEYWORD_WEIGHTS.put("会计档案", 7);
KEYWORD_WEIGHTS.put("信息系统", 7);
KEYWORD_WEIGHTS.put("风险识别", 8);
KEYWORD_WEIGHTS.put("风险评估", 8);
KEYWORD_WEIGHTS.put("内部审计", 9);
KEYWORD_WEIGHTS.put("反舞弊", 9);
KEYWORD_WEIGHTS.put("内部控制评价", 8);
KEYWORD_WEIGHTS.put("岗位轮岗", 7);
KEYWORD_WEIGHTS.put("考核体系", 7);
}
private AuditContent8InternalControlConstants() {
// 防止实例化
}
}

View File

@@ -0,0 +1,273 @@
package com.gxwebsoft.ai.constants;
import java.util.*;
/**
* 审计内容9 - 人员编制管理审计常量类
*/
public class AuditContent9PersonnelConstants {
// 7个审计内容
public static final String[] AUDIT_CONTENTS = {
"检查劳务派遣用工的合规性",
"核查被审计单位是否通过'假外包,真派遣'形式规避用工责任及成本",
"检查人员经费的使用是否规范",
"检查借用人员管理规范性",
"绩效管理体系健全性、合规性",
"检查机构编制合规性",
"预算编制与实际执行差异"
};
// 审计子内容映射
public static final Map<String, List<AuditSubContent>> AUDIT_SUB_CONTENTS = new LinkedHashMap<>();
static {
// 1. 检查劳务派遣用工的合规性
AUDIT_SUB_CONTENTS.put(AUDIT_CONTENTS[0], Arrays.asList(
new AuditSubContent(
"1.检查劳务派遣人数占企业用工总量比例是否≤10%",
"年度、半年度或月度员工花名册(区分正式工与派遣工,标注入职时间)",
"核查被审计单位审计期间年度(或半年度或月度)用工情况,计算派遣工占比,\n公式如下派遣工比例=派遣工人数/(正式工人数+派遣工人数)\n合规标准该比例不得超过10%。若计算结果10%,则判定为用工比例不合规。",
"合并生成一个审计取证单",
"①劳务派遣暂行规定_人力资源和社会保障部_中国政府网——第四条\n②《中华人民共和国劳动合同法》第六十六条"
),
new AuditSubContent(
"2.检查派遣岗位是否均符合'三性'标准临时性≤6个月辅助性替代性",
"①劳务派遣合同及岗位说明书;涉及转正的,需补充提供劳动合同;\n②职代会决议文件并附公示记录照片\n③核心岗位清单\n④如涉及替代性岗位需提供原岗位员工的脱产、休假证明等。",
"岗位标准派遣岗位仅限于临时性不超过6个月、辅助性需职代会通过并公示、替代性如产假顶岗岗位。核心岗位如技术、管理等必须转为正式工用工单位决定使用被派遣劳动者的辅助性岗位应当经职工代表大会或者全体职工讨论提出方案和意见与工会或者职工代表平等协商确定并在用工单位内公示。\n①核查临时性工作岗位存续时间若超过6个月则判定该岗位不符合劳务派遣的临时性规定\n②核查派遣岗位名称是否与公示辅助性岗位清单一致不一致则违反劳务派遣辅助性规定\n③检查替代性岗位是否提供休假证明等材料若材料无法证实其符合设立条件则派遣岗位设立存在瑕疵违反劳务派遣的替代性规定。",
"",
"①劳务派遣暂行规定_人力资源和社会保障部_中国政府网——第三条\n②《中华人民共和国劳动合同法》第六十六条"
),
new AuditSubContent(
"3.检查派遣工与同类岗位的正式工是否同工同酬",
"正式工与派遣工薪酬对比表(或工资表)、社保缴纳凭证、福利发放记录",
"对同一(类)岗位的劳务派遣和正式工进行薪酬差额分析,并形成派遣工权益保障差异分析记录:\n①核查社保是否按用工单位所在地标准缴纳\n②抽检加班费、绩效奖金及福利待遇等项目的核算差异。",
"",
"①劳务派遣暂行规定_人力资源和社会保障部_中国政府网——第七、第九条\n②《中华人民共和国劳动合同法》第六十三条"
),
new AuditSubContent(
"4.检查工伤处理程序中用工单位的配合义务履行情况",
"①工伤事故通报派遣单位的书面记录;\n②用工单位参与工伤调查的会议纪要/现场核查记录;\n③职业病诊断过程记录委托书、交接单等\n④提供的职业史证明、危害因素检测报告\n⑤《劳务派遣协议》关于工伤保险责任条款及补偿办法\n⑥用工单位支付协议约定补偿的财务凭证",
"①工伤事故:检查事故发生后及时向派遣单位通报的证据;核实派员参与调查、提供现场材料的记录;\n②职业病诊断确认用工单位是否主动处理诊断事宜如对接机构验证所提供职业史、检测报告的真实性比对考勤、检测备案\n③责任约定审查协议是否包含'用工单位不承担工伤保险责任'等违法条款;核查补偿办法中用工单位义务的财务履行凭证;\n④询问访谈近审计期间工伤派遣工核实用工单位配合度。",
"",
"①劳务派遣暂行规定_人力资源和社会保障部_中国政府网——第十条\n②《工伤保险条例》第十七条、第十九条\n③《中华人民共和国职业病防治法》第四十七条\n④企业内控制度"
)
));
// 2. 核查被审计单位是否通过"假外包,真派遣"形式规避用工责任及成本
AUDIT_SUB_CONTENTS.put(AUDIT_CONTENTS[1], Arrays.asList(
new AuditSubContent(
"1.确认'外包'合同约定的是'劳务派遣'还是'劳务外包'的法律关系",
"外包合同及其补充协议",
"检查合同条款性质认定的关键要点:\n①若合同约定发包单位享有人员'用工管理权',包括直接调配权及要求员工遵守发包方《员工手册》等管理规定,则构成'劳务派遣'法律关系;若合同主要约定'业务成果验收标准',且外包公司自主安排生产服务、负责人员考勤管理,则构成'劳务外包'法律关系。\n②费用结算条款约定'按项目工作量'还是'验收成果计费':如存在以'人员数量、岗位配置、服务时长或出勤天数(隐含'人头费'逻辑)'等指标结算费用的情形,则构成'劳务派遣'法律关系;如基于'基于项目成果结算',如验收合格报告数量、项目阶段交付清单等,则构成'劳务外包'法律关系。",
"合并生成一个审计取证单。\n取证单主要内容包括审计调查事项摘要、处理建议、附件与问题相匹配的支撑资料即工作底稿索引等。\n其中'审计(调查)事项摘要'包含:标题、审计记录、审计发现、定性依据。\n1.标题:突出核心问题,采用观点性语句。一般为审计内容、审计目标的结论性描述。例如:\n在审计期间XX单位存在'假外包,真派遣'行为。\n2.审计记录:仅客观记录审计核查的具体事实(时间、地点、主体、行为、数据等);不使用主观评价性语言(如'违规''不合理')或问题判断性表述;确保事实可交叉验证(引证合同条款、凭证编号等原始文件)。一般采用白描句式:'经核查[具体资料/凭证],……[事实描述]……'例如:\n① 核查2019年1月1日签订的《XX服务合同》编号XYZ-2019-001第3条约定'乙方(服务商)员工需遵守甲方考勤制度,甲方有权对乙方人员工作质量进行考核并决定留用'。\n② 调取2019年6月外包人员考勤表显示实际出勤记录由甲方部门主管李某签字确认绩效评分由甲方人力资源部核定。\n③ 查验2020年3月服务费结算凭证凭证号FV20200315所附明细清单按外包人员当月计薪天数×日工资标准核算费用。\n3.审计发现:基于审计记录的事实,提炼违反规定的具体问题性质。需明确界定违规行为的实质特征。同一性质问题应合并表述,避免分段罗列。一般采用定性句式:'上述行为实质构成……[问题性质]/ 形成……[违规形态]'。例如:\n审计发现该单位通过签订名义上的《劳务外包合同》实际由发包单位直接管理外包人员工作过程并控制费用结算标准形成事实上的劳务派遣用工关系构成'假外包、真派遣'行为。\n4.定性依据:违反的法律法规、政策规定及被审计单位内部管理制度等。\n选择优先级法律法规>部门规章>地方政府规范性文件>被审计单位内部制度。\n引用规范标明文件全称、文号及具体条款引述条款内容须与问题直接对应同时违反多层级规定的按效力层级降序排列。例如\n定性依据\n①《劳务派遣暂行规定》人社部令第22号第三条'用工单位只能在临时性、辅助性或者替代性的工作岗位上使用被派遣劳动者'。\n②被审计单位《XX管理办法》XX集团201835号第X条'……'。",
"①《中华人民共和国劳动合同法》及其实施条例;\n②《中华人民共和国民法典》"
),
new AuditSubContent(
"2.检查发包单位是否实质上直接管理外包人员及其工作过程",
"①考勤记录打卡截图、门禁刷卡数据、OA系统工作安排如能获取、绩效目标确认文件、扣罚工资记录\n②发包单位《员工手册》、奖惩记录\n③工位证明、工卡门禁卡或身份标识卡发放或佩戴要求、设备领用记录。",
"①核实发包单位是否直接安排、记录和处罚外包人员考勤查看考勤记录如钉钉打卡截图、门禁刷卡数据、绩效目标确认文件、OA系统工作安排记录、工资扣罚凭证如'早退扣款'记录),若上述安排、记录和处罚由发包单位直接进行(而非外包公司执行),则表明发包单位存在实际考勤管理权,构成'实质派遣'。\n②核实发包单位的《员工手册》等规章制度是否明确适用于外包人员并被执行审阅发包单位《员工手册》、奖惩通知如警告、调岗通知、工资条或相关记录若实际操作中发包单位可直接对外包人员进行警告、调岗、扣款或奖励等管理动作强有力地证明发包单位的实质性管理权限已延伸至外包人员构成'实质派遣'\n③核实外包人员的工作环境和工作工具由谁提供和控制查看外包人员在发包单位的工位安排记录、工卡发放记录、工作设备领用登记。若外包人员日常在发包单位固定场所工作使用发包单位提供的专属工位、标识如工卡、电脑设备等表明其工作环境高度受控于发包单位构成'实质派遣'。",
"",
"①《中华人民共和国劳动合同法》及其实施条例;\n②《中华人民共和国民法典》"
),
new AuditSubContent(
"3.核查劳务外包服务的费用结算依据是否符合外包法律特征",
"①结算相关的凭证:付款审批单,结算单据(如项目验收单、承揽书、成果清单及对应金额),发票;\n②访谈记录文档或音频",
"1.检查凭证,验证实际结算方式。\n检查付款审批流程中的结算依据以及外包公司提供的结算材料\n①如果结算材料表明该'外包'实际以'人员数量、岗位配置、服务时长或出勤天数(隐含'人头费'逻辑)'等指标结算费用,则构成'实质派遣'。\n②'劳务外包'结算需以项目成果为依据,形成合同→验收单→发票的完整凭证链。结算金额与成果量挂钩,结算单、请款函等文件需基于项目验收单、承揽书等成果凭证生成,以此构成'劳务外包'的合规流程。\n2.访谈财务及外包项目负责人,核实以下事项:\n①费用计算依据若与外包人员数量及工时无关则属于真实'劳务外包';反之,可能构成'劳务派遣'\n②结算调整机制项目延期或增量时真实外包应以成果变更调整结算而非仅追加人员费用。",
"",
"①《中华人民共和国劳动合同法》及其实施条例;\n②《中华人民共和国民法典》"
)
));
// 3. 检查人员经费的使用是否规范
AUDIT_SUB_CONTENTS.put(AUDIT_CONTENTS[2], Arrays.asList(
new AuditSubContent(
"1.检查工资总额控制:工资性支出是否突破国资监管部门核定的年度总额上限,及超限额部分是否按规定完成审批报备",
"① 年度工资总额批复文件;\n② 年度工资汇总统计表;\n③ 超预算调整审批记录",
"核查实发工资总额与批复额度的一致性,确认超支部分是否履行相关决策程序(如职工代表大会审议、国资委备案等),并列出工资总额执行差异",
"生成审计取证单",
"①自治区国资委关于印发《自治区国资委履行出资人职责企业工资总额管理办法》的通知 - 政务公开 - 防城港市人民政府 -\n②企业内控制度\n③《中华人民共和国劳动合同法》第四条 职工代表大会"
),
new AuditSubContent(
"2.检查福利费列支范围:福利费支出的合规性,有无违规发放补贴、变相薪酬行为",
"① 福利费明细账及原始凭证;\n② 职工福利制度文件;\n③ 补贴发放签收记录",
"对福利费支出项目进行抽查,依据制度文件审核合规性,发现违规支出的,列出超范围支出明细清单。",
"生成审计取证单",
"①财政部关于企业加强职工福利费财务管理的通知\n②企业内控制度"
),
new AuditSubContent(
"3.检查劳务费真实性:是否存在虚构人员套取资金等虚假劳务支出行为",
"① 劳务合同;\n② 服务成果交付证明(如报告、验收单);\n③ 支付凭证(包括收款方信息及银行流水)",
"①通过天眼查或国家企业信用信息公示系统核查劳务提供方身份真实性;\n②对比服务成果与合同约定内容是否匹配\n③对核查中发现的问题如实记录。",
"生成审计取证单",
"①《中华人民共和国会计法》第四十三条\n②《财政违法行为处罚处分条例》第七条"
)
));
// 4. 检查借用人员管理规范性
AUDIT_SUB_CONTENTS.put(AUDIT_CONTENTS[3], Arrays.asList(
new AuditSubContent(
"1.检查借用程序合规性",
"①借调相关材料(含沟通记录及正式文件),三方协议(如有)\n②实际在岗证明文件考勤记录\n③续借审批文件",
"①借用必要性审查:根据借调相关材料,核查借调事由是否合理,是否存在以工作专班、跟班学习或交流锻炼等名义变相借调的情况。\n②借用程序合规性审查对照单位借用人员制度核查借调审批手续是否齐全以及是否经本单位党组党委审批并报同级党委组织部门备案。\n③借用期限审查核查借调文件约定的首次借调期限是否超过6个月结合实际在岗证明文件考勤记录若实际存在延期情形是否已提前征得派出单位和本人同意。",
"合并生成一个审计取证单",
"①中共中央办公厅 国务院办公厅印发《整治形式主义为基层减负若干规定》————头条——中央纪委国家监委网站;\n②企业内控制度"
),
new AuditSubContent(
"2.检查经费列支规范性:借用人员费用报销等是否存在重复列支或违规转嫁费用行为",
"①审计期间借用人员名单;\n②费用报销凭证及其明细账\n③借用人员访谈记录",
"根据借用人员名单,在费用报销明细账中核查相关报销记录。依据借调文件或三方协议中明确的福利待遇等承担主体,结合对借用人员的访谈记录,审查是否存在同一借用人员的费用同时在借出单位与借入单位列支的情况。",
"",
"①中共中央办公厅 国务院办公厅印发《整治形式主义为基层减负若干规定》————头条——中央纪委国家监委网站;\n②企业内控制度"
)
));
// 5. 绩效管理体系健全性、合规性
AUDIT_SUB_CONTENTS.put(AUDIT_CONTENTS[4], Arrays.asList(
new AuditSubContent(
"1.确认绩效管理体系健全、制度流程符合法规要求",
"①所有内控制度\n②绩效考核制度发文记录、职工代表大会审议签字文件、制度修订记录等",
"①制度存在性审查:根据关键字,检索被审计单位所有制度,是否有员工绩效考核的制度规定。如有派遣工的,需检查是否有管派遣工的考核管理,并输出《制度清单》(含制度名称、文号、生效日期、具体条文等)。\n②纵向合规性比对将被审计单位的考核办法与国家、自治区、上级单位比较检查是否存在与上级制度相悖的情况并标记冲突点。\n③横向一致性检查与本单位的薪酬分配、干部管理、廉洁从业等其他内部控制制度比较检查绩效考核的协同性是否存在单位制度'左右脑互博'的情况,并标记冲突点。\n④确认是否绩效考核体系制度的设立是否已履行民主程序应当经职工代表大会或全体职工讨论协商确定\n⑤根据以上检测出的问题生成《绩效管理体系健全性、合规性审查审计取证单》含客观事实描述、违规性质是否需要、制度依据、审计建议等内容。",
"合并生成一个审计取证单",
"①《中华人民共和国劳动合同法》第四条;\n②《中央企业负责人经营业绩考核办法》\n③国务院国资委《企业绩效评价标准值》每年更新\n⑤国资委回复国有企业考核分配、工资总额相关的25个问题 http://www.sasac.gov.cn/n2588040/n2590387/n9854182/index.html\n⑥自治区国资委关于印发《关于进一步深化自治区国资委履行出资人职责企业劳动用工和收入分配制度改革的指导意见试行》的通知\n⑦企业内控制度等"
),
new AuditSubContent(
"2.绩效考核程序执行规范性",
"①考核表确认记录;\n②民主评议、领导评价记录\n③绩效考核相关会议纪要、记录\n④申诉处理记录如有",
"①每个部门各抽查X份记录检查考核表、民主评议、领导评价记录及其签字的完整性\n②如有申述检查申诉响应时效\n③生成《绩效考核程序执行规范性审计取证单》",
"",
"企业内控制度"
),
new AuditSubContent(
"3.绩效考核结果合规性",
"①工资计算表\n②职务任免文件",
"①检查工资计算与绩效考核结果是否呈正相关;\n②审核晋升人员绩效排名情况是否存在低绩效仍获晋升的现象。",
"",
"企业内控制度"
),
new AuditSubContent(
"4.验证系统数据准确性",
"①HR系统考核记录\n②纸质存档文件\n③工资发放明细",
"抽查样本,核验系统与纸质文件数据的一致性,并检查人员绩效等级是否存在差异",
"",
"企业内控制度"
)
));
// 6. 检查机构编制合规性
AUDIT_SUB_CONTENTS.put(AUDIT_CONTENTS[5], Arrays.asList(
new AuditSubContent(
"1.验证编制审批流程是否完整",
"机构设立批文、编制批文('三定'方案)",
"对比实际部门数量与编制文件;检查新增机构是否经上级编办审批",
"合并生成一个审计取证单",
"①《中国共产党机构编制工作条例》;\n②《'三定'规定制定和实施办法》559920f6ac788c5c8b2ee86842f36a96.pdf——行政事业单位适用\n③《机构编制监督检查工作办法》\n④机构编制违规违纪违法行为处理和问责规则试行"
),
new AuditSubContent(
"2.验证是否按批复编制设置部门",
"被审计单位组织架构图、职能说明书",
"对比实际部门设置与编制文件是否一致;检查新增机构是否经上级编办审批,识别并标注是否存在未经批复的新增、撤销的临时机构。",
"",
"①《中国共产党机构编制工作条例》;\n②《'三定'规定制定和实施办法》559920f6ac788c5c8b2ee86842f36a96.pdf——行政事业单位适用\n③《机构编制监督检查工作办法》\n④机构编制违规违纪违法行为处理和问责规则试行"
),
new AuditSubContent(
"3.被审计单位职数是否超标",
"党委、董事会成员名单、高管任职文件、员工花名册(含职务、职级等)",
"统计实际高管人数,并比对编制文件规定的领导职数阈值;",
"",
"①《中国共产党机构编制工作条例》;\n②《'三定'规定制定和实施办法》559920f6ac788c5c8b2ee86842f36a96.pdf——行政事业单位适用\n③《机构编制监督检查工作办法》\n④机构编制违规违纪违法行为处理和问责规则试行"
),
new AuditSubContent(
"4.编制总量控制:岗位编制是否超核定标准",
"编制核定表、社保缴纳人数统计",
"抓取编制批文中机构名称、编制数量,与被审计单位实际部门清单、人力资源部门岗位数量自动比对。",
"",
"①《中国共产党机构编制工作条例》;\n②《'三定'规定制定和实施办法》559920f6ac788c5c8b2ee86842f36a96.pdf——行政事业单位适用\n③《机构编制监督检查工作办法》\n④机构编制违规违纪违法行为处理和问责规则试行"
),
new AuditSubContent(
"5.编制调整是否履行审批",
"编制调整审批文件可能包含OA系统日志",
"需结合被审计单位、国资委或上级单位关于编制调整的审批流程判断。另检查编制调整流程是否在OA系统完整留痕发起→审核→批复",
"",
"①《中国共产党机构编制工作条例》;\n②《'三定'规定制定和实施办法》559920f6ac788c5c8b2ee86842f36a96.pdf——行政事业单位适用\n③《机构编制监督检查工作办法》\n④机构编制违规违纪违法行为处理和问责规则试行"
)
));
// 7. 预算编制与实际执行差异
AUDIT_SUB_CONTENTS.put(AUDIT_CONTENTS[6], Arrays.asList(
new AuditSubContent(
"1.验证人员经费真实性,预算申报是否与实有人数匹配",
"工资预算表、工资发放明细表、考勤数据、每月社保缴纳明细等",
"比对预算人数与社保实缴人数,抽查离职人员工资停发时效,检查是否存在虚报人数、'吃空饷'情况,并列出涉及金额。",
"生成审计取证单",
"①中华人民共和国预算法_中国人大网\n②《中华人民共和国预算法实施条例》\n③企业内控制度"
),
new AuditSubContent(
"2.检查职级成本是否合规",
"工资预算表、员工花名册(含职务、职级等)、个税申报记录等",
"识别'高职低编'薪酬倒挂人员,计算其薪酬超出编制标准部分",
"生成审计取证单",
"①中华人民共和国预算法_中国人大网\n②《中华人民共和国预算法实施条例》\n③企业内控制度"
),
new AuditSubContent(
"3.检查项目经费合规性,是否违规使用项目经费支付超编人员成本",
"项目预算明细、费用报销凭证、人员分工表",
"分析项目支出中人工成本占比,核查超编人员参与项目合理性,并列出比例、金额。",
"生成审计取证单",
"①中华人民共和国预算法_中国人大网\n②《中华人民共和国预算法实施条例》\n③企业内控制度"
)
));
}
// 审计子内容类
public static class AuditSubContent {
private String auditTarget;
private String auditEvidence;
private String aiTestContent;
private String generationResult;
private String regulationBasis;
public AuditSubContent(String auditTarget, String auditEvidence, String aiTestContent,
String generationResult, String regulationBasis) {
this.auditTarget = auditTarget;
this.auditEvidence = auditEvidence;
this.aiTestContent = aiTestContent;
this.generationResult = generationResult;
this.regulationBasis = regulationBasis;
}
public String getAuditTarget() { return auditTarget; }
public String getAuditEvidence() { return auditEvidence; }
public String getAiTestContent() { return aiTestContent; }
public String getGenerationResult() { return generationResult; }
public String getRegulationBasis() { return regulationBasis; }
}
// 关键词权重
public static final Map<String, Integer> KEYWORD_WEIGHTS = new HashMap<>();
static {
KEYWORD_WEIGHTS.put("劳务派遣", 10);
KEYWORD_WEIGHTS.put("人员编制", 9);
KEYWORD_WEIGHTS.put("外包", 8);
KEYWORD_WEIGHTS.put("同工同酬", 9);
KEYWORD_WEIGHTS.put("三性标准", 8);
KEYWORD_WEIGHTS.put("工资总额", 8);
KEYWORD_WEIGHTS.put("福利费", 7);
KEYWORD_WEIGHTS.put("绩效考核", 8);
KEYWORD_WEIGHTS.put("机构编制", 9);
KEYWORD_WEIGHTS.put("预算编制", 7);
KEYWORD_WEIGHTS.put("假外包真派遣", 10);
KEYWORD_WEIGHTS.put("借用人员", 7);
KEYWORD_WEIGHTS.put("用工合规", 9);
KEYWORD_WEIGHTS.put("人员经费", 8);
}
// 审计方法
public static final List<String> AUDIT_METHODS = Arrays.asList(
"文档审查", "数据分析", "访谈调查", "现场观察", "抽样测试",
"对比分析", "穿行测试", "合规性检查", "制度评价"
);
private AuditContent9PersonnelConstants() {
// 防止实例化
}
}

View File

@@ -0,0 +1,72 @@
package com.gxwebsoft.ai.controller;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.ai.dto.AuditContentRequest;
import com.gxwebsoft.ai.dto.export.PartyConductExportEntity;
import com.gxwebsoft.ai.service.AuditContent10PartyConductService;
import com.gxwebsoft.common.core.web.ApiResult;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 审计内容10控制器 - 党风廉政建设责任制审计
*/
@Slf4j
@Tag(name = "审计内容10-廉政情况")
@RestController
@RequestMapping("/api/ai/auditContent10")
public class AuditContent10Controller extends BaseAuditContentController {
@Autowired
private AuditContent10PartyConductService auditContent10PartyConductService;
/**
* 生成党风廉政建设责任制审计表数据
*/
@Operation(summary = "生成党风廉政建设责任制审计表")
@PostMapping("/generatePartyConductTable")
public ApiResult<?> generatePartyConductTable(@RequestBody AuditContentRequest request, HttpServletRequest servletRequest) {
return generateTableData(request, servletRequest.getRequestURI(),
(params) -> auditContent10PartyConductService.generatePartyConductTableData(
params.knowledgeBaseId, params.libraryKbIds, params.projectLibrary,
params.username, params.history, params.suggestion
));
}
/**
* 导出党风廉政建设责任制审计表到Excel
*/
@Operation(summary = "导出党风廉政建设责任制审计表到Excel")
@PostMapping("/exportPartyConductTable")
public void exportPartyConductTable(@RequestBody Map<String, Object> request, HttpServletResponse response) {
exportToExcel(request, response, "党风廉政建设责任制审计表",
this::convertToPartyConductEntityList, PartyConductExportEntity.class);
}
// ========== 数据转换方法 ==========
private List<PartyConductExportEntity> convertToPartyConductEntityList(List<Map<String, Object>> originalData) {
return originalData.stream().map(this::convertToPartyConductEntity).collect(Collectors.toList());
}
private PartyConductExportEntity convertToPartyConductEntity(Map<String, Object> item) {
PartyConductExportEntity entity = new PartyConductExportEntity();
entity.setCategory(getStringValue(item, "category"));
entity.setSubCategory(getStringValue(item, "subCategory"));
entity.setDetailCategory(getStringValue(item, "detailCategory"));
entity.setContent(getStringValue(item, "content"));
entity.setExecutionStatus(getStringValue(item, "executionStatus"));
entity.setWorkPaperIndex(formatWorkPaperIndex(item.get("workPaperIndex")));
return entity;
}
}

View File

@@ -0,0 +1,91 @@
package com.gxwebsoft.ai.controller;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.ai.dto.AuditContentRequest;
import com.gxwebsoft.ai.dto.export.HistoryTableExportEntity;
import com.gxwebsoft.ai.service.AuditContent11HistoryService;
import com.gxwebsoft.ai.utils.ExcelExportTool;
import com.gxwebsoft.common.core.web.ApiResult;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 审计内容11控制器 - 历史审计问题整改表
*/
@Slf4j
@Tag(name = "审计内容11-历史审计问题整改")
@RestController
@RequestMapping("/api/ai/auditContent11")
public class AuditContent11Controller extends BaseAuditContentController {
@Autowired
private AuditContent11HistoryService auditContent11HistoryService;
/**
* 生成历史审计问题整改表数据
*/
@Operation(summary = "生成历史审计问题整改表")
@PostMapping("/generateHistoryTable")
public ApiResult<?> generateHistoryTable(@RequestBody AuditContentRequest request, HttpServletRequest servletRequest) {
return generateTableData(request, servletRequest.getRequestURI(),
(params) -> auditContent11HistoryService.generateHistoryTableData(
params.knowledgeBaseId, params.libraryKbIds, params.projectLibrary,
params.username, params.history, params.suggestion
));
}
/**
* 导出历史审计问题整改表到Excel
*/
@Operation(summary = "导出历史审计问题整改表到Excel")
@PostMapping("/exportHistoryTable")
public void exportHistoryTable(@RequestBody Map<String, Object> request, HttpServletResponse response) {
List<Map<String, Object>> dataList = (List<Map<String, Object>>) request.get("data");
String companyName = (String) request.get("companyName");
String auditTime = (String) request.get("auditTime");
List<HistoryTableExportEntity> exportData = convertToHistoryTableEntityList(dataList);
String fileName = "历史审计问题整改表_" + (companyName != null ? companyName : "未知公司");
String sheetName = "历史审计问题整改表";
String title = companyName != null ?
companyName + " - 历史审计问题整改表" + (auditTime != null ? "" + auditTime + "" : "") :
"历史审计问题整改表";
ExcelExportTool.exportExcel(exportData, HistoryTableExportEntity.class, fileName, sheetName, title, response);
}
// ========== 数据转换方法 ==========
private List<HistoryTableExportEntity> convertToHistoryTableEntityList(List<Map<String, Object>> originalData) {
return originalData.stream()
.map(this::convertToHistoryTableEntity)
.collect(Collectors.toList());
}
private HistoryTableExportEntity convertToHistoryTableEntity(Map<String, Object> item) {
HistoryTableExportEntity entity = new HistoryTableExportEntity();
entity.setIndex(getStringValue(item, "index"));
entity.setAuditYear(getStringValue(item, "auditYear"));
entity.setAuditType(getStringValue(item, "auditType"));
entity.setProblemFound(getStringValue(item, "problemFound"));
entity.setRectificationRequirement(getStringValue(item, "rectificationRequirement"));
entity.setRectificationMeasures(getStringValue(item, "rectificationMeasures"));
entity.setRectificationStatus(getStringValue(item, "rectificationStatus"));
entity.setCompletionDate(getStringValue(item, "completionDate"));
entity.setResponsiblePerson(getStringValue(item, "responsiblePerson"));
entity.setRemark(getStringValue(item, "remark"));
entity.setWorkPaperIndex(formatWorkPaperIndex(item.get("workPaperIndex")));
return entity;
}
}

View File

@@ -1,38 +1,25 @@
package com.gxwebsoft.ai.controller;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gxwebsoft.ai.dto.AuditContentRequest;
import com.gxwebsoft.ai.dto.export.EightRegExportEntity;
import com.gxwebsoft.ai.dto.export.ExpenseExportEntity;
import com.gxwebsoft.ai.dto.export.LeaderListExportEntity;
import com.gxwebsoft.ai.entity.AiCloudDoc;
import com.gxwebsoft.ai.entity.AiCloudFile;
import com.gxwebsoft.ai.service.AiHistoryService;
import com.gxwebsoft.ai.utils.ExcelExportTool;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.pwl.entity.PwlProjectLibrary;
import com.gxwebsoft.pwl.service.PwlProjectLibraryService;
import com.gxwebsoft.ai.service.AiCloudDocService;
import com.gxwebsoft.ai.service.AiCloudFileService;
import com.gxwebsoft.ai.service.AuditContent1EightRegService;
import com.gxwebsoft.ai.service.AuditContent1ExpenseService;
import com.gxwebsoft.ai.service.AuditContent1LeaderListService;
import com.gxwebsoft.ai.service.KnowledgeBaseService;
import com.gxwebsoft.common.core.web.ApiResult;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.function.Function;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
@@ -42,10 +29,10 @@ import java.util.stream.Collectors;
@Tag(name = "审计内容1-八项规定")
@RestController
@RequestMapping("/api/ai/auditContent1")
public class AuditContent1Controller extends BaseController {
public class AuditContent1Controller extends BaseAuditContentController {
@Autowired
private AuditContent1LeaderListService auditContent1LeaderListService;
@Autowired
private AuditContent1LeaderListService auditContent1LeaderListService;
@Autowired
private AuditContent1ExpenseService auditContent1ExpenseService;
@@ -53,24 +40,6 @@ public class AuditContent1Controller extends BaseController {
@Autowired
private AuditContent1EightRegService auditContent1EightRegService;
@Autowired
private AiCloudDocService aiCloudDocService;
@Autowired
private AiCloudFileService aiCloudFileService;
@Autowired
private KnowledgeBaseService knowledgeBaseService;
@Autowired
private PwlProjectLibraryService pwlProjectLibraryService;
@Autowired
private AiHistoryService aiHistoryService;
// 历史记录有效期(分钟)
private static final int HISTORY_EXPIRE_MINUTES = 10;
/**
* 生成领导班子名单数据
*/
@@ -110,141 +79,6 @@ public class AuditContent1Controller extends BaseController {
));
}
/**
* 通用的表格数据生成方法
*/
private ApiResult<?> generateTableData(AuditContentRequest request, String interfaceName, Function<GenerateParams, JSONObject> generateFunction) {
final User loginUser = getLoginUser();
String requestHistory = request.getHistory();
request.setHistory("");
// 检查历史记录
String requestHash = generateRequestHash(request, interfaceName);
var history = aiHistoryService.getValidHistory(requestHash, interfaceName, HISTORY_EXPIRE_MINUTES);
if (history != null) {
log.info("返回历史数据,请求哈希: {}", requestHash);
return success(JSONObject.parseObject(history.getResponseData()));
}
request.setHistory(requestHistory);
String kbIdTmp = "";
String libraryKbIds = "";
try {
// 创建临时知识库(如果需要)
if (hasUploadedFiles(request)) {
kbIdTmp = createTempKnowledgeBase(request);
}
// 查询项目库信息
libraryKbIds = getLibraryKbIds(request.getLibraryIds());
// 生成数据
String knowledgeBaseId = getKnowledgeBaseId(kbIdTmp, request.getKbIds());
GenerateParams params = new GenerateParams(knowledgeBaseId, libraryKbIds, request.getProjectLibrary(), loginUser.getUsername(), request.getHistory(), request.getSuggestion());
JSONObject result = generateFunction.apply(params);
if(result.getBoolean("success")) {
// 保存到历史记录
saveToHistory(request, interfaceName, requestHash, result, loginUser);
}
return success(result);
} catch (Exception e) {
log.error("生成八项规定表格数据失败,接口: {}", interfaceName, e);
return fail("生成八项规定表格数据失败: " + e.getMessage());
} finally {
cleanupTempKnowledgeBase(kbIdTmp);
}
}
/**
* 生成请求哈希
*/
private String generateRequestHash(AuditContentRequest request, String interfaceName) {
String requestJson = JSONObject.toJSONString(request);
return DigestUtil.md5Hex(interfaceName + ":" + requestJson);
}
/**
* 保存到历史记录
*/
private void saveToHistory(AuditContentRequest request, String interfaceName, String requestHash, JSONObject result, User loginUser) {
try {
aiHistoryService.saveHistory(requestHash, interfaceName, JSONObject.toJSONString(request), result.toJSONString(), loginUser.getUserId(), loginUser.getUsername(), loginUser.getTenantId());
} catch (Exception e) {
log.warn("保存历史记录失败", e);
}
}
/**
* 检查是否有上传的文件
*/
private boolean hasUploadedFiles(AuditContentRequest request) {
return !request.getDocList().isEmpty() || !request.getFileList().isEmpty();
}
/**
* 获取知识库ID
*/
private String getKnowledgeBaseId(String tempKbId, String requestKbIds) {
return StrUtil.isNotBlank(tempKbId) ? tempKbId : requestKbIds;
}
/**
* 获取项目库KB IDs
*/
private String getLibraryKbIds(String libraryIds) {
if (StrUtil.isBlank(libraryIds)) {
return "";
}
List<String> idList = StrUtil.split(libraryIds, ',');
List<PwlProjectLibrary> ret = pwlProjectLibraryService.list(new LambdaQueryWrapper<PwlProjectLibrary>().in(PwlProjectLibrary::getId, idList));
return ret.stream().map(PwlProjectLibrary::getKbId).filter(StrUtil::isNotBlank).collect(Collectors.joining(","));
}
/**
* 创建临时知识库并提交文档
*/
private String createTempKnowledgeBase(AuditContentRequest request) {
String kbIdTmp = knowledgeBaseService.createKnowledgeBaseTemp();
// 收集文档ID
Set<Integer> docIds = request.getDocList().stream().flatMap(docId -> aiCloudDocService.getSelfAndChildren(docId).stream()).map(AiCloudDoc::getId).collect(Collectors.toSet());
// 查询相关文件
List<AiCloudFile> fileList = getRelatedFiles(docIds, request.getFileList());
// 提取文件ID并提交到知识库
Set<String> kbFileIds = fileList.stream().map(AiCloudFile::getFileId).collect(Collectors.toSet());
if (!kbFileIds.isEmpty()) {
knowledgeBaseService.submitDocuments(kbIdTmp, new ArrayList<>(kbFileIds));
}
return kbIdTmp;
}
/**
* 获取相关文件列表
*/
private List<AiCloudFile> getRelatedFiles(Set<Integer> docIds, List<Integer> fileList) {
LambdaQueryWrapper<AiCloudFile> queryWrapper = new LambdaQueryWrapper<AiCloudFile>()
.in(!docIds.isEmpty(), AiCloudFile::getDocId, docIds)
.or(!fileList.isEmpty())
.in(!fileList.isEmpty(), AiCloudFile::getId, fileList);
return aiCloudFileService.list(queryWrapper);
}
/**
* 清理临时知识库
*/
private void cleanupTempKnowledgeBase(String kbId) {
if (StrUtil.isNotBlank(kbId)) {
try {
knowledgeBaseService.deleteIndex(kbId);
} catch (Exception e) {
log.warn("删除临时知识库失败: {}", kbId, e);
}
}
}
/**
* 导出八项规定对比分析表到Excel
*/
@@ -256,41 +90,23 @@ public class AuditContent1Controller extends BaseController {
}
/**
* 通用的Excel导出方法
* 导出领导班子名单到Excel
*/
private <T> void exportToExcel(Map<String, Object> request, HttpServletResponse response,
String sheetName, Function<List<Map<String, Object>>, List<T>> converter,
Class<T> entityClass) {
List<Map<String, Object>> dataList = (List<Map<String, Object>>) request.get("data");
String companyName = (String) request.get("companyName");
List<T> exportData = converter.apply(dataList);
String fileName = sheetName + "_" + (companyName != null ? companyName : "未知公司");
String title = companyName != null ? companyName + " - " + sheetName : sheetName;
ExcelExportTool.exportExcel(exportData, entityClass, fileName, sheetName, title, response);
@Operation(summary = "导出领导班子名单到Excel")
@PostMapping("/exportLeaderListTable")
public void exportLeaderListTable(@RequestBody Map<String, Object> request, HttpServletResponse response) {
exportToExcel(request, response, "领导班子名单",
this::convertToLeaderListEntityList, LeaderListExportEntity.class);
}
/**
* 参数包装类
* 导出支出情况表到Excel
*/
private static class GenerateParams {
final String knowledgeBaseId;
final String libraryKbIds;
final String projectLibrary;
final String username;
final String history;
final String suggestion;
GenerateParams(String knowledgeBaseId, String libraryKbIds, String projectLibrary, String username, String history, String suggestion) {
this.knowledgeBaseId = knowledgeBaseId;
this.libraryKbIds = libraryKbIds;
this.projectLibrary = projectLibrary;
this.username = username;
this.history = history;
this.suggestion = suggestion;
}
@Operation(summary = "导出支出情况表到Excel")
@PostMapping("/exportExpenseTable")
public void exportExpenseTable(@RequestBody Map<String, Object> request, HttpServletResponse response) {
exportToExcel(request, response, "支出情况表",
this::convertToExpenseEntityList, ExpenseExportEntity.class);
}
// ========== 数据转换方法 ==========
@@ -309,37 +125,6 @@ public class AuditContent1Controller extends BaseController {
return entity;
}
private String getStringValue(Map<String, Object> map, String key) {
Object value = map.get(key);
return value != null ? value.toString() : "";
}
private String formatWorkPaperIndex(Object workPaperIndex) {
if (workPaperIndex == null) {
return "";
}
if (workPaperIndex instanceof List) {
List<?> list = (List<?>) workPaperIndex;
return String.join(", ", list.stream()
.map(Object::toString)
.collect(Collectors.toList()));
}
return workPaperIndex.toString();
}
/**
* 导出领导班子名单到Excel
*/
@Operation(summary = "导出领导班子名单到Excel")
@PostMapping("/exportLeaderListTable")
public void exportLeaderListTable(@RequestBody Map<String, Object> request, HttpServletResponse response) {
exportToExcel(request, response, "领导班子名单", this::convertToLeaderListEntityList, LeaderListExportEntity.class);
}
// 添加数据转换方法
private List<LeaderListExportEntity> convertToLeaderListEntityList(List<Map<String, Object>> originalData) {
return originalData.stream().map(this::convertToLeaderListEntity).collect(Collectors.toList());
}
@@ -358,19 +143,6 @@ public class AuditContent1Controller extends BaseController {
return entity;
}
/**
* 导出支出情况表到Excel
*/
@Operation(summary = "导出支出情况表到Excel")
@PostMapping("/exportExpenseTable")
public void exportExpenseTable(@RequestBody Map<String, Object> request, HttpServletResponse response) {
exportToExcel(request, response, "支出情况表",
this::convertToExpenseEntityList, ExpenseExportEntity.class);
}
// ========== 数据转换方法 ==========
private List<ExpenseExportEntity> convertToExpenseEntityList(List<Map<String, Object>> originalData) {
return originalData.stream().map(this::convertToExpenseEntity).collect(Collectors.toList());
}

View File

@@ -0,0 +1,72 @@
package com.gxwebsoft.ai.controller;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.ai.dto.AuditContentRequest;
import com.gxwebsoft.ai.dto.export.StrategyAuditExportEntity;
import com.gxwebsoft.ai.service.AuditContent2StrategyService;
import com.gxwebsoft.common.core.web.ApiResult;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 审计内容2控制器 - 单位发展战略执行审计
*/
@Slf4j
@Tag(name = "审计内容2-单位发展战略执行")
@RestController
@RequestMapping("/api/ai/auditContent2")
public class AuditContent2Controller extends BaseAuditContentController {
@Autowired
private AuditContent2StrategyService auditContent2StrategyService;
/**
* 生成单位发展战略执行审计表数据
*/
@Operation(summary = "生成单位发展战略执行审计表")
@PostMapping("/generateStrategyAuditTable")
public ApiResult<?> generateStrategyAuditTable(@RequestBody AuditContentRequest request, HttpServletRequest servletRequest) {
return generateTableData(request, servletRequest.getRequestURI(),
(params) -> auditContent2StrategyService.generateStrategyAuditTableData(
params.knowledgeBaseId, params.libraryKbIds, params.projectLibrary,
params.username, params.history, params.suggestion
));
}
/**
* 导出单位发展战略执行审计表到Excel
*/
@Operation(summary = "导出单位发展战略执行审计表到Excel")
@PostMapping("/exportStrategyAuditTable")
public void exportStrategyAuditTable(@RequestBody Map<String, Object> request, HttpServletResponse response) {
exportToExcel(request, response, "单位发展战略执行审计表",
this::convertToExportEntityList, StrategyAuditExportEntity.class);
}
/**
* 数据转换
*/
private List<StrategyAuditExportEntity> convertToExportEntityList(List<Map<String, Object>> originalData) {
return originalData.stream().map(this::convertToExportEntity).collect(Collectors.toList());
}
private StrategyAuditExportEntity convertToExportEntity(Map<String, Object> item) {
StrategyAuditExportEntity entity = new StrategyAuditExportEntity();
entity.setIndex(getStringValue(item, "index"));
entity.setAuditContent(getStringValue(item, "auditContent"));
entity.setCheckEvidence(getStringValue(item, "checkEvidence"));
entity.setTestResult(getStringValue(item, "testResult"));
entity.setWorkPaperIndex(formatWorkPaperIndex(item.get("workPaperIndex")));
return entity;
}
}

View File

@@ -1,36 +1,22 @@
package com.gxwebsoft.ai.controller;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gxwebsoft.ai.dto.AuditContentRequest;
import com.gxwebsoft.ai.dto.export.TripleOneExportEntity;
import com.gxwebsoft.ai.dto.export.DecisionTableExportEntity;
import com.gxwebsoft.ai.entity.AiCloudDoc;
import com.gxwebsoft.ai.entity.AiCloudFile;
import com.gxwebsoft.ai.service.AiHistoryService;
import com.gxwebsoft.ai.utils.ExcelExportTool;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.pwl.entity.PwlProjectLibrary;
import com.gxwebsoft.pwl.service.PwlProjectLibraryService;
import com.gxwebsoft.ai.service.AiCloudDocService;
import com.gxwebsoft.ai.service.AiCloudFileService;
import com.gxwebsoft.ai.service.AuditContent3TripleService;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.ai.service.AuditContent3DecisionService;
import com.gxwebsoft.ai.service.KnowledgeBaseService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.function.Function;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
@@ -40,7 +26,7 @@ import java.util.stream.Collectors;
@Tag(name = "审计内容3-三重一大制度")
@RestController
@RequestMapping("/api/ai/auditContent3")
public class AuditContent3Controller extends BaseController {
public class AuditContent3Controller extends BaseAuditContentController {
@Autowired
private AuditContent3TripleService auditContent3TripleService;
@@ -48,24 +34,6 @@ public class AuditContent3Controller extends BaseController {
@Autowired
private AuditContent3DecisionService auditContent3DecisionService;
@Autowired
private AiCloudDocService aiCloudDocService;
@Autowired
private AiCloudFileService aiCloudFileService;
@Autowired
private KnowledgeBaseService knowledgeBaseService;
@Autowired
private PwlProjectLibraryService pwlProjectLibraryService;
@Autowired
private AiHistoryService aiHistoryService;
// 历史记录有效期(分钟)
private static final int HISTORY_EXPIRE_MINUTES = 10;
/**
* 生成三重一大制度对比分析表数据
*/
@@ -92,141 +60,6 @@ public class AuditContent3Controller extends BaseController {
));
}
/**
* 通用的表格数据生成方法
*/
private ApiResult<?> generateTableData(AuditContentRequest request, String interfaceName, Function<GenerateParams, JSONObject> generateFunction) {
final User loginUser = getLoginUser();
String requestHistory = request.getHistory();
request.setHistory("");
// 检查历史记录
String requestHash = generateRequestHash(request, interfaceName);
var history = aiHistoryService.getValidHistory(requestHash, interfaceName, HISTORY_EXPIRE_MINUTES);
if (history != null) {
log.info("返回历史数据,请求哈希: {}", requestHash);
return success(JSONObject.parseObject(history.getResponseData()));
}
request.setHistory(requestHistory);
String kbIdTmp = "";
String libraryKbIds = "";
try {
// 创建临时知识库(如果需要)
if (hasUploadedFiles(request)) {
kbIdTmp = createTempKnowledgeBase(request);
}
// 查询项目库信息
libraryKbIds = getLibraryKbIds(request.getLibraryIds());
// 生成数据
String knowledgeBaseId = getKnowledgeBaseId(kbIdTmp, request.getKbIds());
GenerateParams params = new GenerateParams(knowledgeBaseId, libraryKbIds, request.getProjectLibrary(), loginUser.getUsername(), request.getHistory(), request.getSuggestion());
JSONObject result = generateFunction.apply(params);
if(result.getBoolean("success")) {
// 保存到历史记录
saveToHistory(request, interfaceName, requestHash, result, loginUser);
}
return success(result);
} catch (Exception e) {
log.error("生成表格数据失败,接口: {}", interfaceName, e);
return fail("生成表格数据失败: " + e.getMessage());
} finally {
cleanupTempKnowledgeBase(kbIdTmp);
}
}
/**
* 生成请求哈希
*/
private String generateRequestHash(AuditContentRequest request, String interfaceName) {
String requestJson = JSONObject.toJSONString(request);
return DigestUtil.md5Hex(interfaceName + ":" + requestJson);
}
/**
* 保存到历史记录
*/
private void saveToHistory(AuditContentRequest request, String interfaceName, String requestHash, JSONObject result, User loginUser) {
try {
aiHistoryService.saveHistory(requestHash, interfaceName, JSONObject.toJSONString(request), result.toJSONString(), loginUser.getUserId(), loginUser.getUsername(), loginUser.getTenantId());
} catch (Exception e) {
log.warn("保存历史记录失败", e);
}
}
/**
* 检查是否有上传的文件
*/
private boolean hasUploadedFiles(AuditContentRequest request) {
return !request.getDocList().isEmpty() || !request.getFileList().isEmpty();
}
/**
* 获取知识库ID
*/
private String getKnowledgeBaseId(String tempKbId, String requestKbIds) {
return StrUtil.isNotBlank(tempKbId) ? tempKbId : requestKbIds;
}
/**
* 获取项目库KB IDs
*/
private String getLibraryKbIds(String libraryIds) {
if (StrUtil.isBlank(libraryIds)) {
return "";
}
List<String> idList = StrUtil.split(libraryIds, ',');
List<PwlProjectLibrary> ret = pwlProjectLibraryService.list(new LambdaQueryWrapper<PwlProjectLibrary>().in(PwlProjectLibrary::getId, idList));
return ret.stream().map(PwlProjectLibrary::getKbId).filter(StrUtil::isNotBlank).collect(Collectors.joining(","));
}
/**
* 创建临时知识库并提交文档
*/
private String createTempKnowledgeBase(AuditContentRequest request) {
String kbIdTmp = knowledgeBaseService.createKnowledgeBaseTemp();
// 收集文档ID
Set<Integer> docIds = request.getDocList().stream().flatMap(docId -> aiCloudDocService.getSelfAndChildren(docId).stream()).map(AiCloudDoc::getId).collect(Collectors.toSet());
// 查询相关文件
List<AiCloudFile> fileList = getRelatedFiles(docIds, request.getFileList());
// 提取文件ID并提交到知识库
Set<String> kbFileIds = fileList.stream().map(AiCloudFile::getFileId).collect(Collectors.toSet());
if (!kbFileIds.isEmpty()) {
knowledgeBaseService.submitDocuments(kbIdTmp, new ArrayList<>(kbFileIds));
}
return kbIdTmp;
}
/**
* 获取相关文件列表
*/
private List<AiCloudFile> getRelatedFiles(Set<Integer> docIds, List<Integer> fileList) {
LambdaQueryWrapper<AiCloudFile> queryWrapper = new LambdaQueryWrapper<AiCloudFile>()
.in(!docIds.isEmpty(), AiCloudFile::getDocId, docIds)
.or(!fileList.isEmpty())
.in(!fileList.isEmpty(), AiCloudFile::getId, fileList);
return aiCloudFileService.list(queryWrapper);
}
/**
* 清理临时知识库
*/
private void cleanupTempKnowledgeBase(String kbId) {
if (StrUtil.isNotBlank(kbId)) {
try {
knowledgeBaseService.deleteIndex(kbId);
} catch (Exception e) {
log.warn("删除临时知识库失败: {}", kbId, e);
}
}
}
/**
* 导出三重一大制度对比分析表到Excel
*/
@@ -247,44 +80,6 @@ public class AuditContent3Controller extends BaseController {
this::convertToDecisionTableEntityList, DecisionTableExportEntity.class);
}
/**
* 通用的Excel导出方法
*/
private <T> void exportToExcel(Map<String, Object> request, HttpServletResponse response,
String sheetName, Function<List<Map<String, Object>>, List<T>> converter,
Class<T> entityClass) {
List<Map<String, Object>> dataList = (List<Map<String, Object>>) request.get("data");
String companyName = (String) request.get("companyName");
List<T> exportData = converter.apply(dataList);
String fileName = sheetName + "_" + (companyName != null ? companyName : "未知公司");
String title = companyName != null ? companyName + " - " + sheetName : sheetName;
ExcelExportTool.exportExcel(exportData, entityClass, fileName, sheetName, title, response);
}
/**
* 参数包装类
*/
private static class GenerateParams {
final String knowledgeBaseId;
final String libraryKbIds;
final String projectLibrary;
final String username;
final String history;
final String suggestion;
GenerateParams(String knowledgeBaseId, String libraryKbIds, String projectLibrary, String username, String history, String suggestion) {
this.knowledgeBaseId = knowledgeBaseId;
this.libraryKbIds = libraryKbIds;
this.projectLibrary = projectLibrary;
this.username = username;
this.history = history;
this.suggestion = suggestion;
}
}
// ========== 数据转换方法 ==========
private List<TripleOneExportEntity> convertToTripleOneEntityList(List<Map<String, Object>> originalData) {
@@ -320,24 +115,4 @@ public class AuditContent3Controller extends BaseController {
entity.setBad(getStringValue(item, "bad"));
return entity;
}
private String getStringValue(Map<String, Object> map, String key) {
Object value = map.get(key);
return value != null ? value.toString() : "";
}
private String formatWorkPaperIndex(Object workPaperIndex) {
if (workPaperIndex == null) {
return "";
}
if (workPaperIndex instanceof List) {
List<?> list = (List<?>) workPaperIndex;
return String.join(", ", list.stream()
.map(Object::toString)
.collect(Collectors.toList()));
}
return workPaperIndex.toString();
}
}

View File

@@ -0,0 +1,86 @@
package com.gxwebsoft.ai.controller;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.ai.dto.AuditContentRequest;
import com.gxwebsoft.ai.dto.export.TargetAuditExportEntity;
import com.gxwebsoft.ai.service.AuditContent4TargetService;
import com.gxwebsoft.ai.utils.ExcelExportTool;
import com.gxwebsoft.common.core.web.ApiResult;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 审计内容4控制器 - 目标责任制完成情况审计
*/
@Slf4j
@Tag(name = "审计内容4-目标责任制完成情况")
@RestController
@RequestMapping("/api/ai/auditContent4")
public class AuditContent4Controller extends BaseAuditContentController {
@Autowired
private AuditContent4TargetService auditContent4TargetService;
/**
* 生成目标责任制完成情况审计表数据
*/
@Operation(summary = "生成目标责任制完成情况审计表")
@PostMapping("/generateTargetTable")
public ApiResult<?> generateTargetTable(@RequestBody AuditContentRequest request, HttpServletRequest servletRequest) {
return generateTableData(request, servletRequest.getRequestURI(),
(params) -> auditContent4TargetService.generateTargetAuditTableData(
params.knowledgeBaseId, params.libraryKbIds, params.projectLibrary,
params.username, params.history, params.suggestion
));
}
/**
* 导出目标责任制完成情况审计表到Excel
*/
@Operation(summary = "导出目标责任制完成情况审计表到Excel")
@PostMapping("/exportTargetTable")
public void exportTargetTable(@RequestBody Map<String, Object> request, HttpServletResponse response) {
List<Map<String, Object>> dataList = (List<Map<String, Object>>) request.get("data");
String companyName = (String) request.get("companyName");
List<TargetAuditExportEntity> exportData = convertToExportEntityList(dataList);
String fileName = "目标责任制完成情况审计表_" + (companyName != null ? companyName : "未知公司");
String title = companyName != null ? companyName + " - 目标责任制完成情况审计表" : "目标责任制完成情况审计表";
String sheetName = "目标责任审计";
ExcelExportTool.exportExcel(exportData, TargetAuditExportEntity.class, fileName, sheetName, title, response);
}
/**
* 数据转换
*/
private List<TargetAuditExportEntity> convertToExportEntityList(List<Map<String, Object>> originalData) {
return originalData.stream().map(this::convertToExportEntity).collect(Collectors.toList());
}
private TargetAuditExportEntity convertToExportEntity(Map<String, Object> item) {
TargetAuditExportEntity entity = new TargetAuditExportEntity();
entity.setIndex(getStringValue(item, "index"));
entity.setYear(getStringValue(item, "year"));
entity.setSuperiorFile(getStringValue(item, "superiorFile"));
entity.setSuperiorCompletion(getStringValue(item, "superiorCompletion"));
entity.setSuperiorReason(getStringValue(item, "superiorReason"));
entity.setSelfPlan(getStringValue(item, "selfPlan"));
entity.setSelfCompletion(getStringValue(item, "selfCompletion"));
entity.setSelfReason(getStringValue(item, "selfReason"));
entity.setRemark(getStringValue(item, "remark"));
entity.setWorkPaperIndex(formatWorkPaperIndex(item.get("workPaperIndex")));
return entity;
}
}

View File

@@ -0,0 +1,127 @@
package com.gxwebsoft.ai.controller;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.ai.dto.AuditContentRequest;
import com.gxwebsoft.ai.dto.export.BudgetManageExportEntity;
import com.gxwebsoft.ai.dto.export.BudgetExecutionExportEntity;
import com.gxwebsoft.ai.service.AuditContent5BudgetManageService;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.ai.service.AuditContent5BudgetExecutionService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 审计内容5控制器 - 预算管理审计
*/
@Slf4j
@Tag(name = "审计内容5-预算管理审计")
@RestController
@RequestMapping("/api/ai/auditContent5")
public class AuditContent5Controller extends BaseAuditContentController {
@Autowired
private AuditContent5BudgetManageService auditContent5BudgetManageService;
@Autowired
private AuditContent5BudgetExecutionService auditContent5BudgetExecutionService;
/**
* 生成预算管理审计表数据
*/
@Operation(summary = "生成预算管理审计表")
@PostMapping("/generateBudgetManageTable")
public ApiResult<?> generateBudgetManageTable(@RequestBody AuditContentRequest request, HttpServletRequest servletRequest) {
return generateTableData(request, servletRequest.getRequestURI(),
(params) -> auditContent5BudgetManageService.generateBudgetManageTableData(
params.knowledgeBaseId, params.libraryKbIds, params.projectLibrary,
params.username, params.history, params.suggestion, request.getData()
));
}
/**
* 生成预算执行情况审计表数据
*/
@Operation(summary = "生成预算执行情况审计表")
@PostMapping("/generateBudgetExecutionTable")
public ApiResult<?> generateBudgetExecutionTable(@RequestBody AuditContentRequest request, HttpServletRequest servletRequest) {
return generateTableData(request, servletRequest.getRequestURI(),
(params) -> auditContent5BudgetExecutionService.generateBudgetExecutionTableData(
params.knowledgeBaseId, params.libraryKbIds, params.projectLibrary,
params.username, params.history, params.suggestion, request.getData()
));
}
/**
* 导出预算管理审计表到Excel
*/
@Operation(summary = "导出预算管理审计表到Excel")
@PostMapping("/exportBudgetManageTable")
public void exportBudgetManageTable(@RequestBody Map<String, Object> request, HttpServletResponse response) {
exportToExcel(request, response, "预算管理审计表",
this::convertToBudgetManageEntityList, BudgetManageExportEntity.class);
}
/**
* 导出预算执行情况审计表到Excel
*/
@Operation(summary = "导出预算执行情况审计表到Excel")
@PostMapping("/exportBudgetExecutionTable")
public void exportBudgetExecutionTable(@RequestBody Map<String, Object> request, HttpServletResponse response) {
exportToExcel(request, response, "预算执行情况审计表",
this::convertToBudgetExecutionEntityList, BudgetExecutionExportEntity.class);
}
// ========== 数据转换方法 ==========
private List<BudgetManageExportEntity> convertToBudgetManageEntityList(List<Map<String, Object>> originalData) {
return originalData.stream().map(this::convertToBudgetManageEntity).collect(Collectors.toList());
}
private List<BudgetExecutionExportEntity> convertToBudgetExecutionEntityList(List<Map<String, Object>> originalData) {
return originalData.stream().map(this::convertToBudgetExecutionEntity).collect(Collectors.toList());
}
private BudgetManageExportEntity convertToBudgetManageEntity(Map<String, Object> item) {
BudgetManageExportEntity entity = new BudgetManageExportEntity();
entity.setBudgetSubject(getStringValue(item, "budgetSubject"));
entity.setIndicatorSourceTotal(getStringValue(item, "indicatorSourceTotal"));
entity.setIndicatorSourceLastYearBalance(getStringValue(item, "indicatorSourceLastYearBalance"));
entity.setIndicatorSourceInitialBudget(getStringValue(item, "indicatorSourceInitialBudget"));
entity.setIndicatorSourceAdditionalBudget(getStringValue(item, "indicatorSourceAdditionalBudget"));
entity.setIndicatorUseTotal(getStringValue(item, "indicatorUseTotal"));
entity.setIndicatorUseAppropriationSubtotal(getStringValue(item, "indicatorUseAppropriationSubtotal"));
entity.setIndicatorUseAppropriation(getStringValue(item, "indicatorUseAppropriation"));
entity.setIndicatorUseSalaryPayment(getStringValue(item, "indicatorUseSalaryPayment"));
entity.setIndicatorUseGovProcurement(getStringValue(item, "indicatorUseGovProcurement"));
entity.setFinanceManagementAccount(getStringValue(item, "financeManagementAccount"));
entity.setBudgetUsedForOther(getStringValue(item, "budgetUsedForOther"));
entity.setIndicatorBalance(getStringValue(item, "indicatorBalance"));
entity.setGovernmentProcurement(getStringValue(item, "governmentProcurement"));
entity.setPayableToUnit(getStringValue(item, "payableToUnit"));
entity.setOther(getStringValue(item, "other"));
entity.setWorkPaperIndex(formatWorkPaperIndex(item.get("workPaperIndex")));
return entity;
}
private BudgetExecutionExportEntity convertToBudgetExecutionEntity(Map<String, Object> item) {
BudgetExecutionExportEntity entity = new BudgetExecutionExportEntity();
entity.setProject(getStringValue(item, "project"));
entity.setLastYearCarryOver(getStringValue(item, "lastYearCarryOver"));
entity.setCurrentYearBudgetTotal(getStringValue(item, "currentYearBudgetTotal"));
entity.setInitialApprovedBudget(getStringValue(item, "initialApprovedBudget"));
entity.setAdditionalBudgetAmount(getStringValue(item, "additionalBudgetAmount"));
entity.setActualAppropriation(getStringValue(item, "actualAppropriation"));
entity.setIndicatorBalance(getStringValue(item, "indicatorBalance"));
entity.setWorkPaperIndex(formatWorkPaperIndex(item.get("workPaperIndex")));
return entity;
}
}

View File

@@ -0,0 +1,91 @@
package com.gxwebsoft.ai.controller;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.ai.dto.AuditContentRequest;
import com.gxwebsoft.ai.dto.export.StateAssetsAuditExportEntity;
import com.gxwebsoft.ai.service.AuditContent6StateAssetsService;
import com.gxwebsoft.ai.utils.ExcelExportTool;
import com.gxwebsoft.common.core.web.ApiResult;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 审计内容6控制器 - 国资管理情况审计
*/
@Slf4j
@Tag(name = "审计内容6-国资管理情况")
@RestController
@RequestMapping("/api/ai/auditContent6")
public class AuditContent6Controller extends BaseAuditContentController {
@Autowired
private AuditContent6StateAssetsService auditContent6StateAssetsService;
/**
* 生成国有资产管理审计表数据
*/
@Operation(summary = "生成国有资产管理审计表")
@PostMapping("/generateAssetsTable")
public ApiResult<?> generateAssetsTable(@RequestBody AuditContentRequest request, HttpServletRequest servletRequest) {
return generateTableData(request, servletRequest.getRequestURI(),
(params) -> auditContent6StateAssetsService.generateStateAssetsAuditTableData(
params.knowledgeBaseId, params.libraryKbIds, params.projectLibrary,
params.username, params.history, params.suggestion
));
}
/**
* 导出国有资产管理审计表到Excel
*/
@Operation(summary = "导出国有资产管理审计表到Excel")
@PostMapping("/exportAssetsTable")
public void exportAssetsTable(@RequestBody Map<String, Object> request, HttpServletResponse response) {
List<Map<String, Object>> dataList = (List<Map<String, Object>>) request.get("data");
String companyName = (String) request.get("companyName");
List<StateAssetsAuditExportEntity> exportData = convertToExportEntityList(dataList);
String fileName = "国有资产管理审计表_" + (companyName != null ? companyName : "未知公司");
String title = companyName != null ? companyName + " - 国有资产管理审计表" : "国有资产管理审计表";
String sheetName = "国资管理审计";
ExcelExportTool.exportExcel(exportData, StateAssetsAuditExportEntity.class, fileName, sheetName, title, response);
}
/**
* 数据转换
*/
private List<StateAssetsAuditExportEntity> convertToExportEntityList(List<Map<String, Object>> originalData) {
return originalData.stream().map(this::convertToExportEntity).collect(Collectors.toList());
}
private StateAssetsAuditExportEntity convertToExportEntity(Map<String, Object> item) {
StateAssetsAuditExportEntity entity = new StateAssetsAuditExportEntity();
entity.setIndex(getStringValue(item, "index"));
entity.setAssetName(getStringValue(item, "assetName"));
entity.setAcquisitionMethod(getStringValue(item, "acquisitionMethod"));
entity.setAssetValue(getStringValue(item, "assetValue"));
entity.setAssetAddress(getStringValue(item, "assetAddress"));
entity.setArea(getStringValue(item, "area"));
entity.setTenant(getStringValue(item, "tenant"));
entity.setContractAmount(getStringValue(item, "contractAmount"));
entity.setLeasePeriod(getStringValue(item, "leasePeriod"));
entity.setRentPaymentTime(getStringValue(item, "rentPaymentTime"));
entity.setPlatformLease(getStringValue(item, "platformLease"));
entity.setApprovalDoc(getStringValue(item, "approvalDoc"));
entity.setInBudget(getStringValue(item, "inBudget"));
entity.setRemark(getStringValue(item, "remark"));
entity.setWorkPaperIndex(formatWorkPaperIndex(item.get("workPaperIndex")));
return entity;
}
}

View File

@@ -0,0 +1,72 @@
package com.gxwebsoft.ai.controller;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.ai.dto.AuditContentRequest;
import com.gxwebsoft.ai.dto.export.InvestmentSituationExportEntity;
import com.gxwebsoft.ai.service.AuditContent7InvestmentService;
import com.gxwebsoft.common.core.web.ApiResult;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 审计内容7控制器 - 重大投资情况审计
*/
@Slf4j
@Tag(name = "审计内容7-重大投资情况")
@RestController
@RequestMapping("/api/ai/auditContent7")
public class AuditContent7Controller extends BaseAuditContentController {
@Autowired
private AuditContent7InvestmentService auditContent7InvestmentService;
/**
* 生成重大投资情况审计表数据
*/
@Operation(summary = "生成重大投资情况审计表")
@PostMapping("/generateInvestmentSituationTable")
public ApiResult<?> generateInvestmentSituationTable(@RequestBody AuditContentRequest request, HttpServletRequest servletRequest) {
return generateTableData(request, servletRequest.getRequestURI(),
(params) -> auditContent7InvestmentService.generateInvestmentSituationTableData(
params.knowledgeBaseId, params.libraryKbIds, params.projectLibrary,
params.username, params.history, params.suggestion
));
}
/**
* 导出重大投资情况审计表到Excel
*/
@Operation(summary = "导出重大投资情况审计表到Excel")
@PostMapping("/exportInvestmentSituationTable")
public void exportInvestmentSituationTable(@RequestBody Map<String, Object> request, HttpServletResponse response) {
exportToExcelWithAuditTime(request, response, "重大投资情况审计表",
this::convertToInvestmentSituationEntityList, InvestmentSituationExportEntity.class);
}
// ========== 数据转换方法 ==========
private List<InvestmentSituationExportEntity> convertToInvestmentSituationEntityList(List<Map<String, Object>> originalData) {
return originalData.stream().map(this::convertToInvestmentSituationEntity).collect(Collectors.toList());
}
private InvestmentSituationExportEntity convertToInvestmentSituationEntity(Map<String, Object> item) {
InvestmentSituationExportEntity entity = new InvestmentSituationExportEntity();
entity.setCategory(getStringValue(item, "category"));
entity.setAuditContent(getStringValue(item, "auditContent"));
entity.setCheckEvidence(getStringValue(item, "checkEvidence"));
entity.setTestResult(getStringValue(item, "testResult"));
entity.setWorkPaperIndex(formatWorkPaperIndex(item.get("workPaperIndex")));
entity.setFileIndex(formatWorkPaperIndex(item.get("fileIndex")));
return entity;
}
}

View File

@@ -0,0 +1,75 @@
package com.gxwebsoft.ai.controller;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.ai.dto.AuditContentRequest;
import com.gxwebsoft.ai.dto.export.InternalControlExportEntity;
import com.gxwebsoft.ai.service.AuditContent8InternalControlService;
import com.gxwebsoft.common.core.web.ApiResult;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 审计内容8控制器 - 单位层面财务管理内部控制测试表
*/
@Slf4j
@Tag(name = "审计内容8-内部控制测试")
@RestController
@RequestMapping("/api/ai/auditContent8")
public class AuditContent8Controller extends BaseAuditContentController {
@Autowired
private AuditContent8InternalControlService auditContent8InternalControlService;
/**
* 生成单位层面财务管理内部控制测试表数据
*/
@Operation(summary = "生成单位层面财务管理内部控制测试表")
@PostMapping("/generateInternalControlTable")
public ApiResult<?> generateInternalControlTable(@RequestBody AuditContentRequest request, HttpServletRequest servletRequest) {
return generateTableData(request, servletRequest.getRequestURI(),
(params) -> auditContent8InternalControlService.generateInternalControlTableData(
params.knowledgeBaseId, params.libraryKbIds, params.projectLibrary,
params.username, params.history, params.suggestion
));
}
/**
* 导出单位层面财务管理内部控制测试表到Excel
*/
@Operation(summary = "导出单位层面财务管理内部控制测试表到Excel")
@PostMapping("/exportInternalControlTable")
public void exportInternalControlTable(@RequestBody Map<String, Object> request, HttpServletResponse response) {
exportToExcel(request, response, "单位层面财务管理内部控制测试表",
this::convertToInternalControlEntityList, InternalControlExportEntity.class);
}
// ========== 数据转换方法 ==========
private List<InternalControlExportEntity> convertToInternalControlEntityList(List<Map<String, Object>> originalData) {
return originalData.stream().map(this::convertToInternalControlEntity).collect(Collectors.toList());
}
private InternalControlExportEntity convertToInternalControlEntity(Map<String, Object> item) {
InternalControlExportEntity entity = new InternalControlExportEntity();
entity.setIndex(getStringValue(item, "index"));
entity.setControlLink(getStringValue(item, "controlLink"));
entity.setControlRequirement(getStringValue(item, "controlRequirement"));
entity.setControlActivity(getStringValue(item, "controlActivity"));
entity.setControlPosition(getStringValue(item, "controlPosition"));
entity.setTestSteps(getStringValue(item, "testSteps"));
entity.setCheckEvidence(getStringValue(item, "checkEvidence"));
entity.setTestResult(getStringValue(item, "testResult"));
entity.setWorkPaperIndex(formatWorkPaperIndex(item.get("workPaperIndex")));
return entity;
}
}

View File

@@ -0,0 +1,72 @@
package com.gxwebsoft.ai.controller;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.ai.dto.AuditContentRequest;
import com.gxwebsoft.ai.dto.export.PersonnelExportEntity;
import com.gxwebsoft.ai.service.AuditContent9PersonnelService;
import com.gxwebsoft.common.core.web.ApiResult;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 审计内容9控制器 - 人员编制管理审计
*/
@Slf4j
@Tag(name = "审计内容9-人员编制管理审计")
@RestController
@RequestMapping("/api/ai/auditContent9")
public class AuditContent9Controller extends BaseAuditContentController {
@Autowired
private AuditContent9PersonnelService auditContent9PersonnelService;
/**
* 生成人员编制管理审计表数据
*/
@Operation(summary = "生成人员编制管理审计表")
@PostMapping("/generatePersonnelTable")
public ApiResult<?> generatePersonnelTable(@RequestBody AuditContentRequest request, HttpServletRequest servletRequest) {
return generateTableData(request, servletRequest.getRequestURI(),
(params) -> auditContent9PersonnelService.generatePersonnelTableData(
params.knowledgeBaseId, params.libraryKbIds, params.projectLibrary,
params.username, params.history, params.suggestion
));
}
/**
* 导出人员编制管理审计表到Excel
*/
@Operation(summary = "导出人员编制管理审计表到Excel")
@PostMapping("/exportPersonnelTable")
public void exportPersonnelTable(@RequestBody Map<String, Object> request, HttpServletResponse response) {
exportToExcel(request, response, "人员编制管理审计表",
this::convertToPersonnelEntityList, PersonnelExportEntity.class);
}
// ========== 数据转换方法 ==========
private List<PersonnelExportEntity> convertToPersonnelEntityList(List<Map<String, Object>> originalData) {
return originalData.stream().map(this::convertToPersonnelEntity).collect(Collectors.toList());
}
private PersonnelExportEntity convertToPersonnelEntity(Map<String, Object> item) {
PersonnelExportEntity entity = new PersonnelExportEntity();
entity.setIndex(getStringValue(item, "index"));
entity.setAuditContent(getStringValue(item, "auditContent"));
entity.setAuditTarget(getStringValue(item, "auditTarget"));
entity.setAuditEvidence(getStringValue(item, "auditEvidence"));
entity.setGenerationResult(getStringValue(item, "generationResult"));
entity.setWorkPaperIndex(formatWorkPaperIndex(item.get("workPaperIndex")));
return entity;
}
}

View File

@@ -0,0 +1,214 @@
package com.gxwebsoft.ai.controller;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.ai.dto.AuditEvidenceRequest;
import com.gxwebsoft.ai.service.AuditEvidenceService;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.common.system.entity.User;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import org.apache.poi.openxml4j.util.ZipSecureFile;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;
import java.util.ArrayList;
import java.util.List;
import com.gxwebsoft.ai.config.TemplateConfig;
import cn.afterturn.easypoi.word.WordExportUtil;
/**
* 审计取证单控制器
*/
@Slf4j
@Tag(name = "审计取证单")
@RestController
@RequestMapping("/api/ai/auditEvidence")
public class AuditEvidenceController extends BaseController {
@Autowired
private AuditEvidenceService auditEvidenceService;
@Autowired
private TemplateConfig templateConfig;
/**
* 生成审计取证单
*/
@Operation(summary = "生成审计取证单")
@PostMapping("/generate")
public ApiResult<?> generateAuditEvidence(@RequestBody AuditEvidenceRequest request) {
try {
final User loginUser = getLoginUser();
request.setUserName(loginUser.getUsername());
log.info("接收到审计取证单生成请求 - 用户: {}, 项目: {}", request.getUserName(), request.getProjectName());
JSONObject result = auditEvidenceService.generateAuditEvidence(request);
if (Boolean.TRUE.equals(result.getBoolean("success"))) {
return success(result);
} else {
return fail(result.getString("error") != null ? result.getString("error") : "生成审计取证单失败");
}
} catch (Exception e) {
log.error("生成审计取证单异常", e);
return fail("生成审计取证单异常: " + e.getMessage());
}
}
/**
* 下载审计取证单Word文档
*/
@Operation(summary = "下载审计取证单Word文档")
@PostMapping("/download")
public void downloadAuditEvidence(@RequestBody AuditEvidenceRequest request, HttpServletResponse response) {
double originalMinInflateRatio = ZipSecureFile.getMinInflateRatio();
try {
ZipSecureFile.setMinInflateRatio(0.001);
// 准备模板数据 - 将取证单字段映射到Word模板
Map<String, Object> map = new HashMap<>();
// map.put("caseIndex", request.getCaseIndex() != null ? request.getCaseIndex() : "");
map.put("caseIndex", request.getCaseIndex() != null ? String.format("%-50s", request.getCaseIndex()) : String.format("%-50s", ""));
map.put("pageIndex", request.getPageIndex() != null ? request.getPageIndex() : "1");
map.put("pageTotal", request.getPageTotal() != null ? request.getPageTotal() : "1");
map.put("projectName", request.getProjectName() != null ? request.getProjectName() : "");
map.put("auditedTarget", request.getAuditedTarget() != null ? request.getAuditedTarget() : "");
map.put("auditMatter", request.getAuditMatter() != null ? request.getAuditMatter() : "");
map.put("summaryTitle", request.getSummaryTitle() != null ? request.getSummaryTitle() : "");
map.put("auditRecord", request.getAuditRecord() != null ? request.getAuditRecord() : "");
map.put("auditFinding", request.getAuditFinding() != null ? request.getAuditFinding() : "");
map.put("evidenceBasis", request.getEvidenceBasis() != null ? request.getEvidenceBasis() : "");
map.put("handling", request.getHandling() != null ? request.getHandling() : "");
map.put("attachment", request.getAttachment() != null ? request.getAttachment() : "");
map.put("auditors", request.getAuditors() != null ? request.getAuditors() : "");
map.put("compileDate", request.getCompileDate() != null ? request.getCompileDate() : "");
map.put("providerOpinion", request.getProviderOpinion() != null ? request.getProviderOpinion() : "");
map.put("providerDate", request.getProviderDate() != null ? request.getProviderDate() : "");
map.put("attachmentPages", request.getAttachmentPages() != null ? request.getAttachmentPages() : "");
map.put("feedbackDeadline", request.getFeedbackDeadline() != null ? request.getFeedbackDeadline() : "");
// 获取登录用户信息
final User loginUser = getLoginUser();
if (request.getAuditors() == null || request.getAuditors().isEmpty()) {
map.put("auditors", loginUser.getUsername());
}
// 使用 Easypoi 的 Word 模板功能生成取证单
XWPFDocument document = WordExportUtil.exportWord07(
templateConfig.getEvidenceTemplatePath(), // 需要配置取证单模板路径
map
);
// 处理换行,确保 \n 转为硬回车(新段落)
processParagraphs(document);
// 设置响应头
String fileName = "审计取证单_" + (request.getProjectName() != null ? request.getProjectName() : "取证单") + ".docx";
response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
response.setHeader("Content-Disposition", "attachment; filename=" + java.net.URLEncoder.encode(fileName, "UTF-8"));
// 输出文档
try (OutputStream out = response.getOutputStream()) {
document.write(out);
out.flush();
}
} catch (Exception e) {
log.error("生成审计取证单Word文档失败", e);
throw new RuntimeException("生成审计取证单失败", e);
} finally {
ZipSecureFile.setMinInflateRatio(originalMinInflateRatio);
}
}
/**
* 处理段落换行(增强版,同时处理表格单元格)
*/
private void processParagraphs(XWPFDocument document) {
// 1. 处理普通段落
List<XWPFParagraph> originalParas = new ArrayList<>(document.getParagraphs());
for (XWPFParagraph para : originalParas) {
String text = para.getText();
if (text == null || !text.contains("\n")) {
continue;
}
String[] parts = text.replace("\r\n", "\n").replace("\r", "\n").split("\n");
// 在原段落位置之前插入新段落
int pos = document.getPosOfParagraph(para);
// 修正:按正序插入(从前往后)
for (int i = 0; i < parts.length; i++) {
// 创建新段落
XWPFParagraph newPara = document.insertNewParagraph(para.getCTP().newCursor());
// 复制样式
newPara.getCTP().setPPr(para.getCTP().getPPr());
XWPFRun newRun = newPara.createRun();
newRun.setText(parts[i].trim());
if (!para.getRuns().isEmpty()) {
newRun.getCTR().setRPr(para.getRuns().get(0).getCTR().getRPr());
}
}
// 删除原段落
document.removeBodyElement(pos + parts.length);
}
// 2. 处理表格单元格中的段落
List<XWPFTable> tables = document.getTables();
for (XWPFTable table : tables) {
for (XWPFTableRow row : table.getRows()) {
for (XWPFTableCell cell : row.getTableCells()) {
List<XWPFParagraph> cellParagraphs = cell.getParagraphs();
for (XWPFParagraph para : cellParagraphs) {
String text = para.getText();
if (text == null || !text.contains("\n")) {
continue;
}
// 清空原段落内容
for (int i = para.getRuns().size() - 1; i >= 0; i--) {
para.removeRun(i);
}
// 分割文本并按行添加
String[] lines = text.replace("\r\n", "\n").replace("\r", "\n").split("\n");
for (int i = 0; i < lines.length; i++) {
XWPFRun run = para.createRun();
run.setText(lines[i].trim());
// 如果不是最后一行,添加换行
if (i < lines.length - 1) {
run.addBreak();
}
}
}
}
}
}
}
}

View File

@@ -0,0 +1,352 @@
package com.gxwebsoft.ai.controller;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gxwebsoft.ai.dto.AuditContentRequest;
import com.gxwebsoft.ai.entity.AiCloudDoc;
import com.gxwebsoft.ai.entity.AiCloudFile;
import com.gxwebsoft.ai.service.AiHistoryService;
import com.gxwebsoft.ai.utils.ExcelExportTool;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.pwl.entity.PwlProjectLibrary;
import com.gxwebsoft.pwl.service.PwlProjectLibraryService;
import com.gxwebsoft.ai.service.AiCloudDocService;
import com.gxwebsoft.ai.service.AiCloudFileService;
import com.gxwebsoft.ai.service.KnowledgeBaseService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* 审计内容基础控制器
*/
@Slf4j
public abstract class BaseAuditContentController extends BaseController {
@Autowired
protected AiCloudDocService aiCloudDocService;
@Autowired
protected AiCloudFileService aiCloudFileService;
@Autowired
protected KnowledgeBaseService knowledgeBaseService;
@Autowired
protected PwlProjectLibraryService pwlProjectLibraryService;
@Autowired
protected AiHistoryService aiHistoryService;
// 历史记录有效期(分钟)
protected static final int HISTORY_EXPIRE_MINUTES = 10;
/**
* 通用的表格数据生成方法
*/
protected ApiResult<?> generateTableData(AuditContentRequest request, String interfaceName, Function<GenerateParams, JSONObject> generateFunction) {
final User loginUser = getLoginUser();
String requestHistory = request.getHistory();
request.setHistory("");
// 检查历史记录
String requestHash = generateRequestHash(request, interfaceName);
var history = aiHistoryService.getValidHistory(requestHash, interfaceName, HISTORY_EXPIRE_MINUTES);
if (history != null) {
log.info("返回历史数据,请求哈希: {}", requestHash);
return success(JSONObject.parseObject(history.getResponseData()));
}
request.setHistory(requestHistory);
String kbIdTmp = "";
String libraryKbIds = "";
try {
// 创建临时知识库(如果需要)
if (hasUploadedFiles(request)) {
kbIdTmp = createTempKnowledgeBase(request);
}
// 查询项目库信息
libraryKbIds = getLibraryKbIds(request.getLibraryIds());
// 生成数据
String knowledgeBaseId = getKnowledgeBaseId(kbIdTmp, request.getKbIds());
GenerateParams params = new GenerateParams(knowledgeBaseId, libraryKbIds, request.getProjectLibrary(), loginUser.getUsername(), request.getHistory(), request.getSuggestion());
JSONObject result = generateFunction.apply(params);
if(result.getBoolean("success")) {
// 转换workPaperIndex原数据["文件名1"+"||"+"下载地址1","文件名2"+"||"+"下载地址2"],转换后:["文件ID1"+"||"+"文件名1"+"||"+"下载地址1","文件ID2"+"||"+"文件名2"+"||"+"下载地址2"]
convertWorkPaperFileInfo(result);
// 保存到历史记录
saveToHistory(request, interfaceName, requestHash, result, loginUser);
}
return success(result);
} catch (Exception e) {
log.error("生成表格数据失败,接口: {}", interfaceName, e);
return fail("生成表格数据失败: " + e.getMessage());
} finally {
cleanupTempKnowledgeBase(kbIdTmp);
}
}
private void convertWorkPaperFileInfo(JSONObject result) {
JSONArray data = result.getJSONArray("data");
for (int i = 0; i < data.size(); i++) {
JSONObject obj = data.getJSONObject(i);
JSONArray workPaperIndexFiles = obj.getJSONArray("workPaperIndex");
if (workPaperIndexFiles != null && !workPaperIndexFiles.isEmpty()) {
for (int j = 0; j < workPaperIndexFiles.size(); j++) {
String files = workPaperIndexFiles.getString(j);
workPaperIndexFiles.set(j, "FileId||" + files);
}
}
}
}
private void convertWorkPaperFileInfo2(JSONObject result) {
JSONArray data = result.getJSONArray("data");
for (int i = 0; i < data.size(); i++) {
JSONObject obj = data.getJSONObject(i);
JSONArray workPaperIndexFileIds = obj.getJSONArray("workPaperIndex");
// 先获取并转换 workPaperIndex 字段
if (workPaperIndexFileIds != null && !workPaperIndexFileIds.isEmpty()) {
// 先查询所有文件
List<AiCloudFile> aiCloudFiles = aiCloudFileService.list(new LambdaQueryWrapper<AiCloudFile>().in(AiCloudFile::getFileId, workPaperIndexFileIds));
// 创建文件ID到文件的映射便于查找
Map<String, AiCloudFile> fileMap = aiCloudFiles.stream().collect(Collectors.toMap(AiCloudFile::getFileId, file -> file));
// 创建转换后的数组(保持原顺序)
JSONArray transformedArray = new JSONArray();
for (Object fileIdObj : workPaperIndexFileIds) {
String fileId = (String) fileIdObj;
AiCloudFile file = fileMap.get(fileId);
if (file != null) {
String transformed = file.getFileId() + "||" + file.getFileName() + "||" + file.getFileUrl();
transformedArray.add(transformed);
} else {
transformedArray.add(fileIdObj);
}
}
// 将转换后的数据塞回原字段
obj.put("workPaperIndex", transformedArray);
// 使用 workPaperIndexFileIds 中的每个 fileId 替换其他字段中的四种格式
for (String key : obj.keySet()) {
if ("workPaperIndex".equals(key)) {
continue; // 跳过 workPaperIndex 字段
}
Object value = obj.get(key);
if (value instanceof String) {
String text = (String) value;
for (Object fileIdObj : workPaperIndexFileIds) {
String fileId = (String) fileIdObj;
text = text.replace("【FileId:" + fileId + "", "")
.replace("FileId:" + fileId + "", "")
.replace("(FileId:" + fileId + ")", "")
.replace("FileId:"+fileId, "")
.replace("" + fileId + "", "")
.replace("" + fileId + "", "")
.replace("(" + fileId + ")", "")
.replace(fileId, "");;
}
obj.put(key, text);
}
}
}
}
}
/**
* 生成请求哈希
*/
protected String generateRequestHash(AuditContentRequest request, String interfaceName) {
String requestJson = JSONObject.toJSONString(request);
return DigestUtil.md5Hex(interfaceName + ":" + requestJson);
}
/**
* 保存到历史记录
*/
protected void saveToHistory(AuditContentRequest request, String interfaceName, String requestHash, JSONObject result, User loginUser) {
try {
aiHistoryService.saveHistory(request.getProjectId(), requestHash, interfaceName, JSONObject.toJSONString(request), result.toJSONString(), loginUser.getUserId(), loginUser.getUsername(), loginUser.getTenantId());
} catch (Exception e) {
log.warn("保存历史记录失败", e);
}
}
/**
* 检查是否有上传的文件
*/
protected boolean hasUploadedFiles(AuditContentRequest request) {
return !request.getDocList().isEmpty() || !request.getFileList().isEmpty();
}
/**
* 获取知识库ID
*/
protected String getKnowledgeBaseId(String tempKbId, String requestKbIds) {
return StrUtil.isNotBlank(tempKbId) ? tempKbId : requestKbIds;
}
/**
* 获取项目库KB IDs
*/
protected String getLibraryKbIds(String libraryIds) {
if (StrUtil.isBlank(libraryIds)) {
return "";
}
List<String> idList = StrUtil.split(libraryIds, ',');
List<PwlProjectLibrary> ret = pwlProjectLibraryService.list(new LambdaQueryWrapper<PwlProjectLibrary>().in(PwlProjectLibrary::getId, idList));
return ret.stream().map(PwlProjectLibrary::getKbId).filter(StrUtil::isNotBlank).collect(Collectors.joining(","));
}
/**
* 创建临时知识库并提交文档
*/
protected String createTempKnowledgeBase(AuditContentRequest request) {
String kbIdTmp = knowledgeBaseService.createKnowledgeBaseTemp();
// 收集文档ID
Set<Integer> docIds = request.getDocList().stream().flatMap(docId -> aiCloudDocService.getSelfAndChildren(docId).stream()).map(AiCloudDoc::getId).collect(Collectors.toSet());
// 查询相关文件
List<AiCloudFile> fileList = getRelatedFiles(docIds, request.getFileList());
// 提取文件ID并提交到知识库
Set<String> kbFileIds = fileList.stream().map(AiCloudFile::getFileId).collect(Collectors.toSet());
if (!kbFileIds.isEmpty()) {
knowledgeBaseService.submitDocuments(kbIdTmp, new ArrayList<>(kbFileIds));
}
return kbIdTmp;
}
/**
* 获取相关文件列表
*/
protected List<AiCloudFile> getRelatedFiles(Set<Integer> docIds, List<Integer> fileList) {
LambdaQueryWrapper<AiCloudFile> queryWrapper = new LambdaQueryWrapper<AiCloudFile>()
.in(!docIds.isEmpty(), AiCloudFile::getDocId, docIds)
.or(!fileList.isEmpty())
.in(!fileList.isEmpty(), AiCloudFile::getId, fileList);
return aiCloudFileService.list(queryWrapper);
}
/**
* 清理临时知识库
*/
protected void cleanupTempKnowledgeBase(String kbId) {
if (StrUtil.isNotBlank(kbId)) {
try {
knowledgeBaseService.deleteIndex(kbId);
} catch (Exception e) {
log.warn("删除临时知识库失败: {}", kbId, e);
}
}
}
/**
* 通用的Excel导出方法
*/
protected <T> void exportToExcel(Map<String, Object> request, HttpServletResponse response,
String sheetName, Function<List<Map<String, Object>>, List<T>> converter,
Class<T> entityClass) {
List<Map<String, Object>> dataList = (List<Map<String, Object>>) request.get("data");
String companyName = (String) request.get("companyName");
List<T> exportData = converter.apply(dataList);
String fileName = sheetName + "_" + (companyName != null ? companyName : "未知公司");
String title = companyName != null ? companyName + " - " + sheetName : sheetName;
ExcelExportTool.exportExcel(exportData, entityClass, fileName, sheetName, title, response);
}
/**
* 带审计时间的Excel导出方法
*/
protected <T> void exportToExcelWithAuditTime(Map<String, Object> request, HttpServletResponse response,
String sheetName, Function<List<Map<String, Object>>, List<T>> converter,
Class<T> entityClass) {
List<Map<String, Object>> dataList = (List<Map<String, Object>>) request.get("data");
String companyName = (String) request.get("companyName");
String auditTime = (String) request.get("auditTime");
List<T> exportData = converter.apply(dataList);
String fileName = sheetName + "_" + (companyName != null ? companyName : "未知公司");
String title = companyName != null ? companyName + " - " + sheetName : sheetName;
if (auditTime != null) {
title += "(审计时间:" + auditTime + "";
}
ExcelExportTool.exportExcel(exportData, entityClass, fileName, sheetName, title, response);
}
/**
* 参数包装类
*/
protected static class GenerateParams {
public final String knowledgeBaseId;
public final String libraryKbIds;
public final String projectLibrary;
public final String username;
public final String history;
public final String suggestion;
public GenerateParams(String knowledgeBaseId, String libraryKbIds, String projectLibrary, String username, String history, String suggestion) {
this.knowledgeBaseId = knowledgeBaseId;
this.libraryKbIds = libraryKbIds;
this.projectLibrary = projectLibrary;
this.username = username;
this.history = history;
this.suggestion = suggestion;
}
}
// ========== 通用的工具方法 ==========
/**
* 获取字符串值
*/
protected String getStringValue(Map<String, Object> map, String key) {
Object value = map.get(key);
return value != null ? value.toString() : "";
}
/**
* 格式化底稿索引
*/
protected String formatWorkPaperIndex(Object workPaperIndex) {
if (workPaperIndex == null) {
return "";
}
if (workPaperIndex instanceof List) {
List<?> list = (List<?>) workPaperIndex;
return String.join(", ", list.stream()
.map(Object::toString)
.collect(Collectors.toList()));
}
return workPaperIndex.toString();
}
}

View File

@@ -93,7 +93,8 @@ public class KnowledgeBaseController extends BaseController {
}
}
boolean result = knowledgeBaseService.uploadDocuments(kbId, files);
List<String> fileIds = knowledgeBaseService.uploadDocuments(kbId, files);
boolean result = knowledgeBaseService.submitDocuments(kbId, fileIds);
if (result) {
return success("成功上传 " + files.length + " 个文件");

View File

@@ -10,6 +10,11 @@ import lombok.Data;
@Data
public class AuditContentRequest {
/**
* 项目ID
*/
private Long projectId;
/**
* 企业库
*/
@@ -30,6 +35,11 @@ public class AuditContentRequest {
*/
private String history;
/**
* 知识库关键词
*/
private String keywords;
/**
* 优化建议
*/

View File

@@ -0,0 +1,35 @@
package com.gxwebsoft.ai.dto;
import lombok.Data;
@Data
public class AuditEvidenceRequest {
// 基础信息
private String caseIndex; // 案引号
private String projectName; // 项目名称
private String auditedTarget; // 被审计单位或个人
private String auditMatter; // 审计事项
private String summaryTitle; // 标题
private String auditRecord; // 审计记录
private String auditFinding; // 审计发现
private String evidenceBasis; // 定性依据
private String handling; // 处理
private String suggestion; // 建议
private String attachment; // 附件
private String auditors; // 审计人员
private String compileDate; // 编制日期
private String providerOpinion; // 证据提供单位意见
private String providerDate; // 证据提供日期
private String attachmentPages; // 附件页数
private String feedbackDeadline; // 反馈期限
// 导出取证单使用
private String pageIndex;
private String pageTotal;
// 历史内容(用于工作流生成)
private String history;
// 用户信息
private String userName;
}

View File

@@ -0,0 +1,37 @@
package com.gxwebsoft.ai.dto.export;
import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.annotation.ExcelTarget;
import lombok.Data;
/**
* 预算执行情况审计表导出实体
*/
@Data
@ExcelTarget("BudgetExecutionExportEntity")
public class BudgetExecutionExportEntity {
@Excel(name = "项目", orderNum = "1", width = 30)
private String project;
@Excel(name = "上年结转", orderNum = "2", width = 15)
private String lastYearCarryOver;
@Excel(name = "本年预算小计", orderNum = "3", width = 15)
private String currentYearBudgetTotal;
@Excel(name = "年初批复预算数", orderNum = "4", width = 15)
private String initialApprovedBudget;
@Excel(name = "追加预算数", orderNum = "5", width = 15)
private String additionalBudgetAmount;
@Excel(name = "实际拨款数", orderNum = "6", width = 15)
private String actualAppropriation;
@Excel(name = "指标结余", orderNum = "7", width = 15)
private String indicatorBalance;
@Excel(name = "工作底稿索引", orderNum = "8", width = 20)
private String workPaperIndex;
}

View File

@@ -0,0 +1,64 @@
package com.gxwebsoft.ai.dto.export;
import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.annotation.ExcelTarget;
import lombok.Data;
/**
* 预算管理审计表导出实体
*/
@Data
@ExcelTarget("BudgetManageExportEntity")
public class BudgetManageExportEntity {
@Excel(name = "预算科目名称", orderNum = "1", width = 25)
private String budgetSubject;
@Excel(name = "指标来源-合计", orderNum = "2", width = 15)
private String indicatorSourceTotal;
@Excel(name = "指标来源-上年结余", orderNum = "3", width = 15)
private String indicatorSourceLastYearBalance;
@Excel(name = "指标来源-年初部门预算", orderNum = "4", width = 15)
private String indicatorSourceInitialBudget;
@Excel(name = "指标来源-追加(减)预算", orderNum = "5", width = 15)
private String indicatorSourceAdditionalBudget;
@Excel(name = "指标运用-合计", orderNum = "6", width = 15)
private String indicatorUseTotal;
@Excel(name = "指标运用-拨款小计", orderNum = "7", width = 15)
private String indicatorUseAppropriationSubtotal;
@Excel(name = "指标运用-拨款", orderNum = "8", width = 15)
private String indicatorUseAppropriation;
@Excel(name = "指标运用-工资统发", orderNum = "9", width = 15)
private String indicatorUseSalaryPayment;
@Excel(name = "指标运用-政府采购", orderNum = "10", width = 15)
private String indicatorUseGovProcurement;
@Excel(name = "财政管理专户", orderNum = "11", width = 15)
private String financeManagementAccount;
@Excel(name = "部门预算用于其他", orderNum = "12", width = 15)
private String budgetUsedForOther;
@Excel(name = "指标结余", orderNum = "13", width = 15)
private String indicatorBalance;
@Excel(name = "政府采购", orderNum = "14", width = 15)
private String governmentProcurement;
@Excel(name = "应拨单位款", orderNum = "15", width = 15)
private String payableToUnit;
@Excel(name = "其他", orderNum = "16", width = 15)
private String other;
@Excel(name = "工作底稿索引", orderNum = "17", width = 20)
private String workPaperIndex;
}

View File

@@ -0,0 +1,46 @@
package com.gxwebsoft.ai.dto.export;
import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.annotation.ExcelTarget;
import lombok.Data;
/**
* 历史审计问题整改表导出实体
*/
@Data
@ExcelTarget("HistoryTableExportEntity")
public class HistoryTableExportEntity {
@Excel(name = "序号", orderNum = "1", width = 8)
private String index;
@Excel(name = "审计年度", orderNum = "2", width = 12)
private String auditYear;
@Excel(name = "审计类型", orderNum = "3", width = 15)
private String auditType;
@Excel(name = "审计发现的问题", orderNum = "4", width = 40, needMerge = true)
private String problemFound;
@Excel(name = "整改要求", orderNum = "5", width = 30, needMerge = true)
private String rectificationRequirement;
@Excel(name = "整改措施", orderNum = "6", width = 30, needMerge = true)
private String rectificationMeasures;
@Excel(name = "整改完成情况", orderNum = "7", width = 15)
private String rectificationStatus;
@Excel(name = "整改完成时间", orderNum = "8", width = 15)
private String completionDate;
@Excel(name = "整改责任人", orderNum = "9", width = 15)
private String responsiblePerson;
@Excel(name = "备注", orderNum = "10", width = 20, needMerge = true)
private String remark;
@Excel(name = "工作底稿索引", orderNum = "11", width = 25, needMerge = true)
private String workPaperIndex;
}

View File

@@ -0,0 +1,40 @@
package com.gxwebsoft.ai.dto.export;
import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.annotation.ExcelTarget;
import lombok.Data;
/**
* 单位层面财务管理内部控制测试表导出实体
*/
@Data
@ExcelTarget("InternalControlExportEntity")
public class InternalControlExportEntity {
@Excel(name = "序号", orderNum = "1", width = 8)
private String index;
@Excel(name = "控制环节", orderNum = "2", width = 25)
private String controlLink;
@Excel(name = "控制要求", orderNum = "3", width = 25)
private String controlRequirement;
@Excel(name = "控制活动描述", orderNum = "4", width = 30)
private String controlActivity;
@Excel(name = "控制职责岗位", orderNum = "5", width = 20)
private String controlPosition;
@Excel(name = "测试步骤", orderNum = "6", width = 30)
private String testSteps;
@Excel(name = "检查的证据及测试内容", orderNum = "7", width = 40)
private String checkEvidence;
@Excel(name = "测试结果", orderNum = "8", width = 12)
private String testResult;
@Excel(name = "工作底稿索引", orderNum = "9", width = 25)
private String workPaperIndex;
}

View File

@@ -0,0 +1,31 @@
package com.gxwebsoft.ai.dto.export;
import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.annotation.ExcelTarget;
import lombok.Data;
/**
* 重大投资情况审计表导出实体
*/
@Data
@ExcelTarget("InvestmentSituationExportEntity")
public class InvestmentSituationExportEntity {
@Excel(name = "审计类别", orderNum = "1", width = 20)
private String category;
@Excel(name = "审计内容", orderNum = "2", width = 60)
private String auditContent;
@Excel(name = "检查的证据及测试内容", orderNum = "3", width = 80)
private String checkEvidence;
@Excel(name = "测试结果", orderNum = "4", width = 15)
private String testResult;
@Excel(name = "工作底稿索引", orderNum = "5", width = 40)
private String workPaperIndex;
@Excel(name = "文件索引", orderNum = "6", width = 40)
private String fileIndex;
}

View File

@@ -0,0 +1,31 @@
package com.gxwebsoft.ai.dto.export;
import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.annotation.ExcelTarget;
import lombok.Data;
/**
* 党风廉政建设责任制审计表导出实体
*/
@Data
@ExcelTarget("PartyConductExportEntity")
public class PartyConductExportEntity {
@Excel(name = "大类", orderNum = "1", width = 20, isWrap = true)
private String category;
@Excel(name = "子类", orderNum = "2", width = 25, isWrap = true)
private String subCategory;
@Excel(name = "小类", orderNum = "3", width = 15, isWrap = true)
private String detailCategory;
@Excel(name = "内容", orderNum = "4", width = 40, isWrap = true)
private String content;
@Excel(name = "执行情况", orderNum = "5", width = 12)
private String executionStatus;
@Excel(name = "工作底稿索引", orderNum = "6", width = 30, isWrap = true)
private String workPaperIndex;
}

View File

@@ -0,0 +1,40 @@
// PersonnelExportEntity.java
package com.gxwebsoft.ai.dto.export;
import lombok.Data;
/**
* 人员编制管理审计导出实体
*/
@Data
public class PersonnelExportEntity {
/**
* 序号
*/
private String index;
/**
* 审计内容
*/
private String auditContent;
/**
* 审计目标
*/
private String auditTarget;
/**
* 审计证据
*/
private String auditEvidence;
/**
* 生成结果
*/
private String generationResult;
/**
* 工作底稿索引
*/
private String workPaperIndex;
}

View File

@@ -0,0 +1,58 @@
package com.gxwebsoft.ai.dto.export;
import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.annotation.ExcelTarget;
import lombok.Data;
/**
* 国有资产管理审计导出实体
*/
@Data
@ExcelTarget("StateAssetsAuditExportEntity")
public class StateAssetsAuditExportEntity {
@Excel(name = "序号", orderNum = "0", width = 8)
private String index;
@Excel(name = "国有资产名称", orderNum = "1", width = 30)
private String assetName;
@Excel(name = "国有资产取得方式", orderNum = "2", width = 25)
private String acquisitionMethod;
@Excel(name = "国有资产价值", orderNum = "3", width = 20)
private String assetValue;
@Excel(name = "国有资产地址", orderNum = "4", width = 30)
private String assetAddress;
@Excel(name = "面积", orderNum = "5", width = 15)
private String area;
@Excel(name = "承租方", orderNum = "6", width = 25)
private String tenant;
@Excel(name = "合同金额", orderNum = "7", width = 20)
private String contractAmount;
@Excel(name = "租赁合同起止时间", orderNum = "8", width = 25)
private String leasePeriod;
@Excel(name = "国有资产租金缴纳时间", orderNum = "9", width = 25)
private String rentPaymentTime;
@Excel(name = "国有资产出租是否上平台", orderNum = "10", width = 25)
private String platformLease;
@Excel(name = "国有资产出租的审批文件", orderNum = "11", width = 35)
private String approvalDoc;
@Excel(name = "是否纳入预算", orderNum = "12", width = 15)
private String inBudget;
@Excel(name = "备注", orderNum = "13", width = 30)
private String remark;
@Excel(name = "工作底稿索引", orderNum = "14", width = 40)
private String workPaperIndex;
}

View File

@@ -0,0 +1,37 @@
package com.gxwebsoft.ai.dto.export;
import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.annotation.ExcelTarget;
import lombok.Data;
/**
* 单位发展战略执行审计导出实体
*/
@Data
@ExcelTarget("StrategyAuditExportEntity")
public class StrategyAuditExportEntity {
@Excel(name = "序号", orderNum = "0", width = 10)
private String index;
// @Excel(name = "审计分类", orderNum = "1", width = 15)
// private String category;
@Excel(name = "审计内容", orderNum = "2", width = 50)
private String auditContent;
// @Excel(name = "政策法规要求", orderNum = "3", width = 40)
// private String policyRequirement;
// @Excel(name = "审计标准", orderNum = "4", width = 30)
// private String auditStandard;
@Excel(name = "检查的证据及测试内容", orderNum = "5", width = 40)
private String checkEvidence;
@Excel(name = "测试结果", orderNum = "6", width = 10)
private String testResult;
@Excel(name = "工作底稿索引", orderNum = "7", width = 20)
private String workPaperIndex;
}

View File

@@ -0,0 +1,43 @@
package com.gxwebsoft.ai.dto.export;
import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.annotation.ExcelTarget;
import lombok.Data;
/**
* 目标责任制完成情况审计导出实体
*/
@Data
@ExcelTarget("TargetAuditExportEntity")
public class TargetAuditExportEntity {
@Excel(name = "序号", orderNum = "0", width = 8)
private String index;
@Excel(name = "年度", orderNum = "1", width = 12)
private String year;
@Excel(name = "上级主管部门下达目标责任制-下达文件", orderNum = "2", width = 40)
private String superiorFile;
@Excel(name = "上级主管部门下达目标责任制-完成情况", orderNum = "3", width = 15)
private String superiorCompletion;
@Excel(name = "上级主管部门下达目标责任制-未完成原因", orderNum = "4", width = 30)
private String superiorReason;
@Excel(name = "单位自定下达目标责任制-计划文件", orderNum = "5", width = 40)
private String selfPlan;
@Excel(name = "单位自定下达目标责任制-完成情况", orderNum = "6", width = 15)
private String selfCompletion;
@Excel(name = "单位自定下达目标责任制-未完成原因", orderNum = "7", width = 30)
private String selfReason;
@Excel(name = "备注", orderNum = "8", width = 30)
private String remark;
@Excel(name = "工作底稿索引", orderNum = "9", width = 40)
private String workPaperIndex;
}

View File

@@ -24,6 +24,9 @@ public class AiHistory implements Serializable {
@TableId(value = "id", type = IdType.AUTO)
private Long id;
@Schema(description = "项目ID")
private Long projectId;
@Schema(description = "请求哈希值")
private String requestHash;

View File

@@ -10,6 +10,9 @@
<if test="param.id != null">
AND a.id = #{param.id}
</if>
<if test="param.projectId != null">
AND a.project_id = #{param.projectId}
</if>
<if test="param.requestHash != null">
AND a.request_hash = #{param.requestHash}
</if>

View File

@@ -24,6 +24,10 @@ public class AiHistoryParam extends BaseParam {
@QueryField(type = QueryType.EQ)
private Long id;
@Schema(description = "项目ID")
@QueryField(type = QueryType.EQ)
private Long projectId;
@Schema(description = "请求哈希值")
@QueryField(type = QueryType.EQ)
private String requestHash;

View File

@@ -51,6 +51,7 @@ public interface AiHistoryService extends IService<AiHistory> {
/**
* 保存历史记录
*
* @param projectId 项目ID
* @param requestHash 请求哈希值
* @param interfaceName 接口名称
* @param requestData 请求数据
@@ -58,5 +59,5 @@ public interface AiHistoryService extends IService<AiHistory> {
* @param userId 用户ID
* @param username 用户名
*/
void saveHistory(String requestHash, String interfaceName, String requestData, String responseData, Integer userId, String username, Integer tenantId);
void saveHistory(Long projectId, String requestHash, String interfaceName, String requestData, String responseData, Integer userId, String username, Integer tenantId);
}

View File

@@ -0,0 +1,15 @@
package com.gxwebsoft.ai.service;
import com.alibaba.fastjson.JSONObject;
/**
* 审计内容10服务接口 - 党风廉政建设责任制审计
*/
public interface AuditContent10PartyConductService {
/**
* 生成党风廉政建设责任制审计表数据
*/
JSONObject generatePartyConductTableData(String kbIds, String libraryKbIds, String projectLibrary,
String userName, String history, String suggestion);
}

View File

@@ -0,0 +1,23 @@
package com.gxwebsoft.ai.service;
import com.alibaba.fastjson.JSONObject;
/**
* 审计内容11-历史审计问题整改服务接口
*/
public interface AuditContent11HistoryService {
/**
* 生成历史审计问题整改表数据
*
* @param kbIds 知识库ID
* @param libraryKbIds 项目库知识库ID
* @param projectLibrary 项目库
* @param userName 用户名
* @param history 历史内容
* @param suggestion 用户建议
* @return JSON结果
*/
JSONObject generateHistoryTableData(String kbIds, String libraryKbIds, String projectLibrary,
String userName, String history, String suggestion);
}

View File

@@ -0,0 +1,24 @@
package com.gxwebsoft.ai.service;
import com.alibaba.fastjson.JSONObject;
/**
* 单位发展战略执行审计服务接口
*/
public interface AuditContent2StrategyService {
/**
* 生成单位发展战略执行审计表数据
*
* @param kbIds 企业知识库ID多个用逗号分隔
* @param libraryKbIds 公共法律法规库ID多个用逗号分隔
* @param projectLibrary 审计案例库ID
* @param userName 用户名
* @param history 历史记录
* @param suggestion 用户建议
* @return JSON格式的审计表数据
*/
JSONObject generateStrategyAuditTableData(String kbIds, String libraryKbIds,
String projectLibrary, String userName,
String history, String suggestion);
}

View File

@@ -0,0 +1,16 @@
package com.gxwebsoft.ai.service;
import com.alibaba.fastjson.JSONObject;
/**
* 审计内容4-目标责任制完成情况服务接口
*/
public interface AuditContent4TargetService {
/**
* 生成目标责任制完成情况审计表数据
*/
JSONObject generateTargetAuditTableData(String kbIds, String libraryKbIds,
String projectLibrary, String userName,
String history, String suggestion);
}

View File

@@ -0,0 +1,23 @@
package com.gxwebsoft.ai.service;
import com.alibaba.fastjson.JSONObject;
/**
* 审计内容5-预算执行情况审计服务接口
*/
public interface AuditContent5BudgetExecutionService {
/**
* 生成预算执行情况审计表数据
* @param kbIds 知识库ID
* @param libraryKbIds 项目库知识库ID
* @param projectLibrary 项目库
* @param userName 用户名
* @param history 历史记录
* @param suggestion 用户建议
* @param data 前端传入的预算管理审计数据(可选)
* @return JSON格式的审计表数据
*/
JSONObject generateBudgetExecutionTableData(String kbIds, String libraryKbIds, String projectLibrary,
String userName, String history, String suggestion, Object data);
}

View File

@@ -0,0 +1,22 @@
package com.gxwebsoft.ai.service;
import com.alibaba.fastjson.JSONObject;
/**
* 审计内容5-预算管理审计服务接口
*/
public interface AuditContent5BudgetManageService {
/**
* 生成预算管理审计表数据
* @param kbIds 知识库ID
* @param libraryKbIds 项目库知识库ID
* @param projectLibrary 项目库
* @param userName 用户名
* @param history 历史记录
* @param suggestion 用户建议
* @return JSON格式的审计表数据
*/
JSONObject generateBudgetManageTableData(String kbIds, String libraryKbIds, String projectLibrary,
String userName, String history, String suggestion, Object data);
}

View File

@@ -0,0 +1,15 @@
package com.gxwebsoft.ai.service;
import com.alibaba.fastjson.JSONObject;
/**
* 审计内容6-国资管理情况服务接口
*/
public interface AuditContent6StateAssetsService {
/**
* 生成国有资产管理审计表数据
*/
JSONObject generateStateAssetsAuditTableData(String kbIds, String libraryKbIds, String projectLibrary,
String userName, String history, String suggestion);
}

View File

@@ -0,0 +1,23 @@
package com.gxwebsoft.ai.service;
import com.alibaba.fastjson.JSONObject;
/**
* 审计内容7-重大投资情况服务接口
*/
public interface AuditContent7InvestmentService {
/**
* 生成重大投资情况审计表数据
* @param kbIds 知识库ID
* @param libraryKbIds 项目库知识库ID
* @param projectLibrary 审计案例库ID
* @param userName 用户名
* @param history 历史记录
* @param suggestion 用户建议
* @return 生成的表格数据
*/
JSONObject generateInvestmentSituationTableData(String kbIds, String libraryKbIds,
String projectLibrary, String userName,
String history, String suggestion);
}

View File

@@ -0,0 +1,13 @@
package com.gxwebsoft.ai.service;
import com.alibaba.fastjson.JSONObject;
public interface AuditContent8InternalControlService {
/**
* 生成单位层面财务管理内部控制测试表数据
*/
JSONObject generateInternalControlTableData(
String kbIds, String libraryKbIds, String projectLibrary,
String userName, String history, String suggestion);
}

View File

@@ -0,0 +1,13 @@
package com.gxwebsoft.ai.service;
import com.alibaba.fastjson.JSONObject;
public interface AuditContent9PersonnelService {
/**
* 生成人员编制管理审计表数据
*/
JSONObject generatePersonnelTableData(
String kbIds, String libraryKbIds, String projectLibrary,
String userName, String history, String suggestion);
}

View File

@@ -0,0 +1,11 @@
package com.gxwebsoft.ai.service;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.ai.dto.AuditEvidenceRequest;
public interface AuditEvidenceService {
/**
* 生成审计取证单
*/
JSONObject generateAuditEvidence(AuditEvidenceRequest request);
}

View File

@@ -58,15 +58,15 @@ public interface KnowledgeBaseService {
/**
* 上传知识库文档
*/
boolean uploadDocuments(String kbId, MultipartFile[] files);
List<String> uploadDocuments(String kbId, MultipartFile[] files);
/**
* 知识库追加导入已解析的文档
*/
void submitDocuments(String kbId, String fileId);
boolean submitDocuments(String kbId, String fileId);
/**
* 知识库追加导入已解析的文档
*/
void submitDocuments(String kbId, List<String> fileIds);
boolean submitDocuments(String kbId, List<String> fileIds);
}

View File

@@ -5,13 +5,17 @@ import com.aliyun.bailian20231229.models.RetrieveResponse;
import com.aliyun.bailian20231229.models.RetrieveResponseBody;
import com.aliyun.bailian20231229.models.RetrieveResponseBody.RetrieveResponseBodyData;
import com.aliyun.bailian20231229.models.RetrieveResponseBody.RetrieveResponseBodyDataNodes;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.ai.config.KnowledgeBaseConfig;
import com.gxwebsoft.ai.entity.AiCloudFile;
import com.gxwebsoft.ai.factory.KnowledgeBaseClientFactory;
import com.gxwebsoft.ai.util.KnowledgeBaseUtil;
import com.gxwebsoft.ai.service.AiCloudFileService;
import com.gxwebsoft.ai.util.AiCloudKnowledgeBaseUtil;
import com.gxwebsoft.common.core.context.TenantContext;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
@@ -20,6 +24,10 @@ import org.springframework.beans.factory.annotation.Autowired;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@Slf4j
public abstract class AbstractAuditContentService {
@@ -30,8 +38,14 @@ public abstract class AbstractAuditContentService {
@Autowired
protected KnowledgeBaseConfig config;
@Autowired
protected AiCloudFileService aiCloudFileService;
protected static final String DIFY_WORKFLOW_URL = "http://1.14.159.185:8180/v1/workflows/run";
// 用于同步的锁对象池
private static final Map<String, Object> kbLocks = new ConcurrentHashMap<>();
/**
* 调用工作流通用方法
*/
@@ -53,17 +67,29 @@ public abstract class AbstractAuditContentService {
JsonNode rootNode = objectMapper.readTree(result);
String outputText = rootNode.path("data")
.path("outputs")
.path("result")
.asText();
.path("outputs")
.path("result")
.asText();
if (StrUtil.isBlank(outputText)) {
log.warn("{}工作流返回结果为空", workflowName);
log.warn("{}工作流返回 result 为空", workflowName);
return new JSONArray();
}
JsonNode arrayNode = objectMapper.readTree(outputText);
JSONArray jsonArray = JSONArray.parseArray(arrayNode.toString());
// ★ NEW先从 ```json``` 中提取
String jsonText = extractJsonFromMarkdown(outputText);
// ★ NEW兜底提取
if (StrUtil.isBlank(jsonText)) {
jsonText = extractFirstJson(outputText);
}
if (StrUtil.isBlank(jsonText)) {
log.error("{} 工作流返回内容无法解析为 JSON原始内容{}", workflowName, outputText);
throw new RuntimeException("Dify 返回内容中未找到有效 JSON");
}
JSONArray jsonArray = JSONArray.parseArray(jsonText);
log.info("成功解析{}工作流返回数据,记录数: {}", workflowName, jsonArray.size());
return jsonArray;
@@ -74,6 +100,55 @@ public abstract class AbstractAuditContentService {
}
}
/**
* 从 ```json 代码块中提取 JSON
*/
private static String extractJsonFromMarkdown(String text) {
if (StrUtil.isBlank(text)) {
return null;
}
Pattern pattern = Pattern.compile("```json\\s*(.*?)\\s*```", Pattern.DOTALL);
Matcher matcher = pattern.matcher(text);
if (matcher.find()) {
return matcher.group(1).trim();
}
return null;
}
/**
* 兜底:从混合文本中提取第一个完整 JSON{} 或 []
*/
private static String extractFirstJson(String text) {
if (StrUtil.isBlank(text)) return null;
int start = -1;
char open = 0, close = 0;
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
if (c == '{' || c == '[') {
start = i;
open = c;
close = (c == '{') ? '}' : ']';
break;
}
}
if (start == -1) return null;
int count = 0;
for (int i = start; i < text.length(); i++) {
char c = text.charAt(i);
if (c == open) count++;
if (c == close) count--;
if (count == 0) {
return text.substring(start, i + 1);
}
}
return null;
}
/**
* 构建工作流请求通用方法
*/
@@ -101,54 +176,147 @@ public abstract class AbstractAuditContentService {
* 查询知识库通用方法
*/
protected List<String> queryKnowledgeBase(String kbId, List<String> queries, int topK) {
Set<String> results = new LinkedHashSet<>();
String workspaceId = config.getWorkspaceId();
Object lock = kbLocks.computeIfAbsent(kbId, k -> new Object());
synchronized (lock) {
try {
// 1. 收集所有节点和文档ID
List<RetrieveResponseBodyDataNodes> allNodes = collectKnowledgeNodes(kbId, queries, topK);
if (allNodes.isEmpty()) {
return new ArrayList<>();
}
// 2. 批量查询文件URL
Map<String, String> fileUrlMap = TenantContext.callIgnoreTenant(() -> batchQueryFileUrls(allNodes));
// 3. 处理节点生成结果
return processNodesToResults(allNodes, fileUrlMap);
} catch (Exception e) {
log.error("查询知识库失败 - kbId: {}", kbId, e);
return new ArrayList<>();
}
}
}
/**
* 收集知识库节点
*/
private List<RetrieveResponseBodyDataNodes> collectKnowledgeNodes(String kbId, List<String> queries, int topK) {
List<RetrieveResponseBodyDataNodes> allNodes = new ArrayList<>();
String workspaceId = config.getWorkspaceId();
try {
Client client = clientFactory.createClient();
for (String query : queries) {
try {
RetrieveResponse resp = KnowledgeBaseUtil.retrieveIndex(client, workspaceId, kbId, query);
Optional.ofNullable(resp)
RetrieveResponse resp = AiCloudKnowledgeBaseUtil.retrieveIndex(client, workspaceId, kbId, query);
List<RetrieveResponseBodyDataNodes> nodes = Optional.ofNullable(resp)
.map(RetrieveResponse::getBody)
.map(RetrieveResponseBody::getData)
.map(RetrieveResponseBodyData::getNodes)
.orElse(Collections.emptyList())
.stream()
.limit(topK)
.forEach(node -> processKnowledgeNode(node, results));
.collect(Collectors.toList());
allNodes.addAll(nodes);
} catch (Exception e) {
log.warn("查询知识库失败 - kbId: {}, query: {}", kbId, query, e);
}
}
} catch (Exception e) {
log.error("创建知识库客户端失败", e);
}
return new ArrayList<>(results);
return allNodes;
}
/**
* 处理知识库节点通用方法
* 批量查询文件URL
*/
protected void processKnowledgeNode(RetrieveResponseBodyDataNodes node, Set<String> results) {
try {
String text = node.getText();
if (StrUtil.isBlank(text) || text.length() < 10) {
return;
}
String docName = extractDocumentName(node);
String formattedText = String.format("《%s》%s", docName, text);
results.add(formattedText);
} catch (Exception e) {
log.warn("处理知识库节点失败", e);
protected Map<String, String> batchQueryFileUrls(List<RetrieveResponseBodyDataNodes> nodes) {
// 收集所有文档ID
Set<String> docIds = nodes.stream().map(this::extractDocumentId).filter(StrUtil::isNotBlank).collect(Collectors.toSet());
if (docIds.isEmpty()) {
return Collections.emptyMap();
}
try {
// 批量查询
List<AiCloudFile> files = aiCloudFileService.list(new LambdaQueryWrapper<AiCloudFile>().in(AiCloudFile::getFileId, docIds));
// 构建映射表
return files.stream()
.filter(file -> file.getFileUrl() != null)
.collect(Collectors.toMap(
AiCloudFile::getFileId,
AiCloudFile::getFileUrl
));
} catch (Exception e) {
log.error("批量查询文件信息失败", e);
return Collections.emptyMap();
}
}
/**
* 处理节点生成结果
*/
private List<String> processNodesToResults(List<RetrieveResponseBodyDataNodes> nodes, Map<String, String> fileUrlMap) {
Set<String> results = new LinkedHashSet<>();
// 构建可用文件列表
StringBuilder fileListBuilder = new StringBuilder();
fileListBuilder.append("\n\n**可用真实文件列表(仅限以下文件,不得虚构其他文件名):**\n");
Set<String> processedFiles = new HashSet<>(); // 避免重复
for (RetrieveResponseBodyDataNodes node : nodes) {
try {
// 检查文本有效性
String text = node.getText();
if (StrUtil.isBlank(text) || text.length() < 10) {
continue;
}
// 获取文档信息
String docName = extractDocumentName(node);
String docId = extractDocumentId(node);
String fileUrl = fileUrlMap.get(docId);
if (StrUtil.isBlank(fileUrl)) {
fileUrl = extractDocumentUrl(node);
}
if (StrUtil.isBlank(fileUrl)) {
fileUrl = "无链接";
}
// 添加文件名到列表(去重)
if (StrUtil.isNotBlank(docName) && !processedFiles.contains(docName)) {
processedFiles.add(docName);
fileListBuilder.append("- 《").append(docName).append("");
if (!"无链接".equals(fileUrl)) {
fileListBuilder.append(" || ").append(fileUrl);
}
fileListBuilder.append("\n");
}
// 格式化为知识库内容
JSONObject json = new JSONObject();
json.put("document_name", docName);
json.put("file_url", fileUrl);
json.put("content", text);
String formattedText = json.toJSONString();
results.add(formattedText);
} catch (Exception e) {
log.warn("处理知识库节点失败", e);
}
}
// 添加文件列表到结果
fileListBuilder.append("\n**重要约束:**\n");
fileListBuilder.append("1. 只能使用上述列表中的文件,不得虚构其他文件名\n");
fileListBuilder.append("2. 如果某项检查未涉及上述文件,则 workPaperIndex 填写\"[]\"\n");
fileListBuilder.append("3. 所有文件必须来自提供的知识库内容\n");
results.add(fileListBuilder.toString());
return new ArrayList<>(results);
}
/**
@@ -170,6 +338,44 @@ public abstract class AbstractAuditContentService {
return "相关文档";
}
/**
* 提取文档Id通用方法
*/
protected String extractDocumentId(RetrieveResponseBodyDataNodes node) {
try {
Object metadataObj = node.getMetadata();
if (metadataObj instanceof Map) {
Map<?, ?> metadata = (Map<?, ?>) metadataObj;
Object docIdObj = metadata.get("doc_id");
if (docIdObj != null) {
return docIdObj.toString();
}
}
} catch (Exception e) {
log.debug("提取文档名称失败", e);
}
return "相关文档";
}
/**
* 提取文档url通用方法
*/
protected String extractDocumentUrl(RetrieveResponseBodyDataNodes node) {
try {
Object metadataObj = node.getMetadata();
if (metadataObj instanceof Map) {
Map<?, ?> metadata = (Map<?, ?>) metadataObj;
Object docIdObj = metadata.get("doc_url");
if (docIdObj != null) {
return docIdObj.toString();
}
}
} catch (Exception e) {
log.debug("提取文档名称失败", e);
}
return "相关文档";
}
/**
* 构建成功响应通用方法
*/

View File

@@ -6,8 +6,11 @@ import com.gxwebsoft.ai.config.KnowledgeBaseConfig;
import com.gxwebsoft.ai.factory.KnowledgeBaseClientFactory;
import com.gxwebsoft.ai.util.AiCloudDataCenterUtil;
import com.gxwebsoft.ai.util.AiCloudKnowledgeBaseUtil;
import com.gxwebsoft.common.system.controller.FileController;
import com.gxwebsoft.common.system.entity.FileRecord;
import com.gxwebsoft.common.system.entity.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
@@ -51,11 +54,15 @@ public class AiCloudFileServiceImpl extends ServiceImpl<AiCloudFileMapper, AiClo
private AiCloudDocService aiCloudDocService;
@Resource
@Lazy
private OaCompanyService oaCompanyService;
@Resource
private KnowledgeBaseService knowledgeBaseService;
@Resource
private FileController fileController;
@Override
public PageResult<AiCloudFile> pageRel(AiCloudFileParam param) {
PageParam<AiCloudFile, AiCloudFileParam> page = new PageParam<>(param);
@@ -92,6 +99,8 @@ public class AiCloudFileServiceImpl extends ServiceImpl<AiCloudFileMapper, AiClo
AddFileResponse addFileResponse = AiCloudDataCenterUtil.uploadFile(client, workspaceId, categoryId, file);
String fileId = addFileResponse.getBody().getData().getFileId();
FileRecord fileRecord = fileController.upload(file, loginUser.getTenantId());
// 保存文件信息到数据库
AiCloudFile aiCloudFile = new AiCloudFile();
aiCloudFile.setDocId(docId);
@@ -100,6 +109,7 @@ public class AiCloudFileServiceImpl extends ServiceImpl<AiCloudFileMapper, AiClo
aiCloudFile.setFileType(getFileExtension(file.getOriginalFilename()));
aiCloudFile.setFileExt(getFileExtension(file.getOriginalFilename()));
aiCloudFile.setFileId(fileId);
aiCloudFile.setFileUrl(fileRecord.getDownloadUrl());
aiCloudFile.setUploadTime(LocalDateTime.now());
aiCloudFile.setWorkspaceId(workspaceId);

View File

@@ -57,8 +57,9 @@ public class AiHistoryServiceImpl extends ServiceImpl<AiHistoryMapper, AiHistory
}
@Override
public void saveHistory(String requestHash, String interfaceName, String requestData, String responseData, Integer userId, String username, Integer tenantId) {
public void saveHistory(Long projectId, String requestHash, String interfaceName, String requestData, String responseData, Integer userId, String username, Integer tenantId) {
AiHistory history = new AiHistory();
history.setProjectId(projectId);
history.setRequestHash(requestHash);
history.setInterfaceName(interfaceName);
history.setRequestData(requestData);

View File

@@ -0,0 +1,307 @@
package com.gxwebsoft.ai.service.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.ai.constants.AuditContent10PartyConductConstants;
import com.gxwebsoft.ai.service.AuditContent10PartyConductService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import cn.hutool.core.util.StrUtil;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
@Slf4j
@Service
public class AuditContent10PartyConductServiceImpl extends AbstractAuditContentService implements AuditContent10PartyConductService {
// 工作流配置
private static final String DIFY_WORKFLOW_TOKEN = "Bearer app-NpWFaPdBAl3LH7HqRXenlnVD";
@Override
public JSONObject generatePartyConductTableData(String kbIds, String libraryKbIds, String projectLibrary, String userName, String history, String suggestion) {
log.info("开始生成党风廉政建设责任制审计表数据 - 用户: {}, kbIds: {}, libraryIds: {}, projectLibrary: {}", userName, kbIds, libraryKbIds, projectLibrary);
long startTime = System.currentTimeMillis();
try {
// 获取所有子类(基于常量类中的映射关系)
List<String> allSubCategories = AuditContent10PartyConductConstants.getAllSubCategories();
log.info("共发现 {} 个子类需要处理", allSubCategories.size());
// 异步并行处理每个子类
Map<String, CompletableFuture<JSONArray>> futures = processCategoriesAsync(
allSubCategories,
subCategory -> generateSubCategoryDataAsync(subCategory, kbIds, libraryKbIds, projectLibrary, userName, history, suggestion)
);
// 等待所有异步任务完成
CompletableFuture.allOf(futures.values().toArray(new CompletableFuture[0])).join();
// 合并所有子类的结果
JSONArray allData = mergeCategoryResults(allSubCategories, futures);
// 对结果进行排序(直接调用常量类的排序方法)
AuditContent10PartyConductConstants.sortPartyConductData(allData);
log.info("党风廉政建设责任制审计表生成成功 - 记录数: {}, 处理时间: {}ms", allData.size(), (System.currentTimeMillis() - startTime));
return buildSuccessResponse(allData, startTime, "party_conduct_audit");
} catch (Exception e) {
log.error("生成党风廉政建设责任制审计表失败", e);
return buildErrorResponse("生成党风廉政建设责任制审计表失败: " + e.getMessage());
}
}
/**
* 异步生成单个子类的数据
*/
@Async
public CompletableFuture<JSONArray> generateSubCategoryDataAsync(String subCategory, String kbIds, String libraryKbIds, String projectLibrary, String userName, String history, String suggestion) {
return CompletableFuture.supplyAsync(() -> {
try {
log.info("开始生成子类 {} 的数据", subCategory);
// 1. 为当前子类召回相关知识
Map<String, List<String>> knowledgeSources = retrieveKnowledgeForSubCategory(
subCategory, kbIds, libraryKbIds, projectLibrary
);
// 2. 构建完整的知识上下文(包含固定内容和动态内容)
String knowledgeContext = buildCompleteKnowledgeContext(
subCategory, knowledgeSources, history, suggestion
);
// 3. 调用工作流生成数据
JSONObject requestBody = buildWorkflowRequest(knowledgeContext, userName);
JSONArray subCategoryData = callWorkflow(DIFY_WORKFLOW_URL, DIFY_WORKFLOW_TOKEN, requestBody, "廉政情况-" + subCategory);
log.info("子类 {} 数据生成完成,生成 {} 条记录", subCategory, subCategoryData.size());
return subCategoryData;
} catch (Exception e) {
log.error("生成子类 {} 数据失败", subCategory, e);
return new JSONArray();
}
});
}
/**
* 为单个子类检索相关知识
*/
private Map<String, List<String>> retrieveKnowledgeForSubCategory(String subCategory, String kbIds, String libraryKbIds, String projectLibrary) {
Map<String, List<String>> knowledgeSources = new HashMap<>();
knowledgeSources.put("enterprise", new ArrayList<>());
knowledgeSources.put("regulation", new ArrayList<>());
knowledgeSources.put("auditCase", new ArrayList<>());
// 构建当前子类的查询词
List<String> subCategoryQueries = buildSubCategoryQueries(subCategory);
// 企业单位库检索
if (StrUtil.isNotBlank(kbIds)) {
Arrays.stream(kbIds.split(","))
.map(String::trim)
.filter(StrUtil::isNotBlank)
.forEach(kbId -> knowledgeSources.get("enterprise")
.addAll(queryKnowledgeBase(kbId, subCategoryQueries, 100)));
}
// 公共法律法规库检索
if (StrUtil.isNotBlank(libraryKbIds)) {
Arrays.stream(libraryKbIds.split(","))
.map(String::trim)
.filter(StrUtil::isNotBlank)
.forEach(libId -> knowledgeSources.get("regulation")
.addAll(queryKnowledgeBase(libId, subCategoryQueries, 80)));
}
// 审计案例库检索
if (StrUtil.isNotBlank(projectLibrary)) {
knowledgeSources.get("auditCase").addAll(
queryKnowledgeBase(projectLibrary, subCategoryQueries, 60));
}
// 智能去重和排序
knowledgeSources.forEach((key, list) -> {
List<String> processed = list.stream()
.distinct()
.sorted(this::partyConductComparator)
.limit(getLimitBySourceType(key))
.collect(Collectors.toList());
knowledgeSources.put(key, processed);
});
log.debug("子类 {} 知识检索完成 - 企业: {}条, 法规: {}条, 案例: {}条",
subCategory,
knowledgeSources.get("enterprise").size(),
knowledgeSources.get("regulation").size(),
knowledgeSources.get("auditCase").size());
return knowledgeSources;
}
/**
* 构建子类特定的查询词
*/
private List<String> buildSubCategoryQueries(String subCategory) {
List<String> queries = new ArrayList<>();
// 基础查询词
queries.add(subCategory);
queries.add(subCategory + " 制度规定");
queries.add(subCategory + " 执行情况");
// 根据子类类型添加特定查询词
if (subCategory.equals(AuditContent10PartyConductConstants.SUBCATEGORY_MAIN_RESPONSIBILITY)) {
queries.add("主体责任 监督责任 责任清单");
queries.add("党风廉政建设责任制 党组责任 纪检责任");
} else if (subCategory.equals(AuditContent10PartyConductConstants.SUBCATEGORY_EIGHT_REGULATIONS)) {
queries.add("中央八项规定 监督检查 问题线索");
queries.add("八项规定精神 违规问题 通报曝光");
} else if (subCategory.equals(AuditContent10PartyConductConstants.SUBCATEGORY_ANTI_CORRUPTION)) {
queries.add("群众身边腐败 四风问题 案件查处");
queries.add("基层腐败 专项治理 长效机制");
} else if (subCategory.equals(AuditContent10PartyConductConstants.SUBCATEGORY_DISCIPLINE_ENFORCEMENT)) {
queries.add("政治纪律 组织纪律 政令畅通");
queries.add("纪律执行 重大决策 转办督办");
} else if (subCategory.equals(AuditContent10PartyConductConstants.SUBCATEGORY_MONTHLY_REPORT) ||
subCategory.equals(AuditContent10PartyConductConstants.SUBCATEGORY_RECTIFICATION_TASK) ||
subCategory.equals(AuditContent10PartyConductConstants.SUBCATEGORY_RECTIFICATION_ACCOUNTABILITY)) {
queries.add("巡视整改 整改报告 整改措施");
queries.add("巡视反馈 整改方案 整改完成");
} else if (subCategory.equals(AuditContent10PartyConductConstants.SUBCATEGORY_THREE_TURNS) ||
subCategory.equals(AuditContent10PartyConductConstants.SUBCATEGORY_SYSTEM_CONSTRUCTION)) {
queries.add("纪律检查体制改革 三转工作 纪检体制改革");
queries.add("纪检制度建设 监督执纪问责");
}
return queries;
}
/**
* 构建完整的知识上下文 - 包含完整的子类示例数据
*/
private String buildCompleteKnowledgeContext(String subCategory, Map<String, List<String>> knowledgeSources, String history, String suggestion) {
StringBuilder context = new StringBuilder();
// 1. 获取当前子类的大类
String category = findCategoryBySubCategory(subCategory);
String categoryDesc = AuditContent10PartyConductConstants.CATEGORY_DESCRIPTIONS.getOrDefault(category, "");
String subCategoryDesc = AuditContent10PartyConductConstants.SUBCATEGORY_DESCRIPTIONS.getOrDefault(subCategory, "");
// 2. 党风廉政建设责任制审计要求
context.append("## 党风廉政建设责任制审计要求\n");
context.append("请基于以下知识生成").append(category).append("-").append(subCategory).append("相关的党风廉政建设责任制审计表数据:\n\n");
context.append("1. 严格按照廉政情况表的结构生成数据:大类、子类、小类、内容、执行情况、工作底稿索引\n");
context.append("2. **执行情况字段必须填写:详细情况内容说明,基于知识库证据判断,不能留空**\n");
context.append("3. 工作底稿索引必须填写实际存在的完整文件名,确保能在文件夹中搜索到\n");
context.append("4. 内容字段必须填写具体、可核查的检查点描述\n\n");
// 3. 数据结构说明
context.append("## 数据结构说明\n");
context.append("当前大类:").append(category).append(" - ").append(categoryDesc).append("\n");
context.append("当前子类:").append(subCategory).append(" - ").append(subCategoryDesc).append("\n");
// 获取当前子类的小类列表
List<String> detailCategories = AuditContent10PartyConductConstants.SUBCATEGORY_DETAIL_MAP.getOrDefault(subCategory, Collections.emptyList());
if (!detailCategories.isEmpty()) {
context.append("\n可用的子类包括\n");
for (String detailCategory : detailCategories) {
context.append("- ").append(detailCategory).append("\n");
}
}
context.append("\n可用的执行情况详细情况内容说明\n\n");
// 4. 完整的示例数据
context.append("## 示例数据(参考结构)\n");
String exampleDataJson = AuditContent10PartyConductConstants.getExampleDataJsonString(subCategory);
context.append("以下是相关审计内容的").append(subCategory).append("的完整示例数据,请参考这些内容的结构生成:\n\n");
context.append(exampleDataJson).append("\n\n");
// 5. 历史内容
if (StrUtil.isNotBlank(history)) {
context.append("## 历史生成内容\n");
context.append("以下是之前生成的内容,请基于此进行优化:\n");
context.append(history).append("\n\n");
}
// 6. 用户建议
if (StrUtil.isNotBlank(suggestion)) {
context.append("## 用户优化建议\n");
context.append("请根据以下建议对生成内容进行调整:\n");
context.append(suggestion).append("\n\n");
}
// 7. 企业单位知识
if (!knowledgeSources.get("enterprise").isEmpty()) {
context.append("## 企业单位知识\n");
knowledgeSources.get("enterprise").forEach(knowledge ->
context.append(knowledge).append("\n"));
context.append("\n");
}
// 8. 法律法规知识
if (!knowledgeSources.get("regulation").isEmpty()) {
context.append("## 法律法规知识\n");
knowledgeSources.get("regulation").forEach(knowledge ->
context.append(knowledge).append("\n"));
context.append("\n");
}
// 9. 审计案例知识
if (!knowledgeSources.get("auditCase").isEmpty()) {
context.append("## 审计案例知识\n");
knowledgeSources.get("auditCase").forEach(knowledge ->
context.append(knowledge).append("\n"));
context.append("\n");
}
return context.toString();
}
/**
* 根据子类查找对应的大类
*/
private String findCategoryBySubCategory(String subCategory) {
for (Map.Entry<String, List<String>> entry : AuditContent10PartyConductConstants.CATEGORY_SUBCATEGORY_MAP.entrySet()) {
if (entry.getValue().contains(subCategory)) {
return entry.getKey();
}
}
return AuditContent10PartyConductConstants.CATEGORY_TARGET_RESPONSIBILITY; // 默认返回第一个大类
}
/**
* 廉政情况相关性比较器
*/
private int partyConductComparator(String reg1, String reg2) {
int score1 = calculatePartyConductRelevanceScore(reg1);
int score2 = calculatePartyConductRelevanceScore(reg2);
return Integer.compare(score2, score1);
}
/**
* 计算廉政情况相关性分数
*/
private int calculatePartyConductRelevanceScore(String content) {
return AuditContent10PartyConductConstants.KEYWORD_WEIGHTS.entrySet().stream()
.filter(entry -> content.contains(entry.getKey()))
.mapToInt(Map.Entry::getValue)
.sum();
}
private int getLimitBySourceType(String sourceType) {
switch (sourceType) {
case "enterprise": return 100;
case "regulation": return 80;
case "auditCase": return 60;
default: return 50;
}
}
}

View File

@@ -0,0 +1,291 @@
package com.gxwebsoft.ai.service.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.ai.constants.AuditContent11HistoryConstants;
import com.gxwebsoft.ai.service.AuditContent11HistoryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import cn.hutool.core.util.StrUtil;
import java.util.*;
import java.util.stream.Collectors;
@Slf4j
@Service
public class AuditContent11HistoryServiceImpl extends AbstractAuditContentService implements AuditContent11HistoryService {
// 工作流配置
private static final String DIFY_WORKFLOW_TOKEN = "Bearer app-tMty75ly5NmqQXvBGZMxOKdk";
@Override
public JSONObject generateHistoryTableData(String kbIds, String libraryKbIds, String projectLibrary,
String userName, String history, String suggestion) {
log.info("开始生成历史审计问题整改表数据 - 用户: {}, kbIds: {}, libraryIds: {}, projectLibrary: {}",
userName, kbIds, libraryKbIds, projectLibrary);
long startTime = System.currentTimeMillis();
try {
// 1. 检索相关知识
Map<String, List<String>> knowledgeSources = retrieveHistoryAuditKnowledge(
kbIds, libraryKbIds, projectLibrary
);
// 2. 构建完整的知识上下文
String knowledgeContext = buildCompleteKnowledgeContext(
knowledgeSources, history, suggestion
);
// 3. 调用工作流生成数据
JSONObject requestBody = buildWorkflowRequest(knowledgeContext, userName);
JSONArray tableData = callWorkflow(DIFY_WORKFLOW_URL, DIFY_WORKFLOW_TOKEN, requestBody, "历史审计问题整改");
// 4. 处理返回数据,确保格式正确
JSONArray processedData = processTableData(tableData);
log.info("历史审计问题整改表生成成功 - 记录数: {}, 处理时间: {}ms",
processedData.size(), (System.currentTimeMillis() - startTime));
return buildSuccessResponse(processedData, startTime, "history_audit_rectification");
} catch (Exception e) {
log.error("生成历史审计问题整改表失败", e);
return buildErrorResponse("生成历史审计问题整改表失败: " + e.getMessage());
}
}
/**
* 检索历史审计问题相关知识
*/
private Map<String, List<String>> retrieveHistoryAuditKnowledge(String kbIds, String libraryKbIds, String projectLibrary) {
Map<String, List<String>> knowledgeSources = new HashMap<>();
knowledgeSources.put("enterprise", new ArrayList<>());
knowledgeSources.put("auditReports", new ArrayList<>());
knowledgeSources.put("rectificationReports", new ArrayList<>());
knowledgeSources.put("regulations", new ArrayList<>());
// 构建查询关键词
List<String> queries = buildHistoryAuditQueries();
// 企业单位库检索(历史审计问题)
if (StrUtil.isNotBlank(kbIds)) {
Arrays.stream(kbIds.split(","))
.map(String::trim)
.filter(StrUtil::isNotBlank)
.forEach(kbId -> knowledgeSources.get("enterprise")
.addAll(queryKnowledgeBase(kbId, queries, 150)));
}
// 审计报告库检索
if (StrUtil.isNotBlank(libraryKbIds)) {
Arrays.stream(libraryKbIds.split(","))
.map(String::trim)
.filter(StrUtil::isNotBlank)
.forEach(libId -> {
knowledgeSources.get("auditReports")
.addAll(queryKnowledgeBase(libId, Arrays.asList("审计报告", "审计发现问题"), 100));
knowledgeSources.get("rectificationReports")
.addAll(queryKnowledgeBase(libId, Arrays.asList("整改报告", "整改情况", "整改措施"), 80));
});
}
// 法律法规库检索(从项目库)
if (StrUtil.isNotBlank(projectLibrary)) {
knowledgeSources.get("regulations").addAll(
queryKnowledgeBase(projectLibrary,
Arrays.asList("审计制度", "整改机制", "责任追究"), 60));
}
// 智能去重和排序
knowledgeSources.forEach((key, list) -> {
List<String> processed = list.stream()
.distinct()
.sorted(this::historyAuditComparator)
.limit(getLimitBySourceType(key))
.collect(Collectors.toList());
knowledgeSources.put(key, processed);
});
log.debug("历史审计问题知识检索完成 - 企业: {}条, 审计报告: {}条, 整改报告: {}条, 法规: {}条",
knowledgeSources.get("enterprise").size(),
knowledgeSources.get("auditReports").size(),
knowledgeSources.get("rectificationReports").size(),
knowledgeSources.get("regulations").size());
return knowledgeSources;
}
/**
* 构建历史审计问题查询关键词
*/
private List<String> buildHistoryAuditQueries() {
return Arrays.asList(
"审计发现问题 整改情况",
"历史审计 遗留问题",
"审计报告 整改报告",
"问题整改 措施 效果",
"审计年度 审计类型"
);
}
/**
* 构建完整的知识上下文
*/
private String buildCompleteKnowledgeContext(Map<String, List<String>> knowledgeSources,
String history, String suggestion) {
StringBuilder context = new StringBuilder();
// 1. 审计内容11的要求
context.append("## 审计内容11历史审计问题整改\n");
context.append("**审计重点:**\n");
context.append("1. ").append(AuditContent11HistoryConstants.FOCUS_DESCRIPTIONS.get(AuditContent11HistoryConstants.FOCUS_SYSTEM_MECHANISM)).append("\n");
context.append("2. ").append(AuditContent11HistoryConstants.FOCUS_DESCRIPTIONS.get(AuditContent11HistoryConstants.FOCUS_HISTORICAL_ISSUES)).append("\n");
context.append("3. ").append(AuditContent11HistoryConstants.FOCUS_DESCRIPTIONS.get(AuditContent11HistoryConstants.FOCUS_RECTIFICATION_EFFECT)).append("\n");
context.append("4. ").append(AuditContent11HistoryConstants.FOCUS_DESCRIPTIONS.get(AuditContent11HistoryConstants.FOCUS_SYSTEM_IMPROVEMENT)).append("\n");
context.append("5. ").append(AuditContent11HistoryConstants.FOCUS_DESCRIPTIONS.get(AuditContent11HistoryConstants.FOCUS_SELF_RECTIFICATION)).append("\n\n");
context.append("**审计方法及步骤:**\n");
context.append("1. ").append(AuditContent11HistoryConstants.METHOD_DESCRIPTIONS.get(AuditContent11HistoryConstants.METHOD_REVIEW_REPORT)).append("\n");
context.append("2. ").append(AuditContent11HistoryConstants.METHOD_DESCRIPTIONS.get(AuditContent11HistoryConstants.METHOD_REVIEW_RECTIFICATION)).append("\n");
context.append("3. ").append(AuditContent11HistoryConstants.METHOD_DESCRIPTIONS.get(AuditContent11HistoryConstants.METHOD_VERIFY_RECTIFICATION)).append("\n");
context.append("4. ").append(AuditContent11HistoryConstants.METHOD_DESCRIPTIONS.get(AuditContent11HistoryConstants.METHOD_INTERVIEW)).append("\n");
context.append("5. ").append(AuditContent11HistoryConstants.METHOD_DESCRIPTIONS.get(AuditContent11HistoryConstants.METHOD_REVIEW_DOCS)).append("\n\n");
// 2. 数据格式要求
context.append("## 数据格式要求\n");
context.append("需要生成历史审计问题整改表数据,尽可能生成多个年度、多种类型的审计问题,数量不限:\n\n");
context.append("**表格字段说明:**\n");
context.append("1. **审计年度**审计报告所属年份2023年\n");
context.append("2. **审计类型**:内部审计、外部审计、专项审计、经济责任审计等\n");
context.append("3. **审计发现的问题**:具体审计发现的问题描述,需详细说明\n");
context.append("4. **整改要求**:对问题的整改要求,包括时间、内容等\n");
context.append("5. **整改措施**:具体的整改措施和实施情况\n");
context.append("6. **整改完成情况**:已完成、整改中、未整改、部分整改\n");
context.append("7. **整改完成时间**:具体完成时间或计划完成时间\n");
context.append("8. **整改责任人**:负责整改的责任人姓名和职务\n");
context.append("9. **备注**:其他需要说明的情况\n");
context.append("10. **工作底稿索引**:相关审计报告、整改报告等文件名称,必须是实际存在的完整文件名\n\n");
context.append("**生成要求:**\n");
context.append("1. 基于知识库内容,尽可能全面地生成历次审计发现的问题和整改情况\n");
context.append("2. 每个问题应包含完整的审计年度、类型、问题描述、整改要求、措施、完成情况等\n");
context.append("3. 重点关注整改措施的落实情况和实际效果\n");
context.append("4. 工作底稿索引必须准确对应实际文件名称,确保能在文件夹中搜索到\n");
context.append("5. 整改完成情况需根据实际情况判断,证据充分的才能判定为'已完成'\n");
context.append("6. 对于历史遗留问题,需特别注明是否为非任期问题\n");
context.append("7. 对于制度完善情况,需说明审计后是否建立了相关制度机制\n\n");
// 3. 历史内容
if (StrUtil.isNotBlank(history)) {
context.append("## 历史生成内容\n");
context.append("以下是之前生成的内容,请基于此进行优化:\n");
context.append(history).append("\n\n");
}
// 4. 用户建议
if (StrUtil.isNotBlank(suggestion)) {
context.append("## 用户优化建议\n");
context.append("请根据以下建议对生成内容进行调整:\n");
context.append(suggestion).append("\n\n");
}
// 5. 企业单位知识(审计问题)
if (!knowledgeSources.get("enterprise").isEmpty()) {
context.append("## 企业单位审计问题知识\n");
knowledgeSources.get("enterprise").forEach(knowledge ->
context.append(knowledge).append("\n"));
context.append("\n");
}
// 6. 审计报告知识
if (!knowledgeSources.get("auditReports").isEmpty()) {
context.append("## 审计报告知识\n");
knowledgeSources.get("auditReports").forEach(knowledge ->
context.append(knowledge).append("\n"));
context.append("\n");
}
// 7. 整改报告知识
if (!knowledgeSources.get("rectificationReports").isEmpty()) {
context.append("## 整改报告知识\n");
knowledgeSources.get("rectificationReports").forEach(knowledge ->
context.append(knowledge).append("\n"));
context.append("\n");
}
// 8. 法规制度知识
if (!knowledgeSources.get("regulations").isEmpty()) {
context.append("## 审计整改相关法规制度\n");
knowledgeSources.get("regulations").forEach(knowledge ->
context.append(knowledge).append("\n"));
}
return context.toString();
}
/**
* 处理表格数据,确保格式正确
*/
private JSONArray processTableData(JSONArray rawData) {
JSONArray processedData = new JSONArray();
for (int i = 0; i < rawData.size(); i++) {
JSONObject item = rawData.getJSONObject(i);
JSONObject processedItem = new JSONObject();
// 设置序号
processedItem.put("index", i + 1);
// 复制所有字段
processedItem.putAll(item);
// 确保必填字段存在
if (!processedItem.containsKey("auditYear")) {
processedItem.put("auditYear", "2023年");
}
if (!processedItem.containsKey("auditType")) {
processedItem.put("auditType", AuditContent11HistoryConstants.AUDIT_TYPE_INTERNAL);
}
if (!processedItem.containsKey("rectificationStatus")) {
processedItem.put("rectificationStatus", AuditContent11HistoryConstants.STATUS_IN_PROGRESS);
}
processedData.add(processedItem);
}
return processedData;
}
/**
* 历史审计问题相关性比较器
*/
private int historyAuditComparator(String reg1, String reg2) {
int score1 = calculateHistoryAuditRelevanceScore(reg1);
int score2 = calculateHistoryAuditRelevanceScore(reg2);
return Integer.compare(score2, score1);
}
/**
* 计算历史审计问题相关性分数
*/
private int calculateHistoryAuditRelevanceScore(String content) {
return AuditContent11HistoryConstants.KEYWORD_WEIGHTS.entrySet().stream()
.filter(entry -> content.contains(entry.getKey()))
.mapToInt(Map.Entry::getValue)
.sum();
}
private int getLimitBySourceType(String sourceType) {
switch (sourceType) {
case "enterprise": return 150;
case "auditReports": return 100;
case "rectificationReports": return 80;
case "regulations": return 60;
default: return 50;
}
}
}

View File

@@ -248,7 +248,8 @@ public class AuditContent1EightRegServiceImpl extends AbstractAuditContentServic
context.append("- content审计内容具体中共中央八项规定/具体中央八项规定实施细则)\n");
context.append("- testContent审计检查的证据需详细描述查阅过程、查阅的具体文件和内容\n");
context.append("- result审计测试的结果通过/不通过),严格判断,从严掌握通过标准\n");
context.append("- workPaperIndex相关《参考文件》,必须是实际存在的完整文件,不能使用附表标题,确保能在文件夹中搜索到\n");
// context.append("- workPaperIndex相关《参考文件FileId》,必须是实际存在的完整文件FileId,不能使用附表标题,确保能在文件夹中搜索到\n");
context.append("- workPaperIndex相关[\"实际存在的完整文件名||FileUrl\"],必须是实际存在的完整文件名,不能使用附表标题,确保能在文件夹中搜索到\n");
context.append("\n注意\n");
context.append("1. 请根据知识库内容尽可能全面地生成所有相关制度规定和检查点\n");
context.append("2. 工作底稿索引必须准确对应实际文件名称,避免使用附表或章节标题\n");
@@ -260,6 +261,14 @@ public class AuditContent1EightRegServiceImpl extends AbstractAuditContentServic
context.append("### 政策内容\n").append(AuditContent1EightRegConstants.POLICY_CONTENTS.get(category)).append("\n\n");
context.append("### 实施细则\n").append(AuditContent1EightRegConstants.IMPLEMENTATION_DETAILS.get(category)).append("\n\n");
// 4. 审计建议 - 新增部分
String auditSuggestion = AuditContent1EightRegConstants.AUDIT_SUGGESTIONS.get(category);
if (StrUtil.isNotBlank(auditSuggestion)) {
context.append("## 审计建议\n");
context.append("如发现被审计单位在").append(category).append("方面存在不符合中央八项规定的情况,可参考以下审计建议:\n\n");
context.append(auditSuggestion).append("\n\n");
}
// 4. 历史内容
if (StrUtil.isNotBlank(history)) {
context.append("## 历史生成内容\n");

View File

@@ -28,7 +28,7 @@ public class AuditContent1ExpenseServiceImpl extends AbstractAuditContentService
long startTime = System.currentTimeMillis();
try {
// 1. 检索相关知识
// 1. 检索相关知识(优化查询策略,避免工程类报表)
Map<String, List<String>> knowledgeSources = retrieveKnowledgeForExpense(kbIds, libraryKbIds, projectLibrary);
// 2. 构建完整的知识上下文
@@ -38,14 +38,24 @@ public class AuditContent1ExpenseServiceImpl extends AbstractAuditContentService
JSONObject requestBody = buildWorkflowRequest(knowledgeContext, userName);
JSONArray expenseData = callWorkflow(DIFY_WORKFLOW_URL, DIFY_WORKFLOW_TOKEN, requestBody, "支出情况表");
// 4. 数据验证和补充
expenseData = validateAndEnhanceExpenseData(expenseData);
log.info("支出情况表生成成功 - 记录数: {}, 处理时间: {}ms",
expenseData.size(), (System.currentTimeMillis() - startTime));
// 4. 按 expenseType 和 year 排序
if (expenseData != null && !expenseData.isEmpty()) {
expenseData.sort((o1, o2) -> {
JSONObject obj1 = (JSONObject) o1;
JSONObject obj2 = (JSONObject) o2;
// 先按 expenseType 排序
int typeCompare = obj1.getString("expenseType").compareTo(obj2.getString("expenseType"));
if (typeCompare != 0) {
return typeCompare;
}
// 再按 year 排序
return obj1.getString("year").compareTo(obj2.getString("year"));
});
}
// 5. 不进行数据验证和补充,直接返回大模型输出
log.info("支出情况表生成成功 - 记录数: {}, 处理时间: {}ms", expenseData.size(), (System.currentTimeMillis() - startTime));
return buildSuccessResponse(expenseData, startTime, "expense_audit");
} catch (Exception e) {
log.error("生成支出情况表失败", e);
return buildErrorResponse("生成支出情况表失败: " + e.getMessage());
@@ -53,190 +63,7 @@ public class AuditContent1ExpenseServiceImpl extends AbstractAuditContentService
}
/**
* 验证和增强支出情况表数据
*/
private JSONArray validateAndEnhanceExpenseData(JSONArray originalData) {
if (originalData == null || originalData.isEmpty()) {
log.warn("原始数据为空,返回空数组");
return new JSONArray();
}
JSONArray enhancedData = new JSONArray();
for (int i = 0; i < originalData.size(); i++) {
JSONObject item = originalData.getJSONObject(i);
if (item != null) {
// 确保所有必需字段都存在
enhanceExpenseData(item);
enhancedData.add(item);
}
}
// 确保数据完整性至少16条记录
if (enhancedData.size() < 16) {
enhancedData = supplementMissingExpenseData(enhancedData);
}
log.info("数据增强完成 - 原始记录数: {}, 增强后记录数: {}", originalData.size(), enhancedData.size());
return enhancedData;
}
/**
* 增强单个支出数据
*/
private void enhanceExpenseData(JSONObject expenseData) {
// 确保支出类型正确
String expenseType = expenseData.getString("expenseType");
if (StrUtil.isBlank(expenseType) || !isValidExpenseType(expenseType)) {
expenseData.put("expenseType", AuditContent1ExpenseConstants.EXPENSE_TYPE_RECEPTION);
}
// 确保年份在2020-2023范围内
String year = expenseData.getString("year");
if (StrUtil.isBlank(year) || !isValidYear(year)) {
expenseData.put("year", "2023");
}
// 确保金额格式正确
if (StrUtil.isBlank(expenseData.getString("finalStatementAmount"))) {
expenseData.put("finalStatementAmount", "0.00");
}
if (StrUtil.isBlank(expenseData.getString("initialBudgetAmount"))) {
expenseData.put("initialBudgetAmount", "0.00");
}
// 计算缺失的百分比字段
calculateMissingPercentages(expenseData);
// 确保数据来源
if (StrUtil.isBlank(expenseData.getString("dataSource"))) {
String yearStr = expenseData.getString("year");
expenseData.put("dataSource", yearStr + "年度部门决算报表");
}
// 确保工作底稿索引是数组格式
if (!expenseData.containsKey("workPaperIndex") || expenseData.get("workPaperIndex") == null) {
JSONArray workPaperIndex = new JSONArray();
workPaperIndex.add("" + expenseData.getString("year") + "年度部门决算报表》");
workPaperIndex.add("" + expenseData.getString("year") + "年预算执行情况分析》");
expenseData.put("workPaperIndex", workPaperIndex);
}
}
/**
* 补充缺失的支出数据
*/
private JSONArray supplementMissingExpenseData(JSONArray existingData) {
JSONArray supplementedData = new JSONArray();
supplementedData.addAll(existingData);
// 获取已存在的数据组合
Set<String> existingCombinations = new HashSet<>();
for (int i = 0; i < existingData.size(); i++) {
JSONObject item = existingData.getJSONObject(i);
String key = item.getString("expenseType") + "_" + item.getString("year");
existingCombinations.add(key);
}
// 补充缺失的数据
String[] expenseTypes = {
AuditContent1ExpenseConstants.EXPENSE_TYPE_RECEPTION,
AuditContent1ExpenseConstants.EXPENSE_TYPE_OVERSEAS,
AuditContent1ExpenseConstants.EXPENSE_TYPE_VEHICLE,
AuditContent1ExpenseConstants.EXPENSE_TYPE_MEETING
};
String[] years = {"2020", "2021", "2022", "2023"};
for (String expenseType : expenseTypes) {
for (String year : years) {
String key = expenseType + "_" + year;
if (!existingCombinations.contains(key)) {
JSONObject newItem = createDefaultExpenseRecord(expenseType, year);
supplementedData.add(newItem);
}
}
}
return supplementedData;
}
/**
* 创建默认的支出记录
*/
private JSONObject createDefaultExpenseRecord(String expenseType, String year) {
JSONObject record = new JSONObject();
record.put("expenseType", expenseType);
record.put("year", year);
record.put("finalStatementAmount", "0.00");
record.put("initialBudgetAmount", "0.00");
record.put("changePercentage", "0.0%");
record.put("budgetRatio", "0.0%");
record.put("remark", "根据年度财务报告数据生成");
record.put("dataSource", year + "年度部门决算报表");
JSONArray workPaperIndex = new JSONArray();
workPaperIndex.add("" + year + "年度部门决算报表》");
workPaperIndex.add("" + year + "年预算执行情况分析》");
record.put("workPaperIndex", workPaperIndex);
return record;
}
/**
* 计算缺失的百分比字段
*/
private void calculateMissingPercentages(JSONObject expenseData) {
try {
String finalAmountStr = expenseData.getString("finalStatementAmount").replace(",", "");
String budgetAmountStr = expenseData.getString("initialBudgetAmount").replace(",", "");
double finalAmount = Double.parseDouble(finalAmountStr);
double budgetAmount = Double.parseDouble(budgetAmountStr);
// 计算增减百分比
if (budgetAmount > 0) {
double changePercentage = ((finalAmount - budgetAmount) / budgetAmount) * 100;
if (!expenseData.containsKey("changePercentage") || StrUtil.isBlank(expenseData.getString("changePercentage"))) {
expenseData.put("changePercentage", String.format("%.1f%%", changePercentage));
}
// 计算预算占比
double budgetRatio = (finalAmount / budgetAmount) * 100;
if (!expenseData.containsKey("budgetRatio") || StrUtil.isBlank(expenseData.getString("budgetRatio"))) {
expenseData.put("budgetRatio", String.format("%.1f%%", budgetRatio));
}
}
} catch (Exception e) {
log.warn("计算百分比失败: {}", e.getMessage());
}
}
/**
* 检查支出类型是否有效
*/
private boolean isValidExpenseType(String expenseType) {
return expenseType.equals(AuditContent1ExpenseConstants.EXPENSE_TYPE_RECEPTION) ||
expenseType.equals(AuditContent1ExpenseConstants.EXPENSE_TYPE_OVERSEAS) ||
expenseType.equals(AuditContent1ExpenseConstants.EXPENSE_TYPE_VEHICLE) ||
expenseType.equals(AuditContent1ExpenseConstants.EXPENSE_TYPE_MEETING);
}
/**
* 检查年份是否有效
*/
private boolean isValidYear(String year) {
for (int validYear : AuditContent1ExpenseConstants.YEAR_RANGE) {
if (year.equals(String.valueOf(validYear))) {
return true;
}
}
return false;
}
/**
* 检索支出情况表相关知识 - 优化查询策略
* 检索支出情况表相关知识 - 优化查询策略,排除工程类报表
*/
private Map<String, List<String>> retrieveKnowledgeForExpense(String kbIds, String libraryKbIds, String projectLibrary) {
Map<String, List<String>> knowledgeSources = new HashMap<>();
@@ -244,8 +71,8 @@ public class AuditContent1ExpenseServiceImpl extends AbstractAuditContentService
knowledgeSources.put("regulation", new ArrayList<>());
knowledgeSources.put("auditCase", new ArrayList<>());
// 构建更全面的查询词
List<String> queries = buildEnhancedExpenseQueries();
// 构建更精确的查询词,专门针对四类支出
List<String> queries = buildPreciseExpenseQueries();
// 财务数据库检索
if (StrUtil.isNotBlank(kbIds)) {
@@ -254,6 +81,10 @@ public class AuditContent1ExpenseServiceImpl extends AbstractAuditContentService
.filter(StrUtil::isNotBlank)
.forEach(kbId -> {
List<String> financialKnowledge = queryKnowledgeBase(kbId, queries, 200);
// 过滤掉工程类报表内容
financialKnowledge = filterOutEngineeringReports(financialKnowledge);
knowledgeSources.get("financial").addAll(financialKnowledge);
log.debug("财务知识库 {} 检索到 {} 条相关知识", kbId, financialKnowledge.size());
});
@@ -265,21 +96,22 @@ public class AuditContent1ExpenseServiceImpl extends AbstractAuditContentService
.map(String::trim)
.filter(StrUtil::isNotBlank)
.forEach(libId -> {
List<String> regulationKnowledge = queryKnowledgeBase(libId, queries, 100);
List<String> regulationKnowledge = queryKnowledgeBase(libId, queries, 50);
knowledgeSources.get("regulation").addAll(regulationKnowledge);
});
}
// 审计案例库检索
if (StrUtil.isNotBlank(projectLibrary)) {
List<String> auditCaseKnowledge = queryKnowledgeBase(projectLibrary, queries, 50);
List<String> auditCaseKnowledge = queryKnowledgeBase(projectLibrary, queries, 30);
knowledgeSources.get("auditCase").addAll(auditCaseKnowledge);
}
// 智能去重排序
// 智能去重排序和过滤
knowledgeSources.forEach((key, list) -> {
List<String> processed = list.stream()
.distinct()
.filter(this::isRelevantExpenseContent) // 过滤相关性
.sorted(this::expenseComparator)
.limit(getLimitBySourceType(key))
.collect(Collectors.toList());
@@ -295,69 +127,115 @@ public class AuditContent1ExpenseServiceImpl extends AbstractAuditContentService
}
/**
* 构建增强的支出情况表查询词
* 构建精确的支出情况表查询词
*/
private List<String> buildEnhancedExpenseQueries() {
private List<String> buildPreciseExpenseQueries() {
return Arrays.asList(
"决算报表 预算报表 财务报表 年度报告",
"公务接待 接待费 招待费 餐饮费",
"出国费用 出境费用 国际差旅 境外考察",
"公车运行维护 车辆费 汽车费 交通费",
"会议费 培训费 会务费 培训费用",
"八项规定 三公经费 公务支出",
"预算执行 预算调整 超预算 预算控制",
"2020年 2021年 2022年 2023年",
"支出明细 费用明细 开支情况",
"财务分析 费用分析 支出分析"
// 直接针对四类支出的查询
"公务接待 接待费 招待费 餐饮费 公务用餐",
"出国 出境 国际差旅 境外考察 出国费用",
"公车运行维护 车辆费 汽车费 交通费 公务用车",
"会议培训费 会议费 培训费 会务费 培训支出",
// 财务文档查询(排除工程类)
"决算报表 公务接待 出国 公车 会议培训",
"预算报表 三公经费 支出明细",
"部门决算 公务支出 费用统计",
"部门预算 经费预算 支出预算",
// 通用年度查询,不指定具体年份,让知识库返回所有年份数据
"年度 公务接待 出国 公车 会议培训",
"决算 公务接待 出国 公车 会议培训",
"预算 公务接待 出国 公车 会议培训",
"三公经费 支出 决算 预算"
);
}
/**
* 构建完整的知识上下文 - 优化提示
* 过滤掉工程类报表内容
*/
private List<String> filterOutEngineeringReports(List<String> knowledgeList) {
return knowledgeList.stream()
.filter(content -> {
// 检查是否包含工程类关键词
for (String excludeKeyword : AuditContent1ExpenseConstants.ENGINEERING_EXCLUDE_KEYWORDS) {
if (content.contains(excludeKeyword)) {
log.debug("过滤工程类内容: {}", content.substring(0, Math.min(50, content.length())));
return false;
}
}
return true;
})
.collect(Collectors.toList());
}
/**
* 检查内容是否与支出相关
*/
private boolean isRelevantExpenseContent(String content) {
String lowerContent = content.toLowerCase();
// 必须包含至少一个支出类型关键词
boolean hasExpenseType = lowerContent.contains("公务接待") ||
lowerContent.contains("接待费") ||
lowerContent.contains("出国") ||
lowerContent.contains("出境") ||
lowerContent.contains("公车") ||
lowerContent.contains("车辆费") ||
lowerContent.contains("会议") ||
lowerContent.contains("培训") ||
lowerContent.contains("三公经费");
// 排除工程类内容
boolean isEngineering = false;
for (String excludeKeyword : AuditContent1ExpenseConstants.ENGINEERING_EXCLUDE_KEYWORDS) {
if (content.contains(excludeKeyword)) {
isEngineering = true;
break;
}
}
return hasExpenseType && !isEngineering;
}
/**
* 构建完整的知识上下文 - 简化版本,只传递知识内容
*/
private String buildCompleteKnowledgeContext(Map<String, List<String>> knowledgeSources, String history, String suggestion) {
StringBuilder context = new StringBuilder();
// 1. 支出情况表分析要求 - 增强要求
context.append("## 支出情况表分析要求\n");
context.append("请基于以下知识生成完整详细的公务接待/出国/公车运行维护/会议培训费等支出情况表数据\n\n");
context.append("1. 必须生成完整的支出情况表数据覆盖2020-2023四个年度\n");
context.append("2. 重点关注四类支出:公务接待、出国(出境)、公车运行维护、会议培训费\n");
context.append("3. 从财务知识库中提取所有实际的支出数据,要求全面完整\n");
context.append("4. 确保信息的准确性和完整性,包括决算数、预算数、增减情况和占比情况\n");
context.append("5. 工作底稿索引必须准确对应实际文件名称,可以包含多个相关文件\n");
context.append("6. 要求生成尽可能多、尽可能完整的支出记录,覆盖所有年份和支出类型\n\n");
// 1. 审计关注要点(简化版)
context.append("## 审计关注要点\n");
context.append("请基于以下知识生成完整的公务接待/出国/公车运行维护/会议培训费等支出情况表数据\n");
context.append("重点关注以下审计要点:\n");
context.append("1. 检查公务接待、出国、公车、会议培训四类支出的预算执行情况\n");
context.append("2. 对比年初预算数和决算报表数,分析增减情况\n");
context.append("3. 关注是否存在未经预算批准变相公款消费的情况\n");
context.append("4. 检查报销手续是否完善,是否存在超支使用\n\n");
// 2. 数据格式要求
context.append("## 数据格式要求\n");
context.append("需要生成完整详细的支出情况表数据:\n\n");
context.append(AuditContent1ExpenseConstants.DATA_FORMAT_REQUIREMENT);
context.append("\n\n重要要求\n");
context.append("1. 必须根据知识库内容生成尽可能多、尽可能完整的支出信息\n");
context.append("2. 工作底稿索引必须准确对应实际文件名称,避免使用附表或章节标题\n");
context.append("3. 金额单位为元,保持两位小数,可以使用逗号分隔千位\n");
context.append("4. 百分比计算要准确,增减情况正数表示增长,负数表示减少\n");
context.append("5. 数据来源要具体2023年度部门决算报表\n");
context.append("6. 备注信息可以包含超支原因、特殊情况说明等\n\n");
// 2. 特别提醒
context.append("## 特别提醒\n");
context.append("1. 必须准确识别支出类型:只提取\"公务接待\"\"出国\"\"公车运行维护\"\"会议培训费\"四类支出\n");
context.append("2. 不要将《工程造价和概(预)算执行情况表》等工程类报表误识别为\"三公经费\"报表\n");
// context.append("3. 工作底稿索引必须使用实际存在的完整文件名称作为FileId\n\n");
context.append("3. 工作底稿索引必须使用实际存在的完整文件名||FileUrl\n\n");
// 3. 历史内容
if (StrUtil.isNotBlank(history)) {
context.append("## 历史生成内容\n");
context.append("以下是之前生成的内容,请基于此进行优化和补充:\n");
context.append("## 历史生成内容参考\n");
context.append(history).append("\n\n");
}
// 4. 用户建议
if (StrUtil.isNotBlank(suggestion)) {
context.append("## 用户优化建议\n");
context.append("请根据以下建议对生成内容进行调整:\n");
context.append(suggestion).append("\n\n");
}
// 5. 财务知识
// 5. 财务知识(核心内容)
if (!knowledgeSources.get("financial").isEmpty()) {
context.append("## 财务知识\n");
context.append("是财务相关的报表和文件信息,请仔细分析并提取所有支出数据:\n");
context.append("## 财务知识库内容\n");
context.append("以下是财务相关的报表和文件信息,请仔细分析并提取所有支出数据:\n\n");
knowledgeSources.get("financial").forEach(knowledge ->
context.append(knowledge).append("\n"));
context.append("\n");
@@ -365,7 +243,7 @@ public class AuditContent1ExpenseServiceImpl extends AbstractAuditContentService
// 6. 法律法规知识
if (!knowledgeSources.get("regulation").isEmpty()) {
context.append("## 法律法规知识\n");
context.append("## 法律法规参考\n");
knowledgeSources.get("regulation").forEach(knowledge ->
context.append(knowledge).append("\n"));
context.append("\n");
@@ -373,7 +251,7 @@ public class AuditContent1ExpenseServiceImpl extends AbstractAuditContentService
// 7. 审计案例知识
if (!knowledgeSources.get("auditCase").isEmpty()) {
context.append("## 审计案例知识\n");
context.append("## 审计案例参考\n");
knowledgeSources.get("auditCase").forEach(knowledge ->
context.append(knowledge).append("\n"));
}
@@ -403,10 +281,10 @@ public class AuditContent1ExpenseServiceImpl extends AbstractAuditContentService
private int getLimitBySourceType(String sourceType) {
switch (sourceType) {
case "financial": return 150;
case "regulation": return 80;
case "auditCase": return 40;
default: return 100;
case "financial": return 100; // 减少数量,提高质量
case "regulation": return 50;
case "auditCase": return 30;
default: return 50;
}
}
}

View File

@@ -39,7 +39,7 @@ public class AuditContent1LeaderListServiceImpl extends AbstractAuditContentServ
JSONArray leaderListData = callWorkflow(DIFY_WORKFLOW_URL, DIFY_WORKFLOW_TOKEN, requestBody, "领导班子名单");
// 4. 数据验证和补充
leaderListData = validateAndEnhanceLeaderListData(leaderListData);
// leaderListData = validateAndEnhanceLeaderListData(leaderListData);
log.info("领导班子名单生成成功 - 记录数: {}, 处理时间: {}ms",
leaderListData.size(), (System.currentTimeMillis() - startTime));
@@ -117,13 +117,6 @@ public class AuditContent1LeaderListServiceImpl extends AbstractAuditContentServ
}
}
}
// 确保工作底稿索引是数组格式
if (!leaderData.containsKey("workPaperIndex") || leaderData.get("workPaperIndex") == null) {
JSONArray workPaperIndex = new JSONArray();
workPaperIndex.add("《千汇发20256号千汇公司关于领导班子成员工作分工的通知》");
leaderData.put("workPaperIndex", workPaperIndex);
}
}
/**

View File

@@ -0,0 +1,239 @@
package com.gxwebsoft.ai.service.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.ai.constants.AuditContent2StrategyConstants;
import com.gxwebsoft.ai.service.AuditContent2StrategyService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import cn.hutool.core.util.StrUtil;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
@Slf4j
@Service
public class AuditContent2StrategyServiceImpl extends AbstractAuditContentService implements AuditContent2StrategyService {
// 工作流配置
private static final String DIFY_WORKFLOW_TOKEN = "Bearer app-3cPaXHIPFPS6lIfMGV67NOu0";
@Override
public JSONObject generateStrategyAuditTableData(String kbIds, String libraryKbIds, String projectLibrary,
String userName, String history, String suggestion) {
log.info("开始生成单位发展战略执行审计表数据 - 用户: {}, kbIds: {}, libraryIds: {}, projectLibrary: {}",
userName, kbIds, libraryKbIds, projectLibrary);
long startTime = System.currentTimeMillis();
try {
// 异步并行处理每个分类
Map<String, CompletableFuture<JSONArray>> futures = processCategoriesAsync(
AuditContent2StrategyConstants.CATEGORY_ORDER,
category -> generateCategoryDataAsync(category, kbIds, libraryKbIds, projectLibrary, userName, history, suggestion)
);
// 等待所有异步任务完成
CompletableFuture.allOf(futures.values().toArray(new CompletableFuture[0])).join();
// 合并所有分类的结果
JSONArray allData = mergeCategoryResults(AuditContent2StrategyConstants.CATEGORY_ORDER, futures);
log.info("单位发展战略执行审计表生成成功 - 记录数: {}, 处理时间: {}ms", allData.size(), (System.currentTimeMillis() - startTime));
return buildSuccessResponse(allData, startTime, "strategy_audit");
} catch (Exception e) {
log.error("生成单位发展战略执行审计表失败", e);
return buildErrorResponse("生成单位发展战略执行审计表失败: " + e.getMessage());
}
}
/**
* 异步生成单个分类的数据
*/
@Async
public CompletableFuture<JSONArray> generateCategoryDataAsync(String category, String kbIds, String libraryKbIds,
String projectLibrary, String userName, String history, String suggestion) {
return CompletableFuture.supplyAsync(() -> {
try {
log.info("开始生成分类 {} 的数据", category);
// 1. 为当前分类召回相关知识
Map<String, List<String>> knowledgeSources = retrieveKnowledgeForCategory(
category, kbIds, libraryKbIds, projectLibrary
);
// 2. 构建完整的知识上下文
String knowledgeContext = buildCompleteKnowledgeContext(
category, knowledgeSources, history, suggestion
);
// 3. 调用工作流生成数据
JSONObject requestBody = buildWorkflowRequest(knowledgeContext, userName);
JSONArray categoryData = callWorkflow(DIFY_WORKFLOW_URL, DIFY_WORKFLOW_TOKEN, requestBody, "发展战略-" + category);
log.info("分类 {} 数据生成完成,生成 {} 条记录", category, categoryData.size());
return categoryData;
} catch (Exception e) {
log.error("生成分类 {} 数据失败", category, e);
return new JSONArray();
}
});
}
/**
* 为单个分类检索相关知识
*/
private Map<String, List<String>> retrieveKnowledgeForCategory(String category, String kbIds, String libraryKbIds, String projectLibrary) {
Map<String, List<String>> knowledgeSources = new HashMap<>();
knowledgeSources.put("enterprise", new ArrayList<>());
knowledgeSources.put("regulation", new ArrayList<>());
knowledgeSources.put("auditCase", new ArrayList<>());
// 从常量类获取当前分类的查询词
List<String> categoryQueries = AuditContent2StrategyConstants.CATEGORY_QUERIES.getOrDefault(
category, Arrays.asList(category + " 审计 检查")
);
// 企业单位库检索 - 这是主要考察内容
if (StrUtil.isNotBlank(kbIds)) {
Arrays.stream(kbIds.split(","))
.map(String::trim)
.filter(StrUtil::isNotBlank)
.forEach(kbId -> knowledgeSources.get("enterprise")
.addAll(queryKnowledgeBase(kbId, categoryQueries, 150)));
}
// 公共法律法规库检索
if (StrUtil.isNotBlank(libraryKbIds)) {
Arrays.stream(libraryKbIds.split(","))
.map(String::trim)
.filter(StrUtil::isNotBlank)
.forEach(libId -> knowledgeSources.get("regulation")
.addAll(queryKnowledgeBase(libId, categoryQueries, 80)));
}
// 审计案例库检索
if (StrUtil.isNotBlank(projectLibrary)) {
knowledgeSources.get("auditCase").addAll(
queryKnowledgeBase(projectLibrary, categoryQueries, 60));
}
// 智能去重和排序
knowledgeSources.forEach((key, list) -> {
List<String> processed = list.stream()
.distinct()
.limit(AuditContent2StrategyConstants.SOURCE_LIMITS.getOrDefault(key, 50))
.collect(Collectors.toList());
knowledgeSources.put(key, processed);
});
log.debug("分类 {} 知识检索完成 - 企业: {}条, 法规: {}条, 案例: {}条",
category,
knowledgeSources.get("enterprise").size(),
knowledgeSources.get("regulation").size(),
knowledgeSources.get("auditCase").size());
return knowledgeSources;
}
/**
* 构建完整的知识上下文
*/
private String buildCompleteKnowledgeContext(String category, Map<String, List<String>> knowledgeSources,
String history, String suggestion) {
StringBuilder context = new StringBuilder();
// 1. 核心审计任务
context.append("## 核心审计任务\n");
context.append(AuditContent2StrategyConstants.AUDIT_OBJECTIVE).append("\n\n");
context.append("本次重点审计分类:").append(category).append("\n");
context.append("对应发展理念:").append(AuditContent2StrategyConstants.CATEGORY_DEVELOPMENT_CONCEPT.get(category)).append("\n");
context.append("分类描述:").append(AuditContent2StrategyConstants.CATEGORY_DESCRIPTIONS.get(category)).append("\n");
context.append("审计重点:").append(AuditContent2StrategyConstants.getBriefAuditFrameworkForCategory(category)).append("\n\n");
// 2. 执行结果分析要求
context.append("## 执行结果分析要求(必须遵循)\n");
context.append("**必须深入分析实际执行结果,重点关注贯彻落实的证据:**\n");
context.append("**检查要求(满足以下任一条件即可):**\n");
context.append("1. **会议纪要路径**:检查是否有会议纪要证明按照\"党组织委员会→公司领导班子→董事会\"逐级开会落实;\n");
context.append(" *或者*\n");
context.append("2. **其他落实证据**:检查是否有其他材料(签批文件、任务分解、执行报告等)证明相关审计内容已从上往下逐级贯彻落实。\n");
context.append("\n");
context.append("**在检查证据中必须明确指出:**\n");
context.append("①是否存在有效的贯彻落实证据(会议纪要或其他材料);\n");
context.append("②执行过程是否有充分材料支撑;\n");
context.append("③执行结果是否达到预期。\n\n");
// 3. 审计框架
context.append("## 审计框架(审计规则)\n");
String categoryFramework = AuditContent2StrategyConstants.CATEGORY_AUDIT_FRAMEWORK_FRAGMENTS.get(category);
if (categoryFramework != null) {
context.append(categoryFramework).append("\n");
} else {
context.append(AuditContent2StrategyConstants.AUDIT_FRAMEWORK).append("\n");
}
// 4. 企业单位知识(主要考察内容)
if (!knowledgeSources.get("enterprise").isEmpty()) {
context.append("## 企业单位知识(具体考察内容)\n");
context.append("基于审计框架,结合以下企业实际资料生成审计记录:\n\n");
knowledgeSources.get("enterprise").forEach(knowledge ->
context.append("").append(knowledge).append("\n"));
context.append("\n");
} else {
context.append("## 企业单位知识\n");
context.append("未检索到相关企业资料,请基于审计框架生成审计内容。\n\n");
}
// 5. 审计工作原则
context.append("## 审计工作原则\n");
context.append(AuditContent2StrategyConstants.AUDIT_PRINCIPLES).append("\n\n");
// 6. 数据格式要求
context.append("## 数据格式要求\n");
context.append("生成JSON数组每个元素包含4个字段\n");
context.append("1. auditContent: 具体审计内容(基于框架,结合企业实际)\n");
context.append("2. checkEvidence: 检查证据(引用企业具体文件,必须包含执行结果分析)\n");
context.append("3. testResult: 测试结果(通过/不通过)(基于充分证据严格判断)\n");
// context.append("4. workPaperIndex: 工作底稿索引具体文件FileId\n\n");
context.append("4. workPaperIndex: 工作底稿索引(具体文件完整文件名||FileUrl\n\n");
// 7. 法规和案例参考(如果有)
if (!knowledgeSources.get("regulation").isEmpty()) {
context.append("## 法律法规参考\n");
knowledgeSources.get("regulation").forEach(knowledge ->
context.append("").append(knowledge).append("\n"));
context.append("\n");
}
if (!knowledgeSources.get("auditCase").isEmpty()) {
context.append("## 审计案例参考\n");
knowledgeSources.get("auditCase").forEach(knowledge ->
context.append("").append(knowledge).append("\n"));
context.append("\n");
}
// 8. 历史内容(如果有)
if (StrUtil.isNotBlank(history)) {
context.append("## 历史生成内容\n");
context.append(history).append("\n\n");
}
// 9. 用户建议(如果有)
if (StrUtil.isNotBlank(suggestion)) {
context.append("## 用户建议\n");
context.append(suggestion).append("\n");
}
// 记录上下文长度用于监控
log.debug("分类 {} 构建的知识上下文长度: {} 字符", category, context.length());
return context.toString();
}
}

View File

@@ -194,14 +194,19 @@ public class AuditContent3TripleServiceImpl extends AbstractAuditContentService
context.append("- companyFormulation公司层面的三重一大相关制度规定及执行情况需包含详细分析过程和查阅依据\n");
context.append("- checkEvidence审计检查的证据需详细描述查阅过程、查阅的具体文件和内容\n");
context.append("- testResult审计测试的结果通过/不通过),严格判断,从严掌握通过标准\n");
context.append("- workPaperIndex相关《参考文件名》必须是实际存在的完整文件,不能使用附表标题,确保能在文件夹中搜索到\n");
// context.append("- workPaperIndex相关《参考文件名FileId》,必须是实际存在的完整文件FileId,不能使用附表标题,确保能在文件夹中搜索到\n");
context.append("- workPaperIndex相关[\"实际存在的完整文件名||FileUrl\"],必须是实际存在的完整文件名,不能使用附表标题,确保能在文件夹中搜索到\n");
context.append("\n注意\n");
context.append("1. 请根据知识库内容尽可能全面地生成所有相关制度规定和检查点\n");
context.append("2. 公司执行情况分析需包含:查阅了哪些文件、发现了什么内容、与制度的差异点、分析判断过程\n");
context.append("3. 工作底稿索引必须准确对应实际文件名称,避免使用附表或章节标题\n");
context.append("4. 测试结果判定需严格,对于制度不一致、执行不到位、证据不充分的情况必须判定为不通过\n");
context.append("5. 审计检查的证据主要按公司制度为主,政策内容和集团制度为次要\n");
context.append("6. 审计检查的证据增加判断公司制度是否与政策内容和集团制度相符\n\n");
context.append("6. 审计检查的证据增加判断公司制度是否与政策内容和集团制度相符\n");
context.append("7. 历史问题整改分析:需核查历史问题是否已整改,结合最新时间材料(如最新会议纪要)分析当前是否存在相同问题\n");
context.append("8. 项目上会核查:涉及三重一大的项目必须核查是否按规定上会,检查有无会议纪要作为证据\n");
context.append("9. 制度权限关系:明确分析公司制度与集团制度的关联关系,权限设置必须遵循公司权限≤集团权限的原则\n");
context.append("10. 层级关系识别:注意识别文件中的上级单位信息,分析制度执行是否符合层级管理要求\n\n");
// 3. 参考数据(从常量类中获取)
context.append("## 参考数据\n");

View File

@@ -0,0 +1,333 @@
// AuditContent4TargetServiceImpl.java
package com.gxwebsoft.ai.service.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.ai.constants.AuditContent4TargetConstants;
import com.gxwebsoft.ai.service.AuditContent4TargetService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import cn.hutool.core.util.StrUtil;
import java.util.*;
import java.util.stream.Collectors;
@Slf4j
@Service
public class AuditContent4TargetServiceImpl extends AbstractAuditContentService implements AuditContent4TargetService {
// 工作流配置
private static final String DIFY_WORKFLOW_TOKEN = "Bearer app-Z6YPjz3nAB46roFnZSfCTk3w";
@Override
public JSONObject generateTargetAuditTableData(String kbIds, String libraryKbIds, String projectLibrary,
String userName, String history, String suggestion) {
log.info("开始生成目标责任制完成情况审计表数据 - 用户: {}, kbIds: {}, libraryIds: {}, projectLibrary: {}",
userName, kbIds, libraryKbIds, projectLibrary);
long startTime = System.currentTimeMillis();
try {
// 1. 检索相关知识
Map<String, List<String>> knowledgeSources = retrieveKnowledgeForTargetResponsibility(
kbIds, libraryKbIds, projectLibrary
);
// 2. 构建完整的知识上下文
String knowledgeContext = buildCompleteKnowledgeContext(
knowledgeSources, history, suggestion
);
// 3. 调用工作流生成数据
JSONObject requestBody = buildWorkflowRequest(knowledgeContext, userName);
JSONArray auditData = callWorkflow(DIFY_WORKFLOW_URL, DIFY_WORKFLOW_TOKEN, requestBody, "目标责任制审计");
// 4. 后处理:确保数据格式正确
auditData = processAuditData(auditData);
log.info("目标责任制完成情况审计表生成成功 - 记录数: {}, 处理时间: {}ms",
auditData.size(), (System.currentTimeMillis() - startTime));
return buildSuccessResponse(auditData, startTime, "target_audit");
} catch (Exception e) {
log.error("生成目标责任制完成情况审计表失败", e);
return buildErrorResponse("生成目标责任制完成情况审计表失败: " + e.getMessage());
}
}
/**
* 检索目标责任制相关知识
*/
private Map<String, List<String>> retrieveKnowledgeForTargetResponsibility(String kbIds, String libraryKbIds, String projectLibrary) {
Map<String, List<String>> knowledgeSources = new HashMap<>();
knowledgeSources.put("enterprise", new ArrayList<>());
knowledgeSources.put("regulation", new ArrayList<>());
knowledgeSources.put("auditCase", new ArrayList<>());
// 构建查询词
List<String> queries = buildTargetResponsibilityQueries();
// 企业单位库检索
if (StrUtil.isNotBlank(kbIds)) {
Arrays.stream(kbIds.split(","))
.map(String::trim)
.filter(StrUtil::isNotBlank)
.forEach(kbId -> knowledgeSources.get("enterprise")
.addAll(queryKnowledgeBase(kbId, queries, 100)));
}
// 公共法律法规库检索
if (StrUtil.isNotBlank(libraryKbIds)) {
Arrays.stream(libraryKbIds.split(","))
.map(String::trim)
.filter(StrUtil::isNotBlank)
.forEach(libId -> knowledgeSources.get("regulation")
.addAll(queryKnowledgeBase(libId, queries, 80)));
}
// 审计案例库检索
if (StrUtil.isNotBlank(projectLibrary)) {
knowledgeSources.get("auditCase").addAll(
queryKnowledgeBase(projectLibrary, queries, 60));
}
// 智能去重和排序
knowledgeSources.forEach((key, list) -> {
List<String> processed = list.stream()
.distinct()
.sorted(this::targetResponsibilityComparator)
.limit(getLimitBySourceType(key))
.collect(Collectors.toList());
knowledgeSources.put(key, processed);
});
log.debug("目标责任制知识检索完成 - 企业: {}条, 法规: {}条, 案例: {}条",
knowledgeSources.get("enterprise").size(),
knowledgeSources.get("regulation").size(),
knowledgeSources.get("auditCase").size());
return knowledgeSources;
}
/**
* 构建目标责任制查询词
*/
private List<String> buildTargetResponsibilityQueries() {
return Arrays.asList(
"目标责任 目标责任制 目标任务",
"下达文件 计划文件 考核办法",
"完成情况 未完成原因 考核结果",
"上级主管 主管部门",
"年度计划 工作目标 考核指标",
"责任书 责任状 目标考核",
"经营目标 工作计划 绩效考核",
"重点工作 专项任务 年度总结"
);
}
/**
* 构建完整的知识上下文
*/
private String buildCompleteKnowledgeContext(Map<String, List<String>> knowledgeSources,
String history, String suggestion) {
StringBuilder context = new StringBuilder();
// 1. 核心审计任务
context.append("## 核心审计任务\n");
context.append("审计分类:").append(AuditContent4TargetConstants.CATEGORY_TARGET_RESPONSIBILITY).append("\n");
context.append("审计描述:检查被审计领导干部任职期间,对照上级主管部门下达的目标责任或单位自定的目标责任,检查其完成情况\n\n");
// 2. 审计框架(审计规则)
context.append("## 审计框架(审计规则)\n");
context.append("以下审计框架定义了审计范围和要点,请基于此框架开展工作:\n");
context.append(AuditContent4TargetConstants.AUDIT_FRAMEWORK).append("\n\n");
// 3. 审计目标
context.append("## 审计目标\n");
context.append(AuditContent4TargetConstants.AUDIT_OBJECTIVE).append("\n\n");
// 4. 审计工作原则
context.append("## 审计工作原则\n");
context.append(AuditContent4TargetConstants.AUDIT_PRINCIPLES).append("\n\n");
// 5. 企业单位知识(主要考察内容)
if (!knowledgeSources.get("enterprise").isEmpty()) {
context.append("## 企业单位知识(具体考察内容)\n");
context.append("以下是企业单位的实际资料,请基于审计框架,结合这些具体内容生成审计记录:\n\n");
knowledgeSources.get("enterprise").forEach(knowledge ->
context.append("").append(knowledge).append("\n"));
context.append("\n");
}
// 6. 审计要点提示
context.append("## 审计要点提示\n");
context.append(AuditContent4TargetConstants.AUDIT_KEY_POINTS).append("\n\n");
// 7. 数据格式要求
context.append("## 数据格式要求\n");
context.append("请生成JSON数组格式的审计表数据每个审计条目包含以下字段\n");
context.append(AuditContent4TargetConstants.OUTPUT_FORMAT).append("\n\n");
// 8. 审计证据要求
context.append("## 审计证据要求\n");
context.append(AuditContent4TargetConstants.AUDIT_EVIDENCE_REQUIREMENTS).append("\n\n");
// 9. 特别提醒(新增关键优化点)
context.append("## 特别提醒\n");
context.append("1. 审计证据必须包含具体的查阅过程:查阅了哪些文件、文件中发现了什么内容\n");
// context.append("2. workPaperIndex必须填写实际存在的完整文件FileId确保能在文件夹中搜索到\n");
context.append("2. workPaperIndex必须填写实际存在的完整文件名||FileUrl确保能在文件夹中搜索到\n");
context.append("3. 完成情况判定必须基于充分证据:只有证据充分且完全符合要求才能判定为已完成\n");
context.append("4. 对于执行不到位、效果不佳、证据不充分的情况必须在备注中说明\n");
context.append("5. 尽可能识别知识库中所有相关年度,生成对应的审计记录\n");
context.append("6. 如果知识库中没有单位自定目标文件,请根据企业职责和上级目标合理推断单位自定计划内容\n");
context.append("7. 不能填写简单的\"\",要提供有意义的描述\n");
context.append("8. 对于正在进行的年度,完成情况应填写\"年度未结束无法评估\"\n");
context.append("9. 如果知识库中有多个目标责任文件,每个文件都应生成独立的审计记录\n");
context.append("10. 同一年度可能有不同类型的多个目标责任,应尽可能多地生成审计记录\n");
context.append("11. 不能填写简单的\"\",要提供有意义的描述\n");
context.append("12. 对于正在进行的年度,完成情况应填写\"无法评估\"\n\n");
// 10. 法规和案例参考
if (!knowledgeSources.get("regulation").isEmpty()) {
context.append("## 法律法规参考\n");
knowledgeSources.get("regulation").forEach(knowledge ->
context.append("").append(knowledge).append("\n"));
context.append("\n");
}
if (!knowledgeSources.get("auditCase").isEmpty()) {
context.append("## 审计案例参考\n");
knowledgeSources.get("auditCase").forEach(knowledge ->
context.append("").append(knowledge).append("\n"));
context.append("\n");
}
// 11. 历史内容(如果有)
if (StrUtil.isNotBlank(history)) {
context.append("## 历史生成内容\n");
context.append(history).append("\n\n");
}
// 12. 用户建议(如果有)
if (StrUtil.isNotBlank(suggestion)) {
context.append("## 用户建议\n");
context.append(suggestion).append("\n\n");
}
log.debug("目标责任制审计知识上下文长度: {} 字符", context.length());
return context.toString();
}
/**
* 目标责任制审计相关性比较器
*/
private int targetResponsibilityComparator(String reg1, String reg2) {
int score1 = calculateTargetResponsibilityRelevanceScore(reg1);
int score2 = calculateTargetResponsibilityRelevanceScore(reg2);
return Integer.compare(score2, score1); // 降序排序
}
/**
* 计算目标责任制审计相关性分数
*/
private int calculateTargetResponsibilityRelevanceScore(String content) {
return AuditContent4TargetConstants.KEYWORD_WEIGHTS.entrySet().stream()
.filter(entry -> content.contains(entry.getKey()))
.mapToInt(Map.Entry::getValue)
.sum();
}
private int getLimitBySourceType(String sourceType) {
switch (sourceType) {
case "enterprise": return 200; // 企业知识数量
case "regulation": return 80; // 法规数量
case "auditCase": return 60; // 案例数量
default: return 50;
}
}
/**
* 后处理审计数据(优化字段处理逻辑)
*/
private JSONArray processAuditData(JSONArray auditData) {
if (auditData == null || auditData.isEmpty()) {
return auditData;
}
JSONArray processedData = new JSONArray();
for (int i = 0; i < auditData.size(); i++) {
JSONObject item = auditData.getJSONObject(i);
// 确保序号存在
if (!item.containsKey("index") || item.getInteger("index") == null) {
item.put("index", i + 1);
}
// 确保年度存在
if (!item.containsKey("year") || StrUtil.isBlank(item.getString("year"))) {
item.put("year", "未知年度");
}
// 优化单位自定计划字段:不能是简单的"无"
String selfPlan = item.getString("selfPlan");
if (StrUtil.isBlank(selfPlan) || "".equals(selfPlan)) {
String year = item.getString("year");
item.put("selfPlan", year + "年度经营工作计划");
}
// 优化自定完成情况:不能是简单的"无"
String selfCompletion = item.getString("selfCompletion");
if (StrUtil.isBlank(selfCompletion) || "".equals(selfCompletion)) {
String superiorCompletion = item.getString("superiorCompletion");
if ("已完成".equals(superiorCompletion)) {
item.put("selfCompletion", "已完成");
} else if ("部分完成".equals(superiorCompletion)) {
item.put("selfCompletion", "部分完成");
} else if ("未完成".equals(superiorCompletion)) {
item.put("selfCompletion", "未完成");
} else if (superiorCompletion != null &&
(superiorCompletion.contains("尚未完成") || superiorCompletion.contains("年度未结束"))) {
item.put("selfCompletion", "年度未结束无法评估");
} else {
item.put("selfCompletion", "未提供完成情况数据");
}
}
// 优化自定未完成原因:不能是简单的"无"
String selfReason = item.getString("selfReason");
if (StrUtil.isBlank(selfReason) || "".equals(selfReason)) {
String selfComp = item.getString("selfCompletion");
if ("已完成".equals(selfComp)) {
item.put("selfReason", "无未完成原因");
} else if ("部分完成".equals(selfComp)) {
item.put("selfReason", "部分指标未达预期");
} else if ("未完成".equals(selfComp)) {
item.put("selfReason", "经营目标未实现");
} else if ("年度未结束无法评估".equals(selfComp)) {
item.put("selfReason", "年度尚未结束,无法评估");
} else {
item.put("selfReason", "未提供原因分析");
}
}
// 确保工作底稿索引是数组格式
// if (!item.containsKey("workPaperIndex") || !(item.get("workPaperIndex") instanceof JSONArray)) {
// JSONArray workPaperIndex = new JSONArray();
// String year = item.getString("year");
// workPaperIndex.add(year + "年度目标责任书");
// workPaperIndex.add(year + "年度工作总结报告");
// item.put("workPaperIndex", workPaperIndex);
// }
processedData.add(item);
}
return processedData;
}
}

View File

@@ -0,0 +1,314 @@
package com.gxwebsoft.ai.service.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.ai.constants.AuditContent5BudgetExecutionConstants;
import com.gxwebsoft.ai.service.AuditContent5BudgetExecutionService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import java.util.*;
import java.util.stream.Collectors;
@Slf4j
@Service
public class AuditContent5BudgetExecutionServiceImpl extends AbstractAuditContentService implements AuditContent5BudgetExecutionService {
// 工作流配置
private static final String DIFY_WORKFLOW_TOKEN = "Bearer app-40NwSJCFSFKkOwRdGe8nqVsA";
@Override
public JSONObject generateBudgetExecutionTableData(String kbIds, String libraryKbIds, String projectLibrary,
String userName, String history, String suggestion, Object data) {
log.info("开始生成预算执行情况审计表数据 - 用户: {}, kbIds: {}, libraryIds: {}, projectLibrary: {}",
userName, kbIds, libraryKbIds, projectLibrary);
long startTime = System.currentTimeMillis();
try {
if (ObjectUtil.isEmpty(data)) {
JSONObject result = new JSONObject();
log.warn("未传入预算管理审计数据,无法生成预算执行情况审计表");
result.put("success", false);
result.put("error", "需要预算管理审计数据作为生成依据");
return result;
}
// 1. 检索相关知识
Map<String, List<String>> knowledgeSources = retrieveKnowledgeForBudgetExecution(
kbIds, libraryKbIds, projectLibrary
);
// 2. 构建完整的知识上下文(包含预算管理数据)
String knowledgeContext = buildCompleteKnowledgeContext(knowledgeSources, history, suggestion, data.toString());
// 3. 调用工作流生成数据
JSONObject requestBody = buildWorkflowRequest(knowledgeContext, userName);
JSONArray auditData = callWorkflow(DIFY_WORKFLOW_URL, DIFY_WORKFLOW_TOKEN, requestBody, "预算执行情况审计");
log.info("预算执行情况审计表生成成功 - 记录数: {}, 处理时间: {}ms",
auditData.size(), (System.currentTimeMillis() - startTime));
return buildSuccessResponse(auditData, startTime, "budget_execution_audit");
} catch (Exception e) {
log.error("生成预算执行情况审计表失败", e);
return buildErrorResponse("生成预算执行情况审计表失败: " + e.getMessage());
}
}
/**
* 检索预算执行情况相关知识
*/
private Map<String, List<String>> retrieveKnowledgeForBudgetExecution(String kbIds, String libraryKbIds, String projectLibrary) {
Map<String, List<String>> knowledgeSources = new HashMap<>();
knowledgeSources.put("enterprise", new ArrayList<>());
knowledgeSources.put("regulation", new ArrayList<>());
knowledgeSources.put("auditCase", new ArrayList<>());
knowledgeSources.put("financial", new ArrayList<>());
// 构建查询词 - 具体化,提高识别率
List<String> queries = buildBudgetExecutionQueries();
// 企业单位库检索 - 增加查询深度
if (StrUtil.isNotBlank(kbIds)) {
Arrays.stream(kbIds.split(","))
.map(String::trim)
.filter(StrUtil::isNotBlank)
.forEach(kbId -> knowledgeSources.get("enterprise")
.addAll(queryKnowledgeBase(kbId, queries, 100)));
}
// 公共法律法规库检索
if (StrUtil.isNotBlank(libraryKbIds)) {
Arrays.stream(libraryKbIds.split(","))
.map(String::trim)
.filter(StrUtil::isNotBlank)
.forEach(libId -> knowledgeSources.get("regulation")
.addAll(queryKnowledgeBase(libId, queries, 100)));
}
// 审计案例库检索
if (StrUtil.isNotBlank(projectLibrary)) {
knowledgeSources.get("auditCase").addAll(
queryKnowledgeBase(projectLibrary, queries, 80));
}
// 财务知识库检索(预算执行相关)
if (StrUtil.isNotBlank(kbIds)) {
knowledgeSources.get("financial").addAll(
queryKnowledgeBase(kbIds.split(",")[0], buildFinancialExecutionQueries(), 120));
}
// 智能去重和排序
knowledgeSources.forEach((key, list) -> {
List<String> processed = list.stream()
.map(String::trim) // 去除首尾空格
.filter(str -> !StrUtil.isBlank(str)) // 过滤空字符串
.distinct()
.sorted(this::budgetExecutionComparator)
.limit(getLimitBySourceType(key))
.collect(Collectors.toList());
knowledgeSources.put(key, processed);
});
log.debug("预算执行情况知识检索完成 - 企业: {}条, 法规: {}条, 案例: {}条, 财务: {}条",
knowledgeSources.get("enterprise").size(),
knowledgeSources.get("regulation").size(),
knowledgeSources.get("auditCase").size(),
knowledgeSources.get("financial").size());
return knowledgeSources;
}
/**
* 构建预算执行情况查询词 - 具体化
*/
private List<String> buildBudgetExecutionQueries() {
return Arrays.asList(
"预算执行率 执行进度 进度报表",
"实际拨款 拨款到位 资金拨付",
"预算调整 追加预算 调整审批",
"预算执行分析 执行情况分析 执行报告",
"项目执行 项目实施 项目进度",
"资金使用 资金拨付 资金到位",
"指标结余 预算结余 结转结余",
"预算执行偏差 执行差异 差异分析",
"月度执行 季度执行 年度执行",
"预算执行监督 执行检查 执行审计",
"预算执行效果 执行效益 执行成果",
"预算执行合规 执行规范 执行合法",
"预算执行台账 执行记录 执行日志",
"拨款凭证 付款凭证 资金支付",
"预算执行预警 执行风险 风险预警",
"预算执行考核 执行评价 绩效考核",
"预算执行整改 执行问题 整改措施",
"预算执行信息化 执行系统 电子台账",
"预算执行报告 执行汇报 执行总结",
"预算执行公开 执行透明 信息公开"
);
}
/**
* 构建财务执行相关查询词
*/
private List<String> buildFinancialExecutionQueries() {
return Arrays.asList(
"财务报表 财务报告 会计报表",
"资金流水 银行流水 现金流水",
"支付凭证 付款记录 银行回单",
"预算执行表 执行进度表 执行明细",
"决算报表 决算报告 决算分析",
"费用报销 报销凭证 报销记录",
"项目支出 项目付款 项目结算",
"资金监管 资金监控 资金跟踪",
"财务分析 执行分析 差异分析",
"审计报告 审计意见 审计整改"
);
}
/**
* 构建完整的知识上下文
*/
private String buildCompleteKnowledgeContext(Map<String, List<String>> knowledgeSources,
String history, String suggestion, String data) {
StringBuilder context = new StringBuilder();
// 1. 核心审计任务
context.append("## 核心审计任务\n");
context.append("审计分类:").append(AuditContent5BudgetExecutionConstants.CATEGORY_BUDGET_EXECUTION).append("\n");
context.append("审计描述:检查预算执行的进度、合规性、效果,分析预算执行偏差原因,评估预算执行效益\n\n");
// 2. 审计框架(审计规则)
context.append("## 审计框架(审计规则)\n");
context.append("以下审计框架定义了审计范围和要点,请基于此框架开展工作:\n");
context.append(AuditContent5BudgetExecutionConstants.AUDIT_FRAMEWORK).append("\n\n");
// 3. 审计目标
context.append("## 审计目标\n");
context.append(AuditContent5BudgetExecutionConstants.AUDIT_OBJECTIVE).append("\n\n");
// 4. 审计工作原则
context.append("## 审计工作原则\n");
context.append(AuditContent5BudgetExecutionConstants.AUDIT_PRINCIPLES).append("\n\n");
// 4.5. 预算管理审计数据(作为上下文)
if (ObjectUtil.isNotEmpty(data)) {
context.append("## 预算管理审计数据(作为参考上下文)\n");
context.append(data).append("\n\n");
}
// 5. 企业单位知识(主要考察内容)
if (!knowledgeSources.get("enterprise").isEmpty()) {
context.append("## 企业单位知识(具体考察内容)\n");
context.append("以下是企业单位的实际预算执行资料,请基于审计框架,结合这些具体内容生成审计记录:\n\n");
knowledgeSources.get("enterprise").forEach(knowledge ->
context.append("").append(knowledge).append("\n"));
context.append("\n");
}
// 6. 财务知识(预算执行相关)
if (!knowledgeSources.get("financial").isEmpty()) {
context.append("## 财务知识(预算执行相关)\n");
context.append("以下是财务相关预算执行资料,包括预算执行进度、资金拨付等信息:\n\n");
knowledgeSources.get("financial").forEach(knowledge ->
context.append("").append(knowledge).append("\n"));
context.append("\n");
}
// 7. 审计要点提示
context.append("## 审计要点提示\n");
context.append(AuditContent5BudgetExecutionConstants.AUDIT_KEY_POINTS).append("\n\n");
// 8. 数据格式要求
context.append("## 数据格式要求\n");
context.append("请生成JSON数组格式的审计表数据每个审计条目包含以下字段\n");
context.append(AuditContent5BudgetExecutionConstants.OUTPUT_FORMAT).append("\n\n");
// 9. 审计证据要求
context.append("## 审计证据要求\n");
context.append(AuditContent5BudgetExecutionConstants.AUDIT_EVIDENCE_REQUIREMENTS).append("\n\n");
// 10. 特别提醒 - 强调全面识别
context.append("## 特别提醒\n");
context.append("1. 必须全面分析预算执行全过程,包括执行进度、执行效果、执行合规性\n");
context.append("2. 重点关注预算执行率、资金到位率、预算执行偏差等关键指标\n");
context.append("3. 金额字段应填写具体数值,如\"1,000,000.00\",不能填写简单的\"\"\"\"\n");
// context.append("4. workPaperIndex必须填写实际存在的完整文件FileId\n");
context.append("4. workPaperIndex必须填写实际存在的完整文件名||FileUrl\n");
context.append("5. 对于无数据的字段,可填写\"-\"或留空,但不能填写\"\"\n");
context.append("6. 基于预算执行全流程进行审计分析,包括月度、季度、年度执行情况\n");
context.append("7. 重点关注预算执行偏差原因分析和整改措施\n");
context.append("8. 尽可能多地生成审计记录,覆盖所有预算项目和执行环节\n\n");
// 11. 审计项目参考
context.append("## 审计项目参考(常见类型)\n");
AuditContent5BudgetExecutionConstants.AUDIT_PROJECT_TYPES.forEach(project ->
context.append("").append(project).append("\n"));
context.append("\n");
// 12. 法规和案例参考
if (!knowledgeSources.get("regulation").isEmpty()) {
context.append("## 法律法规参考\n");
knowledgeSources.get("regulation").forEach(knowledge ->
context.append("").append(knowledge).append("\n"));
context.append("\n");
}
if (!knowledgeSources.get("auditCase").isEmpty()) {
context.append("## 审计案例参考\n");
knowledgeSources.get("auditCase").forEach(knowledge ->
context.append("").append(knowledge).append("\n"));
context.append("\n");
}
// 13. 历史内容(如果有)
if (StrUtil.isNotBlank(history)) {
context.append("## 历史生成内容\n");
context.append(history).append("\n\n");
}
// 14. 用户建议(如果有)
if (StrUtil.isNotBlank(suggestion)) {
context.append("## 用户建议\n");
context.append(suggestion).append("\n\n");
}
log.debug("预算执行情况审计知识上下文长度: {} 字符", context.length());
return context.toString();
}
/**
* 预算执行情况审计相关性比较器
*/
private int budgetExecutionComparator(String reg1, String reg2) {
int score1 = calculateBudgetExecutionRelevanceScore(reg1);
int score2 = calculateBudgetExecutionRelevanceScore(reg2);
return Integer.compare(score2, score1); // 降序排序
}
/**
* 计算预算执行情况审计相关性分数
*/
private int calculateBudgetExecutionRelevanceScore(String content) {
return AuditContent5BudgetExecutionConstants.KEYWORD_WEIGHTS.entrySet().stream()
.filter(entry -> content.contains(entry.getKey()))
.mapToInt(Map.Entry::getValue)
.sum();
}
private int getLimitBySourceType(String sourceType) {
switch (sourceType) {
case "enterprise": return 250;
case "financial": return 150;
case "regulation": return 60;
case "auditCase": return 40;
default: return 50;
}
}
}

View File

@@ -0,0 +1,313 @@
package com.gxwebsoft.ai.service.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.ai.constants.AuditContent5BudgetManageConstants;
import com.gxwebsoft.ai.service.AuditContent5BudgetManageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import java.util.*;
import java.util.stream.Collectors;
@Slf4j
@Service
public class AuditContent5BudgetManageServiceImpl extends AbstractAuditContentService implements AuditContent5BudgetManageService {
// 工作流配置
private static final String DIFY_WORKFLOW_TOKEN = "Bearer app-ZGILK3nfQ9A0jHot1r4Tta0r";
@Override
public JSONObject generateBudgetManageTableData(String kbIds, String libraryKbIds, String projectLibrary,
String userName, String history, String suggestion, Object data) {
log.info("开始生成预算管理审计表数据 - 用户: {}, kbIds: {}, libraryIds: {}, projectLibrary: {}",
userName, kbIds, libraryKbIds, projectLibrary);
long startTime = System.currentTimeMillis();
try {
if (ObjectUtil.isEmpty(data)) {
JSONObject result = new JSONObject();
log.warn("未传入审计内容6大数据无法生成预算管理审计表");
result.put("success", false);
result.put("error", "需要审计内容6数据作为生成依据");
return result;
}
// 1. 检索相关知识
Map<String, List<String>> knowledgeSources = retrieveKnowledgeForBudgetManagement(
kbIds, libraryKbIds, projectLibrary
);
// 2. 构建完整的知识上下文
String knowledgeContext = buildCompleteKnowledgeContext(knowledgeSources, history, suggestion, data.toString());
// 3. 调用工作流生成数据
JSONObject requestBody = buildWorkflowRequest(knowledgeContext, userName);
JSONArray auditData = callWorkflow(DIFY_WORKFLOW_URL, DIFY_WORKFLOW_TOKEN, requestBody, "预算管理审计");
log.info("预算管理审计表生成成功 - 记录数: {}, 处理时间: {}ms",
auditData.size(), (System.currentTimeMillis() - startTime));
return buildSuccessResponse(auditData, startTime, "budget_manage_audit");
} catch (Exception e) {
log.error("生成预算管理审计表失败", e);
return buildErrorResponse("生成预算管理审计表失败: " + e.getMessage());
}
}
/**
* 检索预算管理相关知识
*/
private Map<String, List<String>> retrieveKnowledgeForBudgetManagement(String kbIds, String libraryKbIds, String projectLibrary) {
Map<String, List<String>> knowledgeSources = new HashMap<>();
knowledgeSources.put("enterprise", new ArrayList<>());
knowledgeSources.put("regulation", new ArrayList<>());
knowledgeSources.put("auditCase", new ArrayList<>());
knowledgeSources.put("financial", new ArrayList<>());
// 构建查询词 - 具体化,提高识别率
List<String> queries = buildBudgetManagementQueries();
// 企业单位库检索 - 增加查询深度
if (StrUtil.isNotBlank(kbIds)) {
Arrays.stream(kbIds.split(","))
.map(String::trim)
.filter(StrUtil::isNotBlank)
.forEach(kbId -> knowledgeSources.get("enterprise")
.addAll(queryKnowledgeBase(kbId, queries, 100)));
}
// 公共法律法规库检索
if (StrUtil.isNotBlank(libraryKbIds)) {
Arrays.stream(libraryKbIds.split(","))
.map(String::trim)
.filter(StrUtil::isNotBlank)
.forEach(libId -> knowledgeSources.get("regulation")
.addAll(queryKnowledgeBase(libId, queries, 100)));
}
// 审计案例库检索
if (StrUtil.isNotBlank(projectLibrary)) {
knowledgeSources.get("auditCase").addAll(
queryKnowledgeBase(projectLibrary, queries, 80));
}
// 财务知识库检索(预算相关)
if (StrUtil.isNotBlank(kbIds)) {
knowledgeSources.get("financial").addAll(
queryKnowledgeBase(kbIds.split(",")[0], buildFinancialQueries(), 120));
}
// 智能去重和排序
knowledgeSources.forEach((key, list) -> {
List<String> processed = list.stream()
.map(String::trim) // 去除首尾空格
.filter(str -> !StrUtil.isBlank(str)) // 过滤空字符串
.distinct()
.sorted(this::budgetManagementComparator)
.limit(getLimitBySourceType(key))
.collect(Collectors.toList());
knowledgeSources.put(key, processed);
});
log.debug("预算管理知识检索完成 - 企业: {}条, 法规: {}条, 案例: {}条, 财务: {}条",
knowledgeSources.get("enterprise").size(),
knowledgeSources.get("regulation").size(),
knowledgeSources.get("auditCase").size(),
knowledgeSources.get("financial").size());
return knowledgeSources;
}
/**
* 构建预算管理查询词 - 具体化
*/
private List<String> buildBudgetManagementQueries() {
return Arrays.asList(
"部门预算 预算编制 预算报表",
"预算调整 追加预算 预算调剂",
"预算执行 预算决算 决算报表",
"指标来源 指标运用 指标结余",
"财政拨款 资金拨付 经费拨款",
"工资统发 人员经费 工资发放",
"政府采购 采购预算 采购资金",
"财政管理专户 专户管理 资金专户",
"项目预算 项目申报 项目资金",
"预算科目 科目设置 会计科目",
"上年结余 结余资金 结转资金",
"年初预算 年度预算 预算安排",
"追加预算 预算追加 调整预算",
"预算审批 审批手续 审批流程",
"预算下达 预算批复 批复文件",
"会计处理 账务处理 财务处理",
"预算调剂 科目调剂 资金调剂",
"经营收支 经营预算 企业预算",
"可行性研究 项目评审 评审报告",
"执行单位 实施单位 承办单位"
);
}
/**
* 构建财务相关查询词
*/
private List<String> buildFinancialQueries() {
return Arrays.asList(
"财务报表 财务报告 会计报表",
"会计凭证 记账凭证 原始凭证",
"会计账簿 总账 明细账",
"资金流水 银行流水 现金流水",
"收支明细 收入支出 收付实现",
"经费支出 费用报销 报销凭证",
"工资表 工资发放表 人员工资",
"采购发票 采购合同 付款凭证",
"预算执行表 执行进度 进度报表",
"决算报告 决算分析 决算说明"
);
}
/**
* 构建完整的知识上下文
*/
private String buildCompleteKnowledgeContext(Map<String, List<String>> knowledgeSources,
String history, String suggestion, String data) {
StringBuilder context = new StringBuilder();
// 1. 核心审计任务
context.append("## 核心审计任务\n");
context.append("审计分类:").append(AuditContent5BudgetManageConstants.CATEGORY_BUDGET_MANAGEMENT).append("\n");
context.append("审计描述:检查预算编制的完整准确、预算调整审批的合规,以及预算支出的真实合法合规情况\n\n");
// 2. 审计框架(审计规则)
context.append("## 审计框架(审计规则)\n");
context.append("以下审计框架定义了审计范围和要点,请基于此框架开展工作:\n");
context.append(AuditContent5BudgetManageConstants.AUDIT_FRAMEWORK).append("\n\n");
// 3. 审计目标
context.append("## 审计目标\n");
context.append(AuditContent5BudgetManageConstants.AUDIT_OBJECTIVE).append("\n\n");
// 4. 审计工作原则
context.append("## 审计工作原则\n");
context.append(AuditContent5BudgetManageConstants.AUDIT_PRINCIPLES).append("\n\n");
// 4.5. 国有资产的管理情况、政府采购执行情况审计内容6数据作为上下文
if (StrUtil.isNotBlank(data)) {
context.append("## 国有资产的管理情况、政府采购执行情况审计内容6分析数据作为参考上下文\n");
context.append(data).append("\n\n");
}
// 5. 企业单位知识(主要考察内容)
if (!knowledgeSources.get("enterprise").isEmpty()) {
context.append("## 企业单位知识(具体考察内容)\n");
context.append("以下是企业单位的实际资料,请基于审计框架,结合这些具体内容生成审计记录:\n\n");
knowledgeSources.get("enterprise").forEach(knowledge ->
context.append("").append(knowledge).append("\n"));
context.append("\n");
}
// 6. 财务知识(预算相关)
if (!knowledgeSources.get("financial").isEmpty()) {
context.append("## 财务知识(预算相关)\n");
context.append("以下是财务相关资料,包括预算编制、执行、调整等信息:\n\n");
knowledgeSources.get("financial").forEach(knowledge ->
context.append("").append(knowledge).append("\n"));
context.append("\n");
}
// 7. 审计要点提示
context.append("## 审计要点提示\n");
context.append(AuditContent5BudgetManageConstants.AUDIT_KEY_POINTS).append("\n\n");
// 8. 数据格式要求
context.append("## 数据格式要求\n");
context.append("请生成JSON数组格式的审计表数据每个审计条目包含以下字段\n");
context.append(AuditContent5BudgetManageConstants.OUTPUT_FORMAT).append("\n\n");
// 9. 审计证据要求
context.append("## 审计证据要求\n");
context.append(AuditContent5BudgetManageConstants.AUDIT_EVIDENCE_REQUIREMENTS).append("\n\n");
// 10. 特别提醒 - 强调全面识别
context.append("## 特别提醒\n");
context.append("1. 必须全面识别知识库中所有预算科目,包括:基本支出、项目支出、人员经费、公用经费等\n");
context.append("2. 每个独立的预算科目都要生成独立的审计记录,不限制数量,尽可能多地生成\n");
context.append("3. 金额字段应填写具体数值,如\"1,000,000.00\",不能填写简单的\"\"\"\"\n");
// context.append("4. workPaperIndex必须填写实际存在的完整文件FileId\n");
context.append("4. workPaperIndex必须填写实际存在的完整文件名||FileUrl\n");
context.append("5. 对于无数据的字段,可填写\"-\"或留空,但不能填写\"\"\n");
context.append("6. 基于预算编制、调整、执行的全流程进行审计分析\n");
context.append("7. 重点关注预算调整的合规性和预算执行的真实性\n\n");
// 11. 预算科目参考
context.append("## 预算科目参考(常见类型)\n");
AuditContent5BudgetManageConstants.BUDGET_SUBJECT_TYPES.forEach(subject ->
context.append("").append(subject).append("\n"));
context.append("\n");
// 12. 法规和案例参考
if (!knowledgeSources.get("regulation").isEmpty()) {
context.append("## 法律法规参考\n");
knowledgeSources.get("regulation").forEach(knowledge ->
context.append("").append(knowledge).append("\n"));
context.append("\n");
}
if (!knowledgeSources.get("auditCase").isEmpty()) {
context.append("## 审计案例参考\n");
knowledgeSources.get("auditCase").forEach(knowledge ->
context.append("").append(knowledge).append("\n"));
context.append("\n");
}
// 13. 历史内容(如果有)
if (StrUtil.isNotBlank(history)) {
context.append("## 历史生成内容\n");
context.append(history).append("\n\n");
}
// 14. 用户建议(如果有)
if (StrUtil.isNotBlank(suggestion)) {
context.append("## 用户建议\n");
context.append(suggestion).append("\n\n");
}
log.debug("预算管理审计知识上下文长度: {} 字符", context.length());
return context.toString();
}
/**
* 预算管理审计相关性比较器
*/
private int budgetManagementComparator(String reg1, String reg2) {
int score1 = calculateBudgetManagementRelevanceScore(reg1);
int score2 = calculateBudgetManagementRelevanceScore(reg2);
return Integer.compare(score2, score1); // 降序排序
}
/**
* 计算预算管理审计相关性分数
*/
private int calculateBudgetManagementRelevanceScore(String content) {
return AuditContent5BudgetManageConstants.KEYWORD_WEIGHTS.entrySet().stream()
.filter(entry -> content.contains(entry.getKey()))
.mapToInt(Map.Entry::getValue)
.sum();
}
private int getLimitBySourceType(String sourceType) {
switch (sourceType) {
case "enterprise": return 250;
case "financial": return 150;
case "regulation": return 60;
case "auditCase": return 40;
default: return 50;
}
}
}

View File

@@ -0,0 +1,337 @@
package com.gxwebsoft.ai.service.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.ai.constants.AuditContent6StateAssetsConstants;
import com.gxwebsoft.ai.service.AuditContent6StateAssetsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import cn.hutool.core.util.StrUtil;
import java.util.*;
import java.util.stream.Collectors;
@Slf4j
@Service
public class AuditContent6StateAssetsServiceImpl extends AbstractAuditContentService implements AuditContent6StateAssetsService {
// 工作流配置
private static final String DIFY_WORKFLOW_TOKEN = "Bearer app-lsqVD2hTWYQpA89SDSr9s3dH";
@Override
public JSONObject generateStateAssetsAuditTableData(String kbIds, String libraryKbIds, String projectLibrary,
String userName, String history, String suggestion) {
log.info("开始生成国有资产管理审计表数据 - 用户: {}, kbIds: {}, libraryIds: {}, projectLibrary: {}",
userName, kbIds, libraryKbIds, projectLibrary);
long startTime = System.currentTimeMillis();
try {
// 1. 检索相关知识
Map<String, List<String>> knowledgeSources = retrieveKnowledgeForStateAssetsManagement(
kbIds, libraryKbIds, projectLibrary
);
// 2. 构建完整的知识上下文
String knowledgeContext = buildCompleteKnowledgeContext(
knowledgeSources, history, suggestion
);
// 3. 调用工作流生成数据
JSONObject requestBody = buildWorkflowRequest(knowledgeContext, userName);
JSONArray auditData = callWorkflow(DIFY_WORKFLOW_URL, DIFY_WORKFLOW_TOKEN, requestBody, "国资管理审计");
// 4. 后处理:确保数据格式正确
auditData = processAuditData(auditData);
log.info("国有资产管理审计表生成成功 - 记录数: {}, 处理时间: {}ms",
auditData.size(), (System.currentTimeMillis() - startTime));
return buildSuccessResponse(auditData, startTime, "state_assets_audit");
} catch (Exception e) {
log.error("生成国有资产管理审计表失败", e);
return buildErrorResponse("生成国有资产管理审计表失败: " + e.getMessage());
}
}
/**
* 检索国资管理相关知识
*/
private Map<String, List<String>> retrieveKnowledgeForStateAssetsManagement(String kbIds, String libraryKbIds, String projectLibrary) {
Map<String, List<String>> knowledgeSources = new HashMap<>();
knowledgeSources.put("enterprise", new ArrayList<>());
knowledgeSources.put("regulation", new ArrayList<>());
knowledgeSources.put("auditCase", new ArrayList<>());
// 构建查询词 - 具体化,提高识别率
List<String> queries = buildStateAssetsQueries();
// 企业单位库检索 - 增加查询深度
if (StrUtil.isNotBlank(kbIds)) {
Arrays.stream(kbIds.split(","))
.map(String::trim)
.filter(StrUtil::isNotBlank)
.forEach(kbId -> knowledgeSources.get("enterprise")
.addAll(queryKnowledgeBase(kbId, queries, 100)));
}
// 公共法律法规库检索
if (StrUtil.isNotBlank(libraryKbIds)) {
Arrays.stream(libraryKbIds.split(","))
.map(String::trim)
.filter(StrUtil::isNotBlank)
.forEach(libId -> knowledgeSources.get("regulation")
.addAll(queryKnowledgeBase(libId, queries, 100)));
}
// 审计案例库检索
if (StrUtil.isNotBlank(projectLibrary)) {
knowledgeSources.get("auditCase").addAll(
queryKnowledgeBase(projectLibrary, queries, 80));
}
// 智能去重和排序
knowledgeSources.forEach((key, list) -> {
List<String> processed = list.stream()
.map(String::trim) // 去除首尾空格
.filter(str -> !StrUtil.isBlank(str)) // 过滤空字符串
.distinct()
.sorted(this::stateAssetsManagementComparator)
.limit(getLimitBySourceType(key))
.collect(Collectors.toList());
knowledgeSources.put(key, processed);
});
log.debug("国资管理知识检索完成 - 企业: {}条, 法规: {}条, 案例: {}条",
knowledgeSources.get("enterprise").size(),
knowledgeSources.get("regulation").size(),
knowledgeSources.get("auditCase").size());
return knowledgeSources;
}
/**
* 构建国资管理查询词 - 具体化
*/
private List<String> buildStateAssetsQueries() {
return Arrays.asList(
"固定资产 资产台账 资产登记",
"房屋 土地 土地使用权",
"车辆 汽车 运输工具",
"机械设备 生产设备 仪器设备",
"办公设备 电脑 打印机 空调",
"仓库 厂房 办公楼 宿舍楼",
"家具 电器 电子设备",
"无形资产 软件 专利权",
"在建工程 工程项目",
"土地证 房产证 不动产权证",
"资产评估 资产价值 原值 净值",
"资产折旧 累计折旧",
"资产盘点 盘点表 盘点记录",
"资产报废 资产处置",
"资产出租 租赁合同 租金",
"资产转让 资产出售",
"政府采购 采购合同",
"招投标 投标文件",
"资产配置 资产采购",
"资产使用 资产保管"
);
}
/**
* 构建完整的知识上下文
*/
private String buildCompleteKnowledgeContext(Map<String, List<String>> knowledgeSources,
String history, String suggestion) {
StringBuilder context = new StringBuilder();
// 1. 核心审计任务
context.append("## 核心审计任务\n");
context.append("审计分类:").append(AuditContent6StateAssetsConstants.CATEGORY_STATE_ASSETS_MANAGEMENT).append("\n");
context.append("审计描述:检查国有资产管理情况和政府采购执行情况,确保资产安全完整和采购规范\n\n");
// 2. 审计框架(审计规则)
context.append("## 审计框架(审计规则)\n");
context.append("以下审计框架定义了审计范围和要点,请基于此框架开展工作:\n");
context.append(AuditContent6StateAssetsConstants.AUDIT_FRAMEWORK).append("\n\n");
// 3. 审计目标
context.append("## 审计目标\n");
context.append(AuditContent6StateAssetsConstants.AUDIT_OBJECTIVE).append("\n\n");
// 4. 审计工作原则
context.append("## 审计工作原则\n");
context.append(AuditContent6StateAssetsConstants.AUDIT_PRINCIPLES).append("\n\n");
// 5. 企业单位知识(主要考察内容)
if (!knowledgeSources.get("enterprise").isEmpty()) {
context.append("## 企业单位知识(具体考察内容)\n");
context.append("以下是企业单位的实际资料,请基于审计框架,结合这些具体内容生成审计记录:\n\n");
knowledgeSources.get("enterprise").forEach(knowledge ->
context.append("").append(knowledge).append("\n"));
context.append("\n");
}
// 6. 审计要点提示
context.append("## 审计要点提示\n");
context.append(AuditContent6StateAssetsConstants.AUDIT_KEY_POINTS).append("\n\n");
// 7. 数据格式要求
context.append("## 数据格式要求\n");
context.append("请生成JSON数组格式的审计表数据每个审计条目包含以下字段\n");
context.append(AuditContent6StateAssetsConstants.OUTPUT_FORMAT).append("\n\n");
// 8. 审计证据要求
context.append("## 审计证据要求\n");
context.append(AuditContent6StateAssetsConstants.AUDIT_EVIDENCE_REQUIREMENTS).append("\n\n");
// 9. 特别提醒 - 强调全面识别
context.append("## 特别提醒\n");
context.append("1. 必须全面识别知识库中所有国有资产,包括:房屋、土地、车辆、机械设备、办公设备、电子设备、家具、无形资产等\n");
context.append("2. 每个独立的资产都要生成独立的审计记录,不限制数量,尽可能多地生成\n");
context.append("3. 即使资产信息不完整,也要基于现有信息生成审计记录\n");
// context.append("4. workPaperIndex必须填写实际存在的完整文件FileId\n");
context.append("4. workPaperIndex必须填写实际存在的完整文件名||FileUrl\n");
context.append("5. 对于未出租资产,承租方、合同金额等字段填写\"未出租\"\n");
context.append("6. 备注中应详细说明资产状况、使用情况、合规性评价\n");
context.append("7. 不能填写简单的\"\",要提供有意义的描述\n\n");
// 10. 法规和案例参考
if (!knowledgeSources.get("regulation").isEmpty()) {
context.append("## 法律法规参考\n");
knowledgeSources.get("regulation").forEach(knowledge ->
context.append("").append(knowledge).append("\n"));
context.append("\n");
}
if (!knowledgeSources.get("auditCase").isEmpty()) {
context.append("## 审计案例参考\n");
knowledgeSources.get("auditCase").forEach(knowledge ->
context.append("").append(knowledge).append("\n"));
context.append("\n");
}
// 11. 历史内容(如果有)
if (StrUtil.isNotBlank(history)) {
context.append("## 历史生成内容\n");
context.append(history).append("\n\n");
}
// 12. 用户建议(如果有)
if (StrUtil.isNotBlank(suggestion)) {
context.append("## 用户建议\n");
context.append(suggestion).append("\n\n");
}
log.debug("国资管理审计知识上下文长度: {} 字符", context.length());
return context.toString();
}
/**
* 国资管理审计相关性比较器
*/
private int stateAssetsManagementComparator(String reg1, String reg2) {
int score1 = calculateStateAssetsRelevanceScore(reg1);
int score2 = calculateStateAssetsRelevanceScore(reg2);
return Integer.compare(score2, score1); // 降序排序
}
/**
* 计算国资管理审计相关性分数
*/
private int calculateStateAssetsRelevanceScore(String content) {
return AuditContent6StateAssetsConstants.KEYWORD_WEIGHTS.entrySet().stream()
.filter(entry -> content.contains(entry.getKey()))
.mapToInt(Map.Entry::getValue)
.sum();
}
private int getLimitBySourceType(String sourceType) {
switch (sourceType) {
case "enterprise": return 300; // 增加企业知识数量
case "regulation": return 60;
case "auditCase": return 40;
default: return 50;
}
}
/**
* 后处理审计数据
*/
private JSONArray processAuditData(JSONArray auditData) {
if (auditData == null || auditData.isEmpty()) {
return auditData;
}
JSONArray processedData = new JSONArray();
for (int i = 0; i < auditData.size(); i++) {
JSONObject item = auditData.getJSONObject(i);
// 确保序号存在
if (!item.containsKey("index") || item.getInteger("index") == null) {
item.put("index", i + 1);
}
// 确保国有资产名称存在
if (!item.containsKey("assetName") || StrUtil.isBlank(item.getString("assetName"))) {
item.put("assetName", "国有资产" + (i + 1));
}
// 优化取得方式
String acquisitionMethod = item.getString("acquisitionMethod");
if (StrUtil.isBlank(acquisitionMethod) || "".equals(acquisitionMethod)) {
item.put("acquisitionMethod", "购置");
}
// 优化资产价值
String assetValue = item.getString("assetValue");
if (StrUtil.isBlank(assetValue) || "".equals(assetValue)) {
item.put("assetValue", "待评估");
}
// 优化面积
String area = item.getString("area");
if (StrUtil.isBlank(area) || "".equals(area)) {
item.put("area", "未提供");
}
// 优化出租相关字段
String platformLease = item.getString("platformLease");
if (StrUtil.isBlank(platformLease) || "".equals(platformLease)) {
item.put("platformLease", "");
}
String tenant = item.getString("tenant");
if (StrUtil.isBlank(tenant) || "".equals(tenant) || tenant.contains("")) {
item.put("tenant", "未出租");
item.put("contractAmount", "未出租");
item.put("leasePeriod", "未出租");
item.put("rentPaymentTime", "未出租");
item.put("approvalDoc", "未出租");
}
// 优化是否纳入预算
String inBudget = item.getString("inBudget");
if (StrUtil.isBlank(inBudget) || "".equals(inBudget)) {
item.put("inBudget", "");
}
// 确保工作底稿索引是数组格式
// if (!item.containsKey("workPaperIndex") || !(item.get("workPaperIndex") instanceof JSONArray)) {
// JSONArray workPaperIndex = new JSONArray();
// String assetName = item.getString("assetName");
// workPaperIndex.add(assetName + "资产登记台账");
// item.put("workPaperIndex", workPaperIndex);
// }
processedData.add(item);
}
return processedData;
}
}

View File

@@ -0,0 +1,359 @@
package com.gxwebsoft.ai.service.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.ai.constants.AuditContent7Constants;
import com.gxwebsoft.ai.service.AuditContent7InvestmentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import cn.hutool.core.util.StrUtil;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
@Slf4j
@Service
public class AuditContent7InvestmentServiceImpl extends AbstractAuditContentService implements AuditContent7InvestmentService {
// Dify工作流配置
private static final String DIFY_WORKFLOW_TOKEN = "Bearer app-rNhgcQkNr2JJP9lePT3ICzgW";
// 审计类别顺序
private static final List<String> CATEGORY_ORDER = AuditContent7Constants.getAllCategories();
@Override
public JSONObject generateInvestmentSituationTableData(String kbIds, String libraryKbIds,
String projectLibrary, String userName,
String history, String suggestion) {
log.info("开始生成重大投资情况审计表数据 - 用户: {}, kbIds: {}, libraryIds: {}, projectLibrary: {}",
userName, kbIds, libraryKbIds, projectLibrary);
long startTime = System.currentTimeMillis();
try {
// 异步并行处理每个审计类别
Map<String, CompletableFuture<JSONArray>> futures = processCategoriesAsync(
CATEGORY_ORDER,
category -> generateCategoryDataAsync(category, kbIds, libraryKbIds, projectLibrary, userName, history, suggestion)
);
// 等待所有异步任务完成
CompletableFuture.allOf(futures.values().toArray(new CompletableFuture[0])).join();
// 合并所有分类的结果
JSONArray allData = mergeCategoryResults(CATEGORY_ORDER, futures);
log.info("重大投资情况审计表生成成功 - 记录数: {}, 处理时间: {}ms", allData.size(), (System.currentTimeMillis() - startTime));
return buildSuccessResponse(allData, startTime, "investment_situation_audit");
} catch (Exception e) {
log.error("生成重大投资情况审计表失败", e);
return buildErrorResponse("生成重大投资情况审计表失败: " + e.getMessage());
}
}
/**
* 异步生成单个审计类别的数据
*/
@Async
public CompletableFuture<JSONArray> generateCategoryDataAsync(String category, String kbIds,
String libraryKbIds, String projectLibrary,
String userName, String history, String suggestion) {
return CompletableFuture.supplyAsync(() -> {
try {
log.info("开始生成审计类别 {} 的数据", category);
// 1. 为当前审计类别召回相关知识
Map<String, List<String>> knowledgeSources = retrieveKnowledgeForCategory(
category, kbIds, libraryKbIds, projectLibrary
);
// 2. 构建完整的知识上下文
String knowledgeContext = buildCompleteKnowledgeContext(
category, knowledgeSources, history, suggestion
);
// 3. 调用Dify工作流生成数据
JSONObject requestBody = buildWorkflowRequest(knowledgeContext, userName);
JSONArray categoryData = callWorkflow(DIFY_WORKFLOW_URL, DIFY_WORKFLOW_TOKEN, requestBody, "重大投资情况-" + category);
log.info("审计类别 {} 数据生成完成,生成 {} 条记录", category, categoryData.size());
return categoryData;
} catch (Exception e) {
log.error("生成审计类别 {} 数据失败", category, e);
return new JSONArray();
}
});
}
/**
* 为单个审计类别检索相关知识
*/
private Map<String, List<String>> retrieveKnowledgeForCategory(String category, String kbIds,
String libraryKbIds, String projectLibrary) {
Map<String, List<String>> knowledgeSources = new HashMap<>();
knowledgeSources.put("enterprise", new ArrayList<>());
knowledgeSources.put("regulation", new ArrayList<>());
knowledgeSources.put("auditCase", new ArrayList<>());
knowledgeSources.put("financial", new ArrayList<>()); // 财务数据单独处理
// 构建当前审计类别的查询词
List<String> categoryQueries = buildCategoryQueries(category);
// 企业单位库检索
if (StrUtil.isNotBlank(kbIds)) {
Arrays.stream(kbIds.split(","))
.map(String::trim)
.filter(StrUtil::isNotBlank)
.forEach(kbId -> {
knowledgeSources.get("enterprise")
.addAll(queryKnowledgeBase(kbId, categoryQueries, 120));
// 单独查询财务相关文档
knowledgeSources.get("financial")
.addAll(queryKnowledgeBase(kbId,
Arrays.asList("资产负债表", "利润表", "现金流量表", "会计科目", "银行流水"), 80));
});
}
// 公共法律法规库检索
if (StrUtil.isNotBlank(libraryKbIds)) {
Arrays.stream(libraryKbIds.split(","))
.map(String::trim)
.filter(StrUtil::isNotBlank)
.forEach(libId -> knowledgeSources.get("regulation")
.addAll(queryKnowledgeBase(libId, categoryQueries, 100)));
}
// 审计案例库检索
if (StrUtil.isNotBlank(projectLibrary)) {
knowledgeSources.get("auditCase").addAll(
queryKnowledgeBase(projectLibrary, categoryQueries, 80));
}
// 智能去重和排序(按相关性)
knowledgeSources.forEach((key, list) -> {
List<String> processed = list.stream()
.distinct()
.sorted(this::investmentRelevanceComparator)
.limit(getLimitBySourceType(key))
.collect(Collectors.toList());
knowledgeSources.put(key, processed);
});
log.debug("审计类别 {} 知识检索完成 - 企业: {}条, 法规: {}条, 案例: {}条, 财务: {}条",
category,
knowledgeSources.get("enterprise").size(),
knowledgeSources.get("regulation").size(),
knowledgeSources.get("auditCase").size(),
knowledgeSources.get("financial").size());
return knowledgeSources;
}
/**
* 构建审计类别特定的查询词
*/
private List<String> buildCategoryQueries(String category) {
switch (category) {
case AuditContent7Constants.CATEGORY_MAJOR_INVESTMENT:
return Arrays.asList("对外投资 决策程序 审批手续 可行性研究 投资效益",
"长期投资 短期投资 投资合同 投资回报");
case AuditContent7Constants.CATEGORY_MAJOR_PROJECT:
return Arrays.asList("工程建设 项目审批 安全质量 环保要求 工程效益",
"工程项目 工程管理 竣工验收");
case AuditContent7Constants.CATEGORY_MAJOR_CAPITAL:
return Arrays.asList("资本运作 并购重组 交易对价 资金来源",
"股权交易 资产评估 资本运营");
case AuditContent7Constants.CATEGORY_MAJOR_ASSET_DISPOSAL:
return Arrays.asList("资产处置 资产评估 交易价格 产权交易",
"资产转让 资产拍卖 资产划转");
case AuditContent7Constants.CATEGORY_MAJOR_PROCUREMENT:
return Arrays.asList("物资采购 服务采购 招标投标 采购价格",
"采购合同 供应商 采购管理");
case AuditContent7Constants.CATEGORY_MAJOR_GUARANTEE:
return Arrays.asList("担保借款 担保合同 借款合同 风险控制",
"对外担保 借款审批 抵押质押");
default:
return Arrays.asList(category);
}
}
/**
* 构建完整的知识上下文
*/
private String buildCompleteKnowledgeContext(String category, Map<String, List<String>> knowledgeSources,
String history, String suggestion) {
StringBuilder context = new StringBuilder();
// 1. 审计要求说明
context.append("## 重大投资情况审计要求 - ").append(category).append("\n");
context.append("请基于以下知识生成").append(category).append("相关的审计表格数据:\n\n");
context.append("**审计目标:**\n");
context.append("- 核查重大投资决策的合规性和民主性\n");
context.append("- 检查审批手续的完备性\n");
context.append("- 评估可行性研究和尽职调查的充分性\n");
context.append("- 核査投资项目的效益情况\n");
context.append("- 识别决策程序、审批过程、操作过程中的风险和问题\n\n");
// 2. 审计方法(从常量中获取)
context.append("## 审计方法及步骤\n");
context.append(AuditContent7Constants.AUDIT_INSTRUCTIONS.get("GENERAL_RULE")).append("\n\n");
// 3. 审计指令(决策程序检查)
context.append("## 审计检查指令\n");
context.append(AuditContent7Constants.AUDIT_INSTRUCTIONS.get("DECISION_SYSTEM_CHECK")).append("\n");
context.append(AuditContent7Constants.AUDIT_INSTRUCTIONS.get("DECISION_PROCEDURE_CHECK")).append("\n\n");
// 4. 数据格式要求
context.append("## 数据格式要求\n");
context.append("需要生成").append(category).append("分类的数据,尽可能生成多个实例:\n");
context.append("- ").append(category).append("").append(AuditContent7Constants.CATEGORY_DESCRIPTIONS.get(category)).append("\n");
context.append("\n");
context.append("每条记录应包含5个核心字段\n");
context.append("- **category**:固定为\"").append(category).append("\"\n");
context.append("- **auditContent**:具体的审计内容,从以下模板中选择或根据知识库生成\n");
context.append("- **checkEvidence**:详细的检查证据描述,必须包含:\n");
context.append(" ①查阅的具体文件名称和内容\n");
context.append(" ②检查过程和方法\n");
context.append(" ③与制度要求的差异点\n");
context.append(" ④明确的总结性结论(问题、风险、合规状况)\n");
context.append("- **testResult**:测试结果(通过/不通过/待检查),严格判断:\n");
context.append(" • 通过:证据充分且完全符合要求\n");
context.append(" • 不通过:制度不一致、执行不到位、证据不充分\n");
context.append(" • 待检查:无法确定,需要进一步检查\n");
// context.append("- **workPaperIndex**相关《工作底稿索引FileId》必须是实际存在的完整文件FileId确保能在文件夹中搜索到\n");
context.append("- **workPaperIndex**:相关[\"实际存在的完整文件名||FileUrl\"],必须是实际存在的完整文件名,不能使用附表标题,确保能在文件夹中搜索到\n");
context.append("- **fileIndex**:相关《文件索引》,关联的支持文件\n\n");
// 5. 审计内容模板(提供参考)
context.append("## 审计内容模板(供参考)\n");
List<String> templates = AuditContent7Constants.AUDIT_CONTENT_TEMPLATES.get(category);
if (templates != null && !templates.isEmpty()) {
for (int i = 0; i < Math.min(templates.size(), 5); i++) {
context.append(i + 1).append(". ").append(templates.get(i)).append("\n");
}
}
context.append("(请根据知识库内容,从不同角度生成多个审计检查点)\n\n");
// 6. 文件类型参考(用于工作底稿索引)
context.append("## 相关文件类型参考\n");
AuditContent7Constants.FILE_TYPE_KEYWORDS.forEach((type, keywords) -> {
context.append("- ").append(type).append("").append(String.join("", keywords)).append("\n");
});
context.append("\n");
// 7. 历史内容
if (StrUtil.isNotBlank(history)) {
context.append("## 历史生成内容\n");
context.append("以下是之前生成的内容,请基于此进行优化:\n");
context.append(history).append("\n\n");
}
// 8. 用户建议
if (StrUtil.isNotBlank(suggestion)) {
context.append("## 用户优化建议\n");
context.append("请根据以下建议对生成内容进行调整:\n");
context.append(suggestion).append("\n\n");
}
// 9. 企业单位知识
if (!knowledgeSources.get("enterprise").isEmpty()) {
context.append("## 企业单位制度知识\n");
knowledgeSources.get("enterprise").forEach(knowledge ->
context.append(knowledge).append("\n"));
context.append("\n");
}
// 10. 法律法规知识
if (!knowledgeSources.get("regulation").isEmpty()) {
context.append("## 法律法规知识\n");
knowledgeSources.get("regulation").forEach(knowledge ->
context.append(knowledge).append("\n"));
context.append("\n");
}
// 11. 审计案例知识
if (!knowledgeSources.get("auditCase").isEmpty()) {
context.append("## 审计案例知识\n");
knowledgeSources.get("auditCase").forEach(knowledge ->
context.append(knowledge).append("\n"));
context.append("\n");
}
// 12. 财务数据知识
if (!knowledgeSources.get("financial").isEmpty()) {
context.append("## 财务数据知识\n");
context.append("(重点关注:资产负债表、利润表、会计科目、银行流水等)\n");
knowledgeSources.get("financial").forEach(knowledge ->
context.append(knowledge).append("\n"));
}
return context.toString();
}
/**
* 重大投资情况相关性比较器
*/
private int investmentRelevanceComparator(String reg1, String reg2) {
int score1 = calculateInvestmentRelevanceScore(reg1);
int score2 = calculateInvestmentRelevanceScore(reg2);
return Integer.compare(score2, score1); // 降序排列
}
/**
* 计算重大投资情况相关性分数
*/
private int calculateInvestmentRelevanceScore(String content) {
return AuditContent7Constants.KEYWORD_WEIGHTS.entrySet().stream()
.filter(entry -> content.contains(entry.getKey()))
.mapToInt(Map.Entry::getValue)
.sum();
}
/**
* 根据知识来源类型获取限制数量
*/
private int getLimitBySourceType(String sourceType) {
switch (sourceType) {
case "enterprise": return 120;
case "regulation": return 100;
case "auditCase": return 80;
case "financial": return 60;
default: return 50;
}
}
/**
* 重写callWorkflow方法适配重大投资情况工作流的返回格式
*/
@Override
protected JSONArray callWorkflow(String url, String token, JSONObject requestBody, String workflowName) {
try {
log.info("调用{}工作流,请求体长度: {}", workflowName, requestBody.toString().length());
// 调用父类方法获取工作流响应
JSONArray result = super.callWorkflow(url, token, requestBody, workflowName);
// 如果父类方法返回结果为空,则尝试按重大投资情况特有的格式解析
if (result == null || result.isEmpty()) {
// 这里可以根据需要添加特定的解析逻辑
log.warn("{}工作流返回结果为空,使用默认空数组", workflowName);
return new JSONArray();
}
log.info("成功获取{}工作流返回数据,记录数: {}", workflowName, result.size());
return result;
} catch (Exception e) {
log.error("调用{}工作流失败", workflowName, e);
throw new RuntimeException("调用" + workflowName + "工作流失败: " + e.getMessage(), e);
}
}
}

View File

@@ -0,0 +1,327 @@
package com.gxwebsoft.ai.service.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.ai.constants.AuditContent8InternalControlConstants;
import com.gxwebsoft.ai.service.AuditContent8InternalControlService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import cn.hutool.core.util.StrUtil;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
@Slf4j
@Service
public class AuditContent8InternalControlServiceImpl extends AbstractAuditContentService implements AuditContent8InternalControlService {
// 工作流配置
private static final String DIFY_WORKFLOW_TOKEN = "Bearer app-R1GN6zKkrfBYVMtwz8c6pyRM";
// 审计测试方法
private static final List<String> TEST_METHODS = Arrays.asList(
"符合性测试", "穿行测试", "抽样测试", "观察询问", "文档查阅"
);
@Override
public JSONObject generateInternalControlTableData(String kbIds, String libraryKbIds, String projectLibrary, String userName, String history, String suggestion) {
log.info("开始生成单位层面财务管理内部控制测试表数据 - 用户: {}, kbIds: {}, libraryIds: {}, projectLibrary: {}", userName, kbIds, libraryKbIds, projectLibrary);
long startTime = System.currentTimeMillis();
try {
// 异步并行处理每个控制环节
Map<String, CompletableFuture<JSONArray>> futures = processCategoriesAsync(
Arrays.asList(AuditContent8InternalControlConstants.CONTROL_LINKS),
controlLink -> generateControlLinkDataAsync(controlLink, kbIds, libraryKbIds, projectLibrary, userName, history, suggestion)
);
// 等待所有异步任务完成
CompletableFuture.allOf(futures.values().toArray(new CompletableFuture[0])).join();
// 合并所有分类的结果
JSONArray allData = mergeCategoryResults(Arrays.asList(AuditContent8InternalControlConstants.CONTROL_LINKS), futures);
log.info("单位层面财务管理内部控制测试表生成成功 - 记录数: {}, 处理时间: {}ms", allData.size(), (System.currentTimeMillis() - startTime));
return buildSuccessResponse(allData, startTime, "internal_control_audit");
} catch (Exception e) {
log.error("生成单位层面财务管理内部控制测试表失败", e);
return buildErrorResponse("生成单位层面财务管理内部控制测试表失败: " + e.getMessage());
}
}
/**
* 异步生成单个控制环节的数据
*/
@Async
public CompletableFuture<JSONArray> generateControlLinkDataAsync(String controlLink, String kbIds, String libraryKbIds, String projectLibrary, String userName, String history, String suggestion) {
return CompletableFuture.supplyAsync(() -> {
try {
log.info("开始生成控制环节 {} 的数据", controlLink);
// 1. 为当前控制环节召回相关知识
Map<String, List<String>> knowledgeSources = retrieveKnowledgeForControlLink(
controlLink, kbIds, libraryKbIds, projectLibrary
);
// 2. 构建完整的知识上下文
String knowledgeContext = buildCompleteKnowledgeContext(
controlLink, knowledgeSources, history, suggestion
);
// 3. 调用工作流生成数据
JSONObject requestBody = buildWorkflowRequest(knowledgeContext, userName);
JSONArray controlLinkData = callWorkflow(DIFY_WORKFLOW_URL, DIFY_WORKFLOW_TOKEN, requestBody, "内部控制-" + controlLink);
log.info("控制环节 {} 数据生成完成,生成 {} 条记录", controlLink, controlLinkData.size());
return controlLinkData;
} catch (Exception e) {
log.error("生成控制环节 {} 数据失败", controlLink, e);
return new JSONArray();
}
});
}
/**
* 为单个控制环节检索相关知识
*/
private Map<String, List<String>> retrieveKnowledgeForControlLink(String controlLink, String kbIds, String libraryKbIds, String projectLibrary) {
Map<String, List<String>> knowledgeSources = new HashMap<>();
knowledgeSources.put("enterprise", new ArrayList<>());
knowledgeSources.put("regulation", new ArrayList<>());
knowledgeSources.put("auditCase", new ArrayList<>());
// 构建当前控制环节的查询词
List<String> controlQueries = buildControlLinkQueries(controlLink);
// 企业单位库检索
if (StrUtil.isNotBlank(kbIds)) {
Arrays.stream(kbIds.split(","))
.map(String::trim)
.filter(StrUtil::isNotBlank)
.forEach(kbId -> knowledgeSources.get("enterprise")
.addAll(queryKnowledgeBase(kbId, controlQueries, 120)));
}
// 公共法律法规库检索
if (StrUtil.isNotBlank(libraryKbIds)) {
Arrays.stream(libraryKbIds.split(","))
.map(String::trim)
.filter(StrUtil::isNotBlank)
.forEach(libId -> knowledgeSources.get("regulation")
.addAll(queryKnowledgeBase(libId, controlQueries, 100)));
}
// 审计案例库检索
if (StrUtil.isNotBlank(projectLibrary)) {
knowledgeSources.get("auditCase").addAll(
queryKnowledgeBase(projectLibrary, controlQueries, 80));
}
// 智能去重和排序
knowledgeSources.forEach((key, list) -> {
List<String> processed = list.stream()
.distinct()
.sorted(this::internalControlComparator)
.limit(getLimitBySourceType(key))
.collect(Collectors.toList());
knowledgeSources.put(key, processed);
});
log.debug("控制环节 {} 知识检索完成 - 企业: {}条, 法规: {}条, 案例: {}条",
controlLink,
knowledgeSources.get("enterprise").size(),
knowledgeSources.get("regulation").size(),
knowledgeSources.get("auditCase").size());
return knowledgeSources;
}
/**
* 构建控制环节特定的查询词
*/
private List<String> buildControlLinkQueries(String controlLink) {
// 根据控制环节构建相关查询词
List<String> queries = new ArrayList<>();
// 通用查询词
queries.add(controlLink);
queries.add("内部控制 " + controlLink);
queries.add("财务管理 " + controlLink);
// 根据特定控制环节添加相关关键词
if (controlLink.contains("岗位")) {
queries.add("岗位职责 不相容职务分离");
queries.add("岗位设置 职责划分");
}
if (controlLink.contains("授权审批")) {
queries.add("授权审批流程 审批权限");
queries.add("财务管理授权");
}
if (controlLink.contains("重大事项")) {
queries.add("重大事项决策 集体决策");
queries.add("三重一大 财务管理");
}
if (controlLink.contains("会计")) {
queries.add("会计核算 会计档案");
queries.add("会计凭证 会计账簿");
}
if (controlLink.contains("信息系统")) {
queries.add("财务信息系统 数据备份");
queries.add("信息安全 用户管理");
}
if (controlLink.contains("风险")) {
queries.add("财务风险管理 风险识别");
queries.add("风险评估 风险应对");
}
if (controlLink.contains("内部审计")) {
queries.add("内审部门 审计监督");
queries.add("审计检查 审计报告");
}
if (controlLink.contains("反舞弊")) {
queries.add("财务舞弊 举报投诉");
queries.add("舞弊防范 举报保护");
}
return queries;
}
/**
* 构建完整的知识上下文
*/
private String buildCompleteKnowledgeContext(String controlLink, Map<String, List<String>> knowledgeSources, String history, String suggestion) {
StringBuilder context = new StringBuilder();
// 1. 单位层面财务管理内部控制测试要求
context.append("## 单位层面财务管理内部控制测试要求 - ").append(controlLink).append("\n");
context.append("请基于以下知识生成").append(controlLink).append("相关的单位层面财务管理内部控制测试数据:\n\n");
context.append("1. 控制环节:").append(controlLink).append("\n");
context.append("2. 控制要求:").append(AuditContent8InternalControlConstants.CONTROL_REQUIREMENTS.get(controlLink)).append("\n");
context.append("3. 控制活动描述:").append(AuditContent8InternalControlConstants.CONTROL_ACTIVITIES.get(controlLink)).append("\n");
context.append("4. 控制职责岗位:").append(AuditContent8InternalControlConstants.CONTROL_POSITIONS.get(controlLink)).append("\n");
context.append("5. 测试步骤:\n");
AuditContent8InternalControlConstants.TEST_STEPS.get(controlLink).forEach(step ->
context.append(" ").append(step).append("\n"));
context.append("\n");
context.append("## 审计测试要求\n");
context.append("1. 基于测试步骤逐项检查,评估内部控制的有效性\n");
context.append("2. 检查证据必须具体到查阅的文件名称、内容、检查过程和发现的问题\n");
context.append("3. 测试结果必须基于充分证据严格判断:\n");
context.append(" - 通过:所有测试步骤均得到有效执行且证据充分\n");
context.append(" - 不通过:任一测试步骤未执行、执行不到位或证据不足\n");
context.append("4. 工作底稿索引必须填写实际存在的完整文件名\n");
context.append("5. 重点关注货币资金管理、财务报销、资产管理、物资采购等关键环节\n\n");
// 2. 数据格式要求
context.append("## 数据格式要求\n");
context.append("需要生成").append(controlLink).append("控制环节的内部控制测试数据:\n\n");
context.append("**重要:每个测试步骤必须单独生成一条记录**\n\n");
context.append("每条记录应包含以下字段:\n");
context.append("- controlLink控制环节固定值不要修改\n");
context.append("- controlRequirement控制要求固定值不要修改\n");
context.append("- controlActivity控制活动描述固定值不要修改\n");
context.append("- controlPosition控制职责岗位固定值不要修改\n");
context.append("- testSteps测试步骤**只包含当前步骤内容**,如\"1是否有制度规定\"\n");
context.append("- checkEvidence检查证据针对当前测试步骤的详细检查证据\n");
context.append("- testResult测试结果基于当前测试步骤的检查证据严格判断只有证据充分且完全符合要求才能判定为\"通过\",否则必须判定为\"不通过\"\n");
// context.append("- workPaperIndex工作底稿索引FileId实际存在的完整文件FileId确保能在文件夹中搜索到\n\n");
context.append("- workPaperIndex工作底稿索引文件名实际存在的完整文件名||FileUrl确保能在文件夹中搜索到\n\n");
context.append("**生成规则:**\n");
context.append("1. **每个测试步骤单独生成一条完整记录**\n");
context.append("2. 如果测试步骤中有多个小点123必须为每个小点生成独立记录\n");
context.append("3. 每条记录的检查证据必须专门针对该测试步骤\n");
context.append("4. 每条记录的测试结果必须基于该步骤的检查证据独立判断\n");
context.append("5. 控制环节、控制要求、控制活动描述、控制职责岗位字段在所有相关记录中保持相同\n\n");
context.append("**注意:**\n");
context.append("1. 检查证据必须详细描述:针对当前测试步骤查阅了哪些制度文件、检查了哪些业务凭证、访谈了哪些人员、发现了什么问题\n");
context.append("2. 测试结果判定必须严格,对于制度不健全、执行不到位、证据不充分的情况必须判定为\"不通过\"\n");
context.append("3. 工作底稿索引必须准确对应实际审计工作底稿文件名称,不能使用章节标题\n");
context.append("4. 审计检查可采用:符合性测试、穿行测试、抽样测试、观察询问、文档查阅等方法\n");
context.append("5. 重点关注内部控制制度的建立健全性和执行的有效性\n\n");
// 3. 审计测试方法参考
context.append("## 审计测试方法参考\n");
context.append("审计时可采用的测试方法:\n");
TEST_METHODS.forEach(method -> context.append("- ").append(method).append("\n"));
context.append("\n");
// 4. 历史内容
if (StrUtil.isNotBlank(history)) {
context.append("## 历史生成内容\n");
context.append("以下是之前生成的内容,请基于此进行优化:\n");
context.append(history).append("\n\n");
}
// 5. 用户建议
if (StrUtil.isNotBlank(suggestion)) {
context.append("## 用户优化建议\n");
context.append("请根据以下建议对生成内容进行调整:\n");
context.append(suggestion).append("\n\n");
}
// 6. 企业单位知识
if (!knowledgeSources.get("enterprise").isEmpty()) {
context.append("## 企业单位知识\n");
knowledgeSources.get("enterprise").forEach(knowledge ->
context.append(knowledge).append("\n"));
context.append("\n");
}
// 7. 法律法规知识
if (!knowledgeSources.get("regulation").isEmpty()) {
context.append("## 法律法规知识\n");
knowledgeSources.get("regulation").forEach(knowledge ->
context.append(knowledge).append("\n"));
context.append("\n");
}
// 8. 审计案例知识
if (!knowledgeSources.get("auditCase").isEmpty()) {
context.append("## 审计案例知识\n");
knowledgeSources.get("auditCase").forEach(knowledge ->
context.append(knowledge).append("\n"));
}
return context.toString();
}
/**
* 内部控制相关性比较器
*/
private int internalControlComparator(String reg1, String reg2) {
int score1 = calculateInternalControlRelevanceScore(reg1);
int score2 = calculateInternalControlRelevanceScore(reg2);
return Integer.compare(score2, score1);
}
/**
* 计算内部控制相关性分数
*/
private int calculateInternalControlRelevanceScore(String content) {
return AuditContent8InternalControlConstants.KEYWORD_WEIGHTS.entrySet().stream()
.filter(entry -> content.contains(entry.getKey()))
.mapToInt(Map.Entry::getValue)
.sum();
}
private int getLimitBySourceType(String sourceType) {
switch (sourceType) {
case "enterprise": return 120;
case "regulation": return 100;
case "auditCase": return 80;
default: return 50;
}
}
}

View File

@@ -0,0 +1,563 @@
package com.gxwebsoft.ai.service.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.ai.constants.AuditContent9PersonnelConstants;
import com.gxwebsoft.ai.service.AuditContent9PersonnelService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import cn.hutool.core.util.StrUtil;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
@Slf4j
@Service
public class AuditContent9PersonnelServiceImpl extends AbstractAuditContentService implements AuditContent9PersonnelService {
private static final String DIFY_WORKFLOW_TOKEN = "Bearer app-fmGhYITVQVAHaY3GJYonIGPA";
private static final String DIFY_WORKFLOW_TOKEN_EXT = "Bearer app-olBqOrzi1IQCWyDqthME6SYG";
@Override
public JSONObject generatePersonnelTableData(String kbIds, String libraryKbIds, String projectLibrary,
String userName, String history, String suggestion) {
log.info("开始生成人员编制管理审计表数据");
long startTime = System.currentTimeMillis();
try {
// 异步并行处理每个审计内容7个大项
Map<String, CompletableFuture<JSONArray>> futures = new HashMap<>();
for (String auditContent : AuditContent9PersonnelConstants.AUDIT_CONTENTS) {
futures.put(auditContent, CompletableFuture.supplyAsync(() ->
generateAuditContentData(auditContent, kbIds, libraryKbIds, projectLibrary,
userName, history, suggestion)
));
}
// 等待所有异步任务完成
CompletableFuture.allOf(futures.values().toArray(new CompletableFuture[0])).join();
// 合并所有结果
JSONArray allData = new JSONArray();
int index = 1;
for (String auditContent : AuditContent9PersonnelConstants.AUDIT_CONTENTS) {
JSONArray contentData = futures.get(auditContent).get();
if (contentData != null) {
for (int i = 0; i < contentData.size(); i++) {
JSONObject item = contentData.getJSONObject(i);
item.put("index", index++);
allData.add(item);
}
}
}
log.info("人员编制管理审计表生成完成 - 记录数: {}, 耗时: {}ms",
allData.size(), System.currentTimeMillis() - startTime);
return buildSuccessResponse(allData, startTime, "personnel_establishment_audit");
} catch (Exception e) {
log.error("生成人员编制管理审计表失败", e);
return buildErrorResponse("生成失败: " + e.getMessage());
}
}
/**
* 生成单个审计内容(大项)下的所有子项数据
*/
private JSONArray generateAuditContentData(String auditContent, String kbIds, String libraryKbIds,
String projectLibrary, String userName,
String history, String suggestion) {
JSONArray results = new JSONArray();
List<AuditContent9PersonnelConstants.AuditSubContent> subContents =
AuditContent9PersonnelConstants.AUDIT_SUB_CONTENTS.get(auditContent);
if (subContents == null || subContents.isEmpty()) {
return results;
}
// 为该审计内容检索相关知识
Map<String, List<String>> knowledgeSources = retrieveKnowledgeForAuditContent(
auditContent, subContents, kbIds, libraryKbIds, projectLibrary
);
// 处理每个子项
for (AuditContent9PersonnelConstants.AuditSubContent subContent : subContents) {
try {
JSONArray subResult = generateSubItemData(auditContent, subContent, knowledgeSources,
userName, history, suggestion);
if (subResult != null && !subResult.isEmpty()) {
results.addAll(subResult);
}
} catch (Exception e) {
log.error("处理子项失败: {} - {}", auditContent, subContent.getAuditTarget(), e);
}
}
return results;
}
/**
* 为审计内容检索相关知识
*/
private Map<String, List<String>> retrieveKnowledgeForAuditContent(
String auditContent, List<AuditContent9PersonnelConstants.AuditSubContent> subContents,
String kbIds, String libraryKbIds, String projectLibrary) {
Map<String, List<String>> knowledgeSources = new HashMap<>();
knowledgeSources.put("enterprise", new ArrayList<>());
knowledgeSources.put("regulation", new ArrayList<>());
knowledgeSources.put("auditCase", new ArrayList<>());
// 构建该审计内容的关键词
List<String> keywords = buildAuditContentKeywords(auditContent, subContents);
// 检索企业知识库
if (StrUtil.isNotBlank(kbIds)) {
String[] kbIdArray = kbIds.split(",");
for (String kbId : kbIdArray) {
if (StrUtil.isNotBlank(kbId)) {
knowledgeSources.get("enterprise").addAll(
queryKnowledgeBase(kbId.trim(), keywords, 80)
);
}
}
}
// 检索法规库
if (StrUtil.isNotBlank(libraryKbIds)) {
String[] libIdArray = libraryKbIds.split(",");
for (String libId : libIdArray) {
if (StrUtil.isNotBlank(libId)) {
knowledgeSources.get("regulation").addAll(
queryKnowledgeBase(libId.trim(), keywords, 60)
);
}
}
}
// 检索案例库
if (StrUtil.isNotBlank(projectLibrary)) {
knowledgeSources.get("auditCase").addAll(
queryKnowledgeBase(projectLibrary, keywords, 40)
);
}
// 去重
knowledgeSources.forEach((key, list) -> {
List<String> processed = list.stream()
.distinct()
// .sorted(this::keywordRelevanceComparator)
// .limit(getLimitBySourceType(key))
.collect(Collectors.toList());
knowledgeSources.put(key, processed);
});
return knowledgeSources;
}
/**
* 构建审计内容关键词
*/
private List<String> buildAuditContentKeywords(String auditContent,
List<AuditContent9PersonnelConstants.AuditSubContent> subContents) {
List<String> keywords = new ArrayList<>();
keywords.add(auditContent);
// 添加审计内容相关的关键词
if (auditContent.contains("劳务派遣")) {
keywords.addAll(Arrays.asList("劳务派遣", "派遣工", "同工同酬", "三性标准"));
} else if (auditContent.contains("外包")) {
keywords.addAll(Arrays.asList("劳务外包", "外包合同", "假外包真派遣"));
} else if (auditContent.contains("人员经费")) {
keywords.addAll(Arrays.asList("工资总额", "福利费", "劳务费"));
keywords.addAll(Arrays.asList(
"工资总额", "福利费", "劳务费",
"补贴", "慰问", "福利",
"节日", "生日", "体检",
"食堂", "交通补贴", "通讯补贴",
"误餐补贴", "职工福利", "员工福利",
"防暑降温", "取暖费", "劳保用品"
));
} else if (auditContent.contains("借用人员")) {
keywords.addAll(Arrays.asList("借调", "借用人员", "借调程序"));
} else if (auditContent.contains("绩效管理")) {
keywords.addAll(Arrays.asList("绩效考核", "绩效管理", "绩效体系"));
} else if (auditContent.contains("机构编制")) {
keywords.addAll(Arrays.asList("机构编制", "三定方案", "编制审批", "领导职数"));
} else if (auditContent.contains("预算编制")) {
keywords.addAll(Arrays.asList("预算编制", "人员经费预算", "预算执行"));
}
// 添加所有子项的审计目标作为关键词
for (AuditContent9PersonnelConstants.AuditSubContent subContent : subContents) {
keywords.add(subContent.getAuditTarget());
}
return keywords.stream().distinct().collect(Collectors.toList());
}
/**
* 生成子项数据
*/
private JSONArray generateSubItemData(String auditContent,
AuditContent9PersonnelConstants.AuditSubContent subContent,
Map<String, List<String>> knowledgeSources,
String userName, String history, String suggestion) {
try {
JSONArray ext = new JSONArray();
String updatedHistory = history; // 使用新变量避免修改入参
// 检查是否是福利费列支范围检查子项
String extSubContent = AuditContent9PersonnelConstants.AUDIT_SUB_CONTENTS.get(AuditContent9PersonnelConstants.AUDIT_CONTENTS[2]).get(1).getAuditTarget();
if (subContent.getAuditTarget().equals(extSubContent)) {
// 生成扩展数据(福利费明细清单)
String contextExt = buildSubItemContextExt(auditContent, subContent, knowledgeSources, history, suggestion);
JSONObject requestBodyExt = buildWorkflowRequest(contextExt, userName);
ext = callWorkflow(DIFY_WORKFLOW_URL, DIFY_WORKFLOW_TOKEN_EXT, requestBodyExt, auditContent + "-" + subContent.getAuditTarget());
// 更新历史内容(不影响原始入参)
if (StrUtil.isNotBlank(history)) {
updatedHistory = history + "\n《福利费超范围支出明细清单》" + ext.toJSONString();
}
}
// 构建主上下文
String context = buildSubItemContext(auditContent, subContent, knowledgeSources, updatedHistory, suggestion);
// 调用Dify工作流
JSONObject requestBody = buildWorkflowRequest(context, userName);
JSONArray result = callWorkflow(DIFY_WORKFLOW_URL, DIFY_WORKFLOW_TOKEN, requestBody, auditContent + "-" + subContent.getAuditTarget());
// 处理返回结果
return processSubItemResult(result, auditContent, subContent, ext);
} catch (Exception e) {
log.error("生成子项数据失败: {} - {}", auditContent, subContent.getAuditTarget(), e);
return new JSONArray();
}
}
/**
* 构建子项上下文
*/
private String buildSubItemContext(String auditContent,
AuditContent9PersonnelConstants.AuditSubContent subContent,
Map<String, List<String>> knowledgeSources,
String history, String suggestion) {
StringBuilder context = new StringBuilder();
context.append("## 审计任务\n");
context.append("生成人员编制管理审计数据\n\n");
context.append("## 审计要求\n");
context.append("1. 审计内容:").append(auditContent).append("\n");
context.append("2. 审计目标:").append(subContent.getAuditTarget()).append("\n");
context.append("3. 审计证据:").append(subContent.getAuditEvidence()).append("\n");
context.append("4. 审计方法:").append(subContent.getAiTestContent()).append("\n");
context.append("5. 制度依据:").append(subContent.getRegulationBasis()).append("\n\n");
context.append("## 生成结果要求\n");
context.append(subContent.getGenerationResult()).append("\n\n");
context.append("## 重要要求\n");
context.append("1. 必须使用具体单位名称,禁止使用'XX单位'等模糊词汇\n");
context.append("2. 审计记录必须具体,包含文件名称、数据、人员等详细信息\n");
context.append("3. 重点关注问题发现,提供具体证据和建议\n");
context.append("4. **如果在上传资料中找不到相应证据/凭证,不要直接判定违反规定,应说明'未找到相关材料,无法判定'**\n");
context.append("5. **除了审计证据中列出的资料清单,还需主动查找上传材料中其他涉及审计内容和目标的材料**\n");
context.append("6. **合同与主体公司不相关时,不应判定在主体公司责任范围内,需明确区分责任主体**\n\n");
context.append("## 审计判断原则\n");
context.append("1. **证据不足原则**:当缺乏关键证据时,不做出违规判定\n");
context.append("2. **主动查找原则**:不局限于给定清单,主动识别所有相关材料\n");
context.append("3. **责任主体原则**:明确区分合同主体,不扩大责任范围\n\n");
context.append("## 返回格式\n");
context.append("返回JSON数组每条记录包含以下字段\n");
context.append("- auditContent固定为'").append(auditContent).append("'\n");
context.append("- auditTarget固定为'").append(subContent.getAuditTarget()).append("'\n");
context.append("- auditEvidence固定为'").append(subContent.getAuditEvidence()).append("'\n");
context.append("- generationResult审计发现和结论\n");
// context.append("- workPaperIndex工作底稿索引具体的文件FileId数组\n\n");
context.append("- workPaperIndex工作底稿索引具体的文件[\"实际存在的完整文件名1||FileUrl1\", \"实际存在的完整文件名2||FileUrl2\", ...]数组\n\n");
context.append("## generationResult格式\n");
context.append("标题:在审计期间,[具体单位名称]存在[具体问题](如有充分证据)\n");
context.append("或:在审计期间,[具体单位名称]未提供充分证据证明[审计事项]\n\n");
context.append("审计记录:\n");
context.append("1. 核查的具体文件和内容\n");
context.append("2. **注明是否找到审计证据清单中要求的材料**\n");
context.append("3. **注明是否发现其他相关材料**\n");
context.append("4. **注明合同主体是否与审计单位一致**\n\n");
context.append("审计发现:\n");
context.append("1. 如有充分证据:上述行为构成[问题性质],违反了[相关规定]\n");
context.append("2. 如证据不足:未找到相关材料,无法判定是否合规\n\n");
context.append("定性依据:\n");
context.append("① [法规1];② [法规2]\n");
context.append("**如无违规,可不填写定性依据**\n\n");
context.append("处理建议:\n");
context.append("1. [建议1]2. [建议2]\n\n");
context.append("附件:\n");
context.append("- [实际查阅的文件1]\n");
context.append("- [实际查阅的文件2]\n\n");
// 添加历史内容
if (StrUtil.isNotBlank(history)) {
context.append("## 历史内容\n");
context.append(history).append("\n\n");
}
// 添加用户建议
if (StrUtil.isNotBlank(suggestion)) {
context.append("## 用户建议\n");
context.append(suggestion).append("\n\n");
}
// 添加相关知识
if (!knowledgeSources.get("enterprise").isEmpty()) {
context.append("## 企业信息\n");
knowledgeSources.get("enterprise").forEach(info ->
context.append(info).append("\n"));
}
if (!knowledgeSources.get("regulation").isEmpty()) {
context.append("## 法规信息\n");
knowledgeSources.get("regulation").forEach(info ->
context.append(info).append("\n"));
}
if (!knowledgeSources.get("auditCase").isEmpty()) {
context.append("## 案例信息\n");
knowledgeSources.get("auditCase").forEach(info ->
context.append(info).append("\n"));
}
return context.toString();
}
/**
* 构建福利费超范围支出明细清单的上下文
*/
private String buildSubItemContextExt(String auditContent,
AuditContent9PersonnelConstants.AuditSubContent subContent,
Map<String, List<String>> knowledgeSources,
String history, String suggestion) {
StringBuilder context = new StringBuilder();
context.append("## 审计任务\n");
context.append("生成福利费支出明细清单数据\n\n");
context.append("## 审计要求\n");
context.append("1. 审计内容:").append(auditContent).append("\n");
context.append("2. 审计目标:").append(subContent.getAuditTarget()).append("\n");
context.append("3. 审计证据:").append(subContent.getAuditEvidence()).append("\n");
context.append("4. 审计方法:").append(subContent.getAiTestContent()).append("\n");
context.append("5. 制度依据:").append(subContent.getRegulationBasis()).append("\n\n");
context.append("## 生成结果要求\n");
context.append("生成福利费支出明细清单,包括所有福利费支出的详细记录\n\n");
context.append("## 重要要求\n");
context.append("1. **积极查找知识库中所有福利费相关支出记录**,包括但不限于:\n");
context.append(" - 福利费支出凭证、报销单\n");
context.append(" - 工资表中的福利费项目\n");
context.append(" - 补贴发放记录、福利发放记录\n");
context.append(" - 节日慰问、职工福利相关支出\n");
context.append(" - 职工食堂、交通补贴、通讯补贴等\n");
context.append("2. **即使信息不完整也要尽可能记录**\n");
context.append(" - 如果凭证号不明确,可以使用'未知'或根据内容推断\n");
context.append(" - 如果日期不明确,可以合理推断或使用'审计期间'\n");
context.append(" - 如果金额不明确,可以根据上下文合理估计\n");
context.append("3. **允许合理推断**\n");
context.append(" - 根据支出用途推断款项性质\n");
context.append(" - 根据文件内容推断归属部门/人员\n");
context.append(" - 根据上下文补充缺失信息\n");
context.append("4. **优先使用实际信息**,只有在确实无法获取时才允许推断\n\n");
context.append("## 审计判断原则\n");
context.append("1. **积极查找原则**:尽可能查找所有可能的福利费相关支出\n");
context.append("2. **信息补充原则**:对不完整信息进行合理补充\n");
context.append("3. **分类识别原则**:识别以下类型的福利费支出:\n");
context.append(" - 职工福利发放(节日福利、生日福利等)\n");
context.append(" - 职工补贴(交通、通讯、餐饮补贴等)\n");
context.append(" - 职工活动支出(文体活动、旅游活动等)\n");
context.append(" - 职工慰问支出(生病慰问、困难补助等)\n");
context.append(" - 其他福利性支出\n");
context.append("4. **合规性初步判断**\n");
context.append(" - 对于明显超出常规福利费范围的项目进行标注\n");
context.append(" - 对于可能违规的支出进行初步分析\n\n");
context.append("## 审计步骤\n");
context.append("1. 第一步:全面搜索知识库中所有福利费相关支出\n");
context.append("2. 第二步:尽可能多地提取福利费支出记录\n");
context.append("3. 第三步:对每条记录进行信息补充和整理\n");
context.append("4. 第四步:初步分析支出合规性\n");
context.append("5. 第五步:生成完整的福利费支出明细清单\n\n");
context.append("## 返回格式\n");
context.append("返回JSON数组每条记录必须包含以下字段严格按照字段名和格式\n");
context.append("- **index**序号数字从1开始自动递增\n");
context.append("- **voucher**:凭证号(字符串,优先使用实际凭证号,如无法获取可用'未知'或合理推断)\n");
context.append("- **expenditureDate**支出日期字符串格式YYYY-MM-DD如无法获取可用'审计期间'\n");
context.append("- **usage**:用途(字符串,详细说明支出用途)\n");
context.append("- **payee**:收款方(字符串,完整收款方名称,如无法获取可用'相关单位/个人'\n");
context.append("- **amount**金额数字单位保留两位小数如无法获取可用0.00\n");
context.append("- **belongTo**:归属部门/人员(字符串,明确责任主体,如无法获取可用'相关部门'\n");
context.append("- **natureDesc**:款项性质说明(字符串,详细说明款项性质和目的)\n");
context.append("- **violationDesc**:违规说明(字符串,如果不明确是否违规,可留空或写'待进一步核实'\n\n");
context.append("## 重点关注福利费支出类型\n");
context.append("1. **常规福利费**:节日慰问品、职工生日福利、职工体检等\n");
context.append("2. **职工补贴**:交通补贴、通讯补贴、误餐补贴、住房补贴等\n");
context.append("3. **职工活动**:文体活动、旅游活动、团建活动等\n");
context.append("4. **职工慰问**:生病慰问、困难补助、婚丧嫁娶慰问等\n");
context.append("5. **职工福利设施**:职工食堂、活动室、休息室等支出\n");
context.append("6. **其他福利**:防暑降温费、取暖费、劳保用品等\n\n");
context.append("## 如何从知识库中提取信息\n");
context.append("1. **搜索关键词**:福利费、补贴、慰问、福利、节日、生日、体检、活动、食堂、交通、通讯、餐饮\n");
context.append("2. **文件类型**:财务凭证、报销单、工资表、发放记录、会议纪要、审批单\n");
context.append("3. **提取策略**\n");
context.append(" - 从财务凭证中提取凭证号、金额、日期\n");
context.append(" - 从报销单中提取用途、收款方\n");
context.append(" - 从审批记录中提取归属部门\n");
context.append(" - 综合分析文件内容推断款项性质\n\n");
context.append("## 特殊处理说明\n");
context.append("1. **如果知识库中没有直接福利费凭证**\n");
context.append(" - 可以查找相关会议纪要中提到的福利费支出\n");
context.append(" - 可以查找工资表中的福利费项目\n");
context.append(" - 可以查找报销单中的福利相关支出\n");
context.append("2. **信息补充方法**\n");
context.append(" - 通过文件名推断凭证号\n");
context.append(" - 通过文件创建日期推断支出日期\n");
context.append(" - 通过上下文推断款项用途\n");
context.append("3. **生成多条记录**\n");
context.append(" - 一条福利费支出凭证可以生成一条记录\n");
context.append(" - 一份工资表中的福利费项目可以生成多条记录\n");
context.append(" - 一份会议纪要中的多项福利费决定可以生成多条记录\n\n");
// 添加历史内容
if (StrUtil.isNotBlank(history)) {
context.append("## 历史内容\n");
context.append(history).append("\n\n");
}
// 添加用户建议
if (StrUtil.isNotBlank(suggestion)) {
context.append("## 用户建议\n");
context.append(suggestion).append("\n\n");
}
// 添加相关知识
if (!knowledgeSources.get("enterprise").isEmpty()) {
context.append("## 企业财务信息\n");
context.append("请仔细查找以下内容中的福利费相关信息:\n");
knowledgeSources.get("enterprise").forEach(info -> {
context.append(info).append("\n");
});
}
// if (!knowledgeSources.get("regulation").isEmpty()) {
// context.append("## 法规信息\n");
// context.append("参考以下福利费管理规定:\n");
// knowledgeSources.get("regulation").forEach(info -> {
// context.append(info).append("\n");
// });
// }
// if (!knowledgeSources.get("auditCase").isEmpty()) {
// context.append("## 审计案例信息\n");
// context.append("参考以下福利费审计案例:\n");
// knowledgeSources.get("auditCase").forEach(info -> {
// context.append(info).append("\n");
// });
// }
context.append("\n## 最终要求\n");
context.append("请基于以上信息和知识库内容,尽可能多地生成福利费支出明细清单数据。\n");
context.append("要求尽可能真实、完整,即使信息不完整也要尽量生成记录。\n");
context.append("如果知识库中没有任何福利费相关信息,请返回空数组。\n");
context.append("如果有福利费相关信息请至少生成3-5条记录尽可能多地提取信息。\n");
return context.toString();
}
/**
* 处理子项返回结果
*/
private JSONArray processSubItemResult(JSONArray result, String auditContent,
AuditContent9PersonnelConstants.AuditSubContent subContent, JSONArray ext) {
if (result == null || result.isEmpty()) {
JSONArray defaultResult = new JSONArray();
JSONObject defaultItem = new JSONObject();
defaultItem.put("auditContent", auditContent);
defaultItem.put("auditTarget", subContent.getAuditTarget());
defaultItem.put("auditEvidence", subContent.getAuditEvidence());
defaultItem.put("generationResult", "审计数据待生成");
defaultItem.put("workPaperIndex", new JSONArray());
defaultResult.add(defaultItem);
return defaultResult;
}
// 检查是否是福利费列支范围检查子项
String extSubContent = AuditContent9PersonnelConstants.AUDIT_SUB_CONTENTS.get(AuditContent9PersonnelConstants.AUDIT_CONTENTS[2]).get(1).getAuditTarget();
if (ext.size() > 0 && subContent.getAuditTarget().equals(extSubContent)) {
// 将扩展数据添加到结果中
JSONObject firstItem = result.getJSONObject(0);
firstItem.put("ext", ext);
}
return result;
}
// /**
// * 关键词相关性比较器
// */
// private int keywordRelevanceComparator(String content1, String content2) {
// int score1 = calculateKeywordScore(content1);
// int score2 = calculateKeywordScore(content2);
// return Integer.compare(score2, score1);
// }
//
// /**
// * 计算关键词得分
// */
// private int calculateKeywordScore(String content) {
// int score = 0;
// for (Map.Entry<String, Integer> entry : AuditContent9PersonnelConstants.KEYWORD_WEIGHTS.entrySet()) {
// if (content.contains(entry.getKey())) {
// score += entry.getValue();
// }
// }
// return score;
// }
//
// /**
// * 获取不同来源的限制条数
// */
// private int getLimitBySourceType(String sourceType) {
// switch (sourceType) {
// case "enterprise": return 80;
// case "regulation": return 60;
// case "auditCase": return 40;
// default: return 30;
// }
// }
}

View File

@@ -0,0 +1,204 @@
package com.gxwebsoft.ai.service.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.ai.dto.AuditEvidenceRequest;
import com.gxwebsoft.ai.service.AuditEvidenceService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import java.util.Date;
@Slf4j
@Service
public class AuditEvidenceServiceImpl implements AuditEvidenceService {
// Dify工作流配置
private static final String DIFY_WORKFLOW_URL = "http://1.14.159.185:8180/v1/workflows/run";
private static final String DIFY_WORKFLOW_TOKEN = "Bearer app-DEhvF537rQfy6MvH9KeBKUVj";
@Override
public JSONObject generateAuditEvidence(AuditEvidenceRequest request) {
log.info("开始生成审计取证单 - 用户: {}, 项目: {}", request.getUserName(), request.getProjectName());
long startTime = System.currentTimeMillis();
try {
// 1. 构建完整上下文
String knowledgeContext = buildCompleteContext(request);
// 2. 构建工作流请求
JSONObject requestBody = buildWorkflowRequest(knowledgeContext, request.getUserName());
// 3. 调用Dify工作流
JSONObject result = callWorkflow(requestBody, "审计取证单");
// 4. 添加处理时间等信息
result.put("success", true);
result.put("processing_time", (System.currentTimeMillis() - startTime) + "ms");
result.put("generated_time", new Date().toString());
log.info("审计取证单生成成功 - 处理时间: {}ms", (System.currentTimeMillis() - startTime));
return result;
} catch (Exception e) {
log.error("生成审计取证单失败", e);
return buildErrorResponse("生成审计取证单失败: " + e.getMessage());
}
}
/**
* 构建完整上下文
*/
private String buildCompleteContext(AuditEvidenceRequest request) {
StringBuilder context = new StringBuilder();
// 1. 审计取证单生成要求
context.append("## 审计取证单生成要求\n");
context.append("请基于以下信息生成一份完整的审计取证单。审计取证单是审计工作中的重要文书,用于记录审计发现的问题、事实依据、处理建议等。\n\n");
// 2. 输出格式要求
context.append("## 输出格式要求\n");
context.append("请严格按照以下JSON格式输出不要包含任何额外文本\n");
context.append("{\n");
// context.append(" \"caseIndex\": \"案件编号,如审计-[2024]-001\",\n");
// context.append(" \"projectName\": \"具体项目名称\",\n");
context.append(" \"auditedTarget\": \"被审计单位或个人\",\n");
context.append(" \"auditMatter\": \"审计事项描述\",\n");
context.append(" \"summaryTitle\": \"核心问题标题\",\n");
context.append(" \"auditRecord\": \"客观的审计核查事实记录,包括时间、地点、主体、行为、数据等\",\n");
context.append(" \"auditFinding\": \"审计发现的具体问题、性质及影响\",\n");
context.append(" \"evidenceBasis\": \"定性依据,引用法规、制度或合同条款\",\n");
context.append(" \"handling\": \"拟采取的处理措施\",\n");
context.append(" \"suggestion\": \"改进或整改建议\",\n");
context.append(" \"attachment\": \"列示随附的证明材料只出现材料中文名称不要出现FileId不要出现网站链接\",\n");
context.append(" \"auditors\": \"审计人员姓名\",\n");
context.append(" \"compileDate\": \"编制日期格式YYYY-MM-DD\",\n");
context.append(" \"providerOpinion\": \"证据提供单位或个人意见\",\n");
context.append(" \"providerDate\": \"证据提供日期格式YYYY-MM-DD\",\n");
context.append(" \"attachmentPages\": \"附件页数2\",\n");
context.append(" \"feedbackDeadline\": \"反馈期限5个工作日内\"\n");
context.append("}\n");
// 3. 字段内容要求
context.append("## 字段内容具体要求\n");
context.append("1. **审计记录**:客观记录审计核查的具体事实,包括时间、地点、主体、行为、数据等,避免主观评价。\n");
context.append("2. **审计发现**:基于审计记录提出具体问题性质,先事实后定性,避免夸大。\n");
context.append("3. **定性依据**必须引用具体的法规、制度或合同条款格式如根据《XX法》第XX条规定...\n");
context.append("4. **处理措施**:针对发现的问题提出具体的处理措施,要有可操作性。\n");
context.append("5. **建议**:针对问题根源提出改进或整改建议,要具体可行。\n");
context.append("6. **日期**所有日期必须使用YYYY-MM-DD格式。\n\n");
// 4. 用户提供的基础信息
if (StrUtil.isNotBlank(request.getProjectName()) ||
StrUtil.isNotBlank(request.getAuditedTarget()) ||
StrUtil.isNotBlank(request.getAuditMatter())) {
context.append("## 用户提供的基础信息\n");
if (StrUtil.isNotBlank(request.getProjectName())) {
context.append("- 项目名称:").append(request.getProjectName()).append("\n");
}
if (StrUtil.isNotBlank(request.getAuditedTarget())) {
context.append("- 被审计单位/个人:").append(request.getAuditedTarget()).append("\n");
}
if (StrUtil.isNotBlank(request.getAuditMatter())) {
context.append("- 审计事项:").append(request.getAuditMatter()).append("\n");
}
if (StrUtil.isNotBlank(request.getSummaryTitle())) {
context.append("- 标题:").append(request.getSummaryTitle()).append("\n");
}
context.append("\n");
}
// 5. 历史内容(如果存在)
if (StrUtil.isNotBlank(request.getHistory())) {
context.append("## 历史内容参考\n");
context.append("以下是与本次审计相关的历史内容,请参考但不完全照搬:\n");
context.append(request.getHistory()).append("\n\n");
}
// 6. 额外要求
context.append("## 额外要求\n");
context.append("1. 内容必须真实、准确、完整,符合审计文书规范\n");
context.append("2. 语言表述要严谨、客观、规范\n");
context.append("3. 各字段内容要相互衔接,逻辑清晰\n");
context.append("4. 如果某些信息不明确,请根据审计常规进行合理补充\n");
log.debug("构建的上下文长度: {}", context.length());
return context.toString();
}
/**
* 构建工作流请求
*/
private JSONObject buildWorkflowRequest(String knowledge, String userName) {
JSONObject requestBody = new JSONObject();
JSONObject inputs = new JSONObject();
inputs.put("knowledge", knowledge);
requestBody.put("inputs", inputs);
requestBody.put("response_mode", "blocking");
requestBody.put("user", userName);
requestBody.put("timeout", 300); // 5分钟超时
return requestBody;
}
/**
* 调用工作流
*/
private JSONObject callWorkflow(JSONObject requestBody, String workflowName) {
try {
log.info("调用{}工作流,请求体长度: {}", workflowName, requestBody.toString().length());
String result = HttpUtil.createPost(DIFY_WORKFLOW_URL)
.header("Authorization", DIFY_WORKFLOW_TOKEN)
.header("Content-Type", "application/json")
.body(requestBody.toString())
.timeout(5 * 60 * 1000) // 5分钟
.execute()
.body();
log.info("{}工作流返回结果长度: {}", workflowName, result.length());
JSONObject jsonResponse = JSONObject.parseObject(result);
// 提取输出文本
String outputText = jsonResponse.getJSONObject("data")
.getJSONObject("outputs")
.getString("result");
if (StrUtil.isBlank(outputText)) {
log.warn("{}工作流返回结果为空", workflowName);
return new JSONObject();
}
// 解析为JSON对象
JSONObject auditEvidence = JSONObject.parseObject(outputText);
log.info("成功解析{}工作流返回数据", workflowName);
return auditEvidence;
} catch (Exception e) {
log.error("调用{}工作流失败", workflowName, e);
throw new RuntimeException("调用" + workflowName + "工作流失败: " + e.getMessage(), e);
}
}
/**
* 构建错误响应
*/
private JSONObject buildErrorResponse(String errorMessage) {
JSONObject result = new JSONObject();
result.put("success", false);
result.put("error", errorMessage);
result.put("timestamp", System.currentTimeMillis());
return result;
}
}

View File

@@ -9,7 +9,7 @@ import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.ai.config.KnowledgeBaseConfig;
import com.gxwebsoft.ai.factory.KnowledgeBaseClientFactory;
import com.gxwebsoft.ai.service.AuditReportService;
import com.gxwebsoft.ai.util.KnowledgeBaseUtil;
import com.gxwebsoft.ai.util.AiCloudKnowledgeBaseUtil;
import com.gxwebsoft.pwl.entity.PwlProjectLibrary;
import com.gxwebsoft.pwl.service.PwlProjectLibraryService;
@@ -319,7 +319,7 @@ public class AuditReportServiceImpl implements AuditReportService {
try {
Client client = clientFactory.createClient();
RetrieveResponse resp = KnowledgeBaseUtil.retrieveIndex(client, workspaceId, kbId, query);
RetrieveResponse resp = AiCloudKnowledgeBaseUtil.retrieveIndex(client, workspaceId, kbId, query);
if (resp.getBody() != null && resp.getBody().getData() != null
&& resp.getBody().getData().getNodes() != null) {

View File

@@ -1,6 +1,7 @@
package com.gxwebsoft.ai.service.impl;
import com.aliyun.bailian20231229.Client;
import com.aliyun.bailian20231229.models.AddFileResponse;
import com.aliyun.bailian20231229.models.CreateIndexResponse;
import com.aliyun.bailian20231229.models.DeleteIndexDocumentResponse;
import com.aliyun.bailian20231229.models.DeleteIndexResponse;
@@ -13,9 +14,8 @@ import com.gxwebsoft.ai.constants.KnowledgeBaseConstants;
import com.gxwebsoft.ai.dto.KnowledgeBaseRequest;
import com.gxwebsoft.ai.factory.KnowledgeBaseClientFactory;
import com.gxwebsoft.ai.service.KnowledgeBaseService;
import com.gxwebsoft.ai.util.AiCloudDataCenterUtil;
import com.gxwebsoft.ai.util.AiCloudKnowledgeBaseUtil;
import com.gxwebsoft.ai.util.KnowledgeBaseUploader;
import com.gxwebsoft.ai.util.KnowledgeBaseUtil;
import cn.hutool.core.util.StrUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
@@ -24,6 +24,7 @@ import org.springframework.web.multipart.MultipartFile;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashSet;
@@ -56,7 +57,7 @@ public class KnowledgeBaseServiceImpl implements KnowledgeBaseService {
try {
Client client = clientFactory.createClient();
RetrieveResponse resp = KnowledgeBaseUtil.retrieveIndex(client, workspaceId, indexId, searchQuery);
RetrieveResponse resp = AiCloudKnowledgeBaseUtil.retrieveIndex(client, workspaceId, indexId, searchQuery);
for (RetrieveResponseBodyDataNodes node : resp.getBody().getData().getNodes()) {
result.add(node.getText());
if (result.size() >= searchTopK) {
@@ -79,7 +80,7 @@ public class KnowledgeBaseServiceImpl implements KnowledgeBaseService {
}
Client client = clientFactory.createClient();
CreateIndexResponse indexResponse = KnowledgeBaseUtil.createIndex(client, workspaceId, companyCode, companyName);
CreateIndexResponse indexResponse = AiCloudKnowledgeBaseUtil.createIndex(client, workspaceId, companyCode, companyName);
return indexResponse.getBody().getData().getId();
} catch (Exception e) {
throw new RuntimeException("创建知识库失败: " + e.getMessage(), e);
@@ -97,7 +98,7 @@ public class KnowledgeBaseServiceImpl implements KnowledgeBaseService {
String workspaceId = config.getWorkspaceId();
try {
Client client = clientFactory.createClient();
ListIndicesResponse indicesResponse = KnowledgeBaseUtil.listIndices(client, workspaceId);
ListIndicesResponse indicesResponse = AiCloudKnowledgeBaseUtil.listIndices(client, workspaceId);
return indicesResponse.getBody().getData().getIndices().stream()
.anyMatch(index -> companyCode.equals(index.getName()));
@@ -111,7 +112,7 @@ public class KnowledgeBaseServiceImpl implements KnowledgeBaseService {
String workspaceId = config.getWorkspaceId();
try {
Client client = clientFactory.createClient();
ListIndicesResponse indicesResponse = KnowledgeBaseUtil.listIndices(client, workspaceId);
ListIndicesResponse indicesResponse = AiCloudKnowledgeBaseUtil.listIndices(client, workspaceId);
return indicesResponse.getBody().getData().getIndices().stream()
.filter(index -> companyCode.equals(index.getName()))
@@ -129,7 +130,7 @@ public class KnowledgeBaseServiceImpl implements KnowledgeBaseService {
String workspaceId = config.getWorkspaceId();
try {
Client client = clientFactory.createClient();
ListIndexDocumentsResponse indexDocumentsResponse = KnowledgeBaseUtil.listIndexDocuments(client, workspaceId, kbId, pageSize, pageNumber);
ListIndexDocumentsResponse indexDocumentsResponse = AiCloudKnowledgeBaseUtil.listIndexDocuments(client, workspaceId, kbId, pageSize, pageNumber);
ret.put("data", indexDocumentsResponse.getBody().getData().getDocuments());
ret.put("total", indexDocumentsResponse.getBody().getData().getTotalCount());
} catch (Exception e) {
@@ -143,7 +144,7 @@ public class KnowledgeBaseServiceImpl implements KnowledgeBaseService {
String workspaceId = config.getWorkspaceId();
try {
Client client = clientFactory.createClient();
DeleteIndexResponse indexDocumentResponse = KnowledgeBaseUtil.deleteIndex(client, workspaceId, kbId);
DeleteIndexResponse indexDocumentResponse = AiCloudKnowledgeBaseUtil.deleteIndex(client, workspaceId, kbId);
return indexDocumentResponse.getBody().getSuccess();
} catch (Exception e) {
throw new RuntimeException("删除知识库失败: " + e.getMessage(), e);
@@ -156,7 +157,10 @@ public class KnowledgeBaseServiceImpl implements KnowledgeBaseService {
List<String> ids = StrUtil.splitTrim(fileIds, ",");
try {
Client client = clientFactory.createClient();
DeleteIndexDocumentResponse indexDocumentResponse = KnowledgeBaseUtil.deleteIndexDocument(client, workspaceId, kbId, ids);
DeleteIndexDocumentResponse indexDocumentResponse = AiCloudKnowledgeBaseUtil.deleteIndexDocument(client, workspaceId, kbId, ids);
for(String id : ids) {
AiCloudKnowledgeBaseUtil.deleteAppDocument(client, workspaceId, id);
}
return indexDocumentResponse.getBody().getSuccess();
} catch (Exception e) {
throw new RuntimeException("删除知识库下的文档失败: " + e.getMessage(), e);
@@ -164,17 +168,24 @@ public class KnowledgeBaseServiceImpl implements KnowledgeBaseService {
}
@Override
public boolean uploadDocuments(String kbId, MultipartFile[] files) {
public List<String> uploadDocuments(String kbId, MultipartFile[] files) {
String workspaceId = config.getWorkspaceId();
int count = files.length;
try {
Client client = clientFactory.createClient();
List<String> fileIds = KnowledgeBaseUploader.uploadDocuments(client, workspaceId, kbId, files);
//上传切片完成后删除原文档(释放云空间)
for(String fileId : fileIds) {
KnowledgeBaseUtil.deleteAppDocument(client, workspaceId, fileId);
List<String> fileIds = new ArrayList<>();
for(MultipartFile file : files) {
AddFileResponse addFileResponse = AiCloudDataCenterUtil.uploadFile(client, workspaceId, "cate_28190570c20043d692897701d4547401_10377381", file);
String fileId = addFileResponse.getBody().getData().getFileId();
fileIds.add(fileId);
}
return !fileIds.isEmpty() && fileIds.size() == count;
// List<String> fileIds = AiCloudKnowledgeBaseUtil.uploadDocuments(client, workspaceId, kbId, files);
//上传切片完成后删除原文档(释放云空间)
// for(String fileId : fileIds) {
// AiCloudKnowledgeBaseUtil.deleteAppDocument(client, workspaceId, fileId);
// }
return fileIds;
} catch (Exception e) {
throw new RuntimeException("上传文档到知识库失败: " + e.getMessage(), e);
}
@@ -182,25 +193,28 @@ public class KnowledgeBaseServiceImpl implements KnowledgeBaseService {
@Async
@Override
public void submitDocuments(String kbId, String fileId) {
public boolean submitDocuments(String kbId, String fileId) {
String workspaceId = config.getWorkspaceId();
try {
Client client = clientFactory.createClient();
AiCloudKnowledgeBaseUtil.submitIndexAddDocumentsJob(client, workspaceId, kbId, fileId);
boolean result = AiCloudKnowledgeBaseUtil.submitIndexAddDocumentsJob(client, workspaceId, kbId, fileId).getBody().getSuccess();
return result;
} catch (Exception e) {
throw new RuntimeException("添加文档到知识库失败: " + e.getMessage(), e);
}
}
@Override
public void submitDocuments(String kbId, List<String> fileIds) {
public boolean submitDocuments(String kbId, List<String> fileIds) {
String workspaceId = config.getWorkspaceId();
boolean result = true;
try {
Client client = clientFactory.createClient();
AiCloudKnowledgeBaseUtil.submitIndexAddDocumentsJob(client, workspaceId, kbId, fileIds);
result = result && AiCloudKnowledgeBaseUtil.submitIndexAddDocumentsJob(client, workspaceId, kbId, fileIds).getBody().getSuccess();
} catch (Exception e) {
throw new RuntimeException("添加文档到知识库失败: " + e.getMessage(), e);
}
return result;
}

View File

@@ -15,7 +15,7 @@ import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
@@ -261,6 +261,11 @@ public class AiCloudDataCenterUtil {
String fileId = addFileResponse.getBody().getData().getFileId();
waitForFileParsing(client, workspaceId, fileId);
// fileId的UUID部分做为标签更新 file_df12ed21b7384353bd75868444c516ae_10377381 -> df12ed21b7384353bd75868444c516ae
String tag = StrUtil.subBetween(fileId, "_", "_").substring(0, 32);
updateFileTag(client, workspaceId, fileId, Arrays.asList(tag));
return addFileResponse;
}

View File

@@ -1,10 +1,12 @@
package com.gxwebsoft.ai.util;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.alibaba.fastjson.JSON;
import com.aliyun.bailian20231229.models.CreateIndexResponse;
import com.aliyun.bailian20231229.models.DeleteFileResponse;
import com.aliyun.bailian20231229.models.DeleteIndexDocumentResponse;
@@ -37,7 +39,36 @@ public class AiCloudKnowledgeBaseUtil {
RetrieveRequest retrieveRequest = new RetrieveRequest();
retrieveRequest.setIndexId(indexId);
retrieveRequest.setQuery(query);
retrieveRequest.setDenseSimilarityTopK(null);
retrieveRequest.setDenseSimilarityTopK(100);
retrieveRequest.setSparseSimilarityTopK(100);
retrieveRequest.setEnableReranking(false);//开启耗费巨量token
RuntimeOptions runtime = new RuntimeOptions();
return client.retrieveWithOptions(workspaceId, retrieveRequest, null, runtime);
}
/**
* 在指定的知识库中检索信息。
*
* @param client 客户端对象bailian20231229Client
* @param workspaceId 业务空间ID
* @param indexId 知识库ID
* @param query 检索查询语句
* @param filesIds 指定文件
* @return 阿里云百炼服务的响应
*/
public static RetrieveResponse retrieveIndex(com.aliyun.bailian20231229.Client client, String workspaceId, String indexId, String query, List<String> filesIds) throws Exception {
RetrieveRequest retrieveRequest = new RetrieveRequest();
retrieveRequest.setIndexId(indexId);
retrieveRequest.setQuery(query);
retrieveRequest.setDenseSimilarityTopK(100);
retrieveRequest.setSparseSimilarityTopK(100);
retrieveRequest.setEnableReranking(false);//开启耗费巨量token
List<Map<String, String>> searchFilters = new ArrayList<>();
Map<String, String> searchFiltersTags = new HashMap<>();
searchFiltersTags.put("tags", JSON.toJSONString(filesIds));
searchFilters.add(searchFiltersTags);
retrieveRequest.setSearchFilters(searchFilters);
// retrieveRequest.setRerankMinScore(null);
RuntimeOptions runtime = new RuntimeOptions();
return client.retrieveWithOptions(workspaceId, retrieveRequest, null, runtime);
}

View File

@@ -1,384 +1,384 @@
package com.gxwebsoft.ai.util;
import com.aliyun.bailian20231229.models.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.io.FileInputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
* 创建知识库
* @author GIIT-YC
*
*/
public class KnowledgeBaseCreate {
String ALIBABA_CLOUD_ACCESS_KEY_ID = "LTAI5tD5YRKuxWz6Eg7qrM4P";
String ALIBABA_CLOUD_ACCESS_KEY_SECRET = "bO8TBDXflOwbtSKimPpG8XrJnyzgTk";
String WORKSPACE_ID = "llm-4pf5auwewoz34zqu";
/**
* 检查并提示设置必要的环境变量。
*
* @return true 如果所有必需的环境变量都已设置,否则 false
*/
public static boolean checkEnvironmentVariables() {
Map<String, String> requiredVars = new HashMap<>();
requiredVars.put("ALIBABA_CLOUD_ACCESS_KEY_ID", "阿里云访问密钥ID");
requiredVars.put("ALIBABA_CLOUD_ACCESS_KEY_SECRET", "阿里云访问密钥密码");
requiredVars.put("WORKSPACE_ID", "阿里云百炼业务空间ID");
List<String> missingVars = new ArrayList<>();
for (Map.Entry<String, String> entry : requiredVars.entrySet()) {
String value = System.getenv(entry.getKey());
if (value == null || value.isEmpty()) {
missingVars.add(entry.getKey());
System.out.println("错误:请设置 " + entry.getKey() + " 环境变量 (" + entry.getValue() + ")");
}
}
return missingVars.isEmpty();
}
/**
* 计算文档的MD5值。
*
* @param filePath 文档本地路径
* @return 文档的MD5值
* @throws Exception 如果计算过程中发生错误
*/
public static String calculateMD5(String filePath) throws Exception {
MessageDigest md = MessageDigest.getInstance("MD5");
try (FileInputStream fis = new FileInputStream(filePath)) {
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
md.update(buffer, 0, bytesRead);
}
}
StringBuilder sb = new StringBuilder();
for (byte b : md.digest()) {
sb.append(String.format("%02x", b & 0xff));
}
return sb.toString();
}
/**
* 获取文档大小(以字节为单位)。
*
* @param filePath 文档本地路径
* @return 文档大小(以字节为单位)
*/
public static String getFileSize(String filePath) {
File file = new File(filePath);
long fileSize = file.length();
return String.valueOf(fileSize);
}
/**
* 初始化客户端Client
*
* @return 配置好的客户端对象
*/
public static com.aliyun.bailian20231229.Client createClient() throws Exception {
com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
.setAccessKeyId(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"))
.setAccessKeySecret(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"));
// 下方接入地址以公有云的公网接入地址为例,可按需更换接入地址。
config.endpoint = "bailian.cn-beijing.aliyuncs.com";
return new com.aliyun.bailian20231229.Client(config);
}
/**
* 申请文档上传租约。
*
* @param client 客户端对象
* @param categoryId 类目ID
* @param fileName 文档名称
* @param fileMd5 文档的MD5值
* @param fileSize 文档大小(以字节为单位)
* @param workspaceId 业务空间ID
* @return 阿里云百炼服务的响应对象
*/
public static ApplyFileUploadLeaseResponse applyLease(com.aliyun.bailian20231229.Client client, String categoryId,
String fileName, String fileMd5, String fileSize, String workspaceId) throws Exception {
Map<String, String> headers = new HashMap<>();
com.aliyun.bailian20231229.models.ApplyFileUploadLeaseRequest applyFileUploadLeaseRequest = new com.aliyun.bailian20231229.models.ApplyFileUploadLeaseRequest();
applyFileUploadLeaseRequest.setFileName(fileName);
applyFileUploadLeaseRequest.setMd5(fileMd5);
applyFileUploadLeaseRequest.setSizeInBytes(fileSize);
com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
ApplyFileUploadLeaseResponse applyFileUploadLeaseResponse = null;
applyFileUploadLeaseResponse = client.applyFileUploadLeaseWithOptions(categoryId, workspaceId,
applyFileUploadLeaseRequest, headers, runtime);
return applyFileUploadLeaseResponse;
}
/**
* 上传文档到临时存储。
*
* @param preSignedUrl 上传租约中的 URL
* @param headers 上传请求的头部
* @param filePath 文档本地路径
* @throws Exception 如果上传过程中发生错误
*/
public static void uploadFile(String preSignedUrl, Map<String, String> headers, String filePath) throws Exception {
File file = new File(filePath);
if (!file.exists() || !file.isFile()) {
throw new IllegalArgumentException("文件不存在或不是普通文件: " + filePath);
}
try (FileInputStream fis = new FileInputStream(file)) {
URL url = new URL(preSignedUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("PUT");
conn.setDoOutput(true);
// 设置上传请求头
conn.setRequestProperty("X-bailian-extra", headers.get("X-bailian-extra"));
conn.setRequestProperty("Content-Type", headers.get("Content-Type"));
// 分块读取并上传文档
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
conn.getOutputStream().write(buffer, 0, bytesRead);
}
int responseCode = conn.getResponseCode();
if (responseCode != 200) {
throw new RuntimeException("上传失败: " + responseCode);
}
}
}
/**
* 将文档添加到类目中。
*
* @param client 客户端对象
* @param leaseId 租约ID
* @param parser 用于文档的解析器
* @param categoryId 类目ID
* @param workspaceId 业务空间ID
* @return 阿里云百炼服务的响应对象
*/
public static AddFileResponse addFile(com.aliyun.bailian20231229.Client client, String leaseId, String parser,
String categoryId, String workspaceId) throws Exception {
Map<String, String> headers = new HashMap<>();
com.aliyun.bailian20231229.models.AddFileRequest addFileRequest = new com.aliyun.bailian20231229.models.AddFileRequest();
addFileRequest.setLeaseId(leaseId);
addFileRequest.setParser(parser);
addFileRequest.setCategoryId(categoryId);
com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
return client.addFileWithOptions(workspaceId, addFileRequest, headers, runtime);
}
/**
* 查询文档的基本信息。
*
* @param client 客户端对象
* @param workspaceId 业务空间ID
* @param fileId 文档ID
* @return 阿里云百炼服务的响应对象
*/
public static DescribeFileResponse describeFile(com.aliyun.bailian20231229.Client client, String workspaceId,
String fileId) throws Exception {
Map<String, String> headers = new HashMap<>();
com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
return client.describeFileWithOptions(workspaceId, fileId, headers, runtime);
}
/**
* 在阿里云百炼服务中创建知识库(初始化)。
*
* @param client 客户端对象
* @param workspaceId 业务空间ID
* @param fileId 文档ID
* @param name 知识库名称
* @param structureType 知识库的数据类型
* @param sourceType 应用数据的数据类型,支持类目类型和文档类型
* @param sinkType 知识库的向量存储类型
* @return 阿里云百炼服务的响应对象
*/
public static CreateIndexResponse createIndex(com.aliyun.bailian20231229.Client client, String workspaceId,
String fileId, String name, String structureType, String sourceType, String sinkType) throws Exception {
Map<String, String> headers = new HashMap<>();
com.aliyun.bailian20231229.models.CreateIndexRequest createIndexRequest = new com.aliyun.bailian20231229.models.CreateIndexRequest();
createIndexRequest.setStructureType(structureType);
createIndexRequest.setName(name);
createIndexRequest.setSourceType(sourceType);
createIndexRequest.setSinkType(sinkType);
createIndexRequest.setDocumentIds(Collections.singletonList(fileId));
com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
return client.createIndexWithOptions(workspaceId, createIndexRequest, headers, runtime);
}
/**
* 向阿里云百炼服务提交索引任务。
*
* @param client 客户端对象
* @param workspaceId 业务空间ID
* @param indexId 知识库ID
* @return 阿里云百炼服务的响应对象
*/
public static SubmitIndexJobResponse submitIndex(com.aliyun.bailian20231229.Client client, String workspaceId,
String indexId) throws Exception {
Map<String, String> headers = new HashMap<>();
com.aliyun.bailian20231229.models.SubmitIndexJobRequest submitIndexJobRequest = new com.aliyun.bailian20231229.models.SubmitIndexJobRequest();
submitIndexJobRequest.setIndexId(indexId);
com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
return client.submitIndexJobWithOptions(workspaceId, submitIndexJobRequest, headers, runtime);
}
/**
* 查询索引任务状态。
*
* @param client 客户端对象
* @param workspaceId 业务空间ID
* @param jobId 任务ID
* @param indexId 知识库ID
* @return 阿里云百炼服务的响应对象
*/
public static GetIndexJobStatusResponse getIndexJobStatus(com.aliyun.bailian20231229.Client client,
String workspaceId, String jobId, String indexId) throws Exception {
Map<String, String> headers = new HashMap<>();
com.aliyun.bailian20231229.models.GetIndexJobStatusRequest getIndexJobStatusRequest = new com.aliyun.bailian20231229.models.GetIndexJobStatusRequest();
getIndexJobStatusRequest.setIndexId(indexId);
getIndexJobStatusRequest.setJobId(jobId);
com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
GetIndexJobStatusResponse getIndexJobStatusResponse = null;
getIndexJobStatusResponse = client.getIndexJobStatusWithOptions(workspaceId, getIndexJobStatusRequest, headers,
runtime);
return getIndexJobStatusResponse;
}
/**
* 使用阿里云百炼服务创建知识库。
*
* @param filePath 文档本地路径
* @param workspaceId 业务空间ID
* @param name 知识库名称
* @return 如果成功返回知识库ID否则返回 null
*/
public static String createKnowledgeBase(String filePath, String workspaceId, String name) {
// 设置默认值
String categoryId = "default";
String parser = "DASHSCOPE_DOCMIND";
String sourceType = "DATA_CENTER_FILE";
String structureType = "unstructured";
String sinkType = "DEFAULT";
try {
// 步骤1初始化客户端Client
System.out.println("步骤1初始化Client");
com.aliyun.bailian20231229.Client client = createClient();
// 步骤2准备文档信息
System.out.println("步骤2准备文档信息");
String fileName = new File(filePath).getName();
String fileMd5 = calculateMD5(filePath);
String fileSize = getFileSize(filePath);
// 步骤3申请上传租约
System.out.println("步骤3向阿里云百炼申请上传租约");
ApplyFileUploadLeaseResponse leaseResponse = applyLease(client, categoryId, fileName, fileMd5, fileSize,
workspaceId);
String leaseId = leaseResponse.getBody().getData().getFileUploadLeaseId();
String uploadUrl = leaseResponse.getBody().getData().getParam().getUrl();
Object uploadHeaders = leaseResponse.getBody().getData().getParam().getHeaders();
// 步骤4上传文档
System.out.println("步骤4上传文档到阿里云百炼");
// 请自行安装jackson-databind
// 将上一步的uploadHeaders转换为Map(Key-Value形式)
ObjectMapper mapper = new ObjectMapper();
Map<String, String> uploadHeadersMap = (Map<String, String>) mapper
.readValue(mapper.writeValueAsString(uploadHeaders), Map.class);
uploadFile(uploadUrl, uploadHeadersMap, filePath);
// 步骤5将文档添加到服务器
System.out.println("步骤5将文档添加到阿里云百炼服务器");
AddFileResponse addResponse = addFile(client, leaseId, parser, categoryId, workspaceId);
String fileId = addResponse.getBody().getData().getFileId();
// 步骤6检查文档状态
System.out.println("步骤6检查阿里云百炼中的文档状态");
while (true) {
DescribeFileResponse describeResponse = describeFile(client, workspaceId, fileId);
String status = describeResponse.getBody().getData().getStatus();
System.out.println("当前文档状态:" + status);
if (status.equals("INIT")) {
System.out.println("文档待解析,请稍候...");
} else if (status.equals("PARSING")) {
System.out.println("文档解析中,请稍候...");
} else if (status.equals("PARSE_SUCCESS")) {
System.out.println("文档解析完成!");
break;
} else {
System.out.println("未知的文档状态:" + status + ",请联系技术支持。");
return null;
}
TimeUnit.SECONDS.sleep(5);
}
// 步骤7初始化知识库
System.out.println("步骤7在阿里云百炼中创建知识库");
CreateIndexResponse indexResponse = createIndex(client, workspaceId, fileId, name, structureType,
sourceType, sinkType);
String indexId = indexResponse.getBody().getData().getId();
// 步骤8提交索引任务
System.out.println("步骤8向阿里云百炼提交索引任务");
SubmitIndexJobResponse submitResponse = submitIndex(client, workspaceId, indexId);
String jobId = submitResponse.getBody().getData().getId();
// 步骤9获取索引任务状态
System.out.println("步骤9获取阿里云百炼索引任务状态");
while (true) {
GetIndexJobStatusResponse getStatusResponse = getIndexJobStatus(client, workspaceId, jobId, indexId);
String status = getStatusResponse.getBody().getData().getStatus();
System.out.println("当前索引任务状态:" + status);
if (status.equals("COMPLETED")) {
break;
}
TimeUnit.SECONDS.sleep(5);
}
System.out.println("阿里云百炼知识库创建成功!");
return indexId;
} catch (Exception e) {
System.out.println("发生错误:" + e.getMessage());
e.printStackTrace();
return null;
}
}
/**
* 主函数。
*/
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
if (!checkEnvironmentVariables()) {
return;
}
System.out.print("请输入您需要上传文档的实际本地路径以Linux为例/xxx/xxx/阿里云百炼系列手机产品介绍.docx");
String filePath = scanner.nextLine();
System.out.print("请为您的知识库输入一个名称:");
String kbName = scanner.nextLine();
String workspaceId = System.getenv("WORKSPACE_ID");
String result = createKnowledgeBase(filePath, workspaceId, kbName);
if (result != null) {
System.out.println("知识库ID: " + result);
}
}
}
//package com.gxwebsoft.ai.util;
//
//import com.aliyun.bailian20231229.models.*;
//import com.fasterxml.jackson.databind.ObjectMapper;
//
//import java.io.File;
//import java.io.FileInputStream;
//import java.net.HttpURLConnection;
//import java.net.URL;
//import java.security.MessageDigest;
//import java.util.*;
//import java.util.concurrent.TimeUnit;
//
///**
// * 创建知识库
// * @author GIIT-YC
// *
// */
//public class KnowledgeBaseCreate {
//
// String ALIBABA_CLOUD_ACCESS_KEY_ID = "LTAI5tD5YRKuxWz6Eg7qrM4P";
// String ALIBABA_CLOUD_ACCESS_KEY_SECRET = "bO8TBDXflOwbtSKimPpG8XrJnyzgTk";
// String WORKSPACE_ID = "llm-4pf5auwewoz34zqu";
//
// /**
// * 检查并提示设置必要的环境变量。
// *
// * @return true 如果所有必需的环境变量都已设置,否则 false
// */
// public static boolean checkEnvironmentVariables() {
// Map<String, String> requiredVars = new HashMap<>();
// requiredVars.put("ALIBABA_CLOUD_ACCESS_KEY_ID", "阿里云访问密钥ID");
// requiredVars.put("ALIBABA_CLOUD_ACCESS_KEY_SECRET", "阿里云访问密钥密码");
// requiredVars.put("WORKSPACE_ID", "阿里云百炼业务空间ID");
//
// List<String> missingVars = new ArrayList<>();
// for (Map.Entry<String, String> entry : requiredVars.entrySet()) {
// String value = System.getenv(entry.getKey());
// if (value == null || value.isEmpty()) {
// missingVars.add(entry.getKey());
// System.out.println("错误:请设置 " + entry.getKey() + " 环境变量 (" + entry.getValue() + ")");
// }
// }
//
// return missingVars.isEmpty();
// }
//
// /**
// * 计算文档的MD5值。
// *
// * @param filePath 文档本地路径
// * @return 文档的MD5值
// * @throws Exception 如果计算过程中发生错误
// */
// public static String calculateMD5(String filePath) throws Exception {
// MessageDigest md = MessageDigest.getInstance("MD5");
// try (FileInputStream fis = new FileInputStream(filePath)) {
// byte[] buffer = new byte[4096];
// int bytesRead;
// while ((bytesRead = fis.read(buffer)) != -1) {
// md.update(buffer, 0, bytesRead);
// }
// }
// StringBuilder sb = new StringBuilder();
// for (byte b : md.digest()) {
// sb.append(String.format("%02x", b & 0xff));
// }
// return sb.toString();
// }
//
// /**
// * 获取文档大小(以字节为单位)。
// *
// * @param filePath 文档本地路径
// * @return 文档大小(以字节为单位)
// */
// public static String getFileSize(String filePath) {
// File file = new File(filePath);
// long fileSize = file.length();
// return String.valueOf(fileSize);
// }
//
// /**
// * 初始化客户端Client
// *
// * @return 配置好的客户端对象
// */
// public static com.aliyun.bailian20231229.Client createClient() throws Exception {
// com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
// .setAccessKeyId(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"))
// .setAccessKeySecret(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"));
// // 下方接入地址以公有云的公网接入地址为例,可按需更换接入地址。
// config.endpoint = "bailian.cn-beijing.aliyuncs.com";
// return new com.aliyun.bailian20231229.Client(config);
// }
//
// /**
// * 申请文档上传租约。
// *
// * @param client 客户端对象
// * @param categoryId 类目ID
// * @param fileName 文档名称
// * @param fileMd5 文档的MD5值
// * @param fileSize 文档大小(以字节为单位)
// * @param workspaceId 业务空间ID
// * @return 阿里云百炼服务的响应对象
// */
// public static ApplyFileUploadLeaseResponse applyLease(com.aliyun.bailian20231229.Client client, String categoryId,
// String fileName, String fileMd5, String fileSize, String workspaceId) throws Exception {
// Map<String, String> headers = new HashMap<>();
// com.aliyun.bailian20231229.models.ApplyFileUploadLeaseRequest applyFileUploadLeaseRequest = new com.aliyun.bailian20231229.models.ApplyFileUploadLeaseRequest();
// applyFileUploadLeaseRequest.setFileName(fileName);
// applyFileUploadLeaseRequest.setMd5(fileMd5);
// applyFileUploadLeaseRequest.setSizeInBytes(fileSize);
// com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
// ApplyFileUploadLeaseResponse applyFileUploadLeaseResponse = null;
// applyFileUploadLeaseResponse = client.applyFileUploadLeaseWithOptions(categoryId, workspaceId,
// applyFileUploadLeaseRequest, headers, runtime);
// return applyFileUploadLeaseResponse;
// }
//
// /**
// * 上传文档到临时存储。
// *
// * @param preSignedUrl 上传租约中的 URL
// * @param headers 上传请求的头部
// * @param filePath 文档本地路径
// * @throws Exception 如果上传过程中发生错误
// */
// public static void uploadFile(String preSignedUrl, Map<String, String> headers, String filePath) throws Exception {
// File file = new File(filePath);
// if (!file.exists() || !file.isFile()) {
// throw new IllegalArgumentException("文件不存在或不是普通文件: " + filePath);
// }
//
// try (FileInputStream fis = new FileInputStream(file)) {
// URL url = new URL(preSignedUrl);
// HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// conn.setRequestMethod("PUT");
// conn.setDoOutput(true);
//
// // 设置上传请求头
// conn.setRequestProperty("X-bailian-extra", headers.get("X-bailian-extra"));
// conn.setRequestProperty("Content-Type", headers.get("Content-Type"));
//
// // 分块读取并上传文档
// byte[] buffer = new byte[4096];
// int bytesRead;
// while ((bytesRead = fis.read(buffer)) != -1) {
// conn.getOutputStream().write(buffer, 0, bytesRead);
// }
//
// int responseCode = conn.getResponseCode();
// if (responseCode != 200) {
// throw new RuntimeException("上传失败: " + responseCode);
// }
// }
// }
//
// /**
// * 将文档添加到类目中。
// *
// * @param client 客户端对象
// * @param leaseId 租约ID
// * @param parser 用于文档的解析器
// * @param categoryId 类目ID
// * @param workspaceId 业务空间ID
// * @return 阿里云百炼服务的响应对象
// */
// public static AddFileResponse addFile(com.aliyun.bailian20231229.Client client, String leaseId, String parser,
// String categoryId, String workspaceId) throws Exception {
// Map<String, String> headers = new HashMap<>();
// com.aliyun.bailian20231229.models.AddFileRequest addFileRequest = new com.aliyun.bailian20231229.models.AddFileRequest();
// addFileRequest.setLeaseId(leaseId);
// addFileRequest.setParser(parser);
// addFileRequest.setCategoryId(categoryId);
// com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
// return client.addFileWithOptions(workspaceId, addFileRequest, headers, runtime);
// }
//
// /**
// * 查询文档的基本信息。
// *
// * @param client 客户端对象
// * @param workspaceId 业务空间ID
// * @param fileId 文档ID
// * @return 阿里云百炼服务的响应对象
// */
// public static DescribeFileResponse describeFile(com.aliyun.bailian20231229.Client client, String workspaceId,
// String fileId) throws Exception {
// Map<String, String> headers = new HashMap<>();
// com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
// return client.describeFileWithOptions(workspaceId, fileId, headers, runtime);
// }
//
// /**
// * 在阿里云百炼服务中创建知识库(初始化)。
// *
// * @param client 客户端对象
// * @param workspaceId 业务空间ID
// * @param fileId 文档ID
// * @param name 知识库名称
// * @param structureType 知识库的数据类型
// * @param sourceType 应用数据的数据类型,支持类目类型和文档类型
// * @param sinkType 知识库的向量存储类型
// * @return 阿里云百炼服务的响应对象
// */
// public static CreateIndexResponse createIndex(com.aliyun.bailian20231229.Client client, String workspaceId,
// String fileId, String name, String structureType, String sourceType, String sinkType) throws Exception {
// Map<String, String> headers = new HashMap<>();
// com.aliyun.bailian20231229.models.CreateIndexRequest createIndexRequest = new com.aliyun.bailian20231229.models.CreateIndexRequest();
// createIndexRequest.setStructureType(structureType);
// createIndexRequest.setName(name);
// createIndexRequest.setSourceType(sourceType);
// createIndexRequest.setSinkType(sinkType);
// createIndexRequest.setDocumentIds(Collections.singletonList(fileId));
// com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
// return client.createIndexWithOptions(workspaceId, createIndexRequest, headers, runtime);
// }
//
// /**
// * 向阿里云百炼服务提交索引任务。
// *
// * @param client 客户端对象
// * @param workspaceId 业务空间ID
// * @param indexId 知识库ID
// * @return 阿里云百炼服务的响应对象
// */
// public static SubmitIndexJobResponse submitIndex(com.aliyun.bailian20231229.Client client, String workspaceId,
// String indexId) throws Exception {
// Map<String, String> headers = new HashMap<>();
// com.aliyun.bailian20231229.models.SubmitIndexJobRequest submitIndexJobRequest = new com.aliyun.bailian20231229.models.SubmitIndexJobRequest();
// submitIndexJobRequest.setIndexId(indexId);
// com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
// return client.submitIndexJobWithOptions(workspaceId, submitIndexJobRequest, headers, runtime);
// }
//
// /**
// * 查询索引任务状态。
// *
// * @param client 客户端对象
// * @param workspaceId 业务空间ID
// * @param jobId 任务ID
// * @param indexId 知识库ID
// * @return 阿里云百炼服务的响应对象
// */
// public static GetIndexJobStatusResponse getIndexJobStatus(com.aliyun.bailian20231229.Client client,
// String workspaceId, String jobId, String indexId) throws Exception {
// Map<String, String> headers = new HashMap<>();
// com.aliyun.bailian20231229.models.GetIndexJobStatusRequest getIndexJobStatusRequest = new com.aliyun.bailian20231229.models.GetIndexJobStatusRequest();
// getIndexJobStatusRequest.setIndexId(indexId);
// getIndexJobStatusRequest.setJobId(jobId);
// com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
// GetIndexJobStatusResponse getIndexJobStatusResponse = null;
// getIndexJobStatusResponse = client.getIndexJobStatusWithOptions(workspaceId, getIndexJobStatusRequest, headers,
// runtime);
// return getIndexJobStatusResponse;
// }
//
// /**
// * 使用阿里云百炼服务创建知识库。
// *
// * @param filePath 文档本地路径
// * @param workspaceId 业务空间ID
// * @param name 知识库名称
// * @return 如果成功返回知识库ID否则返回 null
// */
// public static String createKnowledgeBase(String filePath, String workspaceId, String name) {
// // 设置默认值
// String categoryId = "default";
// String parser = "DASHSCOPE_DOCMIND";
// String sourceType = "DATA_CENTER_FILE";
// String structureType = "unstructured";
// String sinkType = "DEFAULT";
// try {
// // 步骤1初始化客户端Client
// System.out.println("步骤1初始化Client");
// com.aliyun.bailian20231229.Client client = createClient();
//
// // 步骤2准备文档信息
// System.out.println("步骤2准备文档信息");
// String fileName = new File(filePath).getName();
// String fileMd5 = calculateMD5(filePath);
// String fileSize = getFileSize(filePath);
//
// // 步骤3申请上传租约
// System.out.println("步骤3向阿里云百炼申请上传租约");
// ApplyFileUploadLeaseResponse leaseResponse = applyLease(client, categoryId, fileName, fileMd5, fileSize,
// workspaceId);
// String leaseId = leaseResponse.getBody().getData().getFileUploadLeaseId();
// String uploadUrl = leaseResponse.getBody().getData().getParam().getUrl();
// Object uploadHeaders = leaseResponse.getBody().getData().getParam().getHeaders();
//
// // 步骤4上传文档
// System.out.println("步骤4上传文档到阿里云百炼");
// // 请自行安装jackson-databind
// // 将上一步的uploadHeaders转换为Map(Key-Value形式)
// ObjectMapper mapper = new ObjectMapper();
// Map<String, String> uploadHeadersMap = (Map<String, String>) mapper
// .readValue(mapper.writeValueAsString(uploadHeaders), Map.class);
// uploadFile(uploadUrl, uploadHeadersMap, filePath);
//
// // 步骤5将文档添加到服务器
// System.out.println("步骤5将文档添加到阿里云百炼服务器");
// AddFileResponse addResponse = addFile(client, leaseId, parser, categoryId, workspaceId);
// String fileId = addResponse.getBody().getData().getFileId();
//
// // 步骤6检查文档状态
// System.out.println("步骤6检查阿里云百炼中的文档状态");
// while (true) {
// DescribeFileResponse describeResponse = describeFile(client, workspaceId, fileId);
// String status = describeResponse.getBody().getData().getStatus();
// System.out.println("当前文档状态:" + status);
//
// if (status.equals("INIT")) {
// System.out.println("文档待解析,请稍候...");
// } else if (status.equals("PARSING")) {
// System.out.println("文档解析中,请稍候...");
// } else if (status.equals("PARSE_SUCCESS")) {
// System.out.println("文档解析完成!");
// break;
// } else {
// System.out.println("未知的文档状态:" + status + ",请联系技术支持。");
// return null;
// }
// TimeUnit.SECONDS.sleep(5);
// }
//
// // 步骤7初始化知识库
// System.out.println("步骤7在阿里云百炼中创建知识库");
// CreateIndexResponse indexResponse = createIndex(client, workspaceId, fileId, name, structureType,
// sourceType, sinkType);
// String indexId = indexResponse.getBody().getData().getId();
//
// // 步骤8提交索引任务
// System.out.println("步骤8向阿里云百炼提交索引任务");
// SubmitIndexJobResponse submitResponse = submitIndex(client, workspaceId, indexId);
// String jobId = submitResponse.getBody().getData().getId();
//
// // 步骤9获取索引任务状态
// System.out.println("步骤9获取阿里云百炼索引任务状态");
// while (true) {
// GetIndexJobStatusResponse getStatusResponse = getIndexJobStatus(client, workspaceId, jobId, indexId);
// String status = getStatusResponse.getBody().getData().getStatus();
// System.out.println("当前索引任务状态:" + status);
//
// if (status.equals("COMPLETED")) {
// break;
// }
// TimeUnit.SECONDS.sleep(5);
// }
//
// System.out.println("阿里云百炼知识库创建成功!");
// return indexId;
//
// } catch (Exception e) {
// System.out.println("发生错误:" + e.getMessage());
// e.printStackTrace();
// return null;
// }
// }
//
// /**
// * 主函数。
// */
// public static void main(String[] args) {
// Scanner scanner = new Scanner(System.in);
// if (!checkEnvironmentVariables()) {
// return;
// }
//
// System.out.print("请输入您需要上传文档的实际本地路径以Linux为例/xxx/xxx/阿里云百炼系列手机产品介绍.docx");
// String filePath = scanner.nextLine();
//
// System.out.print("请为您的知识库输入一个名称:");
// String kbName = scanner.nextLine();
//
// String workspaceId = System.getenv("WORKSPACE_ID");
// String result = createKnowledgeBase(filePath, workspaceId, kbName);
// if (result != null) {
// System.out.println("知识库ID: " + result);
// }
// }
//}

View File

@@ -1,145 +1,145 @@
package com.gxwebsoft.ai.util;
import com.aliyun.bailian20231229.models.DeleteIndexResponse;
import com.aliyun.bailian20231229.models.ListIndicesResponse;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.*;
/**
* 管理知识库
* @author GIIT-YC
*
*/
public class KnowledgeBaseManage {
String ALIBABA_CLOUD_ACCESS_KEY_ID = "LTAI5tD5YRKuxWz6Eg7qrM4P";
String ALIBABA_CLOUD_ACCESS_KEY_SECRET = "bO8TBDXflOwbtSKimPpG8XrJnyzgTk";
String WORKSPACE_ID = "llm-4pf5auwewoz34zqu";
/**
* 检查并提示设置必要的环境变量。
*
* @return true 如果所有必需的环境变量都已设置,否则 false
*/
public static boolean checkEnvironmentVariables() {
Map<String, String> requiredVars = new HashMap<>();
requiredVars.put("ALIBABA_CLOUD_ACCESS_KEY_ID", "阿里云访问密钥ID");
requiredVars.put("ALIBABA_CLOUD_ACCESS_KEY_SECRET", "阿里云访问密钥密码");
requiredVars.put("WORKSPACE_ID", "阿里云百炼业务空间ID");
List<String> missingVars = new ArrayList<>();
for (Map.Entry<String, String> entry : requiredVars.entrySet()) {
String value = System.getenv(entry.getKey());
if (value == null || value.isEmpty()) {
missingVars.add(entry.getKey());
System.out.println("错误:请设置 " + entry.getKey() + " 环境变量 (" + entry.getValue() + ")");
}
}
return missingVars.isEmpty();
}
/**
* 创建并配置客户端Client
*
* @return 配置好的客户端Client
*/
public static com.aliyun.bailian20231229.Client createClient() throws Exception {
com.aliyun.credentials.Client credential = new com.aliyun.credentials.Client();
com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
.setCredential(credential);
// 下方接入地址以公有云的公网接入地址为例,可按需更换接入地址。
config.endpoint = "bailian.cn-beijing.aliyuncs.com";
return new com.aliyun.bailian20231229.Client(config);
}
/**
* 获取指定业务空间下一个或多个知识库的详细信息
*
* @param client 客户端Client
* @param workspaceId 业务空间ID
* @return 阿里云百炼服务的响应
*/
public static ListIndicesResponse listIndices(com.aliyun.bailian20231229.Client client, String workspaceId)
throws Exception {
Map<String, String> headers = new HashMap<>();
com.aliyun.bailian20231229.models.ListIndicesRequest listIndicesRequest = new com.aliyun.bailian20231229.models.ListIndicesRequest();
com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
return client.listIndicesWithOptions(workspaceId, listIndicesRequest, headers, runtime);
}
/**
* 永久性删除指定的知识库
*
* @param client 客户端Client
* @param workspaceId 业务空间ID
* @param indexId 知识库ID
* @return 阿里云百炼服务的响应
*/
public static DeleteIndexResponse deleteIndex(com.aliyun.bailian20231229.Client client, String workspaceId,
String indexId) throws Exception {
Map<String, String> headers = new HashMap<>();
com.aliyun.bailian20231229.models.DeleteIndexRequest deleteIndexRequest = new com.aliyun.bailian20231229.models.DeleteIndexRequest();
deleteIndexRequest.setIndexId(indexId);
com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
return client.deleteIndexWithOptions(workspaceId, deleteIndexRequest, headers, runtime);
}
/**
* 主函数
*/
public static void main(String[] args) {
if (!checkEnvironmentVariables()) {
System.out.println("环境变量校验未通过。");
return;
}
try {
Scanner scanner = new Scanner(System.in);
System.out.print("请选择要执行的操作:\n1. 查看知识库\n2. 删除知识库\n请输入选项1或2");
String startOption = scanner.nextLine();
com.aliyun.bailian20231229.Client client = createClient();
if (startOption.equals("1")) {
// 查看知识库
System.out.println("\n执行查看知识库");
String workspaceId = System.getenv("WORKSPACE_ID");
ListIndicesResponse response = listIndices(client, workspaceId);
// 请自行安装jackson-databind。将响应转换为 JSON 字符串
ObjectMapper mapper = new ObjectMapper();
String result = mapper.writeValueAsString(response.getBody().getData());
System.out.println(result);
} else if (startOption.equals("2")) {
System.out.println("\n执行删除知识库");
String workspaceId = System.getenv("WORKSPACE_ID");
System.out.print("请输入知识库ID"); // 即 CreateIndex 接口返回的 Data.Id您也可以在阿里云百炼控制台的知识库页面获取。
String indexId = scanner.nextLine();
// 删除前二次确认
boolean confirm = false;
while (!confirm) {
System.out.print("您确定要永久性删除该知识库 " + indexId + " 吗?(y/n): ");
String input = scanner.nextLine().trim().toLowerCase();
if (input.equals("y")) {
confirm = true;
} else if (input.equals("n")) {
System.out.println("已取消删除操作。");
return;
} else {
System.out.println("无效输入,请输入 y 或 n。");
}
}
DeleteIndexResponse resp = deleteIndex(client, workspaceId, indexId);
if (resp.getBody().getStatus().equals("200")) {
System.out.println("知识库" + indexId + "删除成功!");
} else {
ObjectMapper mapper = new ObjectMapper();
System.out.println("发生错误:" + mapper.writeValueAsString(resp.getBody()));
}
} else {
System.out.println("无效的选项,程序退出。");
}
} catch (Exception e) {
System.out.println("发生错误:" + e.getMessage());
}
}
}
//package com.gxwebsoft.ai.util;
//
//import com.aliyun.bailian20231229.models.DeleteIndexResponse;
//import com.aliyun.bailian20231229.models.ListIndicesResponse;
//import com.fasterxml.jackson.databind.ObjectMapper;
//
//import java.util.*;
//
///**
// * 管理知识库
// * @author GIIT-YC
// *
// */
//public class KnowledgeBaseManage {
//
// String ALIBABA_CLOUD_ACCESS_KEY_ID = "LTAI5tD5YRKuxWz6Eg7qrM4P";
// String ALIBABA_CLOUD_ACCESS_KEY_SECRET = "bO8TBDXflOwbtSKimPpG8XrJnyzgTk";
// String WORKSPACE_ID = "llm-4pf5auwewoz34zqu";
//
// /**
// * 检查并提示设置必要的环境变量。
// *
// * @return true 如果所有必需的环境变量都已设置,否则 false
// */
// public static boolean checkEnvironmentVariables() {
// Map<String, String> requiredVars = new HashMap<>();
// requiredVars.put("ALIBABA_CLOUD_ACCESS_KEY_ID", "阿里云访问密钥ID");
// requiredVars.put("ALIBABA_CLOUD_ACCESS_KEY_SECRET", "阿里云访问密钥密码");
// requiredVars.put("WORKSPACE_ID", "阿里云百炼业务空间ID");
//
// List<String> missingVars = new ArrayList<>();
// for (Map.Entry<String, String> entry : requiredVars.entrySet()) {
// String value = System.getenv(entry.getKey());
// if (value == null || value.isEmpty()) {
// missingVars.add(entry.getKey());
// System.out.println("错误:请设置 " + entry.getKey() + " 环境变量 (" + entry.getValue() + ")");
// }
// }
//
// return missingVars.isEmpty();
// }
//
// /**
// * 创建并配置客户端Client
// *
// * @return 配置好的客户端Client
// */
// public static com.aliyun.bailian20231229.Client createClient() throws Exception {
// com.aliyun.credentials.Client credential = new com.aliyun.credentials.Client();
// com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
// .setCredential(credential);
// // 下方接入地址以公有云的公网接入地址为例,可按需更换接入地址。
// config.endpoint = "bailian.cn-beijing.aliyuncs.com";
// return new com.aliyun.bailian20231229.Client(config);
// }
//
// /**
// * 获取指定业务空间下一个或多个知识库的详细信息
// *
// * @param client 客户端Client
// * @param workspaceId 业务空间ID
// * @return 阿里云百炼服务的响应
// */
// public static ListIndicesResponse listIndices(com.aliyun.bailian20231229.Client client, String workspaceId)
// throws Exception {
// Map<String, String> headers = new HashMap<>();
// com.aliyun.bailian20231229.models.ListIndicesRequest listIndicesRequest = new com.aliyun.bailian20231229.models.ListIndicesRequest();
// com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
// return client.listIndicesWithOptions(workspaceId, listIndicesRequest, headers, runtime);
// }
//
// /**
// * 永久性删除指定的知识库
// *
// * @param client 客户端Client
// * @param workspaceId 业务空间ID
// * @param indexId 知识库ID
// * @return 阿里云百炼服务的响应
// */
// public static DeleteIndexResponse deleteIndex(com.aliyun.bailian20231229.Client client, String workspaceId,
// String indexId) throws Exception {
// Map<String, String> headers = new HashMap<>();
// com.aliyun.bailian20231229.models.DeleteIndexRequest deleteIndexRequest = new com.aliyun.bailian20231229.models.DeleteIndexRequest();
// deleteIndexRequest.setIndexId(indexId);
// com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
// return client.deleteIndexWithOptions(workspaceId, deleteIndexRequest, headers, runtime);
// }
//
// /**
// * 主函数
// */
// public static void main(String[] args) {
// if (!checkEnvironmentVariables()) {
// System.out.println("环境变量校验未通过。");
// return;
// }
//
// try {
// Scanner scanner = new Scanner(System.in);
// System.out.print("请选择要执行的操作:\n1. 查看知识库\n2. 删除知识库\n请输入选项1或2");
// String startOption = scanner.nextLine();
// com.aliyun.bailian20231229.Client client = createClient();
// if (startOption.equals("1")) {
// // 查看知识库
// System.out.println("\n执行查看知识库");
// String workspaceId = System.getenv("WORKSPACE_ID");
// ListIndicesResponse response = listIndices(client, workspaceId);
// // 请自行安装jackson-databind。将响应转换为 JSON 字符串
// ObjectMapper mapper = new ObjectMapper();
// String result = mapper.writeValueAsString(response.getBody().getData());
// System.out.println(result);
// } else if (startOption.equals("2")) {
// System.out.println("\n执行删除知识库");
// String workspaceId = System.getenv("WORKSPACE_ID");
// System.out.print("请输入知识库ID"); // 即 CreateIndex 接口返回的 Data.Id您也可以在阿里云百炼控制台的知识库页面获取。
// String indexId = scanner.nextLine();
// // 删除前二次确认
// boolean confirm = false;
// while (!confirm) {
// System.out.print("您确定要永久性删除该知识库 " + indexId + " 吗?(y/n): ");
// String input = scanner.nextLine().trim().toLowerCase();
// if (input.equals("y")) {
// confirm = true;
// } else if (input.equals("n")) {
// System.out.println("已取消删除操作。");
// return;
// } else {
// System.out.println("无效输入,请输入 y 或 n。");
// }
// }
// DeleteIndexResponse resp = deleteIndex(client, workspaceId, indexId);
// if (resp.getBody().getStatus().equals("200")) {
// System.out.println("知识库" + indexId + "删除成功!");
// } else {
// ObjectMapper mapper = new ObjectMapper();
// System.out.println("发生错误:" + mapper.writeValueAsString(resp.getBody()));
// }
// } else {
// System.out.println("无效的选项,程序退出。");
// }
// } catch (Exception e) {
// System.out.println("发生错误:" + e.getMessage());
// }
// }
//}

View File

@@ -1,110 +1,110 @@
package com.gxwebsoft.ai.util;
import com.aliyun.bailian20231229.models.RetrieveRequest;
import com.aliyun.bailian20231229.models.RetrieveResponse;
import com.aliyun.teautil.models.RuntimeOptions;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.*;
/**
* 检索知识库
* @author GIIT-YC
*
*/
public class KnowledgeBaseRetrieve {
static String ALIBABA_CLOUD_ACCESS_KEY_ID = "LTAI5tD5YRKuxWz6Eg7qrM4P";
static String ALIBABA_CLOUD_ACCESS_KEY_SECRET = "bO8TBDXflOwbtSKimPpG8XrJnyzgTk";
static String WORKSPACE_ID = "llm-4pf5auwewoz34zqu";
/**
* 检查并提示设置必要的环境变量。
*
* @return true 如果所有必需的环境变量都已设置,否则 false
*/
public static boolean checkEnvironmentVariables() {
Map<String, String> requiredVars = new HashMap<>();
requiredVars.put("ALIBABA_CLOUD_ACCESS_KEY_ID", "阿里云访问密钥ID");
requiredVars.put("ALIBABA_CLOUD_ACCESS_KEY_SECRET", "阿里云访问密钥密码");
requiredVars.put("WORKSPACE_ID", "阿里云百炼业务空间ID");
List<String> missingVars = new ArrayList<>();
for (Map.Entry<String, String> entry : requiredVars.entrySet()) {
String value = System.getenv(entry.getKey());
if (value == null || value.isEmpty()) {
missingVars.add(entry.getKey());
System.out.println("错误:请设置 " + entry.getKey() + " 环境变量 (" + entry.getValue() + ")");
}
}
return missingVars.isEmpty();
}
/**
* 初始化客户端Client
*
* @return 配置好的客户端对象
*/
public static com.aliyun.bailian20231229.Client createClient() throws Exception {
com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
.setAccessKeyId(ALIBABA_CLOUD_ACCESS_KEY_ID)
.setAccessKeySecret(ALIBABA_CLOUD_ACCESS_KEY_SECRET);
// 下方接入地址以公有云的公网接入地址为例,可按需更换接入地址。
config.endpoint = "bailian.cn-beijing.aliyuncs.com";
return new com.aliyun.bailian20231229.Client(config);
}
/**
* 在指定的知识库中检索信息。
*
* @param client 客户端对象bailian20231229Client
* @param workspaceId 业务空间ID
* @param indexId 知识库ID
* @param query 检索查询语句
* @return 阿里云百炼服务的响应
*/
public static RetrieveResponse retrieveIndex(com.aliyun.bailian20231229.Client client, String workspaceId,
String indexId, String query) throws Exception {
RetrieveRequest retrieveRequest = new RetrieveRequest();
retrieveRequest.setIndexId(indexId);
retrieveRequest.setQuery(query);
retrieveRequest.setDenseSimilarityTopK(null);
RuntimeOptions runtime = new RuntimeOptions();
return client.retrieveWithOptions(workspaceId, retrieveRequest, null, runtime);
}
/**
* 使用阿里云百炼服务检索知识库。
*/
public static void main(String[] args) {
// if (!checkEnvironmentVariables()) {
// System.out.println("环境变量校验未通过。");
// return;
//package com.gxwebsoft.ai.util;
//
//import com.aliyun.bailian20231229.models.RetrieveRequest;
//import com.aliyun.bailian20231229.models.RetrieveResponse;
//import com.aliyun.teautil.models.RuntimeOptions;
//import com.fasterxml.jackson.databind.ObjectMapper;
//
//import java.util.*;
//
///**
// * 检索知识库
// * @author GIIT-YC
// *
// */
//public class KnowledgeBaseRetrieve {
//
// static String ALIBABA_CLOUD_ACCESS_KEY_ID = "LTAI5tD5YRKuxWz6Eg7qrM4P";
// static String ALIBABA_CLOUD_ACCESS_KEY_SECRET = "bO8TBDXflOwbtSKimPpG8XrJnyzgTk";
// static String WORKSPACE_ID = "llm-4pf5auwewoz34zqu";
//
//
// /**
// * 检查并提示设置必要的环境变量。
// *
// * @return true 如果所有必需的环境变量都已设置,否则 false
// */
// public static boolean checkEnvironmentVariables() {
// Map<String, String> requiredVars = new HashMap<>();
// requiredVars.put("ALIBABA_CLOUD_ACCESS_KEY_ID", "阿里云访问密钥ID");
// requiredVars.put("ALIBABA_CLOUD_ACCESS_KEY_SECRET", "阿里云访问密钥密码");
// requiredVars.put("WORKSPACE_ID", "阿里云百炼业务空间ID");
//
// List<String> missingVars = new ArrayList<>();
// for (Map.Entry<String, String> entry : requiredVars.entrySet()) {
// String value = System.getenv(entry.getKey());
// if (value == null || value.isEmpty()) {
// missingVars.add(entry.getKey());
// System.out.println("错误:请设置 " + entry.getKey() + " 环境变量 (" + entry.getValue() + ")");
// }
// }
try {
// 步骤1初始化客户端Client
System.out.println("步骤1创建Client");
com.aliyun.bailian20231229.Client client = createClient();
// 步骤2检索知识库
System.out.println("步骤2检索知识库");
Scanner scanner = new Scanner(System.in);
System.out.print("请输入知识库ID"); // 即 CreateIndex 接口返回的 Data.Id您也可以在阿里云百炼控制台的知识库页面获取。
String indexId = scanner.nextLine();
System.out.print("请输入检索query");
String query = scanner.nextLine();
String workspaceId = WORKSPACE_ID;
RetrieveResponse resp = retrieveIndex(client, workspaceId, indexId, query);
// 请自行安装jackson-databind。将响应体responsebody转换为 JSON 字符串
ObjectMapper mapper = new ObjectMapper();
String result = mapper.writeValueAsString(resp.getBody());
System.out.println(result);
} catch (Exception e) {
System.out.println("发生错误:" + e.getMessage());
}
}
}
//
// return missingVars.isEmpty();
// }
//
// /**
// * 初始化客户端Client
// *
// * @return 配置好的客户端对象
// */
// public static com.aliyun.bailian20231229.Client createClient() throws Exception {
// com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
// .setAccessKeyId(ALIBABA_CLOUD_ACCESS_KEY_ID)
// .setAccessKeySecret(ALIBABA_CLOUD_ACCESS_KEY_SECRET);
// // 下方接入地址以公有云的公网接入地址为例,可按需更换接入地址。
// config.endpoint = "bailian.cn-beijing.aliyuncs.com";
// return new com.aliyun.bailian20231229.Client(config);
// }
//
// /**
// * 在指定的知识库中检索信息。
// *
// * @param client 客户端对象bailian20231229Client
// * @param workspaceId 业务空间ID
// * @param indexId 知识库ID
// * @param query 检索查询语句
// * @return 阿里云百炼服务的响应
// */
// public static RetrieveResponse retrieveIndex(com.aliyun.bailian20231229.Client client, String workspaceId,
// String indexId, String query) throws Exception {
// RetrieveRequest retrieveRequest = new RetrieveRequest();
// retrieveRequest.setIndexId(indexId);
// retrieveRequest.setQuery(query);
// retrieveRequest.setDenseSimilarityTopK(null);
// RuntimeOptions runtime = new RuntimeOptions();
// return client.retrieveWithOptions(workspaceId, retrieveRequest, null, runtime);
// }
//
// /**
// * 使用阿里云百炼服务检索知识库。
// */
// public static void main(String[] args) {
//// if (!checkEnvironmentVariables()) {
//// System.out.println("环境变量校验未通过。");
//// return;
//// }
//
// try {
// // 步骤1初始化客户端Client
// System.out.println("步骤1创建Client");
// com.aliyun.bailian20231229.Client client = createClient();
//
// // 步骤2检索知识库
// System.out.println("步骤2检索知识库");
// Scanner scanner = new Scanner(System.in);
// System.out.print("请输入知识库ID"); // 即 CreateIndex 接口返回的 Data.Id您也可以在阿里云百炼控制台的知识库页面获取。
// String indexId = scanner.nextLine();
// System.out.print("请输入检索query");
// String query = scanner.nextLine();
// String workspaceId = WORKSPACE_ID;
// RetrieveResponse resp = retrieveIndex(client, workspaceId, indexId, query);
//
// // 请自行安装jackson-databind。将响应体responsebody转换为 JSON 字符串
// ObjectMapper mapper = new ObjectMapper();
// String result = mapper.writeValueAsString(resp.getBody());
// System.out.println(result);
// } catch (Exception e) {
// System.out.println("发生错误:" + e.getMessage());
// }
// }
//}

View File

@@ -1,384 +1,384 @@
package com.gxwebsoft.ai.util;
import com.aliyun.bailian20231229.models.*;
import com.aliyun.teautil.models.RuntimeOptions;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.io.FileInputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Paths;
import java.security.MessageDigest;
import java.util.*;
/**
* 更新知识库
* @author GIIT-YC
*
*/
public class KnowledgeBaseUpdate {
String ALIBABA_CLOUD_ACCESS_KEY_ID = "LTAI5tD5YRKuxWz6Eg7qrM4P";
String ALIBABA_CLOUD_ACCESS_KEY_SECRET = "bO8TBDXflOwbtSKimPpG8XrJnyzgTk";
String WORKSPACE_ID = "llm-4pf5auwewoz34zqu";
/**
* 检查并提示设置必要的环境变量。
*
* @return true 如果所有必需的环境变量都已设置,否则 false
*/
public static boolean checkEnvironmentVariables() {
Map<String, String> requiredVars = new HashMap<>();
requiredVars.put("ALIBABA_CLOUD_ACCESS_KEY_ID", "阿里云访问密钥ID");
requiredVars.put("ALIBABA_CLOUD_ACCESS_KEY_SECRET", "阿里云访问密钥密码");
requiredVars.put("WORKSPACE_ID", "阿里云百炼业务空间ID");
List<String> missingVars = new ArrayList<>();
for (Map.Entry<String, String> entry : requiredVars.entrySet()) {
String value = System.getenv(entry.getKey());
if (value == null || value.isEmpty()) {
missingVars.add(entry.getKey());
System.out.println("错误:请设置 " + entry.getKey() + " 环境变量 (" + entry.getValue() + ")");
}
}
return missingVars.isEmpty();
}
/**
* 创建并配置客户端Client
*
* @return 配置好的客户端Client
*/
public static com.aliyun.bailian20231229.Client createClient() throws Exception {
com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
.setAccessKeyId(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"))
.setAccessKeySecret(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"));
// 下方接入地址以公有云的公网接入地址为例,可按需更换接入地址。
config.endpoint = "bailian.cn-beijing.aliyuncs.com";
return new com.aliyun.bailian20231229.Client(config);
}
/**
* 计算文档的MD5值
*
* @param filePath 文档本地路径
* @return 文档的MD5值
*/
public static String calculateMD5(String filePath) throws Exception {
MessageDigest md = MessageDigest.getInstance("MD5");
try (FileInputStream fis = new FileInputStream(filePath)) {
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
md.update(buffer, 0, bytesRead);
}
}
StringBuilder sb = new StringBuilder();
for (byte b : md.digest()) {
sb.append(String.format("%02x", b & 0xff));
}
return sb.toString();
}
/**
* 获取文档大小(以字节为单位)
*
* @param filePath 文档本地路径
* @return 文档大小(以字节为单位)
*/
public static String getFileSize(String filePath) {
File file = new File(filePath);
long fileSize = file.length();
return String.valueOf(fileSize);
}
/**
* 申请文档上传租约。
*
* @param client 客户端对象
* @param categoryId 类目ID
* @param fileName 文档名称
* @param fileMd5 文档的MD5值
* @param fileSize 文档大小(以字节为单位)
* @param workspaceId 业务空间ID
* @return 阿里云百炼服务的响应对象
*/
public static ApplyFileUploadLeaseResponse applyLease(com.aliyun.bailian20231229.Client client, String categoryId,
String fileName, String fileMd5, String fileSize, String workspaceId) throws Exception {
Map<String, String> headers = new HashMap<>();
com.aliyun.bailian20231229.models.ApplyFileUploadLeaseRequest applyFileUploadLeaseRequest = new com.aliyun.bailian20231229.models.ApplyFileUploadLeaseRequest();
applyFileUploadLeaseRequest.setFileName(fileName);
applyFileUploadLeaseRequest.setMd5(fileMd5);
applyFileUploadLeaseRequest.setSizeInBytes(fileSize);
com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
ApplyFileUploadLeaseResponse applyFileUploadLeaseResponse = null;
applyFileUploadLeaseResponse = client.applyFileUploadLeaseWithOptions(categoryId, workspaceId,
applyFileUploadLeaseRequest, headers, runtime);
return applyFileUploadLeaseResponse;
}
/**
* 上传文档到临时存储。
*
* @param preSignedUrl 上传租约中的 URL
* @param headers 上传请求的头部
* @param filePath 文档本地路径
* @throws Exception 如果上传过程中发生错误
*/
public static void uploadFile(String preSignedUrl, Map<String, String> headers, String filePath) throws Exception {
File file = new File(filePath);
if (!file.exists() || !file.isFile()) {
throw new IllegalArgumentException("文件不存在或不是普通文件: " + filePath);
}
try (FileInputStream fis = new FileInputStream(file)) {
URL url = new URL(preSignedUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("PUT");
conn.setDoOutput(true);
// 设置上传请求头
conn.setRequestProperty("X-bailian-extra", headers.get("X-bailian-extra"));
conn.setRequestProperty("Content-Type", headers.get("Content-Type"));
// 分块读取并上传文档
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
conn.getOutputStream().write(buffer, 0, bytesRead);
}
int responseCode = conn.getResponseCode();
if (responseCode != 200) {
throw new RuntimeException("上传失败: " + responseCode);
}
}
}
/**
* 将文档添加到类目中。
*
* @param client 客户端对象
* @param leaseId 租约ID
* @param parser 用于文档的解析器
* @param categoryId 类目ID
* @param workspaceId 业务空间ID
* @return 阿里云百炼服务的响应对象
*/
public static AddFileResponse addFile(com.aliyun.bailian20231229.Client client, String leaseId, String parser,
String categoryId, String workspaceId) throws Exception {
Map<String, String> headers = new HashMap<>();
com.aliyun.bailian20231229.models.AddFileRequest addFileRequest = new com.aliyun.bailian20231229.models.AddFileRequest();
addFileRequest.setLeaseId(leaseId);
addFileRequest.setParser(parser);
addFileRequest.setCategoryId(categoryId);
com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
return client.addFileWithOptions(workspaceId, addFileRequest, headers, runtime);
}
/**
* 查询文档的基本信息。
*
* @param client 客户端对象
* @param workspaceId 业务空间ID
* @param fileId 文档ID
* @return 阿里云百炼服务的响应对象
*/
public static DescribeFileResponse describeFile(com.aliyun.bailian20231229.Client client, String workspaceId,
String fileId) throws Exception {
Map<String, String> headers = new HashMap<>();
com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
return client.describeFileWithOptions(workspaceId, fileId, headers, runtime);
}
/**
* 向一个非结构化知识库追加导入已解析的文档
*
* @param client 客户端Client
* @param workspaceId 业务空间ID
* @param indexId 知识库ID
* @param fileId 文档ID
* @param sourceType 数据类型
* @return 阿里云百炼服务的响应
*/
public static SubmitIndexAddDocumentsJobResponse submitIndexAddDocumentsJob(
com.aliyun.bailian20231229.Client client, String workspaceId, String indexId, String fileId,
String sourceType) throws Exception {
Map<String, String> headers = new HashMap<>();
SubmitIndexAddDocumentsJobRequest submitIndexAddDocumentsJobRequest = new SubmitIndexAddDocumentsJobRequest();
submitIndexAddDocumentsJobRequest.setIndexId(indexId);
submitIndexAddDocumentsJobRequest.setDocumentIds(Collections.singletonList(fileId));
submitIndexAddDocumentsJobRequest.setSourceType(sourceType);
RuntimeOptions runtime = new RuntimeOptions();
return client.submitIndexAddDocumentsJobWithOptions(workspaceId, submitIndexAddDocumentsJobRequest, headers,
runtime);
}
/**
* 查询索引任务状态。
*
* @param client 客户端对象
* @param workspaceId 业务空间ID
* @param jobId 任务ID
* @param indexId 知识库ID
* @return 阿里云百炼服务的响应对象
*/
public static GetIndexJobStatusResponse getIndexJobStatus(com.aliyun.bailian20231229.Client client,
String workspaceId, String jobId, String indexId) throws Exception {
Map<String, String> headers = new HashMap<>();
com.aliyun.bailian20231229.models.GetIndexJobStatusRequest getIndexJobStatusRequest = new com.aliyun.bailian20231229.models.GetIndexJobStatusRequest();
getIndexJobStatusRequest.setIndexId(indexId);
getIndexJobStatusRequest.setJobId(jobId);
com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
GetIndexJobStatusResponse getIndexJobStatusResponse = null;
getIndexJobStatusResponse = client.getIndexJobStatusWithOptions(workspaceId, getIndexJobStatusRequest, headers,
runtime);
return getIndexJobStatusResponse;
}
/**
* 从指定的非结构化知识库中永久删除一个或多个文档
*
* @param client 客户端Client
* @param workspaceId 业务空间ID
* @param indexId 知识库ID
* @param fileId 文档ID
* @return 阿里云百炼服务的响应
*/
public static DeleteIndexDocumentResponse deleteIndexDocument(com.aliyun.bailian20231229.Client client,
String workspaceId, String indexId, String fileId) throws Exception {
Map<String, String> headers = new HashMap<>();
DeleteIndexDocumentRequest deleteIndexDocumentRequest = new DeleteIndexDocumentRequest();
deleteIndexDocumentRequest.setIndexId(indexId);
deleteIndexDocumentRequest.setDocumentIds(Collections.singletonList(fileId));
com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
return client.deleteIndexDocumentWithOptions(workspaceId, deleteIndexDocumentRequest, headers, runtime);
}
/**
* 使用阿里云百炼服务更新知识库
*
* @param filePath 文档(更新后的)的实际本地路径
* @param workspaceId 业务空间ID
* @param indexId 需要更新的知识库ID
* @param oldFileId 需要更新的文档的FileID
* @return 如果成功返回知识库ID否则返回 null
*/
public static String updateKnowledgeBase(String filePath, String workspaceId, String indexId, String oldFileId) {
// 设置默认值
String categoryId = "default";
String parser = "DASHSCOPE_DOCMIND";
String sourceType = "DATA_CENTER_FILE";
try {
// 步骤1初始化客户端Client
System.out.println("步骤1创建Client");
com.aliyun.bailian20231229.Client client = createClient();
// 步骤2准备文档信息更新后的文档
System.out.println("步骤2准备文档信息");
String fileName = Paths.get(filePath).getFileName().toString();
String fileMd5 = calculateMD5(filePath);
String fileSize = getFileSize(filePath);
// 步骤3申请上传租约
System.out.println("步骤3向阿里云百炼申请上传租约");
ApplyFileUploadLeaseResponse leaseResponse = applyLease(client, categoryId, fileName, fileMd5, fileSize,
workspaceId);
String leaseId = leaseResponse.getBody().getData().getFileUploadLeaseId();
String uploadUrl = leaseResponse.getBody().getData().getParam().getUrl();
Object uploadHeaders = leaseResponse.getBody().getData().getParam().getHeaders();
// 步骤4上传文档到临时存储
System.out.println("步骤4上传文档到临时存储");
// 请自行安装jackson-databind
// 将上一步的uploadHeaders转换为Map(Key-Value形式)
ObjectMapper mapper = new ObjectMapper();
Map<String, String> uploadHeadersMap = (Map<String, String>) mapper
.readValue(mapper.writeValueAsString(uploadHeaders), Map.class);
uploadFile(uploadUrl, uploadHeadersMap, filePath);
// 步骤5添加文档到类目中
System.out.println("步骤5添加文档到类目中");
AddFileResponse addResponse = addFile(client, leaseId, parser, categoryId, workspaceId);
String fileId = addResponse.getBody().getData().getFileId();
// 步骤6检查更新后的文档状态
System.out.println("步骤6检查阿里云百炼中的文档状态");
while (true) {
DescribeFileResponse describeResponse = describeFile(client, workspaceId, fileId);
String status = describeResponse.getBody().getData().getStatus();
System.out.println("当前文档状态:" + status);
if ("INIT".equals(status)) {
System.out.println("文档待解析,请稍候...");
} else if ("PARSING".equals(status)) {
System.out.println("文档解析中,请稍候...");
} else if ("PARSE_SUCCESS".equals(status)) {
System.out.println("文档解析完成!");
break;
} else {
System.out.println("未知的文档状态:" + status + ",请联系技术支持。");
return null;
}
Thread.sleep(5000);
}
// 步骤7提交追加文档任务
System.out.println("步骤7提交追加文档任务");
SubmitIndexAddDocumentsJobResponse indexAddResponse = submitIndexAddDocumentsJob(client, workspaceId,
indexId, fileId, sourceType);
String jobId = indexAddResponse.getBody().getData().getId();
// 步骤8等待追加任务完成
System.out.println("步骤8等待追加任务完成");
while (true) {
GetIndexJobStatusResponse jobStatusResponse = getIndexJobStatus(client, workspaceId, jobId, indexId);
String status = jobStatusResponse.getBody().getData().getStatus();
System.out.println("当前索引任务状态:" + status);
if ("COMPLETED".equals(status)) {
break;
}
Thread.sleep(5000);
}
// 步骤9删除旧文档
System.out.println("步骤9删除旧文档");
deleteIndexDocument(client, workspaceId, indexId, oldFileId);
System.out.println("阿里云百炼知识库更新成功!");
return indexId;
} catch (Exception e) {
System.out.println("发生错误:" + e.getMessage());
return null;
}
}
/**
* 主函数。
*/
public static void main(String[] args) {
if (!checkEnvironmentVariables()) {
System.out.println("环境变量校验未通过。");
return;
}
Scanner scanner = new Scanner(System.in);
System.out.print("请输入您需要上传文档更新后的的实际本地路径以Linux为例/xxx/xxx/阿里云百炼系列手机产品介绍.docx");
String filePath = scanner.nextLine();
System.out.print("请输入需要更新的知识库ID"); // 即 CreateIndex 接口返回的 Data.Id您也可以在阿里云百炼控制台的知识库页面获取。
String indexId = scanner.nextLine(); // 即 AddFile 接口返回的 FileId。您也可以在阿里云百炼控制台的应用数据页面单击文件名称旁的 ID 图标获取。
System.out.print("请输入需要更新的文档的 FileID");
String oldFileId = scanner.nextLine();
String workspaceId = System.getenv("WORKSPACE_ID");
String result = updateKnowledgeBase(filePath, workspaceId, indexId, oldFileId);
if (result != null) {
System.out.println("知识库更新成功返回知识库ID: " + result);
} else {
System.out.println("知识库更新失败。");
}
}
}
//package com.gxwebsoft.ai.util;
//
//import com.aliyun.bailian20231229.models.*;
//import com.aliyun.teautil.models.RuntimeOptions;
//import com.fasterxml.jackson.databind.ObjectMapper;
//
//import java.io.File;
//import java.io.FileInputStream;
//import java.net.HttpURLConnection;
//import java.net.URL;
//import java.nio.file.Paths;
//import java.security.MessageDigest;
//import java.util.*;
//
///**
// * 更新知识库
// * @author GIIT-YC
// *
// */
//public class KnowledgeBaseUpdate {
//
// String ALIBABA_CLOUD_ACCESS_KEY_ID = "LTAI5tD5YRKuxWz6Eg7qrM4P";
// String ALIBABA_CLOUD_ACCESS_KEY_SECRET = "bO8TBDXflOwbtSKimPpG8XrJnyzgTk";
// String WORKSPACE_ID = "llm-4pf5auwewoz34zqu";
//
// /**
// * 检查并提示设置必要的环境变量。
// *
// * @return true 如果所有必需的环境变量都已设置,否则 false
// */
// public static boolean checkEnvironmentVariables() {
// Map<String, String> requiredVars = new HashMap<>();
// requiredVars.put("ALIBABA_CLOUD_ACCESS_KEY_ID", "阿里云访问密钥ID");
// requiredVars.put("ALIBABA_CLOUD_ACCESS_KEY_SECRET", "阿里云访问密钥密码");
// requiredVars.put("WORKSPACE_ID", "阿里云百炼业务空间ID");
//
// List<String> missingVars = new ArrayList<>();
// for (Map.Entry<String, String> entry : requiredVars.entrySet()) {
// String value = System.getenv(entry.getKey());
// if (value == null || value.isEmpty()) {
// missingVars.add(entry.getKey());
// System.out.println("错误:请设置 " + entry.getKey() + " 环境变量 (" + entry.getValue() + ")");
// }
// }
//
// return missingVars.isEmpty();
// }
//
// /**
// * 创建并配置客户端Client
// *
// * @return 配置好的客户端Client
// */
// public static com.aliyun.bailian20231229.Client createClient() throws Exception {
// com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
// .setAccessKeyId(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"))
// .setAccessKeySecret(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"));
// // 下方接入地址以公有云的公网接入地址为例,可按需更换接入地址。
// config.endpoint = "bailian.cn-beijing.aliyuncs.com";
// return new com.aliyun.bailian20231229.Client(config);
// }
//
// /**
// * 计算文档的MD5值
// *
// * @param filePath 文档本地路径
// * @return 文档的MD5值
// */
// public static String calculateMD5(String filePath) throws Exception {
// MessageDigest md = MessageDigest.getInstance("MD5");
// try (FileInputStream fis = new FileInputStream(filePath)) {
// byte[] buffer = new byte[4096];
// int bytesRead;
// while ((bytesRead = fis.read(buffer)) != -1) {
// md.update(buffer, 0, bytesRead);
// }
// }
// StringBuilder sb = new StringBuilder();
// for (byte b : md.digest()) {
// sb.append(String.format("%02x", b & 0xff));
// }
// return sb.toString();
// }
//
// /**
// * 获取文档大小(以字节为单位)
// *
// * @param filePath 文档本地路径
// * @return 文档大小(以字节为单位)
// */
// public static String getFileSize(String filePath) {
// File file = new File(filePath);
// long fileSize = file.length();
// return String.valueOf(fileSize);
// }
//
// /**
// * 申请文档上传租约。
// *
// * @param client 客户端对象
// * @param categoryId 类目ID
// * @param fileName 文档名称
// * @param fileMd5 文档的MD5值
// * @param fileSize 文档大小(以字节为单位)
// * @param workspaceId 业务空间ID
// * @return 阿里云百炼服务的响应对象
// */
// public static ApplyFileUploadLeaseResponse applyLease(com.aliyun.bailian20231229.Client client, String categoryId,
// String fileName, String fileMd5, String fileSize, String workspaceId) throws Exception {
// Map<String, String> headers = new HashMap<>();
// com.aliyun.bailian20231229.models.ApplyFileUploadLeaseRequest applyFileUploadLeaseRequest = new com.aliyun.bailian20231229.models.ApplyFileUploadLeaseRequest();
// applyFileUploadLeaseRequest.setFileName(fileName);
// applyFileUploadLeaseRequest.setMd5(fileMd5);
// applyFileUploadLeaseRequest.setSizeInBytes(fileSize);
// com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
// ApplyFileUploadLeaseResponse applyFileUploadLeaseResponse = null;
// applyFileUploadLeaseResponse = client.applyFileUploadLeaseWithOptions(categoryId, workspaceId,
// applyFileUploadLeaseRequest, headers, runtime);
// return applyFileUploadLeaseResponse;
// }
//
// /**
// * 上传文档到临时存储。
// *
// * @param preSignedUrl 上传租约中的 URL
// * @param headers 上传请求的头部
// * @param filePath 文档本地路径
// * @throws Exception 如果上传过程中发生错误
// */
// public static void uploadFile(String preSignedUrl, Map<String, String> headers, String filePath) throws Exception {
// File file = new File(filePath);
// if (!file.exists() || !file.isFile()) {
// throw new IllegalArgumentException("文件不存在或不是普通文件: " + filePath);
// }
//
// try (FileInputStream fis = new FileInputStream(file)) {
// URL url = new URL(preSignedUrl);
// HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// conn.setRequestMethod("PUT");
// conn.setDoOutput(true);
//
// // 设置上传请求头
// conn.setRequestProperty("X-bailian-extra", headers.get("X-bailian-extra"));
// conn.setRequestProperty("Content-Type", headers.get("Content-Type"));
//
// // 分块读取并上传文档
// byte[] buffer = new byte[4096];
// int bytesRead;
// while ((bytesRead = fis.read(buffer)) != -1) {
// conn.getOutputStream().write(buffer, 0, bytesRead);
// }
//
// int responseCode = conn.getResponseCode();
// if (responseCode != 200) {
// throw new RuntimeException("上传失败: " + responseCode);
// }
// }
// }
//
// /**
// * 将文档添加到类目中。
// *
// * @param client 客户端对象
// * @param leaseId 租约ID
// * @param parser 用于文档的解析器
// * @param categoryId 类目ID
// * @param workspaceId 业务空间ID
// * @return 阿里云百炼服务的响应对象
// */
// public static AddFileResponse addFile(com.aliyun.bailian20231229.Client client, String leaseId, String parser,
// String categoryId, String workspaceId) throws Exception {
// Map<String, String> headers = new HashMap<>();
// com.aliyun.bailian20231229.models.AddFileRequest addFileRequest = new com.aliyun.bailian20231229.models.AddFileRequest();
// addFileRequest.setLeaseId(leaseId);
// addFileRequest.setParser(parser);
// addFileRequest.setCategoryId(categoryId);
// com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
// return client.addFileWithOptions(workspaceId, addFileRequest, headers, runtime);
// }
//
// /**
// * 查询文档的基本信息。
// *
// * @param client 客户端对象
// * @param workspaceId 业务空间ID
// * @param fileId 文档ID
// * @return 阿里云百炼服务的响应对象
// */
// public static DescribeFileResponse describeFile(com.aliyun.bailian20231229.Client client, String workspaceId,
// String fileId) throws Exception {
// Map<String, String> headers = new HashMap<>();
// com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
// return client.describeFileWithOptions(workspaceId, fileId, headers, runtime);
// }
//
// /**
// * 向一个非结构化知识库追加导入已解析的文档
// *
// * @param client 客户端Client
// * @param workspaceId 业务空间ID
// * @param indexId 知识库ID
// * @param fileId 文档ID
// * @param sourceType 数据类型
// * @return 阿里云百炼服务的响应
// */
// public static SubmitIndexAddDocumentsJobResponse submitIndexAddDocumentsJob(
// com.aliyun.bailian20231229.Client client, String workspaceId, String indexId, String fileId,
// String sourceType) throws Exception {
// Map<String, String> headers = new HashMap<>();
// SubmitIndexAddDocumentsJobRequest submitIndexAddDocumentsJobRequest = new SubmitIndexAddDocumentsJobRequest();
// submitIndexAddDocumentsJobRequest.setIndexId(indexId);
// submitIndexAddDocumentsJobRequest.setDocumentIds(Collections.singletonList(fileId));
// submitIndexAddDocumentsJobRequest.setSourceType(sourceType);
// RuntimeOptions runtime = new RuntimeOptions();
// return client.submitIndexAddDocumentsJobWithOptions(workspaceId, submitIndexAddDocumentsJobRequest, headers,
// runtime);
// }
//
// /**
// * 查询索引任务状态。
// *
// * @param client 客户端对象
// * @param workspaceId 业务空间ID
// * @param jobId 任务ID
// * @param indexId 知识库ID
// * @return 阿里云百炼服务的响应对象
// */
// public static GetIndexJobStatusResponse getIndexJobStatus(com.aliyun.bailian20231229.Client client,
// String workspaceId, String jobId, String indexId) throws Exception {
// Map<String, String> headers = new HashMap<>();
// com.aliyun.bailian20231229.models.GetIndexJobStatusRequest getIndexJobStatusRequest = new com.aliyun.bailian20231229.models.GetIndexJobStatusRequest();
// getIndexJobStatusRequest.setIndexId(indexId);
// getIndexJobStatusRequest.setJobId(jobId);
// com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
// GetIndexJobStatusResponse getIndexJobStatusResponse = null;
// getIndexJobStatusResponse = client.getIndexJobStatusWithOptions(workspaceId, getIndexJobStatusRequest, headers,
// runtime);
// return getIndexJobStatusResponse;
// }
//
// /**
// * 从指定的非结构化知识库中永久删除一个或多个文档
// *
// * @param client 客户端Client
// * @param workspaceId 业务空间ID
// * @param indexId 知识库ID
// * @param fileId 文档ID
// * @return 阿里云百炼服务的响应
// */
// public static DeleteIndexDocumentResponse deleteIndexDocument(com.aliyun.bailian20231229.Client client,
// String workspaceId, String indexId, String fileId) throws Exception {
// Map<String, String> headers = new HashMap<>();
// DeleteIndexDocumentRequest deleteIndexDocumentRequest = new DeleteIndexDocumentRequest();
// deleteIndexDocumentRequest.setIndexId(indexId);
// deleteIndexDocumentRequest.setDocumentIds(Collections.singletonList(fileId));
// com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
// return client.deleteIndexDocumentWithOptions(workspaceId, deleteIndexDocumentRequest, headers, runtime);
// }
//
// /**
// * 使用阿里云百炼服务更新知识库
// *
// * @param filePath 文档(更新后的)的实际本地路径
// * @param workspaceId 业务空间ID
// * @param indexId 需要更新的知识库ID
// * @param oldFileId 需要更新的文档的FileID
// * @return 如果成功返回知识库ID否则返回 null
// */
// public static String updateKnowledgeBase(String filePath, String workspaceId, String indexId, String oldFileId) {
// // 设置默认值
// String categoryId = "default";
// String parser = "DASHSCOPE_DOCMIND";
// String sourceType = "DATA_CENTER_FILE";
// try {
// // 步骤1初始化客户端Client
// System.out.println("步骤1创建Client");
// com.aliyun.bailian20231229.Client client = createClient();
//
// // 步骤2准备文档信息更新后的文档
// System.out.println("步骤2准备文档信息");
// String fileName = Paths.get(filePath).getFileName().toString();
// String fileMd5 = calculateMD5(filePath);
// String fileSize = getFileSize(filePath);
//
// // 步骤3申请上传租约
// System.out.println("步骤3向阿里云百炼申请上传租约");
// ApplyFileUploadLeaseResponse leaseResponse = applyLease(client, categoryId, fileName, fileMd5, fileSize,
// workspaceId);
// String leaseId = leaseResponse.getBody().getData().getFileUploadLeaseId();
// String uploadUrl = leaseResponse.getBody().getData().getParam().getUrl();
// Object uploadHeaders = leaseResponse.getBody().getData().getParam().getHeaders();
//
// // 步骤4上传文档到临时存储
// System.out.println("步骤4上传文档到临时存储");
// // 请自行安装jackson-databind
// // 将上一步的uploadHeaders转换为Map(Key-Value形式)
// ObjectMapper mapper = new ObjectMapper();
// Map<String, String> uploadHeadersMap = (Map<String, String>) mapper
// .readValue(mapper.writeValueAsString(uploadHeaders), Map.class);
// uploadFile(uploadUrl, uploadHeadersMap, filePath);
//
// // 步骤5添加文档到类目中
// System.out.println("步骤5添加文档到类目中");
// AddFileResponse addResponse = addFile(client, leaseId, parser, categoryId, workspaceId);
// String fileId = addResponse.getBody().getData().getFileId();
//
// // 步骤6检查更新后的文档状态
// System.out.println("步骤6检查阿里云百炼中的文档状态");
// while (true) {
// DescribeFileResponse describeResponse = describeFile(client, workspaceId, fileId);
// String status = describeResponse.getBody().getData().getStatus();
// System.out.println("当前文档状态:" + status);
// if ("INIT".equals(status)) {
// System.out.println("文档待解析,请稍候...");
// } else if ("PARSING".equals(status)) {
// System.out.println("文档解析中,请稍候...");
// } else if ("PARSE_SUCCESS".equals(status)) {
// System.out.println("文档解析完成!");
// break;
// } else {
// System.out.println("未知的文档状态:" + status + ",请联系技术支持。");
// return null;
// }
// Thread.sleep(5000);
// }
//
// // 步骤7提交追加文档任务
// System.out.println("步骤7提交追加文档任务");
// SubmitIndexAddDocumentsJobResponse indexAddResponse = submitIndexAddDocumentsJob(client, workspaceId,
// indexId, fileId, sourceType);
// String jobId = indexAddResponse.getBody().getData().getId();
//
// // 步骤8等待追加任务完成
// System.out.println("步骤8等待追加任务完成");
// while (true) {
// GetIndexJobStatusResponse jobStatusResponse = getIndexJobStatus(client, workspaceId, jobId, indexId);
// String status = jobStatusResponse.getBody().getData().getStatus();
// System.out.println("当前索引任务状态:" + status);
// if ("COMPLETED".equals(status)) {
// break;
// }
// Thread.sleep(5000);
// }
//
// // 步骤9删除旧文档
// System.out.println("步骤9删除旧文档");
// deleteIndexDocument(client, workspaceId, indexId, oldFileId);
//
// System.out.println("阿里云百炼知识库更新成功!");
// return indexId;
// } catch (Exception e) {
// System.out.println("发生错误:" + e.getMessage());
// return null;
// }
// }
//
// /**
// * 主函数。
// */
// public static void main(String[] args) {
// if (!checkEnvironmentVariables()) {
// System.out.println("环境变量校验未通过。");
// return;
// }
//
// Scanner scanner = new Scanner(System.in);
// System.out.print("请输入您需要上传文档更新后的的实际本地路径以Linux为例/xxx/xxx/阿里云百炼系列手机产品介绍.docx");
// String filePath = scanner.nextLine();
//
// System.out.print("请输入需要更新的知识库ID"); // 即 CreateIndex 接口返回的 Data.Id您也可以在阿里云百炼控制台的知识库页面获取。
// String indexId = scanner.nextLine(); // 即 AddFile 接口返回的 FileId。您也可以在阿里云百炼控制台的应用数据页面单击文件名称旁的 ID 图标获取。
//
// System.out.print("请输入需要更新的文档的 FileID");
// String oldFileId = scanner.nextLine();
//
// String workspaceId = System.getenv("WORKSPACE_ID");
// String result = updateKnowledgeBase(filePath, workspaceId, indexId, oldFileId);
// if (result != null) {
// System.out.println("知识库更新成功返回知识库ID: " + result);
// } else {
// System.out.println("知识库更新失败。");
// }
// }
//}

View File

@@ -1,303 +1,303 @@
package com.gxwebsoft.ai.util;
import com.aliyun.bailian20231229.Client;
import com.aliyun.bailian20231229.models.*;
import com.aliyun.teautil.models.RuntimeOptions;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Paths;
import java.security.MessageDigest;
import java.util.*;
import org.springframework.web.multipart.MultipartFile;
/**
* 知识库上传工具类
* @author GIIT-YC
*
*/
public class KnowledgeBaseUploader {
/**
* 上传文档到知识库直接处理MultipartFile
*
* @param client 阿里云客户端
* @param workspaceId 业务空间ID
* @param indexId 知识库ID
* @param file 上传的文件
* @return 新文档的FileID失败返回null
*/
public static String uploadDocument(com.aliyun.bailian20231229.Client client, String workspaceId, String indexId, MultipartFile file) {
try {
// 准备文档信息
String fileName = file.getOriginalFilename();
String fileMd5 = calculateMD5(file.getInputStream());
String fileSize = String.valueOf(file.getSize());
// 申请上传租约
ApplyFileUploadLeaseRequest leaseRequest = new ApplyFileUploadLeaseRequest()
.setFileName(fileName)
.setMd5(fileMd5)
.setSizeInBytes(fileSize);
ApplyFileUploadLeaseResponse leaseResponse = client.applyFileUploadLeaseWithOptions(
"default", workspaceId, leaseRequest, new HashMap<>(), new RuntimeOptions());
String leaseId = leaseResponse.getBody().getData().getFileUploadLeaseId();
String uploadUrl = leaseResponse.getBody().getData().getParam().getUrl();
// 上传文件
ObjectMapper mapper = new ObjectMapper();
Map<String, String> headers = mapper.readValue(mapper.writeValueAsString(leaseResponse.getBody().getData().getParam().getHeaders()), Map.class);
uploadFile(uploadUrl, headers, file);
// 添加文件到类目
AddFileRequest addRequest = new AddFileRequest()
.setLeaseId(leaseId)
.setParser("DASHSCOPE_DOCMIND")
.setCategoryId("default");
AddFileResponse addResponse = client.addFileWithOptions(workspaceId, addRequest, new HashMap<>(), new RuntimeOptions());
String fileId = addResponse.getBody().getData().getFileId();
// 等待文件解析完成
waitForFileParsing(client, workspaceId, fileId);
// 添加到知识库
SubmitIndexAddDocumentsJobRequest indexRequest = new SubmitIndexAddDocumentsJobRequest()
.setIndexId(indexId)
.setDocumentIds(Collections.singletonList(fileId))
.setSourceType("DATA_CENTER_FILE");
SubmitIndexAddDocumentsJobResponse indexResponse = client.submitIndexAddDocumentsJobWithOptions(workspaceId, indexRequest, new HashMap<>(), new RuntimeOptions());
// 等待索引完成
waitForIndexJob(client, workspaceId, indexResponse.getBody().getData().getId(), indexId);
return fileId;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 批量上传文档到知识库
*/
public static List<String> uploadDocuments(com.aliyun.bailian20231229.Client client, String workspaceId, String indexId, MultipartFile[] files) {
List<String> fileIds = new ArrayList<>();
for (MultipartFile file : files) {
String fileId = uploadDocument(client, workspaceId, indexId, file);
if (fileId != null) {
fileIds.add(fileId);
}
}
return fileIds;
}
/**
* 上传文档到知识库
*
* @param client 阿里云客户端
* @param workspaceId 业务空间ID
* @param indexId 知识库ID
* @param filePath 文档本地路径
* @return 新文档的FileID失败返回null
*/
public static String uploadDocument(com.aliyun.bailian20231229.Client client, String workspaceId, String indexId, String filePath) {
try {
// 准备文档信息
String fileName = Paths.get(filePath).getFileName().toString();
String fileMd5 = calculateMD5(filePath);
String fileSize = String.valueOf(new File(filePath).length());
// 申请上传租约
ApplyFileUploadLeaseRequest leaseRequest = new ApplyFileUploadLeaseRequest()
.setFileName(fileName)
.setMd5(fileMd5)
.setSizeInBytes(fileSize);
ApplyFileUploadLeaseResponse leaseResponse = client.applyFileUploadLeaseWithOptions(
"default", workspaceId, leaseRequest, new HashMap<>(), new RuntimeOptions());
String leaseId = leaseResponse.getBody().getData().getFileUploadLeaseId();
String uploadUrl = leaseResponse.getBody().getData().getParam().getUrl();
// 上传文件
ObjectMapper mapper = new ObjectMapper();
Map<String, String> headers = mapper.readValue(
mapper.writeValueAsString(leaseResponse.getBody().getData().getParam().getHeaders()),
Map.class);
uploadFile(uploadUrl, headers, filePath);
// 添加文件到类目
AddFileRequest addRequest = new AddFileRequest()
.setLeaseId(leaseId)
.setParser("DASHSCOPE_DOCMIND")
.setCategoryId("default");
AddFileResponse addResponse = client.addFileWithOptions(
workspaceId, addRequest, new HashMap<>(), new RuntimeOptions());
String fileId = addResponse.getBody().getData().getFileId();
// 等待文件解析完成
waitForFileParsing(client, workspaceId, fileId);
// 添加到知识库
SubmitIndexAddDocumentsJobRequest indexRequest = new SubmitIndexAddDocumentsJobRequest()
.setIndexId(indexId)
.setDocumentIds(Collections.singletonList(fileId))
.setSourceType("DATA_CENTER_FILE");
SubmitIndexAddDocumentsJobResponse indexResponse = client.submitIndexAddDocumentsJobWithOptions(
workspaceId, indexRequest, new HashMap<>(), new RuntimeOptions());
// 等待索引完成
waitForIndexJob(client, workspaceId, indexResponse.getBody().getData().getId(), indexId);
return fileId;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
private static String calculateMD5(String filePath) throws Exception {
MessageDigest md = MessageDigest.getInstance("MD5");
try (FileInputStream fis = new FileInputStream(filePath)) {
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
md.update(buffer, 0, bytesRead);
}
}
StringBuilder sb = new StringBuilder();
for (byte b : md.digest()) {
sb.append(String.format("%02x", b & 0xff));
}
return sb.toString();
}
private static void uploadFile(String preSignedUrl, Map<String, String> headers,
String filePath) throws Exception {
try (FileInputStream fis = new FileInputStream(filePath)) {
HttpURLConnection conn = (HttpURLConnection) new URL(preSignedUrl).openConnection();
conn.setRequestMethod("PUT");
conn.setDoOutput(true);
conn.setRequestProperty("X-bailian-extra", headers.get("X-bailian-extra"));
conn.setRequestProperty("Content-Type", headers.get("Content-Type"));
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
conn.getOutputStream().write(buffer, 0, bytesRead);
}
if (conn.getResponseCode() != 200) {
throw new RuntimeException("上传失败: " + conn.getResponseCode());
}
}
}
private static void waitForFileParsing(com.aliyun.bailian20231229.Client client,
String workspaceId, String fileId) throws Exception {
while (true) {
DescribeFileResponse response = client.describeFileWithOptions(
workspaceId, fileId, new HashMap<>(), new RuntimeOptions());
String status = response.getBody().getData().getStatus();
if ("PARSE_SUCCESS".equals(status)) break;
if ("PARSE_FAILED".equals(status)) throw new RuntimeException("文档解析失败");
Thread.sleep(5000);
}
}
private static void waitForIndexJob(com.aliyun.bailian20231229.Client client,
String workspaceId, String jobId, String indexId) throws Exception {
while (true) {
GetIndexJobStatusRequest request = new GetIndexJobStatusRequest()
.setIndexId(indexId)
.setJobId(jobId);
GetIndexJobStatusResponse response = client.getIndexJobStatusWithOptions(
workspaceId, request, new HashMap<>(), new RuntimeOptions());
String status = response.getBody().getData().getStatus();
if ("COMPLETED".equals(status)) break;
if ("FAILED".equals(status)) throw new RuntimeException("索引任务失败");
Thread.sleep(5000);
}
}
private static String calculateMD5(InputStream inputStream) throws Exception {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
md.update(buffer, 0, bytesRead);
}
StringBuilder sb = new StringBuilder();
for (byte b : md.digest()) {
sb.append(String.format("%02x", b & 0xff));
}
return sb.toString();
}
private static void uploadFile(String preSignedUrl, Map<String, String> headers,
MultipartFile file) throws Exception {
HttpURLConnection conn = (HttpURLConnection) new URL(preSignedUrl).openConnection();
conn.setRequestMethod("PUT");
conn.setDoOutput(true);
conn.setRequestProperty("X-bailian-extra", headers.get("X-bailian-extra"));
conn.setRequestProperty("Content-Type", headers.get("Content-Type"));
try (InputStream inputStream = file.getInputStream()) {
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
conn.getOutputStream().write(buffer, 0, bytesRead);
}
}
if (conn.getResponseCode() != 200) {
throw new RuntimeException("上传失败: " + conn.getResponseCode());
}
}
/**
* 初始化客户端Client
*
* @return 配置好的客户端对象
*/
public static com.aliyun.bailian20231229.Client createClient(String accessKeyId, String accessKeySecret) throws Exception {
com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
.setAccessKeyId(accessKeyId)
.setAccessKeySecret(accessKeySecret);
// 下方接入地址以公有云的公网接入地址为例,可按需更换接入地址。
config.endpoint = "bailian.cn-beijing.aliyuncs.com";
return new com.aliyun.bailian20231229.Client(config);
}
public static void main(String[] args) throws Exception {
String ALIBABA_CLOUD_ACCESS_KEY_ID = "LTAI5tD5YRKuxWz6Eg7qrM4P";
String ALIBABA_CLOUD_ACCESS_KEY_SECRET = "bO8TBDXflOwbtSKimPpG8XrJnyzgTk";
String WORKSPACE_ID = "llm-4pf5auwewoz34zqu";
String indexId = "b9pvwfqp3d";
String filePath = "D:\\公司经济责任审计方案模板.docx";
Client client = createClient(ALIBABA_CLOUD_ACCESS_KEY_ID, ALIBABA_CLOUD_ACCESS_KEY_SECRET);
uploadDocument(client, WORKSPACE_ID, indexId, filePath);
}
}
//package com.gxwebsoft.ai.util;
//
//import com.aliyun.bailian20231229.Client;
//import com.aliyun.bailian20231229.models.*;
//import com.aliyun.teautil.models.RuntimeOptions;
//import com.fasterxml.jackson.databind.ObjectMapper;
//
//import java.io.File;
//import java.io.FileInputStream;
//import java.io.InputStream;
//import java.net.HttpURLConnection;
//import java.net.URL;
//import java.nio.file.Paths;
//import java.security.MessageDigest;
//import java.util.*;
//
//import org.springframework.web.multipart.MultipartFile;
//
///**
// * 知识库上传工具类
// * @author GIIT-YC
// *
// */
//public class KnowledgeBaseUploader {
//
// /**
// * 上传文档到知识库直接处理MultipartFile
// *
// * @param client 阿里云客户端
// * @param workspaceId 业务空间ID
// * @param indexId 知识库ID
// * @param file 上传的文件
// * @return 新文档的FileID失败返回null
// */
// public static String uploadDocument(com.aliyun.bailian20231229.Client client, String workspaceId, String indexId, MultipartFile file) {
// try {
// // 准备文档信息
// String fileName = file.getOriginalFilename();
// String fileMd5 = calculateMD5(file.getInputStream());
// String fileSize = String.valueOf(file.getSize());
//
// // 申请上传租约
// ApplyFileUploadLeaseRequest leaseRequest = new ApplyFileUploadLeaseRequest()
// .setFileName(fileName)
// .setMd5(fileMd5)
// .setSizeInBytes(fileSize);
//
// ApplyFileUploadLeaseResponse leaseResponse = client.applyFileUploadLeaseWithOptions(
// "default", workspaceId, leaseRequest, new HashMap<>(), new RuntimeOptions());
//
// String leaseId = leaseResponse.getBody().getData().getFileUploadLeaseId();
// String uploadUrl = leaseResponse.getBody().getData().getParam().getUrl();
//
// // 上传文件
// ObjectMapper mapper = new ObjectMapper();
// Map<String, String> headers = mapper.readValue(mapper.writeValueAsString(leaseResponse.getBody().getData().getParam().getHeaders()), Map.class);
//
// uploadFile(uploadUrl, headers, file);
//
// // 添加文件到类目
// AddFileRequest addRequest = new AddFileRequest()
// .setLeaseId(leaseId)
// .setParser("DASHSCOPE_DOCMIND")
// .setCategoryId("default");
//
// AddFileResponse addResponse = client.addFileWithOptions(workspaceId, addRequest, new HashMap<>(), new RuntimeOptions());
//
// String fileId = addResponse.getBody().getData().getFileId();
//
// // 等待文件解析完成
// waitForFileParsing(client, workspaceId, fileId);
//
// // 添加到知识库
// SubmitIndexAddDocumentsJobRequest indexRequest = new SubmitIndexAddDocumentsJobRequest()
// .setIndexId(indexId)
// .setDocumentIds(Collections.singletonList(fileId))
// .setSourceType("DATA_CENTER_FILE");
//
// SubmitIndexAddDocumentsJobResponse indexResponse = client.submitIndexAddDocumentsJobWithOptions(workspaceId, indexRequest, new HashMap<>(), new RuntimeOptions());
//
// // 等待索引完成
// waitForIndexJob(client, workspaceId, indexResponse.getBody().getData().getId(), indexId);
//
// return fileId;
//
// } catch (Exception e) {
// e.printStackTrace();
// return null;
// }
// }
//
// /**
// * 批量上传文档到知识库
// */
// public static List<String> uploadDocuments(com.aliyun.bailian20231229.Client client, String workspaceId, String indexId, MultipartFile[] files) {
// List<String> fileIds = new ArrayList<>();
// for (MultipartFile file : files) {
// String fileId = uploadDocument(client, workspaceId, indexId, file);
// if (fileId != null) {
// fileIds.add(fileId);
// }
// }
// return fileIds;
// }
//
// /**
// * 上传文档到知识库
// *
// * @param client 阿里云客户端
// * @param workspaceId 业务空间ID
// * @param indexId 知识库ID
// * @param filePath 文档本地路径
// * @return 新文档的FileID失败返回null
// */
// public static String uploadDocument(com.aliyun.bailian20231229.Client client, String workspaceId, String indexId, String filePath) {
// try {
// // 准备文档信息
// String fileName = Paths.get(filePath).getFileName().toString();
// String fileMd5 = calculateMD5(filePath);
// String fileSize = String.valueOf(new File(filePath).length());
//
// // 申请上传租约
// ApplyFileUploadLeaseRequest leaseRequest = new ApplyFileUploadLeaseRequest()
// .setFileName(fileName)
// .setMd5(fileMd5)
// .setSizeInBytes(fileSize);
//
// ApplyFileUploadLeaseResponse leaseResponse = client.applyFileUploadLeaseWithOptions(
// "default", workspaceId, leaseRequest, new HashMap<>(), new RuntimeOptions());
//
// String leaseId = leaseResponse.getBody().getData().getFileUploadLeaseId();
// String uploadUrl = leaseResponse.getBody().getData().getParam().getUrl();
//
// // 上传文件
// ObjectMapper mapper = new ObjectMapper();
// Map<String, String> headers = mapper.readValue(
// mapper.writeValueAsString(leaseResponse.getBody().getData().getParam().getHeaders()),
// Map.class);
//
// uploadFile(uploadUrl, headers, filePath);
//
// // 添加文件到类目
// AddFileRequest addRequest = new AddFileRequest()
// .setLeaseId(leaseId)
// .setParser("DASHSCOPE_DOCMIND")
// .setCategoryId("default");
//
// AddFileResponse addResponse = client.addFileWithOptions(
// workspaceId, addRequest, new HashMap<>(), new RuntimeOptions());
//
// String fileId = addResponse.getBody().getData().getFileId();
//
// // 等待文件解析完成
// waitForFileParsing(client, workspaceId, fileId);
//
// // 添加到知识库
// SubmitIndexAddDocumentsJobRequest indexRequest = new SubmitIndexAddDocumentsJobRequest()
// .setIndexId(indexId)
// .setDocumentIds(Collections.singletonList(fileId))
// .setSourceType("DATA_CENTER_FILE");
//
// SubmitIndexAddDocumentsJobResponse indexResponse = client.submitIndexAddDocumentsJobWithOptions(
// workspaceId, indexRequest, new HashMap<>(), new RuntimeOptions());
//
// // 等待索引完成
// waitForIndexJob(client, workspaceId, indexResponse.getBody().getData().getId(), indexId);
//
// return fileId;
//
// } catch (Exception e) {
// e.printStackTrace();
// return null;
// }
// }
//
// private static String calculateMD5(String filePath) throws Exception {
// MessageDigest md = MessageDigest.getInstance("MD5");
// try (FileInputStream fis = new FileInputStream(filePath)) {
// byte[] buffer = new byte[4096];
// int bytesRead;
// while ((bytesRead = fis.read(buffer)) != -1) {
// md.update(buffer, 0, bytesRead);
// }
// }
// StringBuilder sb = new StringBuilder();
// for (byte b : md.digest()) {
// sb.append(String.format("%02x", b & 0xff));
// }
// return sb.toString();
// }
//
// private static void uploadFile(String preSignedUrl, Map<String, String> headers,
// String filePath) throws Exception {
// try (FileInputStream fis = new FileInputStream(filePath)) {
// HttpURLConnection conn = (HttpURLConnection) new URL(preSignedUrl).openConnection();
// conn.setRequestMethod("PUT");
// conn.setDoOutput(true);
// conn.setRequestProperty("X-bailian-extra", headers.get("X-bailian-extra"));
// conn.setRequestProperty("Content-Type", headers.get("Content-Type"));
//
// byte[] buffer = new byte[4096];
// int bytesRead;
// while ((bytesRead = fis.read(buffer)) != -1) {
// conn.getOutputStream().write(buffer, 0, bytesRead);
// }
//
// if (conn.getResponseCode() != 200) {
// throw new RuntimeException("上传失败: " + conn.getResponseCode());
// }
// }
// }
//
// private static void waitForFileParsing(com.aliyun.bailian20231229.Client client,
// String workspaceId, String fileId) throws Exception {
// while (true) {
// DescribeFileResponse response = client.describeFileWithOptions(
// workspaceId, fileId, new HashMap<>(), new RuntimeOptions());
//
// String status = response.getBody().getData().getStatus();
// if ("PARSE_SUCCESS".equals(status)) break;
// if ("PARSE_FAILED".equals(status)) throw new RuntimeException("文档解析失败");
// Thread.sleep(5000);
// }
// }
//
// private static void waitForIndexJob(com.aliyun.bailian20231229.Client client,
// String workspaceId, String jobId, String indexId) throws Exception {
// while (true) {
// GetIndexJobStatusRequest request = new GetIndexJobStatusRequest()
// .setIndexId(indexId)
// .setJobId(jobId);
//
// GetIndexJobStatusResponse response = client.getIndexJobStatusWithOptions(
// workspaceId, request, new HashMap<>(), new RuntimeOptions());
//
// String status = response.getBody().getData().getStatus();
// if ("COMPLETED".equals(status)) break;
// if ("FAILED".equals(status)) throw new RuntimeException("索引任务失败");
// Thread.sleep(5000);
// }
// }
//
// private static String calculateMD5(InputStream inputStream) throws Exception {
// MessageDigest md = MessageDigest.getInstance("MD5");
// byte[] buffer = new byte[4096];
// int bytesRead;
// while ((bytesRead = inputStream.read(buffer)) != -1) {
// md.update(buffer, 0, bytesRead);
// }
// StringBuilder sb = new StringBuilder();
// for (byte b : md.digest()) {
// sb.append(String.format("%02x", b & 0xff));
// }
// return sb.toString();
// }
//
// private static void uploadFile(String preSignedUrl, Map<String, String> headers,
// MultipartFile file) throws Exception {
// HttpURLConnection conn = (HttpURLConnection) new URL(preSignedUrl).openConnection();
// conn.setRequestMethod("PUT");
// conn.setDoOutput(true);
// conn.setRequestProperty("X-bailian-extra", headers.get("X-bailian-extra"));
// conn.setRequestProperty("Content-Type", headers.get("Content-Type"));
//
// try (InputStream inputStream = file.getInputStream()) {
// byte[] buffer = new byte[4096];
// int bytesRead;
// while ((bytesRead = inputStream.read(buffer)) != -1) {
// conn.getOutputStream().write(buffer, 0, bytesRead);
// }
// }
//
// if (conn.getResponseCode() != 200) {
// throw new RuntimeException("上传失败: " + conn.getResponseCode());
// }
// }
//
// /**
// * 初始化客户端Client
// *
// * @return 配置好的客户端对象
// */
// public static com.aliyun.bailian20231229.Client createClient(String accessKeyId, String accessKeySecret) throws Exception {
// com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
// .setAccessKeyId(accessKeyId)
// .setAccessKeySecret(accessKeySecret);
// // 下方接入地址以公有云的公网接入地址为例,可按需更换接入地址。
// config.endpoint = "bailian.cn-beijing.aliyuncs.com";
// return new com.aliyun.bailian20231229.Client(config);
// }
//
// public static void main(String[] args) throws Exception {
// String ALIBABA_CLOUD_ACCESS_KEY_ID = "LTAI5tD5YRKuxWz6Eg7qrM4P";
// String ALIBABA_CLOUD_ACCESS_KEY_SECRET = "bO8TBDXflOwbtSKimPpG8XrJnyzgTk";
// String WORKSPACE_ID = "llm-4pf5auwewoz34zqu";
// String indexId = "b9pvwfqp3d";
// String filePath = "D:\\公司经济责任审计方案模板.docx";
//
// Client client = createClient(ALIBABA_CLOUD_ACCESS_KEY_ID, ALIBABA_CLOUD_ACCESS_KEY_SECRET);
//
// uploadDocument(client, WORKSPACE_ID, indexId, filePath);
// }
//}

View File

@@ -1,136 +1,156 @@
package com.gxwebsoft.ai.util;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.aliyun.bailian20231229.models.CreateIndexResponse;
import com.aliyun.bailian20231229.models.DeleteFileResponse;
import com.aliyun.bailian20231229.models.DeleteIndexDocumentResponse;
import com.aliyun.bailian20231229.models.DeleteIndexResponse;
import com.aliyun.bailian20231229.models.ListIndexDocumentsResponse;
import com.aliyun.bailian20231229.models.ListIndicesResponse;
import com.aliyun.bailian20231229.models.RetrieveRequest;
import com.aliyun.bailian20231229.models.RetrieveResponse;
import com.aliyun.teautil.models.RuntimeOptions;
/**
* 知识库工具类
* @author GIIT-YC
*
*/
public class KnowledgeBaseUtil {
/**
* 在指定的知识库中检索信息。
*
* @param client 客户端对象bailian20231229Client
* @param workspaceId 业务空间ID
* @param indexId 知识库ID
* @param query 检索查询语句
* @return 阿里云百炼服务的响应
*/
public static RetrieveResponse retrieveIndex(com.aliyun.bailian20231229.Client client, String workspaceId, String indexId, String query) throws Exception {
RetrieveRequest retrieveRequest = new RetrieveRequest();
retrieveRequest.setIndexId(indexId);
retrieveRequest.setQuery(query);
retrieveRequest.setDenseSimilarityTopK(null);
RuntimeOptions runtime = new RuntimeOptions();
return client.retrieveWithOptions(workspaceId, retrieveRequest, null, runtime);
}
/**
* 在阿里云百炼服务中创建知识库(初始化)。
*
* @param client 客户端对象
* @param workspaceId 业务空间ID
* @param name 知识库名称
* @param desc 知识库描述
* @return 阿里云百炼服务的响应对象
*/
public static CreateIndexResponse createIndex(com.aliyun.bailian20231229.Client client, String workspaceId, String name, String desc) throws Exception {
Map<String, String> headers = new HashMap<>();
com.aliyun.bailian20231229.models.CreateIndexRequest createIndexRequest = new com.aliyun.bailian20231229.models.CreateIndexRequest();
createIndexRequest.setStructureType("unstructured");
createIndexRequest.setName(name);
createIndexRequest.setDescription(desc);
createIndexRequest.setSinkType("DEFAULT");
createIndexRequest.setEmbeddingModelName("text-embedding-v4");
com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
return client.createIndexWithOptions(workspaceId, createIndexRequest, headers, runtime);
}
/**
* 获取指定业务空间下一个或多个知识库的详细信息
*
* @param client 客户端Client
* @param workspaceId 业务空间ID
* @return 阿里云百炼服务的响应
*/
public static ListIndicesResponse listIndices(com.aliyun.bailian20231229.Client client, String workspaceId) throws Exception {
Map<String, String> headers = new HashMap<>();
com.aliyun.bailian20231229.models.ListIndicesRequest listIndicesRequest = new com.aliyun.bailian20231229.models.ListIndicesRequest();
com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
return client.listIndicesWithOptions(workspaceId, listIndicesRequest, headers, runtime);
}
/**
* 永久性删除指定的知识库
*
* @param client 客户端Client
* @param workspaceId 业务空间ID
* @param indexId 知识库ID
* @return 阿里云百炼服务的响应
*/
public static DeleteIndexResponse deleteIndex(com.aliyun.bailian20231229.Client client, String workspaceId, String indexId) throws Exception {
Map<String, String> headers = new HashMap<>();
com.aliyun.bailian20231229.models.DeleteIndexRequest deleteIndexRequest = new com.aliyun.bailian20231229.models.DeleteIndexRequest();
deleteIndexRequest.setIndexId(indexId);
com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
return client.deleteIndexWithOptions(workspaceId, deleteIndexRequest, headers, runtime);
}
/**
* 查询知识库下的文档列表
*
* @param client 客户端Client
* @param workspaceId 业务空间ID
* @param indexId 知识库ID
* @return 阿里云百炼服务的响应
*/
public static ListIndexDocumentsResponse listIndexDocuments(com.aliyun.bailian20231229.Client client, String workspaceId, String indexId, Integer pageSize, Integer pageNumber) throws Exception {
com.aliyun.bailian20231229.models.ListIndexDocumentsRequest listIndexDocumentsRequest = new com.aliyun.bailian20231229.models.ListIndexDocumentsRequest();
listIndexDocumentsRequest.setIndexId(indexId);
listIndexDocumentsRequest.setPageSize(pageSize);
listIndexDocumentsRequest.setPageNumber(pageNumber);
return client.listIndexDocuments(workspaceId, listIndexDocumentsRequest);
}
/**
* 删除知识库下的文档
*
* @param client 客户端Client
* @param workspaceId 业务空间ID
* @param indexId 知识库ID
* @param ids 删除文件ID列表
* @return 阿里云百炼服务的响应
*/
public static DeleteIndexDocumentResponse deleteIndexDocument(com.aliyun.bailian20231229.Client client, String workspaceId, String indexId, List<String> ids) throws Exception {
com.aliyun.bailian20231229.models.DeleteIndexDocumentRequest deleteIndexDocumentRequest = new com.aliyun.bailian20231229.models.DeleteIndexDocumentRequest();
deleteIndexDocumentRequest.setIndexId(indexId);
deleteIndexDocumentRequest.setDocumentIds(ids);
return client.deleteIndexDocument(workspaceId, deleteIndexDocumentRequest);
}
/**
* 删除阿里云应用数据文档
*
* @param client 客户端Client
* @param workspaceId 业务空间ID
* @param fileId 删除文件ID
* @return 阿里云百炼服务的响应
*/
public static DeleteFileResponse deleteAppDocument(com.aliyun.bailian20231229.Client client, String workspaceId, String fileId) throws Exception {
return client.deleteFile(fileId, workspaceId);
}
}
//package com.gxwebsoft.ai.util;
//
//import java.util.ArrayList;
//import java.util.HashMap;
//import java.util.List;
//import java.util.Map;
//
//import com.alibaba.fastjson.JSON;
//import com.aliyun.bailian20231229.models.CreateIndexResponse;
//import com.aliyun.bailian20231229.models.DeleteFileResponse;
//import com.aliyun.bailian20231229.models.DeleteIndexDocumentResponse;
//import com.aliyun.bailian20231229.models.DeleteIndexResponse;
//import com.aliyun.bailian20231229.models.ListIndexDocumentsResponse;
//import com.aliyun.bailian20231229.models.ListIndicesResponse;
//import com.aliyun.bailian20231229.models.RetrieveRequest;
//import com.aliyun.bailian20231229.models.RetrieveResponse;
//import com.aliyun.teautil.models.RuntimeOptions;
//
///**
// * 知识库工具类
// * @author GIIT-YC
// *
// */
//public class KnowledgeBaseUtil {
//
// /**
// * 在指定的知识库中检索信息。
// *
// * @param client 客户端对象bailian20231229Client
// * @param workspaceId 业务空间ID
// * @param indexId 知识库ID
// * @param query 检索查询语句
// * @return 阿里云百炼服务的响应
// */
// public static RetrieveResponse retrieveIndex(com.aliyun.bailian20231229.Client client, String workspaceId, String indexId, String query) throws Exception {
// RetrieveRequest retrieveRequest = new RetrieveRequest();
// retrieveRequest.setIndexId(indexId);
// retrieveRequest.setQuery(query);
// retrieveRequest.setDenseSimilarityTopK(100);
// retrieveRequest.setSparseSimilarityTopK(100);
// retrieveRequest.setEnableReranking(false);//开启耗费巨量token
// RuntimeOptions runtime = new RuntimeOptions();
// return client.retrieveWithOptions(workspaceId, retrieveRequest, null, runtime);
// }
//
// public static RetrieveResponse retrieveIndex(com.aliyun.bailian20231229.Client client, String workspaceId, String indexId, String query, List<String> filesIds) throws Exception {
// RetrieveRequest retrieveRequest = new RetrieveRequest();
// retrieveRequest.setIndexId(indexId);
// retrieveRequest.setQuery(query);
// retrieveRequest.setDenseSimilarityTopK(100);
// retrieveRequest.setSparseSimilarityTopK(100);
// retrieveRequest.setEnableReranking(false);//开启耗费巨量token
// List<Map<String, String>> searchFilters = new ArrayList<>();
// Map<String, String> searchFiltersTags = new HashMap<>();
// searchFiltersTags.put("tags", JSON.toJSONString(filesIds));
// searchFilters.add(searchFiltersTags);
// retrieveRequest.setSearchFilters(searchFilters);
// RuntimeOptions runtime = new RuntimeOptions();
// return client.retrieveWithOptions(workspaceId, retrieveRequest, null, runtime);
// }
//
// /**
// * 在阿里云百炼服务中创建知识库(初始化)。
// *
// * @param client 客户端对象
// * @param workspaceId 业务空间ID
// * @param name 知识库名称
// * @param desc 知识库描述
// * @return 阿里云百炼服务的响应对象
// */
// public static CreateIndexResponse createIndex(com.aliyun.bailian20231229.Client client, String workspaceId, String name, String desc) throws Exception {
// Map<String, String> headers = new HashMap<>();
// com.aliyun.bailian20231229.models.CreateIndexRequest createIndexRequest = new com.aliyun.bailian20231229.models.CreateIndexRequest();
// createIndexRequest.setStructureType("unstructured");
// createIndexRequest.setName(name);
// createIndexRequest.setDescription(desc);
// createIndexRequest.setSinkType("DEFAULT");
// createIndexRequest.setEmbeddingModelName("text-embedding-v4");
// com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
// return client.createIndexWithOptions(workspaceId, createIndexRequest, headers, runtime);
// }
//
// /**
// * 获取指定业务空间下一个或多个知识库的详细信息
// *
// * @param client 客户端Client
// * @param workspaceId 业务空间ID
// * @return 阿里云百炼服务的响应
// */
// public static ListIndicesResponse listIndices(com.aliyun.bailian20231229.Client client, String workspaceId) throws Exception {
// Map<String, String> headers = new HashMap<>();
// com.aliyun.bailian20231229.models.ListIndicesRequest listIndicesRequest = new com.aliyun.bailian20231229.models.ListIndicesRequest();
// com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
// return client.listIndicesWithOptions(workspaceId, listIndicesRequest, headers, runtime);
// }
//
// /**
// * 永久性删除指定的知识库
// *
// * @param client 客户端Client
// * @param workspaceId 业务空间ID
// * @param indexId 知识库ID
// * @return 阿里云百炼服务的响应
// */
// public static DeleteIndexResponse deleteIndex(com.aliyun.bailian20231229.Client client, String workspaceId, String indexId) throws Exception {
// Map<String, String> headers = new HashMap<>();
// com.aliyun.bailian20231229.models.DeleteIndexRequest deleteIndexRequest = new com.aliyun.bailian20231229.models.DeleteIndexRequest();
// deleteIndexRequest.setIndexId(indexId);
// com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
// return client.deleteIndexWithOptions(workspaceId, deleteIndexRequest, headers, runtime);
// }
//
// /**
// * 查询知识库下的文档列表
// *
// * @param client 客户端Client
// * @param workspaceId 业务空间ID
// * @param indexId 知识库ID
// * @return 阿里云百炼服务的响应
// */
// public static ListIndexDocumentsResponse listIndexDocuments(com.aliyun.bailian20231229.Client client, String workspaceId, String indexId, Integer pageSize, Integer pageNumber) throws Exception {
// com.aliyun.bailian20231229.models.ListIndexDocumentsRequest listIndexDocumentsRequest = new com.aliyun.bailian20231229.models.ListIndexDocumentsRequest();
// listIndexDocumentsRequest.setIndexId(indexId);
// listIndexDocumentsRequest.setPageSize(pageSize);
// listIndexDocumentsRequest.setPageNumber(pageNumber);
// return client.listIndexDocuments(workspaceId, listIndexDocumentsRequest);
// }
//
// /**
// * 删除知识库下的文档
// *
// * @param client 客户端Client
// * @param workspaceId 业务空间ID
// * @param indexId 知识库ID
// * @param ids 删除文件ID列表
// * @return 阿里云百炼服务的响应
// */
// public static DeleteIndexDocumentResponse deleteIndexDocument(com.aliyun.bailian20231229.Client client, String workspaceId, String indexId, List<String> ids) throws Exception {
// com.aliyun.bailian20231229.models.DeleteIndexDocumentRequest deleteIndexDocumentRequest = new com.aliyun.bailian20231229.models.DeleteIndexDocumentRequest();
// deleteIndexDocumentRequest.setIndexId(indexId);
// deleteIndexDocumentRequest.setDocumentIds(ids);
// return client.deleteIndexDocument(workspaceId, deleteIndexDocumentRequest);
// }
//
// /**
// * 删除阿里云应用数据文档
// *
// * @param client 客户端Client
// * @param workspaceId 业务空间ID
// * @param fileId 删除文件ID
// * @return 阿里云百炼服务的响应
// */
// public static DeleteFileResponse deleteAppDocument(com.aliyun.bailian20231229.Client client, String workspaceId, String fileId) throws Exception {
// return client.deleteFile(fileId, workspaceId);
// }
//}

View File

@@ -1,6 +1,9 @@
package com.gxwebsoft.common.system.controller;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.common.core.annotation.OperationLog;
import com.gxwebsoft.common.core.config.ConfigProperties;
@@ -316,4 +319,23 @@ public class FileController extends BaseController {
return fail("修改失败");
}
public FileRecord upload(MultipartFile file, Integer tenantId) {
FileRecord fileRecord = new FileRecord();
if (file == null || file.isEmpty()) {
return fileRecord;
}
try {
String requestURL = config.getServerUrl() + "/oss/upload";
String response = HttpRequest.post(requestURL)
.header("Tenantid", tenantId != null ? tenantId.toString() : getTenantId().toString())
.form("file", file.getBytes(), file.getOriginalFilename())
.execute()
.body();
JSONObject data = JSONObject.parseObject(response).getJSONObject("data");
fileRecord = data != null ? BeanUtil.copyProperties(data, FileRecord.class) : fileRecord;
} catch (Exception e) {
e.printStackTrace();
}
return fileRecord;
}
}

View File

@@ -112,6 +112,10 @@ public class OaCompanyController extends BaseController {
@Operation(summary = "删除企业信息")
@DeleteMapping("/{id}")
public ApiResult<?> remove(@PathVariable("id") Integer id) {
//删云目录
oaCompanyService.removeCompanyDocDirectories(id);
//删云知识库
oaCompanyService.removeCompanyKnowledgeBase(id);
if (oaCompanyService.removeById(id)) {
return success("删除成功");
}

View File

@@ -46,4 +46,19 @@ public interface OaCompanyService extends IService<OaCompany> {
* @param userId 创建用户ID
*/
void initCompanyDocDirectories(OaCompany oaCompany, Integer userId);
/**
* 清空企业目录
*
* @param oaCompany 企业Id
*/
boolean removeCompanyDocDirectories(Integer companyId);
/**
* 清空企业知识库
*
* @param oaCompany 企业Id
*/
boolean removeCompanyKnowledgeBase(Integer companyId);
}

View File

@@ -1,16 +1,24 @@
package com.gxwebsoft.oa.service.impl;
import com.aliyun.bailian20231229.Client;
import com.aliyun.bailian20231229.models.DeleteCategoryResponseBody;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gxwebsoft.oa.mapper.OaCompanyMapper;
import com.gxwebsoft.oa.service.OaCompanyService;
import cn.hutool.core.util.StrUtil;
import com.gxwebsoft.oa.entity.OaCompany;
import com.gxwebsoft.oa.param.OaCompanyParam;
import com.gxwebsoft.ai.config.KnowledgeBaseConfig;
import com.gxwebsoft.ai.entity.AiCloudDoc;
import com.gxwebsoft.ai.entity.AiCloudFile;
import com.gxwebsoft.ai.factory.KnowledgeBaseClientFactory;
import com.gxwebsoft.ai.service.AiCloudDocService;
import com.gxwebsoft.ai.service.AiCloudFileService;
import com.gxwebsoft.ai.util.AiCloudDataCenterUtil;
import com.gxwebsoft.ai.util.AiCloudKnowledgeBaseUtil;
import com.gxwebsoft.common.core.web.PageParam;
import com.gxwebsoft.common.core.web.PageResult;
@@ -21,6 +29,7 @@ import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* 企业信息Service实现
@@ -34,6 +43,9 @@ public class OaCompanyServiceImpl extends ServiceImpl<OaCompanyMapper, OaCompany
@Autowired
private AiCloudDocService aiCloudDocService;
@Autowired
private AiCloudFileService aiCloudFileService;
@Autowired
private KnowledgeBaseConfig config;
@@ -123,4 +135,58 @@ public class OaCompanyServiceImpl extends ServiceImpl<OaCompanyMapper, OaCompany
// 批量保存子目录
aiCloudDocService.saveBatch(directories);
}
@Override
public boolean removeCompanyDocDirectories(Integer companyId) {
boolean ret = true;
String workspaceId = config.getWorkspaceId();
if(companyId==null) {
return ret;
}
//目录
List<AiCloudDoc> docList = aiCloudDocService.list(new LambdaQueryWrapper<AiCloudDoc>().eq(AiCloudDoc::getCompanyId, companyId));
List<Integer> docIds = docList.stream().map(AiCloudDoc::getId).collect(Collectors.toList());
//先删目阿里云录下所有文件
List<AiCloudFile> fileList = aiCloudFileService.list(new LambdaQueryWrapper<AiCloudFile>().in(AiCloudFile::getDocId, docIds));
List<Integer> fileIds = fileList.stream().map(AiCloudFile::getId).collect(Collectors.toList());
for(AiCloudFile file : fileList) {
try {
Client client = clientFactory.createClient();
AiCloudDataCenterUtil.deleteFile(client, workspaceId, file.getFileId());
} catch (Exception e) {
e.printStackTrace();
}
}
//再删阿里云目录
List<String> categoryIds = docList.stream().map(AiCloudDoc::getCategoryId).filter(StrUtil::isNotBlank).distinct().collect(Collectors.toList());
for(String categoryId : categoryIds) {
try {
Client client = clientFactory.createClient();
ret = AiCloudDataCenterUtil.deleteCategory(client, workspaceId, categoryId).getBody().getSuccess();
} catch (Exception e) {
e.printStackTrace();
}
}
aiCloudDocService.removeByIds(docIds);
aiCloudFileService.removeByIds(fileIds);
return ret;
}
@Override
public boolean removeCompanyKnowledgeBase(Integer companyId) {
boolean ret = true;
String workspaceId = config.getWorkspaceId();
if(companyId==null) {
return ret;
}
//删阿里云知识库
OaCompany oaCompany = baseMapper.selectById(companyId);
try {
Client client = clientFactory.createClient();
ret = AiCloudKnowledgeBaseUtil.deleteIndex(client, workspaceId, oaCompany.getKbId()).getBody().getSuccess();
} catch (Exception e) {
e.printStackTrace();
}
return ret;
}
}

View File

@@ -3,6 +3,7 @@ package com.gxwebsoft.pwl.controller;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -135,7 +136,8 @@ public class PwlProjectController extends BaseController {
//asLibCode = as00000000001
String asLibCode = "as" + StrUtil.padPre(pwlProject.getId().toString(), 11, '0');
// String asLibCode = "as"+pwlProject.getCode();
String analysisKbId = knowledgeBaseService.createKnowledgeBase(asLibName, asLibCode);
// String analysisKbId = knowledgeBaseService.createKnowledgeBase(asLibName, asLibCode);
String analysisKbId = RandomUtil.randomString(10);
pwlProject.setAnalysisLibrary(analysisKbId);
} catch (Exception e) {
e.printStackTrace();
@@ -152,7 +154,8 @@ public class PwlProjectController extends BaseController {
//pjLibCode = pj00000000001
String pjLibCode = "pj" + StrUtil.padPre(pwlProject.getId().toString(), 11, '0');
// String pjLibCode = "pj"+pwlProject.getCode();
String projectKbId = knowledgeBaseService.createKnowledgeBase(pjLibName, pjLibCode);
// String projectKbId = knowledgeBaseService.createKnowledgeBase(pjLibName, pjLibCode);
String projectKbId = RandomUtil.randomString(10);
pwlProject.setProjectLibrary(projectKbId);
} catch (Exception e) {
e.printStackTrace();

View File

@@ -41,6 +41,9 @@ public class PwlProject implements Serializable {
@Schema(description = "项目标识")
private String code;
@Schema(description = "案引号")
private String caseIndex;
@Schema(description = "上级id, 0是顶级")
private Integer parentId;

View File

@@ -21,6 +21,9 @@
<if test="param.code != null">
AND a.code LIKE CONCAT('%', #{param.code}, '%')
</if>
<if test="param.caseIndex != null">
AND a.case_index LIKE CONCAT('%', #{param.caseIndex}, '%')
</if>
<if test="param.parentId != null">
AND a.parent_id = #{param.parentId}
</if>

View File

@@ -40,6 +40,9 @@ public class PwlProjectParam extends BaseParam {
@Schema(description = "项目标识")
private String code;
@Schema(description = "案引号")
private String caseIndex;
@Schema(description = "上级id, 0是顶级")
@QueryField(type = QueryType.EQ)
private Integer parentId;

View File

@@ -77,3 +77,7 @@ ai:
word-template-path: classpath:templates/audit_report_template.docx
# 或者使用绝对路径
# word-template-path: D:\\公司经济责任审计方案模板.docx
# Word 取证单模板路径
evidence-template-path: classpath:templates/audit_evidence_template.docx
# Word 取证单绝对路径
#evidence-template-path: D:\\audit_evidence_template.docx

View File

@@ -83,3 +83,7 @@ ai:
word-template-path: classpath:templates/audit_report_template.docx
# 或者使用绝对路径
# word-template-path: D:\\公司经济责任审计方案模板.docx
# Word 取证单模板路径
evidence-template-path: classpath:templates/audit_evidence_template.docx
# Word 取证单绝对路径
#evidence-template-path: D:\\audit_evidence_template.docx