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/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/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 71e7aab..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 @@ -147,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/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-server/src/main/resources/application.yaml b/urbanops-server/src/main/resources/application.yaml index 2c7c342..e5f485b 100644 --- a/urbanops-server/src/main/resources/application.yaml +++ b/urbanops-server/src/main/resources/application.yaml @@ -3,7 +3,7 @@ spring: name: urbanops-server profiles: - active: prod + active: dev main: