diff --git a/cutejava-front/src/api/system/component.js b/cutejava-front/src/api/system/component.js new file mode 100644 index 00000000..9dfd9147 --- /dev/null +++ b/cutejava-front/src/api/system/component.js @@ -0,0 +1,8 @@ +import request from '@/utils/request' + +export function queryDeptSelectDataSource() { + return request({ + url: 'api/component/queryDeptSelectDataSource', + method: 'post' + }) +} diff --git a/cutejava-front/src/views/components/business/CuteProductLineSelect.vue b/cutejava-front/src/views/components/business/CuteProductLineSelect.vue new file mode 100644 index 00000000..42cddb89 --- /dev/null +++ b/cutejava-front/src/views/components/business/CuteProductLineSelect.vue @@ -0,0 +1,75 @@ + + + + diff --git a/cutejava-front/src/views/componentsDemo/CuteBusinessDemo.vue b/cutejava-front/src/views/componentsDemo/CuteBusinessDemo.vue index 2d07a507..e6b1cbaa 100644 --- a/cutejava-front/src/views/componentsDemo/CuteBusinessDemo.vue +++ b/cutejava-front/src/views/componentsDemo/CuteBusinessDemo.vue @@ -12,9 +12,13 @@ + + + - 立即创建 - 取消 + 提 交 + 重 置 + 取 消 @@ -30,6 +34,12 @@ + +
+ 产品线选择框 +
+ +
@@ -37,31 +47,49 @@ import CuteUserSelect from '@/views/components/business/CuteUserSelect.vue' import CuteDeptTree from '@/views/components/business/CuteDeptTree.vue' +import CuteProductLineSelect from '@/views/components/business/CuteProductLineSelect.vue' export default { name: 'CuteBusinessDemo', - components: { CuteDeptTree, CuteUserSelect }, + components: { CuteProductLineSelect, CuteDeptTree, CuteUserSelect }, data() { return { form: { user: null, - dept: null + dept: null, + productLine: null } } }, methods: { onUserSelectChange(data) { - console.error('onUserSelectChange=', data) + console.log('onUserSelectChange=', data) }, onDeptTreeNodeClick(data) { - console.error('onDeptTreeNodeClick=', data) + console.log('onDeptTreeNodeClick=', data) }, - onSubmit() { - console.error('this.form=', this.form) + onSubmit(formName) { + this.$refs[formName].validate((valid) => { + if (valid) { + console.log('this.form=', this.form) + } else { + console.error('error submit!!') + return false + } + }) + }, + onReset(formName) { + this.$refs[formName].resetFields() }, onDeptTreeSearch(key) { - console.error('onDeptTreeSearch:key', key) - console.error('onDeptTreeSearch:form.dept', this.form.dept) + console.log('onDeptTreeSearch:key', key) + console.log('onDeptTreeSearch:form.dept', this.form.dept) + }, + onProductLineChange(data) { + console.log('onProductLineChange', data) + }, + onProductLineDetailChange(data) { + console.log('onProductLineDetailChange', data) } } } diff --git a/cutejava-front/src/views/componentsDemo/CutePipelineNodeDemo.vue b/cutejava-front/src/views/componentsDemo/CutePipelineNodeDemo.vue index 70262e4a..97f6e07e 100644 --- a/cutejava-front/src/views/componentsDemo/CutePipelineNodeDemo.vue +++ b/cutejava-front/src/views/componentsDemo/CutePipelineNodeDemo.vue @@ -545,9 +545,9 @@ export default { handleWebSocketMessage(e) { const that = this const data = e.data - // console.error('来自服务器的数据:data', data) + // console.log('来自服务器的数据:data', data) const callbackData = JSON.parse(data) - // console.error('callbackData', callbackData) + // console.log('callbackData', callbackData) try { that.dynamicInstance = JSON.parse(callbackData.data) // 判断流水线是否结束 @@ -607,9 +607,9 @@ export default { id: that.dynamicTemplate.id } try { - if (that.dynamicHook) { - clearInterval(that.dynamicHook) - } + // if (that.dynamicHook) { + // clearInterval(that.dynamicHook) + // } that.dynamicStartButtonLoading = true // 这里的 dynamicStartupStatus状态,需要后期与上下文关联后,初始化的时候带入最近一个流水线实例 // let result diff --git a/cutejava/cutejava-framework/src/main/java/cn/odboy/base/CsSelectOptionItemVo.java b/cutejava/cutejava-framework/src/main/java/cn/odboy/base/CsSelectOptionVo.java similarity index 94% rename from cutejava/cutejava-framework/src/main/java/cn/odboy/base/CsSelectOptionItemVo.java rename to cutejava/cutejava-framework/src/main/java/cn/odboy/base/CsSelectOptionVo.java index ff6041a5..11e67d4d 100644 --- a/cutejava/cutejava-framework/src/main/java/cn/odboy/base/CsSelectOptionItemVo.java +++ b/cutejava/cutejava-framework/src/main/java/cn/odboy/base/CsSelectOptionVo.java @@ -30,7 +30,7 @@ import java.util.Map; @AllArgsConstructor @NoArgsConstructor @EqualsAndHashCode(callSuper = false) -public class CsSelectOptionItemVo extends CsObject { +public class CsSelectOptionVo extends CsObject { private String label; private String value; private Map ext; diff --git a/cutejava/cutejava-framework/src/main/java/cn/odboy/util/CsCollUtil.java b/cutejava/cutejava-framework/src/main/java/cn/odboy/util/CsCollUtil.java index 9f9e0726..710d7609 100644 --- a/cutejava/cutejava-framework/src/main/java/cn/odboy/util/CsCollUtil.java +++ b/cutejava/cutejava-framework/src/main/java/cn/odboy/util/CsCollUtil.java @@ -15,7 +15,7 @@ */ package cn.odboy.util; -import cn.odboy.base.CsSelectOptionItemVo; +import cn.odboy.base.CsSelectOptionVo; import com.alibaba.fastjson2.JSON; import lombok.experimental.UtilityClass; @@ -197,22 +197,22 @@ public final class CsCollUtil extends cn.hutool.core.collection.CollUtil { } public static void main(String[] args) { - List testData = new ArrayList<>(); - CsSelectOptionItemVo selectOption1 = CsSelectOptionItemVo.builder().label("苹果").value("apple").build(); - CsSelectOptionItemVo selectOption2 = CsSelectOptionItemVo.builder().label("苹果").value("apple").build(); - CsSelectOptionItemVo selectOption3 = CsSelectOptionItemVo.builder().label("香蕉").value("banana").build(); - CsSelectOptionItemVo selectOption4 = CsSelectOptionItemVo.builder().label("猫").value("cat").build(); + List testData = new ArrayList<>(); + CsSelectOptionVo selectOption1 = CsSelectOptionVo.builder().label("苹果").value("apple").build(); + CsSelectOptionVo selectOption2 = CsSelectOptionVo.builder().label("苹果").value("apple").build(); + CsSelectOptionVo selectOption3 = CsSelectOptionVo.builder().label("香蕉").value("banana").build(); + CsSelectOptionVo selectOption4 = CsSelectOptionVo.builder().label("猫").value("cat").build(); testData.add(selectOption1); testData.add(selectOption2); testData.add(selectOption3); testData.add(selectOption4); - List selectOptions1 = CsCollUtil.streamAscSort(testData, CsSelectOptionItemVo::getValue); + List selectOptions1 = CsCollUtil.streamAscSort(testData, CsSelectOptionVo::getValue); System.out.println(JSON.toJSONString(selectOptions1)); - List selectOptions2 = CsCollUtil.streamDescSort(testData, CsSelectOptionItemVo::getValue); + List selectOptions2 = CsCollUtil.streamDescSort(testData, CsSelectOptionVo::getValue); System.out.println(JSON.toJSONString(selectOptions2)); - List selectOptions3 = CsCollUtil.streamDistinct(testData, CsSelectOptionItemVo::getValue); + List selectOptions3 = CsCollUtil.streamDistinct(testData, CsSelectOptionVo::getValue); System.out.println(JSON.toJSONString(selectOptions3)); - Map selectMap1 = CsCollUtil.streamToMap(testData, CsSelectOptionItemVo::getValue, CsSelectOptionItemVo::getLabel); + Map selectMap1 = CsCollUtil.streamToMap(testData, CsSelectOptionVo::getValue, CsSelectOptionVo::getLabel); System.out.println(JSON.toJSONString(selectMap1)); // 这只是一个示范 BigDecimal total1 = CsCollUtil.streamBigDecimalAdd(testData, "value"); diff --git a/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/controller/SystemComponentController.java b/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/controller/SystemComponentController.java new file mode 100644 index 00000000..104d17ac --- /dev/null +++ b/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/controller/SystemComponentController.java @@ -0,0 +1,27 @@ +package cn.odboy.system.controller; + +import cn.odboy.system.service.SystemDeptService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +@Api(tags = "系统:组件数据源") +@RequestMapping("/api/component") +public class SystemComponentController { + private final SystemDeptService systemDeptService; + + @ApiOperation("查询部门下拉选择数据源") + @PostMapping(value = "/queryDeptSelectDataSource") + @PreAuthorize("@el.check()") + public ResponseEntity queryDeptSelectDataSource() { + return new ResponseEntity<>(systemDeptService.queryDeptSelectDataSource(), HttpStatus.OK); + } +} diff --git a/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/controller/SystemUserController.java b/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/controller/SystemUserController.java index e09cd743..3648adf2 100644 --- a/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/controller/SystemUserController.java +++ b/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/controller/SystemUserController.java @@ -3,7 +3,7 @@ package cn.odboy.system.controller; import cn.hutool.core.collection.CollectionUtil; import cn.odboy.base.CsPageArgs; import cn.odboy.base.CsResultVo; -import cn.odboy.base.CsSelectOptionItemVo; +import cn.odboy.base.CsSelectOptionVo; import cn.odboy.framework.exception.BadRequestException; import cn.odboy.framework.properties.AppProperties; import cn.odboy.system.constant.SystemCaptchaBizEnum; @@ -190,7 +190,7 @@ public class SystemUserController { @ApiOperation("查询用户基础数据") @PostMapping(value = "/queryUserMetadataOptions") @PreAuthorize("@el.check('user:list')") - public ResponseEntity> queryUserMetadataOptions(@Validated @RequestBody CsPageArgs args) { + public ResponseEntity> queryUserMetadataOptions(@Validated @RequestBody CsPageArgs args) { int maxPageSize = 50; SystemQueryUserArgs criteria = args.getArgs(); LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); @@ -210,7 +210,7 @@ public class SystemUserController { ext.put("deptId", m.getDeptId()); ext.put("email", m.getEmail()); ext.put("phone", m.getPhone()); - return CsSelectOptionItemVo.builder() + return CsSelectOptionVo.builder() .label(m.getNickName()) .value(m.getUsername()) .ext(ext) diff --git a/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/dal/model/SystemProductLineVo.java b/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/dal/model/SystemProductLineVo.java new file mode 100644 index 00000000..92ff5cc5 --- /dev/null +++ b/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/dal/model/SystemProductLineVo.java @@ -0,0 +1,22 @@ +package cn.odboy.system.dal.model; + +import cn.odboy.base.CsObject; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class SystemProductLineVo extends CsObject { + /** + * 部门ID(select的value) + */ + private Long value; + /** + * 产品线,如"研发部/华南分部/devops组" + */ + private String label; + /** + * ID路径,如"1-2-3" + */ + private String idPath; +} diff --git a/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/service/SystemDeptService.java b/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/service/SystemDeptService.java index 57acb103..9fb60e7b 100644 --- a/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/service/SystemDeptService.java +++ b/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/service/SystemDeptService.java @@ -9,6 +9,7 @@ import cn.odboy.framework.exception.BadRequestException; import cn.odboy.system.constant.SystemDataScopeEnum; import cn.odboy.system.dal.dataobject.SystemDeptTb; import cn.odboy.system.dal.model.SystemCreateDeptArgs; +import cn.odboy.system.dal.model.SystemProductLineVo; import cn.odboy.system.dal.model.SystemQueryDeptArgs; import cn.odboy.system.dal.mysql.SystemDeptMapper; import cn.odboy.system.dal.mysql.SystemRoleMapper; @@ -17,6 +18,7 @@ import cn.odboy.system.framework.permission.core.CsSecurityHelper; import cn.odboy.util.ClassUtil; import cn.odboy.util.FileUtil; import cn.odboy.util.StringUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -25,6 +27,7 @@ import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.lang.reflect.Field; import java.util.*; +import java.util.function.Function; import java.util.stream.Collectors; @Service @@ -339,4 +342,59 @@ public class SystemDeptService { } return depts; } + + public List queryDeptSelectDataSource() { + List depts = findEnabledDepts(); + return buildDeptSelectOptions(depts); + } + + private List buildDeptSelectOptions(List depts) { + // 获取所有部门并按父子关系组织 + Map deptMap = depts.stream().collect(Collectors.toMap(SystemDeptTb::getId, Function.identity())); + List options = new ArrayList<>(); + for (SystemDeptTb dept : depts) { + // 构建部门ID路径 + List pathIds = new ArrayList<>(); + buildDeptIdPath(dept, deptMap, pathIds); + + // 反转路径,从顶级部门到当前部门 + Collections.reverse(pathIds); + + SystemProductLineVo dto = new SystemProductLineVo(); + dto.setValue(dept.getId()); + dto.setIdPath(pathIds.stream().map(String::valueOf).collect(Collectors.joining("-"))); + dto.setLabel(buildNamePath(dept, deptMap)); // 保留名称路径用于显示 + + options.add(dto); + } + + // 按部门名称路径排序 + options.sort(Comparator.comparing(SystemProductLineVo::getLabel)); + return options; + } + + private void buildDeptIdPath(SystemDeptTb dept, Map deptMap, List pathIds) { + pathIds.add(dept.getId()); + if (dept.getPid() != null && dept.getPid() != 0 && deptMap.containsKey(dept.getPid())) { + buildDeptIdPath(deptMap.get(dept.getPid()), deptMap, pathIds); + } + } + + private String buildNamePath(SystemDeptTb dept, Map deptMap) { + List pathNames = new ArrayList<>(); + buildDeptNamePath(dept, deptMap, pathNames); + Collections.reverse(pathNames); + return String.join("/", pathNames); + } + + private void buildDeptNamePath(SystemDeptTb dept, Map deptMap, List pathNames) { + pathNames.add(dept.getName()); + if (dept.getPid() != null && dept.getPid() != 0 && deptMap.containsKey(dept.getPid())) { + buildDeptNamePath(deptMap.get(dept.getPid()), deptMap, pathNames); + } + } + + private List findEnabledDepts() { + return systemDeptMapper.selectList(new LambdaQueryWrapper().eq(SystemDeptTb::getEnabled, 1)); + } }