服务申请

This commit is contained in:
Wenchao Gong 2021-09-09 11:14:46 +08:00
parent b3a9ad0af5
commit fea697a6a9
4 changed files with 141 additions and 40 deletions

View File

@ -1,11 +1,15 @@
package com.ruoyi.common.utils;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.lang.tree.parser.NodeParser;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import java.util.List;
import java.util.stream.Collectors;
/**
* 树结构工具类
@ -13,18 +17,116 @@ import java.util.List;
* @author Wenchao Gong
* @date 2021-09-08
*/
public class TreeUtils {
public class TreeUtils
{
public static final TreeNodeConfig DEFAULT_TREE_NODE_CONFIG = new TreeNodeConfig();
public static final long DEFAULT_PARENT_ID = 0L;
public static final String FIELD_NODE_EXIST = "exist";
static
{
static {
DEFAULT_TREE_NODE_CONFIG.setNameKey("label");
}
/**
* 设置默认 parentId
*
* @param list
* @param nodeParser
* @param <T>
* @return
*/
public static <T> List<Tree<Long>> build(List<T> list, NodeParser<T, Long> nodeParser)
{
Long parentId = 0L;
return TreeUtil.build(list, parentId, DEFAULT_TREE_NODE_CONFIG, nodeParser);
return TreeUtil.build(list, DEFAULT_PARENT_ID, DEFAULT_TREE_NODE_CONFIG, nodeParser);
}
/**
* 树构建
*
* @param <T> 转换的实体 为数据源里的对象类型
* @param <E> ID类型
* @param list 源数据集合
* @param parentId 最顶层父id值 一般为 0 之类
* @param nodeParser 转换器
* @param needExistField 是否需要 已存在字段
* @return List
*/
public static <T, E> List<Tree<E>> build(List<T> list, E parentId, NodeParser<T, E> nodeParser,
boolean needExistField)
{
final List<Tree<E>> treeList = CollUtil.newArrayList();
final TreeNodeConfig treeNodeConfig = DEFAULT_TREE_NODE_CONFIG;
Tree<E> tree;
for (T obj : list) {
tree = new Tree<>(treeNodeConfig);
nodeParser.parse(obj, tree);
treeList.add(tree);
}
List<Tree<E>> finalTreeList = CollUtil.newArrayList();
for (Tree<E> node : treeList) {
if (ObjectUtil.equals(parentId, node.getParentId())) {
finalTreeList.add(node);
innerBuild(treeList, node, 0, treeNodeConfig.getDeep(), needExistField);
}
}
// 内存每层已经排过了 这是最外层排序
finalTreeList = finalTreeList.stream().sorted().collect(Collectors.toList());
return finalTreeList;
}
/**
* 递归处理
*
* @param treeNodes 数据集合
* @param parentNode 当前节点
* @param deep 已递归深度
* @param maxDeep 最大递归深度 可能为null即不限制
* @param needExistField 是否需要 已存在字段
*/
private static <T> void innerBuild(List<Tree<T>> treeNodes, Tree<T> parentNode, int deep, Integer maxDeep,
boolean needExistField)
{
if (CollUtil.isEmpty(treeNodes)) {
return;
}
//maxDeep 可能为空
if (maxDeep != null && deep >= maxDeep) {
return;
}
// 每层排序 TreeNodeMap 实现了Comparable接口
treeNodes = treeNodes.stream().sorted().collect(Collectors.toList());
for (Tree<T> childNode : treeNodes) {
if (parentNode.getId().equals(childNode.getParentId())) {
List<Tree<T>> children = parentNode.getChildren();
if (children == null) {
children = CollUtil.newArrayList();
parentNode.setChildren(children);
}
children.add(childNode);
childNode.setParent(parentNode);
if (needExistField) {
Object pobj = parentNode.get(FIELD_NODE_EXIST);
boolean exist = pobj == null ? true : (boolean) pobj;
if (exist && !CollectionUtils.isEmpty(children)) {
long count = children.stream().filter(t -> {
Object obj = t.get(FIELD_NODE_EXIST);
if (obj != null) {
return !(boolean) obj;
} else {
return false;
}
}).count();
if (count > 0) {
exist = false;
}
}
parentNode.put(FIELD_NODE_EXIST, exist);
}
innerBuild(treeNodes, childNode, deep + 1, maxDeep, needExistField);
}
}
}
}

View File

@ -3,21 +3,22 @@ package com.ruoyi.isc.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.parser.NodeParser;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
import com.ruoyi.common.utils.FullPathUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.TreeUtils;
import com.ruoyi.isc.domain.IscService;
import org.springframework.stereotype.Service;
import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.isc.domain.IscServiceCate;
import com.ruoyi.isc.domain.bo.IscServiceCateBo;
import com.ruoyi.isc.domain.vo.IscServiceCateVo;
import com.ruoyi.isc.domain.IscServiceCate;
import com.ruoyi.isc.mapper.IscServiceCateMapper;
import com.ruoyi.isc.service.IIscServiceCateService;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;
@ -35,7 +36,6 @@ public class IscServiceCateServiceImpl extends ServicePlusImpl<IscServiceCateMap
public static final String FIELD_NODE_TYPE = "type";
public static final int NODE_TYPE_SERVICE = 1;
public static final int NODE_TYPE_CATE = 0;
public static final String FIELD_NODE_EXIST = "exist";
@Override
public IscServiceCateVo queryById(Long cateId){
@ -158,7 +158,7 @@ public class IscServiceCateServiceImpl extends ServicePlusImpl<IscServiceCateMap
final Map<String, List<IscService>> cateServiceMap = isServiceTree ? serviceList.stream()
.collect(Collectors.groupingBy(IscService::getCateFullPath)) : null;
return TreeUtils.build(cates, (cate, tree) -> {
NodeParser<IscServiceCate, Long> parser = (cate, tree) -> {
tree.setId(cate.getCateId());
tree.setParentId(cate.getParentId());
tree.setName(cate.getCateName());
@ -166,8 +166,10 @@ public class IscServiceCateServiceImpl extends ServicePlusImpl<IscServiceCateMap
tree.putExtra(FIELD_FULL_PATH, cate.getFullPath());
if(isServiceTree) {
tree.putExtra(FIELD_NODE_TYPE, NODE_TYPE_CATE);
boolean exist = true;
List<IscService> services = cateServiceMap.get(cate.getFullPath());
if(CollectionUtil.isEmpty(services)) {
tree.putExtra(TreeUtils.FIELD_NODE_EXIST, true);
return;
}
for (int index = 0; index < services.size(); index++)
@ -182,14 +184,18 @@ public class IscServiceCateServiceImpl extends ServicePlusImpl<IscServiceCateMap
child.setId(service.getServiceId());
child.setName(service.getServiceName());
child.setWeight(index);
child.setParent(tree);
child.setParentId(tree.getId());
child.putExtra(FIELD_NODE_TYPE, NODE_TYPE_SERVICE);
child.putExtra(FIELD_NODE_EXIST, exitsIds.contains(service.getServiceId()));
boolean contains = exitsIds.contains(service.getServiceId());
child.putExtra(TreeUtils.FIELD_NODE_EXIST, contains);
children.add(child);
if(exist && !contains) {
exist = false;
}
}
tree.putExtra(TreeUtils.FIELD_NODE_EXIST, exist);
}
});
};
return TreeUtils.build(cates, TreeUtils.DEFAULT_PARENT_ID, parser, isServiceTree);
}
private Map<Long, String> batchCateName(List<IscServiceCate> list) {

View File

@ -74,7 +74,7 @@
<el-table v-loading="loading" :data="applicationList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="应用ID" align="center" prop="applicationId" v-if="true" width="50"/>
<el-table-column label="应用ID" align="center" prop="applicationId" v-if="true" width="80"/>
<el-table-column label="应用名称" align="center" prop="applicationName" >
<template slot-scope="scope">
<router-link :to="'/isc/app-service/index/' + scope.row.applicationId" class="link-type">

View File

@ -146,8 +146,10 @@
<!-- 添加或修改应用服务对话框 -->
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="服务" prop="serviceId">
<treeselect v-model="form.serviceId" :options="appServiceOptions" :show-count="true" :normalizer="normalizer" placeholder="请选择服务" style="width:215px"/>
<el-form-item label="服务名称" prop="serviceId">
<!-- :disable-branch-nodes="true" 只能选叶子节点 -->
<treeselect v-model="form.serviceId" :options="appServiceOptions" :show-count="true" :normalizer="normalizer"
:disable-branch-nodes="true" placeholder="请选择服务" style="width:215px"/>
</el-form-item>
<el-form-item label="启用状态">
<el-radio-group v-model="form.enabled">
@ -166,17 +168,17 @@
placeholder="选择到期时间">
</el-date-picker>
</el-form-item>
<el-form-item label="配额" prop="quotaDays">
<el-input v-model="form.quotaDays" placeholder="请输入天配额" />
<el-form-item label="配额" prop="quotaDays">
<el-input-number v-model="form.quotaDays" step="1000" placeholder="请输入日配额" />
</el-form-item>
<el-form-item label="小时配额" prop="quotaHours">
<el-input v-model="form.quotaHours" placeholder="请输入小时配额" />
<el-input-number v-model="form.quotaHours" step="100" placeholder="请输入小时配额" />
</el-form-item>
<el-form-item label="分钟配额" prop="quotaMinutes">
<el-input v-model="form.quotaMinutes" placeholder="请输入分钟配额" />
<el-input-number v-model="form.quotaMinutes" step="10" placeholder="请输入分钟配额" />
</el-form-item>
<el-form-item label="秒配额" prop="quotaSeconds">
<el-input v-model="form.quotaSeconds" placeholder="请输入秒配额" />
<el-input-number v-model="form.quotaSeconds" placeholder="请输入秒配额" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
@ -231,11 +233,12 @@ export default {
queryParams: {
pageNum: 1,
pageSize: 10,
applicationId: undefined,
enabled: undefined,
status: undefined,
applicationId: undefined
},
applicationName: undefined,
applicationId: undefined,
//
form: {},
//
@ -243,9 +246,6 @@ export default {
serviceId: [
{ required: true, message: "服务ID不能为空", trigger: "blur" }
],
applicationId: [
{ required: true, message: "应用ID不能为空", trigger: "blur" }
],
enabled: [
{ required: true, message: "启用状态不能为空", trigger: "blur" }
],
@ -254,7 +254,7 @@ export default {
},
created() {
const applicationId = this.$route.params && this.$route.params.applicationId;
this.form.applicationId = applicationId;
this.applicationId = applicationId;
this.queryParams.applicationId = applicationId;
this.getList(applicationId);
this.getDicts("sys_normal_disable").then(response => {
@ -293,14 +293,13 @@ export default {
},
//
normalizer(node) {
const data = {
return {
id: node.id,
label: node.label,
children: node.children,
disabled: true
}
console.log(data)
return
isDisabled: node.exist,
type: node.type
};
},
//
cancel() {
@ -316,17 +315,11 @@ export default {
enabled: "0",
applyType: undefined,
status: [],
virtualAddr: undefined,
endTime: undefined,
quotaDays: undefined,
quotaHours: undefined,
quotaMinutes: undefined,
quotaSeconds: undefined,
createBy: undefined,
createTime: undefined,
updateBy: undefined,
updateTime: undefined,
delFlag: undefined
};
this.resetForm("form");
},