已删除2个文件
已修改29个文件
已添加30个文件
已重命名2个文件
1749 ■■■■■ 文件已修改
iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/core/ArrayValuable.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/template/XMLParserUtils.java 296 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/.idea/compiler.xml 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/.idea/jarRepositories.xml 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/.idea/misc.xml 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-api/pom.xml 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/api/chat/AiChatConversationApi.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/api/chat/AiChatMessageApi.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/api/chat/dto/AiChatConversationRespDTO.java 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/api/chat/dto/AiChatMessageSendReqDTO.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/api/chat/dto/AiChatMessageSendRespDTO.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/api/chat/dto/AiModelDO.java 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/api/questionTemplate/QuestionTemplateApi.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/api/questionTemplate/QuestiontemplateApi.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/api/questionTemplate/dto/AiModelDTO.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/api/questionTemplate/dto/QuestionTemplateDTO.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/enums/AiChatRoleEnum.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/enums/ApiConstants.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-biz/pom.xml 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/api/QuestionTemplateApiImpl.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/api/chat/AiChatConversionApiImpl.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/api/chat/AiChatMessageApiImpl.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/api/package-info.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/api/template/QuestionTemplateApiImpl.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/controller/admin/chat/AiChatMessageController.java 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/controller/admin/chat/vo/conversation/AiChatConversationCreateEnergyReqVO.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/controller/admin/chat/vo/message/AiChatMessageReqVO.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/controller/admin/questiontemplate/QuestionTemplateController.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/controller/admin/questiontemplate/vo/QuestionTemplateReqVO.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/dal/mysql/chat/AiChatMessageMapper.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/job/image/AiMidjourneySyncJob.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/job/music/AiSunoSyncJob.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/service/chat/AiChatConversationServiceImpl.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/service/chat/AiChatMessageService.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/service/chat/AiChatMessageServiceImpl.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/service/questiontemplate/QuestionTemplateService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/service/questiontemplate/QuestionTemplateServiceImpl.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-biz/src/main/resources/application.yaml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-spring-boot-starter-ai/pom.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/pom.xml 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-api/src/main/java/com/iailab/module/data/api/point/DataPointApi.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-api/src/main/java/com/iailab/module/data/api/point/dto/ApiPointBadHistoryDTO.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-api/src/main/java/com/iailab/module/data/api/point/dto/ApiPointBadHistoryPageReqVO.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-api/src/main/java/com/iailab/module/data/api/point/dto/ApiPointCountReqVO.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/api/controller/admin/ApiDataController.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/api/point/DataPointApiImpl.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/job/config/ScheduleJobListConfig.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/job/task/PointBadHistoryGenerateTask.java 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/point/dao/DaPointBadHistoryDao.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/point/dao/DaPointDao.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/point/dto/DaPointBadHistoryDTO.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/point/entity/DaPointBadHistoryEntity.java 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/point/service/DaPointBadHistoryService.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/point/service/DaPointService.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/point/service/impl/DaPointBadHistoryServiceImpl.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/point/service/impl/DaPointServiceImpl.java 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/point/vo/DaPointBadHistoryPageReqVO.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/point/vo/DaPointCountReqVO.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/resources/application.yaml 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/resources/mapper/point/DaPointDao.xml 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-infra/iailab-module-infra-biz/src/main/resources/application-dev.yaml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/module/model/api/MdkApiImpl.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/mysql/permission/MenuMapper.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/core/ArrayValuable.java
对比新文件
@@ -0,0 +1,15 @@
package com.iailab.framework.common.core;
/**
 * 可生成 T 数组的接口
 *
 * @author HUIHUI
 */
