diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/annotation/Excel.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/annotation/Excel.java index 7e2666c..f17b2e9 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/annotation/Excel.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/annotation/Excel.java @@ -143,6 +143,12 @@ public @interface Excel */ public String[] args() default {}; + /** + * 设置只能选择不能输入的列内容,从数据库获取的,默认数组第一个是class名称,第二个及之后是此class的方法名称(例如getId,getName) + */ + public String[] dbCombo() default {}; + + /** * 字段类型(0:导出导入;1:仅导出;2:仅导入) */ diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/HwDictConstants.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/HwDictConstants.java index a6a18c1..3d673e8 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/HwDictConstants.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/HwDictConstants.java @@ -70,11 +70,16 @@ public class HwDictConstants { public static final String DEVICE_TYPE_GATEWAY_SUB_EQUIPMENT = "2";//网关子设备 public static final String DEVICE_TYPE_DIRECT_CONNECT_DEVICE = "3";//直连设备 + public static final String DEVICE_NETWORKING_MODE_WIFI = "1";//设备联网方式:WiFi + public static final Long DEVICE_ACCESS_PROTOCOL_MQTT = 1L;//设备接入协议:MQTT + public static final Long DEVICE_DATA_FORMAT_JSON = 1L;//数据格式:JSON + public static final String REDIS_KEY_DEVICE_INFO = "hw_device_info";//保存设备用户名和密码等信息的redis的key public static final String REDIS_KEY_ONLINE_DEVICE_COUNT_INFO = "online_device_count";//按照天存放每天设备在线数量 public static final String DEVICE_MODE_STATUS_NORMAL = "1";//设备模型正常状态 + public static final String DEVICE_MODE_STATUS_DELETED = "9";//设备模型删除状态 public static final String SCENE_DEFAULT_FLAG_YES = "1";//场景是否默认标识:是 public static final String SCENE_DEFAULT_FLAG_NO = "0";//场景是否默认标识:否 diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/DeviceTypeEnums.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/DeviceTypeEnums.java new file mode 100644 index 0000000..f47f3b2 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/enums/DeviceTypeEnums.java @@ -0,0 +1,62 @@ +package com.ruoyi.common.core.enums; + + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public enum DeviceTypeEnums { + + /** + * 网关设备 + */ + GATEWAY_DEVICE("1","网关设备"), + + /** + * 网关子设备 + */ + SUB_DEVICE("2", "网关子设备"), + + /** + * 直连设备 + */ + DIRECT_CONNECT_DEVICE("3", "直连设备"); + + + // 属性值与属性名Map + public static final Map dataCodeTypeMap = Arrays.stream(values()).collect( + Collectors.toMap( + DeviceTypeEnums::getDataCode, + DeviceTypeEnums::getDataType + ) + ); + + // 属性名与属性值Map + public static final Map dataTypeCodeMap = Arrays.stream(values()).collect( + Collectors.toMap( + DeviceTypeEnums::getDataType, + DeviceTypeEnums::getDataCode + ) + ); + + // 性别值 + private final String dataCode; + + // 性别名 + private final String dataType; + + DeviceTypeEnums(String dataCode, String dataType) { + this.dataCode = dataCode; + this.dataType = dataType; + } + + public String getDataCode() { + return dataCode; + } + + public String getDataType() { + return dataType; + } + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/poi/ExcelUtil.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/poi/ExcelUtil.java index b0533b4..8bfcfbc 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/poi/ExcelUtil.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/poi/ExcelUtil.java @@ -20,6 +20,7 @@ import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import javax.servlet.http.HttpServletResponse; + import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.RegExUtils; import org.apache.commons.lang3.reflect.FieldUtils; @@ -67,13 +68,12 @@ import com.ruoyi.common.core.utils.reflect.ReflectUtils; * * @author ruoyi */ -public class ExcelUtil -{ +public class ExcelUtil { private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class); public static final String FORMULA_REGEX_STR = "=|-|\\+|@"; - public static final String[] FORMULA_STR = { "=", "-", "+", "@" }; + public static final String[] FORMULA_STR = {"=", "-", "+", "@"}; /** * Excel sheet最大行数,默认65536 @@ -160,6 +160,8 @@ public class ExcelUtil */ private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("######0.00"); + private Map> classListMap = new HashMap>(); + /** * 实体对象 */ @@ -170,8 +172,8 @@ public class ExcelUtil */ public String[] excludeFields; - public ExcelUtil(Class clazz) - { + + public ExcelUtil(Class clazz) { this.clazz = clazz; } @@ -181,15 +183,12 @@ public class ExcelUtil * @param fields 列属性名 示例[单个"name"/多个"id","name"] * @throws Exception */ - public void hideColumn(String... fields) - { + public void hideColumn(String... fields) { this.excludeFields = fields; } - public void init(List list, String sheetName, String title, Type type) - { - if (list == null) - { + public void init(List list, String sheetName, String title, Type type) { + if (list == null) { list = new ArrayList(); } this.list = list; @@ -205,15 +204,12 @@ public class ExcelUtil /** * 创建excel第一行标题 */ - public void createTitle() - { - if (StringUtils.isNotEmpty(title)) - { + public void createTitle() { + if (StringUtils.isNotEmpty(title)) { subMergedFirstRowNum++; subMergedLastRowNum++; int titleLastCol = this.fields.size() - 1; - if (isSubList()) - { + if (isSubList()) { titleLastCol = titleLastCol + subFields.size() - 1; } Row titleRow = sheet.createRow(rownum == 0 ? rownum++ : 0); @@ -228,16 +224,13 @@ public class ExcelUtil /** * 创建对象的子列表名称 */ - public void createSubHead() - { - if (isSubList()) - { + public void createSubHead() { + if (isSubList()) { subMergedFirstRowNum++; subMergedLastRowNum++; Row subRow = sheet.createRow(rownum); int excelNum = 0; - for (Object[] objects : fields) - { + for (Object[] objects : fields) { Excel attr = (Excel) objects[1]; Cell headCell1 = subRow.createCell(excelNum); headCell1.setCellValue(attr.name()); @@ -246,8 +239,7 @@ public class ExcelUtil } int headFirstRow = excelNum - 1; int headLastRow = headFirstRow + subFields.size() - 1; - if (headLastRow > headFirstRow) - { + if (headLastRow > headFirstRow) { sheet.addMergedRegion(new CellRangeAddress(rownum, rownum, headFirstRow, headLastRow)); } rownum++; @@ -256,93 +248,79 @@ public class ExcelUtil /** * 对excel表单默认第一个索引名转换成list - * + * * @param is 输入流 * @return 转换后集合 */ - public List importExcel(InputStream is) throws Exception - { + public List importExcel(InputStream is) throws Exception { return importExcel(is, 0); } /** * 对excel表单默认第一个索引名转换成list - * - * @param is 输入流 + * + * @param is 输入流 * @param titleNum 标题占用行数 * @return 转换后集合 */ - public List importExcel(InputStream is, int titleNum) throws Exception - { + public List importExcel(InputStream is, int titleNum) throws Exception { return importExcel(StringUtils.EMPTY, is, titleNum); } /** * 对excel表单指定表格索引名转换成list - * + * * @param sheetName 表格索引名 - * @param titleNum 标题占用行数 - * @param is 输入流 + * @param titleNum 标题占用行数 + * @param is 输入流 * @return 转换后集合 */ - public List importExcel(String sheetName, InputStream is, int titleNum) throws Exception - { + public List importExcel(String sheetName, InputStream is, int titleNum) throws Exception { this.type = Type.IMPORT; this.wb = WorkbookFactory.create(is); List list = new ArrayList(); // 如果指定sheet名,则取指定sheet中的内容 否则默认指向第1个sheet Sheet sheet = StringUtils.isNotEmpty(sheetName) ? wb.getSheet(sheetName) : wb.getSheetAt(0); - if (sheet == null) - { + if (sheet == null) { throw new IOException("文件sheet不存在"); } // 获取最后一个非空行的行下标,比如总行数为n,则返回的为n-1 int rows = sheet.getLastRowNum(); - if (rows > 0) - { + if (rows > 0) { // 定义一个map用于存放excel列的序号和field. Map cellMap = new HashMap(); // 获取表头 Row heard = sheet.getRow(titleNum); - for (int i = 0; i < heard.getPhysicalNumberOfCells(); i++) - { + for (int i = 0; i < heard.getPhysicalNumberOfCells(); i++) { Cell cell = heard.getCell(i); - if (StringUtils.isNotNull(cell)) - { + if (StringUtils.isNotNull(cell)) { String value = this.getCellValue(heard, i).toString(); cellMap.put(value, i); - } - else - { + } else { cellMap.put(null, i); } } // 有数据时才处理 得到类的所有field. List fields = this.getFields(); Map fieldsMap = new HashMap(); - for (Object[] objects : fields) - { + for (Object[] objects : fields) { Excel attr = (Excel) objects[1]; Integer column = cellMap.get(attr.name()); - if (column != null) - { + if (column != null) { fieldsMap.put(column, objects); } } - for (int i = titleNum + 1; i <= rows; i++) - { + for (int i = titleNum + 1; i <= rows; i++) { // 从第2行开始取数据,默认第一行是表头. Row row = sheet.getRow(i); // 判断当前行是否是空行 - if (isRowEmpty(row)) - { + if (isRowEmpty(row)) { continue; } T entity = null; - for (Map.Entry entry : fieldsMap.entrySet()) - { + for (Map.Entry entry : fieldsMap.entrySet()) { Object val = this.getCellValue(row, entry.getKey()); // 如果不存在实例则新建. @@ -352,74 +330,44 @@ public class ExcelUtil Excel attr = (Excel) entry.getValue()[1]; // 取得类型,并根据对象类型设置值. Class fieldType = field.getType(); - if (String.class == fieldType) - { + if (String.class == fieldType) { String s = Convert.toStr(val); - if (StringUtils.endsWith(s, ".0")) - { + if (StringUtils.endsWith(s, ".0")) { val = StringUtils.substringBefore(s, ".0"); - } - else - { + } else { String dateFormat = field.getAnnotation(Excel.class).dateFormat(); - if (StringUtils.isNotEmpty(dateFormat)) - { + if (StringUtils.isNotEmpty(dateFormat)) { val = parseDateToStr(dateFormat, val); - } - else - { + } else { val = Convert.toStr(val); } } - } - else if ((Integer.TYPE == fieldType || Integer.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val))) - { + } else if ((Integer.TYPE == fieldType || Integer.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val))) { val = Convert.toInt(val); - } - else if ((Long.TYPE == fieldType || Long.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val))) - { + } else if ((Long.TYPE == fieldType || Long.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val))) { val = Convert.toLong(val); - } - else if (Double.TYPE == fieldType || Double.class == fieldType) - { + } else if (Double.TYPE == fieldType || Double.class == fieldType) { val = Convert.toDouble(val); - } - else if (Float.TYPE == fieldType || Float.class == fieldType) - { + } else if (Float.TYPE == fieldType || Float.class == fieldType) { val = Convert.toFloat(val); - } - else if (BigDecimal.class == fieldType) - { + } else if (BigDecimal.class == fieldType) { val = Convert.toBigDecimal(val); - } - else if (Date.class == fieldType) - { - if (val instanceof String) - { + } else if (Date.class == fieldType) { + if (val instanceof String) { val = DateUtils.parseDate(val); - } - else if (val instanceof Double) - { + } else if (val instanceof Double) { val = DateUtil.getJavaDate((Double) val); } - } - else if (Boolean.TYPE == fieldType || Boolean.class == fieldType) - { + } else if (Boolean.TYPE == fieldType || Boolean.class == fieldType) { val = Convert.toBool(val, false); } - if (StringUtils.isNotNull(fieldType)) - { + if (StringUtils.isNotNull(fieldType)) { String propertyName = field.getName(); - if (StringUtils.isNotEmpty(attr.targetAttr())) - { + if (StringUtils.isNotEmpty(attr.targetAttr())) { propertyName = field.getName() + "." + attr.targetAttr(); - } - else if (StringUtils.isNotEmpty(attr.readConverterExp())) - { + } else if (StringUtils.isNotEmpty(attr.readConverterExp())) { val = reverseByExp(Convert.toStr(val), attr.readConverterExp(), attr.separator()); - } - else if (!attr.handler().equals(ExcelHandlerAdapter.class)) - { + } else if (!attr.handler().equals(ExcelHandlerAdapter.class)) { val = dataFormatHandlerAdapter(val, attr); } ReflectUtils.invokeSetter(entity, propertyName, val); @@ -434,27 +382,25 @@ public class ExcelUtil /** * 对list数据源将其里面的数据导入到excel表单 * - * @param response 返回数据 - * @param list 导出数据集合 + * @param response 返回数据 + * @param list 导出数据集合 * @param sheetName 工作表的名称 * @return 结果 */ - public void exportExcel(HttpServletResponse response, List list, String sheetName) - { + public void exportExcel(HttpServletResponse response, List list, String sheetName) { exportExcel(response, list, sheetName, StringUtils.EMPTY); } /** * 对list数据源将其里面的数据导入到excel表单 * - * @param response 返回数据 - * @param list 导出数据集合 + * @param response 返回数据 + * @param list 导出数据集合 * @param sheetName 工作表的名称 - * @param title 标题 + * @param title 标题 * @return 结果 */ - public void exportExcel(HttpServletResponse response, List list, String sheetName, String title) - { + public void exportExcel(HttpServletResponse response, List list, String sheetName, String title) { response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setCharacterEncoding("utf-8"); this.init(list, sheetName, title, Type.EXPORT); @@ -467,8 +413,7 @@ public class ExcelUtil * @param sheetName 工作表的名称 * @return 结果 */ - public void importTemplateExcel(HttpServletResponse response, String sheetName) - { + public void importTemplateExcel(HttpServletResponse response, String sheetName) { importTemplateExcel(response, sheetName, StringUtils.EMPTY); } @@ -476,11 +421,21 @@ public class ExcelUtil * 对list数据源将其里面的数据导入到excel表单 * * @param sheetName 工作表的名称 - * @param title 标题 * @return 结果 */ - public void importTemplateExcel(HttpServletResponse response, String sheetName, String title) - { + public void importTemplateExcel(HttpServletResponse response, String sheetName, Map> classListMap) { + this.classListMap = classListMap; + importTemplateExcel(response, sheetName, StringUtils.EMPTY); + } + + /** + * 对list数据源将其里面的数据导入到excel表单 + * + * @param sheetName 工作表的名称 + * @param title 标题 + * @return 结果 + */ + public void importTemplateExcel(HttpServletResponse response, String sheetName, String title) { response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setCharacterEncoding("utf-8"); this.init(null, sheetName, title, Type.IMPORT); @@ -489,22 +444,16 @@ public class ExcelUtil /** * 对list数据源将其里面的数据导入到excel表单 - * + * * @return 结果 */ - public void exportExcel(HttpServletResponse response) - { - try - { + public void exportExcel(HttpServletResponse response) { + try { writeSheet(); wb.write(response.getOutputStream()); - } - catch (Exception e) - { + } catch (Exception e) { log.error("导出Excel异常{}", e.getMessage()); - } - finally - { + } finally { IOUtils.closeQuietly(wb); } } @@ -512,37 +461,29 @@ public class ExcelUtil /** * 创建写入数据到Sheet */ - public void writeSheet() - { + public void writeSheet() { // 取出一共有多少个sheet. int sheetNo = Math.max(1, (int) Math.ceil(list.size() * 1.0 / sheetSize)); - for (int index = 0; index < sheetNo; index++) - { + for (int index = 0; index < sheetNo; index++) { createSheet(sheetNo, index); // 产生一行 Row row = sheet.createRow(rownum); int column = 0; // 写入各个字段的列头名称 - for (Object[] os : fields) - { + for (Object[] os : fields) { Field field = (Field) os[0]; Excel excel = (Excel) os[1]; - if (Collection.class.isAssignableFrom(field.getType())) - { - for (Field subField : subFields) - { + if (Collection.class.isAssignableFrom(field.getType())) { + for (Field subField : subFields) { Excel subExcel = subField.getAnnotation(Excel.class); this.createHeadCell(subExcel, row, column++); } - } - else - { + } else { this.createHeadCell(excel, row, column++); } } - if (Type.EXPORT.equals(type)) - { + if (Type.EXPORT.equals(type)) { fillExcelData(index, row); addStatisticsRow(); } @@ -551,57 +492,45 @@ public class ExcelUtil /** * 填充excel数据 - * + * * @param index 序号 - * @param row 单元格行 + * @param row 单元格行 */ @SuppressWarnings("unchecked") - public void fillExcelData(int index, Row row) - { + public void fillExcelData(int index, Row row) { int startNo = index * sheetSize; int endNo = Math.min(startNo + sheetSize, list.size()); int rowNo = (1 + rownum) - startNo; - for (int i = startNo; i < endNo; i++) - { + for (int i = startNo; i < endNo; i++) { rowNo = isSubList() ? (i > 1 ? rowNo + 1 : rowNo + i) : i + 1 + rownum - startNo; row = sheet.createRow(rowNo); // 得到导出对象. T vo = (T) list.get(i); Collection subList = null; - if (isSubList()) - { - if (isSubListValue(vo)) - { + if (isSubList()) { + if (isSubListValue(vo)) { subList = getListCellValue(vo); subMergedLastRowNum = subMergedLastRowNum + subList.size(); - } - else - { + } else { subMergedFirstRowNum++; subMergedLastRowNum++; } } int column = 0; - for (Object[] os : fields) - { + for (Object[] os : fields) { Field field = (Field) os[0]; Excel excel = (Excel) os[1]; - if (Collection.class.isAssignableFrom(field.getType()) && StringUtils.isNotNull(subList)) - { + if (Collection.class.isAssignableFrom(field.getType()) && StringUtils.isNotNull(subList)) { boolean subFirst = false; - for (Object obj : subList) - { - if (subFirst) - { + for (Object obj : subList) { + if (subFirst) { rowNo++; row = sheet.createRow(rowNo); } List subFields = FieldUtils.getFieldsListWithAnnotation(obj.getClass(), Excel.class); int subIndex = 0; - for (Field subField : subFields) - { - if (subField.isAnnotationPresent(Excel.class)) - { + for (Field subField : subFields) { + if (subField.isAnnotationPresent(Excel.class)) { subField.setAccessible(true); Excel attr = subField.getAnnotation(Excel.class); this.addCell(attr, row, (T) obj, subField, column + subIndex); @@ -611,9 +540,7 @@ public class ExcelUtil subFirst = true; } this.subMergedFirstRowNum = this.subMergedFirstRowNum + subList.size(); - } - else - { + } else { this.addCell(excel, row, vo, field, column++); } } @@ -622,12 +549,11 @@ public class ExcelUtil /** * 创建表格样式 - * + * * @param wb 工作薄对象 * @return 样式列表 */ - private Map createStyles(Workbook wb) - { + private Map createStyles(Workbook wb) { // 写入各条记录,每条记录对应excel表中的一行 Map styles = new HashMap(); CellStyle style = wb.createCellStyle(); @@ -675,19 +601,16 @@ public class ExcelUtil /** * 根据Excel注解创建表格头样式 - * + * * @param wb 工作薄对象 * @return 自定义样式列表 */ - private Map annotationHeaderStyles(Workbook wb, Map styles) - { + private Map annotationHeaderStyles(Workbook wb, Map styles) { Map headerStyles = new HashMap(); - for (Object[] os : fields) - { + for (Object[] os : fields) { Excel excel = (Excel) os[1]; String key = StringUtils.format("header_{}_{}", excel.headerColor(), excel.headerBackgroundColor()); - if (!headerStyles.containsKey(key)) - { + if (!headerStyles.containsKey(key)) { CellStyle style = wb.createCellStyle(); style.cloneStyleFrom(styles.get("data")); style.setAlignment(HorizontalAlignment.CENTER); @@ -708,19 +631,16 @@ public class ExcelUtil /** * 根据Excel注解创建表格列样式 - * + * * @param wb 工作薄对象 * @return 自定义样式列表 */ - private Map annotationDataStyles(Workbook wb) - { + private Map annotationDataStyles(Workbook wb) { Map styles = new HashMap(); - for (Object[] os : fields) - { + for (Object[] os : fields) { Excel excel = (Excel) os[1]; String key = StringUtils.format("data_{}_{}_{}", excel.align(), excel.color(), excel.backgroundColor()); - if (!styles.containsKey(key)) - { + if (!styles.containsKey(key)) { CellStyle style = wb.createCellStyle(); style.setAlignment(excel.align()); style.setVerticalAlignment(VerticalAlignment.CENTER); @@ -748,20 +668,17 @@ public class ExcelUtil /** * 创建单元格 */ - public Cell createHeadCell(Excel attr, Row row, int column) - { + public Cell createHeadCell(Excel attr, Row row, int column) { // 创建列 Cell cell = row.createCell(column); // 写入列信息 cell.setCellValue(attr.name()); setDataValidation(attr, row, column); cell.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor()))); - if (isSubList()) - { + if (isSubList()) { // 填充默认样式,防止合并单元格样式失效 sheet.setDefaultColumnStyle(column, styles.get(StringUtils.format("data_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor()))); - if (attr.needMerge()) - { + if (attr.needMerge()) { sheet.addMergedRegion(new CellRangeAddress(rownum - 1, rownum, column, column)); } } @@ -770,40 +687,30 @@ public class ExcelUtil /** * 设置单元格信息 - * + * * @param value 单元格值 - * @param attr 注解相关 - * @param cell 单元格信息 + * @param attr 注解相关 + * @param cell 单元格信息 */ - public void setCellVo(Object value, Excel attr, Cell cell) - { - if (ColumnType.STRING == attr.cellType()) - { + public void setCellVo(Object value, Excel attr, Cell cell) { + if (ColumnType.STRING == attr.cellType()) { String cellValue = Convert.toStr(value); // 对于任何以表达式触发字符 =-+@开头的单元格,直接使用tab字符作为前缀,防止CSV注入。 - if (StringUtils.startsWithAny(cellValue, FORMULA_STR)) - { + if (StringUtils.startsWithAny(cellValue, FORMULA_STR)) { cellValue = RegExUtils.replaceFirst(cellValue, FORMULA_REGEX_STR, "\t$0"); } - if (value instanceof Collection && StringUtils.equals("[]", cellValue)) - { + if (value instanceof Collection && StringUtils.equals("[]", cellValue)) { cellValue = StringUtils.EMPTY; } cell.setCellValue(StringUtils.isNull(cellValue) ? attr.defaultValue() : cellValue + attr.suffix()); - } - else if (ColumnType.NUMERIC == attr.cellType()) - { - if (StringUtils.isNotNull(value)) - { + } else if (ColumnType.NUMERIC == attr.cellType()) { + if (StringUtils.isNotNull(value)) { cell.setCellValue(StringUtils.contains(Convert.toStr(value), ".") ? Convert.toDouble(value) : Convert.toInt(value)); } - } - else if (ColumnType.IMAGE == attr.cellType()) - { + } else if (ColumnType.IMAGE == attr.cellType()) { ClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), cell.getRow().getRowNum(), (short) (cell.getColumnIndex() + 1), cell.getRow().getRowNum() + 1); String imagePath = Convert.toStr(value); - if (StringUtils.isNotEmpty(imagePath)) - { + if (StringUtils.isNotEmpty(imagePath)) { byte[] data = ImageUtils.getImage(imagePath); getDrawingPatriarch(cell.getSheet()).createPicture(anchor, cell.getSheet().getWorkbook().addPicture(data, getImageType(data))); @@ -814,10 +721,8 @@ public class ExcelUtil /** * 获取画布 */ - public static Drawing getDrawingPatriarch(Sheet sheet) - { - if (sheet.getDrawingPatriarch() == null) - { + public static Drawing getDrawingPatriarch(Sheet sheet) { + if (sheet.getDrawingPatriarch() == null) { sheet.createDrawingPatriarch(); } return sheet.getDrawingPatriarch(); @@ -826,15 +731,11 @@ public class ExcelUtil /** * 获取图片类型,设置图片插入类型 */ - public int getImageType(byte[] value) - { + public int getImageType(byte[] value) { String type = FileTypeUtils.getFileExtendName(value); - if ("JPG".equalsIgnoreCase(type)) - { + if ("JPG".equalsIgnoreCase(type)) { return Workbook.PICTURE_TYPE_JPEG; - } - else if ("PNG".equalsIgnoreCase(type)) - { + } else if ("PNG".equalsIgnoreCase(type)) { return Workbook.PICTURE_TYPE_PNG; } return Workbook.PICTURE_TYPE_JPEG; @@ -843,49 +744,57 @@ public class ExcelUtil /** * 创建表格样式 */ - public void setDataValidation(Excel attr, Row row, int column) - { - if (attr.name().indexOf("注:") >= 0) - { + public void setDataValidation(Excel attr, Row row, int column) { + if (attr.name().indexOf("注:") >= 0) { sheet.setColumnWidth(column, 6000); - } - else - { + } else { // 设置列宽 sheet.setColumnWidth(column, (int) ((attr.width() + 0.72) * 256)); } - if (StringUtils.isNotEmpty(attr.prompt()) || attr.combo().length > 0) - { - if (attr.combo().length > 15 || StringUtils.join(attr.combo()).length() > 255) - { + if (StringUtils.isNotEmpty(attr.prompt()) || attr.combo().length > 0) { + if (attr.combo().length > 15 || StringUtils.join(attr.combo()).length() > 255) { // 如果下拉数大于15或字符串长度大于255,则使用一个新sheet存储,避免生成的模板下拉值获取不到 setXSSFValidationWithHidden(sheet, attr.combo(), attr.prompt(), 1, 100, column, column); - } - else - { + } else { // 提示信息或只能选择不能输入的列内容. setPromptOrValidation(sheet, attr.combo(), attr.prompt(), 1, 100, column, column); } } + + try { + if (StringUtils.isNotEmpty(attr.prompt()) || attr.dbCombo().length > 0) { + List classList = classListMap.get(attr.dbCombo()[0]); + if (classList != null && !classList.isEmpty()) { + String[] textList = new String[classList.size()]; + for (int i = 0; i < classList.size(); i++) { + Object clazz = classList.get(i); + Object objectId = clazz.getClass().getMethod(attr.dbCombo()[1]).invoke(clazz); + Object objectName = clazz.getClass().getMethod(attr.dbCombo()[2]).invoke(clazz); + textList[i] = objectId + "-" + objectName;//避免名称重复,将ID也附上 + } + + setXSSFValidationWithHidden(sheet, textList, attr.prompt(), 1, 200, column, column); + } + } + } catch (Exception e) { + log.error("导出Excel失败{}", e); + } + } /** * 添加单元格 */ - public Cell addCell(Excel attr, Row row, T vo, Field field, int column) - { + public Cell addCell(Excel attr, Row row, T vo, Field field, int column) { Cell cell = null; - try - { + try { // 设置行高 row.setHeight(maxHeight); // 根据Excel中设置情况决定是否导出,有些情况需要保持为空,希望用户填写这一列. - if (attr.isExport()) - { + if (attr.isExport()) { // 创建cell cell = row.createCell(column); - if (isSubListValue(vo) && getListCellValue(vo).size() > 1 && attr.needMerge()) - { + if (isSubListValue(vo) && getListCellValue(vo).size() > 1 && attr.needMerge()) { CellRangeAddress cellAddress = new CellRangeAddress(subMergedFirstRowNum, subMergedLastRowNum, column, column); sheet.addMergedRegion(cellAddress); } @@ -896,32 +805,21 @@ public class ExcelUtil String dateFormat = attr.dateFormat(); String readConverterExp = attr.readConverterExp(); String separator = attr.separator(); - if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value)) - { + if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value)) { cell.setCellValue(parseDateToStr(dateFormat, value)); - } - else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value)) - { + } else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value)) { cell.setCellValue(convertByExp(Convert.toStr(value), readConverterExp, separator)); - } - else if (value instanceof BigDecimal && -1 != attr.scale()) - { + } else if (value instanceof BigDecimal && -1 != attr.scale()) { cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).doubleValue()); - } - else if (!attr.handler().equals(ExcelHandlerAdapter.class)) - { + } else if (!attr.handler().equals(ExcelHandlerAdapter.class)) { cell.setCellValue(dataFormatHandlerAdapter(value, attr)); - } - else - { + } else { // 设置列类型 setCellVo(value, attr, cell); } addStatisticsData(column, Convert.toStr(value), attr); } - } - catch (Exception e) - { + } catch (Exception e) { log.error("导出Excel失败{}", e); } return cell; @@ -929,36 +827,31 @@ public class ExcelUtil /** * 设置 POI XSSFSheet 单元格提示或选择框 - * - * @param sheet 表单 - * @param textlist 下拉框显示的内容 + * + * @param sheet 表单 + * @param textlist 下拉框显示的内容 * @param promptContent 提示内容 - * @param firstRow 开始行 - * @param endRow 结束行 - * @param firstCol 开始列 - * @param endCol 结束列 + * @param firstRow 开始行 + * @param endRow 结束行 + * @param firstCol 开始列 + * @param endCol 结束列 */ public void setPromptOrValidation(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow, - int firstCol, int endCol) - { + int firstCol, int endCol) { DataValidationHelper helper = sheet.getDataValidationHelper(); DataValidationConstraint constraint = textlist.length > 0 ? helper.createExplicitListConstraint(textlist) : helper.createCustomConstraint("DD1"); CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol); DataValidation dataValidation = helper.createValidation(constraint, regions); - if (StringUtils.isNotEmpty(promptContent)) - { + if (StringUtils.isNotEmpty(promptContent)) { // 如果设置了提示信息则鼠标放上去提示 dataValidation.createPromptBox("", promptContent); dataValidation.setShowPromptBox(true); } // 处理Excel兼容性问题 - if (dataValidation instanceof XSSFDataValidation) - { + if (dataValidation instanceof XSSFDataValidation) { dataValidation.setSuppressDropDownArrow(true); dataValidation.setShowErrorBox(true); - } - else - { + } else { dataValidation.setSuppressDropDownArrow(false); } sheet.addValidationData(dataValidation); @@ -966,21 +859,19 @@ public class ExcelUtil /** * 设置某些列的值只能输入预制的数据,显示下拉框(兼容超出一定数量的下拉框). - * - * @param sheet 要设置的sheet. - * @param textlist 下拉框显示的内容 + * + * @param sheet 要设置的sheet. + * @param textlist 下拉框显示的内容 * @param promptContent 提示内容 - * @param firstRow 开始行 - * @param endRow 结束行 - * @param firstCol 开始列 - * @param endCol 结束列 + * @param firstRow 开始行 + * @param endRow 结束行 + * @param firstCol 开始列 + * @param endCol 结束列 */ - public void setXSSFValidationWithHidden(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow, int firstCol, int endCol) - { + public void setXSSFValidationWithHidden(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow, int firstCol, int endCol) { String hideSheetName = "combo_" + firstCol + "_" + endCol; Sheet hideSheet = wb.createSheet(hideSheetName); // 用于存储 下拉菜单数据 - for (int i = 0; i < textlist.length; i++) - { + for (int i = 0; i < textlist.length; i++) { hideSheet.createRow(i).createCell(0).setCellValue(textlist[i]); } // 创建名称,可被其他单元格引用 @@ -994,20 +885,16 @@ public class ExcelUtil CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol); // 数据有效性对象 DataValidation dataValidation = helper.createValidation(constraint, regions); - if (StringUtils.isNotEmpty(promptContent)) - { + if (StringUtils.isNotEmpty(promptContent)) { // 如果设置了提示信息则鼠标放上去提示 dataValidation.createPromptBox("", promptContent); dataValidation.setShowPromptBox(true); } // 处理Excel兼容性问题 - if (dataValidation instanceof XSSFDataValidation) - { + if (dataValidation instanceof XSSFDataValidation) { dataValidation.setSuppressDropDownArrow(true); dataValidation.setShowErrorBox(true); - } - else - { + } else { dataValidation.setSuppressDropDownArrow(false); } @@ -1020,32 +907,24 @@ public class ExcelUtil * 解析导出值 0=男,1=女,2=未知 * * @param propertyValue 参数值 - * @param converterExp 翻译注解 - * @param separator 分隔符 + * @param converterExp 翻译注解 + * @param separator 分隔符 * @return 解析后值 */ - public static String convertByExp(String propertyValue, String converterExp, String separator) - { + public static String convertByExp(String propertyValue, String converterExp, String separator) { StringBuilder propertyString = new StringBuilder(); String[] convertSource = converterExp.split(","); - for (String item : convertSource) - { + for (String item : convertSource) { String[] itemArray = item.split("="); - if (StringUtils.containsAny(propertyValue, separator)) - { - for (String value : propertyValue.split(separator)) - { - if (itemArray[0].equals(value)) - { + if (StringUtils.containsAny(propertyValue, separator)) { + for (String value : propertyValue.split(separator)) { + if (itemArray[0].equals(value)) { propertyString.append(itemArray[1] + separator); break; } } - } - else - { - if (itemArray[0].equals(propertyValue)) - { + } else { + if (itemArray[0].equals(propertyValue)) { return itemArray[1]; } } @@ -1055,34 +934,26 @@ public class ExcelUtil /** * 反向解析值 男=0,女=1,未知=2 - * + * * @param propertyValue 参数值 - * @param converterExp 翻译注解 - * @param separator 分隔符 + * @param converterExp 翻译注解 + * @param separator 分隔符 * @return 解析后值 */ - public static String reverseByExp(String propertyValue, String converterExp, String separator) - { + public static String reverseByExp(String propertyValue, String converterExp, String separator) { StringBuilder propertyString = new StringBuilder(); String[] convertSource = converterExp.split(","); - for (String item : convertSource) - { + for (String item : convertSource) { String[] itemArray = item.split("="); - if (StringUtils.containsAny(propertyValue, separator)) - { - for (String value : propertyValue.split(separator)) - { - if (itemArray[1].equals(value)) - { + if (StringUtils.containsAny(propertyValue, separator)) { + for (String value : propertyValue.split(separator)) { + if (itemArray[1].equals(value)) { propertyString.append(itemArray[0] + separator); break; } } - } - else - { - if (itemArray[1].equals(propertyValue)) - { + } else { + if (itemArray[1].equals(propertyValue)) { return itemArray[0]; } } @@ -1097,16 +968,12 @@ public class ExcelUtil * @param excel 数据注解 * @return */ - public String dataFormatHandlerAdapter(Object value, Excel excel) - { - try - { + public String dataFormatHandlerAdapter(Object value, Excel excel) { + try { Object instance = excel.handler().newInstance(); - Method formatMethod = excel.handler().getMethod("format", new Class[] { Object.class, String[].class }); + Method formatMethod = excel.handler().getMethod("format", new Class[]{Object.class, String[].class}); value = formatMethod.invoke(instance, value, excel.args()); - } - catch (Exception e) - { + } catch (Exception e) { log.error("不能格式化数据 " + excel.handler(), e.getMessage()); } return Convert.toStr(value); @@ -1115,21 +982,15 @@ public class ExcelUtil /** * 合计统计信息 */ - private void addStatisticsData(Integer index, String text, Excel entity) - { - if (entity != null && entity.isStatistics()) - { + private void addStatisticsData(Integer index, String text, Excel entity) { + if (entity != null && entity.isStatistics()) { Double temp = 0D; - if (!statistics.containsKey(index)) - { + if (!statistics.containsKey(index)) { statistics.put(index, temp); } - try - { + try { temp = Double.valueOf(text); - } - catch (NumberFormatException e) - { + } catch (NumberFormatException e) { } statistics.put(index, statistics.get(index) + temp); } @@ -1138,18 +999,15 @@ public class ExcelUtil /** * 创建统计行 */ - public void addStatisticsRow() - { - if (statistics.size() > 0) - { + public void addStatisticsRow() { + if (statistics.size() > 0) { Row row = sheet.createRow(sheet.getLastRowNum() + 1); Set keys = statistics.keySet(); Cell cell = row.createCell(0); cell.setCellStyle(styles.get("total")); cell.setCellValue("合计"); - for (Integer key : keys) - { + for (Integer key : keys) { cell = row.createCell(key); cell.setCellStyle(styles.get("total")); cell.setCellValue(DOUBLE_FORMAT.format(statistics.get(key))); @@ -1161,28 +1019,22 @@ public class ExcelUtil /** * 获取bean中的属性值 * - * @param vo 实体对象 + * @param vo 实体对象 * @param field 字段 * @param excel 注解 * @return 最终的属性值 * @throws Exception */ - private Object getTargetValue(T vo, Field field, Excel excel) throws Exception - { + private Object getTargetValue(T vo, Field field, Excel excel) throws Exception { Object o = field.get(vo); - if (StringUtils.isNotEmpty(excel.targetAttr())) - { + if (StringUtils.isNotEmpty(excel.targetAttr())) { String target = excel.targetAttr(); - if (target.contains(".")) - { + if (target.contains(".")) { String[] targets = target.split("[.]"); - for (String name : targets) - { + for (String name : targets) { o = getValue(o, name); } - } - else - { + } else { o = getValue(o, target); } } @@ -1197,10 +1049,8 @@ public class ExcelUtil * @return value * @throws Exception */ - private Object getValue(Object o, String name) throws Exception - { - if (StringUtils.isNotNull(o) && StringUtils.isNotEmpty(name)) - { + private Object getValue(Object o, String name) throws Exception { + if (StringUtils.isNotNull(o) && StringUtils.isNotEmpty(name)) { Class clazz = o.getClass(); Field field = clazz.getDeclaredField(name); field.setAccessible(true); @@ -1212,8 +1062,7 @@ public class ExcelUtil /** * 得到所有定义字段 */ - private void createExcelField() - { + private void createExcelField() { this.fields = getFields(); this.fields = this.fields.stream().sorted(Comparator.comparing(objects -> ((Excel) objects[1]).sort())).collect(Collectors.toList()); this.maxHeight = getRowHeight(); @@ -1222,27 +1071,21 @@ public class ExcelUtil /** * 获取字段注解信息 */ - public List getFields() - { + public List getFields() { List fields = new ArrayList(); List tempFields = new ArrayList<>(); tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields())); tempFields.addAll(Arrays.asList(clazz.getDeclaredFields())); - for (Field field : tempFields) - { - if (!ArrayUtils.contains(this.excludeFields, field.getName())) - { + for (Field field : tempFields) { + if (!ArrayUtils.contains(this.excludeFields, field.getName())) { // 单注解 - if (field.isAnnotationPresent(Excel.class)) - { + if (field.isAnnotationPresent(Excel.class)) { Excel attr = field.getAnnotation(Excel.class); - if (attr != null && (attr.type() == Type.ALL || attr.type() == type)) - { + if (attr != null && (attr.type() == Type.ALL || attr.type() == type)) { field.setAccessible(true); - fields.add(new Object[] { field, attr }); + fields.add(new Object[]{field, attr}); } - if (Collection.class.isAssignableFrom(field.getType())) - { + if (Collection.class.isAssignableFrom(field.getType())) { subMethod = getSubMethod(field.getName(), clazz); ParameterizedType pt = (ParameterizedType) field.getGenericType(); Class subClass = (Class) pt.getActualTypeArguments()[0]; @@ -1251,17 +1094,14 @@ public class ExcelUtil } // 多注解 - if (field.isAnnotationPresent(Excels.class)) - { + if (field.isAnnotationPresent(Excels.class)) { Excels attrs = field.getAnnotation(Excels.class); Excel[] excels = attrs.value(); - for (Excel attr : excels) - { + for (Excel attr : excels) { if (!ArrayUtils.contains(this.excludeFields, field.getName() + "." + attr.targetAttr()) - && (attr != null && (attr.type() == Type.ALL || attr.type() == type))) - { + && (attr != null && (attr.type() == Type.ALL || attr.type() == type))) { field.setAccessible(true); - fields.add(new Object[] { field, attr }); + fields.add(new Object[]{field, attr}); } } } @@ -1273,11 +1113,9 @@ public class ExcelUtil /** * 根据注解获取最大行高 */ - public short getRowHeight() - { + public short getRowHeight() { double maxHeight = 0; - for (Object[] os : this.fields) - { + for (Object[] os : this.fields) { Excel excel = (Excel) os[1]; maxHeight = Math.max(maxHeight, excel.height()); } @@ -1287,8 +1125,7 @@ public class ExcelUtil /** * 创建一个工作簿 */ - public void createWorkbook() - { + public void createWorkbook() { this.wb = new SXSSFWorkbook(500); this.sheet = wb.createSheet(); wb.setSheetName(0, sheetName); @@ -1297,15 +1134,13 @@ public class ExcelUtil /** * 创建工作表 - * + * * @param sheetNo sheet数量 - * @param index 序号 + * @param index 序号 */ - public void createSheet(int sheetNo, int index) - { + public void createSheet(int sheetNo, int index) { // 设置工作表的名称. - if (sheetNo > 1 && index > 0) - { + if (sheetNo > 1 && index > 0) { this.sheet = wb.createSheet(); this.createTitle(); wb.setSheetName(index, sheetName + index); @@ -1314,59 +1149,40 @@ public class ExcelUtil /** * 获取单元格值 - * - * @param row 获取的行 + * + * @param row 获取的行 * @param column 获取单元格列号 * @return 单元格值 */ - public Object getCellValue(Row row, int column) - { - if (row == null) - { + public Object getCellValue(Row row, int column) { + if (row == null) { return row; } Object val = ""; - try - { + try { Cell cell = row.getCell(column); - if (StringUtils.isNotNull(cell)) - { - if (cell.getCellType() == CellType.NUMERIC || cell.getCellType() == CellType.FORMULA) - { + if (StringUtils.isNotNull(cell)) { + if (cell.getCellType() == CellType.NUMERIC || cell.getCellType() == CellType.FORMULA) { val = cell.getNumericCellValue(); - if (DateUtil.isCellDateFormatted(cell)) - { + if (DateUtil.isCellDateFormatted(cell)) { val = DateUtil.getJavaDate((Double) val); // POI Excel 日期格式转换 - } - else - { - if ((Double) val % 1 != 0) - { + } else { + if ((Double) val % 1 != 0) { val = new BigDecimal(val.toString()); - } - else - { + } else { val = new DecimalFormat("0").format(val); } } - } - else if (cell.getCellType() == CellType.STRING) - { + } else if (cell.getCellType() == CellType.STRING) { val = cell.getStringCellValue(); - } - else if (cell.getCellType() == CellType.BOOLEAN) - { + } else if (cell.getCellType() == CellType.BOOLEAN) { val = cell.getBooleanCellValue(); - } - else if (cell.getCellType() == CellType.ERROR) - { + } else if (cell.getCellType() == CellType.ERROR) { val = cell.getErrorCellValue(); } } - } - catch (Exception e) - { + } catch (Exception e) { return val; } return val; @@ -1374,21 +1190,17 @@ public class ExcelUtil /** * 判断是否是空行 - * + * * @param row 判断的行 * @return */ - private boolean isRowEmpty(Row row) - { - if (row == null) - { + private boolean isRowEmpty(Row row) { + if (row == null) { return true; } - for (int i = row.getFirstCellNum(); i < row.getLastCellNum(); i++) - { + for (int i = row.getFirstCellNum(); i < row.getLastCellNum(); i++) { Cell cell = row.getCell(i); - if (cell != null && cell.getCellType() != CellType.BLANK) - { + if (cell != null && cell.getCellType() != CellType.BLANK) { return false; } } @@ -1397,32 +1209,23 @@ public class ExcelUtil /** * 格式化不同类型的日期对象 - * + * * @param dateFormat 日期格式 - * @param val 被格式化的日期对象 + * @param val 被格式化的日期对象 * @return 格式化后的日期字符 */ - public String parseDateToStr(String dateFormat, Object val) - { - if (val == null) - { + public String parseDateToStr(String dateFormat, Object val) { + if (val == null) { return ""; } String str; - if (val instanceof Date) - { + if (val instanceof Date) { str = DateUtils.parseDateToStr(dateFormat, (Date) val); - } - else if (val instanceof LocalDateTime) - { + } else if (val instanceof LocalDateTime) { str = DateUtils.parseDateToStr(dateFormat, DateUtils.toDate((LocalDateTime) val)); - } - else if (val instanceof LocalDate) - { + } else if (val instanceof LocalDate) { str = DateUtils.parseDateToStr(dateFormat, DateUtils.toDate((LocalDate) val)); - } - else - { + } else { str = val.toString(); } return str; @@ -1431,31 +1234,25 @@ public class ExcelUtil /** * 是否有对象的子列表 */ - public boolean isSubList() - { + public boolean isSubList() { return StringUtils.isNotNull(subFields) && subFields.size() > 0; } /** * 是否有对象的子列表,集合不为空 */ - public boolean isSubListValue(T vo) - { + public boolean isSubListValue(T vo) { return StringUtils.isNotNull(subFields) && subFields.size() > 0 && StringUtils.isNotNull(getListCellValue(vo)) && getListCellValue(vo).size() > 0; } /** * 获取集合的值 */ - public Collection getListCellValue(Object obj) - { + public Collection getListCellValue(Object obj) { Object value; - try - { - value = subMethod.invoke(obj, new Object[] {}); - } - catch (Exception e) - { + try { + value = subMethod.invoke(obj, new Object[]{}); + } catch (Exception e) { return new ArrayList(); } return (Collection) value; @@ -1463,23 +1260,19 @@ public class ExcelUtil /** * 获取对象的子列表方法 - * - * @param name 名称 + * + * @param name 名称 * @param pojoClass 类对象 * @return 子列表方法 */ - public Method getSubMethod(String name, Class pojoClass) - { + public Method getSubMethod(String name, Class pojoClass) { StringBuffer getMethodName = new StringBuffer("get"); getMethodName.append(name.substring(0, 1).toUpperCase()); getMethodName.append(name.substring(1)); Method method = null; - try - { - method = pojoClass.getMethod(getMethodName.toString(), new Class[] {}); - } - catch (Exception e) - { + try { + method = pojoClass.getMethod(getMethodName.toString(), new Class[]{}); + } catch (Exception e) { log.error("获取对象异常{}", e.getMessage()); } return method; diff --git a/ruoyi-modules/hw-business/src/main/java/com/ruoyi/business/controller/HwDeviceController.java b/ruoyi-modules/hw-business/src/main/java/com/ruoyi/business/controller/HwDeviceController.java index 22454c0..35bf56e 100644 --- a/ruoyi-modules/hw-business/src/main/java/com/ruoyi/business/controller/HwDeviceController.java +++ b/ruoyi-modules/hw-business/src/main/java/com/ruoyi/business/controller/HwDeviceController.java @@ -5,6 +5,7 @@ import com.ruoyi.business.domain.HwDeviceMode; import com.ruoyi.business.domain.HwMonitorUnit; import com.ruoyi.business.domain.HwScene; import com.ruoyi.business.domain.VO.DeviceControlVo; +import com.ruoyi.business.domain.VO.HwDeviceImportVo; import com.ruoyi.business.service.IHwDeviceModeService; import com.ruoyi.business.service.IHwDeviceService; import com.ruoyi.business.service.IHwMonitorUnitService; @@ -19,11 +20,17 @@ import com.ruoyi.common.log.enums.BusinessType; import com.ruoyi.common.security.annotation.InnerAuth; import com.ruoyi.common.security.annotation.RequiresPermissions; import com.ruoyi.common.security.utils.SecurityUtils; +import com.ruoyi.system.api.domain.SysUser; +import org.apache.poi.ss.formula.functions.T; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * 设备信息Controller @@ -70,6 +77,48 @@ public class HwDeviceController extends BaseController { util.exportExcel(response, list, "设备信息数据"); } + + @Log(title = "设备信息", businessType = BusinessType.IMPORT) + @RequiresPermissions("business:device:import") + @PostMapping("/importData") + public AjaxResult importData(MultipartFile file, boolean updateSupport, Long sceneId) throws Exception { + ExcelUtil util = new ExcelUtil(HwDeviceImportVo.class); + List deviceList = util.importExcel(file.getInputStream()); + String message = hwDeviceService.importDevices(deviceList, updateSupport, sceneId); + return success(message); + } + + @RequiresPermissions("business:device:import") + @PostMapping("/importTemplate") + public void importTemplate(HttpServletResponse response, Long sceneId) throws IOException { + ExcelUtil util = new ExcelUtil(HwDeviceImportVo.class); + Map> classListMap = new HashMap>(); + + //根据场景ID获取最子级监控单元列表 + HwMonitorUnit queryMonitorUnit = new HwMonitorUnit(); + queryMonitorUnit.setSceneId(sceneId); + queryMonitorUnit.setMonitorUnitStatus(HwDictConstants.MONITOR_UNIT_STATUS_NORMAL); + List monitorList = hwMonitorUnitService.selectLimitSubMonitorUnit(queryMonitorUnit); + classListMap.put("HwMonitorUnit", monitorList); + + //根据场景ID获取没有删除的网关设备列表 + HwDevice queryDevice = new HwDevice(); + queryDevice.setSceneId(sceneId); + queryDevice.setDeviceType(HwDictConstants.DEVICE_TYPE_GATEWAY_DEVICE); + List gatewayDevices = hwDeviceService.selectHwDeviceList(queryDevice); + classListMap.put("HwDevice", gatewayDevices); + + //根据场景ID获取启用的设备模型列表 + HwDeviceMode queryDeviceMode = new HwDeviceMode(); + queryDeviceMode.setSceneId(sceneId); + queryDeviceMode.setDeviceModeStatus(HwDictConstants.DEVICE_MODE_STATUS_NORMAL); + List deviceModes = hwDeviceModeService.selectHwDeviceModeList(queryDeviceMode); + classListMap.put("HwDeviceMode", deviceModes); + + util.importTemplateExcel(response, "设备数据", classListMap); + } + + /** * 获取设备信息详细信息 */ diff --git a/ruoyi-modules/hw-business/src/main/java/com/ruoyi/business/domain/HwDevice.java b/ruoyi-modules/hw-business/src/main/java/com/ruoyi/business/domain/HwDevice.java index fda4dff..3e35eea 100644 --- a/ruoyi-modules/hw-business/src/main/java/com/ruoyi/business/domain/HwDevice.java +++ b/ruoyi-modules/hw-business/src/main/java/com/ruoyi/business/domain/HwDevice.java @@ -50,7 +50,7 @@ public class HwDevice extends BaseEntity { /** * 设备类型(1:网关设备,2:网关子设备,3:直连设备) */ - @Excel(name = "设备类型", readConverterExp = "1=网关设备,2网关子设备,3直连设备") + @Excel(name = "设备类型", readConverterExp = "1=网关设备,2=网关子设备,3=直连设备") private String deviceType; /** @@ -93,13 +93,13 @@ public class HwDevice extends BaseEntity { /** * 激活状态(1、激活,0、未激活) */ - @Excel(name = "激活状态", readConverterExp = "1=激活,0未激活") + @Excel(name = "激活状态", readConverterExp = "1=激活,0=未激活") private String activeStatus; /** * 设备状态(0、测试,1、发布,9、删除) */ - @Excel(name = "设备状态", readConverterExp = "0=测试,1发布,9删除") + @Excel(name = "设备状态", readConverterExp = "0=测试,1=发布,9=删除") private String deviceStatus; /** diff --git a/ruoyi-modules/hw-business/src/main/java/com/ruoyi/business/domain/VO/HwDeviceImportVo.java b/ruoyi-modules/hw-business/src/main/java/com/ruoyi/business/domain/VO/HwDeviceImportVo.java new file mode 100644 index 0000000..ff5057d --- /dev/null +++ b/ruoyi-modules/hw-business/src/main/java/com/ruoyi/business/domain/VO/HwDeviceImportVo.java @@ -0,0 +1,92 @@ +package com.ruoyi.business.domain.VO; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.common.core.annotation.Excel; +import com.ruoyi.common.core.web.domain.BaseEntity; +import lombok.Data; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import java.util.Date; + +/** + * 设备信息对象 HwDeviceImportVo设备导入对象Vo + * + * @author xins + * @date 2023-09-13 + */ +@Data +public class HwDeviceImportVo extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * 设备编号 + */ + @Excel(name = "设备编号") + private String deviceCode; + + /** + * 设备名称 + */ + @Excel(name = "设备名称") + private String deviceName; + + /** + * 所属场景,关联hw_scene表的scene_id字段 + */ + private Long sceneId; + + /** + * 所属监控单元,关联表hw_monitor_unit字段monitor_unit_id + */ + @Excel(name = "监控单元ID-名称", width = 25, + dbCombo = {"HwMonitorUnit", "getMonitorUnitId", "getMonitorUnitName"}) + private String monitorUnitInfo; + + /** + * 设备类型(1:网关设备,2:网关子设备,3:直连设备) + */ + @Excel(name = "设备类型", combo = {"网关设备", "网关子设备", "直连设备"}) + private String deviceType; + + /** + * 联网方式(1:Wi-Fi,2、蜂窝(2G/3G/4G/5G),3、以太网,4、其他) + */ +// @Excel(name = "联网方式(1=Wi-Fi,2=蜂窝(2G/3G/4G/5G),3=以太网,4=其他)") + private String networkingMode; + + /** + * 接入协议(1、MQTT) + */ +// @Excel(name = "接入协议", readConverterExp = "1=MQTT") + private Long accessProtocol; + + /** + * 数据格式(1、Json) + */ +// @Excel(name = "数据格式", readConverterExp = "1=Json") + private Long dataFormat; + + /** + * 关联设备,hw_device表中国的device_id + */ + @Excel(name = "关联网关设备ID-名称", width = 25, + dbCombo = {"HwDevice", "getDeviceId", "getDeviceName"}) + private String releatedDeviceInfo; + + /** + * 设备模型,关联表hw_device_mode的字段device_mode_id + */ + @Excel(name = "设备模型ID-名称", width = 25, + dbCombo = {"HwDeviceMode", "getDeviceModeId", "getDeviceModeName"}) + private String deviceModeInfo; + + /** + * 接入网关协议(1、Modbus) + * OPC-UA,Modbus,北向接入(阿里云、小度接入),南向接入,视频类接入,通道类接入,自定义接入 + */ +// @Excel(name = "接入网关协议", readConverterExp = "1=Modbus") + private Long accessGwProtocol; + + +} diff --git a/ruoyi-modules/hw-business/src/main/java/com/ruoyi/business/service/IHwDeviceService.java b/ruoyi-modules/hw-business/src/main/java/com/ruoyi/business/service/IHwDeviceService.java index 88461d4..a17b72a 100644 --- a/ruoyi-modules/hw-business/src/main/java/com/ruoyi/business/service/IHwDeviceService.java +++ b/ruoyi-modules/hw-business/src/main/java/com/ruoyi/business/service/IHwDeviceService.java @@ -119,6 +119,16 @@ public interface IHwDeviceService public List selectHwDeviceJoinList(HwDevice hwDevice); + /** + * 导入设备数据 + * + * @param deviceImportVoList 设备数据列表 + * @param isUpdateSupport 是否更新支持,如果已存在,则进行更新数据 + * @param sceneId 场景ID + * @return 结果 + */ + public String importDevices(List deviceImportVoList, Boolean isUpdateSupport, Long sceneId); + /** * @param: days * @description 计算前几天的设备在线数量 diff --git a/ruoyi-modules/hw-business/src/main/java/com/ruoyi/business/service/impl/HwDeviceServiceImpl.java b/ruoyi-modules/hw-business/src/main/java/com/ruoyi/business/service/impl/HwDeviceServiceImpl.java index 69a020a..578a91e 100644 --- a/ruoyi-modules/hw-business/src/main/java/com/ruoyi/business/service/impl/HwDeviceServiceImpl.java +++ b/ruoyi-modules/hw-business/src/main/java/com/ruoyi/business/service/impl/HwDeviceServiceImpl.java @@ -3,14 +3,8 @@ package com.ruoyi.business.service.impl; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; -import com.ruoyi.business.domain.HwDevice; -import com.ruoyi.business.domain.HwDeviceMode; -import com.ruoyi.business.domain.HwDeviceModeFunction; -import com.ruoyi.business.domain.HwScene; -import com.ruoyi.business.domain.VO.DeviceControlVo; -import com.ruoyi.business.domain.VO.DeviceModeVo; -import com.ruoyi.business.domain.VO.DevicesInfoVo; -import com.ruoyi.business.domain.VO.HwDeviceVo; +import com.ruoyi.business.domain.*; +import com.ruoyi.business.domain.VO.*; import com.ruoyi.business.mapper.*; import com.ruoyi.business.service.IHwDeviceService; import com.ruoyi.common.core.constant.Constants; @@ -19,6 +13,7 @@ import com.ruoyi.common.core.constant.SecurityConstants; import com.ruoyi.common.core.constant.TdEngineConstants; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.enums.DataTypeEnums; +import com.ruoyi.common.core.enums.DeviceTypeEnums; import com.ruoyi.common.core.exception.ServiceException; import com.ruoyi.common.core.utils.DateUtils; import com.ruoyi.common.core.utils.NumberUtils; @@ -51,6 +46,8 @@ public class HwDeviceServiceImpl implements IHwDeviceService { @Autowired private HwSceneMapper hwSceneMapper; @Autowired + private HwMonitorUnitMapper hwMonitorUnitMapper; + @Autowired private HwDeviceModeFunctionMapper hwDevieModeFunctionMapper; @Resource private RemoteTdEngineService remoteTdEngineService; @@ -513,6 +510,133 @@ public class HwDeviceServiceImpl implements IHwDeviceService { return hwDeviceMapper.selectHwDeviceJoinList(hwDevice); } + + /** + * 导入设备数据 + * + * @param deviceImportVoList 设备数据列表 + * @param isUpdateSupport 是否更新支持,如果已存在,则进行更新数据 + * @param sceneId 场景ID + * @return 结果 + */ + @Override + public String importDevices(List deviceImportVoList, Boolean isUpdateSupport, Long sceneId) { + if (StringUtils.isNull(deviceImportVoList) || deviceImportVoList.size() == 0) { + throw new ServiceException("导入标准数据不能为空!"); + } + int successNum = 0; + int failureNum = 0; + StringBuilder successMsg = new StringBuilder(); + StringBuilder failureMsg = new StringBuilder(); + String operName = SecurityUtils.getUsername(); + Long tenantId = SecurityUtils.getTenantId(); + String infoSeparator = "-"; + + //判断场景是否属于此租户 + HwScene scene = hwSceneMapper.selectHwSceneBySceneId(sceneId); + if (!scene.getTenantId().equals(tenantId)) { + throw new ServiceException("选择场景不属于此租户!"); + } + + for (HwDeviceImportVo deviceImportVo : deviceImportVoList) { + try { + String checkMsg = this.checkImportDeviceData(deviceImportVo, sceneId, infoSeparator); + if (StringUtils.isNotEmpty(checkMsg)) { + failureNum++; + failureMsg.append( + "
" + + failureNum + "、" + + checkMsg); + + } else { + String deviceCode = deviceImportVo.getDeviceCode(); + String deviceName = deviceImportVo.getDeviceName(); + String deviceType = deviceImportVo.getDeviceType(); + String monitorUnitInfo = deviceImportVo.getMonitorUnitInfo(); + String gateWayDeviceInfo = deviceImportVo.getReleatedDeviceInfo(); + String deviceModeInfo = deviceImportVo.getDeviceModeInfo(); + + Long monitorUnitId = Long.valueOf(monitorUnitInfo.substring(0, monitorUnitInfo.indexOf(infoSeparator))); + Long gatewayDeviceId = null; + Long deviceModeId = null; + + //根据设备类型名称获取code + String deviceTypeCode = DeviceTypeEnums.dataTypeCodeMap.get(deviceType); + + //验证是否存在这个设备 + HwDevice d = hwDeviceMapper.selectHwDeviceByDeviceCode(deviceImportVo.getDeviceCode()); + if (d == null) { + HwDevice device = new HwDevice(); + device.setDeviceCode(deviceCode); + device.setDeviceName(deviceName); + device.setDeviceType(deviceTypeCode); + device.setSceneId(sceneId); + device.setMonitorUnitId(monitorUnitId); + + switch (deviceTypeCode) { + case HwDictConstants.DEVICE_TYPE_GATEWAY_DEVICE: + device.setNetworkingMode(HwDictConstants.DEVICE_NETWORKING_MODE_WIFI); + device.setAccessProtocol(HwDictConstants.DEVICE_ACCESS_PROTOCOL_MQTT); + device.setDataFormat(HwDictConstants.DEVICE_DATA_FORMAT_JSON); + break; + case HwDictConstants.DEVICE_TYPE_GATEWAY_SUB_EQUIPMENT: + gatewayDeviceId = Long.valueOf(gateWayDeviceInfo.substring(0, gateWayDeviceInfo.indexOf(infoSeparator))); + deviceModeId = Long.valueOf(deviceModeInfo.substring(0, deviceModeInfo.indexOf(infoSeparator))); + device.setDeviceModeId(deviceModeId); + device.setReleatedDeviceId(gatewayDeviceId); + break; + case HwDictConstants.DEVICE_TYPE_DIRECT_CONNECT_DEVICE: + deviceModeId = Long.valueOf(deviceModeInfo.substring(0, deviceModeInfo.indexOf(infoSeparator))); + device.setNetworkingMode(HwDictConstants.DEVICE_NETWORKING_MODE_WIFI); + device.setAccessProtocol(HwDictConstants.DEVICE_ACCESS_PROTOCOL_MQTT); + device.setDataFormat(HwDictConstants.DEVICE_DATA_FORMAT_JSON); + device.setDeviceModeId(deviceModeId); + break; + } + + device.setTenantId(tenantId); + device.setCreateBy(operName); + device.setCreateTime(new Date()); + hwDeviceMapper.insertHwDevice(device); + successNum++; + successMsg.append( + "
" + successNum + "、 " + device.getDeviceName() + " 导入成功"); + } else if (isUpdateSupport) {//不支持更新 +// device.setDeviceId(d.getDeviceId()); +// device.setUpdateBy(operName); +// device.setUpdateTime(new Date()); +// hwDeviceMapper.updateHwDevice(device); + successNum++; + successMsg.append( + "
" + successNum + "、" + deviceImportVo.getDeviceName() + " 更新成功"); + } else { + failureNum++; + failureMsg.append( + "
" + + failureNum + + "、" + + deviceImportVo.getDeviceCode() + + "、" + + deviceImportVo.getDeviceName() + + " 已存在"); + } + } + } catch (Exception e) { + failureNum++; + String msg = "
" + failureNum + "、设备名称 " + deviceImportVo.getDeviceName() + " 导入失败:"; + failureMsg.append(msg + e.getMessage()); + } + } + if (failureNum > 0) { + failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:"); + throw new ServiceException(failureMsg.toString()); + } else { + successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:"); + } + return successMsg.toString(); + } + + /** * @param: days * @description 计算前几天的设备在线数量 @@ -889,4 +1013,73 @@ public class HwDeviceServiceImpl implements IHwDeviceService { } } + + /** + * @return String + * @param: deviceImportVo + * @param: sceneId + * @param: infoSeparator + * @description 在导入设备信息时校验数据正确性 + * @author xins + * @date 2023-11-10 10:50 + */ + private String checkImportDeviceData(HwDeviceImportVo deviceImportVo, Long sceneId, String infoSeparator) { + String deviceCode = deviceImportVo.getDeviceCode(); + String deviceName = deviceImportVo.getDeviceName(); + String deviceType = deviceImportVo.getDeviceType(); + String monitorUnitInfo = deviceImportVo.getMonitorUnitInfo(); + String gateWayDeviceInfo = deviceImportVo.getReleatedDeviceInfo(); + String deviceModeInfo = deviceImportVo.getDeviceModeInfo(); + + if (StringUtils.isEmpty(deviceCode) || StringUtils.isEmpty(deviceName) + || StringUtils.isEmpty(deviceType) || StringUtils.isEmpty(monitorUnitInfo)) { + return "设备编号、设备名称、监控单元和设备类型不能为空"; + } + + //判断是否是子级监控单元,并且属于此场景 + Long monitorUnitId = Long.valueOf(monitorUnitInfo.substring(0, monitorUnitInfo.indexOf(infoSeparator))); + HwMonitorUnit monitorUnit = hwMonitorUnitMapper.selectHwMonitorUnitByMonitorUnitId(monitorUnitId); + if (!monitorUnit.getSceneId().equals(sceneId)) { + return "设备名称 " + deviceImportVo.getDeviceName() + " 监控单元不属于所选择场景"; + } + if (monitorUnit.getParentId() != null && !monitorUnit.getParentId().equals(0L)) { + return "设备名称 " + deviceImportVo.getDeviceName() + " 此监控单元不是子级监控单元"; + } + + + //如果是直连设备或子设备,必选选择设备模型,判断设备模型是否存在,并且属于此场景 + if (deviceType.equals(DeviceTypeEnums.DIRECT_CONNECT_DEVICE.getDataType()) + || deviceType.equals(DeviceTypeEnums.SUB_DEVICE.getDataType())) { + if (StringUtils.isEmpty(deviceModeInfo)) { + return "设备名称 " + deviceImportVo.getDeviceName() + " 设备模型不能为空"; + } + Long deviceModeId = Long.valueOf(deviceModeInfo.substring(0, deviceModeInfo.indexOf(infoSeparator))); + HwDeviceMode deviceMode = hwDeviceModeMapper.selectHwDeviceModeByDeviceModeId(deviceModeId); + if (deviceMode == null || deviceMode.getDeviceModeStatus().equals(HwDictConstants.DEVICE_MODE_STATUS_DELETED)) { + return "设备名称 " + deviceImportVo.getDeviceName() + " 设备模型不存在"; + } + + if (!deviceMode.getSceneId().equals(sceneId)) { + return "设备名称 " + deviceImportVo.getDeviceName() + " 设备模型不属于所选择场景"; + } + } + + //如果是网关子设备,必须有关联网关设备,并且关联网关设备属于此场景 + if (deviceType.equals(DeviceTypeEnums.SUB_DEVICE.getDataType())) { + if (StringUtils.isEmpty(gateWayDeviceInfo)) { + return "设备名称 " + deviceImportVo.getDeviceName() + " 关联网关设备不能为空"; + } + Long gatewayDeviceId = Long.valueOf(gateWayDeviceInfo.substring(0, gateWayDeviceInfo.indexOf(infoSeparator))); + HwDevice gatewayDevice = hwDeviceMapper.selectHwDeviceByDeviceId(gatewayDeviceId); + if (gatewayDevice == null || gatewayDevice.getDeviceStatus().equals(HwDictConstants.DEVICE_STATUS_DELETE)) { + return "设备名称 " + deviceImportVo.getDeviceName() + " 关联网关设备不存在"; + } + if (!gatewayDevice.getSceneId().equals(sceneId)) { + return "设备名称 " + deviceImportVo.getDeviceName() + " 关联网关设备不属于所选择场景"; + } + } + + return ""; + } + } diff --git a/ruoyi-modules/hw-business/src/main/java/com/ruoyi/business/service/impl/HwMonitorUnitServiceImpl.java b/ruoyi-modules/hw-business/src/main/java/com/ruoyi/business/service/impl/HwMonitorUnitServiceImpl.java index d21c002..ed28dc4 100644 --- a/ruoyi-modules/hw-business/src/main/java/com/ruoyi/business/service/impl/HwMonitorUnitServiceImpl.java +++ b/ruoyi-modules/hw-business/src/main/java/com/ruoyi/business/service/impl/HwMonitorUnitServiceImpl.java @@ -138,20 +138,13 @@ public class HwMonitorUnitServiceImpl implements IHwMonitorUnitService { } -// @Override -// public List selectSenceAllNums() { -// List allNumsVos = hwMonitorUnitMapper.selectAllNums(); -// List allNums = hwMonitorUnitMapper.selectsum(); -// for (int i = 0; i < allNums.size(); i++) { -// for (int j = 0; j < allNums.size(); j++) { -// if (allNums.get(i).getSceneId().equals(allNumsVos.get(i).getSceneId())) { -// allNums.get(i).setSubSum(allNumsVos.get(i).getSubSum()); -// } -// } -// } -// return allNums; -// } - + /** + * @param: hwMonitorUnit + * @description 只查询最子级监控单元 + * @author xins + * @date 2023-11-10 9:07 + * @return List + */ @Override public List selectLimitSubMonitorUnit(HwMonitorUnit hwMonitorUnit) { @@ -197,7 +190,6 @@ public class HwMonitorUnitServiceImpl implements IHwMonitorUnitService { return hwMonitorUnitMapper.selectHwMonitorUnitByMonitorUnitId(monitorUnitId); } - //todo SysDeptServiceImpl类中的递归方法recursionFn(以实现) @Override public List selectTreeList(List hwMonitorUnits) { List returnList = new ArrayList<>(); diff --git a/ruoyi-modules/hw-business/src/main/resources/mapper/business/HwSceneMapper.xml b/ruoyi-modules/hw-business/src/main/resources/mapper/business/HwSceneMapper.xml index fc55935..bb40a02 100644 --- a/ruoyi-modules/hw-business/src/main/resources/mapper/business/HwSceneMapper.xml +++ b/ruoyi-modules/hw-business/src/main/resources/mapper/business/HwSceneMapper.xml @@ -92,7 +92,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" ${params.tenantDataScope} - order by scene_id desc + order by tenant_id,scene_id desc