dengzedong
2025-06-04 ac80ce61499309d23e5d5bb6ae0960599b49a529
Merge remote-tracking branch 'origin/master'
已修改11个文件
214 ■■■■■ 文件已修改
iailab-module-ai/iailab-module-ai-api/pom.xml 10 ●●●●● 补丁 | 查看 | 原始文档 | 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/QuestionTemplateRespVO.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/controller/admin/questiontemplate/vo/QuestionTemplateSaveReqVO.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/dal/dataobject/questionparamsetting/QuestionParamSettingDO.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/dal/dataobject/questiontemplate/QuestionTemplateDO.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/dal/mysql/questionparamsetting/QuestionParamSettingMapper.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/service/questiontemplate/QuestionTemplateService.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/service/questiontemplate/QuestionTemplateServiceImpl.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-biz/src/main/resources/application.yaml 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/point/collection/handler/CalculateHandle.java 114 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-ai/iailab-module-ai-api/pom.xml
@@ -40,5 +40,15 @@
            <artifactId>spring-boot-starter-validation</artifactId>
            <optional>true</optional>
        </dependency>
        <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>
        </dependency>
    </dependencies>
</project>
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/controller/admin/questiontemplate/QuestionTemplateController.java
@@ -1,5 +1,6 @@
package com.iailab.module.ai.controller.admin.questiontemplate;
import com.iailab.module.ai.service.model.AiModelService;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
@@ -13,6 +14,7 @@
import com.iailab.framework.common.pojo.PageResult;
import com.iailab.framework.common.pojo.CommonResult;
import com.iailab.framework.common.util.object.BeanUtils;
import static com.iailab.framework.common.pojo.CommonResult.success;
@@ -28,6 +30,9 @@
    @Resource
    private QuestionTemplateService questionTemplateService;
    @Resource
    private AiModelService aiModelService;
    @PostMapping("/create")
    @Operation(summary = "创建大模型问题模板")
@@ -67,6 +72,11 @@
    @PreAuthorize("@ss.hasPermission('ai:question-template:query')")
    public CommonResult<PageResult<QuestionTemplateRespVO>> getQuestionTemplatePage(@Valid QuestionTemplatePageReqVO pageReqVO) {
        PageResult<QuestionTemplateDO> pageResult = questionTemplateService.getQuestionTemplatePage(pageReqVO);
        pageResult.getList().forEach(questionTemplateDO ->
                questionTemplateDO.setModelName(
                        aiModelService.getModel(Long.valueOf((questionTemplateDO.getModelId()))).getName()
                )
        );
        return success(BeanUtils.toBean(pageResult, QuestionTemplateRespVO.class));
    }
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/controller/admin/questiontemplate/vo/QuestionTemplateRespVO.java
@@ -1,8 +1,11 @@
package com.iailab.module.ai.controller.admin.questiontemplate.vo;
import com.baomidou.mybatisplus.annotation.TableField;
import com.iailab.module.ai.controller.admin.questionparamsetting.vo.QuestionParamSettingRespVO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "管理后台 - 大模型问题模板 Response VO")
@Data
@@ -13,6 +16,9 @@
    @Schema(description = "模型id", requiredMode = Schema.RequiredMode.REQUIRED, example = "11609")
    private String modelId;
    @Schema(description = "模型名称")
    public String modelName;
    @Schema(description = "问题编号", requiredMode = Schema.RequiredMode.REQUIRED)
    private String questionCode;
