添加 cacheStore.

This commit is contained in:
lijiahang
2023-08-09 15:45:33 +08:00
parent b38fd5ee11
commit 0063b31f35
13 changed files with 238 additions and 116 deletions

View File

@@ -26,7 +26,9 @@ public class SystemMenuUpdateStatusRequest {
@Schema(description = "id") @Schema(description = "id")
private Long id; private Long id;
@NotNull @Schema(description = "是否可见 0不可见 1可见")
private Integer visible;
@Schema(description = "菜单状态 0停用 1启用") @Schema(description = "菜单状态 0停用 1启用")
private Integer status; private Integer status;

View File

@@ -0,0 +1,43 @@
package com.orion.ops.module.infra.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 菜单可见枚举
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/7/16 1:45
*/
@Getter
@AllArgsConstructor
public enum MenuVisibleEnum {
/**
* 显示
*/
HIDE(0),
/**
* 隐藏
*/
SHOW(1),
;
private final Integer visible;
public static MenuVisibleEnum of(Integer visible) {
if (visible == null) {
return null;
}
for (MenuVisibleEnum value : values()) {
if (value.visible.equals(visible)) {
return value;
}
}
return null;
}
}

View File

@@ -19,6 +19,7 @@ import com.orion.ops.module.infra.entity.request.menu.SystemMenuUpdateStatusRequ
import com.orion.ops.module.infra.entity.vo.SystemMenuVO; import com.orion.ops.module.infra.entity.vo.SystemMenuVO;
import com.orion.ops.module.infra.enums.MenuStatusEnum; import com.orion.ops.module.infra.enums.MenuStatusEnum;
import com.orion.ops.module.infra.enums.MenuTypeEnum; import com.orion.ops.module.infra.enums.MenuTypeEnum;
import com.orion.ops.module.infra.enums.MenuVisibleEnum;
import com.orion.ops.module.infra.service.PermissionService; import com.orion.ops.module.infra.service.PermissionService;
import com.orion.ops.module.infra.service.SystemMenuService; import com.orion.ops.module.infra.service.SystemMenuService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -177,22 +178,37 @@ public class SystemMenuServiceImpl implements SystemMenuService {
@Override @Override
public Integer updateSystemMenuStatus(SystemMenuUpdateStatusRequest request) { public Integer updateSystemMenuStatus(SystemMenuUpdateStatusRequest request) {
Long id = request.getId(); Long id = request.getId();
Integer status = Valid.valid(MenuStatusEnum::of, request.getStatus()).getStatus(); Integer status = request.getStatus();
Integer visible = request.getVisible();
if (status != null) {
Valid.valid(MenuStatusEnum::of, status);
}
if (visible != null) {
Valid.valid(MenuVisibleEnum::of, visible);
}
// 查询 // 查询
SystemMenuDO record = systemMenuDAO.selectById(id); SystemMenuDO record = systemMenuDAO.selectById(id);
Valid.notNull(record, ErrorMessage.DATA_ABSENT); Valid.notNull(record, ErrorMessage.DATA_ABSENT);
// 从缓存中查询 // 从缓存中查询
List<SystemMenuCacheDTO> cache = permissionService.getMenuCache(); List<SystemMenuCacheDTO> cache = permissionService.getMenuCache();
// 获取要删除的id // 获取要更新的id
List<Long> updateIdList = this.getChildrenIdList(id, cache, record.getType()); List<Long> updateIdList = this.getChildrenIdList(id, cache, record.getType());
// 修改状态 // 修改状态
SystemMenuDO update = new SystemMenuDO(); SystemMenuDO update = new SystemMenuDO();
update.setStatus(status); update.setStatus(status);
update.setVisible(visible);
int effect = systemMenuDAO.update(update, Conditions.in(SystemMenuDO::getId, updateIdList)); int effect = systemMenuDAO.update(update, Conditions.in(SystemMenuDO::getId, updateIdList));
// 修改引用缓存状态 // 修改引用缓存状态
cache.stream() cache.stream()
.filter(s -> updateIdList.contains(s.getId())) .filter(s -> updateIdList.contains(s.getId()))
.forEach(s -> s.setStatus(status)); .forEach(s -> {
if (status != null) {
s.setStatus(status);
}
if (visible != null) {
s.setVisible(visible);
}
});
log.info("SystemMenuService-updateSystemMenuStatus updateIdList: {}, effect: {}", JSON.toJSONString(updateIdList), effect); log.info("SystemMenuService-updateSystemMenuStatus updateIdList: {}, effect: {}", JSON.toJSONString(updateIdList), effect);
return effect; return effect;
} }

View File

@@ -9,6 +9,7 @@ export interface MenuCreateRequest {
permission?: string; permission?: string;
type?: number; type?: number;
sort?: number; sort?: number;
visible?: number;
cache?: number; cache?: number;
icon?: string; icon?: string;
path?: string; path?: string;
@@ -20,6 +21,7 @@ export interface MenuCreateRequest {
*/ */
export interface MenuUpdateRequest extends MenuCreateRequest { export interface MenuUpdateRequest extends MenuCreateRequest {
id: number; id: number;
status?: number;
} }
/** /**
@@ -70,6 +72,13 @@ export function updateMenu(request: MenuUpdateRequest) {
return axios.put<MenuQueryResponse[]>('/infra/system-menu/update', request); return axios.put<MenuQueryResponse[]>('/infra/system-menu/update', request);
} }
/**
* 修改菜单状态
*/
export function updateMenuStatus(request: MenuUpdateRequest) {
return axios.put<MenuQueryResponse[]>('/infra/system-menu/update-status', request);
}
/** /**
* 删除菜单 * 删除菜单
*/ */

View File

@@ -24,10 +24,22 @@
} }
} }
.modal-form {
.arco-form-item {
&:last-child {
margin-bottom: 0 !important;
}
}
}
.hide { .hide {
display: none; display: none;
} }
.pointer {
cursor: pointer;
}
.ml4 { .ml4 {
margin-left: 4px; margin-left: 4px;
} }