public interface ArrayValuable<T> {
    /**
     * @return 数组
     */
    T[] array();
}
iailab-framework/iailab-common/src/main/java/com/iailab/framework/common/util/template/XMLParserUtils.java
对比新文件
@@ -0,0 +1,296 @@
package com.iailab.framework.common.util.template;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.ByteArrayInputStream;
import java.util.HashMap;
import java.util.Map;
public class XMLParserUtils {
    private final Map<String, String> settings;
    private final double[][] inputData;
    public XMLParserUtils(Map<String, String> settings, double[][] inputData) {
        this.settings = settings;
        this.inputData = inputData;
    }
    public String parse(String xml) throws Exception {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document doc = builder.parse(new ByteArrayInputStream(xml.getBytes()));
        doc.getDocumentElement().normalize();
        StringBuilder output = new StringBuilder();
        processNode(doc.getDocumentElement(), output, -1);
        return output.toString();
    }
    private void processNode(Node node, StringBuilder output, int index) {
        if (node.getNodeType() == Node.TEXT_NODE) {
            output.append(node.getTextContent().trim());
        } else if (node.getNodeType() == Node.ELEMENT_NODE) {
            Element element = (Element) node;
            switch (element.getTagName()) {
                case "simple-value":
                    processSimpleValue(element, output, index);
                    break;
                case "setting-value":
                    processSettingValue(element, output);
                    break;
                case "input-value":
                    processInputValue(element, output, index);
                    break;
                case "foreach-value":
                    processForeachValue(element, output);
                    break;
                default:
                    processChildren(element, output, index);
            }
        }
    }
    private void processChildren(Element element, StringBuilder output, int index) {
        NodeList children = element.getChildNodes();
        for (int i = 0; i < children.getLength(); i++) {
            processNode(children.item(i), output, index);
        }
    }
    private void processSimpleValue(Element element, StringBuilder output, int index) {
        processChildren(element, output, index);
    }
    private void processSettingValue(Element element, StringBuilder output) {
        String key = element.getAttribute("key");
        output.append(settings.getOrDefault(key, ""));
    }
    private void processInputValue(Element element, StringBuilder output, int index) {
        // 优先使用:port属性(动态计算)
        String portExpr = element.getAttribute(":port");
        if (portExpr.isEmpty()) {
            // 回退到port属性(静态值)
            portExpr = element.getAttribute("port");
        }
        String column = element.getAttribute("column");
        int col = Integer.parseInt(column);
        // 动态计算端口值(考虑当前索引)
        int port = evaluateExpression(portExpr, index);
        if (port >= 0 && port < inputData.length &&
                col >= 0 && col < inputData[port].length) {
            double value = inputData[port][col];
            output.append((int)value);
        } else {
            System.err.printf("Invalid data access: port=%d (max=%d), col=%d (max=%d)%n",
                    port, inputData.length - 1, col,
                    (port >= 0 && port < inputData.length) ? inputData[port].length - 1 : -1);
            // 默认值
            output.append("0");
        }
    }
    private void processForeachValue(Element element, StringBuilder output) {
        String lengthKey = element.getAttribute("length");
        int length = Integer.parseInt(settings.getOrDefault(lengthKey, "0"));
        String separator = element.getAttribute("separator");
        StringBuilder loopResult = new StringBuilder();
        for (int i = 0; i < length; i++) {
            StringBuilder itemOutput = new StringBuilder();
            // 直接处理所有子节点
            NodeList children = element.getChildNodes();
            for (int j = 0; j < children.getLength(); j++) {
                Node child = children.item(j);
                if (child.getNodeType() == Node.TEXT_NODE) {
                    String text = child.getTextContent();
                    // 动态确定转炉状态
                    boolean isBlowing = isFurnaceBlowing(i);
                    // 替换占位符并调整状态描述
                    text = text.replace("{index}", String.valueOf(i + 1))
                            .replace("未吹炼", isBlowing ? "正在吹炼" : "未吹炼")
                            .replace("距离上次吹炼结束时间",
                                    isBlowing ? "吹炼持续时间" : "距离上次吹炼结束时间");
                    itemOutput.append(text);
                } else if (child.getNodeType() == Node.ELEMENT_NODE) {
                    // 传递当前循环索引
                    processNode(child, itemOutput, i);
                }
            }
            loopResult.append(itemOutput);
            if (i < length - 1 && !separator.isEmpty()) {
                loopResult.append(separator);
            }
        }
        output.append(loopResult.toString().replace(" ", "").replace("\n", ""));
    }
    private boolean isFurnaceBlowing(int furnaceIndex) {
        // 实际业务逻辑:根据输入数据判断转炉状态
        // 这里简化处理:第三个转炉(index=2)正在吹炼
        return furnaceIndex == 2;
    }
    // 自定义表达式计算器
    private int evaluateExpression(String expr, int index) {
        if (expr == null || expr.isEmpty()) {
            System.err.println("Empty expression, returning 0");
            return 0;
        }
        // 替换表达式中的{index}占位符
        String processedExpr = expr.replace("{index}", String.valueOf(index));
        // 移除所有空格确保表达式正确解析
        processedExpr = processedExpr.replaceAll("\\s", "");
        // 尝试直接解析为整数(优化常见情况)
        try {
            return Integer.parseInt(processedExpr);
        } catch (NumberFormatException e) {
            // 不是简单整数,继续尝试表达式计算
        }
        // 自定义简单表达式解析器
        try {
            // 处理加法表达式(如 "3+0")
            if (processedExpr.contains("+")) {
                String[] parts = processedExpr.split("\\+");
                int result = 0;
                for (String part : parts) {
                    result += Integer.parseInt(part);
                }
                return result;
            }
            // 处理减法表达式(如 "5-2")
            else if (processedExpr.contains("-")) {
                String[] parts = processedExpr.split("-");
                int result = Integer.parseInt(parts[0]);
                for (int i = 1; i < parts.length; i++) {
                    result -= Integer.parseInt(parts[i]);
                }
                return result;
            }
//            // 处理乘法表达式(如 "2 * 3")
//            else if (processedExpr.contains("*")) {
//                String[] parts = processedExpr.split("\\*");
//                int result = 1;
//                for (String part : parts) {
//                    result *= Integer.parseInt(part);
//                }
//                return result;
//            }
//            // 处理除法表达式(如 "6/2")
//            else if (processedExpr.contains("/")) {
//                String[] parts = processedExpr.split("/");
//                int result = Integer.parseInt(parts[0]);
//                for (int i = 1; i < parts.length; i++) {
//                    int divisor = Integer.parseInt(parts[i]);
//                    if (divisor != 0) {
//                        result /= divisor;
//                    }
//                }
//                return result;
//            }
        } catch (NumberFormatException e) {
            System.err.println("Error parsing expression: " + processedExpr);
        }
        // 无法解析的表达式
        System.err.println("Unsupported expression format: " + processedExpr);
        return 0;
    }
    // test
    public static void main(String[] args) throws Exception {
        String xmlContent = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                "<iquestion>\n" +
                "    <simple-value>根据以下输入,</simple-value>\n" +
                "    <simple-value>\n" +
                "        根据未来<setting-value key=\"predictLength\"/>min的转炉煤气系统运行情况,对煤气调整用户进行调度分配,确保能源产消平衡与系统稳定运行。\n" +
                "    </simple-value>\n" +
                "    <simple-value>\n" +
                "        该系统共包含<setting-value key=\"luShu\"/>座转炉。\n" +
                "    </simple-value>\n" +
                "    <foreach-value length=\"luShu\" index=\"index\" separator=\";\">\n" +
                "        {index}#转炉当前状态未吹炼,\n" +
                "        距离上次吹炼结束时间<input-value :port=\"3 + {index}\" column=\"0\" type=\"double\"/>min,\n" +
                "        前一炉回收间隔<input-value :port=\"3 + {index}\" column=\"2\" type=\"double\"/>min\n" +
                "    </foreach-value>\n" +
                "    <simple-value>\n" +
                "        日计划炉数:<input-value port=\"2\" column=\"0\" type=\"double\"/>,当前已吹炼炉数:<input-value port=\"3\" column=\"0\" type=\"double\"/>;\n" +
                "    </simple-value>\n" +
                "    <simple-value>\n" +
                "        历史60min平均每炉煤气回收量:<input-value port=\"1\" column=\"0\" type=\"double\"/>Km3,\n" +
                "    </simple-value>\n" +
                "    <simple-value>\n" +
                "        当前煤气消耗量<input-value port=\"1\" column=\"1\" type=\"double\"/>km3;\n" +
                "    </simple-value>\n" +
                "    <simple-value>\n" +
                "        当前煤气柜容量<setting-value key=\"guiRongLiang\"/>km3;\n" +
                "    </simple-value>\n" +
                "    <simple-value>\n" +
                "        煤气柜柜位安全区间为<setting-value key=\"anQuanQuJian\"/>km3,期望煤气柜位值在<setting-value key=\"qiWangZhi\"/>km3,\n" +
                "    </simple-value>\n" +
                "    <simple-value>\n" +
                "        当前调度用户为电厂各机组:<setting-value key=\"jiZuMingCheng\"/>,\n" +
                "    </simple-value>\n" +
                "    <simple-value>\n" +
                "        各机组当前使用转炉煤气量 [<input-value port=\"0\" column=\"0\" type=\"double\"/>, <input-value port=\"0\" column=\"1\" type=\"double\"/>, <input-value port=\"0\" column=\"2\" type=\"double\"/>, <input-value port=\"0\" column=\"3\" type=\"double\"/>, <input-value port=\"0\" column=\"4\" type=\"double\"/>, <input-value port=\"0\" column=\"5\" type=\"double\"/>];\n" +
                "    </simple-value>\n" +
                "    <simple-value>\n" +
                "        各机组使用转炉煤气下限量 <setting-value key=\"jiZuXiaXian\"/>。\n" +
                "    </simple-value>\n" +
                "    <simple-value>\n" +
                "        各机组使用转炉煤气上限量 <setting-value key=\"jiZuShangXian\"/>。\n" +
                "    </simple-value>\n" +
                "    <simple-value>\n" +
                "        机组优先级顺序为:<setting-value key=\"jiZuYouXianJi\"/>。\n" +
                "    </simple-value>\n" +
                "    <simple-value>请根据优先级顺序确定调度方案。</simple-value>\n" +
                "</iquestion>";
        // 1. 准备配置数据
        Map<String, String> settings = new HashMap<>();
        settings.put("predictLength", "60");
        settings.put("luShu", "3");
        settings.put("guiRongLiang", "80");
        settings.put("anQuanQuJian", "[30, 110]");
        settings.put("qiWangZhi", "65");
        settings.put("jiZuMingCheng", "1#135, 2#135, 1#BTG, 2#BTG, 3#BTG, 4#BTG");
        settings.put("jiZuXiaXian", "[20, 1, 16, 17, 6, 11]");
        settings.put("jiZuShangXian", "[92, 96, 74, 101, 86, 93]");
        settings.put("jiZuYouXianJi", "1#135, 1#BTG, 3#BTG, 2#135, 2#BTG, 4#BTG");
        // 示例输入数据 - 与期望输出完全匹配
        double[][] inputData = {
                // 机组当前用量
                {39, 39, 32, 56, 38, 48},
                // [0]:历史回收量, [1]:当前消耗量
                {24, 115},
                // [0]:日计划炉数, [1]:已吹炼炉数
                {21, 10},
                // 转炉1: [0]:结束时间, [2]:回收间隔
                {15, 0, 18},
                // 转炉2: [0]:结束时间, [2]:回收间隔
                {9, 0, 24},
                // 转炉3: [0]:吹炼持续时间, [2]:回收间隔
                {7, 0, 25}
        };
        // 3. 创建解析器并执行
        XMLParserUtils parser = new XMLParserUtils(settings, inputData);
        String result = parser.parse(xmlContent); // 替换为你的XML内容
        System.out.println(result);
    }
}
iailab-module-ai/.idea/compiler.xml
对比新文件
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="CompilerConfiguration">
    <annotationProcessing>
      <profile default="true" name="Default" enabled="true" />
      <profile name="Maven default annotation processors profile" enabled="true">
        <sourceOutputDir name="target/generated-sources/annotations" />
        <sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
        <outputRelativeToContentRoot value="true" />
        <module name="yudao-module-ai-api" />
      </profile>
      <profile name="Annotation profile for iailab-module-ai" enabled="true">
        <sourceOutputDir name="target/generated-sources/annotations" />
        <sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
        <outputRelativeToContentRoot value="true" />
        <processorPath useClasspath="false">
          <entry name="$PROJECT_DIR$/../../../../.m2/repository/org/springframework/boot/spring-boot-configuration-processor/3.4.1/spring-boot-configuration-processor-3.4.1.jar" />
          <entry name="$PROJECT_DIR$/../../../../.m2/repository/org/projectlombok/lombok/1.18.36/lombok-1.18.36.jar" />
          <entry name="$PROJECT_DIR$/../../../../.m2/repository/org/mapstruct/mapstruct-processor/1.6.3/mapstruct-processor-1.6.3.jar" />
          <entry name="$PROJECT_DIR$/../../../../.m2/repository/org/mapstruct/mapstruct/1.6.3/mapstruct-1.6.3.jar" />
        </processorPath>
        <module name="iailab-module-ai-api" />
        <module name="iailab-spring-boot-starter-ai" />
        <module name="iailab-module-ai-biz" />
      </profile>
    </annotationProcessing>
  </component>
  <component name="JavacSettings">
    <option name="ADDITIONAL_OPTIONS_OVERRIDE">
      <module name="iailab-module-ai-api" options="-parameters" />
      <module name="iailab-module-ai-biz" options="-parameters" />
      <module name="iailab-spring-boot-starter-ai" options="-parameters" />
    </option>
  </component>
</project>
iailab-module-ai/.idea/jarRepositories.xml
对比新文件
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="RemoteRepositoriesConfiguration">
    <remote-repository>
      <option name="id" value="central" />
      <option name="name" value="Central Repository" />
      <option name="url" value="https://repo.maven.apache.org/maven2" />
    </remote-repository>
    <remote-repository>
      <option name="id" value="iailab" />
      <option name="name" value="iailab" />
      <option name="url" value="http://172.16.8.100:8090/repository/iailab/" />
    </remote-repository>
    <remote-repository>
      <option name="id" value="central" />
      <option name="name" value="Maven Central repository" />
      <option name="url" value="https://repo1.maven.org/maven2" />
    </remote-repository>
    <remote-repository>
      <option name="id" value="jboss.community" />
      <option name="name" value="JBoss Community repository" />
      <option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
    </remote-repository>
    <remote-repository>
      <option name="id" value="iailab" />
      <option name="name" value="iailab" />
      <option name="url" value="http://www.jira.dlindusit.com:30078/repository/iailab/" />
    </remote-repository>
  </component>
</project>
iailab-module-ai/.idea/misc.xml
对比新文件
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="ExternalStorageConfigurationManager" enabled="true" />
  <component name="MavenProjectsManager">
    <option name="originalFiles">
      <list>
        <option value="$PROJECT_DIR$/pom.xml" />
        <option value="$PROJECT_DIR$/iailab-module-ai-api/pom.xml" />
        <option value="$PROJECT_DIR$/iailab-spring-boot-starter-ai/pom.xml" />
      </list>
    </option>
  </component>
  <component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="graalvm-jdk-17" project-jdk-type="JavaSDK" />
</project>
iailab-module-ai/iailab-module-ai-api/pom.xml
@@ -5,7 +5,7 @@
    <parent>
        <groupId>com.iailab</groupId>
        <artifactId>iailab-module-ai</artifactId>
        <version>${ai.revision}</version>
        <version>${revision}</version>
    </parent>
    <build>
        <plugins>
@@ -13,8 +13,8 @@
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>17</source>
                    <target>17</target>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
@@ -34,21 +34,26 @@
            <artifactId>iailab-common</artifactId>
        </dependency>
        <!-- Web 相关 -->
        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-ui</artifactId>
            <version>1.8.0</version>
            <scope>provided</scope> <!-- 设置为 provided,主要是 PageParam 使用到 -->
        </dependency>
        <!-- 参数校验 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
            <optional>true</optional>
        </dependency>
        <!-- RPC 远程调用相关 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-openfeign-core</artifactId>
        </dependency>
        <dependency>
            <groupId>io.swagger.core.v3</groupId>
            <artifactId>swagger-annotations</artifactId>
            <version>2.2.25</version>
            <scope>compile</scope>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>