@@ -35,4 +41,5 @@
    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
    private LocalDateTime createTime;
    private List<QuestionParamSettingRespVO> settingList;
}
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/controller/admin/questiontemplate/vo/QuestionTemplateSaveReqVO.java
@@ -1,9 +1,11 @@
package com.iailab.module.ai.controller.admin.questiontemplate.vo;
import com.iailab.module.ai.controller.admin.questionparamsetting.vo.QuestionParamSettingSaveReqVO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import javax.validation.constraints.*;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "管理后台 - 大模型问题模板新增/修改 Request VO")
@Data
@@ -35,4 +37,6 @@
    @Schema(description = "备注", example = "随便")
    private String remark;
    @Schema(description = "问题模版列表")
    private List<QuestionParamSettingSaveReqVO> settingList;
}
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/dal/dataobject/questionparamsetting/QuestionParamSettingDO.java
@@ -23,7 +23,7 @@
    /**
     * id
     */
    @TableId(type = IdType.INPUT)
    @TableId(type = IdType.ASSIGN_ID)
    private String id;
    /**
     * 问题模板id
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/dal/dataobject/questiontemplate/QuestionTemplateDO.java
@@ -1,8 +1,13 @@
package com.iailab.module.ai.dal.dataobject.questiontemplate;
import com.iailab.module.ai.controller.admin.questionparamsetting.vo.QuestionParamSettingRespVO;
import com.iailab.module.ai.controller.admin.questiontemplate.vo.QuestionTemplateSaveReqVO;
import com.iailab.module.ai.dal.dataobject.model.AiModelDO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.time.LocalDateTime;
import java.util.List;
import com.baomidou.mybatisplus.annotation.*;
import com.iailab.framework.mybatis.core.dataobject.BaseDO;
@@ -56,4 +61,9 @@
     */
    private String remark;
    @TableField(exist = false)
    private List<QuestionParamSettingRespVO> settingList;
    @TableField(exist = false)
    public String modelName;
}
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/dal/mysql/questionparamsetting/QuestionParamSettingMapper.java
@@ -1,5 +1,7 @@
package com.iailab.module.ai.dal.mysql.questionparamsetting;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.iailab.framework.common.pojo.PageResult;
import com.iailab.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.iailab.framework.mybatis.core.mapper.BaseMapperX;
@@ -25,4 +27,7 @@
                .orderByDesc(QuestionParamSettingDO::getId));
    }
    default int deleteByTemplateId(String templateId) {
        return delete("template_id",templateId);
    }
}
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/service/questiontemplate/QuestionTemplateService.java
@@ -4,6 +4,9 @@
import com.iailab.module.ai.controller.admin.questiontemplate.vo.*;
import com.iailab.module.ai.dal.dataobject.questiontemplate.QuestionTemplateDO;
import com.iailab.framework.common.pojo.PageResult;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
 * 大模型问题模板 Service 接口
@@ -50,4 +53,12 @@
     */
    PageResult<QuestionTemplateDO> getQuestionTemplatePage(QuestionTemplatePageReqVO pageReqVO);
    /**
     * 根据模型id获得大模型问题模板列表
     *
     * @param modelId 模型id
     * @return 大模型问题模板列表
     */
    List<QuestionTemplateDO> getQuestionTemplateList(@Param("modelId") Long modelId );
}
iailab-module-ai/iailab-module-ai-biz/src/main/java/com/iailab/module/ai/service/questiontemplate/QuestionTemplateServiceImpl.java
@@ -1,5 +1,8 @@
package com.iailab.module.ai.service.questiontemplate;
import com.iailab.module.ai.controller.admin.questionparamsetting.vo.QuestionParamSettingRespVO;
import com.iailab.module.ai.dal.dataobject.questionparamsetting.QuestionParamSettingDO;
import com.iailab.module.ai.dal.mysql.questionparamsetting.QuestionParamSettingMapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
@@ -10,6 +13,9 @@
import com.iailab.framework.common.util.object.BeanUtils;
import com.iailab.module.ai.dal.mysql.questiontemplate.QuestionTemplateMapper;
import java.util.List;
import java.util.UUID;
import static com.iailab.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.iailab.module.ai.enums.ErrorCodeConstants.*;
@@ -26,10 +32,20 @@
    @Resource
    private QuestionTemplateMapper questionTemplateMapper;
    @Resource
    private QuestionParamSettingMapper questionParamSettingMapper;
    @Override
    public String createQuestionTemplate(QuestionTemplateSaveReqVO createReqVO) {
        // 插入
        QuestionTemplateDO questionTemplate = BeanUtils.toBean(createReqVO, QuestionTemplateDO.class);
        String id = UUID.randomUUID().toString();
        questionTemplate.setId(id);
        // 插入设置列表
        createReqVO.getSettingList().forEach(setting -> {
            setting.setTemplateId(id);
            questionParamSettingMapper.insert(BeanUtils.toBean(setting, QuestionParamSettingDO.class));
        });
        questionTemplateMapper.insert(questionTemplate);
        // 返回
        return questionTemplate.getId();
@@ -41,6 +57,14 @@
        validateQuestionTemplateExists(updateReqVO.getId());
        // 更新
        QuestionTemplateDO updateObj = BeanUtils.toBean(updateReqVO, QuestionTemplateDO.class);
        // 删除设置列表
        questionParamSettingMapper.deleteByTemplateId(updateReqVO.getId());
        // 更新设置列表
        updateReqVO.getSettingList().forEach(setting -> {
            setting.setTemplateId(updateReqVO.getId());
            setting.setId(null);
            questionParamSettingMapper.insert(BeanUtils.toBean(setting, QuestionParamSettingDO.class));
        });
        questionTemplateMapper.updateById(updateObj);
    }
