diff --git a/.gitignore b/.gitignore index e625a99..4bf7246 100644 --- a/.gitignore +++ b/.gitignore @@ -53,3 +53,15 @@ application-my.yaml /urbanops-ui-app/unpackage/ **/.DS_Store old/ +/.claudeignore +/docs/all_test.html +/docs/ppt-assets/animations.css +/docs/ppt-assets/base.css +/CLAUDE.md +/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/enums/ErrorCodeConstants_手动操作.java +/docs/ppt-assets/fonts.css +/docs/ppt-assets/runtime.js +/.claude/settings.local.json +/docs/ppt-assets/style.css +/docs/urbanops-architecture-ppt.html +/docs/urbanops-tech-sharing.html diff --git a/sql/mysql/garden_problem_type-fix.sql b/sql/mysql/garden_problem_type-fix.sql new file mode 100644 index 0000000..a7c5d85 --- /dev/null +++ b/sql/mysql/garden_problem_type-fix.sql @@ -0,0 +1,35 @@ +-- ================================================= +-- garden_problem_type 表结构补全 +-- 原因:BaseDO 包含 create_time/update_time/creator/updater/deleted +-- MyBatis Plus @TableLogic 自动 WHERE deleted=0 +-- 缺少这些列会导致 SQL 报错或无数据返回 +-- ================================================= + +-- 如果表已存在数据,先备份 +-- CREATE TABLE garden_problem_type_bak AS SELECT * FROM garden_problem_type; + +-- 方案1:删表重建(无重要数据时) +DROP TABLE IF EXISTS `garden_problem_type`; +CREATE TABLE `garden_problem_type` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `type_code` varchar(32) NOT NULL COMMENT '问题类型编码', + `type_name` varchar(64) NOT NULL COMMENT '问题类型名称', + `level` tinyint NOT NULL COMMENT '层级:1一级 2二级 3三级', + `parent_code` varchar(32) DEFAULT NULL COMMENT '父级类型编码', + `sort` int DEFAULT 0 COMMENT '排序序号', + `status` tinyint DEFAULT 1 COMMENT '状态 1启用 0禁用', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` tinyint NOT NULL DEFAULT 0 COMMENT '逻辑删除 0正常 1删除', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_type_code` (`type_code`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='问题类型三级分类表'; + +-- 方案2:已有数据时,用 ALTER 补齐缺失列(按需执行) +-- ALTER TABLE garden_problem_type ADD COLUMN `creator` varchar(64) DEFAULT '' COMMENT '创建者' AFTER `status`; +-- ALTER TABLE garden_problem_type ADD COLUMN `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间' AFTER `creator`; +-- ALTER TABLE garden_problem_type ADD COLUMN `updater` varchar(64) DEFAULT '' COMMENT '更新者' AFTER `create_time`; +-- ALTER TABLE garden_problem_type ADD COLUMN `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间' AFTER `updater`; +-- ALTER TABLE garden_problem_type ADD COLUMN `deleted` tinyint NOT NULL DEFAULT 0 COMMENT '逻辑删除' AFTER `update_time`; diff --git a/sql/mysql/problem-type-menu-auto.sql b/sql/mysql/problem-type-menu-auto.sql new file mode 100644 index 0000000..05a0766 --- /dev/null +++ b/sql/mysql/problem-type-menu-auto.sql @@ -0,0 +1,33 @@ +-- ================================================= +-- 问题类型配置 - 菜单与权限 SQL(自动查找父菜单ID) +-- 直接执行即可,自动从「工单管理」下挂载菜单 +-- ================================================= + +-- 查询当前最大 ID 作为起始值 +SET @maxId = (SELECT IFNULL(MAX(id), 5000) FROM system_menu); + +-- 查询工单管理 菜单ID +SET @parentId = (SELECT id FROM system_menu WHERE name = '工单管理' AND type = 1 LIMIT 1); + +-- 如果找不到工单管理,尝试匹配 workorder 关键字 +-- SET @parentId = (SELECT id FROM system_menu WHERE (name LIKE '%工单%' OR path LIKE '%workorder%') AND type = 1 LIMIT 1); + +-- 1. 二级菜单:问题类型 +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`) +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'); + +-- 2. 按钮:查询 +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`) +VALUES (@maxId + 2, '问题类型查询', 'garden:problem-type:query', 3, 1, @maxId + 1, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'); + +-- 3. 按钮:创建 +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`) +VALUES (@maxId + 3, '问题类型创建', 'garden:problem-type:create', 3, 2, @maxId + 1, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'); + +-- 4. 按钮:更新 +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`) +VALUES (@maxId + 4, '问题类型更新', 'garden:problem-type:update', 3, 3, @maxId + 1, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'); + +-- 5. 按钮:删除 +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`) +VALUES (@maxId + 5, '问题类型删除', 'garden:problem-type:delete', 3, 4, @maxId + 1, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'); diff --git a/sql/mysql/problem-type-menu.sql b/sql/mysql/problem-type-menu.sql new file mode 100644 index 0000000..c2b59f5 --- /dev/null +++ b/sql/mysql/problem-type-menu.sql @@ -0,0 +1,35 @@ +-- ================================================= +-- 问题类型配置 - 菜单与权限 SQL +-- 说明: +-- 1. 请先查询「工单管理」的菜单 ID,替换下面 @parentId 为实际值 +-- 查询语句:SELECT id FROM system_menu WHERE name = '工单管理' AND type = 1; +-- 2. 修改下面 @menuId 为可用的起始 ID(确保不与已有菜单 ID 冲突) +-- 查询最大ID:SELECT MAX(id) FROM system_menu; +-- 3. 执行前请备份 system_menu 表 +-- ================================================= + +-- 请根据实际情况替换以下变量值: +-- SET @parentId = (SELECT id FROM system_menu WHERE name = '工单管理' AND type = 1); +-- SET @menuId = (SELECT IFNULL(MAX(id), 0) + 1 FROM system_menu); + +-- 示例:假设工单管理 parent_id = 2000,起始 menu_id = 5100 + +-- 1. 二级菜单:问题类型 +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`) +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'); + +-- 2. 按钮权限:查询 +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`) +VALUES (@menuId + 1, '问题类型查询', 'garden:problem-type:query', 3, 1, @menuId, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'); + +-- 3. 按钮权限:创建 +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`) +VALUES (@menuId + 2, '问题类型创建', 'garden:problem-type:create', 3, 2, @menuId, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'); + +-- 4. 按钮权限:更新 +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`) +VALUES (@menuId + 3, '问题类型更新', 'garden:problem-type:update', 3, 3, @menuId, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'); + +-- 5. 按钮权限:删除 +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`) +VALUES (@menuId + 4, '问题类型删除', 'garden:problem-type:delete', 3, 4, @menuId, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'); diff --git a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/admin/costfee/CostFeeController.java b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/admin/costfee/CostFeeController.java index fee8c95..124fba1 100644 --- a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/admin/costfee/CostFeeController.java +++ b/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; import com.zteits.urbanops.module.garden.controller.admin.costfee.vo.WaterFeeImport; import com.zteits.urbanops.module.garden.enums.TemplateEnum; import com.zteits.urbanops.module.garden.service.costfee.CostFeeService; +import com.zteits.urbanops.module.system.api.dept.DeptApi; +import com.zteits.urbanops.module.system.api.dept.dto.DeptRespDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.security.PermitAll; import jakarta.servlet.http.HttpServletResponse; import lombok.AllArgsConstructor; import lombok.Data; import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.ss.util.CellRangeAddressList; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; import org.springframework.util.CollectionUtils; +import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -23,7 +31,6 @@ import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Method; import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; import java.util.*; import static com.zteits.urbanops.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST; @@ -49,6 +56,12 @@ public class CostFeeController{ @Value("${static.resource.server.enable}") private Boolean staticResourceServerenable; + @Autowired + private ResourceLoader resourceLoader; + + @jakarta.annotation.Resource + private DeptApi deptApi; + // Excel文件校验相关 private static final List ALLOWED_EXCEL_SUFFIX = Arrays.asList(".xlsx", ".xlsm"); private static final String EXCEL_MIME_TYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; @@ -59,6 +72,7 @@ public class CostFeeController{ */ @GetMapping("/get-import-template") @Operation(summary = "获得导入用户模板") + @PermitAll public void importTemplate(HttpServletResponse response, @RequestParam("templateName") String templateName) throws IOException { // 参数校验 @@ -74,29 +88,150 @@ public class CostFeeController{ return; } - if (staticResourceServerenable) { - // 构建完整的静态服务器URL(确保路径正确) - String serverUrl = staticResourceServerUrl; - if (serverUrl != null && !serverUrl.endsWith("/")) { - serverUrl += "/"; // 确保URL以/结尾,避免拼接错误 - } + writeAndModifyTemplate(response, template.getName(), template.getStartIndex()); + } + + private void writeAndModifyTemplate(HttpServletResponse response, + String downloadFileName, + int startIndexRow) throws IOException { + + // 拼接模板路径 + String serverUrl = staticResourceServerUrl; + if (serverUrl != null && !serverUrl.endsWith("/")) { + serverUrl += "/"; + } + String fullPath = serverUrl + downloadFileName; + fullPath = fullPath.replace("\\", "/"); + + Resource resource = resourceLoader.getResource(fullPath); + + // 检查文件是否存在 + if (!resource.exists()) { + response.sendError(HttpServletResponse.SC_NOT_FOUND, "模板文件不存在"); + return; + } + + // 设置下载响应头 + response.reset(); + response.setContentType(EXCEL_MIME_TYPE); + // response.setCharacterEncoding("UTF-8"); + String encodedName = URLEncoder.encode(downloadFileName, "UTF-8"); + // 标准文件名编码(Chrome / Edge / Firefox 全兼容) + response.setHeader("Content-Disposition", "attachment;filename*=UTF-8''" + encodedName); + // 浏览器缓存配置(必须) + response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); + response.setHeader("Pragma", "no-cache"); + response.setHeader("Expires", "0"); + + + try (InputStream in = resource.getInputStream(); + XSSFWorkbook workbook = new XSSFWorkbook(in); + OutputStream out = response.getOutputStream()) { - String encodedFileName = URLEncoder.encode(template.getName().split("\\.")[0], StandardCharsets.UTF_8.name()); + Sheet sheet = workbook.getSheetAt(0); - String templateFileName = encodedFileName + "." + template.getName().split("\\.")[1]; + // ============================================== + // 获取最新单位列表 + // ============================================== + List companyList = deptApi.getSubDeptList(); + List newUnits = companyList.stream() + .map(DeptRespDTO::getName) + .filter(Objects::nonNull) + .toList(); - String templateUrl = serverUrl + templateFileName; // 包含templates目录 + log.info("加载到单位列表:{},共{}条", newUnits, newUnits.size()); - // 方式1:重定向到静态资源服务器 - response.sendRedirect(templateUrl); - } else { - String templateFileName = templateName + "." + template.getName().split("\\.")[1]; + // ============================================== + // 生成新下拉 + 自动赋值 + // ============================================== + createDropdownAndSetValue(sheet, newUnits, startIndexRow); + + // 写入并强制刷新 + workbook.write(out); + out.flush(); - // 写入模板文件到响应 - writeTemplateToResponse(response, template.getName(), templateFileName); + } catch (Exception e) { + log.error("模板处理失败", e); + throw new IOException("文件处理失败", e); } } + /** + * 创建下拉框 + 给单元格赋值 + */ + private void createDropdownAndSetValue(Sheet sheet, List options, int startRow) { + if (options.isEmpty()) { + log.error("下拉选项为空,不创建"); + return; + } + + // 获取表头行 + Row headerRow = sheet.getRow(startRow - 1); + if (headerRow == null) { + log.error("表头行不存在:{}", startRow - 1); + return; + } + + // 查找“所属单位”列 + int targetCol = -1; + for (Cell cell : headerRow) { + if (cell != null && cell.getCellType() == CellType.STRING) { + String val = cell.getStringCellValue().trim(); + if (val.contains("所属单位") || val.contains("所属公司") ) { + targetCol = cell.getColumnIndex(); + break; + } + } + } + + if (targetCol == -1) { + log.error("未找到【所属单位】列表头"); + return; + } + + // 取消列隐藏 + sheet.setColumnHidden(targetCol, false); + + // ============================================== + // 遍历行:清空原有内容 + 设置默认值 + // ============================================== + int endRow = 100; + for (int r = startRow; r <= endRow; r++) { + Row row = sheet.getRow(r); + if (row == null) { + row = sheet.createRow(r); + } + + Cell cell = row.getCell(targetCol); + if (cell == null) { + cell = row.createCell(targetCol); + } + String unit = cell.getStringCellValue(); + // 默认赋值【第一个单位】,你可以根据业务改成其他值 + if (!StringUtils.isEmpty(unit)) { + cell.setCellValue(options.get(0)); + } + } + + // ============================================== + // 创建下拉框(作用范围:startRow ~ 1000行) + // ============================================== + CellRangeAddressList regions = new CellRangeAddressList(startRow, endRow, targetCol, targetCol); + DataValidationHelper helper = sheet.getDataValidationHelper(); + DataValidationConstraint constraint = helper.createExplicitListConstraint( + options.toArray(new String[0]) + ); + DataValidation validation = helper.createValidation(constraint, regions); + // 下拉框基础配置 + validation.setEmptyCellAllowed(true); + validation.setSuppressDropDownArrow(true); // 显示箭头 + validation.setShowErrorBox(true); + validation.setShowPromptBox(true); // 启用点击弹出提示 + sheet.addValidationData(validation); + + log.info("【成功】为列{}添加下拉并赋值,行{}~{},选项数:{}", + targetCol, startRow, endRow, options.size()); + } /** * Excel文件上传预览 @@ -214,31 +349,6 @@ public class CostFeeController{ } /** - * 写入模板文件到响应流 - */ - private void writeTemplateToResponse(HttpServletResponse response, String filename, String templatePath) throws IOException { - // 设置响应头 - response.setContentType(EXCEL_MIME_TYPE); - response.setCharacterEncoding("UTF-8"); - String encodedFileName = URLEncoder.encode(filename, "UTF-8").replaceAll("\\+", "%20"); - response.setHeader("Content-Disposition", "attachment;filename=" + encodedFileName); - response.setHeader("Cache-Control", "no-store"); // 禁止缓存 - - // 读取模板文件并写入响应 - try (InputStream in = new ClassPathResource("template/" + templatePath).getInputStream(); - OutputStream out = response.getOutputStream()) { - - byte[] buffer = new byte[4096]; - int bytesRead; - while ((bytesRead = in.read(buffer)) != -1) { - out.write(buffer, 0, bytesRead); - } - out.flush(); - } - } - - - /** * 校验Excel文件有效性(后缀+MIME类型) */ private boolean isValidExcelFile(MultipartFile file) { diff --git a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/admin/problemtype/GardenProblemTypeController.java b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/admin/problemtype/GardenProblemTypeController.java new file mode 100644 index 0000000..de849b9 --- /dev/null +++ b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/admin/problemtype/GardenProblemTypeController.java @@ -0,0 +1,147 @@ +package com.zteits.urbanops.module.garden.controller.admin.problemtype; + +import com.zteits.urbanops.module.garden.controller.admin.problemtype.vo.ProblemTypePageReqVO; +import com.zteits.urbanops.module.garden.controller.admin.problemtype.vo.ProblemTypeRespVO; +import com.zteits.urbanops.module.garden.controller.admin.problemtype.vo.ProblemTypeSaveReqVO; +import org.springframework.web.bind.annotation.*; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.security.access.prepost.PreAuthorize; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Operation; + +import jakarta.validation.*; +import java.util.*; + +import com.zteits.urbanops.framework.common.pojo.CommonResult; +import com.zteits.urbanops.framework.common.pojo.PageResult; +import com.zteits.urbanops.framework.common.util.object.BeanUtils; +import static com.zteits.urbanops.framework.common.pojo.CommonResult.success; + +import com.zteits.urbanops.module.garden.dal.dataobject.problemtype.GardenProblemTypeDO; +import com.zteits.urbanops.module.garden.dal.mysql.problemtype.GardenProblemTypeMapper; +import com.zteits.urbanops.module.garden.service.problemtype.GardenProblemTypeService; + +@Tag(name = "管理后台 - 问题类型配置") +@RestController +@RequestMapping("/garden/problem-type") +@Validated +public class GardenProblemTypeController { + + @Resource + private GardenProblemTypeService gardenProblemTypeService; + + @Resource + private GardenProblemTypeMapper gardenProblemTypeMapper; + + @PostMapping("/create") + @Operation(summary = "创建问题类型(二级/三级)") + @PreAuthorize("@ss.hasPermission('garden:problem-type:create')") + public CommonResult createProblemType(@Valid @RequestBody ProblemTypeSaveReqVO createReqVO) { + return success(gardenProblemTypeService.createProblemType(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新问题类型(二级/三级)") + @PreAuthorize("@ss.hasPermission('garden:problem-type:update')") + public CommonResult updateProblemType(@Valid @RequestBody ProblemTypeSaveReqVO updateReqVO) { + gardenProblemTypeService.updateProblemType(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除问题类型") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('garden:problem-type:delete')") + public CommonResult deleteProblemType(@RequestParam("id") Long id) { + gardenProblemTypeService.deleteProblemType(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得问题类型") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('garden:problem-type:query')") + public CommonResult getProblemType(@RequestParam("id") Long id) { + GardenProblemTypeDO problemType = gardenProblemTypeService.getProblemType(id); + ProblemTypeRespVO respVO = BeanUtils.toBean(problemType, ProblemTypeRespVO.class); + fillParentNames(Arrays.asList(respVO)); + return success(respVO); + } + + @GetMapping("/page") + @Operation(summary = "获得问题类型分页") + @PreAuthorize("@ss.hasPermission('garden:problem-type:query')") + public CommonResult> getProblemTypePage(@Valid ProblemTypePageReqVO pageReqVO) { + PageResult pageResult = gardenProblemTypeService.getProblemTypePage(pageReqVO); + PageResult voPageResult = BeanUtils.toBean(pageResult, ProblemTypeRespVO.class); + fillParentNames(voPageResult.getList()); + return success(voPageResult); + } + + @GetMapping("/list-by-parent") + @Operation(summary = "根据父级编码和层级查询子类型列表(级联下拉用)") + @PreAuthorize("@ss.hasPermission('garden:problem-type:query')") + public CommonResult> getProblemTypeListByParent( + @RequestParam(value = "parentCode", required = false) String parentCode, + @RequestParam("level") Integer level) { + List list = gardenProblemTypeService.getProblemTypeByParentCode(parentCode, level); + return success(BeanUtils.toBean(list, ProblemTypeRespVO.class)); + } + + @GetMapping("/generate-next-code") + @Operation(summary = "根据父级编码生成下一个类型编码") + @PreAuthorize("@ss.hasPermission('garden:problem-type:create')") + public CommonResult generateNextCode(@RequestParam("parentCode") String parentCode) { + return success(gardenProblemTypeService.generateNextCode(parentCode)); + } + + @PostMapping("/sync-level-one") + @Operation(summary = "从字典表同步一级类型") + @PreAuthorize("@ss.hasPermission('garden:problem-type:create')") + public CommonResult syncLevelOne() { + return success(gardenProblemTypeService.syncLevelOneFromDict()); + } + + /** + * 填充每个记录的层级名称: + * level 1 → levelOneName = 自身 typeName + * level 2 → levelTwoName = 自身 typeName, levelOneName = 父级 typeName + * level 3 → levelOneName = 祖父 typeName, levelTwoName = 父级 typeName + */ + private void fillParentNames(List list) { + if (list == null || list.isEmpty()) { + return; + } + for (ProblemTypeRespVO vo : list) { + if (vo.getLevel() == null) continue; + if (vo.getLevel() == 1) { + vo.setLevelOneName(vo.getTypeName()); + } else if (vo.getLevel() == 2) { + vo.setLevelTwoName(vo.getTypeName()); + if (vo.getParentCode() != null) { + GardenProblemTypeDO parent = gardenProblemTypeMapper.selectByTypeCode(vo.getParentCode()); + if (parent != null) { + vo.setLevelOneName(parent.getTypeName()); + } + } + } else if (vo.getLevel() == 3) { + if (vo.getParentCode() != null) { + GardenProblemTypeDO parent = gardenProblemTypeMapper.selectByTypeCode(vo.getParentCode()); + if (parent != null) { + vo.setLevelTwoName(parent.getTypeName()); + if (parent.getParentCode() != null) { + GardenProblemTypeDO grandParent = gardenProblemTypeMapper + .selectByTypeCode(parent.getParentCode()); + if (grandParent != null) { + vo.setLevelOneName(grandParent.getTypeName()); + } + } + } + } + } + } + } + +} diff --git a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/admin/problemtype/vo/ProblemTypePageReqVO.java b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/admin/problemtype/vo/ProblemTypePageReqVO.java new file mode 100644 index 0000000..3110603 --- /dev/null +++ b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/admin/problemtype/vo/ProblemTypePageReqVO.java @@ -0,0 +1,29 @@ +package com.zteits.urbanops.module.garden.controller.admin.problemtype.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import com.zteits.urbanops.framework.common.pojo.PageParam; + +@Schema(description = "管理后台 - 问题类型分页 Request VO") +@Data +public class ProblemTypePageReqVO extends PageParam { + + @Schema(description = "问题类型编码", example = "PT001") + private String typeCode; + + @Schema(description = "问题类型名称", example = "树木倒伏") + private String typeName; + + @Schema(description = "层级:1一级 2二级 3三级", example = "2") + private Integer level; + + @Schema(description = "父级类型编码", example = "BIZ_GARDEN") + private String parentCode; + + @Schema(description = "一级类型编码(级联筛选)", example = "yl") + private String levelOneCode; + + @Schema(description = "状态 1启用 0禁用", example = "1") + private Integer status; + +} diff --git a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/admin/problemtype/vo/ProblemTypeRespVO.java b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/admin/problemtype/vo/ProblemTypeRespVO.java new file mode 100644 index 0000000..2638443 --- /dev/null +++ b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/admin/problemtype/vo/ProblemTypeRespVO.java @@ -0,0 +1,54 @@ +package com.zteits.urbanops.module.garden.controller.admin.problemtype.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import cn.idev.excel.annotation.*; + +@Schema(description = "管理后台 - 问题类型 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ProblemTypeRespVO { + + @Schema(description = "主键ID", example = "1") + @ExcelProperty("主键ID") + private Long id; + + @Schema(description = "问题类型编码", example = "PT001") + @ExcelProperty("问题类型编码") + private String typeCode; + + @Schema(description = "问题类型名称", example = "树木倒伏") + @ExcelProperty("问题类型名称") + private String typeName; + + @Schema(description = "层级:1一级 2二级 3三级", example = "2") + @ExcelProperty("层级") + private Integer level; + + @Schema(description = "父级类型编码", example = "BIZ_GARDEN") + @ExcelProperty("父级类型编码") + private String parentCode; + + @Schema(description = "排序序号", example = "1") + @ExcelProperty("排序序号") + private Integer sort; + + @Schema(description = "状态 1启用 0禁用", example = "1") + @ExcelProperty("状态") + private Integer status; + + @Schema(description = "一级类型名称") + private String levelOneName; + + @Schema(description = "二级类型名称") + private String levelTwoName; + + @Schema(description = "创建者") + @ExcelProperty("创建者") + private String creator; + + @Schema(description = "创建时间") + @ExcelProperty("创建时间") + private String createTime; + +} diff --git a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/admin/problemtype/vo/ProblemTypeSaveReqVO.java b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/admin/problemtype/vo/ProblemTypeSaveReqVO.java new file mode 100644 index 0000000..8d785e1 --- /dev/null +++ b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/admin/problemtype/vo/ProblemTypeSaveReqVO.java @@ -0,0 +1,36 @@ +package com.zteits.urbanops.module.garden.controller.admin.problemtype.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import jakarta.validation.constraints.*; + +@Schema(description = "管理后台 - 问题类型新增/修改 Request VO") +@Data +public class ProblemTypeSaveReqVO { + + @Schema(description = "主键ID", example = "1") + private Long id; + + @Schema(description = "问题类型编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "PT001") + @NotEmpty(message = "问题类型编码不能为空") + private String typeCode; + + @Schema(description = "问题类型名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "树木倒伏") + @NotEmpty(message = "问题类型名称不能为空") + private String typeName; + + @Schema(description = "层级:1一级 2二级 3三级", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @NotNull(message = "层级不能为空") + private Integer level; + + @Schema(description = "父级类型编码", example = "BIZ_GARDEN") + private String parentCode; + + @Schema(description = "排序序号", example = "1") + private Integer sort; + + @Schema(description = "状态 1启用 0禁用", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "状态不能为空") + private Integer status; + +} diff --git a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/convert/AppGardenWorkOrderConvert.java b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/convert/AppGardenWorkOrderConvert.java index 956ce17..2410fd9 100644 --- a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/convert/AppGardenWorkOrderConvert.java +++ b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/convert/AppGardenWorkOrderConvert.java @@ -24,7 +24,7 @@ public interface AppGardenWorkOrderConvert { orderReqVO.setPressingType(2);//紧急 orderReqVO.setOrderName(inspectionPlanDO.getPlanName()); orderReqVO.setSourceId(1);//来源ID 工单来源 1、巡查 - orderReqVO.setSourceName("园林巡查上报"); + orderReqVO.setSourceName("巡查上报"); orderReqVO.setThirdWorkNo(planNo); orderReqVO.setOrderType("C"); orderReqVO.setPressingType(createReqVO.getPressingType()); diff --git a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/dal/dataobject/problemtype/GardenProblemTypeDO.java b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/dal/dataobject/problemtype/GardenProblemTypeDO.java new file mode 100644 index 0000000..dc4a53b --- /dev/null +++ b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/dal/dataobject/problemtype/GardenProblemTypeDO.java @@ -0,0 +1,52 @@ +package com.zteits.urbanops.module.garden.dal.dataobject.problemtype; + +import lombok.*; +import com.baomidou.mybatisplus.annotation.*; +import com.zteits.urbanops.framework.mybatis.core.dataobject.BaseDO; + +/** + * 问题类型三级分类 DO + * + * @author 超级管理员 + */ +@TableName("garden_problem_type") +@KeySequence("garden_problem_type_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class GardenProblemTypeDO extends BaseDO { + + /** + * 主键ID + */ + @TableId + private Long id; + /** + * 问题类型编码 + */ + private String typeCode; + /** + * 问题类型名称 + */ + private String typeName; + /** + * 层级:1一级 2二级 3三级 + */ + private Integer level; + /** + * 父级类型编码 + */ + private String parentCode; + /** + * 排序序号 + */ + private Integer sort; + /** + * 状态 1启用 0禁用 + */ + private Integer status; + +} diff --git a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/dal/mysql/problemtype/GardenProblemTypeMapper.java b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/dal/mysql/problemtype/GardenProblemTypeMapper.java new file mode 100644 index 0000000..8805a5a --- /dev/null +++ b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/dal/mysql/problemtype/GardenProblemTypeMapper.java @@ -0,0 +1,87 @@ +package com.zteits.urbanops.module.garden.dal.mysql.problemtype; + +import com.zteits.urbanops.framework.common.pojo.PageResult; +import com.zteits.urbanops.framework.mybatis.core.query.LambdaQueryWrapperX; +import com.zteits.urbanops.framework.mybatis.core.mapper.BaseMapperX; +import com.zteits.urbanops.module.garden.controller.admin.problemtype.vo.ProblemTypePageReqVO; +import com.zteits.urbanops.module.garden.dal.dataobject.problemtype.GardenProblemTypeDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 问题类型 Mapper + * + * @author 超级管理员 + */ +@Mapper +public interface GardenProblemTypeMapper extends BaseMapperX { + + default PageResult selectPage(ProblemTypePageReqVO reqVO) { + LambdaQueryWrapperX wrapper = new LambdaQueryWrapperX() + .eqIfPresent(GardenProblemTypeDO::getLevel, reqVO.getLevel()) + .eqIfPresent(GardenProblemTypeDO::getStatus, reqVO.getStatus()) + .likeIfPresent(GardenProblemTypeDO::getTypeName, reqVO.getTypeName()) + .likeIfPresent(GardenProblemTypeDO::getTypeCode, reqVO.getTypeCode()); + wrapper.orderByAsc(GardenProblemTypeDO::getSort); + wrapper.orderByAsc(GardenProblemTypeDO::getId); + + // 级联筛选:如果传了 levelOneCode,查出所有二级编码做 IN 查询 + if (reqVO.getLevelOneCode() != null && !reqVO.getLevelOneCode().isEmpty()) { + List levelTwoList = selectByParentCodeAndLevel(reqVO.getLevelOneCode(), 2); + List parentCodes = new ArrayList<>(); + parentCodes.add(reqVO.getLevelOneCode()); // 包含一级自身 + parentCodes.addAll(levelTwoList.stream().map(GardenProblemTypeDO::getTypeCode).collect(Collectors.toList())); + wrapper.in(GardenProblemTypeDO::getParentCode, parentCodes); + } else { + wrapper.eqIfPresent(GardenProblemTypeDO::getParentCode, reqVO.getParentCode()); + } + + return selectPage(reqVO, wrapper); + } + + /** + * 根据 parentCode 和 level 查询子类型列表 + */ + default List selectByParentCodeAndLevel(String parentCode, Integer level) { + return selectList(new LambdaQueryWrapperX() + .eqIfPresent(GardenProblemTypeDO::getParentCode, parentCode) + .eqIfPresent(GardenProblemTypeDO::getLevel, level) + .eq(GardenProblemTypeDO::getStatus, 1) + .orderByAsc(GardenProblemTypeDO::getSort) + .orderByAsc(GardenProblemTypeDO::getId)); + } + + /** + * 根据 typeCode 查询唯一记录 + */ + default GardenProblemTypeDO selectByTypeCode(String typeCode) { + return selectOne(new LambdaQueryWrapperX() + .eq(GardenProblemTypeDO::getTypeCode, typeCode)); + } + + /** + * 生成下一个编码:父级编码 + 5位递增序号 + * 如 parentCode=BIZ_GARDEN → BIZ_GARDEN00001, BIZ_GARDEN00002 + */ + default String generateNextCode(String parentCode) { + List list = selectList(new LambdaQueryWrapperX() + .likeRight(GardenProblemTypeDO::getTypeCode, parentCode) + .orderByDesc(GardenProblemTypeDO::getTypeCode) + .last("LIMIT 1")); + if (list == null || list.isEmpty()) { + return parentCode + "00001"; + } + String maxCode = list.get(0).getTypeCode(); + String seqStr = maxCode.substring(parentCode.length()); + try { + int seq = Integer.parseInt(seqStr) + 1; + return parentCode + String.format("%05d", seq); + } catch (NumberFormatException e) { + return parentCode + "00001"; + } + } + +} diff --git a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/enums/ErrorCodeConstants.java b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/enums/ErrorCodeConstants.java index ffb070e..5cb7aa7 100644 --- a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/enums/ErrorCodeConstants.java +++ b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/enums/ErrorCodeConstants.java @@ -87,9 +87,11 @@ public interface ErrorCodeConstants { ErrorCode INSPECTION_CYCLE_ERROR = new ErrorCode(1-200-100-003, "获取两个时间之间间隔天数错误"); ErrorCode INSPECTION_PLAN_EXISTS = new ErrorCode(1-200-100-007, "道路对应类型已存在记录"); ErrorCode INSPECTION_PLAN_NOT_ALLOW_DELETE = new ErrorCode(1-100-007-005, "计划已开始执行不能删除"); + ErrorCode INSPECTION_COMMIT_PLAN__EXISTS = new ErrorCode(1-100-007-005, "巡检计划明细已提交"); // ========== 养护计划汇总 TODO 补充编号 ========== ErrorCode MAINTAIN_PLAN_NOT_EXISTS = new ErrorCode(1-100-007-001, "养护计划汇总不存在"); + ErrorCode MAINTAIN_COMMIT_PLAN__EXISTS = new ErrorCode(1-100-007-007, "养护计划明细已提交"); //========== 频次 TODO 补充编号 ========== ErrorCode PLAN_RATE_EXISTS = new ErrorCode(1-100-007-001, "养护频次已存在"); @@ -145,4 +147,8 @@ public interface ErrorCodeConstants { ErrorCode EMERGENCY_TASK_NOT_EXISTS = new ErrorCode(1-100-006-002, "抢险任务主不存在"); + // ========== 问题类型配置 1-100-009-000 ========== + ErrorCode PROBLEM_TYPE_NOT_EXISTS = new ErrorCode(1100009000, "问题类型不存在"); + ErrorCode PROBLEM_TYPE_CODE_EXISTS = new ErrorCode(1100009001, "问题类型编码已存在"); + } diff --git a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/inspectionplan/InspectionPlanCommitServiceImpl.java b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/inspectionplan/InspectionPlanCommitServiceImpl.java index c45842f..09c5102 100644 --- a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/inspectionplan/InspectionPlanCommitServiceImpl.java +++ b/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; import com.zteits.urbanops.module.garden.dal.dataobject.inspectionplan.InspectionPlanCommitDO; import com.zteits.urbanops.module.garden.dal.dataobject.inspectionplan.InspectionPlanDO; import com.zteits.urbanops.module.garden.dal.dataobject.inspectionplan.InspectionPlanDetailDO; +import com.zteits.urbanops.module.garden.dal.dataobject.maintainplan.MaintainPlanCommitDO; import com.zteits.urbanops.module.garden.dal.dataobject.road.RoadDO; import com.zteits.urbanops.module.garden.dal.mysql.inspectionplan.InspectionPlanCommitMapper; import com.zteits.urbanops.module.garden.dal.mysql.inspectionplan.InspectionPlanDetailMapper; @@ -43,7 +44,7 @@ import java.util.*; import java.util.stream.Collectors; import static com.zteits.urbanops.framework.common.exception.util.ServiceExceptionUtil.exception; -import static com.zteits.urbanops.module.garden.enums.ErrorCodeConstants.INSPECTION_PLAN_NOT_EXISTS; +import static com.zteits.urbanops.module.garden.enums.ErrorCodeConstants.*; /** @@ -76,6 +77,10 @@ public class InspectionPlanCommitServiceImpl implements InspectionPlanCommitServ @Override public Long createInspectionPlanCommit(InspectionPlanCommitSaveReqVO createReqVO) { + List list = inspectionPlanCommitMapper.selectList(InspectionPlanCommitDO::getPlanNo, createReqVO.getPlanNo()); + if(!CollectionUtils.isEmpty(list)){ + throw exception(INSPECTION_COMMIT_PLAN__EXISTS); + } // 插入 InspectionPlanCommitDO inspectionPlanCommit = BeanUtils.toBean(createReqVO, InspectionPlanCommitDO.class); inspectionPlanCommitMapper.insert(inspectionPlanCommit); diff --git a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/maintainplan/MaintainPlanCommitServiceImpl.java b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/maintainplan/MaintainPlanCommitServiceImpl.java index 24e9e74..57674a0 100644 --- a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/maintainplan/MaintainPlanCommitServiceImpl.java +++ b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/maintainplan/MaintainPlanCommitServiceImpl.java @@ -63,6 +63,10 @@ public class MaintainPlanCommitServiceImpl implements MaintainPlanCommitService @Override public Long createMaintainPlanCommit(MaintainPlanCommitSaveReqVO createReqVO) { + List list = maintainPlanCommitMapper.selectList(MaintainPlanCommitDO::getPlanNo, createReqVO.getPlanNo()); + if(!CollectionUtils.isEmpty(list)){ + throw exception(MAINTAIN_PLAN_NOT_EXISTS); + } // 插入 MaintainPlanCommitDO maintainPlanCommit = BeanUtils.toBean(createReqVO, MaintainPlanCommitDO.class); maintainPlanCommitMapper.insert(maintainPlanCommit); diff --git a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/problemtype/GardenProblemTypeService.java b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/problemtype/GardenProblemTypeService.java new file mode 100644 index 0000000..3c3bcc7 --- /dev/null +++ b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/problemtype/GardenProblemTypeService.java @@ -0,0 +1,80 @@ +package com.zteits.urbanops.module.garden.service.problemtype; + +import com.zteits.urbanops.module.garden.controller.admin.problemtype.vo.ProblemTypePageReqVO; +import com.zteits.urbanops.module.garden.controller.admin.problemtype.vo.ProblemTypeSaveReqVO; +import com.zteits.urbanops.module.garden.dal.dataobject.problemtype.GardenProblemTypeDO; +import com.zteits.urbanops.framework.common.pojo.PageResult; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * 问题类型配置 Service 接口 + * + * @author 超级管理员 + */ +public interface GardenProblemTypeService { + + /** + * 创建问题类型 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createProblemType(@Valid ProblemTypeSaveReqVO createReqVO); + + /** + * 更新问题类型 + * + * @param updateReqVO 更新信息 + */ + void updateProblemType(@Valid ProblemTypeSaveReqVO updateReqVO); + + /** + * 删除问题类型 + * + * @param id 编号 + */ + void deleteProblemType(Long id); + + /** + * 获得问题类型 + * + * @param id 编号 + * @return 问题类型 + */ + GardenProblemTypeDO getProblemType(Long id); + + /** + * 获得问题类型分页 + * + * @param pageReqVO 分页查询 + * @return 问题类型分页 + */ + PageResult getProblemTypePage(ProblemTypePageReqVO pageReqVO); + + /** + * 根据父级编码和层级查询子类型列表 + * + * @param parentCode 父级编码 + * @param level 层级 + * @return 子类型列表 + */ + List getProblemTypeByParentCode(String parentCode, Integer level); + + /** + * 根据父级编码生成下一个类型编码 + * + * @param parentCode 父级编码 + * @return 新编码 + */ + String generateNextCode(String parentCode); + + /** + * 从字典表同步一级类型到 garden_problem_type + * + * @return 同步数量 + */ + int syncLevelOneFromDict(); + +} diff --git a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/problemtype/GardenProblemTypeServiceImpl.java b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/problemtype/GardenProblemTypeServiceImpl.java new file mode 100644 index 0000000..89e4928 --- /dev/null +++ b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/problemtype/GardenProblemTypeServiceImpl.java @@ -0,0 +1,122 @@ +package com.zteits.urbanops.module.garden.service.problemtype; + +import com.zteits.urbanops.framework.common.enums.CommonStatusEnum; +import com.zteits.urbanops.module.garden.controller.admin.problemtype.vo.ProblemTypePageReqVO; +import com.zteits.urbanops.module.garden.controller.admin.problemtype.vo.ProblemTypeSaveReqVO; +import com.zteits.urbanops.module.system.dal.dataobject.dict.DictDataDO; +import com.zteits.urbanops.module.system.service.dict.DictDataService; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; +import jakarta.annotation.Resource; + +import java.util.List; + +import com.zteits.urbanops.module.garden.dal.dataobject.problemtype.GardenProblemTypeDO; +import com.zteits.urbanops.framework.common.pojo.PageResult; +import com.zteits.urbanops.framework.common.util.object.BeanUtils; + +import com.zteits.urbanops.module.garden.dal.mysql.problemtype.GardenProblemTypeMapper; + +import static com.zteits.urbanops.framework.common.exception.util.ServiceExceptionUtil.exception; +import static com.zteits.urbanops.module.garden.enums.ErrorCodeConstants.*; + +/** + * 问题类型配置 Service 实现类 + * + * @author 超级管理员 + */ +@Service +@Validated +public class GardenProblemTypeServiceImpl implements GardenProblemTypeService { + + @Resource + private GardenProblemTypeMapper gardenProblemTypeMapper; + + @Resource + private DictDataService dictDataService; + + @Override + public Long createProblemType(ProblemTypeSaveReqVO createReqVO) { + // 校验编码唯一性 + validateTypeCodeUnique(createReqVO.getTypeCode(), null); + // 插入 + GardenProblemTypeDO problemType = BeanUtils.toBean(createReqVO, GardenProblemTypeDO.class); + gardenProblemTypeMapper.insert(problemType); + return problemType.getId(); + } + + @Override + public void updateProblemType(ProblemTypeSaveReqVO updateReqVO) { + // 校验存在 + validateProblemTypeExists(updateReqVO.getId()); + // 校验编码唯一性(排除自身) + validateTypeCodeUnique(updateReqVO.getTypeCode(), updateReqVO.getId()); + // 更新 + GardenProblemTypeDO updateObj = BeanUtils.toBean(updateReqVO, GardenProblemTypeDO.class); + gardenProblemTypeMapper.updateById(updateObj); + } + + @Override + public void deleteProblemType(Long id) { + // 校验存在 + validateProblemTypeExists(id); + // 删除 + gardenProblemTypeMapper.deleteById(id); + } + + private void validateProblemTypeExists(Long id) { + if (gardenProblemTypeMapper.selectById(id) == null) { + throw exception(PROBLEM_TYPE_NOT_EXISTS); + } + } + + private void validateTypeCodeUnique(String typeCode, Long excludeId) { + GardenProblemTypeDO exist = gardenProblemTypeMapper.selectByTypeCode(typeCode); + if (exist != null && (excludeId == null || !exist.getId().equals(excludeId))) { + throw exception(PROBLEM_TYPE_CODE_EXISTS); + } + } + + @Override + public GardenProblemTypeDO getProblemType(Long id) { + return gardenProblemTypeMapper.selectById(id); + } + + @Override + public PageResult getProblemTypePage(ProblemTypePageReqVO pageReqVO) { + return gardenProblemTypeMapper.selectPage(pageReqVO); + } + + @Override + public List getProblemTypeByParentCode(String parentCode, Integer level) { + return gardenProblemTypeMapper.selectByParentCodeAndLevel(parentCode, level); + } + + @Override + public String generateNextCode(String parentCode) { + return gardenProblemTypeMapper.generateNextCode(parentCode); + } + + @Override + public int syncLevelOneFromDict() { + List dictList = dictDataService.getDictDataList( + CommonStatusEnum.ENABLE.getStatus(), "business_line"); + int count = 0; + for (DictDataDO dict : dictList) { + GardenProblemTypeDO exist = gardenProblemTypeMapper.selectByTypeCode(dict.getValue()); + if (exist == null) { + GardenProblemTypeDO entity = new GardenProblemTypeDO(); + entity.setTypeCode(dict.getValue()); + entity.setTypeName(dict.getLabel()); + entity.setLevel(1); + entity.setParentCode(null); + entity.setSort(dict.getSort()); + entity.setStatus(CommonStatusEnum.ENABLE.getStatus()); + gardenProblemTypeMapper.insert(entity); + count++; + } + } + return count; + } + +} diff --git a/urbanops-module-garden/src/main/resources/mapper/inspectionplan/InspectionPlanCommitMapper.xml b/urbanops-module-garden/src/main/resources/mapper/inspectionplan/InspectionPlanCommitMapper.xml index b959dd4..87e2091 100644 --- a/urbanops-module-garden/src/main/resources/mapper/inspectionplan/InspectionPlanCommitMapper.xml +++ b/urbanops-module-garden/src/main/resources/mapper/inspectionplan/InspectionPlanCommitMapper.xml @@ -102,7 +102,7 @@ - order by a.id desc + order by a.create_time desc