Jay
2024-11-01 03e8aca3ad6201c0d74e00d4c8d7367cdaaa54f9
tag新增导入导出功能
已修改28个文件
已添加9个文件
1129 ■■■■■ 文件已修改
iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/excel/core/handler/SelectSheetWriteHandler.java 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/excel/core/util/ExcelUtils.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-api/src/main/java/com/iailab/module/data/enums/ErrorCodeConstants.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/http/controller/admin/HttpTagController.java 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/http/entity/HttpTagEntity.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/http/service/HttpTagService.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/http/service/impl/HttpTagServiceImpl.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/http/vo/HttpTagRespVO.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/kio/controller/admin/ChannelKioTagController.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/kio/entity/ChannelKioTagEntity.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/kio/service/ChannelKioTagService.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/kio/service/impl/ChannelKioTagServiceImpl.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/kio/vo/KioTagRespVO.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/modbus/controller/admin/ChannelModbusTagController.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/modbus/entity/ChannelModBusTagEntity.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/modbus/service/ChannelModbusTagService.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/modbus/service/impl/ChannelModbusTagServiceImpl.java 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/modbus/vo/ModBusTagExportExcelVO.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/modbus/vo/ModBusTagImportExcelVO.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/modbus/vo/ModBusTagRespVO.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/opcda/controller/admin/ChannelOPCDATagController.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/opcda/entity/ChannelOPCDATagEntity.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/opcda/service/ChannelOPCDATagService.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/opcda/service/impl/ChannelOPCDATagServiceImpl.java 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/opcda/vo/OpcDaTagExportExcelVO.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/opcda/vo/OpcDaTagImportExcelVO.java 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/opcda/vo/OpcDaTagRespVO.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/opcua/controller/admin/ChannelOPCUATagController.java 65 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/opcua/entity/ChannelOPCUATagEntity.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/opcua/service/ChannelOPCUATagService.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/opcua/service/impl/ChannelOPCUATagServiceImpl.java 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/opcua/vo/OpcUaTagExportExcelVO.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/opcua/vo/OpcUaTagImportExcelVO.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/opcua/vo/OpcUaTagRespVO.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/tag/vo/TagExportExcelVO.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/tag/vo/TagImportExcelVO.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/tag/vo/TagImportRespVO.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/excel/core/handler/SelectSheetWriteHandler.java
@@ -7,24 +7,21 @@
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.poi.excel.ExcelUtil;
import com.iailab.framework.common.core.KeyValue;
import com.iailab.framework.dict.core.DictFrameworkUtils;
import com.iailab.framework.excel.core.annotations.ExcelColumnSelect;
import com.iailab.framework.excel.core.function.ExcelColumnSelectFunction;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import com.iailab.framework.common.core.KeyValue;
import com.iailab.framework.dict.core.DictFrameworkUtils;
import com.iailab.framework.excel.core.annotations.ExcelColumnSelect;
import com.iailab.framework.excel.core.function.ExcelColumnSelectFunction;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.HSSFDataValidation;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddressList;
import java.lang.reflect.Field;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import static com.iailab.framework.common.util.collection.CollectionUtils.convertList;
@@ -38,7 +35,6 @@
    /**
     * 数据起始行从 0 开始
     *
     * 约定:本项目第一行有标题所以从 1 开始如果您的 Excel 有多行标题请自行更改
     */
    public static final int FIRST_ROW = 1;
