From 1e1aa5872de5f5e5f1a04aa29813836fc058b68d Mon Sep 17 00:00:00 2001 From: Your Name Date: Mon, 5 Jan 2026 17:47:00 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=B8=BA=E4=BB=BB=E5=8A=A1=E5=AD=90?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E5=A2=9E=E5=8A=A0=E7=88=B6=E5=AD=90=E5=B1=82?= =?UTF-8?q?=E7=BA=A7=E5=85=B3=E7=B3=BB=E5=92=8C=E5=8D=95=E4=BB=B7=E5=88=86?= =?UTF-8?q?=E5=80=BC=E5=AD=97=E6=AE=B5=EF=BC=8C=E6=94=AF=E6=8C=81=E9=9C=80?= =?UTF-8?q?=E6=B1=82=E7=B1=BB=E5=9E=8B=E5=A4=A7=E5=88=86=E7=B1=BB=E7=AD=9B?= =?UTF-8?q?=E9=80=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/TaskSubTypeController.java | 24 +++ .../com/designhub/entity/TaskSubType.java | 42 ++++ .../designhub/service/TaskSubTypeService.java | 81 ++++++++ frontend/src/api/config.ts | 32 +++ frontend/src/views/Settings.vue | 191 ++++++++++++++---- 5 files changed, 332 insertions(+), 38 deletions(-) diff --git a/backend/src/main/java/com/designhub/controller/TaskSubTypeController.java b/backend/src/main/java/com/designhub/controller/TaskSubTypeController.java index b03bef0..adca708 100644 --- a/backend/src/main/java/com/designhub/controller/TaskSubTypeController.java +++ b/backend/src/main/java/com/designhub/controller/TaskSubTypeController.java @@ -78,4 +78,28 @@ public class TaskSubTypeController { taskSubTypeService.updateSortOrder(id, sortOrder); return Result.success(); } + + @Operation(summary = "获取树形结构列表(父子层级)") + @GetMapping("/tree") + public Result> getTreeList() { + return Result.success(taskSubTypeService.getTreeList()); + } + + @Operation(summary = "获取启用的树形结构") + @GetMapping("/tree/enabled") + public Result> getEnabledTreeList() { + return Result.success(taskSubTypeService.getEnabledTreeList()); + } + + @Operation(summary = "获取父级分类列表(需求类型大分类)") + @GetMapping("/parents") + public Result> getParentSubTypes() { + return Result.success(taskSubTypeService.getParentSubTypes()); + } + + @Operation(summary = "获取指定父级下的子分类") + @GetMapping("/children/{parentId}") + public Result> getChildrenByParentId(@PathVariable Long parentId) { + return Result.success(taskSubTypeService.getChildrenByParentId(parentId)); + } } diff --git a/backend/src/main/java/com/designhub/entity/TaskSubType.java b/backend/src/main/java/com/designhub/entity/TaskSubType.java index c30bfe8..9ca8dc4 100644 --- a/backend/src/main/java/com/designhub/entity/TaskSubType.java +++ b/backend/src/main/java/com/designhub/entity/TaskSubType.java @@ -4,7 +4,9 @@ import com.baomidou.mybatisplus.annotation.*; import lombok.Data; import java.io.Serializable; +import java.math.BigDecimal; import java.time.LocalDateTime; +import java.util.List; /** * 任务子类型实体 @@ -20,6 +22,11 @@ public class TaskSubType implements Serializable { @TableId(type = IdType.AUTO) private Long id; + /** + * 父级ID,NULL表示顶级分类(需求类型大分类) + */ + private Long parentId; + /** * 子类型名称 */ @@ -35,6 +42,11 @@ public class TaskSubType implements Serializable { */ private String description; + /** + * 单价分值 + */ + private BigDecimal unitPrice; + /** * 排序 */ @@ -51,6 +63,12 @@ public class TaskSubType implements Serializable { */ private Integer checkInventory; + /** + * 子分类列表(非数据库字段) + */ + @TableField(exist = false) + private List children; + /** * 创建时间 */ @@ -135,4 +153,28 @@ public class TaskSubType implements Serializable { public void setUpdateTime(LocalDateTime updateTime) { this.updateTime = updateTime; } + + public Long getParentId() { + return parentId; + } + + public void setParentId(Long parentId) { + this.parentId = parentId; + } + + public BigDecimal getUnitPrice() { + return unitPrice; + } + + public void setUnitPrice(BigDecimal unitPrice) { + this.unitPrice = unitPrice; + } + + public List getChildren() { + return children; + } + + public void setChildren(List children) { + this.children = children; + } } diff --git a/backend/src/main/java/com/designhub/service/TaskSubTypeService.java b/backend/src/main/java/com/designhub/service/TaskSubTypeService.java index 74cb851..2c96132 100644 --- a/backend/src/main/java/com/designhub/service/TaskSubTypeService.java +++ b/backend/src/main/java/com/designhub/service/TaskSubTypeService.java @@ -10,7 +10,10 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; /** * 任务子类型服务 @@ -142,4 +145,82 @@ public class TaskSubTypeService { subType.setSortOrder(sortOrder); taskSubTypeMapper.updateById(subType); } + + /** + * 获取树形结构的子类型列表 + * 返回父子层级结构,便于前端展示和筛选 + */ + public List getTreeList() { + List allSubTypes = taskSubTypeMapper.selectList( + new LambdaQueryWrapper() + .orderByAsc(TaskSubType::getSortOrder) + ); + + // 找出所有顶级分类(parentId为null) + List parents = allSubTypes.stream() + .filter(st -> st.getParentId() == null) + .collect(Collectors.toList()); + + // 按parentId分组子分类 + Map> childrenMap = allSubTypes.stream() + .filter(st -> st.getParentId() != null) + .collect(Collectors.groupingBy(TaskSubType::getParentId)); + + // 为每个父分类设置子分类 + for (TaskSubType parent : parents) { + parent.setChildren(childrenMap.getOrDefault(parent.getId(), new ArrayList<>())); + } + + return parents; + } + + /** + * 获取所有父级分类(需求类型大分类) + */ + public List getParentSubTypes() { + return taskSubTypeMapper.selectList( + new LambdaQueryWrapper() + .isNull(TaskSubType::getParentId) + .orderByAsc(TaskSubType::getSortOrder) + ); + } + + /** + * 获取指定父级下的子分类 + */ + public List getChildrenByParentId(Long parentId) { + return taskSubTypeMapper.selectList( + new LambdaQueryWrapper() + .eq(TaskSubType::getParentId, parentId) + .orderByAsc(TaskSubType::getSortOrder) + ); + } + + /** + * 获取启用的树形结构 + */ + public List getEnabledTreeList() { + List allSubTypes = taskSubTypeMapper.selectList( + new LambdaQueryWrapper() + .eq(TaskSubType::getIsEnabled, 1) + .orderByAsc(TaskSubType::getSortOrder) + ); + + // 找出所有顶级分类(parentId为null) + List parents = allSubTypes.stream() + .filter(st -> st.getParentId() == null) + .collect(Collectors.toList()); + + // 按parentId分组子分类 + Map> childrenMap = allSubTypes.stream() + .filter(st -> st.getParentId() != null) + .collect(Collectors.groupingBy(TaskSubType::getParentId)); + + // 为每个父分类设置子分类 + for (TaskSubType parent : parents) { + parent.setChildren(childrenMap.getOrDefault(parent.getId(), new ArrayList<>())); + } + + return parents; + } } diff --git a/frontend/src/api/config.ts b/frontend/src/api/config.ts index eea7764..66f9a4d 100644 --- a/frontend/src/api/config.ts +++ b/frontend/src/api/config.ts @@ -63,13 +63,17 @@ export interface TeamScorePool { export interface TaskSubType { id: number + parentId?: number | null // 父级ID,null表示顶级分类 name: string code: string description?: string + unitPrice?: number // 单价分值 sortOrder?: number isEnabled?: number + checkInventory?: number // 是否检查库存 createTime?: string updateTime?: string + children?: TaskSubType[] // 子分类列表 } /** @@ -311,3 +315,31 @@ export const toggleTaskSubTypeEnabled = (id: number) => { return request.post(`/task-sub-types/${id}/toggle-enabled`) } +/** + * 获取树形结构的任务子类型(父子层级) + */ +export const getTaskSubTypeTree = () => { + return request.get('/task-sub-types/tree') +} + +/** + * 获取启用的树形结构 + */ +export const getEnabledTaskSubTypeTree = () => { + return request.get('/task-sub-types/tree/enabled') +} + +/** + * 获取父级分类列表(需求类型大分类) + */ +export const getTaskSubTypeParents = () => { + return request.get('/task-sub-types/parents') +} + +/** + * 获取指定父级下的子分类 + */ +export const getTaskSubTypeChildren = (parentId: number) => { + return request.get(`/task-sub-types/children/${parentId}`) +} + diff --git a/frontend/src/views/Settings.vue b/frontend/src/views/Settings.vue index 99c29e0..f12eaf7 100644 --- a/frontend/src/views/Settings.vue +++ b/frontend/src/views/Settings.vue @@ -136,21 +136,47 @@

任务子类型管理

- - - 添加子类型 - + + + 全部类型 + + {{ p.name }} + + + + + 添加大分类 + + + + 添加子类型 + +