龚焕茏
2024-07-26 38fe4ba31a92e3955a36f0916b790fcf53efaac9
refactor:合同导入模板
4个文件已修改
2个文件已添加
428 ■■■■ 已修改文件
ycl-common/src/main/java/enumeration/ContractRule.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-pojo/src/main/java/com/ycl/platform/domain/entity/CalculateRule.java 28 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/handler/CommentWriteHandler.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/handler/CustomCellWriteHandler.java 258 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/platform/service/impl/ContractScoreServiceImpl.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-server/src/main/java/com/ycl/platform/service/impl/TContractServiceImpl.java 75 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ycl-common/src/main/java/enumeration/ContractRule.java
New file
@@ -0,0 +1,59 @@
package enumeration;
import lombok.Getter;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
/**
 * @author gonghl
 * @since 2024/7/25 上午 10:50
 */
@Getter
public enum ContractRule {
    CONTRACT_RULE_1("视频平均在线率", Arrays.asList("CONTRACT_RULE_2", "CONTRACT_RULE_3", "CONTRACT_RULE_4", "CONTRACT_RULE_5")),
    CONTRACT_RULE_2("≥98%", Collections.EMPTY_LIST),
    CONTRACT_RULE_3("95%≤视频平均在线率<98%", Collections.EMPTY_LIST),
    CONTRACT_RULE_4("90%≤视频平均在线率<95%", Collections.EMPTY_LIST),
    CONTRACT_RULE_5("<90%", Collections.EMPTY_LIST),
    CONTRACT_RULE_6("前端感知源治理工作", Arrays.asList("CONTRACT_RULE_7", "CONTRACT_RULE_8", "CONTRACT_RULE_9")),
    CONTRACT_RULE_7("时钟同步(超过±3秒为不合格)", Collections.EMPTY_LIST),
    CONTRACT_RULE_8("OSD标识", Collections.EMPTY_LIST),
    CONTRACT_RULE_9("一机一档", Collections.EMPTY_LIST),
    CONTRACT_RULE_10("存储故障", Arrays.asList("CONTRACT_RULE_11", "CONTRACT_RULE_12")),
    CONTRACT_RULE_11("因存储设备、云存储软件等引起平台不能正常查看历史图像,须在24小时排除故障", Collections.EMPTY_LIST),
    CONTRACT_RULE_12("因视频或者图片丢失导致重要案事件不能回放或查看", Collections.EMPTY_LIST),
    CONTRACT_RULE_13("对于前端点位异常情况的处理", List.of("CONTRACT_RULE_14")),
    CONTRACT_RULE_14("镜头故障或污染或树枝遮挡或枪机视角偏移正常角度或补光灯应亮未亮", Collections.EMPTY_LIST),
    CONTRACT_RULE_15("建立数据监测维护机制", List.of("CONTRACT_RULE_16")),
    CONTRACT_RULE_16("中标人应当建立数据监测维护机制,当发生数据异常情况时,应在 24 小时内恢复。(数据异常包括实时监控或录像视频拉流失败,图片获取失败、视觉计算解析异常等)。", Collections.EMPTY_LIST),
    CONTRACT_RULE_17("确保录像完整不定期对所有点位录像完整性抽查", Arrays.asList("CONTRACT_RULE_18", "CONTRACT_RULE_19", "CONTRACT_RULE_20", "CONTRACT_RULE_21", "CONTRACT_RULE_22")),
    CONTRACT_RULE_18("每路视频累计丢失10分钟以内", Collections.EMPTY_LIST),
    CONTRACT_RULE_19("丢失10-60 分钟", Collections.EMPTY_LIST),
    CONTRACT_RULE_20("丢失1 小时-4 小时(含)", Collections.EMPTY_LIST),
    CONTRACT_RULE_21("丢失4 小时-12 小时(含)", Collections.EMPTY_LIST),
    CONTRACT_RULE_22("丢失12 小时以上", Collections.EMPTY_LIST),
    CONTRACT_RULE_23("确保图片完整不定期对所有人脸车辆以及智能前端抓拍的图片完整性抽查", List.of("CONTRACT_RULE_24")),
    CONTRACT_RULE_24("发现后台存储不能调取前端设备图片", Collections.EMPTY_LIST),
    ;
    private final String name;
    private final List<String> children;
    ContractRule(String name, List<String> children) {
        this.name = name;
        this.children = children;
    }
    public static List<ContractRule> getParent() {
        return Arrays.stream(ContractRule.values()).filter(contractRule -> !contractRule.getChildren().isEmpty()).toList();
    }
    public static List<ContractRule> getChildren(ContractRule parent) {
        return parent.getChildren().stream().map(ContractRule::valueOf).collect(Collectors.toList());
    }
}
ycl-pojo/src/main/java/com/ycl/platform/domain/entity/CalculateRule.java
@@ -7,12 +7,12 @@
import com.alibaba.excel.enums.poi.VerticalAlignmentEnum;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.ycl.system.domain.TreeEntity;
import com.ycl.system.domain.TreeNode;
import enumeration.converter.RuleDeductCategoryConverter;
import enumeration.general.RuleDeductCategoryEnum;
import lombok.Data;
import java.io.Serial;
import java.util.Date;
/**
@@ -26,13 +26,9 @@
@ContentStyle(horizontalAlignment = HorizontalAlignmentEnum.CENTER, verticalAlignment = VerticalAlignmentEnum.CENTER)
@TableName("t_calculate_rule")
public class CalculateRule extends TreeNode {
    private static final long serialVersionUID = 1L;
    /**
     * 主键
     */
    @ExcelProperty("序号")
    private Long id;
    @Serial
    private static final long serialVersionUID = 1L;
    /**
     * 合同id
@@ -51,18 +47,24 @@
    private Long parentId;
    /**
     * 规则描述
     */
    @ExcelProperty("评判标准")
    private String ruleDesc;
    /**
     * 规则条件
     */
    @ExcelProperty("考核要求")
    private String ruleCondition;
    /**
     * 违规最小值
     */
    @ExcelProperty("违规最小值")
    private Double min;
    /**
     * 违规最大值
     */
    @ExcelProperty("违规最大值")
    private Double max;
    /**
     * 扣减方式 扣指定分数/分数乘以数量/除以数量后乘以分数
     */
    @ExcelProperty(value = "扣分方式", converter = RuleDeductCategoryConverter.class)
