feat 工作空间管理中新增概括总览页面

This commit is contained in:
bwcx_jzy 2024-01-04 17:23:58 +08:00
parent ffddbbdb35
commit 7e9283876a
No known key found for this signature in database
GPG Key ID: E187D6E9DDDE8C53
20 changed files with 271 additions and 74 deletions

View File

@ -2,11 +2,16 @@
### 2.11.0.5-beta
### 🐣 新增功能
1. 【server】新增 工作空间管理中新增概括总览页面
### 🐞 解决BUG、优化功能
1. 【server】优化 支持批量删除构建信息(感谢@奇奇)
2. 【server】修复 删除项目、删除分发检查关联构建失败问题
3. 【all】优化 关闭 Process 方式
4. 【server】优化 节点方法相关页面问题(感谢[@陈旭](https://gitee.com/chenxu8989) [Gitee issues I8TMDW](https://gitee.com/dromara/Jpom/issues/I8TMDW)
------

View File

@ -0,0 +1,91 @@
package org.dromara.jpom.controller;
import cn.hutool.db.Entity;
import cn.keepbx.jpom.IJsonMessage;
import cn.keepbx.jpom.model.JsonMessage;
import lombok.extern.slf4j.Slf4j;
import org.dromara.jpom.func.files.service.FileStorageService;
import org.dromara.jpom.func.files.service.StaticFileStorageService;
import org.dromara.jpom.service.docker.DockerInfoService;
import org.dromara.jpom.service.docker.DockerSwarmInfoService;
import org.dromara.jpom.service.node.NodeService;
import org.dromara.jpom.service.node.ProjectInfoCacheService;
import org.dromara.jpom.service.node.script.NodeScriptServer;
import org.dromara.jpom.service.node.ssh.SshCommandService;
import org.dromara.jpom.service.node.ssh.SshService;
import org.dromara.jpom.service.outgiving.OutGivingServer;
import org.dromara.jpom.service.script.ScriptServer;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
/**
* @author bwcx_jzy
* @since 24/1/4 004
*/
@RestController
@RequestMapping(value = "stat")
@Slf4j
public class DataStatController {
private final NodeService nodeService;
private final ProjectInfoCacheService projectInfoCacheService;
private final NodeScriptServer nodeScriptServer;
private final OutGivingServer outGivingServer;
private final SshService sshService;
private final SshCommandService sshCommandService;
private final ScriptServer scriptServer;
private final DockerInfoService dockerInfoService;
private final FileStorageService fileStorageService;
private final StaticFileStorageService staticFileStorageService;
private final DockerSwarmInfoService dockerSwarmInfoService;
public DataStatController(NodeService nodeService,
ProjectInfoCacheService projectInfoCacheService,
NodeScriptServer nodeScriptServer,
OutGivingServer outGivingServer,
SshService sshService,
SshCommandService sshCommandService,
ScriptServer scriptServer,
DockerInfoService dockerInfoService,
FileStorageService fileStorageService,
StaticFileStorageService staticFileStorageService,
DockerSwarmInfoService dockerSwarmInfoService) {
this.nodeService = nodeService;
this.projectInfoCacheService = projectInfoCacheService;
this.nodeScriptServer = nodeScriptServer;
this.outGivingServer = outGivingServer;
this.sshService = sshService;
this.sshCommandService = sshCommandService;
this.scriptServer = scriptServer;
this.dockerInfoService = dockerInfoService;
this.fileStorageService = fileStorageService;
this.staticFileStorageService = staticFileStorageService;
this.dockerSwarmInfoService = dockerSwarmInfoService;
}
@RequestMapping(value = "workspace", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public IJsonMessage<Map<String, Number>> workspace(HttpServletRequest request) {
String workspaceId = nodeService.getCheckUserWorkspace(request);
Entity entity = Entity.create();
entity.set("workspaceId", workspaceId);
Map<String, Number> map = new HashMap<>(10);
map.put("nodeCount", nodeService.count(entity));
map.put("projectCount", projectInfoCacheService.count(entity));
map.put("nodeScriptCount", nodeScriptServer.count(entity));
map.put("outGivingCount", outGivingServer.count(entity));
map.put("sshCount", sshService.count(entity));
map.put("sshCommandCount", sshCommandService.count(entity));
map.put("scriptCount", scriptServer.count(entity));
map.put("dockerCount", dockerInfoService.count(entity));
map.put("dockerSwarmCount", dockerSwarmInfoService.count(entity));
map.put("fileCount", fileStorageService.count(entity));
//map.put("staticFileCount", staticFileStorageService.count(entity));
return JsonMessage.success("", map);
}
}

View File

@ -43,7 +43,7 @@ import org.dromara.jpom.permission.MethodFeature;
import org.dromara.jpom.permission.SystemPermission;
import org.dromara.jpom.script.CommandParam;
import org.dromara.jpom.service.node.ssh.CommandExecLogService;
import org.dromara.jpom.service.node.ssh.CommandService;
import org.dromara.jpom.service.node.ssh.SshCommandService;
import org.dromara.jpom.service.user.TriggerTokenLogServer;
import org.dromara.jpom.util.CommandUtil;
import org.springframework.http.MediaType;
@ -67,14 +67,14 @@ import java.util.Map;
@Feature(cls = ClassFeature.SSH_COMMAND)
public class CommandInfoController extends BaseServerController {
private final CommandService commandService;
private final SshCommandService sshCommandService;
private final CommandExecLogService commandExecLogService;
private final TriggerTokenLogServer triggerTokenLogServer;
public CommandInfoController(CommandService commandService,
public CommandInfoController(SshCommandService sshCommandService,
CommandExecLogService commandExecLogService,
TriggerTokenLogServer triggerTokenLogServer) {
this.commandService = commandService;
this.sshCommandService = sshCommandService;
this.commandExecLogService = commandExecLogService;
this.triggerTokenLogServer = triggerTokenLogServer;
}
@ -87,7 +87,7 @@ public class CommandInfoController extends BaseServerController {
@RequestMapping(value = "list", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.LIST)
public IJsonMessage<PageResultDto<CommandModel>> page(HttpServletRequest request) {
PageResultDto<CommandModel> page = commandService.listPage(request);
PageResultDto<CommandModel> page = sshCommandService.listPage(request);
return JsonMessage.success("", page);
}
@ -129,10 +129,10 @@ public class CommandInfoController extends BaseServerController {
commandModel.setDefParams(CommandParam.checkStr(defParams));
if (StrUtil.isEmpty(id)) {
commandService.insert(commandModel);
sshCommandService.insert(commandModel);
} else {
commandModel.setId(id);
commandService.updateById(commandModel, request);
sshCommandService.updateById(commandModel, request);
}
return JsonMessage.success("操作成功");
}
@ -155,7 +155,7 @@ public class CommandInfoController extends BaseServerController {
Assert.state(!fastDel, "清理日志文件失败");
//
commandService.delByKey(id, request);
sshCommandService.delByKey(id, request);
commandExecLogService.delByWorkspace(request, entity -> entity.set("commandId", id));
return JsonMessage.success("操作成功");
}
@ -179,7 +179,7 @@ public class CommandInfoController extends BaseServerController {
@ValidatorItem(value = ValidatorRule.NOT_BLANK, msg = "运行节点不能为空") String nodes) throws IOException {
Assert.hasText(id, "请选择执行的命令");
Assert.hasText(nodes, "请选择执行节点");
String batchId = commandService.executeBatch(id, params, nodes);
String batchId = sshCommandService.executeBatch(id, params, nodes);
return JsonMessage.success("操作成功", batchId);
}
@ -196,8 +196,8 @@ public class CommandInfoController extends BaseServerController {
public IJsonMessage<Object> syncToWorkspace(@ValidatorItem String ids, @ValidatorItem String toWorkspaceId, HttpServletRequest request) {
String nowWorkspaceId = nodeService.getCheckUserWorkspace(request);
//
commandService.checkUserWorkspace(toWorkspaceId);
commandService.syncToWorkspace(ids, nowWorkspaceId, toWorkspaceId);
sshCommandService.checkUserWorkspace(toWorkspaceId);
sshCommandService.syncToWorkspace(ids, nowWorkspaceId, toWorkspaceId);
return JsonMessage.success("操作成功");
}
@ -210,15 +210,15 @@ public class CommandInfoController extends BaseServerController {
@RequestMapping(value = "trigger-url", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.EDIT)
public IJsonMessage<Map<String, String>> getTriggerUrl(String id, String rest, HttpServletRequest request) {
CommandModel item = commandService.getByKey(id, request);
CommandModel item = sshCommandService.getByKey(id, request);
UserModel user = getUser();
CommandModel updateInfo;
if (StrUtil.isEmpty(item.getTriggerToken()) || StrUtil.isNotEmpty(rest)) {
updateInfo = new CommandModel();
updateInfo.setId(id);
updateInfo.setTriggerToken(triggerTokenLogServer.restToken(item.getTriggerToken(), commandService.typeName(),
updateInfo.setTriggerToken(triggerTokenLogServer.restToken(item.getTriggerToken(), sshCommandService.typeName(),
item.getId(), user.getId()));
commandService.updateById(updateInfo);
sshCommandService.updateById(updateInfo);
} else {
updateInfo = item;
}

View File

@ -30,6 +30,9 @@ import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.Entity;
import cn.hutool.db.sql.Direction;
import cn.hutool.db.sql.Order;
import cn.keepbx.jpom.IJsonMessage;
import cn.keepbx.jpom.model.JsonMessage;
import com.alibaba.fastjson2.JSONObject;
@ -47,11 +50,13 @@ import org.dromara.jpom.func.user.server.UserLoginLogServer;
import org.dromara.jpom.model.PageResultDto;
import org.dromara.jpom.model.data.MailAccountModel;
import org.dromara.jpom.model.data.WorkspaceModel;
import org.dromara.jpom.model.log.BuildHistoryLog;
import org.dromara.jpom.model.log.UserOperateLogV1;
import org.dromara.jpom.model.user.UserModel;
import org.dromara.jpom.monitor.EmailUtil;
import org.dromara.jpom.permission.Feature;
import org.dromara.jpom.permission.MethodFeature;
import org.dromara.jpom.service.dblog.DbBuildHistoryLogService;
import org.dromara.jpom.service.dblog.DbUserOperateLogService;
import org.dromara.jpom.service.system.SystemParametersServer;
import org.dromara.jpom.service.user.UserBindWorkspaceService;
@ -88,6 +93,7 @@ public class UserBasicInfoController extends BaseServerController {
private final UserLoginLogServer userLoginLogServer;
private final DbUserOperateLogService dbUserOperateLogService;
private final ClusterInfoService clusterInfoService;
private final DbBuildHistoryLogService dbBuildHistoryLogService;
public UserBasicInfoController(SystemParametersServer systemParametersServer,
UserBindWorkspaceService userBindWorkspaceService,
@ -95,7 +101,8 @@ public class UserBasicInfoController extends BaseServerController {
ServerConfig serverConfig,
UserLoginLogServer userLoginLogServer,
DbUserOperateLogService dbUserOperateLogService,
ClusterInfoService clusterInfoService) {
ClusterInfoService clusterInfoService,
DbBuildHistoryLogService dbBuildHistoryLogService) {
this.systemParametersServer = systemParametersServer;
this.userBindWorkspaceService = userBindWorkspaceService;
this.userService = userService;
@ -103,6 +110,7 @@ public class UserBasicInfoController extends BaseServerController {
this.userLoginLogServer = userLoginLogServer;
this.dbUserOperateLogService = dbUserOperateLogService;
this.clusterInfoService = clusterInfoService;
this.dbBuildHistoryLogService = dbBuildHistoryLogService;
}
@ -122,6 +130,8 @@ public class UserBasicInfoController extends BaseServerController {
map.put("id", userModel.getId());
map.put("name", userModel.getName());
map.put("systemUser", userModel.isSystemUser());
map.put("superSystemUser", userModel.isSuperSystemUser());
map.put("demoUser", userModel.isDemoUser());
map.put("email", userModel.getEmail());
map.put("dingDing", userModel.getDingDing());
map.put("workWx", userModel.getWorkWx());
@ -315,6 +325,35 @@ public class UserBasicInfoController extends BaseServerController {
return JsonMessage.success("", pageResult);
}
@RequestMapping(value = "recent-log-data", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.LIST)
public IJsonMessage<JSONObject> recentData(HttpServletRequest request) {
UserModel user = getUser();
JSONObject jsonObject = new JSONObject();
{
Entity entity = Entity.create();
entity.set("userId", user.getId());
List<UserOperateLogV1> operateLog = dbUserOperateLogService.queryList(entity, 10, new Order("createTimeMillis", Direction.DESC));
jsonObject.put("operateLog", operateLog);
}
{
Entity entity = Entity.create();
entity.set("modifyUser", user.getId());
List<UserLoginLogModel> loginLog = userLoginLogServer.queryList(entity, 10, new Order("createTimeMillis", Direction.DESC));
jsonObject.put("loginLog", loginLog);
}
{
String workspaceId = dbBuildHistoryLogService.getCheckUserWorkspace(request);
Entity entity = Entity.create();
entity.set("workspaceId", workspaceId);
entity.set("modifyUser", user.getId());
List<BuildHistoryLog> loginLog = dbBuildHistoryLogService.queryList(entity, 10, new Order("createTimeMillis", Direction.DESC));
jsonObject.put("buildLog", loginLog);
}
return JsonMessage.success("", jsonObject);
}
/**
* 查询集群列表
*

View File

@ -35,7 +35,7 @@ import org.dromara.jpom.common.ServerOpenApi;
import org.dromara.jpom.common.interceptor.NotLogin;
import org.dromara.jpom.model.data.CommandModel;
import org.dromara.jpom.model.user.UserModel;
import org.dromara.jpom.service.node.ssh.CommandService;
import org.dromara.jpom.service.node.ssh.SshCommandService;
import org.dromara.jpom.service.user.TriggerTokenLogServer;
import org.springframework.http.MediaType;
import org.springframework.util.Assert;
@ -59,12 +59,12 @@ import java.util.stream.Collectors;
@Slf4j
public class SshCommandTriggerApiController extends BaseJpomController {
private final CommandService commandService;
private final SshCommandService sshCommandService;
private final TriggerTokenLogServer triggerTokenLogServer;
public SshCommandTriggerApiController(CommandService commandService,
public SshCommandTriggerApiController(SshCommandService sshCommandService,
TriggerTokenLogServer triggerTokenLogServer) {
this.commandService = commandService;
this.sshCommandService = sshCommandService;
this.triggerTokenLogServer = triggerTokenLogServer;
}
@ -77,19 +77,19 @@ public class SshCommandTriggerApiController extends BaseJpomController {
*/
@RequestMapping(value = ServerOpenApi.SSH_COMMAND_TRIGGER_URL, produces = MediaType.APPLICATION_JSON_VALUE)
public IJsonMessage<JSONObject> trigger2(@PathVariable String id, @PathVariable String token) {
CommandModel item = commandService.getByKey(id);
CommandModel item = sshCommandService.getByKey(id);
Assert.notNull(item, "没有对应数据");
Assert.state(StrUtil.equals(token, item.getTriggerToken()), "触发token错误,或者已经失效");
//
Assert.hasText(item.getSshIds(), "当前脚本未绑定 SSH 节点,不能使用触发器执行");
UserModel userModel = triggerTokenLogServer.getUserByToken(token, commandService.typeName());
UserModel userModel = triggerTokenLogServer.getUserByToken(token, sshCommandService.typeName());
//
Assert.notNull(userModel, "触发token错误,或者已经失效:-1");
String batchId;
try {
BaseServerController.resetInfo(userModel);
batchId = commandService.executeBatch(item, item.getDefParams(), item.getSshIds(), 2);
batchId = sshCommandService.executeBatch(item, item.getDefParams(), item.getSshIds(), 2);
} catch (Exception e) {
log.error("触发自动执行SSH命令模版异常", e);
return new JsonMessage<>(500, "执行异常:" + e.getMessage());
@ -130,12 +130,12 @@ public class SshCommandTriggerApiController extends BaseJpomController {
JSONObject jsonObject = (JSONObject) o;
String id = jsonObject.getString("id");
String token = jsonObject.getString("token");
CommandModel item = commandService.getByKey(id);
CommandModel item = sshCommandService.getByKey(id);
if (item == null) {
jsonObject.put("msg", "没有对应数据");
return;
}
UserModel userModel = triggerTokenLogServer.getUserByToken(token, commandService.typeName());
UserModel userModel = triggerTokenLogServer.getUserByToken(token, sshCommandService.typeName());
if (userModel == null) {
jsonObject.put("msg", "对应的用户不存在,触发器已失效");
return;
@ -148,7 +148,7 @@ public class SshCommandTriggerApiController extends BaseJpomController {
BaseServerController.resetInfo(userModel);
String batchId = null;
try {
batchId = commandService.executeBatch(item, item.getDefParams(), item.getSshIds(), 2);
batchId = sshCommandService.executeBatch(item, item.getDefParams(), item.getSshIds(), 2);
} catch (Exception e) {
log.error("触发自动执行命令模版异常", e);
jsonObject.put("msg", "执行异常:" + e.getMessage());

View File

@ -78,13 +78,6 @@ public class BuildHistoryLog extends BaseWorkspaceModel {
* 构建名称
*/
private String buildName;
/**
* 构建名称-未用
*
* @see this#buildName
*/
@Deprecated
private String name;
/**
* 构建编号
*

View File

@ -43,7 +43,7 @@ import org.dromara.jpom.service.node.ProjectInfoCacheService;
import org.dromara.jpom.service.node.script.NodeScriptExecuteLogServer;
import org.dromara.jpom.service.node.script.NodeScriptServer;
import org.dromara.jpom.service.node.ssh.CommandExecLogService;
import org.dromara.jpom.service.node.ssh.CommandService;
import org.dromara.jpom.service.node.ssh.SshCommandService;
import org.dromara.jpom.service.node.ssh.SshService;
import org.dromara.jpom.service.outgiving.DbOutGivingLogService;
import org.dromara.jpom.service.outgiving.LogReadServer;
@ -75,7 +75,7 @@ public enum ClassFeature {
SSH_FILE("SSH文件管理", SshService.class),
SSH_TERMINAL("SSH终端", SshService.class),
SSH_TERMINAL_LOG("SSH终端日志", SshTerminalExecuteLogService.class),
SSH_COMMAND("SSH命令管理", CommandService.class),
SSH_COMMAND("SSH命令管理", SshCommandService.class),
SSH_COMMAND_LOG("SSH命令日志", CommandExecLogService.class),
OUTGIVING("分发管理", OutGivingServer.class),
LOG_READ("日志阅读", LogReadServer.class),

View File

@ -67,7 +67,7 @@ import java.util.Map;
*/
@Service
@Slf4j
public class CommandService extends BaseWorkspaceService<CommandModel> implements ICron<CommandModel>, ITriggerToken {
public class SshCommandService extends BaseWorkspaceService<CommandModel> implements ICron<CommandModel>, ITriggerToken {
private final SshService sshService;
private final CommandExecLogService commandExecLogService;
@ -75,9 +75,9 @@ public class CommandService extends BaseWorkspaceService<CommandModel> implement
private static final byte[] LINE_BYTES = SystemUtil.getOsInfo().getLineSeparator().getBytes(CharsetUtil.CHARSET_UTF_8);
public CommandService(SshService sshService,
CommandExecLogService commandExecLogService,
WorkspaceEnvVarService workspaceEnvVarService) {
public SshCommandService(SshService sshService,
CommandExecLogService commandExecLogService,
WorkspaceEnvVarService workspaceEnvVarService) {
this.sshService = sshService;
this.commandExecLogService = commandExecLogService;
this.workspaceEnvVarService = workspaceEnvVarService;
@ -125,7 +125,7 @@ public class CommandService extends BaseWorkspaceService<CommandModel> implement
return false;
}
log.debug("start ssh command cron {} {} {}", id, buildInfoModel.getName(), autoExecCron);
CronUtils.upsert(taskId, autoExecCron, new CommandService.CronTask(id));
CronUtils.upsert(taskId, autoExecCron, new SshCommandService.CronTask(id));
return true;
}
@ -155,8 +155,8 @@ public class CommandService extends BaseWorkspaceService<CommandModel> implement
public void execute() {
try {
BaseServerController.resetInfo(UserModel.EMPTY);
CommandModel commandModel = CommandService.this.getByKey(this.id);
CommandService.this.executeBatch(commandModel, commandModel.getDefParams(), commandModel.getSshIds(), 1);
CommandModel commandModel = SshCommandService.this.getByKey(this.id);
SshCommandService.this.executeBatch(commandModel, commandModel.getDefParams(), commandModel.getSshIds(), 1);
} catch (Exception e) {
log.error("触发自动执行命令模版异常", e);
} finally {

View File

@ -1,4 +1,9 @@
[
{
"title": "概括总览",
"icon_v3": "laptop",
"id": "overview"
},
{
"title": "节点&项目",
"icon_v3": "apartment",

View File

@ -243,6 +243,14 @@ export function myWorkspace() {
});
}
export function statWorkspace() {
return axios({
url: "/stat/workspace",
method: "get",
params: {},
});
}
/**
* 我的集群
*
@ -315,3 +323,11 @@ export function listOperaterLog(params) {
data: params,
});
}
export function recentLogData(params) {
return axios({
url: "/user/recent-log-data",
method: "post",
data: params,
});
}

View File

@ -1272,9 +1272,6 @@ export default {
};
</script>
<style scoped>
/deep/ .ant-progress-text {
width: auto;
}
/* .replica-btn-del {
position: absolute;
right: 0;

View File

@ -558,3 +558,8 @@ export default {
},
};
</script>
<style scoped>
/deep/ .ant-progress-text {
width: auto;
}
</style>

View File

@ -12,7 +12,7 @@
}
"
>
<a-tabs default-active-key="1" tab-position="left">
<a-tabs v-model="tabKey" tab-position="left">
<a-tab-pane key="1" tab="状态">
<!-- 嵌套表格 -->
<a-table :loading="childLoading" :columns="childColumns" size="middle" :bordered="true" :data-source="list" :pagination="false" rowKey="id_no">
@ -174,6 +174,7 @@ export default {
dispatchStatusMap,
list: [],
tabKey: "1",
data: {},
drawerTitle: "",
drawerFileVisible: false,
@ -242,6 +243,12 @@ export default {
},
//
silenceLoadData() {
if (this.tabKey !== "1") {
//
//
this.countdownTime = Date.now() + this.refreshInterval * 1000;
return;
}
this.childLoading = true;
this.handleReloadById().then(() => {
//

View File

@ -15,7 +15,7 @@ export default {
watch: {},
mounted() {
if (this.getUserInfo && this.getToken) {
this.$router.push({ path: "/node/list" });
this.$router.push({ path: "/overview" });
} else {
//
this.$router.push({

View File

@ -13,15 +13,25 @@
</a-menu-item>
</a-menu>
<a-menu theme="dark" mode="inline" v-model="selectedKeys" @openChange="openChange" :openKeys="getMenuOpenKeys2">
<a-sub-menu v-for="menu in this.mode == 'normal' ? getMenus : getManagementMenus" :key="menu.id">
<span slot="title">
<a-icon :type="menu.icon_v3" :style="{ fontSize: '18px' }" />
<span>{{ menu.title }}</span>
</span>
<a-menu-item v-for="subMenu in menu.childs" :key="subMenu.id" :p="(subMenu.parent = menu)" @click="handleClick(subMenu)">
<span>{{ subMenu.title }}</span>
</a-menu-item>
</a-sub-menu>
<template v-for="menu in this.mode == 'normal' ? getMenus : getManagementMenus">
<template v-if="menu.childs && menu.childs.length">
<a-sub-menu :key="menu.id">
<span slot="title">
<a-icon :type="menu.icon_v3" :style="{ fontSize: '18px' }" />
<span>{{ menu.title }}</span>
</span>
<a-menu-item v-for="subMenu in menu.childs" :key="subMenu.id" :p="(subMenu.parent = menu)" @click="handleClick(subMenu)">
<span>{{ subMenu.title }}</span>
</a-menu-item>
</a-sub-menu>
</template>
<template v-else>
<a-menu-item :key="menu.id" @click="handleClick(menu)">
<a-icon :type="menu.icon_v3" :style="{ fontSize: '18px' }" />
<span>{{ menu.title }}</span>
</a-menu-item>
</template>
</template>
</a-menu>
</div>
</template>
@ -69,7 +79,7 @@ export default {
this.$nextTick(() => {
this.mangerMenuOpenkeys = [];
this.$router.push({
path: this.mode == "normal" ? "/system/management" : "/node/list",
path: this.mode == "normal" ? "/system/management" : "/overview",
});
});
},
@ -100,7 +110,7 @@ export default {
}
//
this.$router.push({
query: { ...this.$route.query, sPid: subMenu.parent.id, sId: subMenu.id },
query: { ...this.$route.query, sPid: subMenu.parent?.id, sId: subMenu.id },
path: subMenu.path,
});
// this.$router.push()

View File

@ -1,7 +1,7 @@
<template>
<div>
<a-tabs>
<a-tab-pane key="1" tab="操作日志">
<a-tabs v-model="tabKey">
<a-tab-pane :key="1" tab="操作日志">
<!-- 数据表格 -->
<a-table
size="middle"
@ -60,7 +60,7 @@
</a-tooltip>
</a-table>
</a-tab-pane>
<a-tab-pane key="2" tab="登录日志">
<a-tab-pane :key="2" tab="登录日志">
<a-table
size="middle"
:data-source="loginlist"
@ -120,6 +120,12 @@ import { listOperaterLog, listLoginLog } from "@/api/user/user";
import { getMonitorOperateTypeList } from "@/api/monitor";
import { operateCodeMap } from "@/api/user/user-login-log";
export default {
props: {
openTab: {
type: Number,
default: 1,
},
},
data() {
return {
operateloading: false,
@ -172,6 +178,7 @@ export default {
width: "170px",
},
],
tabKey: 1,
};
},
computed: {
@ -183,6 +190,9 @@ export default {
},
},
created() {
if (this.openTab) {
this.tabKey = this.openTab;
}
this.operaterloadData();
this.loginloadData();
getMonitorOperateTypeList().then((res) => {

View File

@ -16,6 +16,11 @@ const children = [
name: "my-workspace",
component: () => import("../pages/layout/my-workspace"),
},
{
path: "/overview",
name: "overview",
component: () => import("../pages/layout/overview"),
},
{
path: "/node/list",
name: "node-list",
@ -269,7 +274,7 @@ const router = new Router({
path: "/management",
name: "management",
component: () => import("../pages/layout"),
redirect: "/node/list",
redirect: "/overview",
children: children.map((item) => {
const props = item.props || {};
props.routerUrl = item.path;

View File

@ -55,6 +55,7 @@ const routeMenuMap = {
fileReleaseTask: "/file-manager/release-task",
certificate: "/certificate/list",
authConfig: "/system/oauth-config",
overview: "/overview",
};
export default routeMenuMap;

View File

@ -48,7 +48,7 @@ const app = {
getSystemMenu()
.then((res) => {
res.data.forEach((element) => {
if (element.childs.length > 0) {
if (element.childs?.length > 0) {
element.childs = element.childs.map((child) => {
return {
...child,
@ -73,7 +73,7 @@ const app = {
let currentMenu = null,
firstMenu = null;
menus.forEach((menu) => {
menu.childs.forEach((subMenu) => {
menu.childs?.forEach((subMenu) => {
if (!firstMenu) {
firstMenu = subMenu;
}
@ -89,7 +89,7 @@ const app = {
return (
menus.filter((menu) => {
return (
menu.childs.filter((subMenu) => {
menu.childs?.filter((subMenu) => {
return subMenu.path === item.path;
}).length > 0
);

View File

@ -61,8 +61,8 @@ const app = {
getMenu()
.then((res) => {
if (res.data) {
res.data?.forEach((element) => {
if (element.childs.length > 0) {
res.data = res.data?.map((element) => {
if (element.childs?.length > 0) {
const childs = element.childs.map((child) => {
return {
...child,
@ -71,6 +71,8 @@ const app = {
});
element.childs = childs;
}
element.path = routeMenuMap[element.id];
return element;
});
commit("setMenus", res.data);
resolve();
@ -94,15 +96,25 @@ const app = {
let currentMenu = null,
firstMenu = null;
menus.forEach((menu) => {
menu.childs.forEach((subMenu) => {
if (menu.childs && menu.childs.length) {
menu.childs.forEach((subMenu) => {
if (!firstMenu) {
firstMenu = subMenu;
}
if (subMenu.path === tab.path) {
currentMenu = subMenu;
currentMenu.parent = menu;
}
});
} else {
if (!firstMenu) {
firstMenu = subMenu;
firstMenu = menu;
}
if (subMenu.path === tab.path) {
currentMenu = subMenu;
currentMenu.parent = menu;
if (menu.path === tab.path) {
currentMenu = menu;
// currentMenu.parent = menu;
}
});
}
});
let tabList = state.tabList || [];
// 过滤已经不能显示的菜单
@ -110,7 +122,8 @@ const app = {
return (
menus.filter((menu) => {
return (
menu.childs.filter((subMenu) => {
menu.path == item.path ||
menu.childs?.filter((subMenu) => {
return subMenu.path === item.path;
}).length > 0
);
@ -128,7 +141,7 @@ const app = {
//
tab.title = currentMenu.title;
tab.id = currentMenu.id;
tab.parentId = currentMenu.parent.id;
tab.parentId = currentMenu.parent?.id;
if (index > -1) {
// 设置 activeTabKey