ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/DictService.java
@@ -1,5 +1,7 @@ package org.dromara.common.core.service; import java.util.Map; /** * éç¨ åå ¸æå¡ * @@ -54,4 +56,12 @@ */ String getDictValue(String dictType, String dictLabel, String separator); /** * è·ååå ¸ä¸ææçåå ¸å¼ä¸æ ç¾ * * @param dictType åå ¸ç±»å * @return dictValue为keyï¼dictLabel为å¼ç»æçMap */ Map<String, String> getAllDictByDictType(String dictType); } ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/DropDownOptions.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,149 @@ package org.dromara.common.excel.core; import cn.hutool.core.util.StrUtil; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.dromara.common.core.exception.ServiceException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.function.Function; import java.util.stream.Collectors; /** * <h1>Excel䏿å¯é项</h1> * 注æï¼ä¸ºç¡®ä¿ä¸ææ¡è§£ææ£ç¡®ï¼ä¼ å¼å¡å¿ 使ç¨createOptionValue()å为å¼çæ¼æ¥ * * @author Emil.Zhang */ @Data @AllArgsConstructor @NoArgsConstructor @SuppressWarnings("unused") public class DropDownOptions { /** * ä¸çº§ä¸ææå¨åindexï¼ä»0å¼å§ç® */ private int index = 0; /** * äºçº§ä¸ææå¨çindexï¼ä»0å¼å§ç®ï¼ä¸è½ä¸ä¸çº§ç¸å */ private int nextIndex = 0; /** * ä¸çº§ä¸ææå å«çæ°æ® */ private List<String> options = new ArrayList<>(); /** * äºçº§ä¸ææå å«çæ°æ®Map * <p>以æ¯ä¸ä¸ªä¸çº§é项å¼ä¸ºKeyï¼æ¯ä¸ªä¸çº§é项对åºçäºçº§æ°æ®ä¸ºValue</p> */ private Map<String, List<String>> nextOptions = new HashMap<>(); /** * åé符 */ private static final String DELIMITER = "_"; /** * åå»ºåªæä¸çº§ç䏿é */ public DropDownOptions(int index, List<String> options) { this.index = index; this.options = options; } /** * <h2>å建æ¯ä¸ªé项å¯éå¼</h2> * <p>注æï¼ä¸è½ä»¥æ°åï¼ç¹æ®ç¬¦å·å¼å¤´ï¼é项ä¸ä¸å¯ä»¥å å«ä»»ä½è¿ç®ç¬¦å·</p> * * @param vars å¯éå¼å å å«çåæ° * @return åè§çå¯éå¼ */ public static String createOptionValue(Object... vars) { StringBuilder stringBuffer = new StringBuilder(); String regex = "^[\\S\\d\\u4e00-\\u9fa5]+$"; for (int i = 0; i < vars.length; i++) { String var = StrUtil.trimToEmpty(String.valueOf(vars[i])); if (!var.matches(regex)) { throw new ServiceException("éé¡¹æ°æ®ä¸ç¬¦åè§åï¼ä» å 许使ç¨ä¸è±æåç¬¦ä»¥åæ°å"); } stringBuffer.append(var); if (i < vars.length - 1) { // ç´è³æåä¸ä¸ªåï¼é½ä»¥_ä½ä¸ºåå²çº¿ stringBuffer.append(DELIMITER); } } if (stringBuffer.toString().matches("^\\d_*$")) { throw new ServiceException("ç¦æ¢ä»¥æ°åå¼å¤´"); } return stringBuffer.toString(); } /** * å°å¤çååççå¯éå¼è§£æä¸ºåå§çåæ° * * @param option ç»è¿å¤çåçåççå¯é项 * @return åå§çåæ° */ public static List<String> analyzeOptionValue(String option) { return StrUtil.split(option, DELIMITER, true, true); } /** * å建级è䏿é项 * * @param parentList ç¶å®ä½å¯é项åå§æ°æ® * @param parentIndex ç¶ä¸æéä½ç½® * @param sonList åå®ä½å¯é项åå§æ°æ® * @param sonIndex å䏿éä½ç½® * @param parentHowToGetIdFunction ç¶ç±»å¦ä½è·åå¯ä¸æ è¯ * @param sonHowToGetParentIdFunction åç±»å¦ä½è·åç¶ç±»çå¯ä¸æ è¯ * @param howToBuildEveryOption å¦ä½çæä¸æéå 容 * @return 级è䏿é项 */ public static <T> DropDownOptions buildLinkedOptions(List<T> parentList, int parentIndex, List<T> sonList, int sonIndex, Function<T, Number> parentHowToGetIdFunction, Function<T, Number> sonHowToGetParentIdFunction, Function<T, String> howToBuildEveryOption) { DropDownOptions parentLinkSonOptions = new DropDownOptions(); // å å建ç¶ç±»ç䏿 parentLinkSonOptions.setIndex(parentIndex); parentLinkSonOptions.setOptions( parentList.stream() .map(howToBuildEveryOption) .collect(Collectors.toList()) ); // æåç¶-å级è䏿 Map<String, List<String>> sonOptions = new HashMap<>(); // ç¶çº§ä¾æ®èªå·±çIDåç» Map<Number, List<T>> parentGroupByIdMap = parentList.stream().collect(Collectors.groupingBy(parentHowToGetIdFunction)); // éåæ¯ä¸ªåéï¼æåå°Mapä¸ sonList.forEach(everySon -> { if (parentGroupByIdMap.containsKey(sonHowToGetParentIdFunction.apply(everySon))) { // æ¾å°å¯¹åºçä¸çº§ T parentObj = parentGroupByIdMap.get(sonHowToGetParentIdFunction.apply(everySon)).get(0); // æååç§°åIDä½ä¸ºKey String key = howToBuildEveryOption.apply(parentObj); // Key对åºçValue List<String> thisParentSonOptionList; if (sonOptions.containsKey(key)) { thisParentSonOptionList = sonOptions.get(key); } else { thisParentSonOptionList = new ArrayList<>(); sonOptions.put(key, thisParentSonOptionList); } // å¾Value䏿·»å å½ååéé项 thisParentSonOptionList.add(howToBuildEveryOption.apply(everySon)); } }); parentLinkSonOptions.setNextIndex(sonIndex); parentLinkSonOptions.setNextOptions(sonOptions); return parentLinkSonOptions; } } ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/ExcelDownHandler.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,370 @@ package org.dromara.common.excel.core; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.EnumUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; 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 lombok.extern.slf4j.Slf4j; import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.util.CellRangeAddressList; import org.apache.poi.ss.util.WorkbookUtil; import org.apache.poi.xssf.usermodel.XSSFDataValidation; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.service.DictService; import org.dromara.common.core.utils.SpringUtils; import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.excel.annotation.ExcelDictFormat; import org.dromara.common.excel.annotation.ExcelEnumFormat; import java.lang.reflect.Field; import java.util.*; /** * <h1>Excelè¡¨æ ¼ä¸æéæä½</h1> * èèå°ä¸æéè¿å¤å¯è½å¯¼è´Excelæå¼ç¼æ ¢çé®é¢ï¼åªæ ¡éªå1000è¡ * <p> * å³åªæå1000è¡çæ°æ®å¯ä»¥ç¨ä¸ææ¡ï¼è¶ åºçèªè¡éè¿éå¶æ°æ®éçå½¢å¼ï¼ç¬¬äºæ¬¡è¾åº * * @author Emil.Zhang */ @Slf4j public class ExcelDownHandler implements SheetWriteHandler { /** * Excelè¡¨æ ¼ä¸çååè±æ * ä» ä¸ºäºè§£æåè±æï¼ç¦æ¢ä¿®æ¹ */ private static final String EXCEL_COLUMN_NAME = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; /** * åéæ°æ®Sheetå */ private static final String OPTIONS_SHEET_NAME = "options"; /** * èå¨éæ©æ°æ®Sheetåç头 */ private static final String LINKED_OPTIONS_SHEET_NAME = "linkedOptions"; /** * 䏿å¯é项 */ private final List<DropDownOptions> dropDownOptions; /** * å½ååéè¿åº¦ */ private int currentOptionsColumnIndex; /** * å½åèå¨éæ©è¿åº¦ */ private int currentLinkedOptionsSheetIndex; private final DictService dictService; public ExcelDownHandler(List<DropDownOptions> options) { this.dropDownOptions = options; this.currentOptionsColumnIndex = 0; this.currentLinkedOptionsSheetIndex = 0; this.dictService = SpringUtils.getBean(DictService.class); } /** * <h2>å¼å§åå»ºä¸ææ°æ®</h2> * 1.éè¿è§£æä¼ å ¥ç@ExcelPropertyå级æ¯å¦æ 注æ@DropDowné项 * 妿æä¸è®¾ç½®äºvalueå¼ï¼åå°å ¶ç´æ¥ç½®ä¸ºä¸æå¯é项 * <p> * 2.æè å¨è°ç¨ExcelUtilæ¶æå®äºå¯é项ï¼å°ä¾æ®ä¼ å ¥çå¯é项å䏿 * <p> * 3.äºè å¹¶åï¼æ³¨æè°ç¨æ¹å¼ */ @Override public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { Sheet sheet = writeSheetHolder.getSheet(); // å¼å§è®¾ç½®ä¸ææ¡ HSSFWorkbook DataValidationHelper helper = sheet.getDataValidationHelper(); Field[] fields = writeWorkbookHolder.getClazz().getDeclaredFields(); Workbook workbook = writeWorkbookHolder.getWorkbook(); int length = fields.length; for (int i = 0; i < length; i++) { // 循ç¯å®ä½ä¸çæ¯ä¸ªå±æ§ // å¯éçä¸æå¼ List<String> options = new ArrayList<>(); if (fields[i].isAnnotationPresent(ExcelDictFormat.class)) { // 妿æå®äº@ExcelDictFormatï¼å使ç¨åå ¸çé»è¾ ExcelDictFormat format = fields[i].getDeclaredAnnotation(ExcelDictFormat.class); String dictType = format.dictType(); String converterExp = format.readConverterExp(); if (StrUtil.isNotBlank(dictType)) { // å¦æä¼ éäºåå ¸åï¼å便®åå ¸å»ºç«ä¸æ Collection<String> values = Optional.ofNullable(dictService.getAllDictByDictType(dictType)) .orElseThrow(() -> new ServiceException(String.format("åå ¸ %s ä¸åå¨", dictType))) .values(); options = new ArrayList<>(values); } else if (StrUtil.isNotBlank(converterExp)) { // 妿æå®äºç¡®åçå¼ï¼åç´æ¥è§£æç¡®åçå¼ options = StrUtil.split(converterExp, format.separator(), true, true); } } else if (fields[i].isAnnotationPresent(ExcelEnumFormat.class)) { // å¦å妿æå®äº@ExcelEnumFormatï¼åä½¿ç¨æä¸¾çé»è¾ ExcelEnumFormat format = fields[i].getDeclaredAnnotation(ExcelEnumFormat.class); List<Object> values = EnumUtil.getFieldValues(format.enumClass(), format.textField()); options = StreamUtils.toList(values, String::valueOf); } if (ObjectUtil.isNotEmpty(options)) { // ä» å½ä¸æå¯é项ä¸ä¸ºç©ºæ¶æ§è¡ // è·åå䏿 ï¼é»è®¤ä¸ºå½åå¾ªç¯æ¬¡æ° int index = i; if (fields[i].isAnnotationPresent(ExcelProperty.class)) { // 妿æå®äºå䏿 ï¼ä»¥æå®ç为主 index = fields[i].getDeclaredAnnotation(ExcelProperty.class).index(); } if (options.size() > 20) { // è¿ééå¶å¦æå¯é项大äº20ï¼å使ç¨é¢å¤è¡¨å½¢å¼ dropDownWithSheet(helper, workbook, sheet, index, options); } else { // å¦å使ç¨åºå®å¼å½¢å¼ dropDownWithSimple(helper, sheet, index, options); } } } dropDownOptions.forEach(everyOptions -> { // å¦æä¼ éäºä¸ææ¡éæ©å¨åæ° if (!everyOptions.getNextOptions().isEmpty()) { // å½äºçº§é项ä¸ä¸ºç©ºæ¶ï¼ä½¿ç¨é¢å¤å ³è表çå½¢å¼ dropDownLinkedOptions(helper, workbook, sheet, everyOptions); } else if (everyOptions.getOptions().size() > 10) { // å½ä¸çº§éé¡¹åæ°ä¸ªæ°å¤§äº10ï¼ä½¿ç¨é¢å¤è¡¨çå½¢å¼ dropDownWithSheet(helper, workbook, sheet, everyOptions.getIndex(), everyOptions.getOptions()); } else if (everyOptions.getOptions().size() != 0) { // å½ä¸çº§é项个æ°ä¸ä¸ºç©ºï¼ä½¿ç¨é»è®¤å½¢å¼ dropDownWithSimple(helper, sheet, everyOptions.getIndex(), everyOptions.getOptions()); } }); } /** * <h2>ç®å䏿æ¡</h2> * ç´æ¥å°å¯éé¡¹æ¼æ¥ä¸ºæå®åçæ°æ®æ ¡éªå¼ * * @param celIndex åindex * @param value 䏿éå¯éå¼ */ private void dropDownWithSimple(DataValidationHelper helper, Sheet sheet, Integer celIndex, List<String> value) { if (ObjectUtil.isEmpty(value)) { return; } this.markOptionsToSheet(helper, sheet, celIndex, helper.createExplicitListConstraint(ArrayUtil.toArray(value, String.class))); } /** * <h2>é¢å¤è¡¨æ ¼å½¢å¼ç级è䏿æ¡</h2> * * @param options é¢å¤è¡¨æ ¼å½¢å¼åå¨ç䏿å¯é项 */ private void dropDownLinkedOptions(DataValidationHelper helper, Workbook workbook, Sheet sheet, DropDownOptions options) { String linkedOptionsSheetName = String.format("%s_%d", LINKED_OPTIONS_SHEET_NAME, currentLinkedOptionsSheetIndex); // å建èå¨ä¸ææ°æ®è¡¨ Sheet linkedOptionsDataSheet = workbook.createSheet(WorkbookUtil.createSafeSheetName(linkedOptionsSheetName)); // å°ä¸æè¡¨éè workbook.setSheetHidden(workbook.getSheetIndex(linkedOptionsDataSheet), true); // å®å横åçä¸çº§éé¡¹æ°æ®è¡¨ List<String> firstOptions = options.getOptions(); Map<String, List<String>> secoundOptionsMap = options.getNextOptions(); // å建å称管çå¨ Name name = workbook.createName(); // 设置å称管çå¨çå«å name.setNameName(linkedOptionsSheetName); // 以横å第ä¸è¡å建ä¸çº§ä¸ææ¼æ¥å¼ç¨ä½ç½® String firstOptionsFunction = String.format("%s!$%s$1:$%s$1", linkedOptionsSheetName, getExcelColumnName(0), getExcelColumnName(firstOptions.size()) ); // 设置å称管çå¨çå¼ç¨ä½ç½® name.setRefersToFormula(firstOptionsFunction); // è®¾ç½®æ°æ®æ ¡éªä¸ºåºå模å¼ï¼å¼ç¨çæ¯å称管çå¨ä¸çå«å this.markOptionsToSheet(helper, sheet, options.getIndex(), helper.createFormulaListConstraint(linkedOptionsSheetName)); for (int columIndex = 0; columIndex < firstOptions.size(); columIndex++) { // å æå主表ä¸ä¸çº§ä¸æçåå String firstOptionsColumnName = getExcelColumnName(columIndex); // 䏿¬¡å¾ªç¯æ¯æ¯ä¸ä¸ªä¸çº§é项 int finalI = columIndex; // æ¬æ¬¡å¾ªç¯çä¸çº§éé¡¹å¼ String thisFirstOptionsValue = firstOptions.get(columIndex); // å建第ä¸è¡çæ°æ® Optional.ofNullable(linkedOptionsDataSheet.getRow(0)) // 妿ä¸åå¨åå建第ä¸è¡ .orElseGet(() -> linkedOptionsDataSheet.createRow(finalI)) // 第ä¸è¡å½åå .createCell(columIndex) // 设置å¼ä¸ºå½åä¸çº§éé¡¹å¼ .setCellValue(thisFirstOptionsValue); // 第äºè¡å¼å§ï¼è®¾ç½®ç¬¬äºçº§å«é项忰 List<String> secondOptions = secoundOptionsMap.get(thisFirstOptionsValue); if (CollUtil.isEmpty(secondOptions)) { // å¿ é¡»ä¿è¯è³å°æä¸ä¸ªå ³èé项ï¼å¦åå°å¯¼è´Excelè§£æé误 secondOptions = Collections.singletonList("ææ _0"); } // 以该ä¸çº§é项å¼å建åå称管çå¨ Name sonName = workbook.createName(); // 设置å称管çå¨çå«å sonName.setNameName(thisFirstOptionsValue); // 以第äºè¡è¯¥åæ°æ®æ¼æ¥å¼ç¨ä½ç½® String sonFunction = String.format("%s!$%s$2:$%s$%d", linkedOptionsSheetName, firstOptionsColumnName, firstOptionsColumnName, secondOptions.size() + 1 ); // 设置å称管çå¨çå¼ç¨ä½ç½® sonName.setRefersToFormula(sonFunction); // æ°æ®éªè¯ä¸ºåºå模å¼ï¼å¼ç¨å°æ¯ä¸ä¸ªä¸»è¡¨ä¸çäºçº§é项ä½ç½® // å建å项çå称管çå¨ï¼åªæ¯ä¸ºäºä½¿å¾Excelå¯ä»¥è¯å«å°æ°æ® String mainSheetFirstOptionsColumnName = getExcelColumnName(options.getIndex()); for (int i = 0; i < 100; i++) { // 以ä¸çº§é项对åºç䏻使å¨ä½ç½®å建äºçº§ä¸æ String secondOptionsFunction = String.format("=INDIRECT(%s%d)", mainSheetFirstOptionsColumnName, i + 1); // äºçº§åªè½ä¸»è¡¨æ¯ä¸è¡çæ¯ä¸åæ·»å äºçº§æ ¡éª markLinkedOptionsToSheet(helper, sheet, i, options.getNextIndex(), helper.createFormulaListConstraint(secondOptionsFunction)); } for (int rowIndex = 0; rowIndex < secondOptions.size(); rowIndex++) { // ä»ç¬¬äºè¡å¼å§å¡«å äºçº§é项 int finalRowIndex = rowIndex + 1; int finalColumIndex = columIndex; Row row = Optional.ofNullable(linkedOptionsDataSheet.getRow(finalRowIndex)) // 没æåå建 .orElseGet(() -> linkedOptionsDataSheet.createRow(finalRowIndex)); Optional // 卿¬çº§ä¸çº§é项æå¨çå .ofNullable(row.getCell(finalColumIndex)) // ä¸åå¨åå建 .orElseGet(() -> row.createCell(finalColumIndex)) // 设置äºçº§éé¡¹å¼ .setCellValue(secondOptions.get(rowIndex)); } } currentLinkedOptionsSheetIndex++; } /** * <h2>é¢å¤è¡¨æ ¼å½¢å¼çæ®é䏿æ¡</h2> * ç±äºä¸ææ¡å¯é弿°éè¿å¤ï¼ä¸ºæåExcelæå¼æçï¼ä½¿ç¨é¢å¤è¡¨æ ¼å½¢å¼å䏿 * * @param celIndex 䏿é * @param value 䏿éå¯éå¼ */ private void dropDownWithSheet(DataValidationHelper helper, Workbook workbook, Sheet sheet, Integer celIndex, List<String> value) { // åå»ºä¸ææ°æ®è¡¨ Sheet simpleDataSheet = Optional.ofNullable(workbook.getSheet(WorkbookUtil.createSafeSheetName(OPTIONS_SHEET_NAME))) .orElseGet(() -> workbook.createSheet(WorkbookUtil.createSafeSheetName(OPTIONS_SHEET_NAME))); // å°ä¸æè¡¨éè workbook.setSheetHidden(workbook.getSheetIndex(simpleDataSheet), true); // å®å纵åçä¸çº§éé¡¹æ°æ®è¡¨ for (int i = 0; i < value.size(); i++) { int finalI = i; // è·åæ¯ä¸é项è¡ï¼å¦ææ²¡æåå建 Row row = Optional.ofNullable(simpleDataSheet.getRow(i)) .orElseGet(() -> simpleDataSheet.createRow(finalI)); // è·åæ¬çº§é项对åºçé项åï¼å¦ææ²¡æåå建 Cell cell = Optional.ofNullable(row.getCell(currentOptionsColumnIndex)) .orElseGet(() -> row.createCell(currentOptionsColumnIndex)); // è®¾ç½®å¼ cell.setCellValue(value.get(i)); } // å建å称管çå¨ Name name = workbook.createName(); // 设置å称管çå¨çå«å String nameName = String.format("%s_%d", OPTIONS_SHEET_NAME, celIndex); name.setNameName(nameName); // 以纵å第ä¸åå建ä¸çº§ä¸ææ¼æ¥å¼ç¨ä½ç½® String function = String.format("%s!$%s$1:$%s$%d", OPTIONS_SHEET_NAME, getExcelColumnName(currentOptionsColumnIndex), getExcelColumnName(currentOptionsColumnIndex), value.size()); // 设置å称管çå¨çå¼ç¨ä½ç½® name.setRefersToFormula(function); // è®¾ç½®æ°æ®æ ¡éªä¸ºåºå模å¼ï¼å¼ç¨çæ¯å称管çå¨ä¸çå«å this.markOptionsToSheet(helper, sheet, celIndex, helper.createFormulaListConstraint(nameName)); currentOptionsColumnIndex++; } /** * æè½½ä¸æçåï¼ä» éä¸çº§é项 */ private void markOptionsToSheet(DataValidationHelper helper, Sheet sheet, Integer celIndex, DataValidationConstraint constraint) { // è®¾ç½®æ°æ®æææ§å è½½å¨åªä¸ªåå æ ¼ä¸,åä¸ªåæ°å嫿¯ï¼èµ·å§è¡ãç»æ¢è¡ãèµ·å§åãç»æ¢å CellRangeAddressList addressList = new CellRangeAddressList(1, 1000, celIndex, celIndex); markDataValidationToSheet(helper, sheet, constraint, addressList); } /** * æè½½ä¸æçåï¼ä» éäºçº§é项 */ private void markLinkedOptionsToSheet(DataValidationHelper helper, Sheet sheet, Integer rowIndex, Integer celIndex, DataValidationConstraint constraint) { // è®¾ç½®æ°æ®æææ§å è½½å¨åªä¸ªåå æ ¼ä¸,åä¸ªåæ°å嫿¯ï¼èµ·å§è¡ãç»æ¢è¡ãèµ·å§åãç»æ¢å CellRangeAddressList addressList = new CellRangeAddressList(rowIndex, rowIndex, celIndex, celIndex); markDataValidationToSheet(helper, sheet, constraint, addressList); } /** * åºç¨æ°æ®æ ¡éª */ private void markDataValidationToSheet(DataValidationHelper helper, Sheet sheet, DataValidationConstraint constraint, CellRangeAddressList addressList) { // æ°æ®æææ§å¯¹è±¡ DataValidation dataValidation = helper.createValidation(constraint, addressList); // å¤çExcelå ¼å®¹æ§é®é¢ if (dataValidation instanceof XSSFDataValidation) { //æ°æ®æ ¡éª dataValidation.setSuppressDropDownArrow(true); //é误æç¤º dataValidation.setErrorStyle(DataValidation.ErrorStyle.STOP); dataValidation.createErrorBox("æç¤º", "æ¤å¼ä¸åå æ ¼å®ä¹æ°æ®ä¸ä¸è´"); dataValidation.setShowErrorBox(true); //éå®æç¤º dataValidation.createPromptBox("å¡«å说æï¼", "å¡«åå 容åªè½ä¸ºä¸æä¸æ°æ®ï¼å ¶ä»æ°æ®å°å¯¼è´å¯¼å ¥å¤±è´¥"); dataValidation.setShowPromptBox(true); sheet.addValidationData(dataValidation); } else { dataValidation.setSuppressDropDownArrow(false); } sheet.addValidationData(dataValidation); } /** * <h2>便®åindexè·åååè±æ</h2> * 便®åindex转æ¢ä¸ºExcelä¸çååè±æ * <p>ä¾å¦ç¬¬1åï¼index为0ï¼è§£æåºæ¥ä¸ºAå</p> * 第27åï¼index为26ï¼è§£æä¸ºAAå * <p>第28åï¼index为27ï¼è§£æä¸ºABå</p> * * @param columnIndex åindex * @return åindexæå¨å¾è±æå */ private String getExcelColumnName(int columnIndex) { // 26ä¸å¾ªç¯çæ¬¡æ° int columnCircleCount = columnIndex / 26; // 26ä¸å¾ªç¯å çä½ç½® int thisCircleColumnIndex = columnIndex % 26; // 26ä¸å¾ªç¯ç次æ°å¤§äº0ï¼åè§ä¸ºæ åè³å°ä¸¤ä½ String columnPrefix = columnCircleCount == 0 ? StrUtil.EMPTY : StrUtil.subWithLength(EXCEL_COLUMN_NAME, columnCircleCount - 1, 1); // ä»26ä¸å¾ªç¯å å对åºçæ ä½å String columnNext = StrUtil.subWithLength(EXCEL_COLUMN_NAME, thisCircleColumnIndex, 1); // å°äºè æ¼æ¥å³ä¸ºæç»çæ ä½å return columnPrefix + columnNext; } } ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/utils/ExcelUtil.java
@@ -10,21 +10,19 @@ import com.alibaba.excel.write.metadata.fill.FillConfig; import com.alibaba.excel.write.metadata.fill.FillWrapper; import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.file.FileUtils; import org.dromara.common.excel.convert.ExcelBigNumberConvert; import org.dromara.common.excel.core.CellMergeStrategy; import org.dromara.common.excel.core.DefaultExcelListener; import org.dromara.common.excel.core.ExcelListener; import org.dromara.common.excel.core.ExcelResult; import jakarta.servlet.ServletOutputStream; import jakarta.servlet.http.HttpServletResponse; import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.file.FileUtils; import org.dromara.common.excel.convert.ExcelBigNumberConvert; import org.dromara.common.excel.core.*; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.util.Collection; import java.util.List; import java.util.Map; @@ -87,7 +85,26 @@ try { resetResponse(sheetName, response); ServletOutputStream os = response.getOutputStream(); exportExcel(list, sheetName, clazz, false, os); exportExcel(list, sheetName, clazz, false, os, null); } catch (IOException e) { throw new RuntimeException("导åºExcelå¼å¸¸"); } } /** * 导åºexcel * * @param list å¯¼åºæ°æ®éå * @param sheetName å·¥ä½è¡¨çåç§° * @param clazz å®ä½ç±» * @param response ååºä½ * @param options 级è䏿é */ public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, HttpServletResponse response, List<DropDownOptions> options) { try { resetResponse(sheetName, response); ServletOutputStream os = response.getOutputStream(); exportExcel(list, sheetName, clazz, false, os, options); } catch (IOException e) { throw new RuntimeException("导åºExcelå¼å¸¸"); } @@ -106,7 +123,27 @@ try { resetResponse(sheetName, response); ServletOutputStream os = response.getOutputStream(); exportExcel(list, sheetName, clazz, merge, os); exportExcel(list, sheetName, clazz, merge, os, null); } catch (IOException e) { throw new RuntimeException("导åºExcelå¼å¸¸"); } } /** * 导åºexcel * * @param list å¯¼åºæ°æ®éå * @param sheetName å·¥ä½è¡¨çåç§° * @param clazz å®ä½ç±» * @param merge æ¯å¦åå¹¶åå æ ¼ * @param response ååºä½ * @param options 级è䏿é */ public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, boolean merge, HttpServletResponse response, List<DropDownOptions> options) { try { resetResponse(sheetName, response); ServletOutputStream os = response.getOutputStream(); exportExcel(list, sheetName, clazz, merge, os, options); } catch (IOException e) { throw new RuntimeException("导åºExcelå¼å¸¸"); } @@ -121,7 +158,20 @@ * @param os è¾åºæµ */ public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, OutputStream os) { exportExcel(list, sheetName, clazz, false, os); exportExcel(list, sheetName, clazz, false, os, null); } /** * 导åºexcel * * @param list å¯¼åºæ°æ®éå * @param sheetName å·¥ä½è¡¨çåç§° * @param clazz å®ä½ç±» * @param os è¾åºæµ * @param options 级è䏿éå 容 */ public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, OutputStream os, List<DropDownOptions> options) { exportExcel(list, sheetName, clazz, false, os, options); } /** @@ -133,7 +183,8 @@ * @param merge æ¯å¦åå¹¶åå æ ¼ * @param os è¾åºæµ */ public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, boolean merge, OutputStream os) { public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, boolean merge, OutputStream os, List<DropDownOptions> options) { ExcelWriterSheetBuilder builder = EasyExcel.write(os, clazz) .autoCloseStream(false) // èªå¨éé @@ -144,6 +195,10 @@ if (merge) { // åå¹¶å¤çå¨ builder.registerWriteHandler(new CellMergeStrategy(list, true)); } if (CollUtil.isNotEmpty(options)) { // æ·»å ä¸ææ¡æä½ builder.registerWriteHandler(new ExcelDownHandler(options)); } builder.doWrite(list); } @@ -253,7 +308,7 @@ /** * éç½®ååºä½ */ private static void resetResponse(String sheetName, HttpServletResponse response) { private static void resetResponse(String sheetName, HttpServletResponse response) throws UnsupportedEncodingException { String filename = encodingFilename(sheetName); FileUtils.setAttachmentResponseHeader(response, filename); response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8"); @@ -275,7 +330,7 @@ if (StringUtils.containsAny(propertyValue, separator)) { for (String value : propertyValue.split(separator)) { if (itemArray[0].equals(value)) { propertyString.append(itemArray[1]).append(separator); propertyString.append(itemArray[1] + separator); break; } } @@ -304,7 +359,7 @@ if (StringUtils.containsAny(propertyValue, separator)) { for (String value : propertyValue.split(separator)) { if (itemArray[1].equals(value)) { propertyString.append(itemArray[0]).append(separator); propertyString.append(itemArray[0] + separator); break; } } ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/TestExcelController.java
@@ -1,14 +1,19 @@ package org.dromara.demo.controller; import cn.hutool.core.collection.CollUtil; import org.dromara.common.excel.utils.ExcelUtil; import jakarta.servlet.http.HttpServletResponse; import lombok.AllArgsConstructor; import lombok.Data; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import lombok.RequiredArgsConstructor; import org.dromara.common.excel.core.ExcelResult; import org.dromara.common.excel.utils.ExcelUtil; import org.dromara.demo.domain.vo.ExportDemoVo; import org.dromara.demo.listener.ExportDemoListener; import org.dromara.demo.service.IExportExcelService; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import jakarta.servlet.http.HttpServletResponse; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -19,9 +24,12 @@ * * @author Lion Li */ @RequiredArgsConstructor @RestController @RequestMapping("/demo/excel") public class TestExcelController { private final IExportExcelService exportExcelService; /** * ååè¡¨å¤æ°æ® @@ -76,6 +84,26 @@ ExcelUtil.exportTemplateMultiList(multiListMap, "å¤å表.xlsx", "excel/å¤å表.xlsx", response); } /** * 导åºä¸ææ¡ * * @param response / */ @GetMapping("/exportWithOptions") public void exportWithOptions(HttpServletResponse response) { exportExcelService.exportWithOptions(response); } /** * å¯¼å ¥è¡¨æ ¼ */ @PostMapping(value = "/importWithOptions", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public List<ExportDemoVo> importWithOptions(@RequestPart("file") MultipartFile file) throws Exception { // å¤çè§£æç»æ ExcelResult<ExportDemoVo> excelResult = ExcelUtil.importExcel(file.getInputStream(), ExportDemoVo.class, new ExportDemoListener()); return excelResult.getList(); } @Data @AllArgsConstructor static class TestObj1 { ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/ExportDemoVo.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,118 @@ package org.dromara.demo.domain.vo; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.dromara.common.core.enums.UserStatus; import org.dromara.common.core.validate.AddGroup; import org.dromara.common.core.validate.EditGroup; import org.dromara.common.excel.annotation.ExcelDictFormat; import org.dromara.common.excel.annotation.ExcelEnumFormat; import org.dromara.common.excel.convert.ExcelDictConvert; import org.dromara.common.excel.convert.ExcelEnumConvert; /** * 带æä¸æéçExcelå¯¼åº * * @author Emil.Zhang */ @Data @ExcelIgnoreUnannotated @AllArgsConstructor @NoArgsConstructor public class ExportDemoVo { private static final long serialVersionUID = 1L; /** * ç¨æ·æµç§° */ @ExcelProperty(value = "ç¨æ·å", index = 0) @NotEmpty(message = "ç¨æ·åä¸è½ä¸ºç©º", groups = AddGroup.class) private String nickName; /** * ç¨æ·ç±»å * </p> * 使ç¨ExcelEnumFormat注解éè¦è¿è¡ä¸æéçé¨å */ @ExcelProperty(value = "ç¨æ·ç±»å", index = 1, converter = ExcelEnumConvert.class) @ExcelEnumFormat(enumClass = UserStatus.class, textField = "info") @NotEmpty(message = "ç¨æ·ç±»åä¸è½ä¸ºç©º", groups = AddGroup.class) private String userStatus; /** * æ§å« * <p> * 使ç¨ExcelDictFormat注解éè¦è¿è¡ä¸æéçé¨å */ @ExcelProperty(value = "æ§å«", index = 2, converter = ExcelDictConvert.class) @ExcelDictFormat(dictType = "sys_user_sex") @NotEmpty(message = "æ§å«ä¸è½ä¸ºç©º", groups = AddGroup.class) private String gender; /** * ææºå· */ @ExcelProperty(value = "ææºå·", index = 3) @NotEmpty(message = "ææºå·ä¸è½ä¸ºç©º", groups = AddGroup.class) private String phoneNumber; /** */ @ExcelProperty(value = "Email", index = 4) @NotEmpty(message = "Emailä¸è½ä¸ºç©º", groups = AddGroup.class) private String email; /** * ç * <p> * 级è䏿ï¼ä» 夿æ¯å¦éäº */ @ExcelProperty(value = "ç", index = 5) @NotNull(message = "çä¸è½ä¸ºç©º", groups = AddGroup.class) private String province; /** * æ°æ®åºä¸ççID * </p> * å¤ç宿¯åå夿æ¯å¦å¸æ£ç¡®çå¼ */ @NotNull(message = "è¯·å¿æå¨è¾å ¥", groups = EditGroup.class) private Integer provinceId; /** * å¸ * <p> * 级è䏿 */ @ExcelProperty(value = "å¸", index = 6) @NotNull(message = "å¸ä¸è½ä¸ºç©º", groups = AddGroup.class) private String city; /** * æ°æ®åºä¸çå¸ID */ @NotNull(message = "è¯·å¿æå¨è¾å ¥", groups = EditGroup.class) private Integer cityId; /** * å¿ * <p> * 级è䏿 */ @ExcelProperty(value = "å¿", index = 7) @NotNull(message = "å¿ä¸è½ä¸ºç©º", groups = AddGroup.class) private String area; /** * æ°æ®åºä¸çå¿ID */ @NotNull(message = "è¯·å¿æå¨è¾å ¥", groups = EditGroup.class) private Integer areaId; } ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/listener/ExportDemoListener.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,68 @@ package org.dromara.demo.listener; import cn.hutool.core.util.NumberUtil; import com.alibaba.excel.context.AnalysisContext; import org.dromara.common.core.utils.ValidatorUtils; import org.dromara.common.core.validate.AddGroup; import org.dromara.common.core.validate.EditGroup; import org.dromara.common.excel.core.DefaultExcelListener; import org.dromara.common.excel.core.DropDownOptions; import org.dromara.demo.domain.vo.ExportDemoVo; import java.util.List; /** * Excel另䏿æ¡çè§£æå¤çå¨ * * @author Emil.Zhang */ public class ExportDemoListener extends DefaultExcelListener<ExportDemoVo> { public ExportDemoListener() { // æ¾ç¤ºä½¿ç¨æé 彿°ï¼å¦åå°å¯¼è´ç©ºæé super(true); } @Override public void invoke(ExportDemoVo data, AnalysisContext context) { // å æ ¡éªå¿ å¡« ValidatorUtils.validate(data, AddGroup.class); // å¤ç级è䏿çé¨å String province = data.getProvince(); String city = data.getCity(); String area = data.getArea(); // æ¬è¡ç¨æ·éæ©çç List<String> thisRowSelectedProvinceOption = DropDownOptions.analyzeOptionValue(province); if (thisRowSelectedProvinceOption.size() == 2) { String provinceIdStr = thisRowSelectedProvinceOption.get(1); if (NumberUtil.isNumber(provinceIdStr)) { // ä¸¥æ ¼è¦æ±æ°æ®çè¯å¯ä»¥å¨è¿éå䏿°æ®åºç¸å ³ç夿 // ä¾å¦å¤æçä¿¡æ¯æ¯å¦å¨æ°æ®åºä¸åå¨çï¼å»ºè®®ç»åRedisCacheåç¼å10sï¼åå°æ°æ®åºè°ç¨ data.setProvinceId(Integer.parseInt(provinceIdStr)); } } // æ¬è¡ç¨æ·éæ©çå¸ List<String> thisRowSelectedCityOption = DropDownOptions.analyzeOptionValue(city); if (thisRowSelectedCityOption.size() == 2) { String cityIdStr = thisRowSelectedCityOption.get(1); if (NumberUtil.isNumber(cityIdStr)) { data.setCityId(Integer.parseInt(cityIdStr)); } } // æ¬è¡ç¨æ·éæ©çå¿ List<String> thisRowSelectedAreaOption = DropDownOptions.analyzeOptionValue(area); if (thisRowSelectedAreaOption.size() == 2) { String areaIdStr = thisRowSelectedAreaOption.get(1); if (NumberUtil.isNumber(areaIdStr)) { data.setAreaId(Integer.parseInt(areaIdStr)); } } // å¤ç宿¯ä»¥å夿æ¯å¦ç¬¦åè§å ValidatorUtils.validate(data, EditGroup.class); // æ·»å å°å¤çç»æä¸ getExcelResult().getList().add(data); } } ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/IExportExcelService.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,18 @@ package org.dromara.demo.service; import jakarta.servlet.http.HttpServletResponse; /** * 导åºä¸ææ¡Excelç¤ºä¾ * * @author Emil.Zhang */ public interface IExportExcelService { /** * 导åºä¸ææ¡ * * @param response / */ void exportWithOptions(HttpServletResponse response); } ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/ExportExcelServiceImpl.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,222 @@ package org.dromara.demo.service.impl; import cn.hutool.core.util.StrUtil; import jakarta.servlet.http.HttpServletResponse; import lombok.Data; import lombok.RequiredArgsConstructor; import org.dromara.common.core.enums.UserStatus; import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.excel.core.DropDownOptions; import org.dromara.common.excel.utils.ExcelUtil; import org.dromara.demo.domain.vo.ExportDemoVo; import org.dromara.demo.service.IExportExcelService; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.stream.Collectors; /** * 导åºä¸ææ¡Excelç¤ºä¾ * * @author Emil.Zhang */ @Service @RequiredArgsConstructor public class ExportExcelServiceImpl implements IExportExcelService { @Override public void exportWithOptions(HttpServletResponse response) { // åå»ºè¡¨æ ¼æ°æ®ï¼ä¸å¡ä¸ä¸è¬éè¿æ°æ®åºæ¥è¯¢ List<ExportDemoVo> excelDataList = new ArrayList<>(); for (int i = 0; i < 3; i++) { // æ¨¡ææ°æ®åºä¸ç䏿¡æ°æ® ExportDemoVo everyRowData = new ExportDemoVo(); everyRowData.setNickName("ç¨æ·-" + i); everyRowData.setUserStatus(UserStatus.OK.getCode()); everyRowData.setGender("1"); everyRowData.setPhoneNumber(String.format("175%08d", i)); everyRowData.setEmail(String.format("175%08d", i) + "@163.com"); everyRowData.setProvinceId(i); everyRowData.setCityId(i); everyRowData.setAreaId(i); excelDataList.add(everyRowData); } // éè¿@ExcelIgnoreUnannotatedé å@ExcelPropertyåçæ¾ç¤ºéè¦çå // å¹¶éè¿@DropDown注解æå®ä¸æå¼ï¼æè éè¿å建ExcelOptionsæ¥æå®ä¸ææ¡ // 使ç¨ExcelOptionsæ¶å»ºè®®æå®åindexï¼é²æ¢åºç°ä¸æåè§£æä¸å¯¹é½ // é¦å 仿°æ®åºä¸æ¥è¯¢ä¸ææ¡å çå¯é项 // è¿éæ¨¡ææ¥è¯¢ç»æ List<DemoCityData> provinceList = getProvinceList(), cityList = getCityList(provinceList), areaList = getAreaList(cityList); int provinceIndex = 5, cityIndex = 6, areaIndex = 7; DropDownOptions provinceToCity = DropDownOptions.buildLinkedOptions( provinceList, provinceIndex, cityList, cityIndex, DemoCityData::getId, DemoCityData::getPid, everyOptions -> DropDownOptions.createOptionValue( everyOptions.getName(), everyOptions.getId() ) ); DropDownOptions cityToArea = DropDownOptions.buildLinkedOptions( cityList, cityIndex, areaList, areaIndex, DemoCityData::getId, DemoCityData::getPid, everyOptions -> DropDownOptions.createOptionValue( everyOptions.getName(), everyOptions.getId() ) ); // æææç䏿æ¡åå¨ List<DropDownOptions> options = new ArrayList<>(); options.add(provinceToCity); options.add(cityToArea); // å°æ¤ä¸ºæ¢ææç䏿æ¡å¯éé¡¹å·²å ¨é¨é ç½®å®æ¯ // æ¥ä¸æ¥éè¦å°Excelä¸çå±ç¤ºæ°æ®è½¬æ¢ä¸ºå¯¹åºç䏿é List<ExportDemoVo> outList = StreamUtils.toList(excelDataList, everyRowData -> { // åªéè¦å¤ç没æä½¿ç¨@ExcelDictFormat注解çä¸ææ¡ // ä¸è¬æ¥è¯´ï¼å¯ä»¥ç´æ¥å¨æ°æ®åºæ¥è¯¢å³æ¥è¯¢åºçå¸å¿ä¿¡æ¯ï¼è¿ééè¿æ¨¡ææä½èµå¼ everyRowData.setProvince(buildOptions(provinceList, everyRowData.getProvinceId())); everyRowData.setCity(buildOptions(cityList, everyRowData.getCityId())); everyRowData.setArea(buildOptions(areaList, everyRowData.getAreaId())); return everyRowData; }); ExcelUtil.exportExcel(outList, "䏿æ¡ç¤ºä¾", ExportDemoVo.class, response, options); } private String buildOptions(List<DemoCityData> cityDataList, Integer id) { Map<Integer, List<DemoCityData>> groupByIdMap = cityDataList.stream().collect(Collectors.groupingBy(DemoCityData::getId)); if (groupByIdMap.containsKey(id)) { DemoCityData demoCityData = groupByIdMap.get(id).get(0); return DropDownOptions.createOptionValue(demoCityData.getName(), demoCityData.getId()); } else { return StrUtil.EMPTY; } } /** * æ¨¡ææ¥è¯¢æ°æ®åºæä½ * * @return / */ private List<DemoCityData> getProvinceList() { List<DemoCityData> provinceList = new ArrayList<>(); // å®é ä¸å¡ä¸ä¸è¬éç¨æ°æ®åºè¯»åçå½¢å¼ï¼è¿éç´æ¥æ¼æ¥å建 provinceList.add(new DemoCityData(0, null, "å®å¾½ç")); provinceList.add(new DemoCityData(1, null, "æ±èç")); return provinceList; } /** * æ¨¡ææ¥æ¾æ°æ®åºæä½ï¼éè¦è¿å¸¦æ¥è¯¢åºççæ°æ® * * @param provinceList 模æçç¶çæ°æ® * @return / */ private List<DemoCityData> getCityList(List<DemoCityData> provinceList) { List<DemoCityData> cityList = new ArrayList<>(); // å®é ä¸å¡ä¸ä¸è¬éç¨æ°æ®åºè¯»åçå½¢å¼ï¼è¿éç´æ¥æ¼æ¥å建 cityList.add(new DemoCityData(0, 0, "åè¥å¸")); cityList.add(new DemoCityData(1, 0, "èæ¹å¸")); cityList.add(new DemoCityData(2, 1, "å京å¸")); cityList.add(new DemoCityData(3, 1, "æ é¡å¸")); cityList.add(new DemoCityData(4, 1, "å¾å·å¸")); selectParentData(provinceList, cityList); return cityList; } /** * æ¨¡ææ¥æ¾æ°æ®åºæä½ï¼éè¦è¿å¸¦æ¥è¯¢åºå¸çæ°æ® * * @param cityList 模æçç¶å¸æ°æ® * @return / */ private List<DemoCityData> getAreaList(List<DemoCityData> cityList) { List<DemoCityData> areaList = new ArrayList<>(); // å®é ä¸å¡ä¸ä¸è¬éç¨æ°æ®åºè¯»åçå½¢å¼ï¼è¿éç´æ¥æ¼æ¥å建 areaList.add(new DemoCityData(0, 0, "ç¶æµ·åº")); areaList.add(new DemoCityData(1, 0, "åºæ±åº")); areaList.add(new DemoCityData(2, 1, "åå®å¿")); areaList.add(new DemoCityData(3, 1, "éæ¹åº")); areaList.add(new DemoCityData(4, 2, "çæ¦åº")); areaList.add(new DemoCityData(5, 2, "秦淮åº")); areaList.add(new DemoCityData(6, 3, "å®å ´å¸")); areaList.add(new DemoCityData(7, 3, "æ°å´åº")); areaList.add(new DemoCityData(8, 4, "鼿¥¼åº")); areaList.add(new DemoCityData(9, 4, "丰å¿")); selectParentData(cityList, areaList); return areaList; } /** * æ¨¡ææ°æ®åºçæ¥è¯¢ç¶æ°æ®æä½ * * @param parentList / * @param sonList / */ private void selectParentData(List<DemoCityData> parentList, List<DemoCityData> sonList) { Map<Integer, List<DemoCityData>> parentGroupByIdMap = parentList.stream().collect(Collectors.groupingBy(DemoCityData::getId)); sonList.forEach(everySon -> { if (parentGroupByIdMap.containsKey(everySon.getPid())) { everySon.setPData(parentGroupByIdMap.get(everySon.getPid()).get(0)); } }); } /** * 模æçæ°æ®åºçå¸å¿ */ @Data private static class DemoCityData { /** * æ°æ®åºidåæ®µ */ private Integer id; /** * æ°æ®åºpidåæ®µ */ private Integer pid; /** * æ°æ®åºnameåæ®µ */ private String name; /** * MyBatisPlusè¿å¸¦æ¥è¯¢ç¶æ°æ® */ private DemoCityData pData; public DemoCityData(Integer id, Integer pid, String name) { this.id = id; this.pid = pid; this.name = name; } } } ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDictTypeServiceImpl.java
@@ -265,4 +265,10 @@ } } @Override public Map<String, String> getAllDictByDictType(String dictType) { List<SysDictDataVo> list = selectDictDataByType(dictType); return StreamUtils.toMap(list, SysDictDataVo::getDictValue, SysDictDataVo::getDictLabel); } }