ycl-server/src/main/java/com/ycl/handler/CommentWriteHandler.java
@@ -24,11 +24,11 @@
            Sheet sheet = context.getWriteSheetHolder().getSheet();
            Drawing<?> drawingPatriarch = sheet.createDrawingPatriarch();
            Comment comment1 = drawingPatriarch.createCellComment(new XSSFClientAnchor(0, 0, 0, 0,  5, 4,  4, 5));
            Comment comment1 = drawingPatriarch.createCellComment(new XSSFClientAnchor(0, 0, 0, 0,  5, 5,  4, 6));
            comment1.setString(new XSSFRichTextString("扣除相关镜头数量*0.1分"));
            sheet.getRow(0).getCell(1).setCellComment(comment1);
            Comment comment2 = drawingPatriarch.createCellComment(new XSSFClientAnchor(0, 0, 0, 0, 5, 7,  7, 8));
            Comment comment2 = drawingPatriarch.createCellComment(new XSSFClientAnchor(0, 0, 0, 0, 5, 8,  7, 9));
            comment2.setString(new XSSFRichTextString("扣2分/12小时"));
            sheet.getRow(0).getCell(1).setCellComment(comment2);
        }
ycl-server/src/main/java/com/ycl/handler/CustomCellWriteHandler.java
New file
@@ -0,0 +1,258 @@
package com.ycl.handler;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.util.BooleanUtils;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.handler.context.CellWriteHandlerContext;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.ycl.platform.domain.entity.CalculateRule;
import enumeration.ContractRule;
import enumeration.general.RuleDeductCategoryEnum;
import lombok.Data;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.usermodel.XSSFDataValidation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class CustomCellWriteHandler implements CellWriteHandler {
    /**
     * 这个处理器其实可以做很多事情
     * 他能拿到整个 Excel 的 WorkHook
     * 也能拿到当前的 sheet
     * 也能拿到当前的 cell
     * 所以能做的自定义操作很丰富
     */
    // static class CustomCellWriteHandler {
        @Override
        public void afterCellDispose(CellWriteHandlerContext context) {
            // 当前的 cell
            Cell cell = context.getCell();
            // 这里可以对cell进行任何操作
            // 这里就要考虑 你要针对哪一列进行个性化处理  一定要记得加判断  因为每个 cell 都会执行到这里 所以要记得区分
            if (BooleanUtils.isTrue(context.getHead()) && cell.getColumnIndex() == 1) {
                // 1 表示 省那一列 要对省市区进行联动下拉处理
                ExcelAreaUtil.writeAreaInfo(context, 0);
            }
        }
    // }
    public static class ExcelAreaUtil {
        @Data
        static class AreaInfo {
            private String name;
            private List<String> areaList;
            public AreaInfo(String name, List<String> areaList) {
                this.name = name;
                this.areaList = areaList;
            }
        }
        /**
         * @param context    handler 的 上下文
         * @param startIndex 省的列号  从0开始的
         */
        public static void writeAreaInfo(CellWriteHandlerContext context, int startIndex) {
            // 获取到当前的 sheet 后续要给省市区列加下拉
            WriteSheetHolder writeSheetHolder = context.getWriteSheetHolder();
            Sheet sheet = writeSheetHolder.getSheet();
            // 省市区挨着的列号
            int cIndex = startIndex + 1;
            int aIndex = cIndex + 1;
            // 准备点数据
            List<AreaInfo> provinceList = new ArrayList<>();
            for (ContractRule contractRule : ContractRule.getParent()) {
                provinceList.add(new AreaInfo(contractRule.getName(), ContractRule.getChildren(contractRule).stream().map(ContractRule::getName).toList()));
            }
            // 获取到当前的 excel 因为要创建隐藏的 sheet 也就是省市区的实际内容都来自于隐藏的 sheet
            Workbook workbook = context.getWriteSheetHolder().getParentWriteWorkbookHolder().getWorkbook();
            Sheet hideSheet = workbook.createSheet("area");
            workbook.setSheetHidden(workbook.getSheetIndex(hideSheet), true);
            // 写隐藏 sheet 的省市区信息
            int rowId = 0;
            // 设置第一行,存省的信息
            Row provinceRow = hideSheet.createRow(rowId++);
            provinceRow.createCell(0).setCellValue("省列表");
            for (int i = 0; i < provinceList.size(); i++) {
                Cell provinceCell = provinceRow.createCell(i + 1);
                provinceCell.setCellValue(provinceList.get(i).getName());
            }
            for (AreaInfo pro : provinceList) {
                String pName = pro.getName();
                List<String> cList = pro.getAreaList();
                Row cRow = hideSheet.createRow(rowId++);
                cRow.createCell(0).setCellValue(pName);
                for (int j = 0; j < cList.size(); j++) {
                    String cInfo = cList.get(j);
                    Cell cCell = cRow.createCell(j + 1);
                    cCell.setCellValue(cInfo);
                }
                // 添加名称管理器
                String range = getRange(1, rowId, cList.size());
                Name name = workbook.createName();
                // key不可重复
                name.setNameName(pName);
                String formula = "area!" + range;
                name.setRefersToFormula(formula);
            }
            // 给省添加下拉
            int lastRow = 100;
            setDataValidation(sheet, 1, lastRow, startIndex, startIndex);
            // 给市 区 添加下拉
            // 设置第二列和第三列的有效性
            for (int i = 2; i < lastRow; i++) {
                setDataValidation(CellReference.convertNumToColString(startIndex), sheet, i - 1, i - 1, cIndex, cIndex);
                setDataValidation(CellReference.convertNumToColString(cIndex), sheet, i - 1, i - 1, aIndex, aIndex);
            }
        }
        public static void setDataValidation(Sheet sheetPro, int firstRow, int lastRow, int firstCol, int lastCol) {
            DataValidationHelper dvHelper = sheetPro.getDataValidationHelper();
            String formula = getFormula(1, 1, 1, 34);
            // 省规则
            DataValidationConstraint provConstraint = dvHelper.createFormulaListConstraint(formula);
            // 四个参数分别是:起始行、终止行、起始列、终止列
            CellRangeAddressList provRangeAddressList = new CellRangeAddressList(firstRow, lastRow, firstCol, lastCol);
            DataValidation provinceDataValidation = dvHelper.createValidation(provConstraint, provRangeAddressList);
            // 验证
            provinceDataValidation.createErrorBox("error", "请选择正确的省份");
            provinceDataValidation.setShowErrorBox(true);
            provinceDataValidation.setSuppressDropDownArrow(true);
            sheetPro.addValidationData(provinceDataValidation);
        }
        public static void setDataValidation(String offset, Sheet sheet, int firstRow, int lastRow, int firstCol, int lastCol) {
            DataValidationHelper dvHelper = sheet.getDataValidationHelper();
            String formulaString = String.format("INDIRECT($%s%s)", offset, firstRow + 1);
            DataValidation dataValidation = getDataValidationByFormula(formulaString, dvHelper, firstRow, lastRow, firstCol, lastCol);
            sheet.addValidationData(dataValidation);
        }
        private static DataValidation getDataValidationByFormula(String formulaString, DataValidationHelper dvHelper,
                                                                 int firstRow, int lastRow, int firstCol, int lastCol) {
            // 加载下拉列表内容
            // 举例:若formulaString = "INDIRECT($A$2)" 表示规则数据会从名称管理器中获取key与单元格 A2 值相同的数据,
            // 如果A2是江苏省,那么此处就是江苏省下的市信息。
            DataValidationConstraint dvConstraint = dvHelper.createFormulaListConstraint(formulaString);
            // 设置数据有效性加载在哪个单元格上。
            // 四个参数分别是:起始行、终止行、起始列、终止列
            CellRangeAddressList regions = new CellRangeAddressList(firstRow, lastRow, firstCol, lastCol);
            // 绑定 数据有效性对象
            XSSFDataValidation dataValidation = (XSSFDataValidation) dvHelper.createValidation(dvConstraint, regions);
            dataValidation.setEmptyCellAllowed(true);
            dataValidation.setSuppressDropDownArrow(true);
            dataValidation.setShowErrorBox(true);
            // 设置输入错误提示信息
            dataValidation.createErrorBox("选择错误提示", "你输入的值未在备选列表中,请下拉选择合适的值!");
            return dataValidation;
        }
        private static String getFormula(int firstRow, int lastRow, int firstCol, int lastCol) {
            String ss = String.format("$%s$%s:$%s$%s", CellReference.convertNumToColString(firstCol), firstRow,
                    CellReference.convertNumToColString(lastCol), lastRow);
            return String.format("=%s!%s", "area", ss);
        }
        private static String getRange(int offset, int rowId, int colCount) {
            String columnLetter1 = CellReference.convertNumToColString(offset);
            String columnLetter2 = CellReference.convertNumToColString(offset + colCount - 1);
            return String.format("$%s$%s:$%s$%s", columnLetter1, rowId, columnLetter2, rowId);
        }
    }
    public static void main(String[] args) {
        EasyExcel.write("test.xlsx", CalculateRule.class)
                // 自适应列宽
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                // 下拉框
                .registerWriteHandler(new CustomSheetWriteHandler(Arrays.asList("扣指定分数", "分数乘以数量", "除以数量后乘以分数")))
                .registerWriteHandler(new CustomCellWriteHandler())
                // 标注
                .registerWriteHandler(new CommentWriteHandler())
                .sheet("合同导入模板")
                .doWrite(getExcelData());
    }
    private static List<CalculateRule> getExcelData() {
        ArrayList<CalculateRule> list = new ArrayList<>();
        CalculateRule calculateRule1 = new CalculateRule();
        calculateRule1.setId(1L);
        calculateRule1.setRuleName("视频平均在线率");
        calculateRule1.setRuleCondition("≥98%");
        calculateRule1.setMax(98D);
        calculateRule1.setDeductCategory(RuleDeductCategoryEnum.DEDUCT_POINTS);
        calculateRule1.setCalcFraction(0.00);
        list.add(calculateRule1);
        CalculateRule calculateRule2 = new CalculateRule();
        calculateRule2.setRuleName("视频平均在线率");
        calculateRule2.setRuleCondition("95%≤视频平均在线率<98%");
        calculateRule2.setMax(97D);
        calculateRule2.setMin(95D);
        calculateRule2.setDeductCategory(RuleDeductCategoryEnum.DEDUCT_POINTS);
        calculateRule2.setCalcFraction(5.00);
        list.add(calculateRule2);
        CalculateRule calculateRule3 = new CalculateRule();
        calculateRule3.setRuleName("视频平均在线率");
        calculateRule3.setRuleCondition("90%≤视频平均在线率<95%");
        calculateRule3.setMax(94D);
        calculateRule3.setMin(90D);
        calculateRule3.setDeductCategory(RuleDeductCategoryEnum.DEDUCT_POINTS);
        calculateRule3.setCalcFraction(10.00);
        list.add(calculateRule3);
        CalculateRule calculateRule33 = new CalculateRule();
        calculateRule33.setRuleName("视频平均在线率");
        calculateRule33.setRuleCondition("<90%");
        calculateRule33.setMin(89D);
        calculateRule33.setDeductCategory(RuleDeductCategoryEnum.DEDUCT_POINTS);
        calculateRule33.setCalcFraction(10.00);
        list.add(calculateRule33);
        CalculateRule calculateRule4 = new CalculateRule();
        calculateRule4.setId(2L);
        calculateRule4.setRuleName("前端感知源治理工作");
        calculateRule4.setRuleCondition("时钟同步(超过±3秒为不合格)");
        calculateRule4.setDeductCategory(RuleDeductCategoryEnum.MULTIPLY_POINTS_BY_QUANTITY);
        calculateRule4.setCalcFraction(0.1);
        list.add(calculateRule4);
        CalculateRule calculateRule7 = new CalculateRule();
        calculateRule7.setRuleName("前端感知源治理工作");
        calculateRule7.setRuleCondition("OSD标识");
        list.add(calculateRule7);
        CalculateRule calculateRule6 = new CalculateRule();
        calculateRule6.setRuleName("前端感知源治理工作");
        calculateRule6.setRuleCondition("一机一档");
        list.add(calculateRule6);
        CalculateRule calculateRule5 = new CalculateRule();
        calculateRule5.setId(3L);
        calculateRule5.setRuleName("后台系统的保障");
        calculateRule5.setRuleCondition("单次故障时长若超出72小时不足144小时的,每超出12小时(不足12小时按12小时计)");
        calculateRule5.setMax(144D);
        calculateRule5.setMin(72D);
        calculateRule5.setDeductCategory(RuleDeductCategoryEnum.MULTIPLY_POINTS_AFTER_DIVIDING_QUANTITY);
        calculateRule5.setCalcFraction(2.00);
        calculateRule5.setCalcUnit(12);
        list.add(calculateRule5);
        return list;
    }
}
ycl-server/src/main/java/com/ycl/platform/service/impl/ContractScoreServiceImpl.java
@@ -10,10 +10,8 @@
import com.ycl.platform.mapper.YwUnitMapper;
import com.ycl.platform.service.IContractScoreService;
import com.ycl.system.entity.SysUser;
import com.ycl.utils.DateUtils;
import com.ycl.utils.SecurityUtils;
import enumeration.general.AuditingStatus;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -66,7 +64,7 @@
        contractScore.setRuleIds(Arrays.stream(contractScore.getRuleIdsArray()).map(String::valueOf).collect(Collectors.joining(",")));
        contractScore.setRuleIdsArray(Arrays.stream(contractScore.getRuleIds().split(",")).map(Long::parseLong).toArray(Long[]::new));
        List<CalculateRule> list = new LambdaQueryChainWrapper<>(calculateRuleMapper).in(CalculateRule::getId, contractScore.getRuleIdsArray()).list();
        contractScore.setRuleName(String.join(" / ", new String[]{list.get(0).getRuleName(), list.get(1).getRuleDesc(), list.get(2).getRuleCondition()}));
        contractScore.setRuleName(String.join(" / ", new String[]{list.get(0).getRuleName(), list.get(2).getRuleCondition()}));
        return super.save(contractScore);
    }
