添加应用服务树结构

This commit is contained in:
wenchaogong 2021-09-08 23:51:31 +08:00
parent bb02108ab0
commit b3a9ad0af5
14 changed files with 265 additions and 64 deletions

View File

@ -5,6 +5,9 @@ public class IscConstants {
/** 待审核 */
public static final String AUDIT_WAIT = "0";
/** 审核通过 */
public static final String AUDIT_PASS = "1";
/** 待审核 */
public static final String ONLINE_STATUS_ON = "1";

View File

@ -4,6 +4,8 @@ import java.util.List;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import cn.hutool.core.lang.tree.Tree;
import com.ruoyi.isc.domain.IscServiceCate;
import lombok.RequiredArgsConstructor;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.*;
@ -40,7 +42,7 @@ import io.swagger.annotations.ApiOperation;
@RequestMapping("/isc/appservice")
public class IscAppServiceController extends BaseController {
private final IIscAppServiceService iIscAppServiceService;
private final IIscAppServiceService appServiceService;
/**
* 查询应用服务列表
@ -49,7 +51,7 @@ public class IscAppServiceController extends BaseController {
@PreAuthorize("@ss.hasPermi('isc:appservice:list')")
@GetMapping("/list")
public TableDataInfo<IscAppServiceVo> list(@Validated(QueryGroup.class) IscAppServiceBo bo) {
return iIscAppServiceService.queryPageList(bo);
return appServiceService.queryPageList(bo);
}
/**
@ -60,7 +62,7 @@ public class IscAppServiceController extends BaseController {
@Log(title = "应用服务", businessType = BusinessType.EXPORT)
@GetMapping("/export")
public void export(@Validated IscAppServiceBo bo, HttpServletResponse response) {
List<IscAppServiceVo> list = iIscAppServiceService.queryList(bo);
List<IscAppServiceVo> list = appServiceService.queryList(bo);
ExcelUtil.exportExcel(list, "应用服务", IscAppServiceVo.class, response);
}
@ -72,7 +74,7 @@ public class IscAppServiceController extends BaseController {
@GetMapping("/{serviceAppId}")
public AjaxResult<IscAppServiceVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable("serviceAppId") Long serviceAppId) {
return AjaxResult.success(iIscAppServiceService.queryById(serviceAppId));
return AjaxResult.success(appServiceService.queryById(serviceAppId));
}
/**
@ -84,7 +86,7 @@ public class IscAppServiceController extends BaseController {
@RepeatSubmit()
@PostMapping()
public AjaxResult<Void> add(@Validated(AddGroup.class) @RequestBody IscAppServiceBo bo) {
return toAjax(iIscAppServiceService.insertByBo(bo) ? 1 : 0);
return toAjax(appServiceService.insertByBo(bo) ? 1 : 0);
}
/**
@ -96,7 +98,7 @@ public class IscAppServiceController extends BaseController {
@RepeatSubmit()
@PutMapping()
public AjaxResult<Void> edit(@Validated(EditGroup.class) @RequestBody IscAppServiceBo bo) {
return toAjax(iIscAppServiceService.updateByBo(bo) ? 1 : 0);
return toAjax(appServiceService.updateByBo(bo) ? 1 : 0);
}
/**
@ -108,6 +110,16 @@ public class IscAppServiceController extends BaseController {
@DeleteMapping("/{serviceAppIds}")
public AjaxResult<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] serviceAppIds) {
return toAjax(iIscAppServiceService.deleteWithValidByIds(Arrays.asList(serviceAppIds), true) ? 1 : 0);
return toAjax(appServiceService.deleteWithValidByIds(Arrays.asList(serviceAppIds), true) ? 1 : 0);
}
/**
* 获取应用服务下拉树列表
*/
@GetMapping("/treeselect/{applicationId}")
@ApiOperation("获取应用服务下拉树列表")
public AjaxResult<List<Tree<Long>>> treeselect(@NotNull(message = "应用主键不能为空") @PathVariable Long applicationId)
{
return AjaxResult.success(appServiceService.genAppServiceTree(applicationId));
}
}

View File

@ -64,16 +64,11 @@ public class IscServiceCateController extends BaseController {
* 获取分类下拉树列表
*/
@GetMapping("/treeselect")
public AjaxResult treeselect()
@ApiOperation("获取分类下拉树列表")
public AjaxResult<List<Tree<Long>>> treeselect()
{
List<IscServiceCate> cates = cateService.selectCateList();
return AjaxResult.success(TreeUtils.build(cates, (cate, tree) -> {
tree.setId(cate.getCateId());
tree.setParentId(cate.getParentId());
tree.setName(cate.getCateName());
tree.setWeight(cate.getOrderNum());
tree.putExtra("fullPath", cate.getFullPath());
}));
return AjaxResult.success(cateService.genCateTree(cates));
}
/**

View File

@ -46,12 +46,6 @@ public class IscAppServiceBo extends BaseEntity {
@NotNull(message = "应用ID不能为空", groups = { AddGroup.class, EditGroup.class })
private Long applicationId;
/**
* 用户ID
*/
@ApiModelProperty(value = "用户ID")
private Long userId;
/**
* 启用状态0启用 1停用
*/

View File

@ -34,10 +34,16 @@ public class IscAppServiceVo {
/**
* 服务ID
*/
@ExcelProperty(value = "服务ID")
@ApiModelProperty("服务ID")
private Long serviceId;
/**
* 服务名称
*/
@ExcelProperty(value = "服务名称")
@ApiModelProperty("服务名称")
private String serviceName;
/**
* 应用ID
*/

View File

@ -1,5 +1,6 @@
package com.ruoyi.isc.service;
import cn.hutool.core.lang.tree.Tree;
import com.ruoyi.isc.domain.IscAppService;
import com.ruoyi.isc.domain.vo.IscAppServiceVo;
import com.ruoyi.isc.domain.bo.IscAppServiceBo;
@ -53,4 +54,11 @@ public interface IIscAppServiceService extends IServicePlus<IscAppService, IscAp
* @return
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
/**
* 构造 应用服务树结构
* @param applicationId 应用ID
* @return 应用服务树结构 标识服务是否存在
*/
List<Tree<Long>> genAppServiceTree(Long applicationId);
}

View File

@ -1,10 +1,11 @@
package com.ruoyi.isc.service;
import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.isc.domain.IscServiceCate;
import com.ruoyi.isc.domain.vo.IscServiceCateVo;
import com.ruoyi.isc.domain.bo.IscServiceCateBo;
import cn.hutool.core.lang.tree.Tree;
import com.ruoyi.common.core.mybatisplus.core.IServicePlus;
import com.ruoyi.isc.domain.IscService;
import com.ruoyi.isc.domain.IscServiceCate;
import com.ruoyi.isc.domain.bo.IscServiceCateBo;
import com.ruoyi.isc.domain.vo.IscServiceCateVo;
import java.util.Collection;
import java.util.List;
@ -64,4 +65,20 @@ public interface IIscServiceCateService extends IServicePlus<IscServiceCate, Isc
* @return
*/
Map<String, String> batchCateName(Set<String> fullPathList);
/**
* 组装 服务分类 树结构
* @param cates 所有分类
* @return 树结构信息
*/
List<Tree<Long>> genCateTree(List<IscServiceCate> cates);
/**
* 组装 服务分类 树结构
* @param cates 所有分类
* @param serviceList 可用服务列表
* @param exitsIds 已存在服务ID集合
* @return 树结构信息
*/
List<Tree<Long>> genCateTree(List<IscServiceCate> cates, List<IscService> serviceList, Set<Long> exitsIds);
}

View File

@ -1,13 +1,17 @@
package com.ruoyi.isc.service;
import com.ruoyi.isc.domain.IscService;
import com.ruoyi.isc.domain.vo.IscServiceVo;
import com.ruoyi.isc.domain.bo.IscServiceBo;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import com.ruoyi.common.core.mybatisplus.core.IServicePlus;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.isc.domain.IscService;
import com.ruoyi.isc.domain.bo.IscServiceBo;
import com.ruoyi.isc.domain.vo.IscServiceVo;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* 服务信息Service接口
@ -53,4 +57,24 @@ public interface IIscServiceService extends IServicePlus<IscService, IscServiceV
* @return
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
/**
* 通过服务ID集合 查询服务名称map
* @param serviceIds 服务ID集合
* @return 服务名称map
*/
Map<Long, String> getNameMap(Collection<Long> serviceIds);
/**
* 组装 服务树结构
* @return 服务树结构
*/
List<Tree<Long>> genServiceTree();
/**
* 组装 服务树结构
* @param exitsIds 已存在服务ID集合
* @return 服务树结构
*/
List<Tree<Long>> genServiceTree(Set<Long> exitsIds);
}