@@ -54,22 +50,29 @@
     */
    private final Map<Integer, List<String>> selectMap = new HashMap<>();
    public SelectSheetWriteHandler(Class<?> head) {
    private static Boolean ifSetSelect;
    public SelectSheetWriteHandler(Class<?> head, Boolean selectFlag) {
        ifSetSelect = selectFlag;
        // 加载下拉数据获取接口
        Map<String, ExcelColumnSelectFunction> beansMap = SpringUtil.getBeanFactory().getBeansOfType(ExcelColumnSelectFunction.class);
        if (MapUtil.isEmpty(beansMap)) {
            return;
        }
        List<Field> fields = new ArrayList<>();
        for (Class<?> c = head; c != null; c = c.getSuperclass()) {
            Collections.addAll(fields, c.getDeclaredFields());
        }
        // 解析下拉数据
        int colIndex = 0;
        for (Field field : head.getDeclaredFields()) {
        for (Field field : fields) {
            if (field.isAnnotationPresent(ExcelColumnSelect.class)) {
                ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
                if (excelProperty != null && excelProperty.index() != -1) {
                    colIndex = excelProperty.index();
                    getSelectDataList(excelProperty.index(), field);
                }else{
                    getSelectDataList(colIndex, field);
                }
                getSelectDataList(colIndex, field);
            }
            colIndex++;
        }
@@ -106,27 +109,45 @@
        if (CollUtil.isEmpty(selectMap)) {
            return;
        }
        // 1. 获取相应操作对象
        DataValidationHelper helper = writeSheetHolder.getSheet().getDataValidationHelper(); // 需要设置下拉框的 sheet 页的数据验证助手
        Workbook workbook = writeWorkbookHolder.getWorkbook(); // 获得工作簿
        List<KeyValue<Integer, List<String>>> keyValues = convertList(selectMap.entrySet(), entry -> new KeyValue<>(entry.getKey(), entry.getValue()));
        keyValues.sort(Comparator.comparing(item -> item.getValue().size())); // 升序不然创建下拉会报错
        // 2. 创建数据字典的 sheet 页
        Sheet dictSheet = workbook.createSheet(DICT_SHEET_NAME);
        for (KeyValue<Integer, List<String>> keyValue : keyValues) {
            int rowLength = keyValue.getValue().size();
            // 2.1 设置字典 sheet 页的值,每一列一个字典项
            for (int i = 0; i < rowLength; i++) {
                Row row = dictSheet.getRow(i);
                if (row == null) {
                    row = dictSheet.createRow(i);
        if (ifSetSelect){
            for (KeyValue<Integer, List<String>> keyValue : keyValues) {
                /*起始行、终止行、起始列、终止列  起始行为1即表示表头不设置**/
                CellRangeAddressList addressList = new CellRangeAddressList(FIRST_ROW, LAST_ROW, keyValue.getKey(), keyValue.getKey());
                /*设置下拉框数据**/
                DataValidationConstraint constraint = helper.createExplicitListConstraint(keyValue.getValue().toArray(new String[0]));
                DataValidation dataValidation = helper.createValidation(constraint, addressList);
                if (dataValidation instanceof HSSFDataValidation) {
                    dataValidation.setSuppressDropDownArrow(false);
                } else {
                    dataValidation.setSuppressDropDownArrow(true);
                    dataValidation.setShowErrorBox(true);
                }
                row.createCell(keyValue.getKey()).setCellValue(keyValue.getValue().get(i));
                // 2.2 阻止输入非下拉框的值
                dataValidation.setErrorStyle(DataValidation.ErrorStyle.STOP);
                dataValidation.createErrorBox("提示", "此值不存在于下拉选择中!");
                writeSheetHolder.getSheet().addValidationData(dataValidation);
            }
            // 2.2 设置单元格下拉选择
            setColumnSelect(writeSheetHolder, workbook, helper, keyValue);
        }else{
            // 2. 创建数据字典的 sheet 页
            Sheet dictSheet = workbook.createSheet(DICT_SHEET_NAME);
            for (KeyValue<Integer, List<String>> keyValue : keyValues) {
                int rowLength = keyValue.getValue().size();
                // 2.1 设置字典 sheet 页的值,每一列一部字典项
                for (int i = 0; i < rowLength; i++) {
                    Row row = dictSheet.getRow(i);
                    if (row == null) {
                        row = dictSheet.createRow(i);
                    }
                    row.createCell(keyValue.getKey()).setCellValue(keyValue.getValue().get(i));
                }
                // 2.2 设置单元格下拉选择
                setColumnSelect(writeSheetHolder, workbook, helper, keyValue);
            }
        }
    }
iailab-framework/iailab-common-excel/src/main/java/com/iailab/framework/excel/core/util/ExcelUtils.java
@@ -36,7 +36,7 @@
        EasyExcel.write(response.getOutputStream(), head)
                .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 基于 column 长度,自动适配。最大 255 宽度
                .registerWriteHandler(new SelectSheetWriteHandler(head)) // 基于固定 sheet 实现下拉框
                .registerWriteHandler(new SelectSheetWriteHandler(head,false)) // 基于固定 sheet 实现下拉框
                .registerConverter(new LongStringConverter()) // 避免 Long 类型丢失精度
                .sheet(sheetName).doWrite(data);
        // 设置 header 和 contentType。写在最后的原因是,避免报错时,响应 contentType 已经被修改了
@@ -50,4 +50,17 @@
                .doReadAllSync();
    }
    public static <T> void write(HttpServletResponse response, String filename, String sheetName,
                                 Class<T> head, List<T> data, boolean selectFlag) throws IOException {
        // 输出 Excel
        EasyExcel.write(response.getOutputStream(), head)
                .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 基于 column 长度,自动适配。最大 255 宽度
                .registerWriteHandler(new SelectSheetWriteHandler(head,selectFlag)) // 基于固定 sheet 实现下拉框
                .registerConverter(new LongStringConverter()) // 避免 Long 类型丢失精度
                .sheet(sheetName).doWrite(data);
        // 设置 header 和 contentType。写在最后的原因是,避免报错时,响应 contentType 已经被修改了
        response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, StandardCharsets.UTF_8.name()));
        response.setContentType("application/vnd.ms-excel;charset=UTF-8");
    }
}
iailab-module-data/iailab-module-data-api/src/main/java/com/iailab/module/data/enums/ErrorCodeConstants.java
@@ -7,4 +7,9 @@
    ErrorCode POINT_IMPORT_LIST_IS_EMPTY = new ErrorCode(1_001_001_001, "导入测点数据不能为空!");
    ErrorCode POINT_NOT_EXISTS = new ErrorCode(1_002_001_000, "测点配置不存在");
    ErrorCode POINT_EXISTS = new ErrorCode(1_002_002_000, "测点配置已经存在");
    ErrorCode TAG_IMPORT_LIST_IS_EMPTY = new ErrorCode(2_001_001_001, "导入Tag数据不能为空!");
    ErrorCode TAG_EXISTS = new ErrorCode(2_002_002_001, "Tag已经存在");
}
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/http/controller/admin/HttpTagController.java
@@ -1,21 +1,37 @@
package com.iailab.module.data.channel.http.controller.admin;
import com.iailab.framework.apilog.core.annotation.ApiAccessLog;
import com.iailab.framework.common.pojo.CommonResult;
import com.iailab.framework.common.pojo.PageParam;
import com.iailab.framework.common.pojo.PageResult;
import com.iailab.framework.common.util.object.BeanUtils;
import com.iailab.framework.common.util.object.ConvertUtils;
import com.iailab.framework.excel.core.util.ExcelUtils;
import com.iailab.module.data.channel.http.entity.HttpTagEntity;
import com.iailab.module.data.channel.http.service.HttpTagService;
import com.iailab.module.data.channel.http.vo.HttpTagPageReqVO;
import com.iailab.module.data.channel.http.vo.HttpTagRespVO;
import com.iailab.module.data.channel.tag.vo.TagExportExcelVO;
import com.iailab.module.data.channel.tag.vo.TagImportExcelVO;
import com.iailab.module.data.channel.tag.vo.TagImportRespVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import static com.iailab.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static com.iailab.framework.common.pojo.CommonResult.success;
@@ -75,4 +91,41 @@
        tagService.delete(id);
        return success(true);
    }
    @GetMapping("/export")
    @Operation(summary = "导出modbus tag列表")
    @PreAuthorize("@ss.hasPermission('data:channel-http-tag:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportPointList(@Validated HttpTagPageReqVO reqVO, HttpServletResponse response) throws IOException {
        reqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        PageResult<HttpTagEntity> page = tagService.queryPage(reqVO);
        List<TagExportExcelVO> list = ConvertUtils.sourceToTarget(page.getList(), TagExportExcelVO.class);
        ExcelUtils.write(response, "tag列表.xls", "数据", TagExportExcelVO.class, list, true);
    }
    @GetMapping("/get-import-template")
    @Operation(summary = "获得tag导入模板")
    public void importTemplate(HttpServletResponse response) throws IOException {
        // 手动创建导出 demo
        List<TagImportExcelVO> list = Collections.singletonList(
                TagImportExcelVO.builder().tagName("Tag名称").tagDesc("Tag描述").dataType("String").enabled(1)
                        .build()
        );
        // 输出
        ExcelUtils.write(response, "tag导入模板.xls", "tag列表", TagImportExcelVO.class, list,true);
    }
    @PostMapping("/import")
    @Operation(summary = "导入tag")
    @Parameters({
            @Parameter(name = "file", description = "Excel 文件", required = true),
            @Parameter(name = "updateSupport", description = "是否支持更新,默认为 false", example = "true")
    })
    @PreAuthorize("@ss.hasPermission('data:channel-http-tag:import')")
    public CommonResult<TagImportRespVO> importExcel(@RequestParam("file") MultipartFile file,
                                                     @RequestParam(value = "updateSupport", required = false, defaultValue = "false") Boolean updateSupport,
                                                     @RequestParam("device") String device) throws Exception {
        List<TagImportExcelVO> list = ExcelUtils.read(file, TagImportExcelVO.class);
        return success(tagService.importHttpTagList(list, updateSupport, device));
    }
}
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/http/entity/HttpTagEntity.java
@@ -49,7 +49,7 @@
    /**
     * 是否启用
     */
    private Boolean enabled;
    private Integer enabled;
    /**
     * 创建时间
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/http/service/HttpTagService.java
@@ -3,6 +3,8 @@
import com.iailab.framework.common.pojo.PageResult;
import com.iailab.module.data.channel.http.entity.HttpTagEntity;
import com.iailab.module.data.channel.http.vo.HttpTagPageReqVO;
import com.iailab.module.data.channel.tag.vo.TagImportExcelVO;
import com.iailab.module.data.channel.tag.vo.TagImportRespVO;
import java.util.List;
import java.util.Map;
@@ -23,4 +25,6 @@
    List<HttpTagEntity> selectList(Map<String, Object> params);
    List<HttpTagEntity> getApiId(String code);
    TagImportRespVO importHttpTagList(List<TagImportExcelVO> importTags, boolean isUpdateSupport, String apiId);
}
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/http/service/impl/HttpTagServiceImpl.java
@@ -1,20 +1,28 @@
package com.iailab.module.data.channel.http.service.impl;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.iailab.framework.common.pojo.PageResult;
import com.iailab.framework.common.util.object.BeanUtils;
import com.iailab.framework.common.util.object.ConvertUtils;
import com.iailab.module.data.channel.http.dao.HttpTagDao;
import com.iailab.module.data.channel.http.entity.HttpApiEntity;
import com.iailab.module.data.channel.http.entity.HttpTagEntity;
import com.iailab.module.data.channel.http.service.HttpApiService;
import com.iailab.module.data.channel.http.service.HttpTagService;
import com.iailab.module.data.channel.http.vo.HttpTagPageReqVO;
import com.iailab.module.data.channel.tag.vo.TagImportExcelVO;
import com.iailab.module.data.channel.tag.vo.TagImportRespVO;
import com.iailab.module.data.common.enums.CommonConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.*;
import static com.iailab.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.iailab.module.data.enums.ErrorCodeConstants.*;
@Slf4j
@Service
@@ -73,4 +81,44 @@
                .orderByDesc("create_time"));
    }
    @Override
    public TagImportRespVO importHttpTagList(List<TagImportExcelVO> importTags, boolean isUpdateSupport, String apiId) {
        // 1.1 参数校验
        if (CollUtil.isEmpty(importTags)) {
            throw exception(TAG_IMPORT_LIST_IS_EMPTY);
        }
        // 2. 遍历,逐个创建 or 更新
        TagImportRespVO respVO = TagImportRespVO.builder().createTagNames(new ArrayList<>())
                .updateTagNames(new ArrayList<>()).failureTagNames(new LinkedHashMap<>()).build();
        importTags.forEach(importTag -> {
            // 判断如果不存在,再进行插入
            HttpTagEntity existTag = httpTagDao.selectOne(new QueryWrapper<HttpTagEntity>()
                    .eq("api_id", apiId)
                    .eq("tag_name",importTag.getTagName()));
            if (existTag == null) {
                HttpTagEntity httpTagEntity = ConvertUtils.sourceToTarget(importTag, HttpTagEntity.class);
                httpTagEntity.setId(UUID.randomUUID().toString());
                httpTagEntity.setEnabled(CommonConstant.IS_ENABLE);
                httpTagEntity.setApiId(apiId);
                httpTagEntity.setCreateTime(new Date());
                httpTagDao.insert(httpTagEntity);
                respVO.getCreateTagNames().add(httpTagEntity.getTagName());
                return;
            }
            // 如果存在,判断是否允许更新
            if (!isUpdateSupport) {
                respVO.getFailureTagNames().put(importTag.getTagName(), TAG_EXISTS.getMsg());
                return;
            }
            HttpTagEntity updateTag = BeanUtils.toBean(importTag, HttpTagEntity.class);
            updateTag.setId(existTag.getId());
            baseMapper.updateById(updateTag);
            respVO.getUpdateTagNames().add(importTag.getTagName());
        });
        return respVO;
    }
}
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/http/vo/HttpTagRespVO.java
@@ -39,7 +39,7 @@
    @Schema(description = "是否启用", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
    @ExcelProperty("是否启用")
    private Boolean enabled;
    private Integer enabled;
    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
    @ExcelProperty("创建时间")
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/kio/controller/admin/ChannelKioTagController.java
@@ -1,21 +1,37 @@
package com.iailab.module.data.channel.kio.controller.admin;
import com.iailab.framework.apilog.core.annotation.ApiAccessLog;
import com.iailab.framework.common.pojo.CommonResult;
import com.iailab.framework.common.pojo.PageParam;
import com.iailab.framework.common.pojo.PageResult;
import com.iailab.framework.common.util.object.BeanUtils;
import com.iailab.framework.common.util.object.ConvertUtils;
import com.iailab.framework.excel.core.util.ExcelUtils;
import com.iailab.module.data.channel.kio.entity.ChannelKioTagEntity;
import com.iailab.module.data.channel.kio.service.ChannelKioTagService;
import com.iailab.module.data.channel.kio.vo.KioTagPageReqVO;
import com.iailab.module.data.channel.kio.vo.KioTagRespVO;
import com.iailab.module.data.channel.tag.vo.TagExportExcelVO;
import com.iailab.module.data.channel.tag.vo.TagImportExcelVO;
import com.iailab.module.data.channel.tag.vo.TagImportRespVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import static com.iailab.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static com.iailab.framework.common.pojo.CommonResult.success;
/**
@@ -70,4 +86,40 @@
        return success(true);
    }
    @GetMapping("/export")
    @Operation(summary = "导出modbus tag列表")
    @PreAuthorize("@ss.hasPermission('data:channel-kio-tag:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportPointList(@Validated KioTagPageReqVO reqVO, HttpServletResponse response) throws IOException {
        reqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        PageResult<ChannelKioTagEntity> page = channelKioTagService.queryPage(reqVO);
        List<TagExportExcelVO> list = ConvertUtils.sourceToTarget(page.getList(), TagExportExcelVO.class);
        ExcelUtils.write(response, "tag列表.xls", "数据", TagExportExcelVO.class, list, true);
    }
    @GetMapping("/get-import-template")
    @Operation(summary = "获得tag导入模板")
    public void importTemplate(HttpServletResponse response) throws IOException {
        // 手动创建导出 demo
        List<TagImportExcelVO> list = Collections.singletonList(
                TagImportExcelVO.builder().tagName("Tag名称").tagDesc("Tag描述").dataType("String").enabled(1)
                        .build()
        );
        // 输出
        ExcelUtils.write(response, "tag导入模板.xls", "tag列表", TagImportExcelVO.class, list,true);
    }
    @PostMapping("/import")
    @Operation(summary = "导入tag")
    @Parameters({
            @Parameter(name = "file", description = "Excel 文件", required = true),
            @Parameter(name = "updateSupport", description = "是否支持更新,默认为 false", example = "true")
    })
    @PreAuthorize("@ss.hasPermission('data:channel-kio-tag:import')")
    public CommonResult<TagImportRespVO> importExcel(@RequestParam("file") MultipartFile file,
                                                     @RequestParam(value = "updateSupport", required = false, defaultValue = "false") Boolean updateSupport,
                                                     @RequestParam("device") String device) throws Exception {
        List<TagImportExcelVO> list = ExcelUtils.read(file, TagImportExcelVO.class);
        return success(channelKioTagService.importKioTagList(list, updateSupport, device));
    }
}
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/kio/entity/ChannelKioTagEntity.java
@@ -50,7 +50,7 @@
    /**
     * 是否可以tag
     */
    private Boolean enabled;
    private Integer enabled;
    /**
     * 关联设备
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/kio/service/ChannelKioTagService.java
@@ -3,6 +3,8 @@
import com.iailab.framework.common.pojo.PageResult;
import com.iailab.module.data.channel.kio.entity.ChannelKioTagEntity;
import com.iailab.module.data.channel.kio.vo.KioTagPageReqVO;
import com.iailab.module.data.channel.tag.vo.TagImportExcelVO;
import com.iailab.module.data.channel.tag.vo.TagImportRespVO;
import java.util.List;
@@ -28,4 +30,7 @@
    ChannelKioTagEntity getByTagName(String tagName);
    void deleteByDeviceName(String name);
    TagImportRespVO importKioTagList(List<TagImportExcelVO> importTags, boolean isUpdateSupport, String device);
}
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/kio/service/impl/ChannelKioTagServiceImpl.java
@@ -1,18 +1,26 @@
package com.iailab.module.data.channel.kio.service.impl;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.iailab.framework.common.pojo.PageResult;
import com.iailab.framework.common.util.object.BeanUtils;
import com.iailab.framework.common.util.object.ConvertUtils;
import com.iailab.module.data.channel.kio.dao.ChannelKioTagDao;
import com.iailab.module.data.channel.kio.entity.ChannelKioTagEntity;
import com.iailab.module.data.channel.kio.service.ChannelKioTagService;
import com.iailab.module.data.channel.kio.vo.KioTagPageReqVO;
import com.iailab.module.data.channel.tag.vo.TagImportExcelVO;
import com.iailab.module.data.channel.tag.vo.TagImportRespVO;
import com.iailab.module.data.common.enums.CommonConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.*;
import static com.iailab.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.iailab.module.data.enums.ErrorCodeConstants.*;
/**
 * @author lirm
@@ -71,4 +79,44 @@
    public void deleteByDeviceName(String name) {
        channelKioTagDao.delete(new QueryWrapper<ChannelKioTagEntity>().eq("device",name));
    }
    @Override
    public TagImportRespVO importKioTagList(List<TagImportExcelVO> importTags, boolean isUpdateSupport, String device) {
        // 1.1 参数校验
        if (CollUtil.isEmpty(importTags)) {
            throw exception(TAG_IMPORT_LIST_IS_EMPTY);
        }
        // 2. 遍历,逐个创建 or 更新
        TagImportRespVO respVO = TagImportRespVO.builder().createTagNames(new ArrayList<>())
                .updateTagNames(new ArrayList<>()).failureTagNames(new LinkedHashMap<>()).build();
        importTags.forEach(importTag -> {
            // 判断如果不存在,再进行插入
            ChannelKioTagEntity existTag = channelKioTagDao.selectOne(new QueryWrapper<ChannelKioTagEntity>()
                    .eq("device", device)
                    .eq("tag_name",importTag.getTagName()));
            if (existTag == null) {
                ChannelKioTagEntity channelKioTagEntity = ConvertUtils.sourceToTarget(importTag, ChannelKioTagEntity.class);
                channelKioTagEntity.setId(UUID.randomUUID().toString());
                channelKioTagEntity.setEnabled(CommonConstant.IS_ENABLE);
                channelKioTagEntity.setDevice(device);
                channelKioTagEntity.setCreateTime(new Date());
                channelKioTagDao.insert(channelKioTagEntity);
                respVO.getCreateTagNames().add(channelKioTagEntity.getTagName());
                return;
            }
            // 如果存在,判断是否允许更新
            if (!isUpdateSupport) {
                respVO.getFailureTagNames().put(importTag.getTagName(), TAG_EXISTS.getMsg());
                return;
            }
            ChannelKioTagEntity updateTag = BeanUtils.toBean(importTag, ChannelKioTagEntity.class);
            updateTag.setId(existTag.getId());
            baseMapper.updateById(updateTag);
            respVO.getUpdateTagNames().add(importTag.getTagName());
        });
        return respVO;
    }
}
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/kio/vo/KioTagRespVO.java
@@ -39,7 +39,7 @@
    @Schema(description = "是否可以tag", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
    @ExcelProperty("是否可以tag")
    private Boolean enabled;
    private Integer enabled;
    @Schema(description = "关联设备", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
    @ExcelProperty("关联设备")
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/modbus/controller/admin/ChannelModbusTagController.java
@@ -1,20 +1,37 @@
package com.iailab.module.data.channel.modbus.controller.admin;
import com.iailab.framework.apilog.core.annotation.ApiAccessLog;
import com.iailab.framework.common.pojo.CommonResult;
import com.iailab.framework.common.pojo.PageParam;
import com.iailab.framework.common.pojo.PageResult;
import com.iailab.framework.common.util.object.BeanUtils;
import com.iailab.module.data.channel.modbus.entity.ChannelModBusTagEntity;
import com.iailab.framework.common.util.object.ConvertUtils;
import com.iailab.framework.excel.core.util.ExcelUtils;
import com.iailab.module.data.channel.modbus.entity.ChannelModBusTagEntity;
import com.iailab.module.data.channel.modbus.service.ChannelModbusTagService;
import com.iailab.module.data.channel.modbus.vo.ModBusTagExportExcelVO;
import com.iailab.module.data.channel.modbus.vo.ModBusTagImportExcelVO;
import com.iailab.module.data.channel.modbus.vo.ModBusTagPageReqVO;
import com.iailab.module.data.channel.modbus.vo.ModBusTagRespVO;
import com.iailab.module.data.channel.tag.vo.TagImportRespVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import static com.iailab.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static com.iailab.framework.common.pojo.CommonResult.success;
/**
@@ -31,7 +48,6 @@
    @GetMapping("/page")
    public CommonResult<PageResult<ModBusTagRespVO>> list(@Valid ModBusTagPageReqVO reqVO) {
        PageResult<ChannelModBusTagEntity> page = channelModbusTagService.queryPage(reqVO);
        return success(BeanUtils.toBean(page, ModBusTagRespVO.class));
    }
@@ -82,4 +98,44 @@
        channelModbusTagService.delete(id);
        return success(true);
    }
    @GetMapping("/export")
    @Operation(summary = "导出modbus tag列表")
    @PreAuthorize("@ss.hasPermission('data:channel-modbus-tag:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportPointList(@Validated ModBusTagPageReqVO reqVO, HttpServletResponse response) throws IOException {
        reqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        PageResult<ChannelModBusTagEntity> page = channelModbusTagService.queryPage(reqVO);
        List<ModBusTagExportExcelVO> list = ConvertUtils.sourceToTarget(page.getList(), ModBusTagExportExcelVO.class);
        ExcelUtils.write(response, "tag列表.xls", "数据", ModBusTagExportExcelVO.class, list, true);
    }
    @GetMapping("/get-import-template")
    @Operation(summary = "获得tag导入模板")
    public void importTemplate(HttpServletResponse response) throws IOException {
        // 手动创建导出 demo
        List<ModBusTagImportExcelVO> list = Collections.singletonList(
                ModBusTagImportExcelVO.builder().tagName("Tag名称").tagDesc("Tag描述").dataType("String").
                        address("123").format("1").samplingRate(1000).enabled(1)
                        .build()
        );
        // 输出
        ExcelUtils.write(response, "tag导入模板.xls", "tag列表", ModBusTagImportExcelVO.class, list,true);
    }
    @PostMapping("/import")
    @Operation(summary = "导入tag")
    @Parameters({
            @Parameter(name = "file", description = "Excel 文件", required = true),
            @Parameter(name = "updateSupport", description = "是否支持更新,默认为 false", example = "true")
    })
    @PreAuthorize("@ss.hasPermission('data:channel-modbus-tag:import')")
    public CommonResult<TagImportRespVO> importExcel(@RequestParam("file") MultipartFile file,
                                                     @RequestParam(value = "updateSupport", required = false, defaultValue = "false") Boolean updateSupport,
                                                     @RequestParam("device") String device) throws Exception {
        List<ModBusTagImportExcelVO> list = ExcelUtils.read(file, ModBusTagImportExcelVO.class);
        return success(channelModbusTagService.importModBusTagList(list, updateSupport,device));
    }
}
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/modbus/entity/ChannelModBusTagEntity.java
@@ -39,7 +39,7 @@
    /**
     * 是否启用
     */
    private Boolean enabled;
    private Integer enabled;
    /**
     * 大小端
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/modbus/service/ChannelModbusTagService.java
@@ -3,7 +3,9 @@
import com.iailab.framework.common.pojo.PageResult;
import com.iailab.module.data.channel.modbus.dto.ChannelModbusTagDTO;
import com.iailab.module.data.channel.modbus.entity.ChannelModBusTagEntity;
import com.iailab.module.data.channel.modbus.vo.ModBusTagImportExcelVO;
import com.iailab.module.data.channel.modbus.vo.ModBusTagPageReqVO;
import com.iailab.module.data.channel.tag.vo.TagImportRespVO;
import java.util.List;
@@ -18,7 +20,7 @@
     *
     * @param reqVO
     */
    PageResult queryPage(ModBusTagPageReqVO reqVO);
    PageResult<ChannelModBusTagEntity> queryPage(ModBusTagPageReqVO reqVO);
    
    /**
     * 查询tag详情
@@ -70,12 +72,5 @@
     */
    void deleteByDeviceName(String name);
