8 files modified
2 files added
| | |
| | | |
| | | /** |
| | | * 导出模板 |
| | | * <p> |
| | | * 为区域列添加下拉选择功能,限制用户只能选择预设的区域名称 |
| | | * </p> |
| | | * |
| | | * @param response HTTP响应对象 |
| | | * @throws IOException 导出异常 |
| | | */ |
| | | @GetMapping("export-template") |
| | | @ApiOperationSupport(order = 16) |
| | |
| | | */ |
| | | package org.sxkj.system.controller; |
| | | |
| | | import com.alibaba.excel.EasyExcel; |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | |
| | | import org.springblade.core.tool.utils.BeanUtil; |
| | | import org.springblade.core.tool.utils.DateUtil; |
| | | import org.sxkj.system.entity.Region; |
| | | import org.sxkj.system.excel.DeptImportExcel; |
| | | import org.sxkj.system.excel.RegionExcel; |
| | | import org.sxkj.system.excel.RegionImportExcel; |
| | | import org.sxkj.system.excel.RegionImporter; |
| | | import org.sxkj.system.param.RegionAddParam; |
| | | import org.sxkj.system.param.RegionPageParam; |
| | | import org.sxkj.system.service.IRegionService; |
| | | import org.sxkj.system.util.excel.RegionSheetWriteHandler; |
| | | import org.sxkj.system.vo.RegionVO; |
| | | import org.sxkj.system.vo.TreeVo; |
| | | import org.sxkj.system.wrapper.RegionWrapper; |
| | |
| | | |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import javax.validation.Valid; |
| | | import java.io.IOException; |
| | | import java.io.UnsupportedEncodingException; |
| | | import java.net.URLEncoder; |
| | | import java.nio.charset.StandardCharsets; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | |
| | | @ApiOperation(value = "导入行政区划", notes = "传入excel") |
| | | public R importRegion(MultipartFile file, Integer isCovered) { |
| | | RegionImporter regionImporter = new RegionImporter(regionService, isCovered == 1); |
| | | ExcelUtil.save(file, regionImporter, RegionExcel.class); |
| | | ExcelUtil.save(file, regionImporter, RegionImportExcel.class); |
| | | return R.success("操作成功"); |
| | | } |
| | | |
| | |
| | | /** |
| | | * 导出模板 |
| | | */ |
| | | // @GetMapping("export-template") |
| | | // @ApiOperationSupport(order = 12) |
| | | // @ApiOperation(value = "导出模板") |
| | | // public void exportUser(HttpServletResponse response) { |
| | | // List<RegionImportExcel> list = new ArrayList<>(); |
| | | // ExcelUtil.export(response, "行政区划模板", "行政区划表", list, RegionImportExcel.class); |
| | | // } |
| | | |
| | | @GetMapping("export-template") |
| | | @ApiOperationSupport(order = 12) |
| | | @ApiOperationSupport(order = 16) |
| | | @ApiOperation(value = "导出模板") |
| | | public void exportUser(HttpServletResponse response) { |
| | | List<RegionExcel> list = new ArrayList<>(); |
| | | ExcelUtil.export(response, "行政区划模板", "行政区划表", list, RegionExcel.class); |
| | | public void exportUser(HttpServletResponse response) throws IOException { |
| | | // 设置响应头 |
| | | response.setContentType("application/vnd.ms-excel"); |
| | | response.setCharacterEncoding(StandardCharsets.UTF_8.name()); |
| | | String fileName = URLEncoder.encode("行政区划模板", StandardCharsets.UTF_8.name()); |
| | | response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx"); |
| | | |
| | | // 准备空数据列表 |
| | | List<RegionImportExcel> list = new ArrayList<>(); |
| | | |
| | | // 使用EasyExcel导出,并注册RegionSheetWriteHandler |
| | | EasyExcel.write(response.getOutputStream(), RegionImportExcel.class) |
| | | .registerWriteHandler(new RegionSheetWriteHandler()) |
| | | .sheet("行政区划表") |
| | | .doWrite(list); |
| | | } |
| | | |
| | | /** |
| | |
| | | @ColumnWidth(20) |
| | | private String deptName; |
| | | |
| | | @ExcelProperty(value = "所属区划", converter = ExcelDictConverter.class) |
| | | @ExcelProperty(value = "所属区划编码") |
| | | @ColumnWidth(20) |
| | | @ExcelDictItemLabel(type = "regionName") |
| | | @ExcelDictItem(type = "regionName") |
| | | private String areaCode; |
| | | |
| | | @ExcelProperty("机构描述") |
| New file |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill 庄骞 (smallchill@163.com) |
| | | */ |
| | | package org.sxkj.system.excel; |
| | | |
| | | import com.alibaba.excel.annotation.ExcelProperty; |
| | | import com.alibaba.excel.annotation.write.style.ColumnWidth; |
| | | import com.alibaba.excel.annotation.write.style.ContentRowHeight; |
| | | import com.alibaba.excel.annotation.write.style.HeadRowHeight; |
| | | import lombok.Data; |
| | | import org.sxkj.system.util.excel.ExcelDictConverter; |
| | | import org.sxkj.system.util.excel.ExcelDictItem; |
| | | import org.sxkj.system.util.excel.ExcelDictItemLabel; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * RegionExcel |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @Data |
| | | @ColumnWidth(16) |
| | | @HeadRowHeight(20) |
| | | @ContentRowHeight(18) |
| | | public class RegionImportExcel implements Serializable { |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | @ColumnWidth(20) |
| | | @ExcelProperty("区划编号") |
| | | private String code; |
| | | |
| | | @ColumnWidth(20) |
| | | @ExcelProperty("区划名称") |
| | | private String name; |
| | | |
| | | @ColumnWidth(20) |
| | | @ExcelProperty("上级区划编码") |
| | | private String parentCode; |
| | | |
| | | @ColumnWidth(20) |
| | | @ExcelProperty(value = "层级", converter = ExcelDictConverter.class) |
| | | @ExcelDictItemLabel(type = "regionLevel") |
| | | @ExcelDictItem(type = "regionLevel") |
| | | private String regionLevel; |
| | | |
| | | @ColumnWidth(20) |
| | | @ExcelProperty("排序") |
| | | private Integer sort; |
| | | |
| | | @ColumnWidth(20) |
| | | @ExcelProperty(value = "机构状态", converter = ExcelDictConverter.class) |
| | | @ExcelDictItemLabel(type = "institutionStatus") |
| | | @ExcelDictItem(type = "institutionStatus") |
| | | private String status; |
| | | |
| | | } |
| | |
| | | * @author Chill |
| | | */ |
| | | @RequiredArgsConstructor |
| | | public class RegionImporter implements ExcelImporter<RegionExcel> { |
| | | public class RegionImporter implements ExcelImporter<RegionImportExcel> { |
| | | |
| | | private final IRegionService service; |
| | | private final Boolean isCovered; |
| | | |
| | | @Override |
| | | public void save(List<RegionExcel> data) { |
| | | public void save(List<RegionImportExcel> data) { |
| | | service.importRegion(data, isCovered); |
| | | } |
| | | } |
| | |
| | | and code like concat(concat('%', #{param2.cityCode}),'%') |
| | | </if> |
| | | <if test="param2.districtName!=null and param2.districtName!=''"> |
| | | and district_name like concat(concat('%', #{param2.districtName}),'%') |
| | | and name like concat(concat('%', #{param2.districtName}),'%') |
| | | </if> |
| | | <if test="param2.parentName!=null and param2.parentName!=''"> |
| | | and ( |
| | |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import org.sxkj.system.entity.Region; |
| | | import org.sxkj.system.excel.RegionExcel; |
| | | import org.sxkj.system.excel.RegionImportExcel; |
| | | import org.sxkj.system.param.RegionPageParam; |
| | | import org.sxkj.system.vo.RegionVO; |
| | | import org.sxkj.system.vo.TreeVo; |
| | |
| | | * @param isCovered |
| | | * @return |
| | | */ |
| | | void importRegion(List<RegionExcel> data, Boolean isCovered); |
| | | void importRegion(List<RegionImportExcel> data, Boolean isCovered); |
| | | |
| | | /** |
| | | * 导出区划数据 |
| | |
| | | import org.springblade.core.log.exception.ServiceException; |
| | | import org.springblade.core.tool.utils.*; |
| | | import org.sxkj.common.func.Streams; |
| | | import org.sxkj.system.cache.RegionCache; |
| | | import org.sxkj.system.entity.Region; |
| | | import org.sxkj.system.excel.RegionExcel; |
| | | import org.sxkj.system.excel.RegionImportExcel; |
| | | import org.sxkj.system.mapper.RegionMapper; |
| | | import org.sxkj.system.param.RegionPageParam; |
| | | import org.sxkj.system.service.IRegionService; |
| | |
| | | return baseMapper.lazyTree(parentCode, param); |
| | | } |
| | | |
| | | // WHEN |
| | | // region_level = '5' THEN town_name |
| | | // WHEN |
| | | // region_level = '4' THEN district_name |
| | | // WHEN |
| | | // region_level = '3' THEN city_name |
| | | // WHEN |
| | | // region_level = '2' THEN province_name |
| | | @Override |
| | | public void importRegion(List<RegionExcel> data, Boolean isCovered) { |
| | | public void importRegion(List<RegionImportExcel> data, Boolean isCovered) { |
| | | List<Region> list = new ArrayList<>(); |
| | | data.forEach(regionExcel -> { |
| | | Region region = BeanUtil.copy(regionExcel, Region.class); |
| | | region.setRegionLevel(Integer.valueOf(regionExcel.getRegionLevel())); |
| | | region.setCityName("吉安市"); |
| | | region.setCityCode("360800000000"); |
| | | region.setProvinceCode("360000000000"); |
| | | region.setProvinceName("江西省"); |
| | | if (region.getRegionLevel().equals(DISTRICT_LEVEL)) { |
| | | region.setDistrictCode(region.getCode()); |
| | | region.setDistrictName(region.getName()); |
| | | } |
| | | if (region.getRegionLevel().equals(TOWN_LEVEL)) { |
| | | String parentCode = region.getParentCode(); |
| | | Region byCode = getByCode(parentCode); |
| | | region.setDistrictCode(byCode.getCode()); |
| | | region.setDistrictName(byCode.getName()); |
| | | region.setTownCode(region.getCode()); |
| | | region.setTownName(region.getName()); |
| | | } |
| | | if (region.getRegionLevel().equals(VILLAGE_LEVEL)) { |
| | | String parentCode = region.getParentCode(); |
| | | Region byCode = getByCode(parentCode); |
| | | region.setTownCode(byCode.getCode()); |
| | | region.setTownName(byCode.getName()); |
| | | Region byCode2 = getByCode(byCode.getParentCode()); |
| | | region.setDistrictCode(byCode2.getCode()); |
| | | region.setDistrictName(byCode2.getName()); |
| | | region.setVillageCode(region.getCode()); |
| | | region.setVillageName(region.getName()); |
| | | } |
| | | list.add(region); |
| | | }); |
| | | if (isCovered) { |
| | |
| | | |
| | | @Override |
| | | public TreeVo buildRegionTree(String parentCode) { |
| | | if(StringUtil.isBlank(parentCode)){ |
| | | if (StringUtil.isBlank(parentCode)) { |
| | | return null; |
| | | } |
| | | LambdaQueryWrapper<Region> query = Wrappers.<Region>lambdaQuery() |
| | | .le(Region::getRegionLevel, 3) |
| | | .likeRight(Region::getParentCode, parentCode.replaceAll("0+$", "")) |
| | | .or(regionLambdaQueryWrapper -> |
| | | regionLambdaQueryWrapper.eq(Region::getCode, parentCode) |
| | | ); |
| | | regionLambdaQueryWrapper.eq(Region::getCode, parentCode) |
| | | ); |
| | | List<Region> list = list(query); |
| | | List<TreeVo> regionVOS = Streams.toList(list, region -> { |
| | | TreeVo vo = new TreeVo(); |
| | |
| | | |
| | | List<TreeVo> regionVOS1 = buildRegionTree(regionVOS, parentCode); |
| | | TreeVo treeVo = map.get(parentCode); |
| | | if(Objects.nonNull(treeVo)){ |
| | | if (Objects.nonNull(treeVo)) { |
| | | treeVo.setChildrens(regionVOS1); |
| | | } |
| | | |
| | |
| | | * @return List of RegionVO trees starting from the specified parentCode |
| | | */ |
| | | public List<TreeVo> buildRegionTree(List<TreeVo> allRegions, String parentCode) { |
| | | if(CollectionUtil.isEmpty(allRegions)){ |
| | | if (CollectionUtil.isEmpty(allRegions)) { |
| | | return Collections.EMPTY_LIST; |
| | | } |
| | | |
| | |
| | | /** |
| | | * Recursive method to build the region tree |
| | | * |
| | | * @param regionMap Map of regions grouped by parentCode |
| | | * @param regionMap Map of regions grouped by parentCode |
| | | * @param currentCode Current region code to process |
| | | * @return List of RegionVOs with children populated |
| | | */ |
| New file |
| | |
| | | package org.sxkj.system.util.excel; |
| | | |
| | | import com.alibaba.excel.write.handler.SheetWriteHandler; |
| | | import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; |
| | | import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; |
| | | import org.apache.poi.ss.usermodel.*; |
| | | import org.apache.poi.ss.util.CellRangeAddressList; |
| | | |
| | | /** |
| | | * 区域数据验证处理器 |
| | | * <p> |
| | | * 用于为Excel导出模板中的区域列添加下拉选择功能 |
| | | * </p> |
| | | * |
| | | * @author Chill |
| | | */ |
| | | public class DeptSheetWriteHandler implements SheetWriteHandler { |
| | | |
| | | /** |
| | | * 区域名称列表 |
| | | * <p> |
| | | * 这里需要根据实际情况从区域数据源获取 |
| | | * </p> |
| | | */ |
| | | |
| | | // 启用 禁用 |
| | | private static final String[] ENABLE_DISABLE = { "启用", "禁用" }; |
| | | |
| | | @Override |
| | | public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { |
| | | // 工作表创建前的操作,暂时不需要 |
| | | } |
| | | |
| | | @Override |
| | | public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { |
| | | Workbook workbook = writeWorkbookHolder.getWorkbook(); |
| | | Sheet sheet = writeSheetHolder.getSheet(); |
| | | |
| | | // 为区域列添加下拉选择 |
| | | // 假设区域列是第3列(索引为1),从第2行开始(索引为1) |
| | | addRegionValidation(workbook, sheet, 5, 1, 1000, ENABLE_DISABLE); |
| | | } |
| | | |
| | | /** |
| | | * 为区域列添加数据验证,设置下拉选择 |
| | | * |
| | | * @param workbook 工作簿 |
| | | * @param sheet 工作表 |
| | | * @param column 列索引 |
| | | * @param startRow 开始行索引 |
| | | * @param endRow 结束行索引 |
| | | */ |
| | | private void addRegionValidation(Workbook workbook, Sheet sheet, int column, int startRow, int endRow, String[] regionNames) { |
| | | // 创建数据验证助手 |
| | | DataValidationHelper helper = sheet.getDataValidationHelper(); |
| | | |
| | | // 创建下拉列表约束 |
| | | DataValidationConstraint constraint = helper.createExplicitListConstraint(regionNames); |
| | | |
| | | // 创建数据验证区域 |
| | | CellRangeAddressList addressList = new CellRangeAddressList(startRow, endRow, column, column); |
| | | |
| | | // 创建数据验证 |
| | | DataValidation validation = helper.createValidation(constraint, addressList); |
| | | |
| | | // 设置验证错误提示 |
| | | validation.setErrorStyle(DataValidation.ErrorStyle.STOP); |
| | | validation.setShowErrorBox(true); |
| | | validation.setSuppressDropDownArrow(true); |
| | | validation.createErrorBox("输入错误", "请从下拉列表中选择区域名称"); |
| | | |
| | | // 添加数据验证到工作表 |
| | | sheet.addValidationData(validation); |
| | | } |
| | | |
| | | |
| | | } |
| | |
| | | * 这里需要根据实际情况从区域数据源获取 |
| | | * </p> |
| | | */ |
| | | private static final String[] REGION_NAMES = { |
| | | "吉州区", "青原区", "吉安县", "吉水县", "峡江县", "新干县", "永丰县", "泰和县", "遂川县", "万安县" |
| | | }; |
| | | |
| | | private static final String[] REGION_NAMES = { "市级", "区县级", "街道级" }; |
| | | // 启用 禁用 |
| | | private static final String[] ENABLE_DISABLE = { "启用", "禁用" }; |
| | | |
| | | @Override |
| | | public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { |
| | |
| | | |
| | | // 为区域列添加下拉选择 |
| | | // 假设区域列是第3列(索引为1),从第2行开始(索引为1) |
| | | addRegionValidation(workbook, sheet, 1, 1, 1000); |
| | | addRegionValidation(workbook, sheet, 3, 1, 1000, REGION_NAMES); |
| | | addRegionValidation(workbook, sheet, 5, 1, 1000, ENABLE_DISABLE); |
| | | } |
| | | |
| | | /** |
| | |
| | | * @param startRow 开始行索引 |
| | | * @param endRow 结束行索引 |
| | | */ |
| | | private void addRegionValidation(Workbook workbook, Sheet sheet, int column, int startRow, int endRow) { |
| | | private void addRegionValidation(Workbook workbook, Sheet sheet, int column, int startRow, int endRow, String[] regionNames) { |
| | | // 创建数据验证助手 |
| | | DataValidationHelper helper = sheet.getDataValidationHelper(); |
| | | |
| | | // 创建下拉列表约束 |
| | | DataValidationConstraint constraint = helper.createExplicitListConstraint(REGION_NAMES); |
| | | DataValidationConstraint constraint = helper.createExplicitListConstraint(regionNames); |
| | | |
| | | // 创建数据验证区域 |
| | | CellRangeAddressList addressList = new CellRangeAddressList(startRow, endRow, column, column); |
| | |
| | | // 添加数据验证到工作表 |
| | | sheet.addValidationData(validation); |
| | | } |
| | | |
| | | |
| | | } |