Commit 8db6dcd55b67fcc974afc8818484b2772ee5d664
Merge branch 'master' of http://gitlab1.renniting.cn/JCSS/urbanops
Showing
25 changed files
with
963 additions
and
62 deletions
.gitignore
| ... | ... | @@ -53,3 +53,15 @@ application-my.yaml |
| 53 | 53 | /urbanops-ui-app/unpackage/ |
| 54 | 54 | **/.DS_Store |
| 55 | 55 | old/ |
| 56 | +/.claudeignore | |
| 57 | +/docs/all_test.html | |
| 58 | +/docs/ppt-assets/animations.css | |
| 59 | +/docs/ppt-assets/base.css | |
| 60 | +/CLAUDE.md | |
| 61 | +/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/enums/ErrorCodeConstants_手动操作.java | |
| 62 | +/docs/ppt-assets/fonts.css | |
| 63 | +/docs/ppt-assets/runtime.js | |
| 64 | +/.claude/settings.local.json | |
| 65 | +/docs/ppt-assets/style.css | |
| 66 | +/docs/urbanops-architecture-ppt.html | |
| 67 | +/docs/urbanops-tech-sharing.html | ... | ... |
sql/mysql/garden_problem_type-fix.sql
0 → 100644
| 1 | +-- ================================================= | |
| 2 | +-- garden_problem_type 表结构补全 | |
| 3 | +-- 原因:BaseDO 包含 create_time/update_time/creator/updater/deleted | |
| 4 | +-- MyBatis Plus @TableLogic 自动 WHERE deleted=0 | |
| 5 | +-- 缺少这些列会导致 SQL 报错或无数据返回 | |
| 6 | +-- ================================================= | |
| 7 | + | |
| 8 | +-- 如果表已存在数据,先备份 | |
| 9 | +-- CREATE TABLE garden_problem_type_bak AS SELECT * FROM garden_problem_type; | |
| 10 | + | |
| 11 | +-- 方案1:删表重建(无重要数据时) | |
| 12 | +DROP TABLE IF EXISTS `garden_problem_type`; | |
| 13 | +CREATE TABLE `garden_problem_type` ( | |
| 14 | + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', | |
| 15 | + `type_code` varchar(32) NOT NULL COMMENT '问题类型编码', | |
| 16 | + `type_name` varchar(64) NOT NULL COMMENT '问题类型名称', | |
| 17 | + `level` tinyint NOT NULL COMMENT '层级:1一级 2二级 3三级', | |
| 18 | + `parent_code` varchar(32) DEFAULT NULL COMMENT '父级类型编码', | |
| 19 | + `sort` int DEFAULT 0 COMMENT '排序序号', | |
| 20 | + `status` tinyint DEFAULT 1 COMMENT '状态 1启用 0禁用', | |
| 21 | + `creator` varchar(64) DEFAULT '' COMMENT '创建者', | |
| 22 | + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', | |
| 23 | + `updater` varchar(64) DEFAULT '' COMMENT '更新者', | |
| 24 | + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', | |
| 25 | + `deleted` tinyint NOT NULL DEFAULT 0 COMMENT '逻辑删除 0正常 1删除', | |
| 26 | + PRIMARY KEY (`id`), | |
| 27 | + UNIQUE KEY `uk_type_code` (`type_code`) | |
| 28 | +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='问题类型三级分类表'; | |
| 29 | + | |
| 30 | +-- 方案2:已有数据时,用 ALTER 补齐缺失列(按需执行) | |
| 31 | +-- ALTER TABLE garden_problem_type ADD COLUMN `creator` varchar(64) DEFAULT '' COMMENT '创建者' AFTER `status`; | |
| 32 | +-- ALTER TABLE garden_problem_type ADD COLUMN `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间' AFTER `creator`; | |
| 33 | +-- ALTER TABLE garden_problem_type ADD COLUMN `updater` varchar(64) DEFAULT '' COMMENT '更新者' AFTER `create_time`; | |
| 34 | +-- ALTER TABLE garden_problem_type ADD COLUMN `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间' AFTER `updater`; | |
| 35 | +-- ALTER TABLE garden_problem_type ADD COLUMN `deleted` tinyint NOT NULL DEFAULT 0 COMMENT '逻辑删除' AFTER `update_time`; | ... | ... |
sql/mysql/problem-type-menu-auto.sql
0 → 100644
| 1 | +-- ================================================= | |
| 2 | +-- 问题类型配置 - 菜单与权限 SQL(自动查找父菜单ID) | |
| 3 | +-- 直接执行即可,自动从「工单管理」下挂载菜单 | |
| 4 | +-- ================================================= | |
| 5 | + | |
| 6 | +-- 查询当前最大 ID 作为起始值 | |
| 7 | +SET @maxId = (SELECT IFNULL(MAX(id), 5000) FROM system_menu); | |
| 8 | + | |
| 9 | +-- 查询工单管理 菜单ID | |
| 10 | +SET @parentId = (SELECT id FROM system_menu WHERE name = '工单管理' AND type = 1 LIMIT 1); | |
| 11 | + | |
| 12 | +-- 如果找不到工单管理,尝试匹配 workorder 关键字 | |
| 13 | +-- SET @parentId = (SELECT id FROM system_menu WHERE (name LIKE '%工单%' OR path LIKE '%workorder%') AND type = 1 LIMIT 1); | |
| 14 | + | |
| 15 | +-- 1. 二级菜单:问题类型 | |
| 16 | +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) | |
| 17 | +VALUES (@maxId + 1, '问题类型', '', 2, 10, @parentId, 'problem-type', 'ep:list', 'garden/problemType/index', 'ProblemType', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'); | |
| 18 | + | |
| 19 | +-- 2. 按钮:查询 | |
| 20 | +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) | |
| 21 | +VALUES (@maxId + 2, '问题类型查询', 'garden:problem-type:query', 3, 1, @maxId + 1, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'); | |
| 22 | + | |
| 23 | +-- 3. 按钮:创建 | |
| 24 | +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) | |
| 25 | +VALUES (@maxId + 3, '问题类型创建', 'garden:problem-type:create', 3, 2, @maxId + 1, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'); | |
| 26 | + | |
| 27 | +-- 4. 按钮:更新 | |
| 28 | +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) | |
| 29 | +VALUES (@maxId + 4, '问题类型更新', 'garden:problem-type:update', 3, 3, @maxId + 1, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'); | |
| 30 | + | |
| 31 | +-- 5. 按钮:删除 | |
| 32 | +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) | |
| 33 | +VALUES (@maxId + 5, '问题类型删除', 'garden:problem-type:delete', 3, 4, @maxId + 1, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'); | ... | ... |
sql/mysql/problem-type-menu.sql
0 → 100644
| 1 | +-- ================================================= | |
| 2 | +-- 问题类型配置 - 菜单与权限 SQL | |
| 3 | +-- 说明: | |
| 4 | +-- 1. 请先查询「工单管理」的菜单 ID,替换下面 @parentId 为实际值 | |
| 5 | +-- 查询语句:SELECT id FROM system_menu WHERE name = '工单管理' AND type = 1; | |
| 6 | +-- 2. 修改下面 @menuId 为可用的起始 ID(确保不与已有菜单 ID 冲突) | |
| 7 | +-- 查询最大ID:SELECT MAX(id) FROM system_menu; | |
| 8 | +-- 3. 执行前请备份 system_menu 表 | |
| 9 | +-- ================================================= | |
| 10 | + | |
| 11 | +-- 请根据实际情况替换以下变量值: | |
| 12 | +-- SET @parentId = (SELECT id FROM system_menu WHERE name = '工单管理' AND type = 1); | |
| 13 | +-- SET @menuId = (SELECT IFNULL(MAX(id), 0) + 1 FROM system_menu); | |
| 14 | + | |
| 15 | +-- 示例:假设工单管理 parent_id = 2000,起始 menu_id = 5100 | |
| 16 | + | |
| 17 | +-- 1. 二级菜单:问题类型 | |
| 18 | +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) | |
| 19 | +VALUES (@menuId, '问题类型', '', 2, 10, @parentId, 'problem-type', 'ep:list', 'garden/problemType/index', 'ProblemType', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'); | |
| 20 | + | |
| 21 | +-- 2. 按钮权限:查询 | |
| 22 | +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) | |
| 23 | +VALUES (@menuId + 1, '问题类型查询', 'garden:problem-type:query', 3, 1, @menuId, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'); | |
| 24 | + | |
| 25 | +-- 3. 按钮权限:创建 | |
| 26 | +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) | |
| 27 | +VALUES (@menuId + 2, '问题类型创建', 'garden:problem-type:create', 3, 2, @menuId, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'); | |
| 28 | + | |
| 29 | +-- 4. 按钮权限:更新 | |
| 30 | +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) | |
| 31 | +VALUES (@menuId + 3, '问题类型更新', 'garden:problem-type:update', 3, 3, @menuId, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'); | |
| 32 | + | |
| 33 | +-- 5. 按钮权限:删除 | |
| 34 | +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) | |
| 35 | +VALUES (@menuId + 4, '问题类型删除', 'garden:problem-type:delete', 3, 4, @menuId, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'); | ... | ... |
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/admin/costfee/CostFeeController.java
| ... | ... | @@ -5,16 +5,24 @@ import com.zteits.urbanops.framework.excel.core.util.ExcelUtils; |
| 5 | 5 | import com.zteits.urbanops.module.garden.controller.admin.costfee.vo.WaterFeeImport; |
| 6 | 6 | import com.zteits.urbanops.module.garden.enums.TemplateEnum; |
| 7 | 7 | import com.zteits.urbanops.module.garden.service.costfee.CostFeeService; |
| 8 | +import com.zteits.urbanops.module.system.api.dept.DeptApi; | |
| 9 | +import com.zteits.urbanops.module.system.api.dept.dto.DeptRespDTO; | |
| 8 | 10 | import io.swagger.v3.oas.annotations.Operation; |
| 9 | 11 | import io.swagger.v3.oas.annotations.tags.Tag; |
| 12 | +import jakarta.annotation.security.PermitAll; | |
| 10 | 13 | import jakarta.servlet.http.HttpServletResponse; |
| 11 | 14 | import lombok.AllArgsConstructor; |
| 12 | 15 | import lombok.Data; |
| 13 | 16 | import lombok.extern.slf4j.Slf4j; |
| 17 | +import org.apache.poi.ss.usermodel.*; | |
| 18 | +import org.apache.poi.ss.util.CellRangeAddressList; | |
| 19 | +import org.apache.poi.xssf.usermodel.XSSFWorkbook; | |
| 14 | 20 | import org.springframework.beans.factory.annotation.Autowired; |
| 15 | 21 | import org.springframework.beans.factory.annotation.Value; |
| 16 | -import org.springframework.core.io.ClassPathResource; | |
| 22 | +import org.springframework.core.io.Resource; | |
| 23 | +import org.springframework.core.io.ResourceLoader; | |
| 17 | 24 | import org.springframework.util.CollectionUtils; |
| 25 | +import org.springframework.util.StringUtils; | |
| 18 | 26 | import org.springframework.web.bind.annotation.*; |
| 19 | 27 | import org.springframework.web.multipart.MultipartFile; |
| 20 | 28 | |
| ... | ... | @@ -23,7 +31,6 @@ import java.io.InputStream; |
| 23 | 31 | import java.io.OutputStream; |
| 24 | 32 | import java.lang.reflect.Method; |
| 25 | 33 | import java.net.URLEncoder; |
| 26 | -import java.nio.charset.StandardCharsets; | |
| 27 | 34 | import java.util.*; |
| 28 | 35 | |
| 29 | 36 | import static com.zteits.urbanops.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST; |
| ... | ... | @@ -49,6 +56,12 @@ public class CostFeeController{ |
| 49 | 56 | @Value("${static.resource.server.enable}") |
| 50 | 57 | private Boolean staticResourceServerenable; |
| 51 | 58 | |
| 59 | + @Autowired | |
| 60 | + private ResourceLoader resourceLoader; | |
| 61 | + | |
| 62 | + @jakarta.annotation.Resource | |
| 63 | + private DeptApi deptApi; | |
| 64 | + | |
| 52 | 65 | // Excel文件校验相关 |
| 53 | 66 | private static final List<String> ALLOWED_EXCEL_SUFFIX = Arrays.asList(".xlsx", ".xlsm"); |
| 54 | 67 | private static final String EXCEL_MIME_TYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; |
| ... | ... | @@ -59,6 +72,7 @@ public class CostFeeController{ |
| 59 | 72 | */ |
| 60 | 73 | @GetMapping("/get-import-template") |
| 61 | 74 | @Operation(summary = "获得导入用户模板") |
| 75 | + @PermitAll | |
| 62 | 76 | public void importTemplate(HttpServletResponse response, |
| 63 | 77 | @RequestParam("templateName") String templateName) throws IOException { |
| 64 | 78 | // 参数校验 |
| ... | ... | @@ -74,29 +88,150 @@ public class CostFeeController{ |
| 74 | 88 | return; |
| 75 | 89 | } |
| 76 | 90 | |
| 77 | - if (staticResourceServerenable) { | |
| 78 | - // 构建完整的静态服务器URL(确保路径正确) | |
| 79 | - String serverUrl = staticResourceServerUrl; | |
| 80 | - if (serverUrl != null && !serverUrl.endsWith("/")) { | |
| 81 | - serverUrl += "/"; // 确保URL以/结尾,避免拼接错误 | |
| 82 | - } | |
| 91 | + writeAndModifyTemplate(response, template.getName(), template.getStartIndex()); | |
| 92 | + } | |
| 93 | + | |
| 94 | + private void writeAndModifyTemplate(HttpServletResponse response, | |
| 95 | + String downloadFileName, | |
| 96 | + int startIndexRow) throws IOException { | |
| 97 | + | |
| 98 | + // 拼接模板路径 | |
| 99 | + String serverUrl = staticResourceServerUrl; | |
| 100 | + if (serverUrl != null && !serverUrl.endsWith("/")) { | |
| 101 | + serverUrl += "/"; | |
| 102 | + } | |
| 103 | + String fullPath = serverUrl + downloadFileName; | |
| 104 | + fullPath = fullPath.replace("\\", "/"); | |
| 105 | + | |
| 106 | + Resource resource = resourceLoader.getResource(fullPath); | |
| 107 | + | |
| 108 | + // 检查文件是否存在 | |
| 109 | + if (!resource.exists()) { | |
| 110 | + response.sendError(HttpServletResponse.SC_NOT_FOUND, "模板文件不存在"); | |
| 111 | + return; | |
| 112 | + } | |
| 113 | + | |
| 114 | + // 设置下载响应头 | |
| 115 | + response.reset(); | |
| 116 | + response.setContentType(EXCEL_MIME_TYPE); | |
| 117 | + // response.setCharacterEncoding("UTF-8"); | |
| 118 | + String encodedName = URLEncoder.encode(downloadFileName, "UTF-8"); | |
| 119 | + // 标准文件名编码(Chrome / Edge / Firefox 全兼容) | |
| 120 | + response.setHeader("Content-Disposition", "attachment;filename*=UTF-8''" + encodedName); | |
| 121 | + // 浏览器缓存配置(必须) | |
| 122 | + response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); | |
| 123 | + response.setHeader("Pragma", "no-cache"); | |
| 124 | + response.setHeader("Expires", "0"); | |
| 125 | + | |
| 126 | + | |
| 127 | + try (InputStream in = resource.getInputStream(); | |
| 128 | + XSSFWorkbook workbook = new XSSFWorkbook(in); | |
| 129 | + OutputStream out = response.getOutputStream()) { | |
| 83 | 130 | |
| 84 | - String encodedFileName = URLEncoder.encode(template.getName().split("\\.")[0], StandardCharsets.UTF_8.name()); | |
| 131 | + Sheet sheet = workbook.getSheetAt(0); | |
| 85 | 132 | |
| 86 | - String templateFileName = encodedFileName + "." + template.getName().split("\\.")[1]; | |
| 133 | + // ============================================== | |
| 134 | + // 获取最新单位列表 | |
| 135 | + // ============================================== | |
| 136 | + List<DeptRespDTO> companyList = deptApi.getSubDeptList(); | |
| 137 | + List<String> newUnits = companyList.stream() | |
| 138 | + .map(DeptRespDTO::getName) | |
| 139 | + .filter(Objects::nonNull) | |
| 140 | + .toList(); | |
| 87 | 141 | |
| 88 | - String templateUrl = serverUrl + templateFileName; // 包含templates目录 | |
| 142 | + log.info("加载到单位列表:{},共{}条", newUnits, newUnits.size()); | |
| 89 | 143 | |
| 90 | - // 方式1:重定向到静态资源服务器 | |
| 91 | - response.sendRedirect(templateUrl); | |
| 92 | - } else { | |
| 93 | - String templateFileName = templateName + "." + template.getName().split("\\.")[1]; | |
| 144 | + // ============================================== | |
| 145 | + // 生成新下拉 + 自动赋值 | |
| 146 | + // ============================================== | |
| 147 | + createDropdownAndSetValue(sheet, newUnits, startIndexRow); | |
| 148 | + | |
| 149 | + // 写入并强制刷新 | |
| 150 | + workbook.write(out); | |
| 151 | + out.flush(); | |
| 94 | 152 | |
| 95 | - // 写入模板文件到响应 | |
| 96 | - writeTemplateToResponse(response, template.getName(), templateFileName); | |
| 153 | + } catch (Exception e) { | |
| 154 | + log.error("模板处理失败", e); | |
| 155 | + throw new IOException("文件处理失败", e); | |
| 97 | 156 | } |
| 98 | 157 | } |
| 99 | 158 | |
| 159 | + /** | |
| 160 | + * 创建下拉框 + 给单元格赋值 | |
| 161 | + */ | |
| 162 | + private void createDropdownAndSetValue(Sheet sheet, List<String> options, int startRow) { | |
| 163 | + if (options.isEmpty()) { | |
| 164 | + log.error("下拉选项为空,不创建"); | |
| 165 | + return; | |
| 166 | + } | |
| 167 | + | |
| 168 | + // 获取表头行 | |
| 169 | + Row headerRow = sheet.getRow(startRow - 1); | |
| 170 | + if (headerRow == null) { | |
| 171 | + log.error("表头行不存在:{}", startRow - 1); | |
| 172 | + return; | |
| 173 | + } | |
| 174 | + | |
| 175 | + // 查找“所属单位”列 | |
| 176 | + int targetCol = -1; | |
| 177 | + for (Cell cell : headerRow) { | |
| 178 | + if (cell != null && cell.getCellType() == CellType.STRING) { | |
| 179 | + String val = cell.getStringCellValue().trim(); | |
| 180 | + if (val.contains("所属单位") || val.contains("所属公司") ) { | |
| 181 | + targetCol = cell.getColumnIndex(); | |
| 182 | + break; | |
| 183 | + } | |
| 184 | + } | |
| 185 | + } | |
| 186 | + | |
| 187 | + if (targetCol == -1) { | |
| 188 | + log.error("未找到【所属单位】列表头"); | |
| 189 | + return; | |
| 190 | + } | |
| 191 | + | |
| 192 | + // 取消列隐藏 | |
| 193 | + sheet.setColumnHidden(targetCol, false); | |
| 194 | + | |
| 195 | + // ============================================== | |
| 196 | + // 遍历行:清空原有内容 + 设置默认值 | |
| 197 | + // ============================================== | |
| 198 | + int endRow = 100; | |
| 199 | + for (int r = startRow; r <= endRow; r++) { | |
| 200 | + Row row = sheet.getRow(r); | |
| 201 | + if (row == null) { | |
| 202 | + row = sheet.createRow(r); | |
| 203 | + } | |
| 204 | + | |
| 205 | + Cell cell = row.getCell(targetCol); | |
| 206 | + if (cell == null) { | |
| 207 | + cell = row.createCell(targetCol); | |
| 208 | + } | |
| 209 | + String unit = cell.getStringCellValue(); | |
| 210 | + // 默认赋值【第一个单位】,你可以根据业务改成其他值 | |
| 211 | + if (!StringUtils.isEmpty(unit)) { | |
| 212 | + cell.setCellValue(options.get(0)); | |
| 213 | + } | |
| 214 | + } | |
| 215 | + | |
| 216 | + // ============================================== | |
| 217 | + // 创建下拉框(作用范围:startRow ~ 1000行) | |
| 218 | + // ============================================== | |
| 219 | + CellRangeAddressList regions = new CellRangeAddressList(startRow, endRow, targetCol, targetCol); | |
| 220 | + DataValidationHelper helper = sheet.getDataValidationHelper(); | |
| 221 | + DataValidationConstraint constraint = helper.createExplicitListConstraint( | |
| 222 | + options.toArray(new String[0]) | |
| 223 | + ); | |
| 224 | + DataValidation validation = helper.createValidation(constraint, regions); | |
| 225 | + // 下拉框基础配置 | |
| 226 | + validation.setEmptyCellAllowed(true); | |
| 227 | + validation.setSuppressDropDownArrow(true); // 显示箭头 | |
| 228 | + validation.setShowErrorBox(true); | |
| 229 | + validation.setShowPromptBox(true); // 启用点击弹出提示 | |
| 230 | + sheet.addValidationData(validation); | |
| 231 | + | |
| 232 | + log.info("【成功】为列{}添加下拉并赋值,行{}~{},选项数:{}", | |
| 233 | + targetCol, startRow, endRow, options.size()); | |
| 234 | + } | |
| 100 | 235 | |
| 101 | 236 | /** |
| 102 | 237 | * Excel文件上传预览 |
| ... | ... | @@ -214,31 +349,6 @@ public class CostFeeController{ |
| 214 | 349 | } |
| 215 | 350 | |
| 216 | 351 | /** |
| 217 | - * 写入模板文件到响应流 | |
| 218 | - */ | |
| 219 | - private void writeTemplateToResponse(HttpServletResponse response, String filename, String templatePath) throws IOException { | |
| 220 | - // 设置响应头 | |
| 221 | - response.setContentType(EXCEL_MIME_TYPE); | |
| 222 | - response.setCharacterEncoding("UTF-8"); | |
| 223 | - String encodedFileName = URLEncoder.encode(filename, "UTF-8").replaceAll("\\+", "%20"); | |
| 224 | - response.setHeader("Content-Disposition", "attachment;filename=" + encodedFileName); | |
| 225 | - response.setHeader("Cache-Control", "no-store"); // 禁止缓存 | |
| 226 | - | |
| 227 | - // 读取模板文件并写入响应 | |
| 228 | - try (InputStream in = new ClassPathResource("template/" + templatePath).getInputStream(); | |
| 229 | - OutputStream out = response.getOutputStream()) { | |
| 230 | - | |
| 231 | - byte[] buffer = new byte[4096]; | |
| 232 | - int bytesRead; | |
| 233 | - while ((bytesRead = in.read(buffer)) != -1) { | |
| 234 | - out.write(buffer, 0, bytesRead); | |
| 235 | - } | |
| 236 | - out.flush(); | |
| 237 | - } | |
| 238 | - } | |
| 239 | - | |
| 240 | - | |
| 241 | - /** | |
| 242 | 352 | * 校验Excel文件有效性(后缀+MIME类型) |
| 243 | 353 | */ |
| 244 | 354 | private boolean isValidExcelFile(MultipartFile file) { | ... | ... |
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/admin/problemtype/GardenProblemTypeController.java
0 → 100644
| 1 | +package com.zteits.urbanops.module.garden.controller.admin.problemtype; | |
| 2 | + | |
| 3 | +import com.zteits.urbanops.module.garden.controller.admin.problemtype.vo.ProblemTypePageReqVO; | |
| 4 | +import com.zteits.urbanops.module.garden.controller.admin.problemtype.vo.ProblemTypeRespVO; | |
| 5 | +import com.zteits.urbanops.module.garden.controller.admin.problemtype.vo.ProblemTypeSaveReqVO; | |
| 6 | +import org.springframework.web.bind.annotation.*; | |
| 7 | +import jakarta.annotation.Resource; | |
| 8 | +import org.springframework.validation.annotation.Validated; | |
| 9 | +import org.springframework.security.access.prepost.PreAuthorize; | |
| 10 | +import io.swagger.v3.oas.annotations.tags.Tag; | |
| 11 | +import io.swagger.v3.oas.annotations.Parameter; | |
| 12 | +import io.swagger.v3.oas.annotations.Operation; | |
| 13 | + | |
| 14 | +import jakarta.validation.*; | |
| 15 | +import java.util.*; | |
| 16 | + | |
| 17 | +import com.zteits.urbanops.framework.common.pojo.CommonResult; | |
| 18 | +import com.zteits.urbanops.framework.common.pojo.PageResult; | |
| 19 | +import com.zteits.urbanops.framework.common.util.object.BeanUtils; | |
| 20 | +import static com.zteits.urbanops.framework.common.pojo.CommonResult.success; | |
| 21 | + | |
| 22 | +import com.zteits.urbanops.module.garden.dal.dataobject.problemtype.GardenProblemTypeDO; | |
| 23 | +import com.zteits.urbanops.module.garden.dal.mysql.problemtype.GardenProblemTypeMapper; | |
| 24 | +import com.zteits.urbanops.module.garden.service.problemtype.GardenProblemTypeService; | |
| 25 | + | |
| 26 | +@Tag(name = "管理后台 - 问题类型配置") | |
| 27 | +@RestController | |
| 28 | +@RequestMapping("/garden/problem-type") | |
| 29 | +@Validated | |
| 30 | +public class GardenProblemTypeController { | |
| 31 | + | |
| 32 | + @Resource | |
| 33 | + private GardenProblemTypeService gardenProblemTypeService; | |
| 34 | + | |
| 35 | + @Resource | |
| 36 | + private GardenProblemTypeMapper gardenProblemTypeMapper; | |
| 37 | + | |
| 38 | + @PostMapping("/create") | |
| 39 | + @Operation(summary = "创建问题类型(二级/三级)") | |
| 40 | + @PreAuthorize("@ss.hasPermission('garden:problem-type:create')") | |
| 41 | + public CommonResult<Long> createProblemType(@Valid @RequestBody ProblemTypeSaveReqVO createReqVO) { | |
| 42 | + return success(gardenProblemTypeService.createProblemType(createReqVO)); | |
| 43 | + } | |
| 44 | + | |
| 45 | + @PutMapping("/update") | |
| 46 | + @Operation(summary = "更新问题类型(二级/三级)") | |
| 47 | + @PreAuthorize("@ss.hasPermission('garden:problem-type:update')") | |
| 48 | + public CommonResult<Boolean> updateProblemType(@Valid @RequestBody ProblemTypeSaveReqVO updateReqVO) { | |
| 49 | + gardenProblemTypeService.updateProblemType(updateReqVO); | |
| 50 | + return success(true); | |
| 51 | + } | |
| 52 | + | |
| 53 | + @DeleteMapping("/delete") | |
| 54 | + @Operation(summary = "删除问题类型") | |
| 55 | + @Parameter(name = "id", description = "编号", required = true) | |
| 56 | + @PreAuthorize("@ss.hasPermission('garden:problem-type:delete')") | |
| 57 | + public CommonResult<Boolean> deleteProblemType(@RequestParam("id") Long id) { | |
| 58 | + gardenProblemTypeService.deleteProblemType(id); | |
| 59 | + return success(true); | |
| 60 | + } | |
| 61 | + | |
| 62 | + @GetMapping("/get") | |
| 63 | + @Operation(summary = "获得问题类型") | |
| 64 | + @Parameter(name = "id", description = "编号", required = true, example = "1024") | |
| 65 | + @PreAuthorize("@ss.hasPermission('garden:problem-type:query')") | |
| 66 | + public CommonResult<ProblemTypeRespVO> getProblemType(@RequestParam("id") Long id) { | |
| 67 | + GardenProblemTypeDO problemType = gardenProblemTypeService.getProblemType(id); | |
| 68 | + ProblemTypeRespVO respVO = BeanUtils.toBean(problemType, ProblemTypeRespVO.class); | |
| 69 | + fillParentNames(Arrays.asList(respVO)); | |
| 70 | + return success(respVO); | |
| 71 | + } | |
| 72 | + | |
| 73 | + @GetMapping("/page") | |
| 74 | + @Operation(summary = "获得问题类型分页") | |
| 75 | + @PreAuthorize("@ss.hasPermission('garden:problem-type:query')") | |
| 76 | + public CommonResult<PageResult<ProblemTypeRespVO>> getProblemTypePage(@Valid ProblemTypePageReqVO pageReqVO) { | |
| 77 | + PageResult<GardenProblemTypeDO> pageResult = gardenProblemTypeService.getProblemTypePage(pageReqVO); | |
| 78 | + PageResult<ProblemTypeRespVO> voPageResult = BeanUtils.toBean(pageResult, ProblemTypeRespVO.class); | |
| 79 | + fillParentNames(voPageResult.getList()); | |
| 80 | + return success(voPageResult); | |
| 81 | + } | |
| 82 | + | |
| 83 | + @GetMapping("/list-by-parent") | |
| 84 | + @Operation(summary = "根据父级编码和层级查询子类型列表(级联下拉用)") | |
| 85 | + @PreAuthorize("@ss.hasPermission('garden:problem-type:query')") | |
| 86 | + public CommonResult<List<ProblemTypeRespVO>> getProblemTypeListByParent( | |
| 87 | + @RequestParam(value = "parentCode", required = false) String parentCode, | |
| 88 | + @RequestParam("level") Integer level) { | |
| 89 | + List<GardenProblemTypeDO> list = gardenProblemTypeService.getProblemTypeByParentCode(parentCode, level); | |
| 90 | + return success(BeanUtils.toBean(list, ProblemTypeRespVO.class)); | |
| 91 | + } | |
| 92 | + | |
| 93 | + @GetMapping("/generate-next-code") | |
| 94 | + @Operation(summary = "根据父级编码生成下一个类型编码") | |
| 95 | + @PreAuthorize("@ss.hasPermission('garden:problem-type:create')") | |
| 96 | + public CommonResult<String> generateNextCode(@RequestParam("parentCode") String parentCode) { | |
| 97 | + return success(gardenProblemTypeService.generateNextCode(parentCode)); | |
| 98 | + } | |
| 99 | + | |
| 100 | + @PostMapping("/sync-level-one") | |
| 101 | + @Operation(summary = "从字典表同步一级类型") | |
| 102 | + @PreAuthorize("@ss.hasPermission('garden:problem-type:create')") | |
| 103 | + public CommonResult<Integer> syncLevelOne() { | |
| 104 | + return success(gardenProblemTypeService.syncLevelOneFromDict()); | |
| 105 | + } | |
| 106 | + | |
| 107 | + /** | |
| 108 | + * 填充每个记录的层级名称: | |
| 109 | + * level 1 → levelOneName = 自身 typeName | |
| 110 | + * level 2 → levelTwoName = 自身 typeName, levelOneName = 父级 typeName | |
| 111 | + * level 3 → levelOneName = 祖父 typeName, levelTwoName = 父级 typeName | |
| 112 | + */ | |
| 113 | + private void fillParentNames(List<ProblemTypeRespVO> list) { | |
| 114 | + if (list == null || list.isEmpty()) { | |
| 115 | + return; | |
| 116 | + } | |
| 117 | + for (ProblemTypeRespVO vo : list) { | |
| 118 | + if (vo.getLevel() == null) continue; | |
| 119 | + if (vo.getLevel() == 1) { | |
| 120 | + vo.setLevelOneName(vo.getTypeName()); | |
| 121 | + } else if (vo.getLevel() == 2) { | |
| 122 | + vo.setLevelTwoName(vo.getTypeName()); | |
| 123 | + if (vo.getParentCode() != null) { | |
| 124 | + GardenProblemTypeDO parent = gardenProblemTypeMapper.selectByTypeCode(vo.getParentCode()); | |
| 125 | + if (parent != null) { | |
| 126 | + vo.setLevelOneName(parent.getTypeName()); | |
| 127 | + } | |
| 128 | + } | |
| 129 | + } else if (vo.getLevel() == 3) { | |
| 130 | + if (vo.getParentCode() != null) { | |
| 131 | + GardenProblemTypeDO parent = gardenProblemTypeMapper.selectByTypeCode(vo.getParentCode()); | |
| 132 | + if (parent != null) { | |
| 133 | + vo.setLevelTwoName(parent.getTypeName()); | |
| 134 | + if (parent.getParentCode() != null) { | |
| 135 | + GardenProblemTypeDO grandParent = gardenProblemTypeMapper | |
| 136 | + .selectByTypeCode(parent.getParentCode()); | |
| 137 | + if (grandParent != null) { | |
| 138 | + vo.setLevelOneName(grandParent.getTypeName()); | |
| 139 | + } | |
| 140 | + } | |
| 141 | + } | |
| 142 | + } | |
| 143 | + } | |
| 144 | + } | |
| 145 | + } | |
| 146 | + | |
| 147 | +} | ... | ... |
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/admin/problemtype/vo/ProblemTypePageReqVO.java
0 → 100644
| 1 | +package com.zteits.urbanops.module.garden.controller.admin.problemtype.vo; | |
| 2 | + | |
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 4 | +import lombok.Data; | |
| 5 | +import com.zteits.urbanops.framework.common.pojo.PageParam; | |
| 6 | + | |
| 7 | +@Schema(description = "管理后台 - 问题类型分页 Request VO") | |
| 8 | +@Data | |
| 9 | +public class ProblemTypePageReqVO extends PageParam { | |
| 10 | + | |
| 11 | + @Schema(description = "问题类型编码", example = "PT001") | |
| 12 | + private String typeCode; | |
| 13 | + | |
| 14 | + @Schema(description = "问题类型名称", example = "树木倒伏") | |
| 15 | + private String typeName; | |
| 16 | + | |
| 17 | + @Schema(description = "层级:1一级 2二级 3三级", example = "2") | |
| 18 | + private Integer level; | |
| 19 | + | |
| 20 | + @Schema(description = "父级类型编码", example = "BIZ_GARDEN") | |
| 21 | + private String parentCode; | |
| 22 | + | |
| 23 | + @Schema(description = "一级类型编码(级联筛选)", example = "yl") | |
| 24 | + private String levelOneCode; | |
| 25 | + | |
| 26 | + @Schema(description = "状态 1启用 0禁用", example = "1") | |
| 27 | + private Integer status; | |
| 28 | + | |
| 29 | +} | ... | ... |
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/admin/problemtype/vo/ProblemTypeRespVO.java
0 → 100644
| 1 | +package com.zteits.urbanops.module.garden.controller.admin.problemtype.vo; | |
| 2 | + | |
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 4 | +import lombok.Data; | |
| 5 | +import cn.idev.excel.annotation.*; | |
| 6 | + | |
| 7 | +@Schema(description = "管理后台 - 问题类型 Response VO") | |
| 8 | +@Data | |
| 9 | +@ExcelIgnoreUnannotated | |
| 10 | +public class ProblemTypeRespVO { | |
| 11 | + | |
| 12 | + @Schema(description = "主键ID", example = "1") | |
| 13 | + @ExcelProperty("主键ID") | |
| 14 | + private Long id; | |
| 15 | + | |
| 16 | + @Schema(description = "问题类型编码", example = "PT001") | |
| 17 | + @ExcelProperty("问题类型编码") | |
| 18 | + private String typeCode; | |
| 19 | + | |
| 20 | + @Schema(description = "问题类型名称", example = "树木倒伏") | |
| 21 | + @ExcelProperty("问题类型名称") | |
| 22 | + private String typeName; | |
| 23 | + | |
| 24 | + @Schema(description = "层级:1一级 2二级 3三级", example = "2") | |
| 25 | + @ExcelProperty("层级") | |
| 26 | + private Integer level; | |
| 27 | + | |
| 28 | + @Schema(description = "父级类型编码", example = "BIZ_GARDEN") | |
| 29 | + @ExcelProperty("父级类型编码") | |
| 30 | + private String parentCode; | |
| 31 | + | |
| 32 | + @Schema(description = "排序序号", example = "1") | |
| 33 | + @ExcelProperty("排序序号") | |
| 34 | + private Integer sort; | |
| 35 | + | |
| 36 | + @Schema(description = "状态 1启用 0禁用", example = "1") | |
| 37 | + @ExcelProperty("状态") | |
| 38 | + private Integer status; | |
| 39 | + | |
| 40 | + @Schema(description = "一级类型名称") | |
| 41 | + private String levelOneName; | |
| 42 | + | |
| 43 | + @Schema(description = "二级类型名称") | |
| 44 | + private String levelTwoName; | |
| 45 | + | |
| 46 | + @Schema(description = "创建者") | |
| 47 | + @ExcelProperty("创建者") | |
| 48 | + private String creator; | |
| 49 | + | |
| 50 | + @Schema(description = "创建时间") | |
| 51 | + @ExcelProperty("创建时间") | |
| 52 | + private String createTime; | |
| 53 | + | |
| 54 | +} | ... | ... |
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/admin/problemtype/vo/ProblemTypeSaveReqVO.java
0 → 100644
| 1 | +package com.zteits.urbanops.module.garden.controller.admin.problemtype.vo; | |
| 2 | + | |
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 4 | +import lombok.Data; | |
| 5 | +import jakarta.validation.constraints.*; | |
| 6 | + | |
| 7 | +@Schema(description = "管理后台 - 问题类型新增/修改 Request VO") | |
| 8 | +@Data | |
| 9 | +public class ProblemTypeSaveReqVO { | |
| 10 | + | |
| 11 | + @Schema(description = "主键ID", example = "1") | |
| 12 | + private Long id; | |
| 13 | + | |
| 14 | + @Schema(description = "问题类型编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "PT001") | |
| 15 | + @NotEmpty(message = "问题类型编码不能为空") | |
| 16 | + private String typeCode; | |
| 17 | + | |
| 18 | + @Schema(description = "问题类型名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "树木倒伏") | |
| 19 | + @NotEmpty(message = "问题类型名称不能为空") | |
| 20 | + private String typeName; | |
| 21 | + | |
| 22 | + @Schema(description = "层级:1一级 2二级 3三级", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") | |
| 23 | + @NotNull(message = "层级不能为空") | |
| 24 | + private Integer level; | |
| 25 | + | |
| 26 | + @Schema(description = "父级类型编码", example = "BIZ_GARDEN") | |
| 27 | + private String parentCode; | |
| 28 | + | |
| 29 | + @Schema(description = "排序序号", example = "1") | |
| 30 | + private Integer sort; | |
| 31 | + | |
| 32 | + @Schema(description = "状态 1启用 0禁用", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | |
| 33 | + @NotNull(message = "状态不能为空") | |
| 34 | + private Integer status; | |
| 35 | + | |
| 36 | +} | ... | ... |
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/convert/AppGardenWorkOrderConvert.java
| ... | ... | @@ -24,7 +24,7 @@ public interface AppGardenWorkOrderConvert { |
| 24 | 24 | orderReqVO.setPressingType(2);//紧急 |
| 25 | 25 | orderReqVO.setOrderName(inspectionPlanDO.getPlanName()); |
| 26 | 26 | orderReqVO.setSourceId(1);//来源ID 工单来源 1、巡查 |
| 27 | - orderReqVO.setSourceName("园林巡查上报"); | |
| 27 | + orderReqVO.setSourceName("巡查上报"); | |
| 28 | 28 | orderReqVO.setThirdWorkNo(planNo); |
| 29 | 29 | orderReqVO.setOrderType("C"); |
| 30 | 30 | orderReqVO.setPressingType(createReqVO.getPressingType()); | ... | ... |
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/dal/dataobject/problemtype/GardenProblemTypeDO.java
0 → 100644
| 1 | +package com.zteits.urbanops.module.garden.dal.dataobject.problemtype; | |
| 2 | + | |
| 3 | +import lombok.*; | |
| 4 | +import com.baomidou.mybatisplus.annotation.*; | |
| 5 | +import com.zteits.urbanops.framework.mybatis.core.dataobject.BaseDO; | |
| 6 | + | |
| 7 | +/** | |
| 8 | + * 问题类型三级分类 DO | |
| 9 | + * | |
| 10 | + * @author 超级管理员 | |
| 11 | + */ | |
| 12 | +@TableName("garden_problem_type") | |
| 13 | +@KeySequence("garden_problem_type_seq") | |
| 14 | +@Data | |
| 15 | +@EqualsAndHashCode(callSuper = true) | |
| 16 | +@ToString(callSuper = true) | |
| 17 | +@Builder | |
| 18 | +@NoArgsConstructor | |
| 19 | +@AllArgsConstructor | |
| 20 | +public class GardenProblemTypeDO extends BaseDO { | |
| 21 | + | |
| 22 | + /** | |
| 23 | + * 主键ID | |
| 24 | + */ | |
| 25 | + @TableId | |
| 26 | + private Long id; | |
| 27 | + /** | |
| 28 | + * 问题类型编码 | |
| 29 | + */ | |
| 30 | + private String typeCode; | |
| 31 | + /** | |
| 32 | + * 问题类型名称 | |
| 33 | + */ | |
| 34 | + private String typeName; | |
| 35 | + /** | |
| 36 | + * 层级:1一级 2二级 3三级 | |
| 37 | + */ | |
| 38 | + private Integer level; | |
| 39 | + /** | |
| 40 | + * 父级类型编码 | |
| 41 | + */ | |
| 42 | + private String parentCode; | |
| 43 | + /** | |
| 44 | + * 排序序号 | |
| 45 | + */ | |
| 46 | + private Integer sort; | |
| 47 | + /** | |
| 48 | + * 状态 1启用 0禁用 | |
| 49 | + */ | |
| 50 | + private Integer status; | |
| 51 | + | |
| 52 | +} | ... | ... |
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/dal/mysql/problemtype/GardenProblemTypeMapper.java
0 → 100644
| 1 | +package com.zteits.urbanops.module.garden.dal.mysql.problemtype; | |
| 2 | + | |
| 3 | +import com.zteits.urbanops.framework.common.pojo.PageResult; | |
| 4 | +import com.zteits.urbanops.framework.mybatis.core.query.LambdaQueryWrapperX; | |
| 5 | +import com.zteits.urbanops.framework.mybatis.core.mapper.BaseMapperX; | |
| 6 | +import com.zteits.urbanops.module.garden.controller.admin.problemtype.vo.ProblemTypePageReqVO; | |
| 7 | +import com.zteits.urbanops.module.garden.dal.dataobject.problemtype.GardenProblemTypeDO; | |
| 8 | +import org.apache.ibatis.annotations.Mapper; | |
| 9 | + | |
| 10 | +import java.util.ArrayList; | |
| 11 | +import java.util.List; | |
| 12 | +import java.util.stream.Collectors; | |
| 13 | + | |
| 14 | +/** | |
| 15 | + * 问题类型 Mapper | |
| 16 | + * | |
| 17 | + * @author 超级管理员 | |
| 18 | + */ | |
| 19 | +@Mapper | |
| 20 | +public interface GardenProblemTypeMapper extends BaseMapperX<GardenProblemTypeDO> { | |
| 21 | + | |
| 22 | + default PageResult<GardenProblemTypeDO> selectPage(ProblemTypePageReqVO reqVO) { | |
| 23 | + LambdaQueryWrapperX<GardenProblemTypeDO> wrapper = new LambdaQueryWrapperX<GardenProblemTypeDO>() | |
| 24 | + .eqIfPresent(GardenProblemTypeDO::getLevel, reqVO.getLevel()) | |
| 25 | + .eqIfPresent(GardenProblemTypeDO::getStatus, reqVO.getStatus()) | |
| 26 | + .likeIfPresent(GardenProblemTypeDO::getTypeName, reqVO.getTypeName()) | |
| 27 | + .likeIfPresent(GardenProblemTypeDO::getTypeCode, reqVO.getTypeCode()); | |
| 28 | + wrapper.orderByAsc(GardenProblemTypeDO::getSort); | |
| 29 | + wrapper.orderByAsc(GardenProblemTypeDO::getId); | |
| 30 | + | |
| 31 | + // 级联筛选:如果传了 levelOneCode,查出所有二级编码做 IN 查询 | |
| 32 | + if (reqVO.getLevelOneCode() != null && !reqVO.getLevelOneCode().isEmpty()) { | |
| 33 | + List<GardenProblemTypeDO> levelTwoList = selectByParentCodeAndLevel(reqVO.getLevelOneCode(), 2); | |
| 34 | + List<String> parentCodes = new ArrayList<>(); | |
| 35 | + parentCodes.add(reqVO.getLevelOneCode()); // 包含一级自身 | |
| 36 | + parentCodes.addAll(levelTwoList.stream().map(GardenProblemTypeDO::getTypeCode).collect(Collectors.toList())); | |
| 37 | + wrapper.in(GardenProblemTypeDO::getParentCode, parentCodes); | |
| 38 | + } else { | |
| 39 | + wrapper.eqIfPresent(GardenProblemTypeDO::getParentCode, reqVO.getParentCode()); | |
| 40 | + } | |
| 41 | + | |
| 42 | + return selectPage(reqVO, wrapper); | |
| 43 | + } | |
| 44 | + | |
| 45 | + /** | |
| 46 | + * 根据 parentCode 和 level 查询子类型列表 | |
| 47 | + */ | |
| 48 | + default List<GardenProblemTypeDO> selectByParentCodeAndLevel(String parentCode, Integer level) { | |
| 49 | + return selectList(new LambdaQueryWrapperX<GardenProblemTypeDO>() | |
| 50 | + .eqIfPresent(GardenProblemTypeDO::getParentCode, parentCode) | |
| 51 | + .eqIfPresent(GardenProblemTypeDO::getLevel, level) | |
| 52 | + .eq(GardenProblemTypeDO::getStatus, 1) | |
| 53 | + .orderByAsc(GardenProblemTypeDO::getSort) | |
| 54 | + .orderByAsc(GardenProblemTypeDO::getId)); | |
| 55 | + } | |
| 56 | + | |
| 57 | + /** | |
| 58 | + * 根据 typeCode 查询唯一记录 | |
| 59 | + */ | |
| 60 | + default GardenProblemTypeDO selectByTypeCode(String typeCode) { | |
| 61 | + return selectOne(new LambdaQueryWrapperX<GardenProblemTypeDO>() | |
| 62 | + .eq(GardenProblemTypeDO::getTypeCode, typeCode)); | |
| 63 | + } | |
| 64 | + | |
| 65 | + /** | |
| 66 | + * 生成下一个编码:父级编码 + 5位递增序号 | |
| 67 | + * 如 parentCode=BIZ_GARDEN → BIZ_GARDEN00001, BIZ_GARDEN00002 | |
| 68 | + */ | |
| 69 | + default String generateNextCode(String parentCode) { | |
| 70 | + List<GardenProblemTypeDO> list = selectList(new LambdaQueryWrapperX<GardenProblemTypeDO>() | |
| 71 | + .likeRight(GardenProblemTypeDO::getTypeCode, parentCode) | |
| 72 | + .orderByDesc(GardenProblemTypeDO::getTypeCode) | |
| 73 | + .last("LIMIT 1")); | |
| 74 | + if (list == null || list.isEmpty()) { | |
| 75 | + return parentCode + "00001"; | |
| 76 | + } | |
| 77 | + String maxCode = list.get(0).getTypeCode(); | |
| 78 | + String seqStr = maxCode.substring(parentCode.length()); | |
| 79 | + try { | |
| 80 | + int seq = Integer.parseInt(seqStr) + 1; | |
| 81 | + return parentCode + String.format("%05d", seq); | |
| 82 | + } catch (NumberFormatException e) { | |
| 83 | + return parentCode + "00001"; | |
| 84 | + } | |
| 85 | + } | |
| 86 | + | |
| 87 | +} | ... | ... |
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/enums/ErrorCodeConstants.java
| ... | ... | @@ -87,9 +87,11 @@ public interface ErrorCodeConstants { |
| 87 | 87 | ErrorCode INSPECTION_CYCLE_ERROR = new ErrorCode(1-200-100-003, "获取两个时间之间间隔天数错误"); |
| 88 | 88 | ErrorCode INSPECTION_PLAN_EXISTS = new ErrorCode(1-200-100-007, "道路对应类型已存在记录"); |
| 89 | 89 | ErrorCode INSPECTION_PLAN_NOT_ALLOW_DELETE = new ErrorCode(1-100-007-005, "计划已开始执行不能删除"); |
| 90 | + ErrorCode INSPECTION_COMMIT_PLAN__EXISTS = new ErrorCode(1-100-007-005, "巡检计划明细已提交"); | |
| 90 | 91 | |
| 91 | 92 | // ========== 养护计划汇总 TODO 补充编号 ========== |
| 92 | 93 | ErrorCode MAINTAIN_PLAN_NOT_EXISTS = new ErrorCode(1-100-007-001, "养护计划汇总不存在"); |
| 94 | + ErrorCode MAINTAIN_COMMIT_PLAN__EXISTS = new ErrorCode(1-100-007-007, "养护计划明细已提交"); | |
| 93 | 95 | |
| 94 | 96 | //========== 频次 TODO 补充编号 ========== |
| 95 | 97 | ErrorCode PLAN_RATE_EXISTS = new ErrorCode(1-100-007-001, "养护频次已存在"); |
| ... | ... | @@ -145,4 +147,8 @@ public interface ErrorCodeConstants { |
| 145 | 147 | |
| 146 | 148 | ErrorCode EMERGENCY_TASK_NOT_EXISTS = new ErrorCode(1-100-006-002, "抢险任务主不存在"); |
| 147 | 149 | |
| 150 | + // ========== 问题类型配置 1-100-009-000 ========== | |
| 151 | + ErrorCode PROBLEM_TYPE_NOT_EXISTS = new ErrorCode(1100009000, "问题类型不存在"); | |
| 152 | + ErrorCode PROBLEM_TYPE_CODE_EXISTS = new ErrorCode(1100009001, "问题类型编码已存在"); | |
| 153 | + | |
| 148 | 154 | } | ... | ... |
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/inspectionplan/InspectionPlanCommitServiceImpl.java
| ... | ... | @@ -18,6 +18,7 @@ import com.zteits.urbanops.module.garden.convert.AppGardenWorkOrderConvert; |
| 18 | 18 | import com.zteits.urbanops.module.garden.dal.dataobject.inspectionplan.InspectionPlanCommitDO; |
| 19 | 19 | import com.zteits.urbanops.module.garden.dal.dataobject.inspectionplan.InspectionPlanDO; |
| 20 | 20 | import com.zteits.urbanops.module.garden.dal.dataobject.inspectionplan.InspectionPlanDetailDO; |
| 21 | +import com.zteits.urbanops.module.garden.dal.dataobject.maintainplan.MaintainPlanCommitDO; | |
| 21 | 22 | import com.zteits.urbanops.module.garden.dal.dataobject.road.RoadDO; |
| 22 | 23 | import com.zteits.urbanops.module.garden.dal.mysql.inspectionplan.InspectionPlanCommitMapper; |
| 23 | 24 | import com.zteits.urbanops.module.garden.dal.mysql.inspectionplan.InspectionPlanDetailMapper; |
| ... | ... | @@ -43,7 +44,7 @@ import java.util.*; |
| 43 | 44 | import java.util.stream.Collectors; |
| 44 | 45 | |
| 45 | 46 | import static com.zteits.urbanops.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 46 | -import static com.zteits.urbanops.module.garden.enums.ErrorCodeConstants.INSPECTION_PLAN_NOT_EXISTS; | |
| 47 | +import static com.zteits.urbanops.module.garden.enums.ErrorCodeConstants.*; | |
| 47 | 48 | |
| 48 | 49 | |
| 49 | 50 | /** |
| ... | ... | @@ -76,6 +77,10 @@ public class InspectionPlanCommitServiceImpl implements InspectionPlanCommitServ |
| 76 | 77 | |
| 77 | 78 | @Override |
| 78 | 79 | public Long createInspectionPlanCommit(InspectionPlanCommitSaveReqVO createReqVO) { |
| 80 | + List<InspectionPlanCommitDO> list = inspectionPlanCommitMapper.selectList(InspectionPlanCommitDO::getPlanNo, createReqVO.getPlanNo()); | |
| 81 | + if(!CollectionUtils.isEmpty(list)){ | |
| 82 | + throw exception(INSPECTION_COMMIT_PLAN__EXISTS); | |
| 83 | + } | |
| 79 | 84 | // 插入 |
| 80 | 85 | InspectionPlanCommitDO inspectionPlanCommit = BeanUtils.toBean(createReqVO, InspectionPlanCommitDO.class); |
| 81 | 86 | inspectionPlanCommitMapper.insert(inspectionPlanCommit); | ... | ... |
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/maintainplan/MaintainPlanCommitServiceImpl.java
| ... | ... | @@ -63,6 +63,10 @@ public class MaintainPlanCommitServiceImpl implements MaintainPlanCommitService |
| 63 | 63 | |
| 64 | 64 | @Override |
| 65 | 65 | public Long createMaintainPlanCommit(MaintainPlanCommitSaveReqVO createReqVO) { |
| 66 | + List<MaintainPlanCommitDO> list = maintainPlanCommitMapper.selectList(MaintainPlanCommitDO::getPlanNo, createReqVO.getPlanNo()); | |
| 67 | + if(!CollectionUtils.isEmpty(list)){ | |
| 68 | + throw exception(MAINTAIN_PLAN_NOT_EXISTS); | |
| 69 | + } | |
| 66 | 70 | // 插入 |
| 67 | 71 | MaintainPlanCommitDO maintainPlanCommit = BeanUtils.toBean(createReqVO, MaintainPlanCommitDO.class); |
| 68 | 72 | maintainPlanCommitMapper.insert(maintainPlanCommit); | ... | ... |
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/problemtype/GardenProblemTypeService.java
0 → 100644
| 1 | +package com.zteits.urbanops.module.garden.service.problemtype; | |
| 2 | + | |
| 3 | +import com.zteits.urbanops.module.garden.controller.admin.problemtype.vo.ProblemTypePageReqVO; | |
| 4 | +import com.zteits.urbanops.module.garden.controller.admin.problemtype.vo.ProblemTypeSaveReqVO; | |
| 5 | +import com.zteits.urbanops.module.garden.dal.dataobject.problemtype.GardenProblemTypeDO; | |
| 6 | +import com.zteits.urbanops.framework.common.pojo.PageResult; | |
| 7 | +import jakarta.validation.Valid; | |
| 8 | + | |
| 9 | +import java.util.List; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * 问题类型配置 Service 接口 | |
| 13 | + * | |
| 14 | + * @author 超级管理员 | |
| 15 | + */ | |
| 16 | +public interface GardenProblemTypeService { | |
| 17 | + | |
| 18 | + /** | |
| 19 | + * 创建问题类型 | |
| 20 | + * | |
| 21 | + * @param createReqVO 创建信息 | |
| 22 | + * @return 编号 | |
| 23 | + */ | |
| 24 | + Long createProblemType(@Valid ProblemTypeSaveReqVO createReqVO); | |
| 25 | + | |
| 26 | + /** | |
| 27 | + * 更新问题类型 | |
| 28 | + * | |
| 29 | + * @param updateReqVO 更新信息 | |
| 30 | + */ | |
| 31 | + void updateProblemType(@Valid ProblemTypeSaveReqVO updateReqVO); | |
| 32 | + | |
| 33 | + /** | |
| 34 | + * 删除问题类型 | |
| 35 | + * | |
| 36 | + * @param id 编号 | |
| 37 | + */ | |
| 38 | + void deleteProblemType(Long id); | |
| 39 | + | |
| 40 | + /** | |
| 41 | + * 获得问题类型 | |
| 42 | + * | |
| 43 | + * @param id 编号 | |
| 44 | + * @return 问题类型 | |
| 45 | + */ | |
| 46 | + GardenProblemTypeDO getProblemType(Long id); | |
| 47 | + | |
| 48 | + /** | |
| 49 | + * 获得问题类型分页 | |
| 50 | + * | |
| 51 | + * @param pageReqVO 分页查询 | |
| 52 | + * @return 问题类型分页 | |
| 53 | + */ | |
| 54 | + PageResult<GardenProblemTypeDO> getProblemTypePage(ProblemTypePageReqVO pageReqVO); | |
| 55 | + | |
| 56 | + /** | |
| 57 | + * 根据父级编码和层级查询子类型列表 | |
| 58 | + * | |
| 59 | + * @param parentCode 父级编码 | |
| 60 | + * @param level 层级 | |
| 61 | + * @return 子类型列表 | |
| 62 | + */ | |
| 63 | + List<GardenProblemTypeDO> getProblemTypeByParentCode(String parentCode, Integer level); | |
| 64 | + | |
| 65 | + /** | |
| 66 | + * 根据父级编码生成下一个类型编码 | |
| 67 | + * | |
| 68 | + * @param parentCode 父级编码 | |
| 69 | + * @return 新编码 | |
| 70 | + */ | |
| 71 | + String generateNextCode(String parentCode); | |
| 72 | + | |
| 73 | + /** | |
| 74 | + * 从字典表同步一级类型到 garden_problem_type | |
| 75 | + * | |
| 76 | + * @return 同步数量 | |
| 77 | + */ | |
| 78 | + int syncLevelOneFromDict(); | |
| 79 | + | |
| 80 | +} | ... | ... |
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/problemtype/GardenProblemTypeServiceImpl.java
0 → 100644
| 1 | +package com.zteits.urbanops.module.garden.service.problemtype; | |
| 2 | + | |
| 3 | +import com.zteits.urbanops.framework.common.enums.CommonStatusEnum; | |
| 4 | +import com.zteits.urbanops.module.garden.controller.admin.problemtype.vo.ProblemTypePageReqVO; | |
| 5 | +import com.zteits.urbanops.module.garden.controller.admin.problemtype.vo.ProblemTypeSaveReqVO; | |
| 6 | +import com.zteits.urbanops.module.system.dal.dataobject.dict.DictDataDO; | |
| 7 | +import com.zteits.urbanops.module.system.service.dict.DictDataService; | |
| 8 | +import org.springframework.stereotype.Service; | |
| 9 | +import org.springframework.validation.annotation.Validated; | |
| 10 | +import jakarta.annotation.Resource; | |
| 11 | + | |
| 12 | +import java.util.List; | |
| 13 | + | |
| 14 | +import com.zteits.urbanops.module.garden.dal.dataobject.problemtype.GardenProblemTypeDO; | |
| 15 | +import com.zteits.urbanops.framework.common.pojo.PageResult; | |
| 16 | +import com.zteits.urbanops.framework.common.util.object.BeanUtils; | |
| 17 | + | |
| 18 | +import com.zteits.urbanops.module.garden.dal.mysql.problemtype.GardenProblemTypeMapper; | |
| 19 | + | |
| 20 | +import static com.zteits.urbanops.framework.common.exception.util.ServiceExceptionUtil.exception; | |
| 21 | +import static com.zteits.urbanops.module.garden.enums.ErrorCodeConstants.*; | |
| 22 | + | |
| 23 | +/** | |
| 24 | + * 问题类型配置 Service 实现类 | |
| 25 | + * | |
| 26 | + * @author 超级管理员 | |
| 27 | + */ | |
| 28 | +@Service | |
| 29 | +@Validated | |
| 30 | +public class GardenProblemTypeServiceImpl implements GardenProblemTypeService { | |
| 31 | + | |
| 32 | + @Resource | |
| 33 | + private GardenProblemTypeMapper gardenProblemTypeMapper; | |
| 34 | + | |
| 35 | + @Resource | |
| 36 | + private DictDataService dictDataService; | |
| 37 | + | |
| 38 | + @Override | |
| 39 | + public Long createProblemType(ProblemTypeSaveReqVO createReqVO) { | |
| 40 | + // 校验编码唯一性 | |
| 41 | + validateTypeCodeUnique(createReqVO.getTypeCode(), null); | |
| 42 | + // 插入 | |
| 43 | + GardenProblemTypeDO problemType = BeanUtils.toBean(createReqVO, GardenProblemTypeDO.class); | |
| 44 | + gardenProblemTypeMapper.insert(problemType); | |
| 45 | + return problemType.getId(); | |
| 46 | + } | |
| 47 | + | |
| 48 | + @Override | |
| 49 | + public void updateProblemType(ProblemTypeSaveReqVO updateReqVO) { | |
| 50 | + // 校验存在 | |
| 51 | + validateProblemTypeExists(updateReqVO.getId()); | |
| 52 | + // 校验编码唯一性(排除自身) | |
| 53 | + validateTypeCodeUnique(updateReqVO.getTypeCode(), updateReqVO.getId()); | |
| 54 | + // 更新 | |
| 55 | + GardenProblemTypeDO updateObj = BeanUtils.toBean(updateReqVO, GardenProblemTypeDO.class); | |
| 56 | + gardenProblemTypeMapper.updateById(updateObj); | |
| 57 | + } | |
| 58 | + | |
| 59 | + @Override | |
| 60 | + public void deleteProblemType(Long id) { | |
| 61 | + // 校验存在 | |
| 62 | + validateProblemTypeExists(id); | |
| 63 | + // 删除 | |
| 64 | + gardenProblemTypeMapper.deleteById(id); | |
| 65 | + } | |
| 66 | + | |
| 67 | + private void validateProblemTypeExists(Long id) { | |
| 68 | + if (gardenProblemTypeMapper.selectById(id) == null) { | |
| 69 | + throw exception(PROBLEM_TYPE_NOT_EXISTS); | |
| 70 | + } | |
| 71 | + } | |
| 72 | + | |
| 73 | + private void validateTypeCodeUnique(String typeCode, Long excludeId) { | |
| 74 | + GardenProblemTypeDO exist = gardenProblemTypeMapper.selectByTypeCode(typeCode); | |
| 75 | + if (exist != null && (excludeId == null || !exist.getId().equals(excludeId))) { | |
| 76 | + throw exception(PROBLEM_TYPE_CODE_EXISTS); | |
| 77 | + } | |
| 78 | + } | |
| 79 | + | |
| 80 | + @Override | |
| 81 | + public GardenProblemTypeDO getProblemType(Long id) { | |
| 82 | + return gardenProblemTypeMapper.selectById(id); | |
| 83 | + } | |
| 84 | + | |
| 85 | + @Override | |
| 86 | + public PageResult<GardenProblemTypeDO> getProblemTypePage(ProblemTypePageReqVO pageReqVO) { | |
| 87 | + return gardenProblemTypeMapper.selectPage(pageReqVO); | |
| 88 | + } | |
| 89 | + | |
| 90 | + @Override | |
| 91 | + public List<GardenProblemTypeDO> getProblemTypeByParentCode(String parentCode, Integer level) { | |
| 92 | + return gardenProblemTypeMapper.selectByParentCodeAndLevel(parentCode, level); | |
| 93 | + } | |
| 94 | + | |
| 95 | + @Override | |
| 96 | + public String generateNextCode(String parentCode) { | |
| 97 | + return gardenProblemTypeMapper.generateNextCode(parentCode); | |
| 98 | + } | |
| 99 | + | |
| 100 | + @Override | |
| 101 | + public int syncLevelOneFromDict() { | |
| 102 | + List<DictDataDO> dictList = dictDataService.getDictDataList( | |
| 103 | + CommonStatusEnum.ENABLE.getStatus(), "business_line"); | |
| 104 | + int count = 0; | |
| 105 | + for (DictDataDO dict : dictList) { | |
| 106 | + GardenProblemTypeDO exist = gardenProblemTypeMapper.selectByTypeCode(dict.getValue()); | |
| 107 | + if (exist == null) { | |
| 108 | + GardenProblemTypeDO entity = new GardenProblemTypeDO(); | |
| 109 | + entity.setTypeCode(dict.getValue()); | |
| 110 | + entity.setTypeName(dict.getLabel()); | |
| 111 | + entity.setLevel(1); | |
| 112 | + entity.setParentCode(null); | |
| 113 | + entity.setSort(dict.getSort()); | |
| 114 | + entity.setStatus(CommonStatusEnum.ENABLE.getStatus()); | |
| 115 | + gardenProblemTypeMapper.insert(entity); | |
| 116 | + count++; | |
| 117 | + } | |
| 118 | + } | |
| 119 | + return count; | |
| 120 | + } | |
| 121 | + | |
| 122 | +} | ... | ... |
urbanops-module-garden/src/main/resources/mapper/inspectionplan/InspectionPlanCommitMapper.xml
| ... | ... | @@ -102,7 +102,7 @@ |
| 102 | 102 | </foreach> |
| 103 | 103 | </if> |
| 104 | 104 | |
| 105 | - order by a.id desc | |
| 105 | + order by a.create_time desc | |
| 106 | 106 | </select> |
| 107 | 107 | |
| 108 | 108 | <select id="appInspectionPlanCommitListByPlanNo" resultType="com.zteits.urbanops.module.garden.controller.app.inspectionplan.vo.AppInspectionPlanCommitRespVO"> | ... | ... |
urbanops-module-garden/src/main/resources/mapper/maintainplan/MaintainPlanCommitMapper.xml
urbanops-module-system/src/main/java/com/zteits/urbanops/module/system/controller/admin/dept/DeptController.java
| ... | ... | @@ -19,12 +19,11 @@ import org.springframework.web.bind.annotation.*; |
| 19 | 19 | import jakarta.annotation.Resource; |
| 20 | 20 | import jakarta.validation.Valid; |
| 21 | 21 | |
| 22 | -import java.util.HashMap; | |
| 23 | -import java.util.Map; | |
| 24 | -import java.util.List; | |
| 22 | +import java.util.*; | |
| 25 | 23 | import java.util.stream.Collectors; |
| 26 | 24 | |
| 27 | 25 | import static com.zteits.urbanops.framework.common.pojo.CommonResult.success; |
| 26 | +import static com.zteits.urbanops.framework.common.util.collection.CollectionUtils.convertSet; | |
| 28 | 27 | |
| 29 | 28 | @Tag(name = "管理后台 - 部门") |
| 30 | 29 | @RestController |
| ... | ... | @@ -129,8 +128,13 @@ public class DeptController { |
| 129 | 128 | @Operation(summary = "查询所有组织") |
| 130 | 129 | @GetMapping("/queryAllDeptList") |
| 131 | 130 | @PermitAll |
| 132 | - public Map<String, Object> queryAllDeptList() { | |
| 133 | - List<DeptDO> sysDepts = deptService.getSubDeptAllList(); | |
| 131 | + public Map<String, Object> queryAllDeptList( @RequestParam(required = false) Long deptId) { | |
| 132 | + List<DeptDO> sysDepts = new ArrayList<>(); | |
| 133 | + if(deptId != null){ | |
| 134 | + sysDepts = deptService.getChildDeptList(deptId); | |
| 135 | + }else { | |
| 136 | + sysDepts = deptService.getDeptAllList(); | |
| 137 | + } | |
| 134 | 138 | List<Map<String, Object>> deptResps = sysDepts.stream().map(sysDept -> { |
| 135 | 139 | Map<String, Object> deptMap = new HashMap<>(); |
| 136 | 140 | deptMap.put("deptCode", sysDept.getId() + ""); |
| ... | ... | @@ -140,7 +144,7 @@ public class DeptController { |
| 140 | 144 | deptMap.put("orderNum", sysDept.getSort()); |
| 141 | 145 | return deptMap; |
| 142 | 146 | }).collect(Collectors.toList()); |
| 143 | - | |
| 147 | + | |
| 144 | 148 | // 构建返回格式 |
| 145 | 149 | Map<String, Object> result = new HashMap<>(); |
| 146 | 150 | result.put("msg", "操作成功"); | ... | ... |
urbanops-module-system/src/main/java/com/zteits/urbanops/module/system/controller/app/appmodule/AppAppModuleController.java
| ... | ... | @@ -7,9 +7,11 @@ import com.zteits.urbanops.module.system.controller.app.appmodule.vo.AppModuleVO |
| 7 | 7 | import com.zteits.urbanops.module.system.convert.appmodule.AppModuleConvert; |
| 8 | 8 | import com.zteits.urbanops.module.system.dal.dataobject.appmodule.AppModuleDO; |
| 9 | 9 | import com.zteits.urbanops.module.system.service.appmodule.AppModuleService; |
| 10 | +import com.zteits.urbanops.module.system.service.permission.PermissionService; | |
| 10 | 11 | import io.swagger.v3.oas.annotations.Operation; |
| 11 | 12 | import io.swagger.v3.oas.annotations.tags.Tag; |
| 12 | 13 | import jakarta.annotation.Resource; |
| 14 | +import lombok.extern.slf4j.Slf4j; | |
| 13 | 15 | import org.springframework.validation.annotation.Validated; |
| 14 | 16 | import org.springframework.web.bind.annotation.GetMapping; |
| 15 | 17 | import org.springframework.web.bind.annotation.RequestMapping; |
| ... | ... | @@ -21,6 +23,7 @@ import java.util.Comparator; |
| 21 | 23 | import java.util.LinkedHashMap; |
| 22 | 24 | import java.util.List; |
| 23 | 25 | import java.util.Map; |
| 26 | +import java.util.Set; | |
| 24 | 27 | |
| 25 | 28 | import static com.zteits.urbanops.framework.common.pojo.CommonResult.success; |
| 26 | 29 | |
| ... | ... | @@ -34,29 +37,60 @@ import static com.zteits.urbanops.framework.common.pojo.CommonResult.success; |
| 34 | 37 | @RestController |
| 35 | 38 | @RequestMapping("/member/app-module") |
| 36 | 39 | @Validated |
| 40 | +@Slf4j | |
| 37 | 41 | public class AppAppModuleController { |
| 38 | 42 | |
| 43 | + /** | |
| 44 | + * 园林巡查员角色ID | |
| 45 | + */ | |
| 46 | + private static final Long ROLE_ID_PATROL = 178L; | |
| 47 | + | |
| 48 | + /** | |
| 49 | + * 园林巡查员角色ID | |
| 50 | + */ | |
| 51 | + private static final Long ROLE_ID_PATROL_ZX = 202L; | |
| 52 | + /** | |
| 53 | + * 全域督察员角色ID | |
| 54 | + */ | |
| 55 | + private static final Long ROLE_ID_INSPECTOR = 183L; | |
| 56 | + /** | |
| 57 | + * 巡查工单模块ID | |
| 58 | + */ | |
| 59 | + private static final Long MODULE_ID_PATROL_WORKORDER = 7L; | |
| 60 | + | |
| 39 | 61 | @Resource |
| 40 | 62 | private AppModuleService appModuleService; |
| 41 | 63 | |
| 64 | + @Resource | |
| 65 | + private PermissionService permissionService; | |
| 66 | + | |
| 42 | 67 | @GetMapping("/list") |
| 43 | 68 | @Operation(summary = "获取 App 功能模块列表", description = "获取用户可见的功能模块列表") |
| 44 | 69 | public CommonResult<List<AppModuleVO>> getAppModuleList(AppModuleListReqVO reqVO) { |
| 45 | 70 | // 获取当前登录用户ID |
| 46 | 71 | Long userId = SecurityFrameworkUtils.getLoginUserId(); |
| 47 | - | |
| 72 | + | |
| 48 | 73 | // 查询用户可见的模块列表 |
| 49 | 74 | List<AppModuleDO> list = appModuleService.getVisibleAppModuleList(userId, reqVO); |
| 50 | - | |
| 75 | + | |
| 76 | + // 如果用户同时拥有园林巡查员(178)和全域督察员(183)角色,则隐藏巡查工单菜单,只显示督查工单菜单 | |
| 77 | + if (userId != null) { | |
| 78 | + Set<Long> roleIds = permissionService.getUserRoleIdListByUserId(userId); | |
| 79 | + if (roleIds.contains(ROLE_ID_PATROL_ZX) && roleIds.contains(ROLE_ID_INSPECTOR)) { | |
| 80 | + log.info("[getAppModuleList] 用户({})同时拥有巡查员和督察员角色,隐藏巡查工单菜单", userId); | |
| 81 | + list.removeIf(module -> MODULE_ID_PATROL_WORKORDER.equals(module.getId())); | |
| 82 | + } | |
| 83 | + } | |
| 84 | + | |
| 51 | 85 | // 填充统计数据(根据extra中的statisticKey配置) |
| 52 | 86 | // appModuleService.fillModuleStatistics(list, userId); |
| 53 | - | |
| 87 | + | |
| 54 | 88 | // 转换为 VO 列表并构建树 |
| 55 | 89 | List<AppModuleVO> modules = AppModuleConvert.INSTANCE.convertAppList(list); |
| 56 | 90 | List<AppModuleVO> moduleTree = buildModuleTree(modules); |
| 57 | - | |
| 91 | + | |
| 58 | 92 | // MapStruct 转换已通过 @AfterMapping 自动填充 statisticCount |
| 59 | - | |
| 93 | + | |
| 60 | 94 | return success(moduleTree); |
| 61 | 95 | } |
| 62 | 96 | ... | ... |
urbanops-module-workorder/src/main/java/com/zteits/urbanops/module/workorder/controller/admin/maininfo/MainInfoController.java
| ... | ... | @@ -197,8 +197,21 @@ public class MainInfoController { |
| 197 | 197 | |
| 198 | 198 | Map<String, BpmUserSimpleReqDTO> bpmTaskRespVOS = bpmTaskApi.getLastTaskMapByProcessInstanceId(processInstanceIdList); |
| 199 | 199 | |
| 200 | - // 5. 转换并返回结果 | |
| 201 | - return success(MainInfoConvert.INSTANCE.buildMainInfoPage(pageResult, attachmentMap, bpmTaskRespVOS)); | |
| 200 | + // 5. 查询单位名称 | |
| 201 | + Map<Long, String> companyNameMap = pageResult.getList().stream() | |
| 202 | + .map(MainInfoDO::getCompanyId) | |
| 203 | + .filter(Objects::nonNull) | |
| 204 | + .distinct() | |
| 205 | + .collect(Collectors.toMap( | |
| 206 | + companyId -> companyId, | |
| 207 | + companyId -> { | |
| 208 | + DeptDO dept = deptService.getDept(companyId); | |
| 209 | + return dept != null ? dept.getName() : ""; | |
| 210 | + } | |
| 211 | + )); | |
| 212 | + | |
| 213 | + // 6. 转换并返回结果 | |
| 214 | + return success(MainInfoConvert.INSTANCE.buildMainInfoPage(pageResult, attachmentMap, bpmTaskRespVOS, companyNameMap)); | |
| 202 | 215 | } |
| 203 | 216 | |
| 204 | 217 | @GetMapping("/export-excel") | ... | ... |
urbanops-module-workorder/src/main/java/com/zteits/urbanops/module/workorder/convert/maininfo/MainInfoConvert.java
| ... | ... | @@ -25,7 +25,7 @@ public interface MainInfoConvert { |
| 25 | 25 | |
| 26 | 26 | MainInfoConvert INSTANCE = Mappers.getMapper(MainInfoConvert.class); |
| 27 | 27 | |
| 28 | - default PageResult<AdminMainInfoRespVO> buildMainInfoPage(PageResult<MainInfoDO> pageResult, Map<String, AttachmentDO> attachmentMap, Map<String, BpmUserSimpleReqDTO> bpmTaskRespVOS ) { | |
| 28 | + default PageResult<AdminMainInfoRespVO> buildMainInfoPage(PageResult<MainInfoDO> pageResult, Map<String, AttachmentDO> attachmentMap, Map<String, BpmUserSimpleReqDTO> bpmTaskRespVOS, Map<Long, String> companyNameMap) { | |
| 29 | 29 | List<AdminMainInfoRespVO> mainInfoVOList = CollectionUtils.convertList(pageResult.getList(), mainInfoDO -> { |
| 30 | 30 | AdminMainInfoRespVO mainInfoVo = BeanUtils.toBean(mainInfoDO, AdminMainInfoRespVO.class); |
| 31 | 31 | if (attachmentMap != null && !attachmentMap.isEmpty()) { |
| ... | ... | @@ -48,6 +48,9 @@ public interface MainInfoConvert { |
| 48 | 48 | } |
| 49 | 49 | } |
| 50 | 50 | } |
| 51 | + if (companyNameMap != null && mainInfoDO.getCompanyId() != null) { | |
| 52 | + mainInfoVo.setCompanyName(companyNameMap.getOrDefault(mainInfoDO.getCompanyId(), "")); | |
| 53 | + } | |
| 51 | 54 | return mainInfoVo; |
| 52 | 55 | }); |
| 53 | 56 | return new PageResult<>(mainInfoVOList, pageResult.getTotal()); | ... | ... |
urbanops-server/src/main/resources/application-dev.yaml
| ... | ... | @@ -251,7 +251,7 @@ wechat: |
| 251 | 251 | tokenUrl: https://api.weixin.qq.com/cgi-bin/stable_token |
| 252 | 252 | sendUrl: https://api.weixin.qq.com/cgi-bin/message/template/send |
| 253 | 253 | siot: |
| 254 | - roadUrl: https://iot.jichengshanshui.com.cn:28202/prod-api/fence/fenceInfo/getFenceRoadListByLocation | |
| 254 | + roadUrl: https://test.jichengshanshui.com.cn:28202/prod-api/fence/fenceInfo/getFenceRoadListByLocation | |
| 255 | 255 | |
| 256 | 256 | # 高德地图配置 |
| 257 | 257 | amap: | ... | ... |