2
0

fix:菜单管理界面中英适配

This commit is contained in:
zhongzm
2025-02-11 16:07:02 +08:00
parent ba535e442f
commit a2e1194d44
5 changed files with 140 additions and 56 deletions

View File

@@ -917,6 +917,42 @@ const local: any = {
deleteask:'Do you confirm the deletion?',
title:'Dictionary list',
},
menu:{
menuname:'Name',
path:'Path',
component:'Component',
status:'Status',
nomal:'Normal',
disable:'Disable',
menutype:'Type',
table:'Directory',
menu:'Menu',
button:'Button',
ordernum:'Sort',
icon:'Icon',
createtime:'Create Time',
operate:'Operate',
edit:'Edit',
delete:'Delete',
modaltitle:'Tips',
deleteask:'Are you sure you want to delete the menu?',
deletesuc:'Deletion successful.',
title:'Menu List',
addmenu:'Add Menu',
editmenu:'Edit Menu',
root:'Root node',
parent:'Parent',
islink:'Is backlink',
yes:'Yes',
no:'No',
menucomponent:'Path',
hidemenu:'Hide Menu',
cache:'Cache',
perms:'Permission Identifier',
confirm:'Determine',
close:'Cancel',
nozero:'The sort must be greater than or equal to 0'
}
},
form: {
required: 'Cannot be empty',

View File

@@ -917,6 +917,42 @@ const local:any = {
deleteask:'确认删除吗?',
title:'字典列表',
},
menu:{
menuname:'菜单名称',
path:'路由地址',
component:'组件路径',
status:'状态',
nomal:'正常',
disable:'停用',
menutype:'类型',
table:'目录',
menu:'菜单',
button:'按钮',
ordernum:'排序',
icon:'图标',
createtime:'创建时间',
operate:'操作',
edit:'编辑',
delete:'删除',
modaltitle:'提示',
deleteask:'确定删除该菜单吗',
deletesuc:'删除成功',
title:'菜单列表',
addmenu:'新增菜单',
editmenu:'编辑菜单',
root:'根节点',
parent:'上级菜单',
islink:'是否外链',
yes:'是',
no:'否',
menucomponent:'菜单路径',
hidemenu:'隐藏菜单',
cache:'缓存',
perms:'权限标识',
confirm:'确定',
close:'取消',
nozero:'排序必须大于等于0'
}
},
form: {
required: '不能为空',

View File

@@ -3,33 +3,34 @@ import { Icon } from '@iconify/vue';
import { Button, Tag } from 'ant-design-vue';
import { SimpleScrollbar } from '~/packages/materials/src';
import MenuOperateModal from './modules/menu-operate-modal.vue';
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
const { data, columns, loading, getData } = useTable({
apiFn: doGetMenuList,
columns: () => [
{
key: 'menuName',
dataIndex: 'menuName',
title: '菜单名称',
title: t('page.menu.menuname'),
align: 'left',
width: 200
},
{
key: 'path',
dataIndex: 'path',
title: '路由地址',
title: t('page.menu.path'),
align: 'center'
},
{
key: 'component',
dataIndex: 'component',
title: '组件路径',
title: t('page.menu.component'),
align: 'center'
},
{
key: 'status',
dataIndex: 'status',
title: '状态',
title: t('page.menu.status'),
align: 'center',
customRender: ({ record }) => {
const colorTagMap: Record<string, string> = {
@@ -37,17 +38,17 @@ const { data, columns, loading, getData } = useTable({
1: 'warning'
};
const labelMap: Record<string, string> = {
0: '正常',
1: '停用'
};
return <Tag color={colorTagMap[record.status]}>{labelMap[record.status]}</Tag>;
const labelMap=computed<Record<string, string>>(() => ({
0: t('page.menu.nomal'),
1: t('page.menu.disable')
}));
return <Tag color={colorTagMap[record.status]}>{labelMap.value[record.status]}</Tag>;
}
},
{
key: 'menuType',
dataIndex: 'menuType',
title: '类型',
title: t('page.menu.menutype'),
align: 'center',
customRender: ({ record }) => {
const colorTagMap: Record<string, string> = {
@@ -57,9 +58,9 @@ const { data, columns, loading, getData } = useTable({
};
const labelMap: Record<string, string> = {
M: '目录',
C: '菜单',
F: '按钮'
M: t('page.menu.table'),
C: t('page.menu.menu'),
F: t('page.menu.button')
};
return <Tag color={colorTagMap[record.menuType]}>{labelMap[record.menuType]}</Tag>;
}
@@ -67,13 +68,13 @@ const { data, columns, loading, getData } = useTable({
{
key: 'orderNum',
dataIndex: 'orderNum',
title: '排序',
title: t('page.menu.ordernum'),
align: 'center'
},
{
key: 'icon',
dataIndex: 'icon',
title: '图标',
title: t('page.menu.icon'),
align: 'center',
customRender: ({ record }) => {
return (
@@ -87,20 +88,20 @@ const { data, columns, loading, getData } = useTable({
key: 'createTime',
dataIndex: 'createTime',
align: 'center',
title: '创建时间'
title: t('page.menu.createtime')
},
{
key: 'operate',
title: '操作',
title: t('page.menu.operate'),
align: 'center',
width: 200,
customRender: ({ record }) => (
<div class="flex justify-around gap-8px">
<Button size="small" onClick={() => edit(record.menuId)}>
编辑
{t('page.menu.edit')}
</Button>
<Button size="small" danger onClick={() => handleDelete(record.menuId)}>
删除
{t('page.menu.delete')}
</Button>
</div>
)
@@ -122,12 +123,12 @@ function edit(id: number) {
function handleDelete(id: number) {
$modal.confirm({
title: '提示',
content: '确定删除该菜单吗?',
title: t('page.menu.modaltitle'),
content: t('page.menu.deleteask'),
onOk: async () => {
const { error } = await doDeleteMenu(id);
if (!error) {
$message.success('删除成功');
$message.success(t('page.menu.deletesuc'));
onDeleted();
}
}
@@ -146,8 +147,8 @@ function handleSubmitSuccess() {
<template>
<SimpleScrollbar>
<div class="min-h-500px flex-col-stretch gap-16px overflow-hidden lt-sm:overflow-auto">
<ACard title="菜单列表">
<AButton mb-4 type="primary" @click="handleAdd">新增菜单</AButton>
<ACard :title="t('page.menu.title')">
<AButton mb-4 type="primary" @click="handleAdd">{{ t('page.menu.addmenu') }}</AButton>
<ATable
:checked-row-keys="checkedRowKeys"

View File

@@ -1,3 +1,4 @@
import {useI18n} from "vue-i18n";
const { defaultRequiredRule } = useFormRules();
export type MenuModelType = Pick<
@@ -50,7 +51,7 @@ export const formRules = {
{
validator: (rule, value) => {
if (value < 0) {
return Promise.reject(rule.message || '排序必须大于等于0');
return Promise.reject(rule.message || 'must greater than or equal to 0');
}
return Promise.resolve();
}
@@ -58,13 +59,20 @@ export const formRules = {
]
} as Record<string, App.Global.FormRule | App.Global.FormRule[]>;
export const menuTypeOptions = [
{ label: '目录', value: 'M' },
{ label: '菜单', value: 'C' },
{ label: '按钮', value: 'F' }
];
export const useMenuTypeOptions = () => {
const { t } = useI18n();
export const menuStatusOptions = [
{ label: '正常', value: '0' },
{ label: '停用', value: '1' }
];
return computed(() => [
{ label: t('page.menu.table'), value: 'M' },
{ label: t('page.menu.menu'), value: 'C' },
{ label: t('page.menu.button'), value: 'F' }
]);
};
export const useMenuStatusOptions = () => {
const { t } = useI18n();
return computed(() => [
{ label: t('page.menu.nomal'), value: '0' },
{ label: t('page.menu.disable'), value: '1' }
]);
};

View File

@@ -1,9 +1,12 @@
<script lang="ts" setup>
import { $t } from '@/locales';
import type { MenuModelType } from './form';
import { formRules, menuStatusOptions, menuTypeOptions, resetAddForm } from './form';
import { formRules, useMenuStatusOptions, useMenuTypeOptions, resetAddForm } from './form';
import IconSelect from './icon-select.vue';
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
const menuStatusOptions = useMenuStatusOptions();
const menuTypeOptions = useMenuTypeOptions();
const props = defineProps<{
operateType: AntDesign.TableOperateType;
editingData?: Api.SystemManage.Menu | null;
@@ -22,8 +25,8 @@ const treeData = ref<Api.SystemManage.MenuTree[]>([]);
const title = computed(() => {
const titles: Record<AntDesign.TableOperateType, string> = {
add: '新增菜单',
edit: '编辑菜单'
add: t('page.menu.addmenu'),
edit: t('page.menu.editmenu')
};
return titles[props.operateType];
});
@@ -68,7 +71,7 @@ async function getTreeData() {
{
id: 0,
pId: -1,
label: '根节点',
label: t('page.menu.root'),
children: data
}
];
@@ -89,7 +92,7 @@ getTreeData();
:wrapper-col="{ span: 16, offset: 1 }"
class="grid grid-cols-2 gap-3 px-4 py-4 pt-6"
>
<AFormItem label="上级菜单" name="parentId">
<AFormItem :label="t('page.menu.parent')" name="parentId">
<ATreeSelect
v-model:value="model.parentId"
show-search
@@ -99,46 +102,46 @@ getTreeData();
tree-node-filter-prop="label"
/>
</AFormItem>
<AFormItem label="菜单名称" name="menuName">
<AFormItem :label="t('page.menu.menuname')" name="menuName">
<AInput v-model:value="model.menuName" />
</AFormItem>
<AFormItem label="菜单类型" name="menuType">
<AFormItem :label="t('page.menu.menutype')" name="menuType">
<ASelect v-model:value="model.menuType" :options="menuTypeOptions" />
</AFormItem>
<AFormItem v-if="model.menuType !== 'F'" label="菜单图标" name="icon">
<AFormItem v-if="model.menuType !== 'F'" :label="t('page.menu.icon')" name="icon">
<IconSelect v-model="model.icon" />
</AFormItem>
<AFormItem v-if="model.menuType === 'C'" label="是否外链">
<AFormItem v-if="model.menuType === 'C'" :label="t('page.menu.islink')">
<ARadioGroup v-model:value="model.isFrame" name="radioGroup" @change="() => (model.path = '')">
<ARadio value="0"></ARadio>
<ARadio value="1"></ARadio>
<ARadio value="0">{{ t('page.menu.yes') }}</ARadio>
<ARadio value="1">{{ t('page.menu.no') }}</ARadio>
</ARadioGroup>
</AFormItem>
<AFormItem v-if="model.menuType !== 'F'" label="菜单路径" name="path">
<AFormItem v-if="model.menuType !== 'F'" :label="t('page.menu.menucomponent')" name="path">
path <AInput v-model:value="model.path" />
component <AInput v-model:value="model.component" />
name <AInput v-model:value="model.name" />
</AFormItem>
<AFormItem v-if="model.menuType === 'C'" label="隐藏菜单" name="hideInMenu">
<AFormItem v-if="model.menuType === 'C'" :label="t('page.menu.hidemenu')" name="hideInMenu">
<ASwitch v-model:checked="model.hideInMenu" checked-value="0" un-checked-value="1" />
</AFormItem>
<AFormItem label="排序" name="orderNum">
<AFormItem :label="t('page.menu.ordernum')" name="orderNum">
<AInputNumber v-model:value="model.orderNum" w-full />
</AFormItem>
<AFormItem v-if="model.menuType !== 'F'" label="状态" name="status">
<ASelect v-model:value="model.status" :options="menuStatusOptions" />
<AFormItem v-if="model.menuType !== 'F'" :label="t('page.menu.status')" name="status">
<ASelect v-model:value="model.status" :options="menuStatusOptions"/>
</AFormItem>
<AFormItem v-if="model.menuType === 'C'" label="缓存" name="isCache">
<AFormItem v-if="model.menuType === 'C'" :label="t('page.menu.cache')" name="isCache">
<ASwitch v-model:checked="model.isCache" checked-value="0" un-checked-value="1" />
</AFormItem>
<AFormItem v-if="model.menuType === 'F'" label="权限标识" name="perms">
<AFormItem v-if="model.menuType === 'F'" :label="t('page.menu.perms')" name="perms">
<AInput v-model:value="model.perms" />
</AFormItem>
</AForm>
<template #footer>
<AButton @click="submitForm">确定</AButton>
<AButton @click="closeModal">取消</AButton>
<AButton @click="submitForm">{{ t('page.menu.confirm') }}</AButton>
<AButton @click="closeModal">{{ t('page.menu.close') }}</AButton>
</template>
</AModal>
</template>