使用字典配置替换枚举.

This commit is contained in:
lijiahangmax
2023-10-27 01:43:16 +08:00
parent 5d43a9ce88
commit 74688ca535
17 changed files with 198 additions and 127 deletions

View File

@@ -66,6 +66,8 @@ export interface DictValueQueryResponse extends TableData {
* 字典配置值选项查询响应
*/
export interface DictValueOptionsQueryResponse extends Options {
label: string;
value: string | number | boolean;
[key: string]: unknown;
}

View File

@@ -5,7 +5,7 @@ import useUserStore from './modules/user';
import useTabBarStore from './modules/tab-bar';
import useCacheStore from './modules/cache';
import useTipsStore from './modules/tips';
// import useDictStore from './modules/dict';
import useDictStore from './modules/dict';
const pinia = createPinia();
@@ -16,7 +16,7 @@ export {
useTabBarStore,
useCacheStore,
useTipsStore,
// useDictStore,
useDictStore,
};
export default pinia;

View File

@@ -0,0 +1,66 @@
import type { DictState } from './types';
import { defineStore } from 'pinia';
import { getDictValueList } from '@/api/system/dict-value';
export default defineStore('dict', {
state: (): DictState => ({}),
actions: {
// 加载字典值
async loadKeys(keys: string[]) {
// 检查是否存在
const unloadKeys = keys.filter(key => !this.$state.hasOwnProperty(key));
if (!unloadKeys.length) {
return;
}
// 加载未加载的数据
try {
const { data } = await getDictValueList(unloadKeys);
this.$patch(data as object);
} catch (e) {
}
},
// 获取字典选项
toOptions(key: string) {
return this.$state[key];
},
// 获取选择值
getDictValue(dict: string,
value: any,
key = 'label',
defaultValue = value) {
for (let dictValue of this.$state[dict] || []) {
if (dictValue.value === value) {
return dictValue[key];
}
}
return defaultValue;
},
// 切换字典值对象
toggleDictValue(dict: string,
value: any,
key = 'value',
defaultValue = value) {
for (let dictValue of this.$state[dict] || []) {
if (dictValue.value !== value) {
return dictValue[key];
}
}
return defaultValue;
},
// 切换字典值对象
toggleDict(dict: string, value: any) {
for (let dictValue of this.$state[dict] || []) {
if (dictValue.value !== value) {
return dictValue;
}
}
return {};
}
},
});

View File

@@ -0,0 +1,5 @@
import { DictValueOptionsQueryResponse } from '@/api/system/dict-value';
export interface DictState {
[key: string]: Array<DictValueOptionsQueryResponse>;
}

View File

@@ -24,7 +24,7 @@
<!-- 地址 -->
<template #address="{ record }">
<a-tooltip content="点击复制">
<span class="host-address" @click="copy(record.address)">
<span class="pointer span-blue" @click="copy(record.address)">
<icon-copy /> {{ record.address }}
</span>
</a-tooltip>
@@ -245,8 +245,4 @@
</script>
<style lang="less" scoped>
.host-address {
cursor: pointer;
color: rgb(var(--arcoblue-6))
}
</style>

View File

@@ -92,8 +92,8 @@
</template>
<!-- 地址 -->
<template #address="{ record }">
<span title="复制">
<icon-copy class="copy-left" @click="copy(record.address)" />
<span class="copy-left" @click="copy(record.address)" title="复制">
<icon-copy />
</span>
<span class="span-blue">{{ record.address }}</span>
</template>

View File

@@ -55,7 +55,9 @@
:bordered="false">
<!-- 配置项 -->
<template #keyName="{ record }">
<icon-copy class="copy-left" title="复制" @click="copy(record.keyName)" />
<span class="copy-left" title="复制" @click="copy(record.keyName)">
<icon-copy />
</span>
<span>{{ record.keyName }}</span>
</template>
<!-- 配置值类型 -->

View File

@@ -50,6 +50,7 @@
// 查看
const { data } = await getDictValueList([keyName]);
value.value = JSON.stringify(data[keyName], undefined, 4);
} catch (e) {
} finally {
setLoading(false);
}

View File

