Commit 61400ba4cb2c869a4fc86d21a34092d3c59f55ef

Authored by 王彪总
1 parent 441f44f7

config(servers): 更新服务器配置中的域名地址

- 将 IoT 设备主机地址从 jichengshanshui.com.cn 更改为 fangshanparking.com
- 更新应用配置中多个 API 接口的域名地址
- 修改 SSO 单点登录相关 URL 配置
- 更新微信公众号接口调用地址
- 替换资源服务器下载链接域名
- 修改生产环境社交登录回调地址
- 更新 UAA 认证服务器基础 URL
- 替换 JustAuth 第三方认证源的授权地址
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 +}
... ...
urbanops-server/src/main/resources/application.yaml
... ... @@ -3,7 +3,7 @@ spring:
3 3 name: urbanops-server
4 4  
5 5 profiles:
6   - active: prod
  6 + active: dev
7 7  
8 8  
9 9 main:
... ...