diff --git a/src/main/java/com/gxwebsoft/ai/constants/AuditContent4TargetConstants.java b/src/main/java/com/gxwebsoft/ai/constants/AuditContent4TargetConstants.java new file mode 100644 index 0000000..3e4a61f --- /dev/null +++ b/src/main/java/com/gxwebsoft/ai/constants/AuditContent4TargetConstants.java @@ -0,0 +1,150 @@ +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 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); + KEYWORD_WEIGHTS.put("地矿局", 6); + } + + // 审计要点提示 + 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: 工作底稿索引"; + + // 获取分类的简要审计框架概述 + public static String getBriefAuditFrameworkForCategory(String category) { + if (CATEGORY_TARGET_RESPONSIBILITY.equals(category)) { + return "审计目标责任制的制定、执行和完成情况,评估落实效果"; + } + return "审计目标责任制完成情况"; + } + + // 字段映射(用于前端展示) + public static final Map 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\": [\"实际存在的完整文件名1\", \"实际存在的完整文件名2\", ...]\n" + + " }\n" + + "]\n\n" + + "重要说明:\n" + + "1. 每个审计记录对应一个具体的文件或目标\n" + + "2. 同一年度可能有多个目标责任,每个都应生成独立的审计记录\n" + + "3. 尽可能从知识库中提取所有相关信息,生成尽可能多的记录"; + +} \ No newline at end of file diff --git a/src/main/java/com/gxwebsoft/ai/controller/AuditContent4Controller.java b/src/main/java/com/gxwebsoft/ai/controller/AuditContent4Controller.java new file mode 100644 index 0000000..f8eddb4 --- /dev/null +++ b/src/main/java/com/gxwebsoft/ai/controller/AuditContent4Controller.java @@ -0,0 +1,299 @@ +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.TargetAuditExportEntity; +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.AuditContent4TargetService; +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.stream.Collectors; + +/** + * 审计内容4控制器 - 目标责任制完成情况审计 + */ +@Slf4j +@Tag(name = "审计内容4-目标责任制完成情况") +@RestController +@RequestMapping("/api/ai/auditContent4") +public class AuditContent4Controller extends BaseController { + + @Autowired + private AuditContent4TargetService auditContent4TargetService; + + @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; + + /** + * 生成目标责任制完成情况审计表数据 + */ + @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 + )); + } + + /** + * 通用的表格数据生成方法 + */ + private ApiResult generateTableData(AuditContentRequest request, String interfaceName, Function 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 idList = StrUtil.split(libraryIds, ','); + List ret = pwlProjectLibraryService.list(new LambdaQueryWrapper().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 docIds = request.getDocList().stream().flatMap(docId -> aiCloudDocService.getSelfAndChildren(docId).stream()).map(AiCloudDoc::getId).collect(Collectors.toSet()); + // 查询相关文件 + List fileList = getRelatedFiles(docIds, request.getFileList()); + // 提取文件ID并提交到知识库 + Set kbFileIds = fileList.stream().map(AiCloudFile::getFileId).collect(Collectors.toSet()); + if (!kbFileIds.isEmpty()) { + knowledgeBaseService.submitDocuments(kbIdTmp, new ArrayList<>(kbFileIds)); + } + return kbIdTmp; + } + + /** + * 获取相关文件列表 + */ + private List getRelatedFiles(Set docIds, List fileList) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper() + .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 + */ + @Operation(summary = "导出目标责任制完成情况审计表到Excel") + @PostMapping("/exportTargetTable") + public void exportTargetTable(@RequestBody Map request, HttpServletResponse response) { + exportToExcel(request, response); + } + + /** + * Excel导出方法 + */ + private void exportToExcel(Map request, HttpServletResponse response) { + List> dataList = (List>) request.get("data"); + String companyName = (String) request.get("companyName"); + + List 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 convertToExportEntityList(List> originalData) { + return originalData.stream().map(this::convertToExportEntity).collect(Collectors.toList()); + } + + private TargetAuditExportEntity convertToExportEntity(Map 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; + } + + private String getStringValue(Map 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(); + } + + /** + * 参数包装类 + */ + 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; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/gxwebsoft/ai/dto/export/TargetAuditExportEntity.java b/src/main/java/com/gxwebsoft/ai/dto/export/TargetAuditExportEntity.java new file mode 100644 index 0000000..5d60038 --- /dev/null +++ b/src/main/java/com/gxwebsoft/ai/dto/export/TargetAuditExportEntity.java @@ -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; +} \ No newline at end of file diff --git a/src/main/java/com/gxwebsoft/ai/service/AuditContent4TargetService.java b/src/main/java/com/gxwebsoft/ai/service/AuditContent4TargetService.java new file mode 100644 index 0000000..eaff64c --- /dev/null +++ b/src/main/java/com/gxwebsoft/ai/service/AuditContent4TargetService.java @@ -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); +} \ No newline at end of file diff --git a/src/main/java/com/gxwebsoft/ai/service/impl/AuditContent4TargetServiceImpl.java b/src/main/java/com/gxwebsoft/ai/service/impl/AuditContent4TargetServiceImpl.java new file mode 100644 index 0000000..a533df4 --- /dev/null +++ b/src/main/java/com/gxwebsoft/ai/service/impl/AuditContent4TargetServiceImpl.java @@ -0,0 +1,332 @@ +// 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> 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> retrieveKnowledgeForTargetResponsibility(String kbIds, String libraryKbIds, String projectLibrary) { + Map> knowledgeSources = new HashMap<>(); + knowledgeSources.put("enterprise", new ArrayList<>()); + knowledgeSources.put("regulation", new ArrayList<>()); + knowledgeSources.put("auditCase", new ArrayList<>()); + + // 构建查询词 + List 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 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 buildTargetResponsibilityQueries() { + return Arrays.asList( + "目标责任 目标责任制 目标任务", + "下达文件 计划文件 考核办法", + "完成情况 未完成原因 考核结果", + "地矿局 上级主管 主管部门", + "年度计划 工作目标 考核指标", + "责任书 责任状 目标考核", + "经营目标 工作计划 绩效考核", + "重点工作 专项任务 年度总结" + ); + } + + /** + * 构建完整的知识上下文 + */ + private String buildCompleteKnowledgeContext(Map> 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必须填写实际存在的完整文件名,确保能在文件夹中搜索到\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; + } + +} \ No newline at end of file