@@ -4,6 +4,9 @@ import { ValueTypeEnum } from './enum.types';
* 快捷定义字段
*/
export const definedExtraKeys = [{
name: 'disabled',
type: ValueTypeEnum.BOOLEAN.value
}, {
name: 'status',
type: ValueTypeEnum.STRING.value
}, {

View File

@@ -111,7 +111,7 @@
value: undefined,
label: undefined,
extra: undefined,
sort: 10,
sort: undefined,
};
};
@@ -126,7 +126,7 @@
const openAdd = () => {
title.value = '添加字典配置值';
isAddHandle.value = true;
renderForm({ ...defaultForm(), keyId: formModel.value.keyId });
renderForm({ ...defaultForm(), keyId: formModel.value.keyId, sort: (formModel.value.sort || 0) + 10 });
setVisible(true);
};
@@ -207,6 +207,13 @@
// 关闭
const handleClose = () => {
handlerClear();
if (isAddHandle.value) {
// 关闭后设置排序 -10 下次进入的排序字段会保持不变
formModel.value.sort = (formModel.value.sort || 0) - 10;
} else {
// 关闭后设置排序为 0 下次进入的排序字段为 10
formModel.value.sort = 0;
}
};
// 清空

View File

@@ -78,7 +78,9 @@
:bordered="false">
<!-- 值 -->
<template #value="{ record }">
<icon-copy class="copy-left" title="复制" @click="copy(record.value)" />
<span class="copy-left" title="复制" @click="copy(record.value)">
<icon-copy />
</span>
<a-tooltip :content="record.value">
<span>{{ record.value }}</span>
</a-tooltip>

View File