//    /**
//     * 导入Tag
//     *
//     * @param device
//     * @param file
//     * @throws Exception
//     */
//    void importTag(String device, MultipartFile file) throws Exception;
    TagImportRespVO importModBusTagList(List<ModBusTagImportExcelVO> importTags, boolean isUpdateSupport, String device);
}
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/modbus/service/impl/ChannelModbusTagServiceImpl.java
@@ -1,21 +1,28 @@
package com.iailab.module.data.channel.modbus.service.impl;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.iailab.framework.common.pojo.PageResult;
import com.iailab.framework.common.util.object.BeanUtils;
import com.iailab.framework.common.util.object.ConvertUtils;
import com.iailab.module.data.channel.modbus.dao.ChannelModBusTagDao;
import com.iailab.module.data.channel.modbus.dto.ChannelModbusTagDTO;
import com.iailab.module.data.channel.modbus.entity.ChannelModBusTagEntity;
import com.iailab.module.data.channel.modbus.service.ChannelModbusTagService;
import com.iailab.module.data.channel.modbus.vo.ModBusTagImportExcelVO;
import com.iailab.module.data.channel.modbus.vo.ModBusTagPageReqVO;
import com.iailab.module.data.channel.tag.vo.TagImportRespVO;
import com.iailab.module.data.common.enums.CommonConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.*;
import static com.iailab.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.iailab.module.data.enums.ErrorCodeConstants.*;
/**
 * @author lirm
@@ -82,4 +89,46 @@
        baseMapper.delete(new QueryWrapper<ChannelModBusTagEntity>().eq("device", name));
    }
    @Override
    public TagImportRespVO importModBusTagList(List<ModBusTagImportExcelVO> importTags, boolean isUpdateSupport, String device) {
        // 1.1 参数校验
        if (CollUtil.isEmpty(importTags)) {
            throw exception(TAG_IMPORT_LIST_IS_EMPTY);
        }
        // 2. 遍历,逐个创建 or 更新
        TagImportRespVO respVO = TagImportRespVO.builder().createTagNames(new ArrayList<>())
                .updateTagNames(new ArrayList<>()).failureTagNames(new LinkedHashMap<>()).build();
        importTags.forEach(importTag -> {
            // 判断如果不存在,再进行插入
            ChannelModBusTagEntity existTag = channelModBusTagDao.selectOne(new QueryWrapper<ChannelModBusTagEntity>()
                    .eq("device", device)
                    .eq("tag_name",importTag.getTagName()));
            if (existTag == null) {
                ChannelModBusTagEntity channelModBusTagEntity = ConvertUtils.sourceToTarget(importTag, ChannelModBusTagEntity.class);
                channelModBusTagEntity.setId(UUID.randomUUID().toString());
                channelModBusTagEntity.setEnabled(CommonConstant.IS_ENABLE);
                channelModBusTagEntity.setDevice(device);
                channelModBusTagEntity.setCreateTime(new Date());
                channelModBusTagDao.insert(channelModBusTagEntity);
                respVO.getCreateTagNames().add(channelModBusTagEntity.getTagName());
                return;
            }
            // 如果存在,判断是否允许更新
            if (!isUpdateSupport) {
                respVO.getFailureTagNames().put(importTag.getTagName(), TAG_EXISTS.getMsg());
                return;
            }
            ChannelModBusTagEntity updateTag = BeanUtils.toBean(importTag, ChannelModBusTagEntity.class);
            updateTag.setId(existTag.getId());
            baseMapper.updateById(updateTag);
            respVO.getUpdateTagNames().add(importTag.getTagName());
        });
        return respVO;
    }
}
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/modbus/vo/ModBusTagExportExcelVO.java
对比新文件
@@ -0,0 +1,28 @@
package com.iailab.module.data.channel.modbus.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import com.iailab.module.data.channel.tag.vo.TagExportExcelVO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
 * @author PanZhibao
 * @Description
 * @createTime 2024年08月22日
 */