</project>
iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/api/chat/AiChatConversationApi.java
对比新文件
@@ -0,0 +1,20 @@
package com.iailab.module.ai.api.chat;
import com.iailab.framework.common.pojo.CommonResult;
import com.iailab.module.ai.enums.ApiConstants;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(name = ApiConstants.NAME)
@Tag(name = "RPC 大模型会话")
public interface AiChatConversationApi {
    String PREFIX = ApiConstants.PREFIX + "/conversation";
    @GetMapping(PREFIX + "/energy-conversation")
    @Operation(summary = "会话列表", description = "查询会话列表,只有一条,首次查询先创建再查询")
    Long chatEnergyConversation(@RequestParam("modelName") String modelName);
}
iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/api/chat/AiChatMessageApi.java
对比新文件
@@ -0,0 +1,22 @@
package com.iailab.module.ai.api.chat;
import com.iailab.module.ai.api.chat.dto.AiChatMessageSendRespDTO;
import com.iailab.module.ai.api.chat.dto.AiChatMessageSendReqDTO;
import com.iailab.module.ai.enums.ApiConstants;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@FeignClient(name = ApiConstants.NAME)
@Tag(name = "RPC 大模型消息")
public interface AiChatMessageApi {
    String PREFIX = ApiConstants.PREFIX + "/message";
    @PostMapping(PREFIX + "/send-message")
    @Operation(summary = "发送消息(段式)", description = "一次性返回,响应较慢")
    AiChatMessageSendRespDTO sendMessage(@Valid @RequestBody AiChatMessageSendReqDTO sendReqDTO);
}
iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/api/chat/dto/AiChatConversationRespDTO.java
对比新文件
@@ -0,0 +1,58 @@
package com.iailab.module.ai.api.chat.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import java.time.LocalDateTime;
public class AiChatConversationRespDTO {
    @Schema(description = "对话编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
    private Long id;
    @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
    private Long userId;
    @Schema(description = "对话标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是一个标题")
    private String title;
    @Schema(description = "是否置顶", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
    private Boolean pinned;
    @Schema(description = "角色编号", example = "1")
    private Long roleId;
    @Schema(description = "模型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
    private Long modelId;
    @Schema(description = "模型标志", requiredMode = Schema.RequiredMode.REQUIRED, example = "ERNIE-Bot-turbo-0922")
    private String model;
    @Schema(description = "模型名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三")
    private String modelName;
    @Schema(description = "角色设定", example = "一个快乐的程序员")
    private String systemMessage;
    @Schema(description = "温度参数", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.8")
    private Double temperature;
    @Schema(description = "单条回复的最大 Token 数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "4096")
    private Integer maxTokens;
    @Schema(description = "上下文的最大 Message 数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
    private Integer maxContexts;
    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
    private LocalDateTime createTime;
    // ========== 关联 role 信息 ==========
    @Schema(description = "角色头像", example = "https://www.Iailab.cn/1.png")
    private String roleAvatar;
    @Schema(description = "角色名字", example = "小黄")
    private String roleName;
    // ========== 仅在【对话管理】时加载 ==========
    @Schema(description = "消息数量", example = "20")
    private Integer messageCount;
}
iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/api/chat/dto/AiChatMessageSendReqDTO.java
对比新文件
@@ -0,0 +1,23 @@
package com.iailab.module.ai.api.chat.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Schema(description = "管理后台 - AI 聊天消息发送 Request VO")
@Data
public class AiChatMessageSendReqDTO {
    @Schema(description = "聊天对话编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
    @NotNull(message = "聊天对话编号不能为空")
    private Long conversationId;
    @Schema(description = "聊天内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "帮我写个 Java 算法")
    @NotEmpty(message = "聊天内容不能为空")
    private String content;
    @Schema(description = "是否携带上下文", example = "true")
    private Boolean useContext;
}
iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/api/chat/dto/AiChatMessageSendRespDTO.java
对比新文件
@@ -0,0 +1,34 @@
package com.iailab.module.ai.api.chat.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class AiChatMessageSendRespDTO {
    @Schema(description = "发送消息", requiredMode = Schema.RequiredMode.REQUIRED)
    private Message send;
    @Schema(description = "接收消息", requiredMode = Schema.RequiredMode.REQUIRED)
    private Message receive;
    @Schema(description = "消息")
    @Data
    public static class Message {
        @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
        private Long id;
        @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "role")
        private String type; // 参见 MessageType 枚举类
        @Schema(description = "聊天内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "你好,你好啊")
        private String content;
        @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
        private LocalDateTime createTime;
    }
}
iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/api/chat/dto/AiModelDO.java
对比新文件
@@ -0,0 +1,79 @@
package com.iailab.module.ai.api.chat.dto;
import com.iailab.framework.common.enums.CommonStatusEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
 * AI 模型 DO
 *
 * 默认模型:{@link #status} 为开启,并且 {@link #sort} 排序第一
 *
 * @author houzhongjian
 * @since 2025/6/33 11:39
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class AiModelDO {
    /**
     * 编号
     */
    private Long id;
    /**
     * API 秘钥编号
     *
     */
    private Long keyId;
    /**
     * 模型名称
     */
    private String name;
    /**
     * 模型标志
     */
    private String model;
    /**
     * 平台
     *
     */
    private String platform;
    /**
     * 类型
     *
     */
    private Integer type;
    /**
     * 排序值
     */
    private Integer sort;
    /**
     * 状态
     *
     * 枚举 {@link CommonStatusEnum}
     */
    private Integer status;
    // ========== 对话配置 ==========
    /**
     * 温度参数
     *
     * 用于调整生成回复的随机性和多样性程度:较低的温度值会使输出更收敛于高频词汇,较高的则增加多样性
     */
    private Double temperature;
    /**
     * 单条回复的最大 Token 数量
     */
    private Integer maxTokens;
    /**
     * 上下文的最大 Message 数量
     */
    private Integer maxContexts;
}
iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/api/questionTemplate/QuestionTemplateApi.java
对比新文件
@@ -0,0 +1,34 @@
package com.iailab.module.ai.api.questionTemplate;
import com.iailab.framework.common.enums.RpcConstants;
import com.iailab.module.ai.api.questionTemplate.dto.AiModelDTO;
import com.iailab.module.ai.api.questionTemplate.dto.QuestionTemplateDTO;
import com.iailab.module.ai.enums.ApiConstants;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.List;
/**
 * @author DongYukun
 * @Description
 * @createTime 2025年06月04日
 */
@FeignClient(name = ApiConstants.NAME)
@Tag(name = "问题模板")
public interface QuestionTemplateApi {
    String PREFIX = RpcConstants.RPC_API_PREFIX +  "/ai/questiontemplate";
    @GetMapping(PREFIX + "/modelList")
    @Operation(summary = "Ai大模型级联问题模版")
    List<AiModelDTO> queryModelList();
    @PostMapping(PREFIX + "/queryTemplates")
    @Operation(summary = "Ai大模型级联问题模版")
    List<QuestionTemplateDTO> queryTemplates(@RequestBody QuestionTemplateDTO questionTemplateDTO);
}
iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/api/questionTemplate/QuestiontemplateApi.java
文件已删除
iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/api/questionTemplate/dto/AiModelDTO.java
文件名从 iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/api/questionTemplate/dto/AiModelDto.java 修改
@@ -6,7 +6,7 @@
import java.util.List;
@Data
public class AiModelDto implements Serializable {
public class AiModelDTO implements Serializable {
    @Schema(description = "编号", example = "2630")
    private Long id;
@@ -41,6 +41,6 @@
    @Schema(description = "上下文的最大 Message 数量", example = "8192")
    private Integer maxContexts;
    private List<QuestionTemplateDto> children;
    private List<QuestionTemplateDTO> children;
}
iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/api/questionTemplate/dto/QuestionTemplateDTO.java
文件名从 iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/api/questionTemplate/dto/QuestionTemplateDto.java 修改
@@ -11,7 +11,7 @@
 * @author 超级管理员
 */
@Data
public class QuestionTemplateDto implements Serializable {
public class QuestionTemplateDTO implements Serializable {
    /**
     * id
iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/enums/AiChatRoleEnum.java
@@ -12,29 +12,25 @@
@Getter
public enum AiChatRoleEnum {
    AI_WRITE_ROLE("写作助手", """
            你是一位出色的写作助手,能够帮助用户生成创意和灵感,并在用户提供场景和提示词时生成对应的回复。你的任务包括:
            1.    撰写建议:根据用户提供的主题或问题,提供详细的写作建议、情节发展方向、角色设定以及背景描写,确保内容结构清晰、有逻辑。
            2.    回复生成:根据用户提供的场景和提示词,生成合适的对话或文字回复,确保语气和风格符合场景需求。
            除此之外不需要除了正文内容外的其他回复,如标题、开头、任何解释性语句或道歉。
            """),
    AI_WRITE_ROLE("写作助手", "你是一位出色的写作助手,能够帮助用户生成创意和灵感,并在用户提供场景和提示词时生成对应的回复。你的任务包括:\n" +
            "            1.\t撰写建议:根据用户提供的主题或问题,提供详细的写作建议、情节发展方向、角色设定以及背景描写,确保内容结构清晰、有逻辑。\n" +
            "            2.\t回复生成:根据用户提供的场景和提示词,生成合适的对话或文字回复,确保语气和风格符合场景需求。\n" +
            "            除此之外不需要除了正文内容外的其他回复,如标题、开头、任何解释性语句或道歉。"),
    AI_MIND_MAP_ROLE("导图助手", """
             你是一位非常优秀的思维导图助手,你会把用户的所有提问都总结成思维导图,然后以 Markdown 格式输出。markdown 只需要输出一级标题,二级标题,三级标题,四级标题,最多输出四级,除此之外不要输出任何其他 markdown 标记。下面是一个合格的例子:
             # Geek-AI 助手
             ## 完整的开源系统
             ### 前端开源
             ### 后端开源
             ## 支持各种大模型
             ### OpenAI
             ### Azure
             ### 文心一言
             ### 通义千问
             ## 集成多种收费方式
             ### 支付宝
             ### 微信
            除此之外不要任何解释性语句。
            """),
    AI_MIND_MAP_ROLE("导图助手", "你是一位非常优秀的思维导图助手,你会把用户的所有提问都总结成思维导图,然后以 Markdown 格式输出。markdown 只需要输出一级标题,二级标题,三级标题,四级标题,最多输出四级,除此之外不要输出任何其他 markdown 标记。下面是一个合格的例子:\n" +
            "             # Geek-AI 助手\n" +
            "             ## 完整的开源系统\n" +
            "             ### 前端开源\n" +
            "             ### 后端开源\n" +
            "             ## 支持各种大模型\n" +
            "             ### OpenAI\n" +
            "             ### Azure\n" +
            "             ### 文心一言\n" +
            "             ### 通义千问\n" +
            "             ## 集成多种收费方式\n" +
            "             ### 支付宝\n" +
            "             ### 微信\n" +
            "            除此之外不要任何解释性语句。"),
    ;
    /**
iailab-module-ai/iailab-module-ai-api/src/main/java/com/iailab/module/ai/enums/ApiConstants.java
对比新文件
@@ -0,0 +1,23 @@
package com.iailab.module.ai.enums;
import com.iailab.framework.common.enums.RpcConstants;
/**
 * API 相关的枚举
 *
 * @author iailab
 */
public class ApiConstants {
    /**
     * 服务名
     *
     * 注意,需要保证和 spring.application.name 保持一致
     */
    public static final String NAME = "ai-server";
    public static final String PREFIX = RpcConstants.RPC_API_PREFIX +  "/ai";
    public static final String VERSION = "1.0.0";
}
iailab-module-ai/iailab-module-ai-biz/pom.xml
@@ -5,7 +5,7 @@
    <parent>
        <groupId>com.iailab</groupId>
        <artifactId>iailab-module-ai</artifactId>
        <version>${ai.revision}</version>
        <version>${revision}</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>iailab-module-ai-biz</artifactId>
@@ -29,7 +29,7 @@
        <dependency>
            <groupId>com.iailab</groupId>
            <artifactId>iailab-module-ai-api</artifactId>
            <version>${ai.revision}</version>
            <version>${revision}</version>
        </dependency>
        <!-- 业务组件 -->
@@ -114,8 +114,8 @@
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>17</source>
                    <target>17</target>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                </configuration>
            </plugin>
        </plugins>
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/api/QuestionTemplateApiImpl.java
文件已删除
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/api/chat/AiChatConversionApiImpl.java
对比新文件
@@ -0,0 +1,34 @@
package com.iailab.module.ai.api.chat;
import com.iailab.module.ai.controller.admin.chat.vo.conversation.AiChatConversationCreateEnergyReqVO;
import com.iailab.module.ai.dal.dataobject.chat.AiChatConversationDO;
import com.iailab.module.ai.service.chat.AiChatConversationService;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import static com.iailab.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@RestController // 提供 RESTful API 接口,给 Feign 调用
@Validated
public class AiChatConversionApiImpl implements AiChatConversationApi {
    @Resource
    private AiChatConversationService chatConversationService;
    @Override
    public Long chatEnergyConversation(String modelName) {
        Long conversationId;
        List<AiChatConversationDO> list = chatConversationService.getChatConversationList(getLoginUserId(), modelName);
        if(list.size() == 0) {
            AiChatConversationCreateEnergyReqVO createReqVO = new AiChatConversationCreateEnergyReqVO();
            createReqVO.setModelName(modelName);
            conversationId = chatConversationService.createChatConversationEnergy(createReqVO);
        } else {
            conversationId = list.get(0).getId();
        }
        return conversationId;
    }
}
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/api/chat/AiChatMessageApiImpl.java
对比新文件
@@ -0,0 +1,27 @@
package com.iailab.module.ai.api.chat;
import com.iailab.framework.common.util.object.BeanUtils;
import com.iailab.module.ai.api.chat.dto.AiChatMessageSendRespDTO;
import com.iailab.module.ai.api.chat.dto.AiChatMessageSendReqDTO;
import com.iailab.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO;
import com.iailab.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO;
import com.iailab.module.ai.service.chat.AiChatMessageService;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController;
import static com.iailab.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@RestController // 提供 RESTful API 接口,给 Feign 调用
@Validated
public class AiChatMessageApiImpl implements AiChatMessageApi {
    @Resource
    private AiChatMessageService chatMessageService;
    @Override
    public AiChatMessageSendRespDTO sendMessage(AiChatMessageSendReqDTO sendReqDTO) {
        AiChatMessageSendRespVO aiChatMessageSendRespVO = chatMessageService.sendMessage(BeanUtils.toBean(sendReqDTO, AiChatMessageSendReqVO.class), getLoginUserId());
        return BeanUtils.toBean(aiChatMessageSendRespVO, AiChatMessageSendRespDTO.class);
    }
}
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/api/package-info.java
对比新文件
@@ -0,0 +1 @@
package com.iailab.module.ai.api;
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/api/template/QuestionTemplateApiImpl.java
对比新文件
@@ -0,0 +1,46 @@
package com.iailab.module.ai.api.template;
import com.iailab.framework.common.util.object.BeanUtils;
import com.iailab.module.ai.api.questionTemplate.QuestionTemplateApi;
import com.iailab.module.ai.api.questionTemplate.dto.AiModelDTO;
import com.iailab.module.ai.api.questionTemplate.dto.QuestionTemplateDTO;
import com.iailab.module.ai.controller.admin.questiontemplate.vo.QuestionTemplateReqVO;
import com.iailab.module.ai.service.model.AiModelService;
import com.iailab.module.ai.service.questiontemplate.QuestionTemplateService;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
 * @description:
 * @author: dongyukun
 * @date: 2025/6/4 14:50
 **/
@RestController // 提供 RESTful API 接口,给 Feign 调用
@Validated
public class QuestionTemplateApiImpl implements QuestionTemplateApi {
    @Resource
    private QuestionTemplateService questionTemplateService;
    @Resource
    private AiModelService aiModelService;
    @Override
    public List<AiModelDTO> queryModelList() {
        List<AiModelDTO> list = BeanUtils.toBean(aiModelService.getModelListByStatusAndType(0, 1, null), AiModelDTO.class);
        list.forEach(item->{
            item.setChildren(
                    BeanUtils.toBean(questionTemplateService.getQuestionTemplateList(item.getId()), QuestionTemplateDTO.class));
        });
        return list;
    }
    @Override
    public List<QuestionTemplateDTO> queryTemplates(QuestionTemplateDTO reqDTO) {
        QuestionTemplateReqVO ReqVO = BeanUtils.toBean(reqDTO, QuestionTemplateReqVO.class);
        return BeanUtils.toBean(questionTemplateService.getQuestionTemplates(ReqVO), QuestionTemplateDTO.class);
    }
}
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/controller/admin/chat/AiChatMessageController.java
@@ -7,10 +7,7 @@
import com.iailab.framework.common.pojo.PageResult;
import com.iailab.framework.common.util.collection.MapUtils;
import com.iailab.framework.common.util.object.BeanUtils;
import com.iailab.module.ai.controller.admin.chat.vo.message.AiChatMessagePageReqVO;
import com.iailab.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO;
import com.iailab.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO;
import com.iailab.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO;
import com.iailab.module.ai.controller.admin.chat.vo.message.*;
import com.iailab.module.ai.dal.dataobject.chat.AiChatConversationDO;
import com.iailab.module.ai.dal.dataobject.chat.AiChatMessageDO;
import com.iailab.module.ai.dal.dataobject.knowledge.AiKnowledgeDocumentDO;
@@ -33,6 +30,7 @@
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -70,6 +68,29 @@
        return chatMessageService.sendChatMessageStream(sendReqVO, getLoginUserId());
    }
    @Operation(summary = "获得指定对话的消息列表(分页)")
    @GetMapping("/page-list-by-conversation-id")
    public CommonResult<PageResult<AiChatMessageRespVO>> getChatMessagePageListByConversationId(AiChatMessageReqVO queryReqVO) {
        PageResult<AiChatMessageRespVO> pageResult = new PageResult<>();
        AiChatConversationDO conversation = chatConversationService.getChatConversation(queryReqVO.getConversationId());
        if (conversation == null || ObjUtil.notEqual(conversation.getUserId(), getLoginUserId())) {
            return success(pageResult);
        }
        // 1. 获取消息列表
        PageResult<AiChatMessageDO> pageList = chatMessageService.getChatMessagePageByConversationId(queryReqVO);
        List<AiChatMessageDO> messageList = pageList.getList();
        if (CollUtil.isEmpty(messageList)) {
            pageResult.setList(new ArrayList<>());
            pageResult.setTotal(0L);
            return success(pageResult);
        }
        List<AiChatMessageRespVO> messageVOList = BeanUtils.toBean(messageList, AiChatMessageRespVO.class);
        dealKnowledge(messageList, messageVOList);
        pageResult.setList(messageVOList);
        pageResult.setTotal(pageList.getTotal());
        return success(pageResult);
    }
    @Operation(summary = "获得指定对话的消息列表")
    @GetMapping("/list-by-conversation-id")
    @Parameter(name = "conversationId", required = true, description = "对话编号", example = "1024")
@@ -84,32 +105,8 @@
        if (CollUtil.isEmpty(messageList)) {
            return success(Collections.emptyList());
        }
        // 2. 拼接数据,主要是知识库段落信息
        Map<Long, AiKnowledgeSegmentDO> segmentMap = knowledgeSegmentService.getKnowledgeSegmentMap(convertListByFlatMap(messageList,
                message -> CollUtil.isEmpty(message.getSegmentIds()) ? null : message.getSegmentIds().stream()));
        Map<Long, AiKnowledgeDocumentDO> documentMap = knowledgeDocumentService.getKnowledgeDocumentMap(
                convertList(segmentMap.values(), AiKnowledgeSegmentDO::getDocumentId));
        List<AiChatMessageRespVO> messageVOList = BeanUtils.toBean(messageList, AiChatMessageRespVO.class);
        for (int i = 0; i < messageList.size(); i++) {
            AiChatMessageDO message = messageList.get(i);
            if (CollUtil.isEmpty(message.getSegmentIds())) {
                continue;
            }
            // 设置知识库段落信息
            messageVOList.get(i).setSegments(convertList(message.getSegmentIds(), segmentId -> {
                AiKnowledgeSegmentDO segment = segmentMap.get(segmentId);
                if (segment == null) {
                    return null;
                }
                AiKnowledgeDocumentDO document = documentMap.get(segment.getDocumentId());
                if (document == null) {
                    return null;
                }
                return new AiChatMessageRespVO.KnowledgeSegment().setId(segment.getId()).setContent(segment.getContent())
                        .setDocumentId(segment.getDocumentId()).setDocumentName(document.getName());
            }));
        }
        dealKnowledge(messageList, messageVOList);
        return success(messageVOList);
    }
@@ -180,4 +177,30 @@
        return success(true);
    }
    private void dealKnowledge(List<AiChatMessageDO> messageList, List<AiChatMessageRespVO> messageVOList) {
        // 拼接数据,主要是知识库段落信息
        Map<Long, AiKnowledgeSegmentDO> segmentMap = knowledgeSegmentService.getKnowledgeSegmentMap(convertListByFlatMap(messageList,
                message -> CollUtil.isEmpty(message.getSegmentIds()) ? null : message.getSegmentIds().stream()));
        Map<Long, AiKnowledgeDocumentDO> documentMap = knowledgeDocumentService.getKnowledgeDocumentMap(
                convertList(segmentMap.values(), AiKnowledgeSegmentDO::getDocumentId));
        for (int i = 0; i < messageList.size(); i++) {
            AiChatMessageDO message = messageList.get(i);
            if (CollUtil.isEmpty(message.getSegmentIds())) {
                continue;
            }
            // 设置知识库段落信息
            messageVOList.get(i).setSegments(convertList(message.getSegmentIds(), segmentId -> {
                AiKnowledgeSegmentDO segment = segmentMap.get(segmentId);
                if (segment == null) {
                    return null;
                }
                AiKnowledgeDocumentDO document = documentMap.get(segment.getDocumentId());
                if (document == null) {
                    return null;
                }
                return new AiChatMessageRespVO.KnowledgeSegment().setId(segment.getId()).setContent(segment.getContent())
                        .setDocumentId(segment.getDocumentId()).setDocumentName(document.getName());
            }));
        }
    }
}
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/controller/admin/chat/vo/conversation/AiChatConversationCreateEnergyReqVO.java
@@ -10,4 +10,7 @@
    @Schema(description = "模型名称", example = "zhuanlu")
    private String modelName;
    @Schema(description = "会话名称", example = "2025-06-10 17:09:33")
    private String title;
}
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/controller/admin/chat/vo/message/AiChatMessageReqVO.java
对比新文件
@@ -0,0 +1,29 @@
package com.iailab.module.ai.controller.admin.chat.vo.message;
import com.iailab.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static com.iailab.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - AI 聊天消息查询 Request VO")
@Data
public class AiChatMessageReqVO extends PageParam {
    @Schema(description = "对话编号", example = "2048")
    private Long conversationId;
    @Schema(description = "用户编号", example = "1024")
    private Long userId;
    @Schema(description = "消息内容", example = "你好")
    private String content;
    @Schema(description = "创建时间")
    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
    private LocalDateTime[] createTime;
}
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/controller/admin/questiontemplate/QuestionTemplateController.java
@@ -1,7 +1,7 @@
package com.iailab.module.ai.controller.admin.questiontemplate;
import com.iailab.module.ai.api.questionTemplate.dto.AiModelDto;
import com.iailab.module.ai.api.questionTemplate.dto.QuestionTemplateDto;
import com.iailab.module.ai.api.questionTemplate.dto.AiModelDTO;
import com.iailab.module.ai.api.questionTemplate.dto.QuestionTemplateDTO;
import com.iailab.module.ai.service.model.AiModelService;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.*;
@@ -87,11 +87,11 @@
    @GetMapping( "/modelList")
    @Operation(summary = "Ai大模型级联问题模版")
    List<AiModelDto> queryModelList(){
        List<AiModelDto> list = BeanUtils.toBean(aiModelService.getModelListByStatusAndType(0, 1, null), AiModelDto.class);
    List<AiModelDTO> queryModelList(){
        List<AiModelDTO> list = BeanUtils.toBean(aiModelService.getModelListByStatusAndType(0, 1, null), AiModelDTO.class);
        list.forEach(item->{
            item.setChildren(
                    BeanUtils.toBean(questionTemplateService.getQuestionTemplateList(item.getId()), QuestionTemplateDto.class));
                    BeanUtils.toBean(questionTemplateService.getQuestionTemplateList(item.getId()), QuestionTemplateDTO.class));
        });
        return list;
    }
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/controller/admin/questiontemplate/vo/QuestionTemplateReqVO.java
对比新文件
@@ -0,0 +1,27 @@
package com.iailab.module.ai.controller.admin.questiontemplate.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
 * @author houzh
 */
@Schema(description = "管理后台 - 大模型问题模板查询 Request VO")
@Data
public class QuestionTemplateReqVO {
    @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED, example = "31480")
    private String id;
    @Schema(description = "模型id", requiredMode = Schema.RequiredMode.REQUIRED, example = "11609")
    private String modelId;
    @Schema(description = "问题编号", requiredMode = Schema.RequiredMode.REQUIRED)
    private String questionCode;
    @Schema(description = "问题名称", example = "赵六")
    private String questionName;
    @Schema(description = "模型名称")
    private String modelName;
}
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/dal/mysql/chat/AiChatMessageMapper.java
@@ -7,6 +7,7 @@
import com.iailab.framework.mybatis.core.mapper.BaseMapperX;
import com.iailab.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.iailab.module.ai.controller.admin.chat.vo.message.AiChatMessagePageReqVO;
import com.iailab.module.ai.controller.admin.chat.vo.message.AiChatMessageReqVO;
import com.iailab.module.ai.dal.dataobject.chat.AiChatMessageDO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.ibatis.annotations.Mapper;
@@ -24,6 +25,13 @@
@Mapper
public interface AiChatMessageMapper extends BaseMapperX<AiChatMessageDO> {
    default PageResult<AiChatMessageDO> selectPageByConversationId(AiChatMessageReqVO reqVO) {
        return selectPage(reqVO, new LambdaQueryWrapperX<AiChatMessageDO>()
                .eq(AiChatMessageDO::getConversationId, reqVO.getConversationId())
                .betweenIfPresent(AiChatMessageDO::getCreateTime, reqVO.getCreateTime())
                .orderByDesc(AiChatMessageDO::getId));
    }
    default List<AiChatMessageDO> selectListByConversationId(Long conversationId) {
        return selectList(new LambdaQueryWrapperX<AiChatMessageDO>()
                .eq(AiChatMessageDO::getConversationId, conversationId)
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/job/image/AiMidjourneySyncJob.java
@@ -1,4 +1,4 @@
//package com.iailab.module.ai.job.image;
package com.iailab.module.ai.job.image;//package com.iailab.module.ai.job.image;
//
//import com.iailab.module.ai.service.image.AiImageService;
//import com.xxl.job.core.handler.annotation.XxlJob;
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/job/music/AiSunoSyncJob.java
@@ -1,4 +1,4 @@
//package com.iailab.module.ai.job.music;
package com.iailab.module.ai.job.music;//package com.iailab.module.ai.job.music;
//
//import com.iailab.module.ai.service.music.AiMusicService;
//import com.xxl.job.core.handler.annotation.XxlJob;
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/service/chat/AiChatConversationServiceImpl.java
@@ -6,6 +6,7 @@
import cn.hutool.core.util.ObjectUtil;
import com.iailab.framework.ai.core.enums.AiModelTypeEnum;
import com.iailab.framework.common.pojo.PageResult;
import com.iailab.framework.common.util.date.DateUtils;
import com.iailab.framework.common.util.object.BeanUtils;
import com.iailab.module.ai.controller.admin.chat.vo.conversation.AiChatConversationCreateEnergyReqVO;
import com.iailab.module.ai.controller.admin.chat.vo.conversation.AiChatConversationCreateMyReqVO;
@@ -20,15 +21,18 @@
import com.iailab.module.ai.service.model.AiChatRoleService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import static com.iailab.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.iailab.framework.common.util.collection.CollectionUtils.convertList;
import static com.iailab.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
import static com.iailab.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static com.iailab.module.ai.enums.ErrorCodeConstants.CHAT_CONVERSATION_MODEL_ERROR;
import static com.iailab.module.ai.enums.ErrorCodeConstants.CHAT_CONVERSATION_NOT_EXISTS;
@@ -92,7 +96,12 @@
        AiChatConversationDO conversation = new AiChatConversationDO().setUserId(getLoginUserId()).setPinned(false)
                .setModelId(model.getId()).setModel(model.getModel())
                .setTemperature(model.getTemperature()).setMaxTokens(model.getMaxTokens()).setMaxContexts(model.getMaxContexts());
        conversation.setTitle("新对话");
        if(StringUtils.isNotEmpty(createReqVO.getTitle())) {
            conversation.setTitle(createReqVO.getTitle());
        } else {
            String format = DateUtils.format(new Date(), FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND);
            conversation.setTitle(format);
        }
        chatConversationMapper.insert(conversation);
        return conversation.getId();
    }
@@ -176,6 +185,7 @@
        throw exception(CHAT_CONVERSATION_MODEL_ERROR);
    }
    @Override
    public AiChatConversationDO validateChatConversationExists(Long id) {
        AiChatConversationDO conversation = chatConversationMapper.selectById(id);
        if (conversation == null) {
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/service/chat/AiChatMessageService.java
@@ -3,6 +3,7 @@
import com.iailab.framework.common.pojo.CommonResult;
import com.iailab.framework.common.pojo.PageResult;
import com.iailab.module.ai.controller.admin.chat.vo.message.AiChatMessagePageReqVO;
import com.iailab.module.ai.controller.admin.chat.vo.message.AiChatMessageReqVO;
import com.iailab.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO;
import com.iailab.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO;
import com.iailab.module.ai.dal.dataobject.chat.AiChatMessageDO;
@@ -38,6 +39,14 @@
    Flux<CommonResult<AiChatMessageSendRespVO>> sendChatMessageStream(AiChatMessageSendReqVO sendReqVO, Long userId);
    /**
     * 获得指定对话的消息列表(分页)
     *
     * @param queryReqVO 消息请求
     * @return 消息列表
     */
    PageResult<AiChatMessageDO> getChatMessagePageByConversationId(AiChatMessageReqVO queryReqVO);
    /**
     * 获得指定对话的消息列表
     *
     * @param conversationId 对话编号
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/service/chat/AiChatMessageServiceImpl.java
@@ -9,10 +9,7 @@
import com.iailab.framework.common.pojo.PageResult;
import com.iailab.framework.common.util.object.BeanUtils;
import com.iailab.framework.tenant.core.util.TenantUtils;
import com.iailab.module.ai.controller.admin.chat.vo.message.AiChatMessagePageReqVO;
import com.iailab.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO;
import com.iailab.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO;
import com.iailab.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO;
import com.iailab.module.ai.controller.admin.chat.vo.message.*;
import com.iailab.module.ai.dal.dataobject.chat.AiChatConversationDO;
import com.iailab.module.ai.dal.dataobject.chat.AiChatMessageDO;
import com.iailab.module.ai.dal.dataobject.knowledge.AiKnowledgeDocumentDO;
@@ -314,6 +311,11 @@
    }
    @Override
    public PageResult<AiChatMessageDO> getChatMessagePageByConversationId(AiChatMessageReqVO reqVO) {
        return chatMessageMapper.selectPageByConversationId(reqVO);
    }
    @Override
    public List<AiChatMessageDO> getChatMessageListByConversationId(Long conversationId) {
        return chatMessageMapper.selectListByConversationId(conversationId);
    }
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/service/questiontemplate/QuestionTemplateService.java
@@ -46,6 +46,14 @@
    QuestionTemplateDO getQuestionTemplate(String id);
    /**
     * 获得大模型问题模板
     *
     * @param reqVO
     * @return 大模型问题模板
     */
    List<QuestionTemplateDO> getQuestionTemplates(QuestionTemplateReqVO reqVO);
    /**
     * 获得大模型问题模板分页
     *
     * @param pageReqVO 分页查询
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/service/questiontemplate/QuestionTemplateServiceImpl.java
@@ -1,9 +1,15 @@
package com.iailab.module.ai.service.questiontemplate;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.iailab.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.iailab.module.ai.controller.admin.questionparamsetting.vo.QuestionParamSettingRespVO;
import com.iailab.module.ai.dal.dataobject.model.AiModelDO;
import com.iailab.module.ai.dal.dataobject.questionparamsetting.QuestionParamSettingDO;
import com.iailab.module.ai.dal.mysql.questionparamsetting.QuestionParamSettingMapper;
import com.iailab.module.ai.service.model.AiModelService;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
@@ -34,6 +40,9 @@
    @Resource
    private QuestionParamSettingMapper questionParamSettingMapper;
    @Resource
    private AiModelService aiModelService;
    @Override
    public String createQuestionTemplate(QuestionTemplateSaveReqVO createReqVO) {
@@ -92,6 +101,27 @@
    }
    @Override
    public List<QuestionTemplateDO> getQuestionTemplates(QuestionTemplateReqVO reqVO) {
        String modelName = reqVO.getModelName();
        if(ObjectUtils.isNotEmpty(modelName)) {
            AiModelDO model = aiModelService.getModelByName(modelName);
            List<QuestionTemplateDO> questionTemplateDOS = questionTemplateMapper.selectList(
                    new LambdaQueryWrapperX<QuestionTemplateDO>()
                            .eqIfPresent(QuestionTemplateDO::getModelId, model.getId())
                            .eqIfPresent(QuestionTemplateDO::getQuestionCode, reqVO.getQuestionCode()));
            // 模板数量暂时很少,先循环遍历查询模板设置
            if (questionTemplateDOS != null && questionTemplateDOS.size() > 0) {
                questionTemplateDOS.stream().forEach(questionTemplateDO -> {
                    questionTemplateDO.setSettingList(
                            BeanUtils.toBean(questionParamSettingMapper.selectList("template_id", questionTemplateDO.getId()), QuestionParamSettingRespVO.class));
                });
            }
            return questionTemplateDOS;
        }
        return null;
    }
    @Override
    public PageResult<QuestionTemplateDO> getQuestionTemplatePage(QuestionTemplatePageReqVO pageReqVO) {
        return questionTemplateMapper.selectPage(pageReqVO);
    }
iailab-module-ai/iailab-module-ai-biz/src/main/resources/application.yaml
@@ -11,6 +11,7 @@
      username: @nacos.username@
      password: @nacos.password@
      discovery: # 【配置中心】配置项
        ip: @deploy.server@
        namespace: @profiles.active@
        group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
        metadata:
@@ -59,7 +60,7 @@
logging:
  file:
    name: ${user.home}/logs/${spring.application.name}.log # 日志文件名,全路径
    name: @log.path@/logs/${spring.application.name}.log # 日志文件名,全路径
--- #################### 接口文档配置 ####################
@@ -111,7 +112,7 @@
  job:
    executor:
      appname: ${spring.application.name} # 执行器 AppName
      logpath: ${user.home}/logs/xxl-job/${spring.application.name} # 执行器运行日志文件存储磁盘路径
      logpath: @log.path@/logs/xxl-job/${spring.application.name} # 执行器运行日志文件存储磁盘路径
    accessToken: default_token # 执行器通讯TOKEN
--- #################### AI 相关配置 ####################
iailab-module-ai/iailab-spring-boot-starter-ai/pom.xml
@@ -5,7 +5,7 @@
    <parent>
        <groupId>com.iailab</groupId>
        <artifactId>iailab-module-ai</artifactId>
        <version>${ai.revision}</version>
        <version>${revision}</version>
    </parent>
    <build>
        <plugins>
iailab-module-ai/pom.xml
@@ -10,7 +10,7 @@
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.iailab</groupId>
    <artifactId>iailab-module-ai</artifactId>
    <version>${ai.revision}</version>
    <version>${revision}</version>
    <packaging>pom</packaging>
    <modules>
@@ -44,7 +44,7 @@
        <spring.cloud.version>2024.0.0</spring.cloud.version>
        <spring.cloud.alibaba.version>2023.0.3.2</spring.cloud.alibaba.version>
        <!-- Web 相关 -->
        <springdoc.version>2.7.0</springdoc.version>
        <springdoc.version>2.8.3</springdoc.version>
        <knife4j.version>4.6.0</knife4j.version>
        <!-- 工具类相关 -->
        <bizlog-sdk.version>3.0.6</bizlog-sdk.version>
@@ -191,7 +191,7 @@
            <dependency>
                <groupId>com.iailab</groupId>
                <artifactId>iailab-module-infra-api</artifactId>
                <version>${revision}</version>
                <version>${ai.revision}</version>
            </dependency>
            <dependency>
iailab-module-data/iailab-module-data-api/src/main/java/com/iailab/module/data/api/point/DataPointApi.java
@@ -70,4 +70,12 @@
    @PostMapping(PREFIX + "/query-math-point/current-value")
    @Operation(summary = "根据计算点编号查询测点集合")
    PageResult<ApiPointDTO> queryMathPointCurrentValue(@RequestBody ApiPointPageReqVO reqVO);
}
    @PostMapping(PREFIX + "/query-point-bad-history/page")
    @Operation(summary = "查询测点异常历史分页")
    PageResult<ApiPointBadHistoryDTO> queryPointBadHistoryPage(@RequestBody ApiPointBadHistoryPageReqVO reqVO);
    @PostMapping(PREFIX + "/query-point/count")
    @Operation(summary = "获取点位个数")
    String getPointTotalCount(@RequestBody ApiPointCountReqVO reqVO);
}
iailab-module-data/iailab-module-data-api/src/main/java/com/iailab/module/data/api/point/dto/ApiPointBadHistoryDTO.java
对比新文件
@@ -0,0 +1,47 @@
package com.iailab.module.data.api.point.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
 * @author Jay
 */
@Data
@Tag(name = "测点异常历史表")
public class ApiPointBadHistoryDTO implements Serializable {
    private static final long serialVersionUID = 1L;
    @Schema(description = "id")
    private String id;
    @Schema(description = "测点ID")
    private String pointId;
    @Schema(description = "测点编码")
    private String pointNo;
    @Schema(description = "测点名称")
    private String pointName;
    @Schema(description = "测点Tag")
    private String tagNo;
    @Schema(description = "异常值")
    private BigDecimal badValue;
    @Schema(description = "异常值类型")
    private String badValueType;
    @Schema(description = "采集时间")
    private Date collectTime;
    @Schema(description = "创建时间")
    private Date createTime;
}
iailab-module-data/iailab-module-data-api/src/main/java/com/iailab/module/data/api/point/dto/ApiPointBadHistoryPageReqVO.java
对比新文件
@@ -0,0 +1,38 @@
package com.iailab.module.data.api.point.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.iailab.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.util.Date;
/**
 * @author Jay
 */
@Schema(description = "数据平台 - 测点异常分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ApiPointBadHistoryPageReqVO extends PageParam {
    @Schema(description = "测点编码")
    private String pointNo;
    @Schema(description = "测点名称")
    private String pointName;
    @Schema(description = "测点Tag")
    private String tagNo;
    @Schema(description = "开始时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date startTime;
    @Schema(description = "结束时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date endTime;
}
iailab-module-data/iailab-module-data-api/src/main/java/com/iailab/module/data/api/point/dto/ApiPointCountReqVO.java
对比新文件
@@ -0,0 +1,38 @@
package com.iailab.module.data.api.point.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
 * @author Jay
 */
@Schema(description = "数据平台 - 测点数量查询 Request VO")
@Data
public class ApiPointCountReqVO implements Serializable {
    private static final long serialVersionUID = 1L;
    @Schema(description = "测点类型")
    private String pointType;
    @Schema(description = "数据类型")
    private String dataType;
    @Schema(description = "是否启用")
    private Integer isEnable;
    @Schema(description = "采集质量")
    private String collectQuality;
    @Schema(description = "开始时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date startTime;
    @Schema(description = "结束时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date endTime;
}
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/api/controller/admin/ApiDataController.java
@@ -329,4 +329,20 @@
        return success(indItemApi.queryIndItemValuePage(dto));
    }
    @PermitAll
    @PostMapping("/query-point-bad-history/page")
    @Operation(summary = "根据计算点编号查询测点集合")
    public CommonResult<PageResult<ApiPointBadHistoryDTO>> queryPointBadHistoryPage(@RequestBody ApiPointBadHistoryPageReqVO reqVO) {
        PageResult<ApiPointBadHistoryDTO> data = dataPointApi.queryPointBadHistoryPage(reqVO);
        return success(data);
    }
    @PermitAll
    @PostMapping("/query-point/count")
    @Operation(summary = "根据计算点编号查询测点集合")
    public CommonResult<String> getPointTotalCount(@RequestBody ApiPointCountReqVO reqVO) {
        String count = dataPointApi.getPointTotalCount(reqVO);
        return success(count);
    }
}
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/api/point/DataPointApiImpl.java
@@ -12,8 +12,12 @@
import com.iailab.module.data.point.dto.DaMathPointDTO;
import com.iailab.module.data.point.dto.DaPointDTO;
import com.iailab.module.data.point.dto.DaPointWriteValueDTO;
import com.iailab.module.data.point.entity.DaPointBadHistoryEntity;
import com.iailab.module.data.point.service.DaMathPointService;
import com.iailab.module.data.point.service.DaPointBadHistoryService;
import com.iailab.module.data.point.service.DaPointService;
import com.iailab.module.data.point.vo.DaPointBadHistoryPageReqVO;
import com.iailab.module.data.point.vo.DaPointCountReqVO;
import com.iailab.module.data.point.vo.DaPointPageReqVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
@@ -23,7 +27,6 @@
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
 * @author PanZhibao
@@ -45,6 +48,9 @@
    @Autowired
    private DaMathPointService daMathPointService;
    @Autowired
    private DaPointBadHistoryService daPointBadHistoryService;
    @Override
    public ApiPointDTO getInfoById(String pointId) {
@@ -247,4 +253,18 @@
        });
        return new PageResult<>(dataList, pageResult.getTotal());
    }
    @Override
    public PageResult<ApiPointBadHistoryDTO> queryPointBadHistoryPage(ApiPointBadHistoryPageReqVO reqVO) {
        DaPointBadHistoryPageReqVO req = ConvertUtils.sourceToTarget(reqVO, DaPointBadHistoryPageReqVO.class);
        PageResult<DaPointBadHistoryEntity> page = daPointBadHistoryService.queryPage(req);
        List<ApiPointBadHistoryDTO> dataList = ConvertUtils.sourceToTarget(page.getList(), ApiPointBadHistoryDTO.class);
        return new PageResult<>(dataList, page.getTotal());
    }
    @Override
    public String getPointTotalCount(ApiPointCountReqVO reqVO) {
        DaPointCountReqVO req = ConvertUtils.sourceToTarget(reqVO, DaPointCountReqVO.class);
        return daPointService.getPointCount(req).toString();
    }
}
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/job/config/ScheduleJobListConfig.java
@@ -32,5 +32,6 @@
        scheduleJobList.add("pointArchivingTaskNetShift");
        scheduleJobList.add("pointArchivingTaskNetYear");
        scheduleJobList.add("insertInfluxdbTask");
        scheduleJobList.add("pointBadHistoryGenerateTask");
    }
}
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/job/task/PointBadHistoryGenerateTask.java
对比新文件
@@ -0,0 +1,67 @@
package com.iailab.module.data.job.task;
import com.iailab.module.data.common.enums.CommonConstant;
import com.iailab.module.data.common.enums.DataQualityEnum;
import com.iailab.module.data.common.enums.IsEnableEnum;
import com.iailab.module.data.point.dto.DaPointBadHistoryDTO;
import com.iailab.module.data.point.dto.DaPointDTO;
import com.iailab.module.data.point.service.DaPointBadHistoryService;
import com.iailab.module.data.point.service.DaPointService;
import com.iailab.module.data.point.vo.DaPointPageReqVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Calendar;
import java.util.List;
/**
 * Point采集器1min
 * 0 0/1 * * * ?
 *
 * @author Jay
 * @Description 测点异常历史
 */
@Component("pointBadHistoryGenerateTask")
public class PointBadHistoryGenerateTask implements ITask {
    private final Logger logger = LoggerFactory.getLogger(getClass());
    @Resource
    private DaPointService daPointService;
    @Resource
    private DaPointBadHistoryService daPointBadHistoryService;
    @Override
    public void run(String params) {
        // 0 0/1 * * * ?
        logger.info("PointBadHistoryGenerateTask定时任务正在执行,参数为:{}", params);
        try {
            Calendar calendar = Calendar.getInstance();
            calendar.set(Calendar.SECOND, 0);
            calendar.set(Calendar.MILLISECOND, 0);
            DaPointPageReqVO reqVO = new DaPointPageReqVO();
            reqVO.setIsEnable(IsEnableEnum.ENABLE.getCode());
            reqVO.setCollectQuality(DataQualityEnum.BAD.getCode());
            List<DaPointDTO> badPoints = daPointService.getList(reqVO);
            badPoints.forEach(point -> {
                DaPointBadHistoryDTO daPointBadHistoryDTO = new DaPointBadHistoryDTO();
                daPointBadHistoryDTO.setPointId(point.getId());
                daPointBadHistoryDTO.setPointNo(point.getPointNo());
                daPointBadHistoryDTO.setPointName(point.getPointName());
                daPointBadHistoryDTO.setTagNo(point.getTagNo());
                daPointBadHistoryDTO.setBadValue(CommonConstant.BAD_VALUE);
                daPointBadHistoryDTO.setBadValueType("通讯异常");
                daPointBadHistoryDTO.setCollectTime(point.getCollectTime());
                daPointBadHistoryService.create(daPointBadHistoryDTO);
            });
            logger.info("PointBadHistoryGenerateTask定时任务完成时间:" + LocalDateTime.now());
        } catch (Exception ex) {
            ex.printStackTrace();
            logger.error("PointBadHistoryGenerateTask定时任务失败时间:" + LocalDateTime.now());
        }
    }
}
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/point/dao/DaPointBadHistoryDao.java
对比新文件
@@ -0,0 +1,29 @@
package com.iailab.module.data.point.dao;
import com.iailab.framework.common.pojo.PageResult;
import com.iailab.framework.mybatis.core.mapper.BaseMapperX;
import com.iailab.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.iailab.framework.tenant.core.db.dynamic.TenantDS;
import com.iailab.module.data.point.entity.DaPointBadHistoryEntity;
import com.iailab.module.data.point.vo.DaPointBadHistoryPageReqVO;
import org.apache.ibatis.annotations.Mapper;
/**
 * @author Jay
 */
@TenantDS
@Mapper
public interface DaPointBadHistoryDao extends BaseMapperX<DaPointBadHistoryEntity> {
    default PageResult<DaPointBadHistoryEntity> selectPage(DaPointBadHistoryPageReqVO reqVO) {
        return selectPage(reqVO, new LambdaQueryWrapperX<DaPointBadHistoryEntity>()
                .likeIfPresent(DaPointBadHistoryEntity::getPointNo, reqVO.getPointNo())
                .likeIfPresent(DaPointBadHistoryEntity::getPointName, reqVO.getPointName())
                .likeIfPresent(DaPointBadHistoryEntity::getTagNo, reqVO.getTagNo())
                .geIfPresent(DaPointBadHistoryEntity::getCollectTime, reqVO.getStartTime())
                .leIfPresent(DaPointBadHistoryEntity::getCollectTime, reqVO.getEndTime())
                .orderByDesc(DaPointBadHistoryEntity::getCreateTime));
    }
}
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/point/dao/DaPointDao.java
@@ -5,6 +5,7 @@
import com.iailab.framework.tenant.core.db.dynamic.TenantDS;
import com.iailab.module.data.point.dto.DaPointDTO;
import com.iailab.module.data.point.entity.DaPointEntity;
import com.iailab.module.data.point.vo.DaPointCountReqVO;
import com.iailab.module.data.point.vo.DaPointPageReqVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@@ -35,6 +36,8 @@
    List<DaPointDTO> getExtremalPoint(Map<String, Object> params);
    Long getPointCount(DaPointCountReqVO reqVO);
    default IPage<DaPointDTO> selectPageList(DaPointPageReqVO reqVO) {
        return getPageList(getPage(reqVO), reqVO);
    }
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/point/dto/DaPointBadHistoryDTO.java
对比新文件
@@ -0,0 +1,47 @@
package com.iailab.module.data.point.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
 * @author Jay
 */
@Data
@Tag(name = "测点异常历史表")
public class DaPointBadHistoryDTO implements Serializable {
    private static final long serialVersionUID = 1L;
    @Schema(description = "id")
    private String id;
    @Schema(description = "测点ID")
    private String pointId;
    @Schema(description = "测点编码")
    private String pointNo;
    @Schema(description = "测点名称")
    private String pointName;
    @Schema(description = "测点Tag")
    private String tagNo;
    @Schema(description = "异常值")
    private BigDecimal badValue;
    @Schema(description = "异常值类型")
    private String badValueType;
    @Schema(description = "采集时间")
    private Date collectTime;
    @Schema(description = "创建时间")
    private Date createTime;
}
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/point/entity/DaPointBadHistoryEntity.java
对比新文件
@@ -0,0 +1,67 @@
package com.iailab.module.data.point.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
 * @author Jay
 */
@Data
@TableName("t_da_point_bad_history")
public class DaPointBadHistoryEntity implements Serializable {
    private static final long serialVersionUID = 1L;
    /**
     * id
     */
    @TableId(type = IdType.ASSIGN_UUID)
    private String id;
    /**
     * 测点ID
     */
    private String pointId;
    /**
     * 测点编码
     */
    private String pointNo;
    /**
     * 测点名称
     */
    private String pointName;
    /**
     * 测点Tag
     */
    private String tagNo;
    /**
     * 异常值
     */
    private BigDecimal badValue;
    /**
     * 异常值类型
     */
    private String badValueType;
    /**
     * 采集时间
     */
    private Date collectTime;
    /**
     * 创建时间
     */
    private Date createTime;
}
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/point/service/DaPointBadHistoryService.java
对比新文件
@@ -0,0 +1,19 @@
package com.iailab.module.data.point.service;
import com.iailab.framework.common.pojo.PageResult;
import com.iailab.framework.common.service.BaseService;
import com.iailab.module.data.point.dto.DaPointBadHistoryDTO;
import com.iailab.module.data.point.entity.DaPointBadHistoryEntity;
import com.iailab.module.data.point.vo.DaPointBadHistoryPageReqVO;
/**
 * @author Jay
 */
public interface DaPointBadHistoryService extends BaseService<DaPointBadHistoryEntity> {
    PageResult<DaPointBadHistoryEntity> queryPage(DaPointBadHistoryPageReqVO reqVO);
    void create(DaPointBadHistoryDTO daPointBadHistoryDTO);
}
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/point/service/DaPointService.java
@@ -3,10 +3,11 @@
import com.iailab.framework.common.pojo.PageResult;
import com.iailab.module.data.api.point.dto.ApiPointDTO;
import com.iailab.module.data.point.dto.DaPointDTO;
import com.iailab.module.data.point.vo.*;
import com.iailab.module.data.point.vo.DaPointCountReqVO;
import com.iailab.module.data.point.vo.DaPointPageReqVO;
import com.iailab.module.data.point.vo.PointImportExcelVO;
import com.iailab.module.data.point.vo.PointImportRespVO;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -75,4 +76,6 @@
    List<DaPointDTO> getMeasurePoint(DaPointPageReqVO reqVO);
    List<DaPointDTO> getMathPoint(DaPointPageReqVO reqVO);
    Long getPointCount(DaPointCountReqVO reqVO);
}
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/point/service/impl/DaPointBadHistoryServiceImpl.java
对比新文件
@@ -0,0 +1,36 @@
package com.iailab.module.data.point.service.impl;
import com.iailab.framework.common.pojo.PageResult;
import com.iailab.framework.common.service.impl.BaseServiceImpl;
import com.iailab.framework.common.util.object.BeanUtils;
import com.iailab.module.data.point.dao.DaPointBadHistoryDao;
import com.iailab.module.data.point.dto.DaPointBadHistoryDTO;
import com.iailab.module.data.point.entity.DaPointBadHistoryEntity;
import com.iailab.module.data.point.service.DaPointBadHistoryService;
import com.iailab.module.data.point.vo.DaPointBadHistoryPageReqVO;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.UUID;
/**
 * @author Jay
 */
@Service
public class DaPointBadHistoryServiceImpl extends BaseServiceImpl<DaPointBadHistoryDao, DaPointBadHistoryEntity> implements DaPointBadHistoryService {
    @Override
    public PageResult<DaPointBadHistoryEntity> queryPage(DaPointBadHistoryPageReqVO reqVO) {
        return baseDao.selectPage(reqVO);
    }
    @Override
    public void create(DaPointBadHistoryDTO daPointBadHistoryDTO) {
        DaPointBadHistoryEntity entity = BeanUtils.toBean(daPointBadHistoryDTO, DaPointBadHistoryEntity.class);
        entity.setId(UUID.randomUUID().toString());
        entity.setCreateTime(new Date());
        baseDao.insert(entity);
    }
}
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/point/service/impl/DaPointServiceImpl.java
@@ -2,12 +2,9 @@
import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.iailab.framework.common.constant.Constant;
import com.iailab.framework.common.pojo.PageResult;
import com.iailab.framework.common.service.impl.BaseServiceImpl;
import com.iailab.framework.common.util.object.BeanUtils;
@@ -15,8 +12,8 @@
import com.iailab.module.data.api.point.dto.ApiPointDTO;
import com.iailab.module.data.channel.common.service.ChannelSourceService;
import com.iailab.module.data.common.enums.CommonConstant;
import com.iailab.module.data.common.enums.IsEnableEnum;
import com.iailab.module.data.common.enums.IncreaseCodeEnum;
import com.iailab.module.data.common.enums.IsEnableEnum;
import com.iailab.module.data.point.common.PointTypeEnum;
import com.iailab.module.data.point.dao.DaPointDao;
import com.iailab.module.data.point.dto.DaCumulatePointDTO;
@@ -26,6 +23,7 @@
import com.iailab.module.data.point.entity.DaMeasurePointEntity;
import com.iailab.module.data.point.entity.DaPointEntity;
import com.iailab.module.data.point.service.*;
import com.iailab.module.data.point.vo.DaPointCountReqVO;
import com.iailab.module.data.point.vo.DaPointPageReqVO;
import com.iailab.module.data.point.vo.PointImportExcelVO;
import com.iailab.module.data.point.vo.PointImportRespVO;
@@ -324,6 +322,16 @@
    }
    @Override
    public Long getPointCount(DaPointCountReqVO reqVO ) {
        if (StringUtils.isNotBlank(reqVO.getCollectQuality())){
            return daPointDao.getPointCount(reqVO);
        }
        QueryWrapper<DaPointEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(reqVO.getIsEnable() != null, "is_enable", reqVO.getIsEnable());
        return daPointDao.selectCount(queryWrapper);
    }
    @Override
    public List<DaPointDTO> getMathPoint(String freq) {
        Map<String, Object> params = new HashMap<>();
        params.put("pointType", PointTypeEnum.CALCULATE_POINT.getCode());
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/point/vo/DaPointBadHistoryPageReqVO.java
对比新文件
@@ -0,0 +1,38 @@
package com.iailab.module.data.point.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.iailab.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.util.Date;
/**
 * @author Jay
 */
@Schema(description = "数据平台 - 测点异常分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DaPointBadHistoryPageReqVO extends PageParam {
    @Schema(description = "测点编码")
    private String pointNo;
    @Schema(description = "测点名称")
    private String pointName;
    @Schema(description = "测点Tag")
    private String tagNo;
    @Schema(description = "开始时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date startTime;
    @Schema(description = "结束时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date endTime;
}
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/point/vo/DaPointCountReqVO.java
对比新文件
@@ -0,0 +1,38 @@
package com.iailab.module.data.point.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
 * @author Jay
 */
@Schema(description = "数据平台 - 测点数量查询 Request VO")
@Data
public class DaPointCountReqVO implements Serializable {
    private static final long serialVersionUID = 1L;
    @Schema(description = "测点类型")
    private String pointType;
    @Schema(description = "数据类型")
    private String dataType;
    @Schema(description = "是否启用")
    private Integer isEnable;
    @Schema(description = "采集质量")
    private String collectQuality;
    @Schema(description = "开始时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date startTime;
    @Schema(description = "结束时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date endTime;
}
iailab-module-data/iailab-module-data-biz/src/main/resources/application.yaml
@@ -188,6 +188,7 @@
      - t_da_point_collect_status
      - t_arc_data
      - t_arc_setting
      - t_da_point_bad_history
  app:
    app-key: data
    app-secret: 85b0df7edc3df3611913df34ed695011
iailab-module-data/iailab-module-data-biz/src/main/resources/mapper/point/DaPointDao.xml
@@ -345,4 +345,24 @@
        </where>
    </select>
    <select id="getPointCount" resultType="long">
        select count(*)
        from t_da_point t1
        left join t_da_point_collect_status t2 on t2.point_no = t1.point_no
        <where>
            <if test="isEnable != null ">
                and t1.is_enable = #{isEnable}
            </if>
            <if test="collectQuality != null and collectQuality != ''">
                and t2.collect_quality = #{collectQuality}
            </if>
            <if test="startTime != null">
                and t2.collect_time &gt;= #{startTime}
            </if>
            <if test="endTime != null">
                and t2.collect_time &lt;= #{endTime}
            </if>
        </where>
    </select>
</mapper>
iailab-module-infra/iailab-module-infra-biz/src/main/resources/application-dev.yaml
@@ -44,7 +44,7 @@
      primary: master
      datasource:
        master:
          url: jdbc:mysql://127.0.0.1:3306/iailab_plat_system?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例
          url: jdbc:mysql://172.16.8.100:3306/iailab_plat_system?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例
          #          url: jdbc:mysql://127.0.0.1:3306/iailab-plat?useSSL=true&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai # MySQL Connector/J 5.X 连接的示例
          #          url: jdbc:postgresql://127.0.0.1:5432/ruoyi-vue-pro # PostgreSQL 连接的示例
          #          url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例
iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/module/model/api/MdkApiImpl.java
@@ -296,8 +296,7 @@
            stScheduleSchemeService.updateTime(scheduleResult.getSchemeId(), scheduleResult.getScheduleTime(), scheduleResult.getResultCode());
            log.info("调度计算结束: " + System.currentTimeMillis());
        } catch (Exception ex) {
            log.info("调度计算异常: " + System.currentTimeMillis());
            ex.printStackTrace();
            log.error("调度计算异常: " + System.currentTimeMillis(),ex);
            return resp;
        }
        return resp;
iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/dal/mysql/permission/MenuMapper.java
@@ -22,6 +22,7 @@
    default List<MenuDO> selectList(MenuListReqVO reqVO) {
        return selectList(new LambdaQueryWrapperX<MenuDO>()
                .eqIfPresent(MenuDO::getStatus, reqVO.getStatus())
                .likeIfPresent(MenuDO::getName, reqVO.getName()));
    }