View File

@ -1,10 +1,15 @@
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 com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.common.core.page.PagePlus;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.isc.domain.IscService;
import com.ruoyi.isc.service.IIscServiceService;
import org.springframework.stereotype.Service;
import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@ -15,9 +20,12 @@ import com.ruoyi.isc.domain.IscAppService;
import com.ruoyi.isc.mapper.IscAppServiceMapper;
import com.ruoyi.isc.service.IIscAppServiceService;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.Set;
import java.util.stream.Collectors;
/**
* 应用服务Service业务层处理
@ -28,6 +36,8 @@ import java.util.Collection;
@Service
public class IscAppServiceServiceImpl extends ServicePlusImpl<IscAppServiceMapper, IscAppService, IscAppServiceVo> implements IIscAppServiceService {
@Resource
private IIscServiceService serviceService;
@Override
public IscAppServiceVo queryById(Long serviceAppId){
return getVoById(serviceAppId);
@ -36,20 +46,41 @@ public class IscAppServiceServiceImpl extends ServicePlusImpl<IscAppServiceMappe
@Override
public TableDataInfo<IscAppServiceVo> queryPageList(IscAppServiceBo bo) {
PagePlus<IscAppService, IscAppServiceVo> result = pageVo(PageUtils.buildPagePlus(), buildQueryWrapper(bo));
genServiceName(result.getRecordsVo());
return PageUtils.buildDataInfo(result);
}
@Override
public List<IscAppServiceVo> queryList(IscAppServiceBo bo) {
return listVo(buildQueryWrapper(bo));
final List<IscAppServiceVo> results = listVo(buildQueryWrapper(bo));
genServiceName(results);
return results;
}
/**
* 组装服务名称
* @param results 应用服务列表
*/
private void genServiceName(List<IscAppServiceVo> results)
{
if(CollectionUtil.isEmpty(results)) {
return;
}
Set<Long> serviceIds = results.stream().map(IscAppServiceVo::getServiceId).collect(Collectors.toSet());
Map<Long, String> nameMap = serviceService.getNameMap(serviceIds);
for (IscAppServiceVo result : results)
{
result.setServiceName(nameMap.get(result.getServiceId()));
}
}
private LambdaQueryWrapper<IscAppService> buildQueryWrapper(IscAppServiceBo bo) {
Map<String, Object> params = bo.getParams();
Long userId = SecurityUtils.getUserId();
LambdaQueryWrapper<IscAppService> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getServiceId() != null, IscAppService::getServiceId, bo.getServiceId());
lqw.eq(bo.getApplicationId() != null, IscAppService::getApplicationId, bo.getApplicationId());
lqw.eq(bo.getUserId() != null, IscAppService::getUserId, bo.getUserId());
lqw.eq(!SecurityUtils.isAdmin(userId), IscAppService::getUserId, userId);
lqw.eq(StringUtils.isNotBlank(bo.getEnabled()), IscAppService::getEnabled, bo.getEnabled());
lqw.eq(StringUtils.isNotBlank(bo.getStatus()), IscAppService::getStatus, bo.getStatus());
return lqw;
@ -85,4 +116,13 @@ public class IscAppServiceServiceImpl extends ServicePlusImpl<IscAppServiceMappe
}
return removeByIds(ids);
}
@Override
public List<Tree<Long>> genAppServiceTree(Long applicationId)
{
List<Long> serviceIds = listObjs(Wrappers.<IscAppService>lambdaQuery()
.select(IscAppService::getServiceId)
.eq(IscAppService::getApplicationId, applicationId), o -> (Long) o);
return serviceService.genServiceTree(CollectionUtil.newHashSet(serviceIds));
}
}