@Schema(description = "导出 - ModBusTag信息")
@Data
public class ModBusTagExportExcelVO extends TagExportExcelVO {
    @Schema(description = "地址")
    @ExcelProperty(value = "地址",index = 3)
    private String address;
    @Schema(description = "大小端")
    @ExcelProperty(value = "大小端",index = 4)
    private String format;
    @Schema(description = "采集频率")
    @ExcelProperty(value = "采集频率",index = 5)
    private Integer samplingRate;
}
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/modbus/vo/ModBusTagImportExcelVO.java
对比新文件
@@ -0,0 +1,31 @@
package com.iailab.module.data.channel.modbus.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import com.iailab.module.data.channel.tag.vo.TagImportExcelVO;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder;
/**
 * 用户 Excel 导入 VO
 * @author Jay
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = false) // 设置 chain = false,避免用户导入有问题
@SuperBuilder
public class ModBusTagImportExcelVO extends TagImportExcelVO {
    @ExcelProperty(value = "地址", index = 3)
    private String address;
    @ExcelProperty(value = "大小端", index = 4)
    private String format;
    @ExcelProperty(value = "采集频率", index = 5)
    private Integer samplingRate;
}
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/modbus/vo/ModBusTagRespVO.java
@@ -31,7 +31,7 @@
    @Schema(description = "是否启用", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
    @ExcelProperty("是否启用")
    private Boolean enabled;
    private Integer enabled;
    @Schema(description = "大小端", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
    @ExcelProperty("大小端")
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/opcda/controller/admin/ChannelOPCDATagController.java
@@ -1,22 +1,38 @@
package com.iailab.module.data.channel.opcda.controller.admin;
import com.iailab.framework.apilog.core.annotation.ApiAccessLog;
import com.iailab.framework.common.pojo.CommonResult;
import com.iailab.framework.common.pojo.PageParam;
import com.iailab.framework.common.pojo.PageResult;
import com.iailab.framework.common.util.object.BeanUtils;
import com.iailab.framework.common.util.object.ConvertUtils;
import com.iailab.framework.excel.core.util.ExcelUtils;
import com.iailab.module.data.channel.opcda.entity.ChannelOPCDATagEntity;
import com.iailab.module.data.channel.opcda.service.ChannelOPCDATagService;
import com.iailab.module.data.channel.opcda.vo.OpcDaTagExportExcelVO;
import com.iailab.module.data.channel.opcda.vo.OpcDaTagImportExcelVO;
import com.iailab.module.data.channel.opcda.vo.OpcDaTagPageReqVO;
import com.iailab.module.data.channel.opcda.vo.OpcDaTagRespVO;
import com.iailab.module.data.channel.tag.vo.TagImportRespVO;
import com.iailab.module.data.common.exception.RRException;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import static com.iailab.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static com.iailab.framework.common.pojo.CommonResult.success;
/**
@@ -31,21 +47,21 @@
    @Autowired
    private ChannelOPCDATagService channelOPCDATagService;
    @PreAuthorize("@ss.hasPermission('data:channel-opcua:query')")
    @PreAuthorize("@ss.hasPermission('data:channel-opcda:query')")
    @GetMapping("page")
    public CommonResult<PageResult<OpcDaTagRespVO>> list(@Valid OpcDaTagPageReqVO reqVO) {
        PageResult<ChannelOPCDATagEntity> page = channelOPCDATagService.queryPage(reqVO);
        return success(BeanUtils.toBean(page, OpcDaTagRespVO.class));
    }
    @PreAuthorize("@ss.hasPermission('data:channel-opcua:query')")
    @PreAuthorize("@ss.hasPermission('data:channel-opcda:query')")
    @GetMapping("/info/{id}")
    public CommonResult<ChannelOPCDATagEntity> info(@PathVariable("id") String id) {
        ChannelOPCDATagEntity info = channelOPCDATagService.info(id);
        return success(info);
    }
    @PreAuthorize("@ss.hasPermission('data:channel-opcua:create')")
    @PreAuthorize("@ss.hasPermission('data:channel-opcda:create')")
    @PostMapping("/create")
    public CommonResult<Boolean> create(@RequestBody ChannelOPCDATagEntity channelOPCDATagEntity) {
        String id = UUID.randomUUID().toString();
@@ -55,7 +71,7 @@
        return success(true);
    }
    @PreAuthorize("@ss.hasPermission('data:channel-opcua:update')")
    @PreAuthorize("@ss.hasPermission('data:channel-opcda:update')")
    @PutMapping("/update")
    public CommonResult<Boolean> update(@RequestBody ChannelOPCDATagEntity channelOPCDATagEntity) {
        channelOPCDATagEntity.setUpdateTime(new Date());
@@ -63,7 +79,7 @@
        return success(true);
    }
    @PreAuthorize("@ss.hasPermission('data:channel-opcua:delete')")
    @PreAuthorize("@ss.hasPermission('data:channel-opcda:delete')")
    @DeleteMapping("/delete")
    public CommonResult<Boolean> delete(@RequestParam("id") String id) {
        channelOPCDATagService.delete(id);
@@ -82,4 +98,42 @@
        }
        return success("上传成功");
    }
    @GetMapping("/export")
    @Operation(summary = "导出modbus tag列表")
    @PreAuthorize("@ss.hasPermission('data:channel-opcda-tag:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportPointList(@Validated OpcDaTagPageReqVO reqVO, HttpServletResponse response) throws IOException {
        reqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        PageResult<ChannelOPCDATagEntity> page = channelOPCDATagService.queryPage(reqVO);
        List<OpcDaTagExportExcelVO> list = ConvertUtils.sourceToTarget(page.getList(), OpcDaTagExportExcelVO.class);
        ExcelUtils.write(response, "tag列表.xls", "数据", OpcDaTagExportExcelVO.class, list, true);
    }
    @GetMapping("/get-import-template")
    @Operation(summary = "获得tag导入模板")
    public void importTemplate(HttpServletResponse response) throws IOException {
        // 手动创建导出 demo
        List<OpcDaTagImportExcelVO> list = Collections.singletonList(
                OpcDaTagImportExcelVO.builder().tagName("Tag名称").dataType("String").enabled(1)
                        .build()
        );
        // 输出
        ExcelUtils.write(response, "tag导入模板.xls", "tag列表", OpcDaTagImportExcelVO.class, list,true);
    }
    @PostMapping("/import")
    @Operation(summary = "导入tag")
    @Parameters({
            @Parameter(name = "file", description = "Excel 文件", required = true),
            @Parameter(name = "updateSupport", description = "是否支持更新,默认为 false", example = "true")
    })
    @PreAuthorize("@ss.hasPermission('data:channel-opcda-tag:import')")
    public CommonResult<TagImportRespVO> importExcel(@RequestParam("file") MultipartFile file,
                                                     @RequestParam(value = "updateSupport", required = false, defaultValue = "false") Boolean updateSupport,
                                                     @RequestParam("device") String device) throws Exception {
        List<OpcDaTagImportExcelVO> list = ExcelUtils.read(file, OpcDaTagImportExcelVO.class);
        return success(channelOPCDATagService.importOpcDaTagList(list, updateSupport,device));
    }
}
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/opcda/entity/ChannelOPCDATagEntity.java
@@ -42,7 +42,7 @@
    /**
     * 是否可以tag,如果为false,即使定义了但是runtime不会读取该数据
     */
    private Boolean enabled;
    private Integer enabled;
    /**
     * itemId
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/opcda/service/ChannelOPCDATagService.java
@@ -3,12 +3,12 @@
import com.iailab.framework.common.pojo.PageResult;
import com.iailab.module.data.channel.opcda.dto.ChannelOPCDATagDTO;
import com.iailab.module.data.channel.opcda.entity.ChannelOPCDATagEntity;
import com.iailab.module.data.channel.opcda.vo.OpcDaTagImportExcelVO;
import com.iailab.module.data.channel.opcda.vo.OpcDaTagPageReqVO;
import com.iailab.module.data.common.utils.PageUtils;
import com.iailab.module.data.channel.tag.vo.TagImportRespVO;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
import java.util.Map;
/**
 * @author lirm
@@ -36,4 +36,7 @@
    void update(ChannelOPCDATagEntity channelOPCDATagEntity);
    void delete(String id);
    TagImportRespVO importOpcDaTagList(List<OpcDaTagImportExcelVO> importTags, boolean isUpdateSupport, String serverId);
}
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/opcda/service/impl/ChannelOPCDATagServiceImpl.java
@@ -1,16 +1,21 @@
package com.iailab.module.data.channel.opcda.service.impl;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.iailab.framework.common.pojo.PageResult;
import com.iailab.framework.common.util.object.BeanUtils;
import com.iailab.framework.common.util.object.ConvertUtils;
import com.iailab.module.data.channel.opcda.dao.ChannelOPCDATagDao;
import com.iailab.module.data.channel.opcda.dto.ChannelOPCDATagDTO;
import com.iailab.module.data.channel.opcda.entity.ChannelOPCDATagEntity;
import com.iailab.module.data.channel.opcda.service.ChannelOPCDATagService;
import com.iailab.module.data.channel.opcda.vo.OpcDaTagImportExcelVO;
import com.iailab.module.data.channel.opcda.vo.OpcDaTagPageReqVO;
import com.iailab.module.data.channel.tag.vo.TagImportRespVO;
import com.iailab.module.data.common.enums.CommonConstant;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.xssf.usermodel.XSSFRow;
@@ -23,9 +28,10 @@
import javax.annotation.Resource;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.*;
import static com.iailab.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.iailab.module.data.enums.ErrorCodeConstants.*;
/**
 * @author lirm
@@ -116,7 +122,7 @@
                tagEntity.setTagName(row.getCell(1).getStringCellValue());
                tagEntity.setDataType(row.getCell(2).getStringCellValue());
                tagEntity.setItemId(row.getCell(3).getStringCellValue());
                tagEntity.setEnabled(true);
                tagEntity.setEnabled(CommonConstant.IS_ENABLE);
                tagEntity.setServerId(serverId);
                dangerList.add(tagEntity);
            }
@@ -138,4 +144,44 @@
        }
    }
    @Override
    public TagImportRespVO importOpcDaTagList(List<OpcDaTagImportExcelVO> importTags, boolean isUpdateSupport, String serverId) {
        // 1.1 参数校验
        if (CollUtil.isEmpty(importTags)) {
            throw exception(TAG_IMPORT_LIST_IS_EMPTY);
        }
        // 2. 遍历,逐个创建 or 更新
        TagImportRespVO respVO = TagImportRespVO.builder().createTagNames(new ArrayList<>())
                .updateTagNames(new ArrayList<>()).failureTagNames(new LinkedHashMap<>()).build();
        importTags.forEach(importTag -> {
            // 判断如果不存在,再进行插入
            ChannelOPCDATagEntity existTag = channelOPCDATagDao.selectOne(new QueryWrapper<ChannelOPCDATagEntity>()
                    .eq("server_id", serverId)
                    .eq("tag_name",importTag.getTagName()));
            if (existTag == null) {
                ChannelOPCDATagEntity channelOPCDATagEntity = ConvertUtils.sourceToTarget(importTag, ChannelOPCDATagEntity.class);
                channelOPCDATagEntity.setId(UUID.randomUUID().toString());
                channelOPCDATagEntity.setEnabled(CommonConstant.IS_ENABLE);
                channelOPCDATagEntity.setServerId(serverId);
                channelOPCDATagEntity.setCreateTime(new Date());
                channelOPCDATagDao.insert(channelOPCDATagEntity);
                respVO.getCreateTagNames().add(channelOPCDATagEntity.getTagName());
                return;
            }
            // 如果存在,判断是否允许更新
            if (!isUpdateSupport) {
                respVO.getFailureTagNames().put(importTag.getTagName(), TAG_EXISTS.getMsg());
                return;
            }
            ChannelOPCDATagEntity updateTag = BeanUtils.toBean(importTag, ChannelOPCDATagEntity.class);
            updateTag.setId(existTag.getId());
            baseMapper.updateById(updateTag);
            respVO.getUpdateTagNames().add(importTag.getTagName());
        });
        return respVO;
    }
}
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/opcda/vo/OpcDaTagExportExcelVO.java
对比新文件
@@ -0,0 +1,51 @@
package com.iailab.module.data.channel.opcda.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.iailab.framework.excel.core.annotations.DictFormat;
import com.iailab.framework.excel.core.annotations.ExcelColumnSelect;
import com.iailab.framework.excel.core.convert.DictConvert;
import com.iailab.framework.excel.core.function.ExcelColumnSelectFunction;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.stereotype.Component;
import java.util.List;
/**
 * @author PanZhibao
 * @Description
 * @createTime 2024年08月22日
 */
