吉安感知网项目-后端
linwei
2026-01-29 1abd541be8d02dabaa77d3c6d2fecde5ef0e4b5b
区划改造
8 files modified
2 files added
272 ■■■■ changed files
drone-service/drone-system/src/main/java/org/sxkj/system/controller/DeptController.java 6 ●●●●● patch | view | raw | blame | history
drone-service/drone-system/src/main/java/org/sxkj/system/controller/RegionController.java 38 ●●●● patch | view | raw | blame | history
drone-service/drone-system/src/main/java/org/sxkj/system/excel/DeptImportExcel.java 4 ●●● patch | view | raw | blame | history
drone-service/drone-system/src/main/java/org/sxkj/system/excel/RegionImportExcel.java 70 ●●●●● patch | view | raw | blame | history
drone-service/drone-system/src/main/java/org/sxkj/system/excel/RegionImporter.java 4 ●●●● patch | view | raw | blame | history
drone-service/drone-system/src/main/java/org/sxkj/system/mapper/RegionMapper.xml 2 ●●● patch | view | raw | blame | history
drone-service/drone-system/src/main/java/org/sxkj/system/service/IRegionService.java 3 ●●●● patch | view | raw | blame | history
drone-service/drone-system/src/main/java/org/sxkj/system/service/impl/RegionServiceImpl.java 52 ●●●● patch | view | raw | blame | history
drone-service/drone-system/src/main/java/org/sxkj/system/util/excel/DeptSheetWriteHandler.java 77 ●●●●● patch | view | raw | blame | history
drone-service/drone-system/src/main/java/org/sxkj/system/util/excel/RegionSheetWriteHandler.java 16 ●●●●● patch | view | raw | blame | history
drone-service/drone-system/src/main/java/org/sxkj/system/controller/DeptController.java
@@ -367,12 +367,6 @@
    /**
     * 导出模板
     * <p>
     * 为区域列添加下拉选择功能,限制用户只能选择预设的区域名称
     * </p>
     *
     * @param response HTTP响应对象
     * @throws IOException 导出异常
     */
    @GetMapping("export-template")
    @ApiOperationSupport(order = 16)
drone-service/drone-system/src/main/java/org/sxkj/system/controller/RegionController.java
@@ -16,6 +16,7 @@
 */
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;
@@ -32,11 +33,14 @@
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;
@@ -46,6 +50,10 @@
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;
@@ -197,7 +205,7 @@
    @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("操作成功");
    }
@@ -216,12 +224,32 @@
    /**
     * 导出模板
     */
    // @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);
    }
    /**
drone-service/drone-system/src/main/java/org/sxkj/system/excel/DeptImportExcel.java
@@ -44,10 +44,8 @@
    @ColumnWidth(20)
    private String deptName;
    @ExcelProperty(value = "所属区划", converter = ExcelDictConverter.class)
    @ExcelProperty(value = "所属区划编码")
    @ColumnWidth(20)
    @ExcelDictItemLabel(type = "regionName")
    @ExcelDictItem(type = "regionName")
    private String areaCode;
    @ExcelProperty("机构描述")
drone-service/drone-system/src/main/java/org/sxkj/system/excel/RegionImportExcel.java
New file
@@ -0,0 +1,70 @@
/*
 *      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;
}
drone-service/drone-system/src/main/java/org/sxkj/system/excel/RegionImporter.java
@@ -28,13 +28,13 @@
 * @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);
    }
}
drone-service/drone-system/src/main/java/org/sxkj/system/mapper/RegionMapper.xml
@@ -164,7 +164,7 @@
                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 (
drone-service/drone-system/src/main/java/org/sxkj/system/service/IRegionService.java
@@ -21,6 +21,7 @@
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;
@@ -85,7 +86,7 @@
     * @param isCovered
     * @return
     */
    void importRegion(List<RegionExcel> data, Boolean isCovered);
    void importRegion(List<RegionImportExcel> data, Boolean isCovered);
    /**
     * 导出区划数据
drone-service/drone-system/src/main/java/org/sxkj/system/service/impl/RegionServiceImpl.java
@@ -27,8 +27,10 @@
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;
@@ -124,11 +126,47 @@
        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) {
@@ -197,15 +235,15 @@
    @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();
@@ -220,7 +258,7 @@
        List<TreeVo> regionVOS1 = buildRegionTree(regionVOS, parentCode);
        TreeVo treeVo = map.get(parentCode);
        if(Objects.nonNull(treeVo)){
        if (Objects.nonNull(treeVo)) {
            treeVo.setChildrens(regionVOS1);
        }
@@ -240,7 +278,7 @@
     * @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;
        }
@@ -255,7 +293,7 @@
    /**
     * 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
     */
drone-service/drone-system/src/main/java/org/sxkj/system/util/excel/DeptSheetWriteHandler.java
New file
@@ -0,0 +1,77 @@
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);
    }
}
drone-service/drone-system/src/main/java/org/sxkj/system/util/excel/RegionSheetWriteHandler.java
@@ -25,9 +25,10 @@
     * 这里需要根据实际情况从区域数据源获取
     * </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) {
@@ -41,7 +42,8 @@
        // 为区域列添加下拉选择
        // 假设区域列是第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);
    }
    /**
@@ -53,12 +55,12 @@
     * @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);
@@ -75,4 +77,6 @@
        // 添加数据验证到工作表
        sheet.addValidationData(validation);
    }
}