ycl-server/src/main/java/com/ycl/platform/service/impl/TContractServiceImpl.java
@@ -1,13 +1,13 @@
package com.ycl.platform.service.impl;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.merge.LoopMergeStrategy;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ycl.handler.CommentWriteHandler;
import com.ycl.handler.CustomCellWriteHandler;
import com.ycl.handler.CustomSheetWriteHandler;
import com.ycl.platform.domain.entity.CalculateMoneyRule;
import com.ycl.platform.domain.entity.CalculateRule;
@@ -35,6 +35,7 @@
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
@@ -51,33 +52,24 @@
    private final ICalculateRuleService calculateRuleService;
    private final CalculateMoneyRuleServiceImpl calculateMoneyRuleService;
    private final YwUnitServiceImpl ywUnitService;
    @Override
    public void importTemplate(HttpServletResponse response) {
        try {
            List<CalculateRule> list = getExcelData();
            ArrayList<String> arrayList = new ArrayList<>();
            arrayList.add("扣指定分数");
            arrayList.add("分数乘以数量");
            arrayList.add("除以数量后乘以分数");
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            String fileName = URLEncoder.encode("导入合同模板", StandardCharsets.UTF_8).replace("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
            // 第一列、第二列上下合并3行
            LoopMergeStrategy loopMergeStrategy1 = new LoopMergeStrategy(3, 0);
            LoopMergeStrategy loopMergeStrategy2 = new LoopMergeStrategy(3, 1);
            EasyExcel.write(response.getOutputStream(), CalculateRule.class)
                    .registerWriteHandler(loopMergeStrategy1)
                    .registerWriteHandler(loopMergeStrategy2)
                    // 自适应列宽
                    .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                    // 下拉框
                    .registerWriteHandler(new CustomSheetWriteHandler(arrayList))
                    .registerWriteHandler(new CustomSheetWriteHandler(Arrays.asList("扣指定分数", "分数乘以数量", "除以数量后乘以分数")))
                    .registerWriteHandler(new CustomCellWriteHandler())
                    // 标注
                    .registerWriteHandler(new CommentWriteHandler())
                    .sheet("合同导入模板").doWrite(list);
                    .sheet("合同导入模板")
                    .doWrite(getExcelData());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
@@ -88,44 +80,55 @@
        CalculateRule calculateRule1 = new CalculateRule();
        calculateRule1.setId(1L);
        calculateRule1.setRuleName("视频平均在线率");
        calculateRule1.setRuleDesc("(1)视频在线率=视频在线数量÷前端服务配置数(应扣除不可抗力或与中标人服务无关造成的掉线除外。)");
        calculateRule1.setRuleCondition("≥98%");
        calculateRule1.setMax(98D);
        calculateRule1.setDeductCategory(RuleDeductCategoryEnum.DEDUCT_POINTS);
        calculateRule1.setCalcFraction(0.00);
        list.add(calculateRule1);
        CalculateRule calculateRule2 = new CalculateRule();
        calculateRule2.setRuleDesc("(2)视频平均在线率:当月每日视频在线率的平均值。");
        calculateRule2.setRuleName("视频平均在线率");
        calculateRule2.setRuleCondition("95%≤视频平均在线率<98%");
        calculateRule2.setMax(97D);
        calculateRule2.setMin(95D);
        calculateRule2.setDeductCategory(RuleDeductCategoryEnum.DEDUCT_POINTS);
        calculateRule2.setCalcFraction(5.00);
        list.add(calculateRule2);
        CalculateRule calculateRule3 = new CalculateRule();
        calculateRule3.setRuleDesc("(3)视频在线率保留整数并且向下取整。");
        calculateRule3.setRuleName("视频平均在线率");
        calculateRule3.setRuleCondition("90%≤视频平均在线率<95%");
        calculateRule3.setMax(94D);
        calculateRule3.setMin(90D);
        calculateRule3.setDeductCategory(RuleDeductCategoryEnum.DEDUCT_POINTS);
        calculateRule3.setCalcFraction(10.00);
        list.add(calculateRule3);
        CalculateRule calculateRule33 = new CalculateRule();
        calculateRule33.setRuleName("视频平均在线率");
        calculateRule33.setRuleCondition("<90%");
        calculateRule33.setMin(89D);
        calculateRule33.setDeductCategory(RuleDeductCategoryEnum.DEDUCT_POINTS);
        calculateRule33.setCalcFraction(10.00);
        list.add(calculateRule33);
        CalculateRule calculateRule4 = new CalculateRule();
        calculateRule4.setId(2L);
        calculateRule4.setRuleName("前端感知源治理工作");
        calculateRule4.setRuleDesc("时钟同步(超过±3秒为不合格)");
        calculateRule4.setRuleCondition("视频监控摄像机时钟不同步,24小时内未修复的");
        calculateRule4.setRuleCondition("时钟同步(超过±3秒为不合格)");
        calculateRule4.setDeductCategory(RuleDeductCategoryEnum.MULTIPLY_POINTS_BY_QUANTITY);
        calculateRule4.setCalcFraction(0.1);
        list.add(calculateRule4);
        CalculateRule calculateRule7 = new CalculateRule();
        calculateRule7.setRuleDesc("…………");
        calculateRule7.setRuleCondition("…………");
        calculateRule7.setRuleName("前端感知源治理工作");
        calculateRule7.setRuleCondition("OSD标识");
        list.add(calculateRule7);
        CalculateRule calculateRule6 = new CalculateRule();
        calculateRule6.setRuleDesc("…………");
        calculateRule6.setRuleCondition("…………");
        calculateRule6.setRuleName("前端感知源治理工作");
        calculateRule6.setRuleCondition("一机一档");
        list.add(calculateRule6);
        CalculateRule calculateRule5 = new CalculateRule();
        calculateRule5.setId(3L);
        calculateRule5.setRuleName("后台系统的保障");
        calculateRule5.setRuleDesc("在个别设备故障但不影响该功能模块整体应用情况下,须在72小时以内排除故障。");
        calculateRule5.setRuleCondition("单次故障时长若超出144小时以后,每超出12小时(不足12小时按12小时计)");
        calculateRule5.setRuleCondition("单次故障时长若超出72小时不足144小时的,每超出12小时(不足12小时按12小时计)");
        calculateRule5.setMax(144D);
        calculateRule5.setMin(72D);
        calculateRule5.setDeductCategory(RuleDeductCategoryEnum.MULTIPLY_POINTS_AFTER_DIVIDING_QUANTITY);
        calculateRule5.setCalcFraction(2.00);
        calculateRule5.setCalcUnit(12);
@@ -173,17 +176,17 @@
                fuNew = true;
            }
            // 保存第二层父规则获取第二层父id
            if (StringUtils.isNotBlank(calculateRule.getRuleDesc())) {
                CalculateRule two = new CalculateRule();
                two.setContractId(tContract.getId().intValue());
                two.setParentId(fu1.getId());
                two.setRuleDesc(calculateRule.getRuleDesc());
                two.setCreateTime(DateUtils.getNowDate());
                two.setDeleted(0);
                calculateRuleService.save(two);
                fu2 = two;
                fuNew = false;
            }
            // if (StringUtils.isNotBlank(calculateRule.getRuleDesc())) {
            //     CalculateRule two = new CalculateRule();
            //     two.setContractId(tContract.getId().intValue());
            //     two.setParentId(fu1.getId());
            //     two.setRuleDesc(calculateRule.getRuleDesc());
            //     two.setCreateTime(DateUtils.getNowDate());
            //     two.setDeleted(0);
            //     calculateRuleService.save(two);
            //     fu2 = two;
            //     fuNew = false;
            // }
            calculateRule.setContractId(tContract.getId().intValue());
            calculateRule.setCreateTime(DateUtils.getNowDate());
            calculateRule.setDeleted(0);