@Schema(description = "导出 - Tag信息")
@Data
@ExcelIgnoreUnannotated
@Component
public class OpcDaTagExportExcelVO implements ExcelColumnSelectFunction {
    @Schema(description = "Tag名称")
    @ExcelProperty(value = "Tag名称")
    private String tagName;
    @Schema(description = "数据类型")
    @ExcelProperty(value = "数据类型", converter = DictConvert.class)
    @ExcelColumnSelect(dictType = "tag_data_type")
    @DictFormat("tag_data_type")
    private String dataType;
    @Schema(description = "是否启用")
    @ExcelProperty(value = "是否启用", converter = DictConvert.class)
    @ExcelColumnSelect(dictType = "com_is_int")
    @DictFormat("com_is_int")
    private Integer enabled;
    @Override
    public String getName() {
        return null;
    }
    @Override
    public List<String> getOptions() {
        return null;
    }
}
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/opcda/vo/OpcDaTagImportExcelVO.java
对比新文件
@@ -0,0 +1,53 @@
package com.iailab.module.data.channel.opcda.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import com.iailab.framework.excel.core.annotations.DictFormat;
import com.iailab.framework.excel.core.annotations.ExcelColumnSelect;
import com.iailab.framework.excel.core.convert.DictConvert;
import com.iailab.framework.excel.core.function.ExcelColumnSelectFunction;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder;
import org.springframework.stereotype.Component;
import java.util.List;
/**
 * 用户 Excel 导入 VO
 * @author Jay
 */