@@ -22,8 +22,8 @@
:rules="formRules">
<!-- 上级菜单 -->
<a-form-item field="parentId" label="上级菜单">
<menu-tree-selector v-model:model-value="formModel.parentId"
:disabled="formModel.type === MenuTypeEnum.PARENT_MENU.value" />
<menu-tree-selector v-model:model-value="formModel.parentId as number"
:disabled="formModel.type === MenuType.PARENT_MENU" />
</a-form-item>
<!-- 菜单名称 -->
<a-form-item field="name" label="菜单名称">
@@ -35,10 +35,10 @@
label="菜单类型">
<a-radio-group type="button"
v-model="formModel.type"
:options="toOptions(MenuTypeEnum)" />
:options="toOptions(menuTypeKey)" />
</a-form-item>
<!-- 菜单图标 -->
<a-form-item v-if="formModel.type !== MenuTypeEnum.FUNCTION.value"
<a-form-item v-if="formModel.type !== MenuType.FUNCTION"
field="icon"
label="菜单图标">
<icon-picker v-model:icon="formModel.icon as string">
@@ -48,7 +48,7 @@
</icon-picker>
</a-form-item>
<!-- 菜单权限 -->
<a-form-item v-if="formModel.type === MenuTypeEnum.FUNCTION.value"
<a-form-item v-if="formModel.type === MenuType.FUNCTION"
field="permission"
label="菜单权限">
<a-input v-model="formModel.permission"
@@ -56,7 +56,7 @@
allow-clear />
</a-form-item>
<!-- 外链地址 -->
<a-form-item v-if="formModel.type !== MenuTypeEnum.FUNCTION.value"
<a-form-item v-if="formModel.type !== MenuType.FUNCTION"
field="path"
label="外链地址"
tooltip="输入组件名称后则不会生效">
@@ -65,7 +65,7 @@
allow-clear />
</a-form-item>
<!-- 组件名称 -->
<a-form-item v-if="formModel.type !== MenuTypeEnum.FUNCTION.value"
<a-form-item v-if="formModel.type !== MenuType.FUNCTION"
field="component"
label="组件名称">
<a-input v-model="formModel.component"
@@ -81,30 +81,30 @@
hide-button />
</a-form-item>
<!-- 是否可见 -->
<a-form-item v-if="formModel.type !== MenuTypeEnum.FUNCTION.value"
<a-form-item v-if="formModel.type !== MenuType.FUNCTION"
field="type"
label="是否可见"
tooltip="选择隐藏后不会在菜单以及 tab 中显示 但是可以访问">
<a-switch type="round"
size="large"
v-model="formModel.visible"
:checked-text="MenuVisibleEnum.SHOW.label"
:checked-value="MenuVisibleEnum.SHOW.value"
:unchecked-text="MenuVisibleEnum.HIDE.label"
:unchecked-value="MenuVisibleEnum.HIDE.value" />
:checked-text="getDictValue(menuVisibleKey, MenuVisible.SHOW)"
:unchecked-text="getDictValue(menuVisibleKey, MenuVisible.HIDE)"
:checked-value="MenuVisible.SHOW"
:unchecked-value="MenuVisible.HIDE" />
</a-form-item>
<!-- 是否缓存 -->
<a-form-item v-if="formModel.type !== MenuTypeEnum.FUNCTION.value"
<a-form-item v-if="formModel.type !== MenuType.FUNCTION"
field="type"
label="是否缓存"
tooltip="选择缓存后则会使用 keep-alive 缓存组件">
<a-switch type="round"
size="large"
v-model="formModel.cache"
:checked-text="MenuCacheEnum.ENABLED.label"
:checked-value="MenuCacheEnum.ENABLED.value"
:unchecked-text="MenuCacheEnum.DISABLED.label"
:unchecked-value="MenuCacheEnum.DISABLED.value" />
:checked-text="getDictValue(menuCacheKey, MenuCache.ENABLED)"
:unchecked-text="getDictValue(menuCacheKey, MenuCache.DISABLED)"
:checked-value="MenuCache.ENABLED"
:unchecked-value="MenuCache.DISABLED" />
</a-form-item>
</a-form>
</a-spin>
@@ -123,16 +123,18 @@
import useLoading from '@/hooks/loading';
import useVisible from '@/hooks/visible';
import formRules from '../types/form.rules';
import { sortStep } from '../types/const';
import { MenuTypeEnum, MenuVisibleEnum, MenuCacheEnum } from '../types/enum.types';
import { toOptions } from '@/utils/enum';
import { menuCacheKey, sortStep } from '../types/const';
import { menuVisibleKey, menuTypeKey, MenuType, MenuVisible, MenuCache } from '../types/const';
import IconPicker from '@sanqi377/arco-vue-icon-picker';
import MenuTreeSelector from './menu-tree-selector.vue';
import { createMenu, updateMenu } from '@/api/system/menu';
import { Message } from '@arco-design/web-vue';
import { useDictStore } from '@/store';
const { visible, setVisible } = useVisible();
const { loading, setLoading } = useLoading();
const { toOptions, getDictValue } = useDictStore();
const title = ref<string>();
const isAddHandle = ref<boolean>(true);
@@ -142,11 +144,11 @@
id: undefined,
parentId: 0,
name: undefined,
type: MenuTypeEnum.PARENT_MENU.value,
type: MenuType.PARENT_MENU,
permission: undefined,
sort: undefined,
visible: MenuVisibleEnum.SHOW.value,
cache: MenuCacheEnum.ENABLED.value,
visible: MenuVisible.SHOW,
cache: MenuCache.ENABLED,
icon: undefined,
path: undefined,
component: undefined,
@@ -158,9 +160,9 @@
const emits = defineEmits(['added', 'updated']);
// 选择根目录 parentId就是 0
// 选择根目录 parentId 设置为 0
watch(() => formModel.value.type, () => {
if (formModel.value.type === MenuTypeEnum.PARENT_MENU.value) {
if (formModel.value.type === MenuType.PARENT_MENU) {
formModel.value.parentId = 0;
}
});
@@ -171,7 +173,7 @@
isAddHandle.value = true;
renderForm({ ...defaultForm(), parentId: record.parentId, sort: (record.sort || 0) + sortStep });
// 如果是父菜单默认选中子菜单 如果是子菜单默认选中功能
if (record.type === 1 || record.type === 2) {
if (record.type === MenuType.PARENT_MENU || record.type === MenuType.SUB_MENU) {
formModel.value.type = record.type + 1;
}
setVisible(true);
@@ -202,8 +204,13 @@
return false;
}
if (formModel.value.parentId === 0
&& (formModel.value.type === MenuTypeEnum.SUB_MENU.value || formModel.value.type === MenuTypeEnum.FUNCTION.value)) {
Message.error('创建子目录或功能时 父菜单不能为根目录');
&& (formModel.value.type === MenuType.SUB_MENU || formModel.value.type === MenuType.FUNCTION)) {
formRef.value.setFields({
parentId: {
status: 'error',
message: '创建子目录或功能时 父菜单不能为根目录'
}
});
return false;
}
if (isAddHandle.value) {

View File

@@ -19,7 +19,7 @@
<a-col :span="12">
<a-form-item field="status" label="菜单状态" label-col-flex="60px">
<a-select v-model="formModel.status"
:options="toOptions(MenuStatusEnum)"
:options="toOptions(menuStatusKey)"
placeholder="请选择菜单状态"
allow-clear />
</a-form-item>
@@ -99,7 +99,7 @@
</template>
<!-- 类型 -->
<template #type="{ record }">
<a-tag>{{ getEnumValue(record.type, MenuTypeEnum) }}</a-tag>
<a-tag>{{ getDictValue(menuTypeKey, record.type) }}</a-tag>
</template>
<!-- 状态 -->
<template #status="{ record }">
@@ -108,34 +108,34 @@
<a-popconfirm v-if="hasPermission('infra:system-menu:update-status')"
position="top"
type="warning"
:content="`确定要将当前节点以及所有子节点改为${toggleEnumValue(record.status, MenuStatusEnum, 'label')}?`"
@ok="updateStatus(record.id, toggleEnumValue(record.status, MenuStatusEnum))">
:content="`确定要将当前节点以及所有子节点改为${toggleDictValue(menuStatusKey, record.status, 'label')}?`"
@ok="updateStatus(record.id, toggleDictValue(menuStatusKey, record.status))">
<a-tooltip content="点击切换状态">
<a-tag :color="getEnumValue(record.status, MenuStatusEnum, 'color')" class="pointer">
{{ getEnumValue(record.status, MenuStatusEnum) }}
<a-tag :color="getDictValue(menuStatusKey, record.status, 'color')" class="pointer">
{{ getDictValue(menuStatusKey, record.status) }}
</a-tag>
</a-tooltip>
</a-popconfirm>
<a-tag v-else :color="getEnumValue(record.status, MenuStatusEnum, 'color')">
{{ getEnumValue(record.status, MenuStatusEnum) }}
<a-tag v-else :color="getDictValue(menuStatusKey, record.status, 'color')">
{{ getDictValue(menuStatusKey, record.status) }}
</a-tag>
<!-- 显示状态 -->
<a-popconfirm v-if="hasPermission('infra:system-menu:update-status')"
position="top"
type="warning"
:content="`确定要将当前节点以及所有子节点改为${toggleEnumValue(record.visible, MenuVisibleEnum, 'label')}?`"
@ok="updateVisible(record.id, toggleEnumValue(record.visible, MenuVisibleEnum))">
:content="`确定要将当前节点以及所有子节点改为${toggleDictValue(menuVisibleKey, record.visible, 'label')}?`"
@ok="updateVisible(record.id, toggleDictValue(menuVisibleKey, record.visible))">
<a-tooltip content="点击切换状态">
<a-tag v-if="(record.visible || record.visible === 0) && record.type !== MenuTypeEnum.FUNCTION.value"
:color="getEnumValue(record.visible, MenuVisibleEnum, 'color')"
<a-tag v-if="(record.visible || record.visible === 0) && record.type !== MenuType.FUNCTION"
:color="getDictValue(menuVisibleKey, record.visible, 'color')"
class="pointer">
{{ getEnumValue(record.visible, MenuVisibleEnum) }}
{{ getDictValue(menuVisibleKey, record.visible) }}
</a-tag>
</a-tooltip>
</a-popconfirm>
<a-tag v-else-if="(record.visible || record.visible === 0) && record.type !== MenuTypeEnum.FUNCTION.value"
:color="getEnumValue(record.visible, MenuVisibleEnum, 'color')">
{{ getEnumValue(record.visible, MenuVisibleEnum) }}
<a-tag v-else-if="(record.visible || record.visible === 0) && record.type !== MenuType.FUNCTION"
:color="getDictValue(menuVisibleKey, record.visible, 'color')">
{{ getDictValue(menuVisibleKey, record.visible) }}
</a-tag>
</a-space>
</template>
@@ -145,7 +145,7 @@
<!-- 新增 -->
<a-button type="text"
size="mini"
v-if="record.type !== MenuTypeEnum.FUNCTION.value"
v-if="record.type !== MenuType.FUNCTION"
v-permission="['infra:system-menu:create']"
@click="emits('openAdd', { parentId: record.id, type: record.type, sort: getMaxSort(record.children) })">
新增
@@ -185,13 +185,13 @@
import { reactive, ref } from 'vue';
import useLoading from '@/hooks/loading';
import { getMenuList, deleteMenu, updateMenuStatus, initCache } from '@/api/system/menu';
import { toOptions, getEnumValue, toggleEnumValue } from '@/utils/enum';
import { MenuStatusEnum, MenuVisibleEnum, MenuTypeEnum } from '../types/enum.types';
import { menuStatusKey, menuVisibleKey, menuTypeKey, MenuType } from '../types/const';
import columns from '../types/table.columns';
import { Message } from '@arco-design/web-vue';
import { useCacheStore } from '@/store';
import { useCacheStore, useDictStore } from '@/store';
import usePermission from '@/hooks/permission';
const { toOptions, getDictValue, toggleDictValue } = useDictStore();
const cacheStore = useCacheStore();
const { hasPermission } = usePermission();

View File

@@ -17,6 +17,7 @@
import type { TreeNodeData } from '@arco-design/web-vue';
import { useCacheStore } from '@/store';
import { computed } from 'vue';
import { MenuType } from '../types/const';
const props = defineProps({
modelValue: Number,
@@ -39,8 +40,8 @@
const treeData = (): TreeNodeData[] => {
let render = (arr: any[]): TreeNodeData[] => {
return arr.map((s) => {
// function
if (s.type === 3) {
// function 返回空
if (s.type === MenuType.FUNCTION) {
return null as unknown as TreeNodeData;
}
// 当前节点

View File

@@ -22,11 +22,15 @@
import MenuFormModal from '@/views/system/menu/components/menu-form-modal.vue';
import { onUnmounted, ref } from 'vue';
import { useCacheStore } from '@/store';
import { useCacheStore, useDictStore } from '@/store';
import { dictKeys } from './types/const';
const table = ref();
const modal = ref();
// 加载字典项
useDictStore().loadKeys(dictKeys);
// 卸载时清除 menu cache
onUnmounted(() => {
const cacheStore = useCacheStore();

View File

@@ -1 +1,39 @@
// 排序步长
export const sortStep = 10;
// 菜单类型 值
export const MenuType = {
// 父菜单
PARENT_MENU: 1,
// 子菜单
SUB_MENU: 2,
// 功能
FUNCTION: 3
};
// 菜单是否可见 值
export const MenuVisible = {
// 隐藏
HIDE: 0,
// 显示
SHOW: 1
};
// 菜单缓存状态 值
export const MenuCache = {
// 禁用
DISABLED: 0,
// 启用
ENABLED: 1
};
// 菜单类型 字典项
export const menuTypeKey = 'systemMenuType';
// 菜单状态 字典项
export const menuStatusKey = 'systemMenuStatus';
// 是否可见 字典项
export const menuVisibleKey = 'systemMenuVisible';
// 是否缓存 字典项
export const menuCacheKey = 'systemMenuCache';
export const dictKeys = [menuTypeKey, menuStatusKey, menuVisibleKey, menuCacheKey];

View File

@@ -1,63 +0,0 @@
/**
* 菜单类型
*/
export const MenuTypeEnum = {
PARENT_MENU: {
value: 1,
label: '父菜单'
},
SUB_MENU: {
value: 2,
label: '子菜单'
},
FUNCTION: {
value: 3,
label: '功能'
}
};
/**
* 菜单状态
*/
export const MenuStatusEnum = {
DISABLED: {
value: 0,
label: '停用',
color: 'orange'
},
ENABLED: {
value: 1,
label: '启用',
color: 'blue'
}
};
/**
* 菜单是否可见
*/
export const MenuVisibleEnum = {
HIDE: {
value: 0,
label: '隐藏',
color: 'orange'
},
SHOW: {
value: 1,
label: '显示',
color: 'blue'
}
};
/**
* 菜单缓存状态
*/
export const MenuCacheEnum = {
DISABLED: {
value: 0,
label: '不缓存',
},
ENABLED: {
value: 1,
label: '缓存',
}
};