Commit 61400ba4cb2c869a4fc86d21a34092d3c59f55ef
1 parent
441f44f7
config(servers): 更新服务器配置中的域名地址
- 将 IoT 设备主机地址从 jichengshanshui.com.cn 更改为 fangshanparking.com - 更新应用配置中多个 API 接口的域名地址 - 修改 SSO 单点登录相关 URL 配置 - 更新微信公众号接口调用地址 - 替换资源服务器下载链接域名 - 修改生产环境社交登录回调地址 - 更新 UAA 认证服务器基础 URL - 替换 JustAuth 第三方认证源的授权地址
Showing
13 changed files
with
715 additions
and
1 deletions
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/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/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
| ... | ... | @@ -147,4 +147,8 @@ public interface ErrorCodeConstants { |
| 147 | 147 | |
| 148 | 148 | ErrorCode EMERGENCY_TASK_NOT_EXISTS = new ErrorCode(1-100-006-002, "抢险任务主不存在"); |
| 149 | 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 | + | |
| 150 | 154 | } | ... | ... |
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 | +} | ... | ... |