View File

@ -1,10 +1,14 @@
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 com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.ruoyi.common.constant.UserConstants;
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;
@ -27,6 +31,12 @@ import java.util.stream.Collectors;
@Service
public class IscServiceCateServiceImpl extends ServicePlusImpl<IscServiceCateMapper, IscServiceCate, IscServiceCateVo> implements IIscServiceCateService {
public static final String FIELD_FULL_PATH = "fullPath";
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){
return getVoById(cateId);
@ -135,6 +145,53 @@ public class IscServiceCateServiceImpl extends ServicePlusImpl<IscServiceCateMap
return results;
}
@Override
public List<Tree<Long>> genCateTree(List<IscServiceCate> cates)
{
return genCateTree(cates, null, CollectionUtil.newHashSet());
}
@Override
public List<Tree<Long>> genCateTree(List<IscServiceCate> cates, List<IscService> serviceList, Set<Long> exitsIds)
{
boolean isServiceTree = Objects.nonNull(serviceList);
final Map<String, List<IscService>> cateServiceMap = isServiceTree ? serviceList.stream()
.collect(Collectors.groupingBy(IscService::getCateFullPath)) : null;
return TreeUtils.build(cates, (cate, tree) -> {
tree.setId(cate.getCateId());
tree.setParentId(cate.getParentId());
tree.setName(cate.getCateName());
tree.setWeight(cate.getOrderNum());
tree.putExtra(FIELD_FULL_PATH, cate.getFullPath());
if(isServiceTree) {
tree.putExtra(FIELD_NODE_TYPE, NODE_TYPE_CATE);
List<IscService> services = cateServiceMap.get(cate.getFullPath());
if(CollectionUtil.isEmpty(services)) {
return;
}
for (int index = 0; index < services.size(); index++)
{
IscService service = services.get(index);
List<Tree<Long>> children = tree.getChildren();
if(Objects.isNull(children)) {
children = CollectionUtil.newArrayList();
tree.setChildren(children);
}
final Tree<Long> child = new Tree<>(TreeUtils.DEFAULT_TREE_NODE_CONFIG);
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()));
children.add(child);
}
}
});
}
private Map<Long, String> batchCateName(List<IscServiceCate> list) {
Map<Long, String> results = new HashMap<>();
final Set<Long> parentIds = list.stream().filter(m -> m.getParentId() != 0L).map(IscServiceCate::getParentId).collect(Collectors.toSet());

View File

@ -1,10 +1,13 @@
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 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.IscConstants;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
import com.ruoyi.common.core.page.PagePlus;
import com.ruoyi.common.core.page.TableDataInfo;
@ -24,6 +27,7 @@ import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
/**
@ -126,4 +130,30 @@ public class IscServiceServiceImpl extends ServicePlusImpl<IscServiceMapper, Isc
}
return removeByIds(ids);
}
@Override
public Map<Long, String> getNameMap(Collection<Long> serviceIds)
{
return list(Wrappers.<IscService>lambdaQuery()
.select(IscService::getServiceId, IscService::getServiceName)
.in(IscService::getServiceId, serviceIds)).stream()
.collect(Collectors.toMap(IscService::getServiceId, IscService::getServiceName));
}
@Override
public List<Tree<Long>> genServiceTree()
{
return genServiceTree(CollectionUtil.newHashSet());
}
@Override
public List<Tree<Long>> genServiceTree(Set<Long> exitsIds)
{
List<IscService> serviceList = list(Wrappers.<IscService>lambdaQuery()
.select(IscService::getServiceId, IscService::getServiceName, IscService::getCateFullPath)
.eq(IscService::getStatus, IscConstants.AUDIT_PASS)
.eq(IscService::getEnabled, UserConstants.DICT_NORMAL)
.orderByDesc(IscService::getUpdateTime));
return cateService.genCateTree(cateService.selectCateList(), serviceList, exitsIds);
}
}

View File

@ -42,3 +42,11 @@ export function delAppservice(serviceAppId) {
method: 'delete'
})
}
// 获取应用服务下拉树列表
export function treeselect(applicationId) {
return request({
url: '/isc/appservice/treeselect/' + applicationId,
method: 'get'
})
}

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"/>
<el-table-column label="应用ID" align="center" prop="applicationId" v-if="true" width="50"/>
<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

@ -1,32 +1,15 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="服务ID" prop="serviceId">
<el-form-item label="应用名称">
<el-input
v-model="queryParams.serviceId"
placeholder="请输入服务ID"
v-model="applicationName"
disabled
clearable
size="small"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="应用ID" prop="applicationId">
<el-input
v-model="queryParams.applicationId"
placeholder="请输入应用ID"
clearable
size="small"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="用户ID" prop="userId">
<el-input
v-model="queryParams.userId"
placeholder="请输入用户ID"
clearable
size="small"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="启用状态" prop="enabled">
<el-select v-model="queryParams.enabled" placeholder="请选择启用状态" clearable size="small">
@ -104,7 +87,7 @@
<el-table v-loading="loading" :data="appserviceList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="应用服务ID" align="center" prop="serviceAppId" v-if="false"/>
<el-table-column label="服务ID" align="center" prop="serviceId" />
<el-table-column label="服务名称" align="center" prop="serviceName" />
<el-table-column label="启用状态" align="center" prop="enabled">
<template slot-scope="scope">
<dict-tag :options="enabledOptions" :value="scope.row.enabled"/>
@ -163,11 +146,8 @@
<!-- 添加或修改应用服务对话框 -->
<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="服务ID" prop="serviceId">
<el-input v-model="form.serviceId" placeholder="请输入服务ID" />
</el-form-item>
<el-form-item label="用户ID" prop="userId">
<el-input v-model="form.userId" placeholder="请输入用户ID" />
<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>
<el-form-item label="启用状态">
<el-radio-group v-model="form.enabled">
@ -208,10 +188,13 @@
</template>
<script>
import { listAppservice, getAppservice, delAppservice, addAppservice, updateAppservice } from "@/api/isc/appservice";
import { listAppservice, getAppservice, delAppservice, addAppservice, updateAppservice, treeselect } from "@/api/isc/appservice";
import { getApplication } from "@/api/isc/application";
import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
export default {
name: "Appservice",
components: { Treeselect },
data() {
return {
// loading
@ -242,17 +225,17 @@ export default {
applyTypeOptions: [],
//
statusOptions: [],
//
appServiceOptions: [],
//
queryParams: {
pageNum: 1,
pageSize: 10,
serviceId: undefined,
applicationId: undefined,
userId: undefined,
enabled: undefined,
status: undefined,
},
applicationId: undefined,
applicationName: undefined,
//
form: {},
//
@ -283,6 +266,8 @@ export default {
this.getDicts("sys_audit_status").then(response => {
this.statusOptions = response.data;
});
this.getApplicationName(applicationId);
this.getTreeselect(applicationId);
},
methods: {
/** 查询应用服务列表 */
@ -294,6 +279,29 @@ export default {
this.loading = false;
});
},
/** 获取应用信息 */
getApplicationName(applicationId) {
getApplication(applicationId).then(response => {
this.applicationName = response.data.applicationName;
});
},
/** 获取应用服务分类树结构 */
getTreeselect(applicationId) {
treeselect(applicationId).then(response => {
this.appServiceOptions = response.data;
});
},
//
normalizer(node) {
const data = {
id: node.id,
label: node.label,
children: node.children,
disabled: true
}
console.log(data)
return
},
//
cancel() {
this.open = false;
@ -305,7 +313,6 @@ export default {
serviceAppId: undefined,
serviceId: undefined,
applicationId: this.applicationId,
userId: undefined,
enabled: "0",
applyType: undefined,
status: [],