@@ -50,6 +74,8 @@
        validateQuestionTemplateExists(id);
        // 删除
        questionTemplateMapper.deleteById(id);
        // 删除设置列表
        questionParamSettingMapper.deleteByTemplateId(id);
    }
    private void validateQuestionTemplateExists(String id) {
@@ -60,7 +86,9 @@
    @Override
    public QuestionTemplateDO getQuestionTemplate(String id) {
        return questionTemplateMapper.selectById(id);
        QuestionTemplateDO questionTemplateDO = questionTemplateMapper.selectById(id);
        questionTemplateDO.setSettingList(BeanUtils.toBean(questionParamSettingMapper.selectList("template_id",id), QuestionParamSettingRespVO.class));
        return questionTemplateDO;
    }
    @Override
@@ -68,4 +96,13 @@
        return questionTemplateMapper.selectPage(pageReqVO);
    }
    @Override
    public List<QuestionTemplateDO> getQuestionTemplateList(Long modelId) {
        List<QuestionTemplateDO> questionTemplateDOList = questionTemplateMapper.selectList("model_id",modelId);
        questionTemplateDOList.forEach(DO -> {
            BeanUtils.toBean(questionParamSettingMapper.selectList("template_id",DO.getId()), QuestionParamSettingRespVO.class);
        });
        return questionTemplateDOList;
    }
}
iailab-module-ai/iailab-module-ai-biz/src/main/resources/application.yaml
@@ -220,5 +220,7 @@
    ignore-tables:
      - ai_api_key
      - ai_model
      - ai_question_template
      - ai_question_param_setting
