Commit 19011296ed61f820356f6b201cbb274d57dcb7d3

Authored by vben
1 parent 4f8ad976

feat: multi-language support

Showing 74 changed files with 760 additions and 303 deletions
CHANGELOG.zh_CN.md
... ... @@ -2,7 +2,7 @@
2 2  
3 3 ### ✨ Refactor
4 4  
5   -- 重构整体 layout。更改代码实现方式。代码更精简,并加入多语言支持
  5 +- 重构整体 layout。更改代码实现方式。代码更精简
6 6 - 配置项重构
7 7 - 移除 messageSetting 配置
8 8  
... ... @@ -10,6 +10,7 @@
10 10  
11 11 - 缓存可以配置是否加密,默认生产环境开启 Aes 加密
12 12 - 新增标签页拖拽排序
  13 +- 除示例外加入全局国际化功能,支持中文与英文
13 14  
14 15 ### 🎫 Chores
15 16  
... ...
build/vite/plugin/transform/globby/index.ts
... ... @@ -61,13 +61,20 @@ function varTemplate(data: string[][], name: string) {
61 61  
62 62 // lastKey is a data
63 63 let pathValue = v[0].replace(/\//g, '.').split('.');
  64 + // let scopeKey = '';
  65 + // const len=pathValue.length
  66 + // const scope=pathValue[len-2]
64 67 let lastKey: string | undefined = pathValue.pop();
65 68  
66 69 let deepValue: Record<any, any> = {};
67 70 if (lastKey) {
68   - deepValue[lastKey.replace('_' + pathValue[0], '')] = lastKey;
  71 + // Solve the problem of files with the same name in different folders
  72 + const lastKeyList = lastKey.replace('_' + pathValue[0], '').split('_');
  73 + const key = lastKeyList.pop();
  74 + if (key) {
  75 + deepValue[key] = lastKey;
  76 + }
69 77 }
70   -
71 78 // Set Deep Value
72 79 deepValue = Object.assign(deepValue, dotProp.get(deepData, pathValue.join('.')));
73 80 dotProp.set(deepData, pathValue.join('.'), deepValue);
... ... @@ -169,7 +176,15 @@ const globTransform = function (config: SharedConfig): Transform {
169 176  
170 177 if (matchedGroups && matchedGroups.length) {
171 178 const matchedSegments = matchedGroups[1]; //first everytime "Full Match"
172   - const name = matchedGroups[2] + '_' + matchedSegments.split('/').shift();
  179 + const matchList = matchedSegments.split('/').filter(Boolean);
  180 + const lang = matchList.shift();
  181 + const scope = matchList.pop();
  182 +
  183 + // Solve the problem of files with the same name in different folders
  184 + const scopeKey = scope ? `${scope}_` : '';
  185 + const fileName = matchedGroups[2];
  186 + const name = scopeKey + fileName + '_' + lang;
  187 +
173 188 //send deep way like an (en/modules/system/dashboard) into groups
174 189 groups.push([matchedSegments + name, file]);
175 190 return templateRender({
... ... @@ -186,6 +201,10 @@ const globTransform = function (config: SharedConfig): Transform {
186 201 const filesJoined = replaceFiles.join('\n');
187 202  
188 203 urlMap.set(path, filesJoined);
  204 +
  205 + // console.log('======================');
  206 + // console.log(filesJoined, varTemplate(groups, name));
  207 + // console.log('======================');
189 208 return [
190 209 filesJoined,
191 210 compareString(injectPath, groups),
... ...
src/components/Menu/src/BasicMenu.tsx
... ... @@ -3,7 +3,17 @@ import &#39;./index.less&#39;;
3 3 import type { MenuState } from './types';
4 4 import type { Menu as MenuType } from '/@/router/types';
5 5  
6   -import { computed, defineComponent, unref, reactive, watch, onMounted, ref, toRefs } from 'vue';
  6 +import {
  7 + computed,
  8 + defineComponent,
  9 + unref,
  10 + reactive,
  11 + watch,
  12 + onMounted,
  13 + ref,
  14 + toRefs,
  15 + ComputedRef,
  16 +} from 'vue';
7 17 import { Menu } from 'ant-design-vue';
8 18 import SearchInput from './SearchInput.vue';
9 19 import MenuContent from './MenuContent';
... ... @@ -34,7 +44,7 @@ export default defineComponent({
34 44 const menuState = reactive<MenuState>({
35 45 defaultSelectedKeys: [],
36 46 mode: props.mode,
37   - theme: computed(() => props.theme),
  47 + theme: computed(() => props.theme) as ComputedRef<ThemeEnum>,
38 48 openKeys: [],
39 49 searchValue: '',
40 50 selectedKeys: [],
... ...
src/hooks/web/useI18n.ts
1 1 import { getI18n } from '/@/setup/i18n';
  2 +import projectSetting from '/@/settings/projectSetting';
2 3  
3 4 export function useI18n(namespace?: string) {
4   - const { t, ...methods } = getI18n().global;
5   -
6 5 function getKey(key: string) {
7 6 if (!namespace) {
8 7 return key;
... ... @@ -12,6 +11,18 @@ export function useI18n(namespace?: string) {
12 11 }
13 12 return `${namespace}.${key}`;
14 13 }
  14 + const normalFn = {
  15 + t: (key: string) => {
  16 + return getKey(key);
  17 + },
  18 + };
  19 +
  20 + if (!projectSetting.locale.show || !getI18n()) {
  21 + return normalFn;
  22 + }
  23 +
  24 + const { t, ...methods } = getI18n().global;
  25 +
15 26 return {
16 27 ...methods,
17 28 t: (key: string, ...arg: Parameters<typeof t>) => {
... ...
src/hooks/web/useTitle.ts 0 → 100644
  1 +import { watch } from 'vue';
  2 +import { useRouter } from 'vue-router';
  3 +import { useGlobSetting } from '../setting';
  4 +import { useI18n } from './useI18n';
  5 +import { setTitle } from '/@/utils/browser';
  6 +
  7 +export function useTitle() {
  8 + const { currentRoute } = useRouter();
  9 + const { t } = useI18n();
  10 + watch(
  11 + () => currentRoute.value.path,
  12 + () => {
  13 + const globSetting = useGlobSetting();
  14 + setTitle(t(currentRoute.value.meta.title), globSetting.title);
  15 + },
  16 + { immediate: true, flush: 'post' }
  17 + );
  18 +}
... ...
src/layouts/default/header/LayoutBreadcrumb.tsx
... ... @@ -15,6 +15,7 @@ import { compile } from &#39;path-to-regexp&#39;;
15 15 import router from '/@/router';
16 16  
17 17 import { PageEnum } from '/@/enums/pageEnum';
  18 +import { useI18n } from '/@/hooks/web/useI18n';
18 19  
19 20 export default defineComponent({
20 21 name: 'BasicBreadcrumb',
... ... @@ -28,7 +29,7 @@ export default defineComponent({
28 29 const itemList = ref<AppRouteRecordRaw[]>([]);
29 30  
30 31 const { currentRoute, push } = useRouter();
31   -
  32 + const { t } = useI18n();
32 33 watch(
33 34 () => currentRoute.value,
34 35 () => {
... ... @@ -88,7 +89,7 @@ export default defineComponent({
88 89 }}
89 90 />
90 91 )}
91   - {item.meta.title}
  92 + {t(item.meta.title)}
92 93 </>
93 94 );
94 95 }
... ...
src/layouts/default/menu/useLayoutMenu.ts
... ... @@ -17,7 +17,10 @@ import {
17 17 getShallowMenus,
18 18 } from '/@/router/menus';
19 19 import { permissionStore } from '/@/store/modules/permission';
  20 +import { useI18n } from '/@/hooks/web/useI18n';
  21 +import { cloneDeep } from 'lodash-es';
20 22  
  23 +const { t } = useI18n();
21 24 export function useSplitMenu(splitType: Ref<MenuSplitTyeEnum>) {
22 25 // Menu array
23 26 const menusRef = ref<Menu[]>([]);
... ... @@ -42,6 +45,14 @@ export function useSplitMenu(splitType: Ref&lt;MenuSplitTyeEnum&gt;) {
42 45 return unref(splitType) === MenuSplitTyeEnum.NONE || !unref(getSplit);
43 46 });
44 47  
  48 + const getI18nFlatMenus = computed(() => {
  49 + return setI18nName(flatMenusRef.value, true, false);
  50 + });
  51 +
  52 + const getI18nMenus = computed(() => {
  53 + return setI18nName(menusRef.value, true, true);
  54 + });
  55 +
45 56 watch(
46 57 [() => unref(currentRoute).path, () => unref(splitType)],
47 58 async ([path]: [string, MenuSplitTyeEnum]) => {
... ... @@ -72,6 +83,18 @@ export function useSplitMenu(splitType: Ref&lt;MenuSplitTyeEnum&gt;) {
72 83 genMenus();
73 84 });
74 85  
  86 + function setI18nName(list: Menu[], clone = false, deep = true) {
  87 + const menus = clone ? cloneDeep(list) : list;
  88 + menus.forEach((item) => {
  89 + if (!item.name.includes('.')) return;
  90 + item.name = t(item.name);
  91 + if (item.children && deep) {
  92 + setI18nName(item.children, false, deep);
  93 + }
  94 + });
  95 + return menus;
  96 + }
  97 +
75 98 // Handle left menu split
76 99 async function handleSplitLeftMenu(parentPath: string) {
77 100 if (unref(splitLeft)) return;
... ... @@ -109,5 +132,6 @@ export function useSplitMenu(splitType: Ref&lt;MenuSplitTyeEnum&gt;) {
109 132 return;
110 133 }
111 134 }
112   - return { flatMenusRef, menusRef };
  135 +
  136 + return { flatMenusRef: getI18nFlatMenus, menusRef: getI18nMenus };
113 137 }
... ...
src/layouts/default/multitabs/TabContent.tsx
... ... @@ -15,6 +15,8 @@ import { useHeaderSetting } from &#39;/@/hooks/setting/useHeaderSetting&#39;;
15 15 import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting';
16 16 import { useI18n } from '/@/hooks/web/useI18n';
17 17  
  18 +const { t: titleT } = useI18n();
  19 +
18 20 const ExtraContent: FunctionalComponent = () => {
19 21 return (
20 22 <span class={`multiple-tabs-content__extra `}>
... ... @@ -38,7 +40,7 @@ const TabContent: FunctionalComponent&lt;{ tabItem: TabItem }&gt; = (props) =&gt; {
38 40  
39 41 return (
40 42 <div class={`multiple-tabs-content__content `} onContextmenu={handleContextMenu}>
41   - <span class="ml-1">{meta && meta.title}</span>
  43 + <span class="ml-1">{meta && titleT(meta.title)}</span>
42 44 </div>
43 45 );
44 46 };
... ...
src/locales/lang/en/routes/README.MD 0 → 100644
  1 +Share with menu
... ...
src/locales/lang/en/routes/menus/dashboard.ts renamed to src/locales/lang/en/routes/baisc.ts
1 1 export default {
2   - someentry: 'some text',
  2 + login: 'Login',
3 3 };
... ...
src/locales/lang/en/routes/dashboard.ts 0 → 100644
  1 +export default {
  2 + dashboard: 'Dashboard',
  3 + welcome: 'Home',
  4 + workbench: 'Workbench',
  5 + analysis: 'Analysis',
  6 +};
... ...
src/locales/lang/en/routes/demo/charts.ts 0 → 100644
  1 +export default {
  2 + charts: 'Chart',
  3 + map: 'Map',
  4 + line: 'Line',
  5 + pie: 'Pie',
  6 + apexChart: 'ApexChart',
  7 +};
... ...
src/locales/lang/en/routes/demo/comp.ts 0 → 100644
  1 +export default {
  2 + comp: 'Component',
  3 + basic: 'Basic',
  4 + transition: 'Animation',
  5 + countTo: 'Count To',
  6 +
  7 + scroll: 'Scroll',
  8 + scrollBasic: 'Basic',
  9 + scrollAction: 'Scroll Function',
  10 + virtualScroll: 'Virtual Scroll',
  11 +
  12 + modal: 'Modal',
  13 + drawer: 'Drawer',
  14 + desc: 'Desc',
  15 +
  16 + lazy: 'Lazy',
  17 + lazyBasic: 'Basic',
  18 + lazyTransition: 'Animation',
  19 +
  20 + verify: 'Verify',
  21 + verifyDrag: 'Drag ',
  22 + verifyRotate: 'Picture Restore',
  23 +
  24 + qrcode: 'QR code',
  25 + strength: 'Password strength',
  26 + upload: 'Upload',
  27 +};
... ...
src/locales/lang/en/routes/demo/editor.ts 0 → 100644
  1 +export default {
  2 + editor: 'Editor',
  3 + markdown: 'Markdown editor',
  4 +
  5 + tinymce: 'Rich text',
  6 + tinymceBasic: 'Basic',
  7 + tinymceForm: 'embedded form',
  8 +};
... ...
src/locales/lang/en/routes/demo/excel.ts 0 → 100644
  1 +export default {
  2 + excel: 'Excel',
  3 + customExport: 'Select export format',
  4 + jsonExport: 'JSON data export',
  5 + arrayExport: 'Array data export',
  6 + importExcel: 'Import',
  7 +};
... ...
src/locales/lang/en/routes/demo/feat.ts 0 → 100644
  1 +export default {
  2 + feat: 'Page Function',
  3 + icon: 'Icon',
  4 + tabs: 'Tabs',
  5 + contextMenu: 'Context Menu',
  6 + download: 'Download',
  7 + clickOutSide: 'ClickOutSide',
  8 + imgPreview: 'Picture Preview',
  9 + copy: 'Clipboard',
  10 + msg: 'Message prompt',
  11 + watermark: 'Watermark',
  12 + fullScreen: 'Full Screen',
  13 + errorLog: 'Error Log',
  14 + tab: 'Tab with parameters',
  15 + tab1: 'Tab with parameter 1',
  16 + tab2: 'Tab with parameter 2',
  17 +};
... ...
src/locales/lang/en/routes/demo/form.ts 0 → 100644
  1 +export default {
  2 + form: 'Form',
  3 + basic: 'Basic',
  4 + useForm: 'useForm',
  5 + refForm: 'RefForm',
  6 + advancedForm: 'Shrinkable',
  7 + ruleForm: 'Form validation',
  8 + dynamicForm: 'Dynamic',
  9 + customerForm: 'Custom',
  10 +};
... ...
src/locales/lang/en/routes/demo/iframe.ts 0 → 100644
  1 +export default {
  2 + frame: 'External',
  3 + antv: 'antVue doc (embedded)',
  4 + doc: 'Project doc (embedded)',
  5 + docExternal: 'Project doc (external)',
  6 +};
... ...
src/locales/lang/en/routes/demo/page.ts 0 → 100644
  1 +export default {
  2 + page: 'Page',
  3 +
  4 + form: 'Form',
  5 + formBasic: 'Basic Form',
  6 + formStep: 'Step Form',
  7 + formHigh: 'Advanced Form',
  8 +
  9 + desc: 'Details',
  10 + descBasic: 'Basic Details',
  11 + descHigh: 'Advanced Details',
  12 +
  13 + result: 'Result',
  14 + resultSuccess: 'Success',
  15 + resultFail: 'Failed',
  16 +
  17 + account: 'Personal',
  18 + accountCenter: 'Personal Center',
  19 + accountSetting: 'Personal Settings',
  20 +
  21 + exception: 'Exception',
  22 + netWorkError: 'Network Error',
  23 + notData: 'No data',
  24 +
  25 + list: 'List page',
  26 + listCard: 'Card list',
  27 +};
... ...
src/locales/lang/en/routes/demo/permission.ts 0 → 100644
  1 +export default {
  2 + permission: 'Permission',
  3 +
  4 + front: 'front-end',
  5 + frontPage: 'Page',
  6 + frontBtn: 'Button',
  7 + frontTestA: 'Test page A',
  8 + frontTestB: 'Test page B',
  9 +
  10 + back: 'background',
  11 + backPage: 'Page',
  12 + backBtn: 'Button',
  13 +};
... ...
src/locales/lang/en/routes/demo/table.ts 0 → 100644
  1 +export default {
  2 + table: 'Table',
  3 +
  4 + basic: 'Basic',
  5 + treeTable: 'Tree',
  6 + fetchTable: 'Remote loading',
  7 + fixedColumn: 'Fixed column',
  8 + customerCell: 'Custom column',
  9 + formTable: 'Open search',
  10 + useTable: 'UseTable',
  11 + refTable: 'RefTable',
  12 + multipleHeader: 'MultiLevel header',
  13 + mergeHeader: 'Merge cells',
  14 + expandTable: 'Expandable table',
  15 + fixedHeight: 'Fixed height',
  16 + footerTable: 'Footer',
  17 + editCellTable: 'Editable cell',
  18 + editRowTable: 'Editable row',
  19 +};
... ...
src/locales/lang/en/routes/demo/tree.ts 0 → 100644
  1 +export default {
  2 + tree: 'Tree',
  3 +
  4 + basic: 'Basic',
  5 + editTree: 'Right-click',
  6 + actionTree: 'Function operation',
  7 +};
... ...
src/locales/lang/en/sys/api.ts 0 → 100644
  1 +export default {
  2 + operationFailed: 'Operation failed',
  3 + errorTip: 'Error Tip',
  4 + errorMessage: 'The operation failed, the system is abnormal!',
  5 + timeoutMessage: 'Login timed out, please log in again!',
  6 + apiTimeoutMessage: 'The interface request timed out, please refresh the page and try again!',
  7 + networkException: 'network anomaly',
  8 + networkExceptionMsg: 'Please check if your network connection is normal! The network is abnormal',
  9 +
  10 + errMsg401: 'The user does not have permission (token, user name, password error)!',
  11 + errMsg403: 'The user is authorized, but access is forbidden!',
  12 + errMsg404: 'Network request error, the resource was not found!',
  13 + errMsg405: 'Network request error, request method not allowed!',
  14 + errMsg408: 'Network request timed out!',
  15 + errMsg500: 'Server error, please contact the administrator!',
  16 + errMsg501: 'The network is not implemented!',
  17 + errMsg502: 'Network Error!',
  18 + errMsg503: 'The service is unavailable, the server is temporarily overloaded or maintained!',
  19 + errMsg504: 'Network timeout!',
  20 + errMsg505: 'The http version does not support the request!',
  21 +};
... ...
src/locales/lang/en/sys/app.ts 0 → 100644
  1 +export default {
  2 + loginOutTip: 'Reminder',
  3 + loginOutMessage: 'Confirm to exit the system?',
  4 + menuLoading: 'Menu loading...',
  5 +};
... ...
src/locales/lang/zh_CN/component/modal.ts
1 1 export default {
2   - loadingText: '加载中...',
3 2 cancelText: '关闭',
4 3 okText: '确认',
5 4 };
... ...
src/locales/lang/zh_CN/routes/README.MD 0 → 100644
  1 +Share with menu
... ...
src/locales/lang/zh_CN/routes/menus/dashboard.ts renamed to src/locales/lang/zh_CN/routes/baisc.ts
1 1 export default {
2   - someentry: '一些文本',
  2 + login: '登录',
3 3 };
... ...
src/locales/lang/zh_CN/routes/dashboard.ts 0 → 100644
  1 +export default {
  2 + dashboard: 'Dashboard',
  3 + welcome: '首页',
  4 + workbench: '工作台',
  5 + analysis: '分析页',
  6 +};
... ...
src/locales/lang/zh_CN/routes/demo/charts.ts 0 → 100644
  1 +export default {
  2 + charts: '图表库',
  3 + map: '地图',
  4 + line: '折线图',
  5 + pie: '饼图',
  6 + apexChart: 'ApexChart',
  7 +};
... ...
src/locales/lang/zh_CN/routes/demo/comp.ts 0 → 100644
  1 +export default {
  2 + comp: '组件',
  3 + basic: '基础组件',
  4 + transition: '动画组件',
  5 + countTo: '数字动画',
  6 +
  7 + scroll: '滚动组件',
  8 + scrollBasic: '基础滚动',
  9 + scrollAction: '滚动函数',
  10 + virtualScroll: '虚拟滚动',
  11 +
  12 + modal: '弹窗扩展',
  13 + drawer: '抽屉扩展',
  14 + desc: '详情组件',
  15 +
  16 + lazy: '懒加载组件',
  17 + lazyBasic: '基础示例',
  18 + lazyTransition: '动画效果',
  19 +
  20 + verify: '验证组件',
  21 + verifyDrag: '拖拽校验',
  22 + verifyRotate: '图片还原',
  23 +
  24 + qrcode: '二维码组件',
  25 + strength: '密码强度组件',
  26 + upload: '上传组件',
  27 +};
... ...
src/locales/lang/zh_CN/routes/demo/editor.ts 0 → 100644
  1 +export default {
  2 + editor: '编辑器',
  3 + markdown: 'markdown编辑器',
  4 +
  5 + tinymce: '富文本',
  6 + tinymceBasic: '基础使用',
  7 + tinymceForm: '嵌入form',
  8 +};
... ...
src/locales/lang/zh_CN/routes/demo/excel.ts 0 → 100644
  1 +export default {
  2 + excel: 'Excel',
  3 + customExport: '选择导出格式',
  4 + jsonExport: 'JSON数据导出',
  5 + arrayExport: 'Array数据导出',
  6 + importExcel: '导入',
  7 +};
... ...
src/locales/lang/zh_CN/routes/demo/feat.ts 0 → 100644
  1 +export default {
  2 + feat: '页面功能',
  3 + icon: '图标',
  4 + tabs: '标签页操作',
  5 + contextMenu: '右键菜单',
  6 + download: '文件下载',
  7 + clickOutSide: 'ClickOutSide组件',
  8 + imgPreview: '图片预览',
  9 + copy: '剪切板',
  10 + msg: '消息提示',
  11 + watermark: '水印',
  12 + fullScreen: '全屏',
  13 + errorLog: '错误日志',
  14 + tab: 'Tab带参',
  15 + tab1: 'Tab带参1',
  16 + tab2: 'Tab带参2',
  17 +};
... ...
src/locales/lang/zh_CN/routes/demo/form.ts 0 → 100644
  1 +export default {
  2 + form: 'Form',
  3 + basic: '基础表单',
  4 + useForm: 'useForm',
  5 + refForm: 'RefForm',
  6 + advancedForm: '可收缩表单',
  7 + ruleForm: '表单验证',
  8 + dynamicForm: '动态表单',
  9 + customerForm: '自定义组件',
  10 +};
... ...
src/locales/lang/zh_CN/routes/demo/iframe.ts 0 → 100644
  1 +export default {
  2 + frame: '外部页面',
  3 + antv: 'antVue文档(内嵌)',
  4 + doc: '项目文档(内嵌)',
  5 + docExternal: '项目文档(外链)',
  6 +};
... ...
src/locales/lang/zh_CN/routes/demo/page.ts 0 → 100644
  1 +export default {
  2 + page: '页面',
  3 +
  4 + form: '表单页',
  5 + formBasic: '基础表单',
  6 + formStep: '分步表单',
  7 + formHigh: '高级表单',
  8 +
  9 + desc: '详情页',
  10 + descBasic: '基础详情页',
  11 + descHigh: '高级详情页',
  12 +
  13 + result: '结果页',
  14 + resultSuccess: '成功页',
  15 + resultFail: '失败页',
  16 +
  17 + account: '个人页',
  18 + accountCenter: '个人中心',
  19 + accountSetting: '个人设置',
  20 +
  21 + exception: '异常页',
  22 + netWorkError: '网络错误',
  23 + notData: '无数据',
  24 +
  25 + list: '列表页',
  26 + listCard: '卡片列表',
  27 +};
... ...
src/locales/lang/zh_CN/routes/demo/permission.ts 0 → 100644
  1 +export default {
  2 + permission: '权限管理',
  3 +
  4 + front: '基于前端权限',
  5 + frontPage: '页面权限',
  6 + frontBtn: '按钮权限',
  7 + frontTestA: '权限测试页A',
  8 + frontTestB: '权限测试页B',
  9 +
  10 + back: '基于后台权限',
  11 + backPage: '页面权限',
  12 + backBtn: '按钮权限',
  13 +};
... ...
src/locales/lang/zh_CN/routes/demo/table.ts 0 → 100644
  1 +export default {
  2 + table: 'Table',
  3 +
  4 + basic: '基础表格',
  5 + treeTable: '树形表格',
  6 + fetchTable: '远程加载示例',
  7 + fixedColumn: '固定列',
  8 + customerCell: '自定义列',
  9 + formTable: '开启搜索区域',
  10 + useTable: 'UseTable',
  11 + refTable: 'RefTable',
  12 + multipleHeader: '多级表头',
  13 + mergeHeader: '合并单元格',
  14 + expandTable: '可展开表格',
  15 + fixedHeight: '定高/头部自定义',
  16 + footerTable: '表尾行合计',
  17 + editCellTable: '可编辑单元格',
  18 + editRowTable: '可编辑行',
  19 +};
... ...
src/locales/lang/zh_CN/routes/demo/tree.ts 0 → 100644
  1 +export default {
  2 + tree: 'Tree',
  3 +
  4 + basic: '基础树',
  5 + editTree: '右键示例',
  6 + actionTree: '函数操作示例',
  7 +};
... ...
src/locales/lang/zh_CN/sys/api.ts 0 → 100644
  1 +export default {
  2 + operationFailed: '操作失败',
  3 + errorTip: '错误提示',
  4 + errorMessage: '操作失败,系统异常!',
  5 + timeoutMessage: '登录超时,请重新登录!',
  6 + apiTimeoutMessage: '接口请求超时,请刷新页面重试!',
  7 + networkException: '网络异常',
  8 + networkExceptionMsg: '网请检查您的网络连接是否正常!络异常',
  9 +
  10 + errMsg401: '用户没有权限(令牌、用户名、密码错误)!',
  11 + errMsg403: '用户得到授权,但是访问是被禁止的。!',
  12 + errMsg404: '网络请求错误,未找到该资源!',
  13 + errMsg405: '网络请求错误,请求方法未允许!',
  14 + errMsg408: '网络请求超时!',
  15 + errMsg500: '服务器错误,请联系管理员!',
  16 + errMsg501: '网络未实现!',
  17 + errMsg502: '网络错误!',
  18 + errMsg503: '服务不可用,服务器暂时过载或维护!',
  19 + errMsg504: '网络超时!',
  20 + errMsg505: 'http版本不支持该请求!',
  21 +};
... ...
src/locales/lang/zh_CN/sys/app.ts 0 → 100644
  1 +export default {
  2 + loginOutTip: '温馨提醒',
  3 + loginOutMessage: '是否确认退出系统?',
  4 + menuLoading: '菜单加载中...',
  5 +};
... ...
src/router/guard/index.ts
... ... @@ -13,6 +13,7 @@ import { setTitle } from &#39;/@/utils/browser&#39;;
13 13 import { AxiosCanceler } from '/@/utils/http/axios/axiosCancel';
14 14  
15 15 import { tabStore } from '/@/store/modules/tab';
  16 +import { useI18n } from '/@/hooks/web/useI18n';
16 17  
17 18 const { closeMessageOnSwitch, removeAllHttpPending } = useProjectSetting();
18 19 const globSetting = useGlobSetting();
... ... @@ -54,8 +55,9 @@ export function createGuard(router: Router) {
54 55 });
55 56  
56 57 router.afterEach((to) => {
  58 + const { t } = useI18n();
57 59 // change html title
58   - setTitle(to.meta.title, globSetting.title);
  60 + setTitle(t(to.meta.title), globSetting.title);
59 61 });
60 62 createProgressGuard(router);
61 63 createPermissionGuard(router);
... ...
src/router/menus/modules/dashboard.ts
1 1 import type { MenuModule } from '/@/router/types.d';
  2 +
2 3 const menu: MenuModule = {
3 4 orderNo: 10,
4 5 menu: {
5   - name: 'Dashboard',
  6 + name: 'routes.dashboard.dashboard',
6 7 path: '/dashboard',
7   - // tag: {
8   - // dot: true,
9   - // },
10 8 children: [
11 9 {
12 10 path: '/workbench',
13   - name: '工作台',
14   - // tag: {
15   - // content: 'new',
16   - // },
  11 + name: 'routes.dashboard.workbench',
17 12 },
18 13 {
19 14 path: '/analysis',
20   - name: '分析页',
  15 + name: 'routes.dashboard.analysis',
21 16 },
22 17 {
23 18 path: '/welcome',
24   - name: '首页',
  19 + name: 'routes.dashboard.welcome',
25 20 },
26 21 ],
27 22 },
... ...
src/router/menus/modules/demo/charts.ts
1 1 import type { MenuModule } from '/@/router/types.d';
  2 +
2 3 const menu: MenuModule = {
3 4 orderNo: 500,
4 5 menu: {
5   - name: '图表',
  6 + name: 'routes.demo.charts.charts',
6 7 path: '/charts',
7 8 children: [
8 9 {
9 10 path: 'apexChart',
10   - name: 'ApexChart',
  11 + name: 'routes.demo.charts.apexChart',
11 12 },
12 13 {
13 14 path: 'echarts',
... ... @@ -15,15 +16,15 @@ const menu: MenuModule = {
15 16 children: [
16 17 {
17 18 path: 'map',
18   - name: '地图',
  19 + name: 'routes.demo.charts.map',
19 20 },
20 21 {
21 22 path: 'line',
22   - name: '折线图',
  23 + name: 'routes.demo.charts.line',
23 24 },
24 25 {
25 26 path: 'pie',
26   - name: '饼图',
  27 + name: 'routes.demo.charts.pie',
27 28 },
28 29 ],
29 30 },
... ...
src/router/menus/modules/demo/comp.ts
1 1 import type { MenuModule } from '/@/router/types.d';
  2 +
2 3 const menu: MenuModule = {
3 4 orderNo: 30,
4 5 menu: {
5   - name: '组件',
  6 + name: 'routes.demo.comp.comp',
6 7 path: '/comp',
7 8  
8 9 children: [
9 10 {
10 11 path: 'basic',
11   - name: '基础组件',
  12 + name: 'routes.demo.comp.basic',
12 13 },
13 14 {
14 15 path: 'countTo',
15   - name: '数字动画',
  16 + name: 'routes.demo.comp.countTo',
16 17 },
17 18 {
18 19 path: 'transition',
19   - name: '动画组件',
  20 + name: 'routes.demo.comp.transition',
20 21 },
21 22  
22 23 {
23 24 path: 'modal',
24   - name: '弹窗扩展',
  25 + name: 'routes.demo.comp.modal',
25 26 },
26 27 {
27 28 path: 'drawer',
28   - name: '抽屉扩展',
  29 + name: 'routes.demo.comp.drawer',
29 30 },
30 31 {
31 32 path: 'desc',
32   - name: '详情组件',
  33 + name: 'routes.demo.comp.desc',
33 34 },
34 35 {
35 36 path: 'qrcode',
36   - name: '二维码组件',
  37 + name: 'routes.demo.comp.qrcode',
37 38 },
38 39 {
39 40 path: 'strength-meter',
40   - name: '密码强度组件',
  41 + name: 'routes.demo.comp.strength',
41 42 },
42 43 {
43 44 path: 'upload',
44   - name: '上传组件',
  45 + name: 'routes.demo.comp.upload',
45 46 },
46 47 {
47 48 path: 'scroll',
48   - name: '滚动组件',
  49 + name: 'routes.demo.comp.scroll',
49 50 children: [
50 51 {
51 52 path: 'basic',
52   - name: '基础示例',
  53 + name: 'routes.demo.comp.scrollBasic',
53 54 },
54 55 {
55 56 path: 'action',
56   - name: '函数操作示例',
  57 + name: 'routes.demo.comp.scrollAction',
57 58 },
58 59 {
59 60 path: 'virtualScroll',
60   - name: '虚拟滚动',
  61 + name: 'routes.demo.comp.virtualScroll',
61 62 },
62 63 ],
63 64 },
64 65 {
65 66 path: 'lazy',
66   - name: '懒加载组件',
  67 + name: 'routes.demo.comp.lazy',
67 68 children: [
68 69 {
69 70 path: 'basic',
70   - name: '基础示例',
  71 + name: 'routes.demo.comp.lazyBasic',
71 72 },
72 73 {
73 74 path: 'transition',
74   - name: '动画效果',
  75 + name: 'routes.demo.comp.lazyTransition',
75 76 },
76 77 ],
77 78 },
78 79 {
79 80 path: 'verify',
80   - name: '验证组件',
  81 + name: 'routes.demo.comp.verify',
81 82 children: [
82 83 {
83 84 path: 'drag',
84   - name: '拖拽校验',
  85 + name: 'routes.demo.comp.verifyDrag',
85 86 },
86 87 {
87 88 path: 'rotate',
88   - name: '图片还原校验',
89   - },
90   - ],
91   - },
92   - {
93   - path: '/form',
94   - name: '验证组件',
95   - children: [
96   - {
97   - path: '/base',
98   - name: '拖拽校验',
  89 + name: 'routes.demo.comp.verifyRotate',
99 90 },
100 91 ],
101 92 },
... ...
src/router/menus/modules/demo/editor.ts
1 1 import type { MenuModule } from '/@/router/types.d';
  2 +
2 3 const menu: MenuModule = {
3 4 orderNo: 500,
4 5 menu: {
5   - name: '编辑器',
  6 + name: 'routes.demo.editor.editor',
6 7 path: '/editor',
7 8 children: [
8 9 {
9 10 path: 'markdown',
10   - name: 'markdown编辑器',
  11 + name: 'routes.demo.editor.markdown',
11 12 },
12 13 {
13 14 path: 'tinymce',
14   - name: '富文本',
  15 + name: 'routes.demo.editor.tinymce',
15 16 children: [
16 17 {
17 18 path: 'index',
18   - name: '基础使用',
  19 + name: 'routes.demo.editor.tinymceBasic',
19 20 },
20 21 {
21 22 path: 'editor',
22   - name: '嵌入form使用',
  23 + name: 'routes.demo.editor.tinymceForm',
23 24 },
24 25 ],
25 26 },
... ...
src/router/menus/modules/demo/excel.ts
1 1 import type { MenuModule } from '/@/router/types.d';
  2 +
2 3 const menu: MenuModule = {
3 4 orderNo: 500,
4 5 menu: {
5   - name: 'Excel',
  6 + name: 'routes.demo.excel.excel',
6 7 path: '/excel',
7 8 children: [
8 9 {
9 10 path: 'customExport',
10   - name: '选择导出格式',
  11 + name: 'routes.demo.excel.customExport',
11 12 },
12 13 {
13 14 path: 'jsonExport',
14   - name: 'JSON数据导出',
  15 + name: 'routes.demo.excel.jsonExport',
15 16 },
16 17 {
17 18 path: 'arrayExport',
18   - name: 'Array数据导出',
  19 + name: 'routes.demo.excel.arrayExport',
19 20 },
20 21 {
21 22 path: 'importExcel',
22   - name: '导入',
  23 + name: 'routes.demo.excel.importExcel',
23 24 },
24 25 ],
25 26 },
... ...
src/router/menus/modules/demo/feat.ts
1 1 import type { MenuModule } from '/@/router/types.d';
  2 +
2 3 const menu: MenuModule = {
3 4 orderNo: 19,
4 5 menu: {
5   - name: '功能',
  6 + name: 'routes.demo.feat.feat',
6 7 path: '/feat',
7 8  
8 9 children: [
9 10 {
10 11 path: 'icon',
11   - name: '图标',
  12 + name: 'routes.demo.feat.icon',
12 13 },
13 14 {
14 15 path: 'tabs',
15   - name: '标签页操作',
  16 + name: 'routes.demo.feat.tabs',
16 17 },
17 18 {
18 19 path: 'context-menu',
19   - name: '右键菜单',
  20 + name: 'routes.demo.feat.contextMenu',
20 21 },
21 22 {
22 23 path: 'download',
23   - name: '文件下载',
  24 + name: 'routes.demo.feat.download',
24 25 },
25 26 {
26 27 path: 'click-out-side',
27   - name: 'ClickOutSide',
  28 + name: 'routes.demo.feat.clickOutSide',
28 29 },
29 30 {
30 31 path: 'img-preview',
31   - name: '图片预览',
  32 + name: 'routes.demo.feat.imgPreview',
32 33 },
33 34 {
34 35 path: 'copy',
35   - name: '剪切板',
  36 + name: 'routes.demo.feat.copy',
36 37 },
37 38 {
38 39 path: 'msg',
39   - name: '消息提示',
  40 + name: 'routes.demo.feat.msg',
40 41 },
41 42 {
42 43 path: 'watermark',
43   - name: '水印',
  44 + name: 'routes.demo.feat.watermark',
44 45 },
45 46 {
46 47 path: 'full-screen',
47   - name: '全屏',
  48 + name: 'routes.demo.feat.fullScreen',
48 49 },
49 50 {
50 51 path: 'error-log',
51   - name: '错误日志',
  52 + name: 'routes.demo.feat.errorLog',
52 53 },
53 54 {
54 55 path: 'testTab',
55   - name: '带参Tab',
  56 + name: 'routes.demo.feat.tab',
56 57 children: [
57 58 {
58 59 path: 'id1',
59   - name: '带参tab1',
  60 + name: 'routes.demo.feat.tab1',
60 61 },
61 62 {
62 63 path: 'id2',
63   - name: '带参tab2',
  64 + name: 'routes.demo.feat.tab2',
64 65 },
65 66 ],
66 67 },
... ...
src/router/menus/modules/demo/form.ts
1 1 import type { MenuModule } from '/@/router/types.d';
  2 +
2 3 const menu: MenuModule = {
3 4 orderNo: 40,
4 5 menu: {
5 6 path: '/form',
6   - name: 'Form',
  7 + name: 'routes.demo.form.form',
7 8  
8 9 children: [
9 10 {
10 11 path: 'basic',
11   - name: '基础表单',
  12 + name: 'routes.demo.form.basic',
12 13 },
13 14 {
14 15 path: 'useForm',
15   - name: 'useForm',
  16 + name: 'routes.demo.form.useForm',
16 17 },
17 18 {
18 19 path: 'refForm',
19   - name: 'RefForm',
  20 + name: 'routes.demo.form.refForm',
20 21 },
21 22 {
22 23 path: 'advancedForm',
23   - name: '可收缩表单',
  24 + name: 'routes.demo.form.advancedForm',
24 25 },
25 26 {
26 27 path: 'ruleForm',
27   - name: '表单校验',
  28 + name: 'routes.demo.form.ruleForm',
28 29 },
29 30 {
30 31 path: 'dynamicForm',
31   - name: '动态表单',
  32 + name: 'routes.demo.form.dynamicForm',
32 33 },
33 34 {
34 35 path: 'customerForm',
35   - name: '自定义组件',
  36 + name: 'routes.demo.form.customerForm',
36 37 },
37 38 ],
38 39 },
... ...
src/router/menus/modules/demo/iframe.ts
1 1 import type { MenuModule } from '/@/router/types.d';
  2 +
2 3 const menu: MenuModule = {
3 4 orderNo: 1000,
4 5 menu: {
5   - name: '外部页面',
  6 + name: 'routes.demo.iframe.frame',
6 7 path: '/frame',
7 8 children: [
8 9 {
9 10 path: 'antv',
10   - name: 'antVue文档(内嵌)',
  11 + name: 'routes.demo.iframe.antv',
11 12 },
12 13 {
13 14 path: 'doc',
14   - name: '项目文档(内嵌)',
  15 + name: 'routes.demo.iframe.doc',
15 16 },
16 17 {
17 18 path: 'docExternal',
18   - name: '项目文档(外链)',
  19 + name: 'routes.demo.iframe.docExternal',
19 20 },
20 21 ],
21 22 },
... ...
src/router/menus/modules/demo/page.ts
1 1 import type { MenuModule } from '/@/router/types.d';
  2 +
2 3 const menu: MenuModule = {
3 4 orderNo: 20,
4 5 menu: {
5   - name: '页面',
  6 + name: 'routes.demo.page.page',
6 7 path: '/page-demo',
7 8 tag: {
8 9 dot: true,
... ... @@ -10,56 +11,56 @@ const menu: MenuModule = {
10 11 children: [
11 12 {
12 13 path: 'form',
13   - name: '表单页',
  14 + name: 'routes.demo.page.form',
14 15  
15 16 children: [
16 17 {
17 18 path: 'basic',
18   - name: '基础表单',
  19 + name: 'routes.demo.page.formBasic',
19 20 },
20 21 {
21 22 path: 'step',
22   - name: '分步表单',
  23 + name: 'routes.demo.page.formStep',
23 24 },
24 25 {
25 26 path: 'high',
26   - name: '高级表单',
  27 + name: 'routes.demo.page.formHigh',
27 28 },
28 29 ],
29 30 },
30 31 {
31 32 path: 'desc',
32   - name: '详情页',
  33 + name: 'routes.demo.page.desc',
33 34  
34 35 children: [
35 36 {
36 37 path: 'basic',
37   - name: '基础详情页',
  38 + name: 'routes.demo.page.descBasic',
38 39 },
39 40 {
40 41 path: 'high',
41   - name: '高级详情页',
  42 + name: 'routes.demo.page.descHigh',
42 43 },
43 44 ],
44 45 },
45 46 {
46 47 path: 'result',
47   - name: '结果页',
  48 + name: 'routes.demo.page.result',
48 49  
49 50 children: [
50 51 {
51 52 path: 'success',
52   - name: '成功页',
  53 + name: 'routes.demo.page.resultSuccess',
53 54 },
54 55 {
55 56 path: 'fail',
56   - name: '失败页',
  57 + name: 'routes.demo.page.resultFail',
57 58 },
58 59 ],
59 60 },
60 61 {
61 62 path: 'exception',
62   - name: '异常页',
  63 + name: 'routes.demo.page.exception',
63 64 children: [
64 65 {
65 66 path: '403',
... ... @@ -75,38 +76,38 @@ const menu: MenuModule = {
75 76 },
76 77 {
77 78 path: 'net-work-error',
78   - name: '网络错误',
  79 + name: 'routes.demo.page.netWorkError',
79 80 },
80 81 {
81 82 path: 'not-data',
82   - name: '无数据',
  83 + name: 'routes.demo.page.notData',
83 84 },
84 85 ],
85 86 },
86 87 {
87 88 path: 'account',
88   - name: '个人页',
  89 + name: 'routes.demo.page.account',
89 90 children: [
90 91 {
91 92 path: 'center',
92   - name: '个人中心',
  93 + name: 'routes.demo.page.accountCenter',
93 94 },
94 95 {
95 96 path: 'setting',
96   - name: '个人设置',
  97 + name: 'routes.demo.page.accountSetting',
97 98 },
98 99 ],
99 100 },
100 101 {
101 102 path: 'list',
102   - name: '列表页',
  103 + name: 'routes.demo.page.list',
103 104 tag: {
104 105 content: 'new',
105 106 },
106 107 children: [
107 108 {
108 109 path: 'card',
109   - name: '卡片列表',
  110 + name: 'routes.demo.page.listCard',
110 111 },
111 112 ],
112 113 },
... ...
src/router/menus/modules/demo/permission.ts
1 1 import type { MenuModule } from '/@/router/types.d';
  2 +
2 3 const menu: MenuModule = {
3 4 orderNo: 15,
4 5 menu: {
5   - name: '权限管理',
  6 + name: 'routes.demo.permission.permission',
6 7 path: '/permission',
7 8 children: [
8 9 {
9 10 path: 'front',
10   - name: '基于前端',
  11 + name: 'routes.demo.permission.front',
11 12 children: [
12 13 {
13 14 path: 'page',
14   - name: '页面权限',
  15 + name: 'routes.demo.permission.frontPage',
15 16 },
16 17 {
17 18 path: 'btn',
18   - name: '按钮权限',
  19 + name: 'routes.demo.permission.frontBtn',
19 20 },
20 21 {
21 22 path: 'auth-pageA',
22   - name: '权限测试页A',
  23 + name: 'routes.demo.permission.frontTestA',
23 24 },
24 25 {
25 26 path: 'auth-pageB',
26   - name: '权限测试页B',
  27 + name: 'routes.demo.permission.frontTestB',
27 28 },
28 29 ],
29 30 },
30 31 {
31 32 path: 'back',
32   - name: '基于后台',
  33 + name: 'routes.demo.permission.back',
33 34 children: [
34 35 {
35 36 path: 'page',
36   - name: '页面权限',
  37 + name: 'routes.demo.permission.backPage',
37 38 },
38 39 {
39 40 path: 'btn',
40   - name: '按钮权限',
  41 + name: 'routes.demo.permission.backBtn',
41 42 },
42 43 ],
43 44 },
... ...
src/router/menus/modules/demo/table.ts
1 1 import type { MenuModule } from '/@/router/types.d';
  2 +
2 3 const menu: MenuModule = {
3 4 orderNo: 30,
4 5 menu: {
5 6 path: '/table',
6   - name: 'Table',
  7 + name: 'routes.demo.table.table',
7 8 children: [
8 9 {
9 10 path: 'basic',
10   - name: '基础表格',
  11 + name: 'routes.demo.table.basic',
11 12 },
12 13 {
13 14 path: 'treeTable',
14   - name: '树形表格',
  15 + name: 'routes.demo.table.treeTable',
15 16 },
16 17 {
17 18 path: 'fetchTable',
18   - name: '远程加载',
  19 + name: 'routes.demo.table.fetchTable',
19 20 },
20 21 {
21 22 path: 'fixedColumn',
22   - name: '固定列',
  23 + name: 'routes.demo.table.fixedColumn',
23 24 },
24 25 {
25 26 path: 'customerCell',
26   - name: '自定义列',
  27 + name: 'routes.demo.table.customerCell',
27 28 },
28 29 {
29 30 path: 'formTable',
30   - name: '开启搜索区域',
  31 + name: 'routes.demo.table.formTable',
31 32 },
32 33 {
33 34 path: 'useTable',
34   - name: 'UseTable',
  35 + name: 'routes.demo.table.useTable',
35 36 },
36 37 {
37 38 path: 'refTable',
38   - name: 'RefTable',
  39 + name: 'routes.demo.table.refTable',
39 40 },
40 41 {
41 42 path: 'multipleHeader',
42   - name: '多级表头',
  43 + name: 'routes.demo.table.multipleHeader',
43 44 },
44 45 {
45 46 path: 'mergeHeader',
46   - name: '合并单元格',
  47 + name: 'routes.demo.table.mergeHeader',
47 48 },
48 49 {
49 50 path: 'expandTable',
50   - name: '可展开表格',
  51 + name: 'routes.demo.table.expandTable',
51 52 },
52 53 {
53 54 path: 'fixedHeight',
54   - name: '定高/头部自定义',
  55 + name: 'routes.demo.table.fixedHeight',
55 56 },
56 57 {
57 58 path: 'footerTable',
58   - name: '表尾行合计',
  59 + name: 'routes.demo.table.footerTable',
59 60 },
60 61 {
61 62 path: 'editCellTable',
62   - name: '可编辑单元格',
  63 + name: 'routes.demo.table.editCellTable',
63 64 },
64 65 {
65 66 path: 'editRowTable',
66   - name: '可编辑行',
  67 + name: 'routes.demo.table.editRowTable',
67 68 },
68 69 ],
69 70 },
... ...
src/router/menus/modules/demo/tree.ts
1 1 import type { MenuModule } from '/@/router/types.d';
  2 +
2 3 const menu: MenuModule = {
3 4 orderNo: 50,
4 5 menu: {
5 6 path: '/tree',
6   - name: 'Tree',
  7 + name: 'routes.demo.tree.tree',
7 8 children: [
8 9 {
9 10 path: 'basic',
10   - name: '基础示例',
  11 + name: 'routes.demo.tree.basic',
11 12 },
12 13 {
13 14 path: 'editTree',
14   - name: '右键示例',
  15 + name: 'routes.demo.tree.editTree',
15 16 },
16 17 {
17 18 path: 'actionTree',
18   - name: '函数操作示例',
  19 + name: 'routes.demo.tree.actionTree',
19 20 },
20 21 ],
21 22 },
... ...
src/router/routes/index.ts
... ... @@ -33,7 +33,7 @@ export const LoginRoute: AppRouteRecordRaw = {
33 33 name: 'Login',
34 34 component: () => import('/@/views/sys/login/Login.vue'),
35 35 meta: {
36   - title: '登录',
  36 + title: 'routes.basic.login',
37 37 },
38 38 };
39 39  
... ...
src/router/routes/modules/dashboard.ts
... ... @@ -10,7 +10,7 @@ const dashboard: AppRouteModule = {
10 10 redirect: '/dashboard/workbench',
11 11 meta: {
12 12 icon: 'ant-design:home-outlined',
13   - title: 'Dashboard',
  13 + title: 'routes.dashboard.dashboard',
14 14 },
15 15 },
16 16  
... ... @@ -20,7 +20,7 @@ const dashboard: AppRouteModule = {
20 20 name: 'Welcome',
21 21 component: () => import('/@/views/dashboard/welcome/index.vue'),
22 22 meta: {
23   - title: '首页',
  23 + title: 'routes.dashboard.welcome',
24 24 },
25 25 },
26 26 {
... ... @@ -28,7 +28,7 @@ const dashboard: AppRouteModule = {
28 28 name: 'Workbench',
29 29 component: () => import('/@/views/dashboard/workbench/index.vue'),
30 30 meta: {
31   - title: '工作台',
  31 + title: 'routes.dashboard.workbench',
32 32 affix: true,
33 33 },
34 34 },
... ... @@ -37,7 +37,7 @@ const dashboard: AppRouteModule = {
37 37 name: 'Analysis',
38 38 component: () => import('/@/views/dashboard/analysis/index.vue'),
39 39 meta: {
40   - title: '分析页',
  40 + title: 'routes.dashboard.analysis',
41 41 },
42 42 },
43 43 ],
... ...
src/router/routes/modules/demo/charts.ts
... ... @@ -10,7 +10,7 @@ const charts: AppRouteModule = {
10 10 redirect: '/charts/apexChart',
11 11 meta: {
12 12 icon: 'ant-design:area-chart-outlined',
13   - title: '图表库',
  13 + title: 'routes.demo.charts.charts',
14 14 },
15 15 },
16 16  
... ... @@ -27,7 +27,7 @@ const charts: AppRouteModule = {
27 27 name: 'Map',
28 28 component: () => import('/@/views/demo/echarts/Map.vue'),
29 29 meta: {
30   - title: '地图',
  30 + title: 'routes.demo.charts.map',
31 31 },
32 32 },
33 33 {
... ... @@ -35,7 +35,7 @@ const charts: AppRouteModule = {
35 35 name: 'Line',
36 36 component: () => import('/@/views/demo/echarts/Line.vue'),
37 37 meta: {
38   - title: '折线图',
  38 + title: 'routes.demo.charts.line',
39 39 },
40 40 },
41 41 {
... ... @@ -43,7 +43,7 @@ const charts: AppRouteModule = {
43 43 name: 'Pie',
44 44 component: () => import('/@/views/demo/echarts/Pie.vue'),
45 45 meta: {
46   - title: '饼图',
  46 + title: 'routes.demo.charts.pie',
47 47 },
48 48 },
49 49 ],
... ... @@ -52,7 +52,7 @@ const charts: AppRouteModule = {
52 52 path: '/apexChart',
53 53 name: 'ApexChart',
54 54 meta: {
55   - title: 'ApexChart',
  55 + title: 'routes.demo.charts.apexChart',
56 56 },
57 57 component: () => import('/@/views/demo/echarts/apex/index.vue'),
58 58 },
... ...
src/router/routes/modules/demo/comp.ts
... ... @@ -10,7 +10,7 @@ const comp: AppRouteModule = {
10 10 redirect: '/comp/basic',
11 11 meta: {
12 12 icon: 'ant-design:table-outlined',
13   - title: '组件',
  13 + title: 'routes.demo.comp.comp',
14 14 },
15 15 },
16 16  
... ... @@ -20,7 +20,7 @@ const comp: AppRouteModule = {
20 20 name: 'BasicDemo',
21 21 component: () => import('/@/views/demo/comp/button/index.vue'),
22 22 meta: {
23   - title: '基础组件',
  23 + title: 'routes.demo.comp.basic',
24 24 },
25 25 },
26 26 {
... ... @@ -28,7 +28,7 @@ const comp: AppRouteModule = {
28 28 name: 'transitionDemo',
29 29 component: () => import('/@/views/demo/comp/transition/index.vue'),
30 30 meta: {
31   - title: '动画组件',
  31 + title: 'routes.demo.comp.transition',
32 32 },
33 33 },
34 34 {
... ... @@ -36,7 +36,7 @@ const comp: AppRouteModule = {
36 36 name: 'CountTo',
37 37 component: () => import('/@/views/demo/comp/count-to/index.vue'),
38 38 meta: {
39   - title: '数字动画',
  39 + title: 'routes.demo.comp.countTo',
40 40 },
41 41 },
42 42  
... ... @@ -45,7 +45,7 @@ const comp: AppRouteModule = {
45 45 name: 'ScrollDemo',
46 46 redirect: '/comp/scroll/basic',
47 47 meta: {
48   - title: '滚动组件',
  48 + title: 'routes.demo.comp.scroll',
49 49 },
50 50 children: [
51 51 {
... ... @@ -53,7 +53,7 @@ const comp: AppRouteModule = {
53 53 name: 'BasicScrollDemo',
54 54 component: () => import('/@/views/demo/comp/scroll/index.vue'),
55 55 meta: {
56   - title: '基础滚动',
  56 + title: 'routes.demo.comp.scrollBasic',
57 57 },
58 58 },
59 59 {
... ... @@ -61,7 +61,7 @@ const comp: AppRouteModule = {
61 61 name: 'ActionScrollDemo',
62 62 component: () => import('/@/views/demo/comp/scroll/Action.vue'),
63 63 meta: {
64   - title: '滚动函数',
  64 + title: 'routes.demo.comp.scrollAction',
65 65 },
66 66 },
67 67 {
... ... @@ -69,7 +69,7 @@ const comp: AppRouteModule = {
69 69 name: 'VirtualScrollDemo',
70 70 component: () => import('/@/views/demo/comp/scroll/VirtualScroll.vue'),
71 71 meta: {
72   - title: '虚拟滚动',
  72 + title: 'routes.demo.comp.virtualScroll',
73 73 },
74 74 },
75 75 ],
... ... @@ -80,7 +80,7 @@ const comp: AppRouteModule = {
80 80 name: 'ModalDemo',
81 81 component: () => import('/@/views/demo/comp/modal/index.vue'),
82 82 meta: {
83   - title: '弹窗扩展',
  83 + title: 'routes.demo.comp.modal',
84 84 },
85 85 },
86 86 {
... ... @@ -88,7 +88,7 @@ const comp: AppRouteModule = {
88 88 name: 'DrawerDemo',
89 89 component: () => import('/@/views/demo/comp/drawer/index.vue'),
90 90 meta: {
91   - title: '抽屉扩展',
  91 + title: 'routes.demo.comp.drawer',
92 92 },
93 93 },
94 94 {
... ... @@ -96,7 +96,7 @@ const comp: AppRouteModule = {
96 96 name: 'DescDemo',
97 97 component: () => import('/@/views/demo/comp/desc/index.vue'),
98 98 meta: {
99   - title: '详情组件',
  99 + title: 'routes.demo.comp.desc',
100 100 },
101 101 },
102 102  
... ... @@ -105,7 +105,7 @@ const comp: AppRouteModule = {
105 105 name: 'lazyDemo',
106 106 redirect: '/comp/lazy/basic',
107 107 meta: {
108   - title: '懒加载组件',
  108 + title: 'routes.demo.comp.lazy',
109 109 },
110 110 children: [
111 111 {
... ... @@ -113,7 +113,7 @@ const comp: AppRouteModule = {
113 113 name: 'BasicLazyDemo',
114 114 component: () => import('/@/views/demo/comp/lazy/index.vue'),
115 115 meta: {
116   - title: '基础示例',
  116 + title: 'routes.demo.comp.lazyBasic',
117 117 },
118 118 },
119 119 {
... ... @@ -121,7 +121,7 @@ const comp: AppRouteModule = {
121 121 name: 'BasicTransitionDemo',
122 122 component: () => import('/@/views/demo/comp/lazy/Transition.vue'),
123 123 meta: {
124   - title: '动画效果',
  124 + title: 'routes.demo.comp.lazyTransition',
125 125 },
126 126 },
127 127 ],
... ... @@ -131,7 +131,7 @@ const comp: AppRouteModule = {
131 131 name: 'VerifyDemo',
132 132 redirect: '/comp/verify/drag',
133 133 meta: {
134   - title: '验证组件',
  134 + title: 'routes.demo.comp.verify',
135 135 },
136 136 children: [
137 137 {
... ... @@ -139,7 +139,7 @@ const comp: AppRouteModule = {
139 139 name: 'VerifyDragDemo',
140 140 component: () => import('/@/views/demo/comp/verify/index.vue'),
141 141 meta: {
142   - title: '拖拽校验',
  142 + title: 'routes.demo.comp.verifyDrag',
143 143 },
144 144 },
145 145 {
... ... @@ -147,7 +147,7 @@ const comp: AppRouteModule = {
147 147 name: 'VerifyRotateDemo',
148 148 component: () => import('/@/views/demo/comp/verify/Rotate.vue'),
149 149 meta: {
150   - title: '图片还原',
  150 + title: 'routes.demo.comp.verifyRotate',
151 151 },
152 152 },
153 153 ],
... ... @@ -159,7 +159,7 @@ const comp: AppRouteModule = {
159 159 name: 'QrCodeDemo',
160 160 component: () => import('/@/views/demo/comp/qrcode/index.vue'),
161 161 meta: {
162   - title: '二维码组件',
  162 + title: 'routes.demo.comp.qrcode',
163 163 },
164 164 },
165 165 {
... ... @@ -167,7 +167,7 @@ const comp: AppRouteModule = {
167 167 name: 'StrengthMeterDemo',
168 168 component: () => import('/@/views/demo/comp/strength-meter/index.vue'),
169 169 meta: {
170   - title: '密码强度组件',
  170 + title: 'routes.demo.comp.strength',
171 171 },
172 172 },
173 173 {
... ... @@ -175,7 +175,7 @@ const comp: AppRouteModule = {
175 175 name: 'UploadDemo',
176 176 component: () => import('/@/views/demo/comp/upload/index.vue'),
177 177 meta: {
178   - title: '上传组件',
  178 + title: 'routes.demo.comp.upload',
179 179 },
180 180 },
181 181 ],
... ...
src/router/routes/modules/demo/editor.ts
... ... @@ -10,7 +10,7 @@ const editor: AppRouteModule = {
10 10 redirect: '/editor/markdown',
11 11 meta: {
12 12 icon: 'ant-design:table-outlined',
13   - title: '编辑器',
  13 + title: 'routes.demo.editor.editor',
14 14 },
15 15 },
16 16  
... ... @@ -20,14 +20,14 @@ const editor: AppRouteModule = {
20 20 name: 'MarkdownDemo',
21 21 component: () => import('/@/views/demo/editor/Markdown.vue'),
22 22 meta: {
23   - title: 'markdown编辑器',
  23 + title: 'routes.demo.editor.markdown',
24 24 },
25 25 },
26 26 {
27 27 path: '/tinymce',
28 28 name: 'TinymceDemo',
29 29 meta: {
30   - title: '富文本',
  30 + title: 'routes.demo.editor.tinymce',
31 31 },
32 32 redirect: '/editor/tinymce/index',
33 33 children: [
... ... @@ -36,7 +36,7 @@ const editor: AppRouteModule = {
36 36 name: 'TinymceBasicDemo',
37 37 component: () => import('/@/views/demo/editor/tinymce/index.vue'),
38 38 meta: {
39   - title: '基础使用',
  39 + title: 'routes.demo.editor.tinymceBasic',
40 40 },
41 41 },
42 42 // TODO
... ... @@ -45,7 +45,7 @@ const editor: AppRouteModule = {
45 45 name: 'TinymceFormDemo',
46 46 component: () => import('/@/views/demo/editor/tinymce/Editor.vue'),
47 47 meta: {
48   - title: '嵌入form使用',
  48 + title: 'routes.demo.editor.tinymceForm',
49 49 },
50 50 },
51 51 ],
... ...
src/router/routes/modules/demo/excel.ts
... ... @@ -10,7 +10,7 @@ const excel: AppRouteModule = {
10 10 redirect: '/excel/customExport',
11 11 meta: {
12 12 icon: 'mdi:microsoft-excel',
13   - title: 'Excel',
  13 + title: 'routes.demo.excel.excel',
14 14 },
15 15 },
16 16  
... ... @@ -20,7 +20,7 @@ const excel: AppRouteModule = {
20 20 name: 'CustomExport',
21 21 component: () => import('/@/views/demo/excel/CustomExport.vue'),
22 22 meta: {
23   - title: '选择导出格式',
  23 + title: 'routes.demo.excel.customExport',
24 24 },
25 25 },
26 26 {
... ... @@ -28,7 +28,7 @@ const excel: AppRouteModule = {
28 28 name: 'JsonExport',
29 29 component: () => import('/@/views/demo/excel/JsonExport.vue'),
30 30 meta: {
31   - title: 'JSON数据导出',
  31 + title: 'routes.demo.excel.jsonExport',
32 32 },
33 33 },
34 34 {
... ... @@ -36,7 +36,7 @@ const excel: AppRouteModule = {
36 36 name: 'ArrayExport',
37 37 component: () => import('/@/views/demo/excel/ArrayExport.vue'),
38 38 meta: {
39   - title: 'Array数据导出',
  39 + title: 'routes.demo.excel.arrayExport',
40 40 },
41 41 },
42 42 {
... ... @@ -44,7 +44,7 @@ const excel: AppRouteModule = {
44 44 name: 'ImportExcel',
45 45 component: () => import('/@/views/demo/excel/ImportExcel.vue'),
46 46 meta: {
47   - title: '导入',
  47 + title: 'routes.demo.excel.importExcel',
48 48 },
49 49 },
50 50 ],
... ...
src/router/routes/modules/demo/feat.ts
... ... @@ -10,7 +10,7 @@ const feat: AppRouteModule = {
10 10 redirect: '/feat/icon',
11 11 meta: {
12 12 icon: 'ic:outline-featured-play-list',
13   - title: '页面功能',
  13 + title: 'routes.demo.feat.feat',
14 14 },
15 15 },
16 16  
... ... @@ -20,7 +20,7 @@ const feat: AppRouteModule = {
20 20 name: 'IconDemo',
21 21 component: () => import('/@/views/demo/feat/icon/index.vue'),
22 22 meta: {
23   - title: '图标',
  23 + title: 'routes.demo.feat.icon',
24 24 },
25 25 },
26 26 {
... ... @@ -28,7 +28,7 @@ const feat: AppRouteModule = {
28 28 name: 'TabsDemo',
29 29 component: () => import('/@/views/demo/feat/tabs/index.vue'),
30 30 meta: {
31   - title: '标签页操作',
  31 + title: 'routes.demo.feat.tabs',
32 32 },
33 33 },
34 34  
... ... @@ -37,7 +37,7 @@ const feat: AppRouteModule = {
37 37 name: 'ContextMenuDemo',
38 38 component: () => import('/@/views/demo/feat/context-menu/index.vue'),
39 39 meta: {
40   - title: '右键菜单',
  40 + title: 'routes.demo.feat.contextMenu',
41 41 },
42 42 },
43 43 {
... ... @@ -45,7 +45,7 @@ const feat: AppRouteModule = {
45 45 name: 'DownLoadDemo',
46 46 component: () => import('/@/views/demo/feat/download/index.vue'),
47 47 meta: {
48   - title: '文件下载',
  48 + title: 'routes.demo.feat.download',
49 49 },
50 50 },
51 51 {
... ... @@ -53,7 +53,7 @@ const feat: AppRouteModule = {
53 53 name: 'ClickOutSideDemo',
54 54 component: () => import('/@/views/demo/feat/click-out-side/index.vue'),
55 55 meta: {
56   - title: 'ClickOutSide组件',
  56 + title: 'routes.demo.feat.clickOutSide',
57 57 },
58 58 },
59 59 {
... ... @@ -61,7 +61,7 @@ const feat: AppRouteModule = {
61 61 name: 'ImgPreview',
62 62 component: () => import('/@/views/demo/feat/img-preview/index.vue'),
63 63 meta: {
64   - title: '图片预览',
  64 + title: 'routes.demo.feat.imgPreview',
65 65 },
66 66 },
67 67 {
... ... @@ -69,7 +69,7 @@ const feat: AppRouteModule = {
69 69 name: 'CopyDemo',
70 70 component: () => import('/@/views/demo/feat/copy/index.vue'),
71 71 meta: {
72   - title: '剪切板',
  72 + title: 'routes.demo.feat.copy',
73 73 },
74 74 },
75 75 {
... ... @@ -77,7 +77,7 @@ const feat: AppRouteModule = {
77 77 name: 'MsgDemo',
78 78 component: () => import('/@/views/demo/feat/msg/index.vue'),
79 79 meta: {
80   - title: '消息提示',
  80 + title: 'routes.demo.feat.msg',
81 81 },
82 82 },
83 83 {
... ... @@ -85,7 +85,7 @@ const feat: AppRouteModule = {
85 85 name: 'WatermarkDemo',
86 86 component: () => import('/@/views/demo/feat/watermark/index.vue'),
87 87 meta: {
88   - title: '水印',
  88 + title: 'routes.demo.feat.watermark',
89 89 },
90 90 },
91 91 {
... ... @@ -93,7 +93,7 @@ const feat: AppRouteModule = {
93 93 name: 'FullScreenDemo',
94 94 component: () => import('/@/views/demo/feat/full-screen/index.vue'),
95 95 meta: {
96   - title: '全屏',
  96 + title: 'routes.demo.feat.fullScreen',
97 97 },
98 98 },
99 99 {
... ... @@ -101,7 +101,7 @@ const feat: AppRouteModule = {
101 101 name: 'ErrorLog',
102 102 component: () => import('/@/views/sys/error-log/index.vue'),
103 103 meta: {
104   - title: '错误日志',
  104 + title: 'routes.demo.feat.errorLog',
105 105 },
106 106 },
107 107 {
... ... @@ -109,7 +109,7 @@ const feat: AppRouteModule = {
109 109 name: 'TestTab',
110 110 component: () => import('/@/views/demo/feat/tab-params/index.vue'),
111 111 meta: {
112   - title: 'Tab带参',
  112 + title: 'routes.demo.feat.tab',
113 113 carryParam: true,
114 114 },
115 115 },
... ...
src/router/routes/modules/demo/form.ts
... ... @@ -10,7 +10,7 @@ const form: AppRouteModule = {
10 10 redirect: '/form/basic',
11 11 meta: {
12 12 icon: 'ant-design:table-outlined',
13   - title: 'Form',
  13 + title: 'rroutes.demo.form.form',
14 14 },
15 15 },
16 16  
... ... @@ -20,7 +20,7 @@ const form: AppRouteModule = {
20 20 name: 'FormBasicDemo',
21 21 component: () => import('/@/views/demo/form/index.vue'),
22 22 meta: {
23   - title: '基础表单',
  23 + title: 'rroutes.demo.form.basic',
24 24 },
25 25 },
26 26 {
... ... @@ -28,7 +28,7 @@ const form: AppRouteModule = {
28 28 name: 'UseFormDemo',
29 29 component: () => import('/@/views/demo/form/UseForm.vue'),
30 30 meta: {
31   - title: 'useForm',
  31 + title: 'rroutes.demo.form.useForm',
32 32 },
33 33 },
34 34 {
... ... @@ -36,7 +36,7 @@ const form: AppRouteModule = {
36 36 name: 'RefFormDemo',
37 37 component: () => import('/@/views/demo/form/RefForm.vue'),
38 38 meta: {
39   - title: 'RefForm',
  39 + title: 'rroutes.demo.form.refForm',
40 40 },
41 41 },
42 42 {
... ... @@ -44,7 +44,7 @@ const form: AppRouteModule = {
44 44 name: 'AdvancedFormDemo',
45 45 component: () => import('/@/views/demo/form/AdvancedForm.vue'),
46 46 meta: {
47   - title: '可收缩表单',
  47 + title: 'rroutes.demo.form.advancedForm',
48 48 },
49 49 },
50 50 {
... ... @@ -52,7 +52,7 @@ const form: AppRouteModule = {
52 52 name: 'RuleFormDemo',
53 53 component: () => import('/@/views/demo/form/RuleForm.vue'),
54 54 meta: {
55   - title: '表单验证',
  55 + title: 'rroutes.demo.form.ruleForm',
56 56 },
57 57 },
58 58 {
... ... @@ -60,7 +60,7 @@ const form: AppRouteModule = {
60 60 name: 'DynamicFormDemo',
61 61 component: () => import('/@/views/demo/form/DynamicForm.vue'),
62 62 meta: {
63   - title: '动态表单',
  63 + title: 'rroutes.demo.form.dynamicForm',
64 64 },
65 65 },
66 66 {
... ... @@ -68,7 +68,7 @@ const form: AppRouteModule = {
68 68 name: 'CustomerFormDemo',
69 69 component: () => import('/@/views/demo/form/CustomerForm.vue'),
70 70 meta: {
71   - title: '自定义组件',
  71 + title: 'rroutes.demo.form.customerForm',
72 72 },
73 73 },
74 74 ],
... ...
src/router/routes/modules/demo/iframe.ts
... ... @@ -11,7 +11,7 @@ const iframe: AppRouteModule = {
11 11 redirect: '/frame/antv',
12 12 meta: {
13 13 icon: 'mdi:page-next-outline',
14   - title: '外部页面',
  14 + title: 'routes.demo.iframe.frame',
15 15 },
16 16 },
17 17  
... ... @@ -22,7 +22,7 @@ const iframe: AppRouteModule = {
22 22 component: IFrame,
23 23 meta: {
24 24 frameSrc: 'https://2x.antdv.com/docs/vue/introduce-cn/',
25   - title: 'antVue文档(内嵌)',
  25 + title: 'routes.demo.iframe.antv',
26 26 afterCloseLoading: true,
27 27 },
28 28 },
... ... @@ -32,7 +32,7 @@ const iframe: AppRouteModule = {
32 32 component: IFrame,
33 33 meta: {
34 34 frameSrc: 'https://vvbin.cn/doc-next/',
35   - title: '项目文档(内嵌)',
  35 + title: 'routes.demo.iframe.doc',
36 36 afterCloseLoading: true,
37 37 },
38 38 },
... ... @@ -42,7 +42,7 @@ const iframe: AppRouteModule = {
42 42 component: IFrame,
43 43 meta: {
44 44 externalLink: 'https://vvbin.cn/doc-next/',
45   - title: '项目文档(外链)',
  45 + title: 'routes.demo.iframe.docExternal',
46 46 },
47 47 },
48 48 ],
... ...
src/router/routes/modules/demo/page.ts
... ... @@ -12,7 +12,7 @@ const page: AppRouteModule = {
12 12 redirect: '/page-demo/exception',
13 13 meta: {
14 14 icon: 'mdi:page-next-outline',
15   - title: '页面',
  15 + title: 'routes.demo.page.page',
16 16 },
17 17 children: [
18 18 // =============================form start=============================
... ... @@ -21,7 +21,7 @@ const page: AppRouteModule = {
21 21 name: 'FormPage',
22 22 redirect: '/page-demo/form/basic',
23 23 meta: {
24   - title: '表单页',
  24 + title: 'routes.demo.page.form',
25 25 },
26 26 children: [
27 27 {
... ... @@ -29,7 +29,7 @@ const page: AppRouteModule = {
29 29 name: 'FormBasicPage',
30 30 component: () => import('/@/views/demo/page/form/basic/index.vue'),
31 31 meta: {
32   - title: '基础表单',
  32 + title: 'routes.demo.page.formBasic',
33 33 },
34 34 },
35 35 {
... ... @@ -37,7 +37,7 @@ const page: AppRouteModule = {
37 37 name: 'FormStepPage',
38 38 component: () => import('/@/views/demo/page/form/step/index.vue'),
39 39 meta: {
40   - title: '分步表单',
  40 + title: 'routes.demo.page.formStep',
41 41 },
42 42 },
43 43 {
... ... @@ -45,7 +45,7 @@ const page: AppRouteModule = {
45 45 name: 'FormHightPage',
46 46 component: () => import('/@/views/demo/page/form/high/index.vue'),
47 47 meta: {
48   - title: '高级表单',
  48 + title: 'routes.demo.page.formHigh',
49 49 },
50 50 },
51 51 ],
... ... @@ -57,7 +57,7 @@ const page: AppRouteModule = {
57 57 name: 'DescPage',
58 58 redirect: '/page-demo/desc/basic',
59 59 meta: {
60   - title: '详情页',
  60 + title: 'routes.demo.page.desc',
61 61 },
62 62 children: [
63 63 {
... ... @@ -65,7 +65,7 @@ const page: AppRouteModule = {
65 65 name: 'DescBasicPage',
66 66 component: () => import('/@/views/demo/page/desc/basic/index.vue'),
67 67 meta: {
68   - title: '基础详情页',
  68 + title: 'routes.demo.page.descBasic',
69 69 },
70 70 },
71 71 {
... ... @@ -73,7 +73,7 @@ const page: AppRouteModule = {
73 73 name: 'DescHighPage',
74 74 component: () => import('/@/views/demo/page/desc/high/index.vue'),
75 75 meta: {
76   - title: '高级详情页',
  76 + title: 'routes.demo.page.descHigh',
77 77 },
78 78 },
79 79 ],
... ... @@ -86,7 +86,7 @@ const page: AppRouteModule = {
86 86 name: 'ResultPage',
87 87 redirect: '/page-demo/result/success',
88 88 meta: {
89   - title: '结果页',
  89 + title: 'routes.demo.page.result',
90 90 },
91 91 children: [
92 92 {
... ... @@ -94,7 +94,7 @@ const page: AppRouteModule = {
94 94 name: 'ResultSuccessPage',
95 95 component: () => import('/@/views/demo/page/result/success/index.vue'),
96 96 meta: {
97   - title: '成功页',
  97 + title: 'routes.demo.page.resultSuccess',
98 98 },
99 99 },
100 100 {
... ... @@ -102,7 +102,7 @@ const page: AppRouteModule = {
102 102 name: 'ResultFailPage',
103 103 component: () => import('/@/views/demo/page/result/fail/index.vue'),
104 104 meta: {
105   - title: '失败页',
  105 + title: 'routes.demo.page.resultFail',
106 106 },
107 107 },
108 108 ],
... ... @@ -115,7 +115,7 @@ const page: AppRouteModule = {
115 115 name: 'AccountPage',
116 116 redirect: '/page-demo/account/setting',
117 117 meta: {
118   - title: '个人页',
  118 + title: 'routes.demo.page.account',
119 119 },
120 120 children: [
121 121 {
... ... @@ -123,7 +123,7 @@ const page: AppRouteModule = {
123 123 name: 'AccountCenterPage',
124 124 component: () => import('/@/views/demo/page/account/center/index.vue'),
125 125 meta: {
126   - title: '个人中心',
  126 + title: 'routes.demo.page.accountCenter',
127 127 },
128 128 },
129 129 {
... ... @@ -131,7 +131,7 @@ const page: AppRouteModule = {
131 131 name: 'AccountSettingPage',
132 132 component: () => import('/@/views/demo/page/account/setting/index.vue'),
133 133 meta: {
134   - title: '个人设置',
  134 + title: 'routes.demo.page.accountSetting',
135 135 },
136 136 },
137 137 ],
... ... @@ -143,7 +143,7 @@ const page: AppRouteModule = {
143 143 name: 'ExceptionPage',
144 144 redirect: '/page-demo/exception/404',
145 145 meta: {
146   - title: '异常页',
  146 + title: 'routes.demo.page.exception',
147 147 },
148 148 children: [
149 149 {
... ... @@ -190,7 +190,7 @@ const page: AppRouteModule = {
190 190 status: ExceptionEnum.NET_WORK_ERROR,
191 191 },
192 192 meta: {
193   - title: '网络错误',
  193 + title: 'routes.demo.page.netWorkError',
194 194 afterCloseLoading: true,
195 195 },
196 196 },
... ... @@ -202,7 +202,7 @@ const page: AppRouteModule = {
202 202 status: ExceptionEnum.PAGE_NOT_DATA,
203 203 },
204 204 meta: {
205   - title: '无数据',
  205 + title: 'routes.demo.page.notData',
206 206 afterCloseLoading: true,
207 207 },
208 208 },
... ... @@ -215,7 +215,7 @@ const page: AppRouteModule = {
215 215 name: 'ListPage',
216 216 redirect: '/page-demo/list/card',
217 217 meta: {
218   - title: '列表页',
  218 + title: 'routes.demo.page.list',
219 219 },
220 220 children: [
221 221 {
... ... @@ -223,7 +223,7 @@ const page: AppRouteModule = {
223 223 name: 'ListCardPage',
224 224 component: () => import('/@/views/demo/page/list/card/index.vue'),
225 225 meta: {
226   - title: '卡片列表',
  226 + title: 'routes.demo.page.listCard',
227 227 },
228 228 },
229 229 ],
... ...
src/router/routes/modules/demo/permission.ts
... ... @@ -11,7 +11,7 @@ const permission: AppRouteModule = {
11 11 redirect: '/permission/front/page',
12 12 meta: {
13 13 icon: 'carbon:user-role',
14   - title: '权限管理',
  14 + title: 'routes.demo.permission.permission',
15 15 },
16 16 },
17 17  
... ... @@ -20,7 +20,7 @@ const permission: AppRouteModule = {
20 20 path: '/front',
21 21 name: 'PermissionFrontDemo',
22 22 meta: {
23   - title: '基于前端权限',
  23 + title: 'routes.demo.permission.front',
24 24 },
25 25 children: [
26 26 {
... ... @@ -28,7 +28,7 @@ const permission: AppRouteModule = {
28 28 name: 'FrontPageAuth',
29 29 component: () => import('/@/views/demo/permission/front/index.vue'),
30 30 meta: {
31   - title: '页面权限',
  31 + title: 'routes.demo.permission.frontPage',
32 32 },
33 33 },
34 34 {
... ... @@ -36,7 +36,7 @@ const permission: AppRouteModule = {
36 36 name: 'FrontBtnAuth',
37 37 component: () => import('/@/views/demo/permission/front/Btn.vue'),
38 38 meta: {
39   - title: '按钮权限',
  39 + title: 'routes.demo.permission.frontBtn',
40 40 },
41 41 },
42 42 {
... ... @@ -44,7 +44,7 @@ const permission: AppRouteModule = {
44 44 name: 'FrontAuthPageA',
45 45 component: () => import('/@/views/demo/permission/front/AuthPageA.vue'),
46 46 meta: {
47   - title: '权限测试页A',
  47 + title: 'routes.demo.permission.frontTestA',
48 48 roles: [RoleEnum.SUPER],
49 49 },
50 50 },
... ... @@ -53,7 +53,7 @@ const permission: AppRouteModule = {
53 53 name: 'FrontAuthPageB',
54 54 component: () => import('/@/views/demo/permission/front/AuthPageB.vue'),
55 55 meta: {
56   - title: '权限测试页B',
  56 + title: 'routes.demo.permission.frontTestB',
57 57 roles: [RoleEnum.TEST],
58 58 },
59 59 },
... ... @@ -63,7 +63,7 @@ const permission: AppRouteModule = {
63 63 path: '/back',
64 64 name: 'PermissionBackDemo',
65 65 meta: {
66   - title: '基于后台权限',
  66 + title: 'routes.demo.permission.back',
67 67 },
68 68 children: [
69 69 {
... ... @@ -71,7 +71,7 @@ const permission: AppRouteModule = {
71 71 name: 'BackAuthPage',
72 72 component: () => import('/@/views/demo/permission/back/index.vue'),
73 73 meta: {
74   - title: '页面权限',
  74 + title: 'routes.demo.permission.backPage',
75 75 },
76 76 },
77 77 {
... ... @@ -79,7 +79,7 @@ const permission: AppRouteModule = {
79 79 name: 'BackAuthBtn',
80 80 component: () => import('/@/views/demo/permission/back/Btn.vue'),
81 81 meta: {
82   - title: '按钮权限',
  82 + title: 'routes.demo.permission.backBtn',
83 83 },
84 84 },
85 85 ],
... ...
src/router/routes/modules/demo/table.ts
... ... @@ -10,7 +10,7 @@ const table: AppRouteModule = {
10 10 redirect: '/table/basic',
11 11 meta: {
12 12 icon: 'ant-design:table-outlined',
13   - title: 'Table',
  13 + title: 'routes.demo.table.table',
14 14 },
15 15 },
16 16  
... ... @@ -20,7 +20,7 @@ const table: AppRouteModule = {
20 20 name: 'TableBasicDemo',
21 21 component: () => import('/@/views/demo/table/Basic.vue'),
22 22 meta: {
23   - title: '基础表格',
  23 + title: 'routes.demo.table.basic',
24 24 },
25 25 },
26 26 {
... ... @@ -28,7 +28,7 @@ const table: AppRouteModule = {
28 28 name: 'TreeTableDemo',
29 29 component: () => import('/@/views/demo/table/TreeTable.vue'),
30 30 meta: {
31   - title: '树形表格',
  31 + title: 'routes.demo.table.treeTable',
32 32 },
33 33 },
34 34 {
... ... @@ -36,7 +36,7 @@ const table: AppRouteModule = {
36 36 name: 'FetchTableDemo',
37 37 component: () => import('/@/views/demo/table/FetchTable.vue'),
38 38 meta: {
39   - title: '远程加载示例',
  39 + title: 'routes.demo.table.fetchTable',
40 40 },
41 41 },
42 42 {
... ... @@ -44,7 +44,7 @@ const table: AppRouteModule = {
44 44 name: 'FixedColumnDemo',
45 45 component: () => import('/@/views/demo/table/FixedColumn.vue'),
46 46 meta: {
47   - title: '固定列',
  47 + title: 'routes.demo.table.fixedColumn',
48 48 },
49 49 },
50 50 {
... ... @@ -52,7 +52,7 @@ const table: AppRouteModule = {
52 52 name: 'CustomerCellDemo',
53 53 component: () => import('/@/views/demo/table/CustomerCell.vue'),
54 54 meta: {
55   - title: '自定义列',
  55 + title: 'routes.demo.table.customerCell',
56 56 },
57 57 },
58 58 {
... ... @@ -60,7 +60,7 @@ const table: AppRouteModule = {
60 60 name: 'FormTableDemo',
61 61 component: () => import('/@/views/demo/table/FormTable.vue'),
62 62 meta: {
63   - title: '开启搜索区域',
  63 + title: 'routes.demo.table.formTable',
64 64 },
65 65 },
66 66 {
... ... @@ -68,7 +68,7 @@ const table: AppRouteModule = {
68 68 name: 'UseTableDemo',
69 69 component: () => import('/@/views/demo/table/UseTable.vue'),
70 70 meta: {
71   - title: 'UseTable',
  71 + title: 'routes.demo.table.useTable',
72 72 },
73 73 },
74 74 {
... ... @@ -76,7 +76,7 @@ const table: AppRouteModule = {
76 76 name: 'RefTableDemo',
77 77 component: () => import('/@/views/demo/table/RefTable.vue'),
78 78 meta: {
79   - title: 'RefTable',
  79 + title: 'routes.demo.table.refTable',
80 80 },
81 81 },
82 82 {
... ... @@ -84,7 +84,7 @@ const table: AppRouteModule = {
84 84 name: 'MultipleHeaderDemo',
85 85 component: () => import('/@/views/demo/table/MultipleHeader.vue'),
86 86 meta: {
87   - title: '多级表头',
  87 + title: 'routes.demo.table.multipleHeader',
88 88 },
89 89 },
90 90 {
... ... @@ -92,7 +92,7 @@ const table: AppRouteModule = {
92 92 name: 'MergeHeaderDemo',
93 93 component: () => import('/@/views/demo/table/MergeHeader.vue'),
94 94 meta: {
95   - title: '合并单元格',
  95 + title: 'routes.demo.table.mergeHeader',
96 96 },
97 97 },
98 98 {
... ... @@ -100,7 +100,7 @@ const table: AppRouteModule = {
100 100 name: 'ExpandTableDemo',
101 101 component: () => import('/@/views/demo/table/ExpandTable.vue'),
102 102 meta: {
103   - title: '可展开表格',
  103 + title: 'routes.demo.table.expandTable',
104 104 },
105 105 },
106 106 {
... ... @@ -108,7 +108,7 @@ const table: AppRouteModule = {
108 108 name: 'FixedHeightDemo',
109 109 component: () => import('/@/views/demo/table/FixedHeight.vue'),
110 110 meta: {
111   - title: '定高/头部自定义',
  111 + title: 'routes.demo.table.fixedHeight',
112 112 },
113 113 },
114 114 {
... ... @@ -116,7 +116,7 @@ const table: AppRouteModule = {
116 116 name: 'FooterTableDemo',
117 117 component: () => import('/@/views/demo/table/FooterTable.vue'),
118 118 meta: {
119   - title: '表尾行合计',
  119 + title: 'routes.demo.table.footerTable',
120 120 },
121 121 },
122 122 {
... ... @@ -124,7 +124,7 @@ const table: AppRouteModule = {
124 124 name: 'EditCellTableDemo',
125 125 component: () => import('/@/views/demo/table/EditCellTable.vue'),
126 126 meta: {
127   - title: '可编辑单元格',
  127 + title: 'routes.demo.table.editCellTable',
128 128 },
129 129 },
130 130 {
... ... @@ -132,7 +132,7 @@ const table: AppRouteModule = {
132 132 name: 'EditRowTableDemo',
133 133 component: () => import('/@/views/demo/table/EditRowTable.vue'),
134 134 meta: {
135   - title: '可编辑行',
  135 + title: 'routes.demo.table.editRowTable',
136 136 },
137 137 },
138 138 ],
... ...
src/router/routes/modules/demo/tree.ts
... ... @@ -10,7 +10,7 @@ const tree: AppRouteModule = {
10 10 redirect: '/tree/basic',
11 11 meta: {
12 12 icon: 'clarity:tree-view-line',
13   - title: 'Tree',
  13 + title: 'routes.demo.tree.tree',
14 14 },
15 15 },
16 16 routes: [
... ... @@ -19,7 +19,7 @@ const tree: AppRouteModule = {
19 19 name: 'BasicTreeDemo',
20 20 component: () => import('/@/views/demo/tree/index.vue'),
21 21 meta: {
22   - title: '基础树',
  22 + title: 'routes.demo.tree.basic',
23 23 },
24 24 },
25 25 {
... ... @@ -27,7 +27,7 @@ const tree: AppRouteModule = {
27 27 name: 'EditTreeDemo',
28 28 component: () => import('/@/views/demo/tree/EditTree.vue'),
29 29 meta: {
30   - title: '右键示例',
  30 + title: 'routes.demo.tree.editTree',
31 31 },
32 32 },
33 33 {
... ... @@ -35,7 +35,7 @@ const tree: AppRouteModule = {
35 35 name: 'ActionTreeDemo',
36 36 component: () => import('/@/views/demo/tree/ActionTree.vue'),
37 37 meta: {
38   - title: '函数操作示例',
  38 + title: 'routes.demo.tree.actionTree',
39 39 },
40 40 },
41 41 ],
... ...
src/setup/App.ts
... ... @@ -20,7 +20,7 @@ import {
20 20 } from '/@/setup/theme';
21 21  
22 22 import { appStore } from '/@/store/modules/app';
23   -import { deepMerge } from '../utils/index';
  23 +import { deepMerge } from '/@/utils';
24 24  
25 25 // Used to share global app instances
26 26 let app: App;
... ...
src/setup/i18n/index.ts
1   -import { App, unref } from 'vue';
  1 +import { App } from 'vue';
2 2 import type { I18n, I18nOptions } from 'vue-i18n';
3 3  
4 4 import { createI18n } from 'vue-i18n';
5 5 import localeMessages from '/@/locales';
6 6 import { useLocale } from '/@/hooks/web/useLocale';
7   -import { useLocaleSetting } from '/@/hooks/setting/useLocaleSetting';
8   -
  7 +import projectSetting from '/@/settings/projectSetting';
9 8 const { setupLocale } = useLocale();
10 9  
11   -const { getLang, getAvailableLocales, getFallbackLocale } = useLocaleSetting();
  10 +const { lang, availableLocales, fallback } = projectSetting?.locale;
12 11 const localeData: I18nOptions = {
13 12 legacy: false,
14   - locale: unref(getLang),
15   - fallbackLocale: unref(getFallbackLocale),
  13 + locale: lang,
  14 + fallbackLocale: fallback,
16 15 messages: localeMessages,
17   - availableLocales: unref(getAvailableLocales),
  16 + availableLocales: availableLocales,
18 17 sync: true, //If you don’t want to inherit locale from global scope, you need to set sync of i18n component option to false.
19 18 silentTranslationWarn: false, // true - warning off
20 19 silentFallbackWarn: true,
... ...
src/store/modules/permission.ts
... ... @@ -20,6 +20,9 @@ import { transformRouteToMenu } from &#39;/@/utils/helper/menuHelper&#39;;
20 20  
21 21 import { useMessage } from '/@/hooks/web/useMessage';
22 22 // import { warn } from '/@/utils/log';
  23 +import { useI18n } from '/@/hooks/web/useI18n';
  24 +
  25 +const { t } = useI18n('sys.app');
23 26  
24 27 const { createMessage } = useMessage();
25 28 const NAME = 'permission';
... ... @@ -101,7 +104,7 @@ class Permission extends VuexModule {
101 104 } else if (permissionMode === PermissionModeEnum.BACK) {
102 105 const messageKey = 'loadMenu';
103 106 createMessage.loading({
104   - content: '菜单加载中...',
  107 + content: t('menuLoading'),
105 108 key: messageKey,
106 109 duration: 1,
107 110 });
... ...
src/store/modules/user.ts
... ... @@ -21,6 +21,7 @@ import { loginApi, getUserInfoById } from &#39;/@/api/sys/user&#39;;
21 21  
22 22 import { setLocal, getLocal, getSession, setSession } from '/@/utils/helper/persistent';
23 23 import { useProjectSetting } from '/@/hooks/setting';
  24 +import { useI18n } from '/@/hooks/web/useI18n';
24 25  
25 26 export type UserInfo = Omit<GetUserInfoByUserIdModel, 'roles'>;
26 27  
... ... @@ -29,6 +30,8 @@ hotModuleUnregisterModule(NAME);
29 30  
30 31 const { permissionCacheType } = useProjectSetting();
31 32  
  33 +const { t } = useI18n('sys.app');
  34 +
32 35 function getCache<T>(key: string) {
33 36 const fn = permissionCacheType === CacheTypeEnum.LOCAL ? getLocal : getSession;
34 37 return fn(key) as T;
... ... @@ -144,8 +147,8 @@ class User extends VuexModule {
144 147 const { createConfirm } = useMessage();
145 148 createConfirm({
146 149 iconType: 'warning',
147   - title: '温馨提醒',
148   - content: '是否确认退出系统?',
  150 + title: t('loginOutTip'),
  151 + content: t('loginOutMessage'),
149 152 onOk: async () => {
150 153 await this.loginOut(true);
151 154 },
... ...
src/utils/http/axios/checkStatus.ts
1 1 import { useMessage } from '/@/hooks/web/useMessage';
2 2 import { userStore } from '/@/store/modules/user';
  3 +import { useI18n } from '/@/hooks/web/useI18n';
3 4 const { createMessage } = useMessage();
4 5  
  6 +const { t } = useI18n('sys.api');
  7 +
5 8 const error = createMessage.error!;
6 9 export function checkStatus(status: number, msg: string): void {
7 10 switch (status) {
... ... @@ -12,39 +15,39 @@ export function checkStatus(status: number, msg: string): void {
12 15 // 未登录则跳转登录页面,并携带当前页面的路径
13 16 // 在登录成功后返回当前页面,这一步需要在登录页操作。
14 17 case 401:
15   - error('用户没有权限(令牌、用户名、密码错误)!');
  18 + error(t('errMsg401'));
16 19 userStore.loginOut(true);
17 20 break;
18 21 case 403:
19   - error('用户得到授权,但是访问是被禁止的。!');
  22 + error(t('errMsg403'));
20 23 break;
21 24 // 404请求不存在
22 25 case 404:
23   - error('网络请求错误,未找到该资源!');
  26 + error(t('errMsg404'));
24 27 break;
25 28 case 405:
26   - error('网络请求错误,请求方法未允许!');
  29 + error(t('errMsg405'));
27 30 break;
28 31 case 408:
29   - error('网络请求超时!');
  32 + error(t('errMsg408'));
30 33 break;
31 34 case 500:
32   - error('服务器错误,请联系管理员!');
  35 + error(t('errMsg500'));
33 36 break;
34 37 case 501:
35   - error('网络未实现!');
  38 + error(t('errMsg501'));
36 39 break;
37 40 case 502:
38   - error('网络错误!');
  41 + error(t('errMsg502'));
39 42 break;
40 43 case 503:
41   - error('服务不可用,服务器暂时过载或维护!');
  44 + error(t('errMsg503'));
42 45 break;
43 46 case 504:
44   - error('网络超时!');
  47 + error(t('errMsg504'));
45 48 break;
46 49 case 505:
47   - error('http版本不支持该请求!');
  50 + error(t('errMsg505'));
48 51 break;
49 52 default:
50 53 }
... ...
src/utils/http/axios/index.ts
... ... @@ -20,7 +20,9 @@ import { formatRequestDate } from &#39;/@/utils/dateUtil&#39;;
20 20 import { setObjToUrlParams, deepMerge } from '/@/utils';
21 21 import { errorStore } from '/@/store/modules/error';
22 22 import { errorResult } from './const';
  23 +import { useI18n } from '/@/hooks/web/useI18n';
23 24  
  25 +const { t } = useI18n('sys.api');
24 26 const globSetting = useGlobSetting();
25 27 const prefix = globSetting.urlPrefix;
26 28 const { createMessage, createErrorModal } = useMessage();
... ... @@ -55,7 +57,7 @@ const transform: AxiosTransform = {
55 57 if (message) {
56 58 // errorMessageMode=‘modal’的时候会显示modal错误弹窗,而不是消息提示,用于一些比较重要的错误
57 59 if (options.errorMessageMode === 'modal') {
58   - createErrorModal({ title: '错误提示', content: message });
  60 + createErrorModal({ title: t('errorTip'), content: message });
59 61 } else {
60 62 createMessage.error(message);
61 63 }
... ... @@ -74,7 +76,7 @@ const transform: AxiosTransform = {
74 76 createMessage.error(data.message);
75 77 Promise.reject(new Error(message));
76 78 } else {
77   - const msg = '操作失败,系统异常!';
  79 + const msg = t('errorMessage');
78 80 createMessage.error(msg);
79 81 Promise.reject(new Error(msg));
80 82 }
... ... @@ -82,9 +84,9 @@ const transform: AxiosTransform = {
82 84 }
83 85 // 登录超时
84 86 if (code === ResultEnum.TIMEOUT) {
85   - const timeoutMsg = '登录超时,请重新登录!';
  87 + const timeoutMsg = t('timeoutMessage');
86 88 createErrorModal({
87   - title: '操作失败',
  89 + title: t('operationFailed'),
88 90 content: timeoutMsg,
89 91 });
90 92 Promise.reject(new Error(timeoutMsg));
... ... @@ -159,12 +161,12 @@ const transform: AxiosTransform = {
159 161 const err: string = error.toString();
160 162 try {
161 163 if (code === 'ECONNABORTED' && message.indexOf('timeout') !== -1) {
162   - createMessage.error('接口请求超时,请刷新页面重试!');
  164 + createMessage.error(t('apiTimeoutMessage'));
163 165 }
164 166 if (err && err.includes('Network Error')) {
165 167 createErrorModal({
166   - title: '网络异常',
167   - content: '请检查您的网络连接是否正常!',
  168 + title: t('networkException'),
  169 + content: t('networkExceptionMsg'),
168 170 });
169 171 }
170 172 } catch (error) {
... ...
src/views/sys/login/Login.vue
... ... @@ -3,8 +3,8 @@
3 3 <div class="login-mask" />
4 4 <div class="login-form-wrap">
5 5 <div class="login-form mx-6">
  6 + <AppLocalePicker v-if="showLocale" class="login-form__locale" />
6 7 <div class="login-form__content px-2 py-10">
7   - <AppLocalePicker v-if="showLocale" class="login-form__locale" />
8 8 <header>
9 9 <img :src="logo" class="mr-4" />
10 10 <h1>{{ title }}</h1>
... ... @@ -158,9 +158,16 @@
158 158 },
159 159 });
160 160 </script>
161   -<style lang="less" scoped>
  161 +<style lang="less">
162 162 @import (reference) '../../../design/index.less';
163 163  
  164 + .login-form__locale {
  165 + position: absolute;
  166 + top: 14px;
  167 + right: 14px;
  168 + z-index: 1;
  169 + }
  170 +
164 171 .login {
165 172 position: relative;
166 173 height: 100vh;
... ... @@ -178,7 +185,9 @@
178 185 }
179 186  
180 187 &-form {
181   - width: 520px;
  188 + position: relative;
  189 + bottom: 60px;
  190 + width: 400px;
182 191 background: @white;
183 192 border: 10px solid rgba(255, 255, 255, 0.5);
184 193 border-width: 8px;
... ... @@ -192,26 +201,20 @@
192 201 right: 0;
193 202 display: flex;
194 203 width: 100%;
195   - height: 90%;
  204 + height: 100%;
  205 + // height: 90%;
196 206 justify-content: center;
197 207 align-items: center;
198   - .respond-to(large, {
199   - width: 600px;
200   - right: calc(50% - 270px);
  208 + .respond-to(xlarge, {
  209 + justify-content: flex-end;
201 210 });
202   - .respond-to(xlarge, { width: 540px; right:0});
203   - }
204   -
205   - &__locale {
206   - position: absolute;
207   - top: 10px;
208   - right: 10px;
209 211 }
210 212  
211 213 &__content {
212 214 position: relative;
213 215 width: 100%;
214 216 height: 100%;
  217 + padding: 60px 0 40px 0;
215 218 border: 1px solid #999;
216 219 border-radius: 2px;
217 220  
... ... @@ -228,7 +231,6 @@
228 231 h1 {
229 232 margin-bottom: 0;
230 233 font-size: 24px;
231   - // color: @primary-color;
232 234 text-align: center;
233 235 }
234 236 }
... ...