!3 perf: menu add i18n
Merge pull request !3 from small monkey/menu-i18n
This commit is contained in:
commit
c53f320fef
@ -551,19 +551,40 @@ const local: App.I18n.Schema = {
|
|||||||
},
|
},
|
||||||
menu: {
|
menu: {
|
||||||
title: 'Menu List',
|
title: 'Menu List',
|
||||||
|
parentId: 'Parent Menu',
|
||||||
|
iconType: 'Icon Type',
|
||||||
menuName: 'Menu Name',
|
menuName: 'Menu Name',
|
||||||
icon: 'Menu Icon',
|
icon: 'Menu Icon',
|
||||||
sort: 'Sort',
|
orderNum: 'Sort',
|
||||||
permission: 'Permission',
|
perms: 'Permission Code',
|
||||||
component: 'Component Path',
|
component: 'Component Path',
|
||||||
path: 'Route Path',
|
path: 'Route Path',
|
||||||
|
externalPath: 'External Path',
|
||||||
query: 'Route Parameters',
|
query: 'Route Parameters',
|
||||||
|
iframeQuery: 'Iframe Address',
|
||||||
isFrame: 'External Link',
|
isFrame: 'External Link',
|
||||||
isCache: 'Cache',
|
isCache: 'Cache',
|
||||||
menuType: 'Menu Type',
|
menuType: 'Menu Type',
|
||||||
visible: 'Visible',
|
visible: 'Visible',
|
||||||
status: 'Status',
|
status: 'Status',
|
||||||
createTime: 'Create Time',
|
createTime: 'Create Time',
|
||||||
|
cache: 'cache',
|
||||||
|
noCache: 'No Cache',
|
||||||
|
rootName: 'Root',
|
||||||
|
buttonPermissionList: 'Button Permission List',
|
||||||
|
emptyMenu: 'Empty Menu',
|
||||||
|
menuDetail: 'Menu Detail',
|
||||||
|
iconifyTip: 'iconify address:`https://icones.js.org`',
|
||||||
|
isFrameTip: 'If you choose External Link, the routing address needs to start with `http(s)://`',
|
||||||
|
isCacheTip:
|
||||||
|
'If you select yes, it will be cached by `keep-alive`, and the `name` and address of the matching component must be consistent',
|
||||||
|
visibleTip: 'If you choose Hide, the route will not appear in the sidebar, but it can still be accessed.',
|
||||||
|
statusTip: 'If you choose to disable, the route will not appear in the sidebar and cannot be accessed.',
|
||||||
|
permsTip: "Permission string defined in the controller, such as: @SaCheckPermission('system:user:list')",
|
||||||
|
componentTip:
|
||||||
|
'The component path to access, such as: `system/user/index`, which is in the `views` directory by default',
|
||||||
|
pathTip:
|
||||||
|
'Router path,Example:`user`,If the external network address needs to be accessed in the internal link,then `http(s)://` beginning',
|
||||||
form: {
|
form: {
|
||||||
parentId: {
|
parentId: {
|
||||||
required: 'Please select Parent Menu',
|
required: 'Please select Parent Menu',
|
||||||
@ -581,9 +602,13 @@ const local: App.I18n.Schema = {
|
|||||||
required: 'Please enter Menu Name',
|
required: 'Please enter Menu Name',
|
||||||
invalid: 'Menu Name cannot be empty'
|
invalid: 'Menu Name cannot be empty'
|
||||||
},
|
},
|
||||||
sort: {
|
perms: {
|
||||||
required: 'Please enter Sort',
|
required: 'Please enter permission code',
|
||||||
invalid: 'Sort cannot be empty'
|
invalid: 'Permission code cannot be empty'
|
||||||
|
},
|
||||||
|
orderNum: {
|
||||||
|
required: 'Please enter order num',
|
||||||
|
invalid: 'Order num cannot be empty'
|
||||||
},
|
},
|
||||||
isFrame: {
|
isFrame: {
|
||||||
required: 'Please select External Link',
|
required: 'Please select External Link',
|
||||||
@ -618,10 +643,18 @@ const local: App.I18n.Schema = {
|
|||||||
invalid: 'Permission cannot be empty'
|
invalid: 'Permission cannot be empty'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
placeholder: {
|
||||||
|
iconifyIconPlaceholder: 'Please enter an icon',
|
||||||
|
localIconPlaceholder: 'Please select the local icon',
|
||||||
|
queryKey: 'Please enter a key',
|
||||||
|
queryValue: 'Please enter a value',
|
||||||
|
queryIframe: 'Please enter a iframe address'
|
||||||
|
},
|
||||||
directory: 'Directory',
|
directory: 'Directory',
|
||||||
menu: 'Menu',
|
menu: 'Menu',
|
||||||
button: 'Button',
|
button: 'Button',
|
||||||
addMenu: 'Add Menu',
|
addMenu: 'Add Menu',
|
||||||
|
addChildMenu: 'Add Child Menu',
|
||||||
editMenu: 'Edit Menu'
|
editMenu: 'Edit Menu'
|
||||||
},
|
},
|
||||||
notice: {
|
notice: {
|
||||||
|
@ -551,19 +551,38 @@ const local: App.I18n.Schema = {
|
|||||||
},
|
},
|
||||||
menu: {
|
menu: {
|
||||||
title: '菜单列表',
|
title: '菜单列表',
|
||||||
|
parentId: '上级菜单',
|
||||||
|
iconType: '图标类型',
|
||||||
menuName: '菜单名称',
|
menuName: '菜单名称',
|
||||||
icon: '菜单图标',
|
icon: '菜单图标',
|
||||||
sort: '排序',
|
orderNum: '排序',
|
||||||
permission: '权限标识',
|
perms: '权限字符',
|
||||||
component: '组件路径',
|
component: '组件路径',
|
||||||
path: '路由地址',
|
path: '路由地址',
|
||||||
|
externalPath: '外链地址',
|
||||||
query: '路由参数',
|
query: '路由参数',
|
||||||
|
iframeQuery: 'iframe 地址',
|
||||||
isFrame: '是否外链',
|
isFrame: '是否外链',
|
||||||
isCache: '是否缓存',
|
isCache: '是否缓存',
|
||||||
menuType: '菜单类型',
|
menuType: '菜单类型',
|
||||||
visible: '显示状态',
|
visible: '显示状态',
|
||||||
status: '菜单状态',
|
status: '菜单状态',
|
||||||
createTime: '创建时间',
|
createTime: '创建时间',
|
||||||
|
cache: '缓存',
|
||||||
|
noCache: '不缓存',
|
||||||
|
rootName: '根目录',
|
||||||
|
buttonPermissionList: '按钮权限列表',
|
||||||
|
emptyMenu: '暂无菜单',
|
||||||
|
menuDetail: '菜单详情',
|
||||||
|
iconifyTip: 'iconify 地址:https://icones.js.org',
|
||||||
|
isFrameTip: '选择是外链则路由地址需要以`http(s)://`开头',
|
||||||
|
isCacheTip: '选择是则会被`keep-alive`缓存,需要匹配组件的`name`和地址保持一致',
|
||||||
|
visibleTip: '选择隐藏则路由将不会出现在侧边栏,但仍然可以访问',
|
||||||
|
statusTip: '选择停用则路由将不会出现在侧边栏,也不能被访问',
|
||||||
|
permsTip: "控制器中定义的权限字符,如:`@SaCheckPermission('system:user:list')`",
|
||||||
|
componentTip: '访问的组件路径,如:`system/user/index`,默认在`views`目录下',
|
||||||
|
pathTip:
|
||||||
|
'Router path,Example:`user`,If the external network address needs to be accessed in the internal link,then `http(s)://` beginning',
|
||||||
form: {
|
form: {
|
||||||
parentId: {
|
parentId: {
|
||||||
required: '请选择上级菜单',
|
required: '请选择上级菜单',
|
||||||
@ -581,10 +600,14 @@ const local: App.I18n.Schema = {
|
|||||||
required: '请输入菜单名称',
|
required: '请输入菜单名称',
|
||||||
invalid: '菜单名称不能为空'
|
invalid: '菜单名称不能为空'
|
||||||
},
|
},
|
||||||
sort: {
|
orderNum: {
|
||||||
required: '请输入排序',
|
required: '请输入排序',
|
||||||
invalid: '排序不能为空'
|
invalid: '排序不能为空'
|
||||||
},
|
},
|
||||||
|
perms: {
|
||||||
|
required: '请输入权限字符',
|
||||||
|
invalid: '权限字符不能为空'
|
||||||
|
},
|
||||||
isFrame: {
|
isFrame: {
|
||||||
required: '请选择是否外链',
|
required: '请选择是否外链',
|
||||||
invalid: '是否外链不能为空'
|
invalid: '是否外链不能为空'
|
||||||
@ -618,10 +641,18 @@ const local: App.I18n.Schema = {
|
|||||||
invalid: '权限标识不能为空'
|
invalid: '权限标识不能为空'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
placeholder: {
|
||||||
|
iconifyIconPlaceholder: '请输入图标',
|
||||||
|
localIconPlaceholder: '请选择本地图标',
|
||||||
|
queryKey: '请输入 Key',
|
||||||
|
queryValue: '请输入 Value',
|
||||||
|
queryIframe: '请输入 iframe 地址'
|
||||||
|
},
|
||||||
directory: '目录',
|
directory: '目录',
|
||||||
menu: '菜单',
|
menu: '菜单',
|
||||||
button: '按钮',
|
button: '按钮',
|
||||||
addMenu: '新增菜单',
|
addMenu: '新增菜单',
|
||||||
|
addChildMenu: '新增子菜单',
|
||||||
editMenu: '编辑菜单'
|
editMenu: '编辑菜单'
|
||||||
},
|
},
|
||||||
notice: {
|
notice: {
|
||||||
|
33
src/typings/app.d.ts
vendored
33
src/typings/app.d.ts
vendored
@ -657,25 +657,44 @@ declare namespace App {
|
|||||||
};
|
};
|
||||||
menu: {
|
menu: {
|
||||||
title: string;
|
title: string;
|
||||||
|
parentId: string;
|
||||||
|
iconType: string;
|
||||||
menuName: string;
|
menuName: string;
|
||||||
icon: string;
|
icon: string;
|
||||||
sort: string;
|
orderNum: string;
|
||||||
permission: string;
|
perms: string;
|
||||||
component: string;
|
component: string;
|
||||||
path: string;
|
path: string;
|
||||||
|
externalPath: string;
|
||||||
query: string;
|
query: string;
|
||||||
|
iframeQuery: string;
|
||||||
isFrame: string;
|
isFrame: string;
|
||||||
isCache: string;
|
isCache: string;
|
||||||
menuType: string;
|
menuType: string;
|
||||||
visible: string;
|
visible: string;
|
||||||
status: string;
|
status: string;
|
||||||
createTime: string;
|
createTime: string;
|
||||||
|
cache: string;
|
||||||
|
noCache: string;
|
||||||
|
rootName: string;
|
||||||
|
buttonPermissionList: string;
|
||||||
|
emptyMenu: string;
|
||||||
|
menuDetail: string;
|
||||||
|
iconifyTip: string;
|
||||||
|
isFrameTip: string;
|
||||||
|
isCacheTip: string;
|
||||||
|
visibleTip: string;
|
||||||
|
statusTip: string;
|
||||||
|
permsTip: string;
|
||||||
|
componentTip: string;
|
||||||
|
pathTip: string;
|
||||||
form: {
|
form: {
|
||||||
parentId: FormMsg;
|
parentId: FormMsg;
|
||||||
menuType: FormMsg;
|
menuType: FormMsg;
|
||||||
icon: FormMsg;
|
icon: FormMsg;
|
||||||
menuName: FormMsg;
|
menuName: FormMsg;
|
||||||
sort: FormMsg;
|
orderNum: FormMsg;
|
||||||
|
perms: FormMsg;
|
||||||
isFrame: FormMsg;
|
isFrame: FormMsg;
|
||||||
path: FormMsg;
|
path: FormMsg;
|
||||||
component: FormMsg;
|
component: FormMsg;
|
||||||
@ -685,10 +704,18 @@ declare namespace App {
|
|||||||
status: FormMsg;
|
status: FormMsg;
|
||||||
permission: FormMsg;
|
permission: FormMsg;
|
||||||
};
|
};
|
||||||
|
placeholder: {
|
||||||
|
iconifyIconPlaceholder: string;
|
||||||
|
localIconPlaceholder: string;
|
||||||
|
queryKey: string;
|
||||||
|
queryValue: string;
|
||||||
|
queryIframe: string;
|
||||||
|
};
|
||||||
directory: string;
|
directory: string;
|
||||||
menu: string;
|
menu: string;
|
||||||
button: string;
|
button: string;
|
||||||
addMenu: string;
|
addMenu: string;
|
||||||
|
addChildMenu: string;
|
||||||
editMenu: string;
|
editMenu: string;
|
||||||
};
|
};
|
||||||
notice: {
|
notice: {
|
||||||
|
@ -46,7 +46,7 @@ const getMeunTree = async () => {
|
|||||||
treeData.value = [
|
treeData.value = [
|
||||||
{
|
{
|
||||||
menuId: 0,
|
menuId: 0,
|
||||||
menuName: '根目录',
|
menuName: $t('page.system.menu.rootName'),
|
||||||
icon: 'material-symbols:home-outline-rounded',
|
icon: 'material-symbols:home-outline-rounded',
|
||||||
children: handleTree(data, { idField: 'menuId', filterFn: item => item.menuType !== 'F' })
|
children: handleTree(data, { idField: 'menuId', filterFn: item => item.menuType !== 'F' })
|
||||||
}
|
}
|
||||||
@ -112,7 +112,7 @@ function renderSuffix({ option }: { option: TreeOption }) {
|
|||||||
text
|
text
|
||||||
class="h-18px"
|
class="h-18px"
|
||||||
icon="ic-round-plus"
|
icon="ic-round-plus"
|
||||||
tooltip-content="新增子菜单"
|
tooltip-content={$t('page.system.menu.addChildMenu')}
|
||||||
onClick={(event: Event) => {
|
onClick={(event: Event) => {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
handleAddMenu(option.menuId as CommonType.IdType);
|
handleAddMenu(option.menuId as CommonType.IdType);
|
||||||
@ -203,18 +203,18 @@ const btnColumns: DataTableColumns<Api.System.Menu> = [
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '权限名称',
|
title: $t('page.system.menu.menuName'),
|
||||||
key: 'menuName',
|
key: 'menuName',
|
||||||
minWidth: 120
|
minWidth: 120
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '权限标识',
|
title: $t('page.system.menu.perms'),
|
||||||
key: 'perms',
|
key: 'perms',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
minWidth: 120
|
minWidth: 120
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '状态',
|
title: $t('page.system.menu.status'),
|
||||||
key: 'status',
|
key: 'status',
|
||||||
minWidth: 80,
|
minWidth: 80,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
@ -223,13 +223,13 @@ const btnColumns: DataTableColumns<Api.System.Menu> = [
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '创建时间',
|
title: $t('page.system.menu.createTime'),
|
||||||
key: 'createTime',
|
key: 'createTime',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
minWidth: 150
|
minWidth: 150
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: $t('common.action'),
|
||||||
key: 'actions',
|
key: 'actions',
|
||||||
width: 80,
|
width: 80,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
@ -286,27 +286,27 @@ const btnColumns: DataTableColumns<Api.System.Menu> = [
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<TableSiderLayout default-expanded>
|
<TableSiderLayout default-expanded>
|
||||||
<template #header>菜单列表</template>
|
<template #header>{{ $t('page.system.menu.title') }}</template>
|
||||||
<template #header-extra>
|
<template #header-extra>
|
||||||
<ButtonIcon
|
<ButtonIcon
|
||||||
v-if="hasAuth('system:menu:add')"
|
v-if="hasAuth('system:menu:add')"
|
||||||
size="small"
|
size="small"
|
||||||
icon="material-symbols:add-rounded"
|
icon="material-symbols:add-rounded"
|
||||||
class="h-28px text-icon"
|
class="h-28px text-icon"
|
||||||
tooltip-content="新增菜单"
|
:tooltip-content="$t('page.system.menu.addMenu')"
|
||||||
@click.stop="handleAddMenu(0)"
|
@click.stop="handleAddMenu(0)"
|
||||||
/>
|
/>
|
||||||
<ButtonIcon
|
<ButtonIcon
|
||||||
size="small"
|
size="small"
|
||||||
icon="material-symbols:refresh-rounded"
|
icon="material-symbols:refresh-rounded"
|
||||||
class="h-28px text-icon"
|
class="h-28px text-icon"
|
||||||
tooltip-content="刷新"
|
:tooltip-content="$t('common.refresh')"
|
||||||
@click.stop="reset"
|
@click.stop="reset"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #sider>
|
<template #sider>
|
||||||
<div class="flex gap-6px">
|
<div class="flex gap-6px">
|
||||||
<NInput v-model:value="name" size="small" placeholder="请输入菜单名称" />
|
<NInput v-model:value="name" size="small" :placeholder="$t('page.system.menu.form.menuName.required')" />
|
||||||
</div>
|
</div>
|
||||||
<NSpin :show="loading" class="infinite-scroll">
|
<NSpin :show="loading" class="infinite-scroll">
|
||||||
<NTree
|
<NTree
|
||||||
@ -330,7 +330,7 @@ const btnColumns: DataTableColumns<Api.System.Menu> = [
|
|||||||
@update:selected-keys="(_: Array<string & number>, option: Array<TreeOption | null>) => handleClickTree(option)"
|
@update:selected-keys="(_: Array<string & number>, option: Array<TreeOption | null>) => handleClickTree(option)"
|
||||||
>
|
>
|
||||||
<template #empty>
|
<template #empty>
|
||||||
<NEmpty description="暂无菜单" class="h-full min-h-200px justify-center" />
|
<NEmpty :description="$t('page.system.menu.emptyMenu')" class="h-full min-h-200px justify-center" />
|
||||||
</template>
|
</template>
|
||||||
</NTree>
|
</NTree>
|
||||||
</NSpin>
|
</NSpin>
|
||||||
@ -338,7 +338,7 @@ const btnColumns: DataTableColumns<Api.System.Menu> = [
|
|||||||
<div class="h-full flex-col-stretch gap-16px">
|
<div class="h-full flex-col-stretch gap-16px">
|
||||||
<template v-if="currentMenu">
|
<template v-if="currentMenu">
|
||||||
<NCard
|
<NCard
|
||||||
title="菜单详情"
|
:title="$t('page.system.menu.menuDetail')"
|
||||||
:bordered="false"
|
:bordered="false"
|
||||||
size="small"
|
size="small"
|
||||||
class="max-h-50% card-wrapper"
|
class="max-h-50% card-wrapper"
|
||||||
@ -356,13 +356,13 @@ const btnColumns: DataTableColumns<Api.System.Menu> = [
|
|||||||
<template #icon>
|
<template #icon>
|
||||||
<icon-material-symbols-add-rounded />
|
<icon-material-symbols-add-rounded />
|
||||||
</template>
|
</template>
|
||||||
新增子菜单
|
{{ $t('page.system.menu.addChildMenu') }}
|
||||||
</NButton>
|
</NButton>
|
||||||
<NButton v-if="hasAuth('system:menu:edit')" size="small" ghost type="primary" @click="handleUpdateMenu">
|
<NButton v-if="hasAuth('system:menu:edit')" size="small" ghost type="primary" @click="handleUpdateMenu">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<icon-material-symbols-drive-file-rename-outline-outline />
|
<icon-material-symbols-drive-file-rename-outline-outline />
|
||||||
</template>
|
</template>
|
||||||
编辑
|
{{ $t('common.edit') }}
|
||||||
</NButton>
|
</NButton>
|
||||||
<NPopconfirm @positive-click="() => handleDeleteMenu()">
|
<NPopconfirm @positive-click="() => handleDeleteMenu()">
|
||||||
<template #trigger>
|
<template #trigger>
|
||||||
@ -391,46 +391,50 @@ const btnColumns: DataTableColumns<Api.System.Menu> = [
|
|||||||
label-class="w-20% min-w-88px"
|
label-class="w-20% min-w-88px"
|
||||||
content-class="w-100px"
|
content-class="w-100px"
|
||||||
>
|
>
|
||||||
<NDescriptionsItem label="菜单类型">
|
<NDescriptionsItem :label="$t('page.system.menu.menuName')">
|
||||||
<NTag class="m-1" size="small" type="primary">{{ menuTypeRecord[currentMenu.menuType!] }}</NTag>
|
<NTag class="m-1" size="small" type="primary">{{ menuTypeRecord[currentMenu.menuType!] }}</NTag>
|
||||||
</NDescriptionsItem>
|
</NDescriptionsItem>
|
||||||
<NDescriptionsItem label="菜单状态">
|
<NDescriptionsItem :label="$t('page.system.menu.status')">
|
||||||
<DictTag size="small" :value="currentMenu.status" dict-code="sys_normal_disable" />
|
<DictTag size="small" :value="currentMenu.status" dict-code="sys_normal_disable" />
|
||||||
</NDescriptionsItem>
|
</NDescriptionsItem>
|
||||||
<NDescriptionsItem label="菜单名称">{{ currentMenu.menuName }}</NDescriptionsItem>
|
<NDescriptionsItem :label="$t('page.system.menu.addChildMenu')">
|
||||||
<NDescriptionsItem v-if="currentMenu.menuType === 'C'" label="组件路径">
|
{{ currentMenu.menuName }}
|
||||||
|
</NDescriptionsItem>
|
||||||
|
<NDescriptionsItem v-if="currentMenu.menuType === 'C'" :label="$t('page.system.menu.component')">
|
||||||
{{ currentMenu.component }}
|
{{ currentMenu.component }}
|
||||||
</NDescriptionsItem>
|
</NDescriptionsItem>
|
||||||
<NDescriptionsItem :label="currentMenu.isFrame !== '0' ? '路由地址' : '外链地址'">
|
<NDescriptionsItem
|
||||||
|
:label="currentMenu.isFrame !== '0' ? $t('page.system.menu.path') : $t('page.system.menu.externalPath')"
|
||||||
|
>
|
||||||
{{ currentMenu.path }}
|
{{ currentMenu.path }}
|
||||||
</NDescriptionsItem>
|
</NDescriptionsItem>
|
||||||
<NDescriptionsItem
|
<NDescriptionsItem
|
||||||
v-if="currentMenu.menuType === 'C'"
|
v-if="currentMenu.menuType === 'C'"
|
||||||
:label="currentMenu.isFrame !== '2' ? '路由参数' : 'iframe 地址'"
|
:label="currentMenu.isFrame !== '2' ? $t('page.system.menu.query') : $t('page.system.menu.iframeQuery')"
|
||||||
>
|
>
|
||||||
{{ currentMenu.queryParam }}
|
{{ currentMenu.queryParam }}
|
||||||
</NDescriptionsItem>
|
</NDescriptionsItem>
|
||||||
<NDescriptionsItem v-if="currentMenu.menuType !== 'M'" label="权限标识">
|
<NDescriptionsItem v-if="currentMenu.menuType !== 'M'" :label="$t('page.system.menu.perms')">
|
||||||
{{ currentMenu.perms }}
|
{{ currentMenu.perms }}
|
||||||
</NDescriptionsItem>
|
</NDescriptionsItem>
|
||||||
<NDescriptionsItem label="是否外链">
|
<NDescriptionsItem :label="$t('page.system.menu.isFrame')">
|
||||||
<NTag v-if="currentMenu.isFrame" class="m-1" size="small" :type="tagMap[currentMenu.isFrame]">
|
<NTag v-if="currentMenu.isFrame" class="m-1" size="small" :type="tagMap[currentMenu.isFrame]">
|
||||||
{{ menuIsFrameRecord[currentMenu.isFrame] }}
|
{{ menuIsFrameRecord[currentMenu.isFrame] }}
|
||||||
</NTag>
|
</NTag>
|
||||||
</NDescriptionsItem>
|
</NDescriptionsItem>
|
||||||
<NDescriptionsItem label="显示状态">
|
<NDescriptionsItem :label="$t('page.system.menu.visible')">
|
||||||
<DictTag size="small" :value="currentMenu.visible" dict-code="sys_show_hide" />
|
<DictTag size="small" :value="currentMenu.visible" dict-code="sys_show_hide" />
|
||||||
</NDescriptionsItem>
|
</NDescriptionsItem>
|
||||||
<NDescriptionsItem v-if="currentMenu.menuType === 'C'" label="是否缓存">
|
<NDescriptionsItem v-if="currentMenu.menuType === 'C'" :label="$t('page.system.menu.isCache')">
|
||||||
<NTag v-if="currentMenu.isCache" class="m-1" size="small" :type="tagMap[currentMenu.isCache]">
|
<NTag v-if="currentMenu.isCache" class="m-1" size="small" :type="tagMap[currentMenu.isCache]">
|
||||||
{{ currentMenu.isCache === '0' ? '缓存' : '不缓存' }}
|
{{ currentMenu.isCache === '0' ? $t('page.system.menu.cache') : $t('page.system.menu.noCache') }}
|
||||||
</NTag>
|
</NTag>
|
||||||
</NDescriptionsItem>
|
</NDescriptionsItem>
|
||||||
</NDescriptions>
|
</NDescriptions>
|
||||||
</NCard>
|
</NCard>
|
||||||
|
|
||||||
<NCard
|
<NCard
|
||||||
title="按钮权限列表"
|
:title="$t('page.system.menu.buttonPermissionList')"
|
||||||
:bordered="false"
|
:bordered="false"
|
||||||
size="small"
|
size="small"
|
||||||
class="h-full overflow-auto card-wrapper"
|
class="h-full overflow-auto card-wrapper"
|
||||||
@ -441,7 +445,7 @@ const btnColumns: DataTableColumns<Api.System.Menu> = [
|
|||||||
size="small"
|
size="small"
|
||||||
icon="ic-round-refresh"
|
icon="ic-round-refresh"
|
||||||
class="h-28px text-icon"
|
class="h-28px text-icon"
|
||||||
tooltip-content="刷新"
|
:tooltip-content="$t('common.refresh')"
|
||||||
@click.stop="getBtnMenuList"
|
@click.stop="getBtnMenuList"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
@ -45,8 +45,8 @@ const queryList = ref<{ key: string; value: string }[]>([]);
|
|||||||
|
|
||||||
const drawerTitle = computed(() => {
|
const drawerTitle = computed(() => {
|
||||||
const titles: Record<NaiveUI.TableOperateType, string> = {
|
const titles: Record<NaiveUI.TableOperateType, string> = {
|
||||||
add: '新增菜单',
|
add: $t('page.system.menu.addMenu'),
|
||||||
edit: '编辑菜单'
|
edit: $t('page.system.menu.editMenu')
|
||||||
};
|
};
|
||||||
return titles[props.operateType];
|
return titles[props.operateType];
|
||||||
});
|
});
|
||||||
@ -69,7 +69,7 @@ function createDefaultModel(): Model {
|
|||||||
visible: '0',
|
visible: '0',
|
||||||
status: '0',
|
status: '0',
|
||||||
perms: '',
|
perms: '',
|
||||||
icon: '',
|
icon: undefined,
|
||||||
remark: ''
|
remark: ''
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -77,10 +77,10 @@ function createDefaultModel(): Model {
|
|||||||
type RuleKey = Extract<keyof Model, 'menuName' | 'orderNum' | 'path' | 'component'>;
|
type RuleKey = Extract<keyof Model, 'menuName' | 'orderNum' | 'path' | 'component'>;
|
||||||
|
|
||||||
const rules: Record<RuleKey, App.Global.FormRule> = {
|
const rules: Record<RuleKey, App.Global.FormRule> = {
|
||||||
menuName: createRequiredRule('菜单名称不能为空'),
|
menuName: createRequiredRule($t('page.system.menu.form.menuName.invalid')),
|
||||||
orderNum: createNumberRequiredRule('菜单排序不能为空'),
|
orderNum: createNumberRequiredRule($t('page.system.menu.form.orderNum.invalid')),
|
||||||
path: createRequiredRule('路由地址不能为空'),
|
path: createRequiredRule($t('page.system.menu.form.path.invalid')),
|
||||||
component: createRequiredRule('组件路径不能为空')
|
component: createRequiredRule($t('page.system.menu.form.component.invalid'))
|
||||||
};
|
};
|
||||||
|
|
||||||
const isBtn = computed(() => model.menuType === 'F');
|
const isBtn = computed(() => model.menuType === 'F');
|
||||||
@ -228,17 +228,22 @@ function onCreate() {
|
|||||||
<NDrawerContent :title="drawerTitle" :native-scrollbar="false" closable>
|
<NDrawerContent :title="drawerTitle" :native-scrollbar="false" closable>
|
||||||
<NForm ref="formRef" :model="model" :rules="rules">
|
<NForm ref="formRef" :model="model" :rules="rules">
|
||||||
<NGrid responsive="screen" item-responsive>
|
<NGrid responsive="screen" item-responsive>
|
||||||
<NFormItemGi :span="24" label="上级菜单" path="pid">
|
<NFormItemGi :span="24" :label="$t('page.system.menu.parentId')" path="pid">
|
||||||
<NTreeSelect
|
<NTreeSelect
|
||||||
v-model:value="model.parentId"
|
v-model:value="model.parentId"
|
||||||
:options="treeData as []"
|
:options="treeData as []"
|
||||||
label-field="menuName"
|
label-field="menuName"
|
||||||
key-field="menuId"
|
key-field="menuId"
|
||||||
:default-expanded-keys="[0]"
|
:default-expanded-keys="[0]"
|
||||||
placeholder="请选择上级菜单"
|
:placeholder="$t('page.system.menu.form.parentId.required')"
|
||||||
/>
|
/>
|
||||||
</NFormItemGi>
|
</NFormItemGi>
|
||||||
<NFormItemGi v-if="model.menuType !== 'F'" :span="24" label="菜单类型" path="menuType">
|
<NFormItemGi
|
||||||
|
v-if="model.menuType !== 'F'"
|
||||||
|
:span="24"
|
||||||
|
:label="$t('page.system.menu.menuType')"
|
||||||
|
path="menuType"
|
||||||
|
>
|
||||||
<NRadioGroup v-model:value="model.menuType">
|
<NRadioGroup v-model:value="model.menuType">
|
||||||
<NRadioButton
|
<NRadioButton
|
||||||
v-for="item in menuTypeOptions.filter(item => item.value !== 'F')"
|
v-for="item in menuTypeOptions.filter(item => item.value !== 'F')"
|
||||||
@ -248,10 +253,10 @@ function onCreate() {
|
|||||||
/>
|
/>
|
||||||
</NRadioGroup>
|
</NRadioGroup>
|
||||||
</NFormItemGi>
|
</NFormItemGi>
|
||||||
<NFormItemGi :span="24" label="菜单名称" path="menuName">
|
<NFormItemGi :span="24" :label="$t('page.system.menu.menuName')" path="menuName">
|
||||||
<NInput v-model:value="model.menuName" placeholder="请输入菜单名称" />
|
<NInput v-model:value="model.menuName" :placeholder="$t('page.system.menu.form.menuName.required')" />
|
||||||
</NFormItemGi>
|
</NFormItemGi>
|
||||||
<NFormItemGi v-if="!isBtn" span="24" label="图标类型">
|
<NFormItemGi v-if="!isBtn" span="24" :label="$t('page.system.menu.iconType')">
|
||||||
<NRadioGroup v-model:value="iconType">
|
<NRadioGroup v-model:value="iconType">
|
||||||
<NRadio v-for="item in menuIconTypeOptions" :key="item.value" :value="item.value" :label="item.label" />
|
<NRadio v-for="item in menuIconTypeOptions" :key="item.value" :value="item.value" :label="item.label" />
|
||||||
</NRadioGroup>
|
</NRadioGroup>
|
||||||
@ -259,40 +264,51 @@ function onCreate() {
|
|||||||
<NFormItemGi v-if="!isBtn" span="24" path="icon">
|
<NFormItemGi v-if="!isBtn" span="24" path="icon">
|
||||||
<template #label>
|
<template #label>
|
||||||
<div class="flex-center">
|
<div class="flex-center">
|
||||||
<FormTip content="iconify 地址:`https://icones.js.org`" />
|
<FormTip :content="$t('page.system.menu.iconifyTip')" />
|
||||||
<span class="pl-3px">菜单图标</span>
|
<span class="pl-3px">{{ $t('page.system.menu.icon') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-if="iconType === '1'">
|
<template v-if="iconType === '1'">
|
||||||
<NInput v-model:value="model.icon" placeholder="请输入图标" class="flex-1">
|
<NInput
|
||||||
|
v-model:value="model.icon"
|
||||||
|
:placeholder="$t('page.system.menu.placeholder.iconifyIconPlaceholder')"
|
||||||
|
class="flex-1"
|
||||||
|
>
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<SvgIcon v-if="model.icon" :icon="model.icon" class="text-icon" />
|
<SvgIcon v-if="model.icon" :icon="model.icon" class="text-icon" />
|
||||||
</template>
|
</template>
|
||||||
</NInput>
|
</NInput>
|
||||||
</template>
|
</template>
|
||||||
<template v-if="iconType === '2'">
|
<template v-if="iconType === '2'">
|
||||||
<NSelect v-model:value="model.icon" placeholder="请选择本地图标" filterable :options="localIconOptions" />
|
<NSelect
|
||||||
|
v-model:value="model.icon"
|
||||||
|
:placeholder="$t('page.system.menu.placeholder.localIconPlaceholder')"
|
||||||
|
filterable
|
||||||
|
:options="localIconOptions"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</NFormItemGi>
|
</NFormItemGi>
|
||||||
<NFormItemGi v-if="!isBtn" :span="24" path="path">
|
<NFormItemGi v-if="!isBtn" :span="24" path="path">
|
||||||
<template #label>
|
<template #label>
|
||||||
<div class="flex-center">
|
<div class="flex-center">
|
||||||
<FormTip content="访问的路由地址,如:`user`,如外网地址需内链访问则以 `http(s)://` 开头" />
|
<FormTip :content="$t('page.system.menu.pathTip')" />
|
||||||
<span>{{ model.isFrame !== '0' ? '路由地址' : '外链地址' }}</span>
|
<span>
|
||||||
|
{{ model.isFrame !== '0' ? $t('page.system.menu.path') : $t('page.system.menu.externalPath') }}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<NInput v-model:value="model.path" placeholder="请输入路由地址" />
|
<NInput v-model:value="model.path" :placeholder="$t('page.system.menu.form.path.required')" />
|
||||||
</NFormItemGi>
|
</NFormItemGi>
|
||||||
<NFormItemGi v-if="isMenu && model.isFrame === '1'" :span="24" path="component">
|
<NFormItemGi v-if="isMenu && model.isFrame === '1'" :span="24" path="component">
|
||||||
<template #label>
|
<template #label>
|
||||||
<div class="flex-center">
|
<div class="flex-center">
|
||||||
<FormTip content="访问的组件路径,如:`system/user/index`,默认在`views`目录下" />
|
<FormTip :content="$t('page.system.menu.componentTip')" />
|
||||||
<span>组件路径</span>
|
<span>{{ $t('page.system.menu.component') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<NInputGroup>
|
<NInputGroup>
|
||||||
<NInputGroupLabel>views/</NInputGroupLabel>
|
<NInputGroupLabel>views/</NInputGroupLabel>
|
||||||
<NInput v-model:value="model.component" placeholder="请输入组件地址" />
|
<NInput v-model:value="model.component" :placeholder="$t('page.system.menu.form.path.required')" />
|
||||||
<NInputGroupLabel>/index.vue</NInputGroupLabel>
|
<NInputGroupLabel>/index.vue</NInputGroupLabel>
|
||||||
</NInputGroup>
|
</NInputGroup>
|
||||||
</NFormItemGi>
|
</NFormItemGi>
|
||||||
@ -300,7 +316,7 @@ function onCreate() {
|
|||||||
v-if="isMenu && model.isFrame !== '0'"
|
v-if="isMenu && model.isFrame !== '0'"
|
||||||
span="24"
|
span="24"
|
||||||
:show-feedback="!queryList.length"
|
:show-feedback="!queryList.length"
|
||||||
:label="model.isFrame !== '2' ? '路由参数' : 'iframe 地址'"
|
:label="model.isFrame !== '2' ? $t('page.system.menu.query') : $t('page.system.menu.iframeQuery')"
|
||||||
>
|
>
|
||||||
<NDynamicInput
|
<NDynamicInput
|
||||||
v-if="model.isFrame !== '2'"
|
v-if="model.isFrame !== '2'"
|
||||||
@ -315,7 +331,10 @@ function onCreate() {
|
|||||||
ignore-path-change
|
ignore-path-change
|
||||||
:show-label="false"
|
:show-label="false"
|
||||||
:path="`query[${index}].key`"
|
:path="`query[${index}].key`"
|
||||||
:rule="{ ...createRequiredRule('请输入 Key'), validator: value => isNotNull(value) }"
|
:rule="{
|
||||||
|
...createRequiredRule($t('page.system.menu.placeholder.queryKey')),
|
||||||
|
validator: value => isNotNull(value)
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<NInput v-model:value="queryList[index].key" placeholder="Key" @keydown.enter.prevent />
|
<NInput v-model:value="queryList[index].key" placeholder="Key" @keydown.enter.prevent />
|
||||||
</NFormItem>
|
</NFormItem>
|
||||||
@ -325,29 +344,36 @@ function onCreate() {
|
|||||||
ignore-path-change
|
ignore-path-change
|
||||||
:show-label="false"
|
:show-label="false"
|
||||||
:path="`query[${index}].value`"
|
:path="`query[${index}].value`"
|
||||||
:rule="{ ...createRequiredRule('请输入 Value'), validator: value => isNotNull(value) }"
|
:rule="{
|
||||||
|
...createRequiredRule($t('page.system.menu.placeholder.queryValue')),
|
||||||
|
validator: value => isNotNull(value)
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<NInput v-model:value="queryList[index].value" placeholder="Value" @keydown.enter.prevent />
|
<NInput v-model:value="queryList[index].value" placeholder="Value" @keydown.enter.prevent />
|
||||||
</NFormItem>
|
</NFormItem>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</NDynamicInput>
|
</NDynamicInput>
|
||||||
<NInput v-else v-model:value="model.queryParam" placeholder="请输入 iframe 地址" />
|
<NInput
|
||||||
|
v-else
|
||||||
|
v-model:value="model.queryParam"
|
||||||
|
:placeholder="$t('page.system.menu.placeholder.queryIframe')"
|
||||||
|
/>
|
||||||
</NFormItemGi>
|
</NFormItemGi>
|
||||||
<NFormItemGi :span="24" path="perms">
|
<NFormItemGi :span="24" path="perms">
|
||||||
<template #label>
|
<template #label>
|
||||||
<div class="flex-center">
|
<div class="flex-center">
|
||||||
<FormTip content="控制器中定义的权限字符,如:@SaCheckPermission('system:user:list')" />
|
<FormTip :content="$t('page.system.menu.permsTip')" />
|
||||||
<span>权限字符</span>
|
<span>{{ $t('page.system.menu.perms') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<NInput v-model:value="model.perms" placeholder="请输入菜单名称" />
|
<NInput v-model:value="model.perms" :placeholder="$t('page.system.menu.form.perms.required')" />
|
||||||
</NFormItemGi>
|
</NFormItemGi>
|
||||||
<NFormItemGi v-if="!isBtn" :span="12" path="isFrame">
|
<NFormItemGi v-if="!isBtn" :span="12" path="isFrame">
|
||||||
<template #label>
|
<template #label>
|
||||||
<div class="flex-center">
|
<div class="flex-center">
|
||||||
<FormTip content="选择是外链则路由地址需要以`http(s)://`开头" />
|
<FormTip :content="$t('page.system.menu.isFrameTip')" />
|
||||||
<span>是否外链</span>
|
<span>{{ $t('page.system.menu.isFrame') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<NRadioGroup v-model:value="model.isFrame">
|
<NRadioGroup v-model:value="model.isFrame">
|
||||||
@ -364,8 +390,8 @@ function onCreate() {
|
|||||||
<NFormItemGi v-if="isMenu" :span="12" path="isCache">
|
<NFormItemGi v-if="isMenu" :span="12" path="isCache">
|
||||||
<template #label>
|
<template #label>
|
||||||
<div class="flex-center">
|
<div class="flex-center">
|
||||||
<FormTip content="选择是则会被`keep-alive`缓存,需要匹配组件的`name`和地址保持一致" />
|
<FormTip :content="$t('page.system.menu.isCacheTip')" />
|
||||||
<span>是否缓存</span>
|
<span>{{ $t('page.system.menu.isCache') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<NRadioGroup v-model:value="model.isCache">
|
<NRadioGroup v-model:value="model.isCache">
|
||||||
@ -375,11 +401,11 @@ function onCreate() {
|
|||||||
</NSpace>
|
</NSpace>
|
||||||
</NRadioGroup>
|
</NRadioGroup>
|
||||||
</NFormItemGi>
|
</NFormItemGi>
|
||||||
<NFormItemGi v-if="!isBtn" :span="12" label="显示状态" path="visible">
|
<NFormItemGi v-if="!isBtn" :span="12" :label="$t('page.system.menu.visible')" path="visible">
|
||||||
<template #label>
|
<template #label>
|
||||||
<div class="flex-center">
|
<div class="flex-center">
|
||||||
<FormTip content="选择隐藏则路由将不会出现在侧边栏,但仍然可以访问" />
|
<FormTip :content="$t('page.system.menu.visibleTip')" />
|
||||||
<span>显示状态</span>
|
<span>{{ $t('page.system.menu.visible') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<DictRadio v-model:value="model.visible" dict-code="sys_show_hide" />
|
<DictRadio v-model:value="model.visible" dict-code="sys_show_hide" />
|
||||||
@ -387,14 +413,14 @@ function onCreate() {
|
|||||||
<NFormItemGi :span="12" path="status">
|
<NFormItemGi :span="12" path="status">
|
||||||
<template #label>
|
<template #label>
|
||||||
<div class="flex-center">
|
<div class="flex-center">
|
||||||
<FormTip content="选择停用则路由将不会出现在侧边栏,也不能被访问" />
|
<FormTip :content="$t('page.system.menu.statusTip')" />
|
||||||
<span>菜单状态</span>
|
<span>{{ $t('page.system.menu.status') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<DictRadio v-model:value="model.status" dict-code="sys_normal_disable" />
|
<DictRadio v-model:value="model.status" dict-code="sys_normal_disable" />
|
||||||
</NFormItemGi>
|
</NFormItemGi>
|
||||||
<NFormItemGi :span="12" label="显示排序" path="orderNum">
|
<NFormItemGi :span="12" :label="$t('page.system.menu.orderNum')" path="orderNum">
|
||||||
<NInputNumber v-model:value="model.orderNum" placeholder="请输入排序" />
|
<NInputNumber v-model:value="model.orderNum" :placeholder="$t('page.system.menu.form.orderNum.required')" />
|
||||||
</NFormItemGi>
|
</NFormItemGi>
|
||||||
</NGrid>
|
</NGrid>
|
||||||
</NForm>
|
</NForm>
|
||||||
|
Loading…
Reference in New Issue
Block a user