debug: true
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/point/collection/handler/CalculateHandle.java
@@ -1,6 +1,7 @@
package com.iailab.module.data.point.collection.handler;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.iailab.framework.common.util.string.StrUtils;
import com.iailab.module.data.common.enums.CommonConstant;
import com.iailab.module.data.common.enums.DataTypeEnum;
@@ -16,6 +17,7 @@
import org.apache.commons.lang3.StringUtils;
import javax.annotation.Resource;
import javax.validation.constraints.Max;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
@@ -24,6 +26,7 @@
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Stream;
/**
@@ -58,7 +61,13 @@
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    public static final String regex = "[+\\-\\*/()\\&\\|\\>\\<]";
    public final static String regex = "[+\\-\\*/()\\&\\|\\>\\<]";
    private final static String POINT_PREFIX = "C";
    private final static String PENDING_FLAG = "pending";
    private final static int MAX_RECURSION = 10;
    public List<InfluxPointValuePOJO> handle(Date collectTime, List<DaPointDTO> dtos, Map<String, Object> dataMap, List<String> listGood, List<String> listBad) {
        List<InfluxPointValuePOJO> result = new ArrayList<>();
@@ -67,33 +76,83 @@
            if (CollectionUtils.isEmpty(dtos)) {
                return result;
            }
            Map<String, DaPointDTO> pendingMap = new HashMap<>();
            log.info(JSON.toJSONString(listBad));
            dtos.forEach(dto -> {
                try {
                    Object rawValue = singleCompute(dto, dataMap, listGood, listBad);
                    BigDecimal coefficient = dto.getUnittransfactor() == null ? BigDecimal.ONE : dto.getUnittransfactor();
                    BigDecimal calValue = new BigDecimal(rawValue.toString()).multiply(coefficient);
                    if (dto.getMaxValue() != null && calValue.compareTo(dto.getMaxValue()) > 0) {
                        calValue = dto.getMaxValue();
                    } else if (dto.getMinValue() != null && calValue.compareTo(dto.getMinValue()) < 0) {
                        calValue = dto.getMinValue();
                    if (PENDING_FLAG.equals(rawValue.toString())) {
                        pendingMap.put(dto.getPointNo(), dto);
                    } else {
                        BigDecimal coefficient = dto.getUnittransfactor() == null ? BigDecimal.ONE : dto.getUnittransfactor();
                        BigDecimal calValue = new BigDecimal(rawValue.toString()).multiply(coefficient);
                        if (dto.getMaxValue() != null && calValue.compareTo(dto.getMaxValue()) > 0) {
                            calValue = dto.getMaxValue();
                        } else if (dto.getMinValue() != null && calValue.compareTo(dto.getMinValue()) < 0) {
                            calValue = dto.getMinValue();
                        }
                        dataMap.put(dto.getPointNo(), calValue);
                        InfluxPointValuePOJO pojo = GenInfluxPointValueUtils.getByPoint(dto, calValue);
                        pojo.setTimestamp(GenInfluxPointValueUtils.getByMin(collectTime, DataPointFreqEnum.getEumByCode(dto.getMinfreqid())));
                        result.add(pojo);
                    }
                    InfluxPointValuePOJO pojo = GenInfluxPointValueUtils.getByPoint(dto, calValue);
                    pojo.setTimestamp(GenInfluxPointValueUtils.getByMin(collectTime, DataPointFreqEnum.getEumByCode(dto.getMinfreqid())));
                    result.add(pojo);
                } catch (Exception ex) {
                    ex.printStackTrace();
                    log.info("计算点异常!PointNo=" + dto.getPointNo());
                }
            });
            log.info("计算点处理结束");
            Map<DaPointDTO, Object> valueResult = new HashMap<>();
            handPending(pendingMap, dataMap, listGood, listBad, valueResult, 1);
            log.info("valueResult size=" + valueResult.size());
            valueResult.forEach((key, value) -> {
                InfluxPointValuePOJO pojo = GenInfluxPointValueUtils.getByPoint(key, value);
                pojo.setTimestamp(GenInfluxPointValueUtils.getByMin(collectTime, DataPointFreqEnum.getEumByCode(key.getMinfreqid())));
                result.add(pojo);
            });
            log.info("计算点处理结束");
        } catch (Exception ex) {
            ex.printStackTrace();
            log.info("计算点处理异常!");
        }
        return result;
    }
    private void handPending(Map<String, DaPointDTO> pendingMap, Map<String, Object> dataMap,
                                            List<String> listGood, List<String> listBad, Map<DaPointDTO, Object> valueResult, int count) {
        Map<String, DaPointDTO> tempMap = new HashMap<>();
        if (CollectionUtils.isEmpty(pendingMap)) {
            log.info("pendingMap is empty");
            return;
        }
        log.info("处理包含计算点的");
        log.info("handPending count=" + count);
        if (count > MAX_RECURSION) {
            log.info("最多递归10次");
            return;
        }
        count = count + 1;
        for(String key : pendingMap.keySet()) {
            DaPointDTO dto = pendingMap.get(key);
            Object rawValue = singleCompute(dto, dataMap, listGood, listBad);
            if (PENDING_FLAG.equals(rawValue.toString())) {
                tempMap.put(key, dto);
            } else {
                BigDecimal coefficient = dto.getUnittransfactor() == null ? BigDecimal.ONE : dto.getUnittransfactor();
                BigDecimal calValue = new BigDecimal(rawValue.toString()).multiply(coefficient);
                if (dto.getMaxValue() != null && calValue.compareTo(dto.getMaxValue()) > 0) {
                    calValue = dto.getMaxValue();
                } else if (dto.getMinValue() != null && calValue.compareTo(dto.getMinValue()) < 0) {
                    calValue = dto.getMinValue();
                }
                dataMap.put(dto.getPointNo(), calValue);
                valueResult.put(dto, calValue);
            }
        }
        if (!CollectionUtils.isEmpty(tempMap)) {
            this.handPending(tempMap, dataMap, listGood, listBad, valueResult, count);
        }
    }
    private Object singleCompute(DaPointDTO dto, Map<String, Object> dataMap, List<String> listGood, List<String> listBad) {
@@ -103,17 +162,25 @@
        // 去掉arr中的空格
        arr = Stream.of(arr).filter(StringUtils::isNotBlank).toArray(String[]::new);
        // 判断arr都在dataMap中包含
        if (!Arrays.stream(arr).allMatch(dataMap::containsKey)) {
        /*if (!Arrays.stream(arr).allMatch(dataMap::containsKey)) {
            log.info("dataMap not contains key");
            listBad.add(dto.getPointNo());
            return CommonConstant.BAD_VALUE;
        }
        }*/
        for (int i = 0; i < arr.length; i++) {
            String s = arr[i];
            if (StringUtils.isNotBlank(s) && dataMap.containsKey(s)) {
                // 对每个数加(),否则负值报错
                expression = expression.replace(s, "(" + dataMap.get(s).toString() + ")");
            } else if(StringUtils.isNotBlank(s) && s.trim().startsWith(POINT_PREFIX)) {
                log.info("包含计算点,先挂起");
                log.info("dataMap=" + JSONObject.toJSONString(dataMap));
                return PENDING_FLAG;
            }  else if(StringUtils.isNotBlank(s) && !dataMap.containsKey(s)) {
                log.info("dataMap not contains key " + s);
                listBad.add(dto.getPointNo());
                return CommonConstant.BAD_VALUE;
            }
        }
        expression = expression.replace("&", "&&");
@@ -121,6 +188,7 @@
        expression = expression.replace("False", "false");
        expression = expression.replace("True", "true");
        log.info("PointNo=" + dto.getPointNo() + ";expression=" + expression);
        String result = javaScriptHandler.eval(expression);
        log.info("result=" + result);
        if (result == null || result.contains(JsErrorCode.Infinity.name()) || result.contains(JsErrorCode.NaN.name())) {
@@ -154,7 +222,7 @@
            if (redisTemplate.hasKey(PointCollector.PV + item.getPointNo())) {
                value = redisTemplate.opsForValue().get(PointCollector.PV + item.getPointNo());
            } else {
                Object rawValue = singleCompute(item);
                Object rawValue = singleCompute(item, 1);
                BigDecimal coefficient = item.getUnittransfactor() == null ? BigDecimal.ONE : item.getUnittransfactor();
                value = new BigDecimal(rawValue.toString()).multiply(coefficient);
            }
@@ -163,7 +231,7 @@
        return data;
    }
    private Object singleCompute(DaPointDTO dto) {
    private Object singleCompute(DaPointDTO dto, int count) {
        String result = CommonConstant.BAD_VALUE.toString();
        Map<String, Object> dataMap = new HashMap<>();
        String expression = dto.getExpression();
@@ -179,6 +247,20 @@
            dataMap.putAll(constantHandle.getCurrent(pointNos));
            dataMap.putAll(cumulateHandle.getCurrent(pointNos));
            dataMap.putAll(extremalHandle.getCurrent(pointNos));
            if (s.trim().startsWith(POINT_PREFIX)) {
                log.info("计算点递归查询");
                List<DaPointDTO> pointMathList = daPointService.getMathPoint(pointNos);
                if (CollectionUtils.isEmpty(pointMathList)) {
                    return result;
                }
                log.info("count = " + count);
                if (count > MAX_RECURSION) {
                    return result;
                }
                Object v = this.singleCompute(pointMathList.get(0), count);
                dataMap.put(s, v);
                count = count + 1;
            }
            if (dataMap.get(s) == null) {
                log.info("计算点数据异常");
                log.info("pointNo=" + dto.getPointNo() + ";dataMap.key=" + s);