@Data
@SuperBuilder
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = false) // 设置 chain = false,避免用户导入有问题
@Component
public class OpcDaTagImportExcelVO implements ExcelColumnSelectFunction {
    @ExcelProperty(value = "Tag名称")
    private String tagName;
    @ExcelProperty(value = "数据类型")
    @ExcelColumnSelect(dictType = "tag_data_type")
    @DictFormat("tag_data_type")
    private String dataType;
    @Schema(description = "是否启用")
    @ExcelProperty(value = "是否启用", converter = DictConvert.class)
    @ExcelColumnSelect(dictType = "com_is_int")
    @DictFormat("com_is_int")
    private Integer enabled;
    @Override
    public String getName() {
        return null;
    }
    @Override
    public List<String> getOptions() {
        return null;
    }
}
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/opcda/vo/OpcDaTagRespVO.java
@@ -35,7 +35,7 @@
    @Schema(description = "是否启用", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
    @ExcelProperty("是否启用")
    private Boolean enabled;
    private Integer enabled;
    @Schema(description = "itemID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
    @ExcelProperty("itemID")
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/opcua/controller/admin/ChannelOPCUATagController.java
@@ -1,20 +1,37 @@
package com.iailab.module.data.channel.opcua.controller.admin;
import com.iailab.framework.apilog.core.annotation.ApiAccessLog;
import com.iailab.framework.common.pojo.CommonResult;
import com.iailab.framework.common.pojo.PageParam;
import com.iailab.framework.common.pojo.PageResult;
import com.iailab.framework.common.util.object.BeanUtils;
import com.iailab.framework.common.util.object.ConvertUtils;
import com.iailab.framework.excel.core.util.ExcelUtils;
import com.iailab.module.data.channel.opcua.entity.ChannelOPCUATagEntity;
import com.iailab.module.data.channel.opcua.service.ChannelOPCUATagService;
import com.iailab.module.data.channel.opcua.vo.OpcUaTagExportExcelVO;
import com.iailab.module.data.channel.opcua.vo.OpcUaTagImportExcelVO;
import com.iailab.module.data.channel.opcua.vo.OpcUaTagPageReqVO;
import com.iailab.module.data.channel.opcua.vo.OpcUaTagRespVO;
import com.iailab.module.data.channel.tag.vo.TagImportRespVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import static com.iailab.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static com.iailab.framework.common.pojo.CommonResult.success;
/**
@@ -68,16 +85,40 @@
        return success(true);
    }
//    @PostMapping("/import/{device}")
//    public R importTag(@PathVariable("device") String device, @RequestParam("file") MultipartFile file) {
//        try {
//            if (file.isEmpty()) {
//                throw new RRException("上传文件不能为空");
//            }
//            channelOpcuaTagService.importTag(device, file);
//        } catch (Exception ex) {
//            return R.error(ex.getMessage());
//        }
//        return R.ok();
//    }
    @GetMapping("/export")
    @Operation(summary = "导出modbus tag列表")
    @PreAuthorize("@ss.hasPermission('data:channel-opcua-tag:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportPointList(@Validated OpcUaTagPageReqVO reqVO, HttpServletResponse response) throws IOException {
        reqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        PageResult<ChannelOPCUATagEntity> page = channelOpcuaTagService.queryPage(reqVO);
        List<OpcUaTagExportExcelVO> list = ConvertUtils.sourceToTarget(page.getList(), OpcUaTagExportExcelVO.class);
        ExcelUtils.write(response, "tag列表.xls", "数据", OpcUaTagExportExcelVO.class, list, true);
    }
    @GetMapping("/get-import-template")
    @Operation(summary = "获得tag导入模板")
    public void importTemplate(HttpServletResponse response) throws IOException {
        // 手动创建导出 demo
        List<OpcUaTagImportExcelVO> list = Collections.singletonList(
                OpcUaTagImportExcelVO.builder().tagName("Tag名称").dataType("String").address("123").samplingRate(1000).enabled(1)
                        .build()
        );
        // 输出
        ExcelUtils.write(response, "tag导入模板.xls", "tag列表", OpcUaTagImportExcelVO.class, list,true);
    }
    @PostMapping("/import")
    @Operation(summary = "导入tag")
    @Parameters({
            @Parameter(name = "file", description = "Excel 文件", required = true),
            @Parameter(name = "updateSupport", description = "是否支持更新,默认为 false", example = "true")
    })
    @PreAuthorize("@ss.hasPermission('data:channel-opcua-tag:import')")
    public CommonResult<TagImportRespVO> importExcel(@RequestParam("file") MultipartFile file,
                                                     @RequestParam(value = "updateSupport", required = false, defaultValue = "false") Boolean updateSupport,
                                                     @RequestParam("device") String device) throws Exception {
        List<OpcUaTagImportExcelVO> list = ExcelUtils.read(file, OpcUaTagImportExcelVO.class);
        return success(channelOpcuaTagService.importOpcUaTagList(list, updateSupport,device));
    }
}
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/opcua/entity/ChannelOPCUATagEntity.java
@@ -38,7 +38,7 @@
    /**
     * 是否可以tag,如果为false,即使定义了但是runtime不会读取该数据
     */
    private Boolean enabled;
    private Integer enabled;
    /**
     * 关联设备
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/opcua/service/ChannelOPCUATagService.java
@@ -3,7 +3,9 @@
import com.iailab.framework.common.pojo.PageResult;
import com.iailab.module.data.channel.opcua.dto.ChannelOPCUATagDTO;
import com.iailab.module.data.channel.opcua.entity.ChannelOPCUATagEntity;
import com.iailab.module.data.channel.opcua.vo.OpcUaTagImportExcelVO;
import com.iailab.module.data.channel.opcua.vo.OpcUaTagPageReqVO;
import com.iailab.module.data.channel.tag.vo.TagImportRespVO;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
@@ -34,4 +36,6 @@
    void importTag(String device, MultipartFile file) throws Exception;
    TagImportRespVO importOpcUaTagList(List<OpcUaTagImportExcelVO> importTags, boolean isUpdateSupport, String device);
}
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/opcua/service/impl/ChannelOPCUATagServiceImpl.java
@@ -1,16 +1,21 @@
package com.iailab.module.data.channel.opcua.service.impl;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.iailab.framework.common.pojo.PageResult;
import com.iailab.framework.common.util.object.BeanUtils;
import com.iailab.framework.common.util.object.ConvertUtils;
import com.iailab.module.data.channel.opcua.dao.ChannelOPCUATagDao;
import com.iailab.module.data.channel.opcua.dto.ChannelOPCUATagDTO;
import com.iailab.module.data.channel.opcua.entity.ChannelOPCUATagEntity;
import com.iailab.module.data.channel.opcua.service.ChannelOPCUATagService;
import com.iailab.module.data.channel.opcua.vo.OpcUaTagImportExcelVO;
import com.iailab.module.data.channel.opcua.vo.OpcUaTagPageReqVO;
import com.iailab.module.data.channel.tag.vo.TagImportRespVO;
import com.iailab.module.data.common.enums.CommonConstant;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.xssf.usermodel.XSSFRow;
@@ -23,9 +28,10 @@
import javax.annotation.Resource;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.*;
import static com.iailab.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.iailab.module.data.enums.ErrorCodeConstants.*;
/**
 * @author lirm
@@ -122,7 +128,7 @@
                }else if(row.getCell(3).getStringCellValue().equals("3")){
                    tagEntity.setAddress(String.format("4%04d",Integer.parseInt(row.getCell(4).getStringCellValue())));
                }
                tagEntity.setEnabled(true);
                tagEntity.setEnabled(1);
                tagEntity.setDevice(device);
                tagEntity.setSamplingRate(1);
                dangerList.add(tagEntity);
@@ -144,4 +150,44 @@
            throw ex;
        }
    }
    @Override
    public TagImportRespVO importOpcUaTagList(List<OpcUaTagImportExcelVO> importTags, boolean isUpdateSupport, String device) {
        // 1.1 参数校验
        if (CollUtil.isEmpty(importTags)) {
            throw exception(TAG_IMPORT_LIST_IS_EMPTY);
        }
        // 2. 遍历,逐个创建 or 更新
        TagImportRespVO respVO = TagImportRespVO.builder().createTagNames(new ArrayList<>())
                .updateTagNames(new ArrayList<>()).failureTagNames(new LinkedHashMap<>()).build();
        importTags.forEach(importTag -> {
            // 判断如果不存在,再进行插入
            ChannelOPCUATagEntity existTag = channelOPCUATagDao.selectOne(new QueryWrapper<ChannelOPCUATagEntity>()
                    .eq("device", device)
                    .eq("tag_name",importTag.getTagName()));
            if (existTag == null) {
                ChannelOPCUATagEntity channelOpCuaTagEntity = ConvertUtils.sourceToTarget(importTag, ChannelOPCUATagEntity.class);
                channelOpCuaTagEntity.setId(UUID.randomUUID().toString());
                channelOpCuaTagEntity.setEnabled(CommonConstant.IS_ENABLE);
                channelOpCuaTagEntity.setDevice(device);
                channelOpCuaTagEntity.setCreateTime(new Date());
                channelOPCUATagDao.insert(channelOpCuaTagEntity);
                respVO.getCreateTagNames().add(channelOpCuaTagEntity.getTagName());
                return;
            }
            // 如果存在,判断是否允许更新
            if (!isUpdateSupport) {
                respVO.getFailureTagNames().put(importTag.getTagName(), TAG_EXISTS.getMsg());
                return;
            }
            ChannelOPCUATagEntity updateTag = BeanUtils.toBean(importTag, ChannelOPCUATagEntity.class);
            updateTag.setId(existTag.getId());
            baseMapper.updateById(updateTag);
            respVO.getUpdateTagNames().add(importTag.getTagName());
        });
        return respVO;
    }
}
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/opcua/vo/OpcUaTagExportExcelVO.java
对比新文件
@@ -0,0 +1,59 @@
package com.iailab.module.data.channel.opcua.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.iailab.framework.excel.core.annotations.DictFormat;
import com.iailab.framework.excel.core.annotations.ExcelColumnSelect;
import com.iailab.framework.excel.core.convert.DictConvert;
import com.iailab.framework.excel.core.function.ExcelColumnSelectFunction;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.stereotype.Component;
import java.util.List;
/**
 * @author PanZhibao
 * @Description
 * @createTime 2024年08月22日
 */
@Schema(description = "导出 - Tag信息")
@Data
@ExcelIgnoreUnannotated
@Component
public class OpcUaTagExportExcelVO implements ExcelColumnSelectFunction {
    @Schema(description = "Tag名称")
    @ExcelProperty(value = "Tag名称")
    private String tagName;
    @Schema(description = "数据类型")
    @ExcelProperty(value = "数据类型", converter = DictConvert.class)
    @ExcelColumnSelect(dictType = "tag_data_type")
    @DictFormat("tag_data_type")
    private String dataType;
    @Schema(description = "地址")
    @ExcelProperty(value = "地址")
    private String address;
    @Schema(description = "采集频率")
    @ExcelProperty(value = "采集频率")
    private Integer samplingRate;
    @Schema(description = "是否启用")
    @ExcelProperty(value = "是否启用", converter = DictConvert.class)
    @ExcelColumnSelect(dictType = "com_is_int")
    @DictFormat("com_is_int")
    private Integer enabled;
    @Override
    public String getName() {
        return null;
    }
    @Override
    public List<String> getOptions() {
        return null;
    }
}
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/opcua/vo/OpcUaTagImportExcelVO.java
对比新文件
@@ -0,0 +1,61 @@
package com.iailab.module.data.channel.opcua.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import com.iailab.framework.excel.core.annotations.DictFormat;
import com.iailab.framework.excel.core.annotations.ExcelColumnSelect;
import com.iailab.framework.excel.core.convert.DictConvert;
import com.iailab.framework.excel.core.function.ExcelColumnSelectFunction;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder;
import org.springframework.stereotype.Component;
import java.util.List;
/**
 * 用户 Excel 导入 VO
 * @author Jay
 */
@Data
@SuperBuilder
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = false) // 设置 chain = false,避免用户导入有问题
@Component
public class OpcUaTagImportExcelVO implements ExcelColumnSelectFunction {
    @ExcelProperty(value = "Tag名称")
    private String tagName;
    @ExcelProperty(value = "数据类型")
    @ExcelColumnSelect(dictType = "tag_data_type")
    @DictFormat("tag_data_type")
    private String dataType;
    @Schema(description = "地址")
    @ExcelProperty(value = "地址")
    private String address;
    @Schema(description = "采集频率")
    @ExcelProperty(value = "采集频率")
    private Integer samplingRate;
    @Schema(description = "是否启用")
    @ExcelProperty(value = "是否启用", converter = DictConvert.class)
    @ExcelColumnSelect(dictType = "com_is_int")
    @DictFormat("com_is_int")
    private Integer enabled;
    @Override
    public String getName() {
        return null;
    }
    @Override
    public List<String> getOptions() {
        return null;
    }
}
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/opcua/vo/OpcUaTagRespVO.java
@@ -31,7 +31,7 @@
    @Schema(description = "是否启用", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
    @ExcelProperty("是否启用")
    private Boolean enabled;
    private Integer enabled;
    @Schema(description = "关联设备", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
    @ExcelProperty("关联设备")
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/tag/vo/TagExportExcelVO.java
对比新文件
@@ -0,0 +1,55 @@
package com.iailab.module.data.channel.tag.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.iailab.framework.excel.core.annotations.DictFormat;
import com.iailab.framework.excel.core.annotations.ExcelColumnSelect;
import com.iailab.framework.excel.core.convert.DictConvert;
import com.iailab.framework.excel.core.function.ExcelColumnSelectFunction;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.stereotype.Component;
import java.util.List;
/**
 * @author PanZhibao
 * @Description
 * @createTime 2024年08月22日
 */
@Schema(description = "导出 - Tag信息")
@Data
@ExcelIgnoreUnannotated
@Component
public class TagExportExcelVO implements ExcelColumnSelectFunction {
    @Schema(description = "Tag名称")
    @ExcelProperty(value = "Tag名称", index = 0)
    private String tagName;
    @Schema(description = "Tag描述")
    @ExcelProperty(value = "Tag描述", index = 1)
    private String tagDesc;
    @Schema(description = "数据类型")
    @ExcelProperty(value = "数据类型", index = 2, converter = DictConvert.class)
    @ExcelColumnSelect(dictType = "tag_data_type")
    @DictFormat("tag_data_type")
    private String dataType;
    @Schema(description = "是否启用")
    @ExcelProperty(value = "是否启用", converter = DictConvert.class)
    @ExcelColumnSelect(dictType = "com_is_int")
    @DictFormat("com_is_int")
    private Integer enabled;
    @Override
    public String getName() {
        return null;
    }
    @Override
    public List<String> getOptions() {
        return null;
    }
}
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/tag/vo/TagImportExcelVO.java
对比新文件
@@ -0,0 +1,56 @@
package com.iailab.module.data.channel.tag.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import com.iailab.framework.excel.core.annotations.DictFormat;
import com.iailab.framework.excel.core.annotations.ExcelColumnSelect;
import com.iailab.framework.excel.core.convert.DictConvert;
import com.iailab.framework.excel.core.function.ExcelColumnSelectFunction;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import lombok.experimental.SuperBuilder;
import org.springframework.stereotype.Component;
import java.util.List;
/**
 * 用户 Excel 导入 VO
 * @author Jay
 */
@Data
@SuperBuilder
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = false) // 设置 chain = false,避免用户导入有问题
@Component
public class TagImportExcelVO  implements ExcelColumnSelectFunction {
    @ExcelProperty(value = "Tag名称", index = 0)
    private String tagName;
    @ExcelProperty(value = "Tag描述", index = 1)
    private String tagDesc;
    @ExcelProperty(value = "数据类型", index = 2)
    @ExcelColumnSelect(dictType = "tag_data_type")
    @DictFormat("tag_data_type")
    private String dataType;
    @Schema(description = "是否启用")
    @ExcelProperty(value = "是否启用", converter = DictConvert.class)
    @ExcelColumnSelect(dictType = "com_is_int")
    @DictFormat("com_is_int")
    private Integer enabled;
    @Override
    public String getName() {
        return null;
    }
    @Override
    public List<String> getOptions() {
        return null;
    }
}
iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/channel/tag/vo/TagImportRespVO.java
对比新文件
@@ -0,0 +1,26 @@
package com.iailab.module.data.channel.tag.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Builder;
import lombok.Data;
import java.util.List;
import java.util.Map;
/**
 * @author Jay
 */
@Schema(description = "管理后台 - 用户导入 Response VO")
@Data
@Builder
public class TagImportRespVO {
    @Schema(description = "创建成功的Tag名称数组", requiredMode = Schema.RequiredMode.REQUIRED)
    private List<String> createTagNames;
    @Schema(description = "更新成功的Tag名称数组", requiredMode = Schema.RequiredMode.REQUIRED)
    private List<String> updateTagNames;
    @Schema(description = "导入失败的Tag集合,key 为Tag名称,value 为失败原因", requiredMode = Schema.RequiredMode.REQUIRED)
    private Map<String, String> failureTagNames;
}