View File

@@ -2,7 +2,7 @@ import { createPinia } from 'pinia';
import useAppStore from './modules/app'; import useAppStore from './modules/app';
import useUserStore from './modules/user'; import useUserStore from './modules/user';
import useTabBarStore from './modules/tab-bar'; import useTabBarStore from './modules/tab-bar';
import useMenuStore from './modules/system/menu'; import useCacheStore from './modules/cache';
const pinia = createPinia(); const pinia = createPinia();
@@ -10,7 +10,7 @@ export {
useAppStore, useAppStore,
useUserStore, useUserStore,
useTabBarStore, useTabBarStore,
useMenuStore useCacheStore
}; };
export default pinia; export default pinia;

View File

@@ -0,0 +1,29 @@
import { defineStore } from 'pinia';
import { CacheState } from './types';
import { MenuQueryResponse } from '@/api/system/menu';
const useCacheStore = defineStore('cache', {
state: (): CacheState => ({
menus: []
}),
getters: {},
actions: {
/**
* 更新菜单
*/
updateMenu(menus: MenuQueryResponse[]) {
this.menus = menus;
},
/**
* 清空菜单
*/
resetMenu() {
this.menus = [];
},
},
});
export default useCacheStore;

View File

@@ -1,6 +1,6 @@
import { MenuQueryResponse } from '@/api/system/menu'; import { MenuQueryResponse } from '@/api/system/menu';
export interface MenuState { export interface CacheState {
menus: MenuQueryResponse[], menus: MenuQueryResponse[],
[key: string]: unknown; [key: string]: unknown;

View File

@@ -1,84 +0,0 @@
import { defineStore } from 'pinia';
import { MenuState } from './types';
import { MenuQueryResponse } from '@/api/system/menu';
import { TreeNodeData } from '@arco-design/web-vue';
const useMenuStore = defineStore('menu', {
state: (): MenuState => ({
menus: []
}),
getters: {
menuState(state: MenuState): MenuState {
return { ...state };
},
treeData(state: MenuState): TreeNodeData[] {
let render = (arr: any[]): TreeNodeData[] => {
return arr.map((s) => {
// 非 function
if (s.type === 3) {
return null as unknown as TreeNodeData;
}
// 当前节点
const node = {
key: s.id,
title: s.name,
children: undefined as unknown
} as TreeNodeData;
// 子节点
if (s.children && s.children.length) {
node.children = render(s.children);
}
return node;
}).filter(Boolean);
};
return [{
key: 0,
title: '根目录',
children: render([...state.menus])
}];
}
},
actions: {
/**
* 更新菜单
*/
updateMenu(menus: MenuQueryResponse[]) {
this.menus = menus;
},
/**
* 获取父菜单
*/
findParentMenu(arr: any, id: number): any {
if (!arr || !arr.length) {
return null;
}
// 当前级
for (let e of arr) {
if (e.id === id) {
return arr;
}
}
// 子级
for (let e of arr) {
if (e.children && e.children.length) {
if (this.findParentMenu(e.children, id)) {
return e.children;
}
}
}
return null;
},
/**
* 清空菜单
*/
reset() {
this.menus = [];
},
},
});
export default useMenuStore;

View File

@@ -9,6 +9,33 @@ export const toOptions = (enums: any) => {
return arr; return arr;
}; };
/**
* 切换枚举值
*/
export const toggleEnumValue = (value: any,
enums: any,
key = 'value',
defaultValue = value) => {
for (let k in enums) {
if (enums[k].value !== value) {
return enums[k][key];
}
}
return defaultValue;
};
/**
* 切换枚举对象
*/
export const toggleEnum = (value: any, enums: any) => {
for (let k in enums) {
if (enums[k].value !== value) {
return enums[k];
}
}
return {};
};
/** /**
* 获取枚举值 * 获取枚举值
*/ */

View File

@@ -1,5 +1,6 @@
<template> <template>
<a-modal v-model:visible="visible" <a-modal v-model:visible="visible"
body-class="modal-form"
title-align="start" title-align="start"
:title="title" :title="title"
:top="80" :top="80"
@@ -212,17 +213,12 @@
const handlerClear = () => { const handlerClear = () => {
setLoading(false); setLoading(false);
setVisible(false); setVisible(false);
// 触发 watch 防止第二次加载变成根目录
renderForm(defaultForm());
}; };
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
:deep(.arco-form) {
&-item {
&:last-child {
margin-bottom: 0 !important;
}
}
}
</style> </style>

View File

@@ -93,14 +93,25 @@
<template #status="{ record }"> <template #status="{ record }">
<a-space> <a-space>
<!-- 菜单状态 --> <!-- 菜单状态 -->
<a-tag :color="getEnumValue(record.status, MenuStatusEnum,'color')"> <a-popconfirm position="top"
{{ getEnumValue(record.status, MenuStatusEnum) }} type="warning"
</a-tag> :content="`确定要将当前节点以及所有子节点改为${toggleEnumValue(record.status, MenuStatusEnum, 'label')}?`"
@ok="updateStatus(record.id, toggleEnumValue(record.status, MenuStatusEnum))">
<a-tag :color="getEnumValue(record.status, MenuStatusEnum,'color')" class="pointer">
{{ getEnumValue(record.status, MenuStatusEnum) }}
</a-tag>
</a-popconfirm>
<!-- 显示状态 --> <!-- 显示状态 -->
<a-tag v-if="(record.visible || record.visible === 0) && record.type !== MenuTypeEnum.FUNCTION.value" <a-popconfirm position="top"
:color="getEnumValue(record.visible, MenuVisibleEnum,'color')"> type="warning"
{{ getEnumValue(record.visible, MenuVisibleEnum) }} :content="`确定要将当前节点以及所有子节点改为${toggleEnumValue(record.visible, MenuVisibleEnum, 'label')}?`"
</a-tag> @ok="updateVisible(record.id, toggleEnumValue(record.visible, MenuVisibleEnum))">
<a-tag v-if="(record.visible || record.visible === 0) && record.type !== MenuTypeEnum.FUNCTION.value"
:color="getEnumValue(record.visible, MenuVisibleEnum,'color')"
class="pointer">
{{ getEnumValue(record.visible, MenuVisibleEnum) }}
</a-tag>
</a-popconfirm>
</a-space> </a-space>
</template> </template>
<!-- 操作 --> <!-- 操作 -->
@@ -147,14 +158,14 @@
<script lang="ts" setup> <script lang="ts" setup>
import { reactive, ref, onUnmounted } from 'vue'; import { reactive, ref, onUnmounted } from 'vue';
import useLoading from '@/hooks/loading'; import useLoading from '@/hooks/loading';
import { getMenuList, deleteMenu, MenuQueryResponse } from '@/api/system/menu'; import { getMenuList, deleteMenu, updateMenuStatus, MenuQueryResponse } from '@/api/system/menu';
import { toOptions, getEnumValue } from '@/utils/enum'; import { toOptions, getEnumValue, toggleEnumValue } from '@/utils/enum';
import { MenuStatusEnum, MenuVisibleEnum, MenuTypeEnum } from '../type/enum.types'; import { MenuStatusEnum, MenuVisibleEnum, MenuTypeEnum } from '../type/enum.types';
import columns from '../type/table.columns'; import columns from '../type/table.columns';
import { Message } from '@arco-design/web-vue'; import { Message } from '@arco-design/web-vue';
import { useMenuStore } from '@/store'; import { useCacheStore } from '@/store';
const menuStore = useMenuStore(); const cacheStore = useCacheStore();
const formRef = ref<any>(); const formRef = ref<any>();
const formModel = reactive({ const formModel = reactive({
@@ -176,8 +187,31 @@
setFetchLoading(true); setFetchLoading(true);
// 调用删除接口 // 调用删除接口
await deleteMenu(id); await deleteMenu(id);
// 获取父菜单
const findParentMenu = (arr: any, id: number): any => {
if (!arr || !arr.length) {
return null;
}
// 当前级
for (let e of arr) {
if (e.id === id) {
return arr;
}
}
// 子级
for (let e of arr) {
if (e.children && e.children.length) {
if (findParentMenu(e.children, id)) {
return e.children;
}
}
}
return null;
};
// 获取父级容器 // 获取父级容器
const parent = menuStore.findParentMenu(tableRenderData.value, id) as unknown as MenuQueryResponse[]; const parent = findParentMenu(tableRenderData.value, id) as unknown as MenuQueryResponse[];
if (parent) { if (parent) {
// 删除 // 删除
for (let i = 0; i < parent.length; i++) { for (let i = 0; i < parent.length; i++) {
@@ -212,7 +246,7 @@
setFetchLoading(true); setFetchLoading(true);
const { data } = await getMenuList(formModel); const { data } = await getMenuList(formModel);
tableRenderData.value = data as MenuQueryResponse[]; tableRenderData.value = data as MenuQueryResponse[];
menuStore.updateMenu(tableRenderData.value); cacheStore.updateMenu(tableRenderData.value);
} finally { } finally {
setFetchLoading(false); setFetchLoading(false);
} }
@@ -230,9 +264,21 @@
tableRef.value.expandAll(expandStatus.value = !expandStatus.value); tableRef.value.expandAll(expandStatus.value = !expandStatus.value);
}; };
// 修改状态
const updateStatus = async (id: number, status: number) => {
await updateMenuStatus({ id, status });
await loadMenuData();
};
// 修改可见状态
const updateVisible = async (id: number, visible: number) => {
await updateMenuStatus({ id, visible });
await loadMenuData();
};
// 卸载时清除 store // 卸载时清除 store
onUnmounted(() => { onUnmounted(() => {
menuStore.reset(); cacheStore.resetMenu();
}); });
</script> </script>

View File

@@ -1,6 +1,6 @@
<template> <template>
<a-tree-select v-model:model-value="value" <a-tree-select v-model:model-value="value"
:data="treeData" :data="treeData()"
:disabled="disabled" :disabled="disabled"
:allow-search="true" :allow-search="true"
:filter-tree-node="filterTreeNode" :filter-tree-node="filterTreeNode"
@@ -14,8 +14,9 @@
</script> </script>
<script lang="ts" setup> <script lang="ts" setup>
import { useMenuStore } from '@/store'; import { useCacheStore } from '@/store';
import { computed } from 'vue'; import { computed } from 'vue';
import { TreeNodeData } from '@arco-design/web-vue';
const props = defineProps({ const props = defineProps({
modelValue: Number, modelValue: Number,
@@ -34,8 +35,33 @@
}); });
// 树数据 // 树数据
const menuStore = useMenuStore(); const cacheStore = useCacheStore();
const treeData = menuStore.treeData; const treeData = (): TreeNodeData[] => {
let render = (arr: any[]): TreeNodeData[] => {
return arr.map((s) => {
// 非 function
if (s.type === 3) {
return null as unknown as TreeNodeData;
}
// 当前节点
const node = {
key: s.id,
title: s.name,
children: undefined as unknown
} as TreeNodeData;
// 子节点
if (s.children && s.children.length) {
node.children = render(s.children);
}
return node;
}).filter(Boolean);
};
return [{
key: 0,
title: '根目录',
children: render([...cacheStore.menus])
}];
};
// 搜索 // 搜索
const filterTreeNode = (searchValue: string, nodeData: { title: string; }) => { const filterTreeNode = (searchValue: string, nodeData: { title: string; }) => {