feat: multi-language support

This commit is contained in:
vben 2020-11-26 21:10:21 +08:00
parent 4f8ad976cc
commit 19011296ed
76 changed files with 764 additions and 307 deletions

View File

@ -2,7 +2,7 @@
### ✨ Refactor ### ✨ Refactor
- 重构整体 layout。更改代码实现方式。代码更精简,并加入多语言支持 - 重构整体 layout。更改代码实现方式。代码更精简
- 配置项重构 - 配置项重构
- 移除 messageSetting 配置 - 移除 messageSetting 配置
@ -10,6 +10,7 @@
- 缓存可以配置是否加密,默认生产环境开启 Aes 加密 - 缓存可以配置是否加密,默认生产环境开启 Aes 加密
- 新增标签页拖拽排序 - 新增标签页拖拽排序
- 除示例外加入全局国际化功能,支持中文与英文
### 🎫 Chores ### 🎫 Chores

View File

@ -61,13 +61,20 @@ function varTemplate(data: string[][], name: string) {
// lastKey is a data // lastKey is a data
let pathValue = v[0].replace(/\//g, '.').split('.'); let pathValue = v[0].replace(/\//g, '.').split('.');
// let scopeKey = '';
// const len=pathValue.length
// const scope=pathValue[len-2]
let lastKey: string | undefined = pathValue.pop(); let lastKey: string | undefined = pathValue.pop();
let deepValue: Record<any, any> = {}; let deepValue: Record<any, any> = {};
if (lastKey) { if (lastKey) {
deepValue[lastKey.replace('_' + pathValue[0], '')] = lastKey; // Solve the problem of files with the same name in different folders
const lastKeyList = lastKey.replace('_' + pathValue[0], '').split('_');
const key = lastKeyList.pop();
if (key) {
deepValue[key] = lastKey;
}
} }
// Set Deep Value // Set Deep Value
deepValue = Object.assign(deepValue, dotProp.get(deepData, pathValue.join('.'))); deepValue = Object.assign(deepValue, dotProp.get(deepData, pathValue.join('.')));
dotProp.set(deepData, pathValue.join('.'), deepValue); dotProp.set(deepData, pathValue.join('.'), deepValue);
@ -169,7 +176,15 @@ const globTransform = function (config: SharedConfig): Transform {
if (matchedGroups && matchedGroups.length) { if (matchedGroups && matchedGroups.length) {
const matchedSegments = matchedGroups[1]; //first everytime "Full Match" const matchedSegments = matchedGroups[1]; //first everytime "Full Match"
const name = matchedGroups[2] + '_' + matchedSegments.split('/').shift(); const matchList = matchedSegments.split('/').filter(Boolean);
const lang = matchList.shift();
const scope = matchList.pop();
// Solve the problem of files with the same name in different folders
const scopeKey = scope ? `${scope}_` : '';
const fileName = matchedGroups[2];
const name = scopeKey + fileName + '_' + lang;
//send deep way like an (en/modules/system/dashboard) into groups //send deep way like an (en/modules/system/dashboard) into groups
groups.push([matchedSegments + name, file]); groups.push([matchedSegments + name, file]);
return templateRender({ return templateRender({
@ -186,6 +201,10 @@ const globTransform = function (config: SharedConfig): Transform {
const filesJoined = replaceFiles.join('\n'); const filesJoined = replaceFiles.join('\n');
urlMap.set(path, filesJoined); urlMap.set(path, filesJoined);
// console.log('======================');
// console.log(filesJoined, varTemplate(groups, name));
// console.log('======================');
return [ return [
filesJoined, filesJoined,
compareString(injectPath, groups), compareString(injectPath, groups),

View File

@ -3,7 +3,17 @@ import './index.less';
import type { MenuState } from './types'; import type { MenuState } from './types';
import type { Menu as MenuType } from '/@/router/types'; import type { Menu as MenuType } from '/@/router/types';
import { computed, defineComponent, unref, reactive, watch, onMounted, ref, toRefs } from 'vue'; import {
computed,
defineComponent,
unref,
reactive,
watch,
onMounted,
ref,
toRefs,
ComputedRef,
} from 'vue';
import { Menu } from 'ant-design-vue'; import { Menu } from 'ant-design-vue';
import SearchInput from './SearchInput.vue'; import SearchInput from './SearchInput.vue';
import MenuContent from './MenuContent'; import MenuContent from './MenuContent';
@ -34,7 +44,7 @@ export default defineComponent({
const menuState = reactive<MenuState>({ const menuState = reactive<MenuState>({
defaultSelectedKeys: [], defaultSelectedKeys: [],
mode: props.mode, mode: props.mode,
theme: computed(() => props.theme), theme: computed(() => props.theme) as ComputedRef<ThemeEnum>,
openKeys: [], openKeys: [],
searchValue: '', searchValue: '',
selectedKeys: [], selectedKeys: [],

View File

@ -1,8 +1,7 @@
import { getI18n } from '/@/setup/i18n'; import { getI18n } from '/@/setup/i18n';
import projectSetting from '/@/settings/projectSetting';
export function useI18n(namespace?: string) { export function useI18n(namespace?: string) {
const { t, ...methods } = getI18n().global;
function getKey(key: string) { function getKey(key: string) {
if (!namespace) { if (!namespace) {
return key; return key;
@ -12,6 +11,18 @@ export function useI18n(namespace?: string) {
} }
return `${namespace}.${key}`; return `${namespace}.${key}`;
} }
const normalFn = {
t: (key: string) => {
return getKey(key);
},
};
if (!projectSetting.locale.show || !getI18n()) {
return normalFn;
}
const { t, ...methods } = getI18n().global;
return { return {
...methods, ...methods,
t: (key: string, ...arg: Parameters<typeof t>) => { t: (key: string, ...arg: Parameters<typeof t>) => {

18
src/hooks/web/useTitle.ts Normal file
View File

@ -0,0 +1,18 @@
import { watch } from 'vue';
import { useRouter } from 'vue-router';
import { useGlobSetting } from '../setting';
import { useI18n } from './useI18n';
import { setTitle } from '/@/utils/browser';
export function useTitle() {
const { currentRoute } = useRouter();
const { t } = useI18n();
watch(
() => currentRoute.value.path,
() => {
const globSetting = useGlobSetting();
setTitle(t(currentRoute.value.meta.title), globSetting.title);
},
{ immediate: true, flush: 'post' }
);
}

View File

@ -15,6 +15,7 @@ import { compile } from 'path-to-regexp';
import router from '/@/router'; import router from '/@/router';
import { PageEnum } from '/@/enums/pageEnum'; import { PageEnum } from '/@/enums/pageEnum';
import { useI18n } from '/@/hooks/web/useI18n';
export default defineComponent({ export default defineComponent({
name: 'BasicBreadcrumb', name: 'BasicBreadcrumb',
@ -28,7 +29,7 @@ export default defineComponent({
const itemList = ref<AppRouteRecordRaw[]>([]); const itemList = ref<AppRouteRecordRaw[]>([]);
const { currentRoute, push } = useRouter(); const { currentRoute, push } = useRouter();
const { t } = useI18n();
watch( watch(
() => currentRoute.value, () => currentRoute.value,
() => { () => {
@ -88,7 +89,7 @@ export default defineComponent({
}} }}
/> />
)} )}
{item.meta.title} {t(item.meta.title)}
</> </>
); );
} }

View File

@ -17,7 +17,10 @@ import {
getShallowMenus, getShallowMenus,
} from '/@/router/menus'; } from '/@/router/menus';
import { permissionStore } from '/@/store/modules/permission'; import { permissionStore } from '/@/store/modules/permission';
import { useI18n } from '/@/hooks/web/useI18n';
import { cloneDeep } from 'lodash-es';
const { t } = useI18n();
export function useSplitMenu(splitType: Ref<MenuSplitTyeEnum>) { export function useSplitMenu(splitType: Ref<MenuSplitTyeEnum>) {
// Menu array // Menu array
const menusRef = ref<Menu[]>([]); const menusRef = ref<Menu[]>([]);
@ -42,6 +45,14 @@ export function useSplitMenu(splitType: Ref<MenuSplitTyeEnum>) {
return unref(splitType) === MenuSplitTyeEnum.NONE || !unref(getSplit); return unref(splitType) === MenuSplitTyeEnum.NONE || !unref(getSplit);
}); });
const getI18nFlatMenus = computed(() => {
return setI18nName(flatMenusRef.value, true, false);
});
const getI18nMenus = computed(() => {
return setI18nName(menusRef.value, true, true);
});
watch( watch(
[() => unref(currentRoute).path, () => unref(splitType)], [() => unref(currentRoute).path, () => unref(splitType)],
async ([path]: [string, MenuSplitTyeEnum]) => { async ([path]: [string, MenuSplitTyeEnum]) => {
@ -72,6 +83,18 @@ export function useSplitMenu(splitType: Ref<MenuSplitTyeEnum>) {
genMenus(); genMenus();
}); });
function setI18nName(list: Menu[], clone = false, deep = true) {
const menus = clone ? cloneDeep(list) : list;
menus.forEach((item) => {
if (!item.name.includes('.')) return;
item.name = t(item.name);
if (item.children && deep) {
setI18nName(item.children, false, deep);
}
});
return menus;
}
// Handle left menu split // Handle left menu split
async function handleSplitLeftMenu(parentPath: string) { async function handleSplitLeftMenu(parentPath: string) {
if (unref(splitLeft)) return; if (unref(splitLeft)) return;
@ -109,5 +132,6 @@ export function useSplitMenu(splitType: Ref<MenuSplitTyeEnum>) {
return; return;
} }
} }
return { flatMenusRef, menusRef };
return { flatMenusRef: getI18nFlatMenus, menusRef: getI18nMenus };
} }

View File

@ -15,6 +15,8 @@ import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting'; import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting';
import { useI18n } from '/@/hooks/web/useI18n'; import { useI18n } from '/@/hooks/web/useI18n';
const { t: titleT } = useI18n();
const ExtraContent: FunctionalComponent = () => { const ExtraContent: FunctionalComponent = () => {
return ( return (
<span class={`multiple-tabs-content__extra `}> <span class={`multiple-tabs-content__extra `}>
@ -38,7 +40,7 @@ const TabContent: FunctionalComponent<{ tabItem: TabItem }> = (props) => {
return ( return (
<div class={`multiple-tabs-content__content `} onContextmenu={handleContextMenu}> <div class={`multiple-tabs-content__content `} onContextmenu={handleContextMenu}>
<span class="ml-1">{meta && meta.title}</span> <span class="ml-1">{meta && titleT(meta.title)}</span>
</div> </div>
); );
}; };

View File

@ -0,0 +1 @@
Share with menu

View File

@ -0,0 +1,3 @@
export default {
login: 'Login',
};

View File

@ -0,0 +1,6 @@
export default {
dashboard: 'Dashboard',
welcome: 'Home',
workbench: 'Workbench',
analysis: 'Analysis',
};

View File

@ -0,0 +1,7 @@
export default {
charts: 'Chart',
map: 'Map',
line: 'Line',
pie: 'Pie',
apexChart: 'ApexChart',
};

View File

@ -0,0 +1,27 @@
export default {
comp: 'Component',
basic: 'Basic',
transition: 'Animation',
countTo: 'Count To',
scroll: 'Scroll',
scrollBasic: 'Basic',
scrollAction: 'Scroll Function',
virtualScroll: 'Virtual Scroll',
modal: 'Modal',
drawer: 'Drawer',
desc: 'Desc',
lazy: 'Lazy',
lazyBasic: 'Basic',
lazyTransition: 'Animation',
verify: 'Verify',
verifyDrag: 'Drag ',
verifyRotate: 'Picture Restore',
qrcode: 'QR code',
strength: 'Password strength',
upload: 'Upload',
};

View File

@ -0,0 +1,8 @@
export default {
editor: 'Editor',
markdown: 'Markdown editor',
tinymce: 'Rich text',
tinymceBasic: 'Basic',
tinymceForm: 'embedded form',
};

View File

@ -0,0 +1,7 @@
export default {
excel: 'Excel',
customExport: 'Select export format',
jsonExport: 'JSON data export',
arrayExport: 'Array data export',
importExcel: 'Import',
};

View File

@ -0,0 +1,17 @@
export default {
feat: 'Page Function',
icon: 'Icon',
tabs: 'Tabs',
contextMenu: 'Context Menu',
download: 'Download',
clickOutSide: 'ClickOutSide',
imgPreview: 'Picture Preview',
copy: 'Clipboard',
msg: 'Message prompt',
watermark: 'Watermark',
fullScreen: 'Full Screen',
errorLog: 'Error Log',
tab: 'Tab with parameters',
tab1: 'Tab with parameter 1',
tab2: 'Tab with parameter 2',
};

View File

@ -0,0 +1,10 @@
export default {
form: 'Form',
basic: 'Basic',
useForm: 'useForm',
refForm: 'RefForm',
advancedForm: 'Shrinkable',
ruleForm: 'Form validation',
dynamicForm: 'Dynamic',
customerForm: 'Custom',
};

View File

@ -0,0 +1,6 @@
export default {
frame: 'External',
antv: 'antVue doc (embedded)',
doc: 'Project doc (embedded)',
docExternal: 'Project doc (external)',
};

View File

@ -0,0 +1,27 @@
export default {
page: 'Page',
form: 'Form',
formBasic: 'Basic Form',
formStep: 'Step Form',
formHigh: 'Advanced Form',
desc: 'Details',
descBasic: 'Basic Details',
descHigh: 'Advanced Details',
result: 'Result',
resultSuccess: 'Success',
resultFail: 'Failed',
account: 'Personal',
accountCenter: 'Personal Center',
accountSetting: 'Personal Settings',
exception: 'Exception',
netWorkError: 'Network Error',
notData: 'No data',
list: 'List page',
listCard: 'Card list',
};

View File

@ -0,0 +1,13 @@
export default {
permission: 'Permission',
front: 'front-end',
frontPage: 'Page',
frontBtn: 'Button',
frontTestA: 'Test page A',
frontTestB: 'Test page B',
back: 'background',
backPage: 'Page',
backBtn: 'Button',
};

View File

@ -0,0 +1,19 @@
export default {
table: 'Table',
basic: 'Basic',
treeTable: 'Tree',
fetchTable: 'Remote loading',
fixedColumn: 'Fixed column',
customerCell: 'Custom column',
formTable: 'Open search',
useTable: 'UseTable',
refTable: 'RefTable',
multipleHeader: 'MultiLevel header',
mergeHeader: 'Merge cells',
expandTable: 'Expandable table',
fixedHeight: 'Fixed height',
footerTable: 'Footer',
editCellTable: 'Editable cell',
editRowTable: 'Editable row',
};

View File

@ -0,0 +1,7 @@
export default {
tree: 'Tree',
basic: 'Basic',
editTree: 'Right-click',
actionTree: 'Function operation',
};

View File

@ -1,3 +0,0 @@
export default {
someentry: 'some text',
};

View File

@ -0,0 +1,21 @@
export default {
operationFailed: 'Operation failed',
errorTip: 'Error Tip',
errorMessage: 'The operation failed, the system is abnormal!',
timeoutMessage: 'Login timed out, please log in again!',
apiTimeoutMessage: 'The interface request timed out, please refresh the page and try again!',
networkException: 'network anomaly',
networkExceptionMsg: 'Please check if your network connection is normal! The network is abnormal',
errMsg401: 'The user does not have permission (token, user name, password error)!',
errMsg403: 'The user is authorized, but access is forbidden!',
errMsg404: 'Network request error, the resource was not found!',
errMsg405: 'Network request error, request method not allowed!',
errMsg408: 'Network request timed out!',
errMsg500: 'Server error, please contact the administrator!',
errMsg501: 'The network is not implemented!',
errMsg502: 'Network Error!',
errMsg503: 'The service is unavailable, the server is temporarily overloaded or maintained!',
errMsg504: 'Network timeout!',
errMsg505: 'The http version does not support the request!',
};

View File

@ -0,0 +1,5 @@
export default {
loginOutTip: 'Reminder',
loginOutMessage: 'Confirm to exit the system?',
menuLoading: 'Menu loading...',
};

View File

@ -1,5 +1,4 @@
export default { export default {
loadingText: '加载中...',
cancelText: '关闭', cancelText: '关闭',
okText: '确认', okText: '确认',
}; };

View File

@ -0,0 +1 @@
Share with menu

View File

@ -0,0 +1,3 @@
export default {
login: '登录',
};

View File

@ -0,0 +1,6 @@
export default {
dashboard: 'Dashboard',
welcome: '首页',
workbench: '工作台',
analysis: '分析页',
};

View File

@ -0,0 +1,7 @@
export default {
charts: '图表库',
map: '地图',
line: '折线图',
pie: '饼图',
apexChart: 'ApexChart',
};

View File

@ -0,0 +1,27 @@
export default {
comp: '组件',
basic: '基础组件',
transition: '动画组件',
countTo: '数字动画',
scroll: '滚动组件',
scrollBasic: '基础滚动',
scrollAction: '滚动函数',
virtualScroll: '虚拟滚动',
modal: '弹窗扩展',
drawer: '抽屉扩展',
desc: '详情组件',
lazy: '懒加载组件',
lazyBasic: '基础示例',
lazyTransition: '动画效果',
verify: '验证组件',
verifyDrag: '拖拽校验',
verifyRotate: '图片还原',
qrcode: '二维码组件',
strength: '密码强度组件',
upload: '上传组件',
};

View File

@ -0,0 +1,8 @@
export default {
editor: '编辑器',
markdown: 'markdown编辑器',
tinymce: '富文本',
tinymceBasic: '基础使用',
tinymceForm: '嵌入form',
};

View File

@ -0,0 +1,7 @@
export default {
excel: 'Excel',
customExport: '选择导出格式',
jsonExport: 'JSON数据导出',
arrayExport: 'Array数据导出',
importExcel: '导入',
};

View File

@ -0,0 +1,17 @@
export default {
feat: '页面功能',
icon: '图标',
tabs: '标签页操作',
contextMenu: '右键菜单',
download: '文件下载',
clickOutSide: 'ClickOutSide组件',
imgPreview: '图片预览',
copy: '剪切板',
msg: '消息提示',
watermark: '水印',
fullScreen: '全屏',
errorLog: '错误日志',
tab: 'Tab带参',
tab1: 'Tab带参1',
tab2: 'Tab带参2',
};

View File

@ -0,0 +1,10 @@
export default {
form: 'Form',
basic: '基础表单',
useForm: 'useForm',
refForm: 'RefForm',
advancedForm: '可收缩表单',
ruleForm: '表单验证',
dynamicForm: '动态表单',
customerForm: '自定义组件',
};

View File

@ -0,0 +1,6 @@
export default {
frame: '外部页面',
antv: 'antVue文档(内嵌)',
doc: '项目文档(内嵌)',
docExternal: '项目文档(外链)',
};

View File

@ -0,0 +1,27 @@
export default {
page: '页面',
form: '表单页',
formBasic: '基础表单',
formStep: '分步表单',
formHigh: '高级表单',
desc: '详情页',
descBasic: '基础详情页',
descHigh: '高级详情页',
result: '结果页',
resultSuccess: '成功页',
resultFail: '失败页',
account: '个人页',
accountCenter: '个人中心',
accountSetting: '个人设置',
exception: '异常页',
netWorkError: '网络错误',
notData: '无数据',
list: '列表页',
listCard: '卡片列表',
};

View File

@ -0,0 +1,13 @@
export default {
permission: '权限管理',
front: '基于前端权限',
frontPage: '页面权限',
frontBtn: '按钮权限',
frontTestA: '权限测试页A',
frontTestB: '权限测试页B',
back: '基于后台权限',
backPage: '页面权限',
backBtn: '按钮权限',
};

View File

@ -0,0 +1,19 @@
export default {
table: 'Table',
basic: '基础表格',
treeTable: '树形表格',
fetchTable: '远程加载示例',
fixedColumn: '固定列',
customerCell: '自定义列',
formTable: '开启搜索区域',
useTable: 'UseTable',
refTable: 'RefTable',
multipleHeader: '多级表头',
mergeHeader: '合并单元格',
expandTable: '可展开表格',
fixedHeight: '定高/头部自定义',
footerTable: '表尾行合计',
editCellTable: '可编辑单元格',
editRowTable: '可编辑行',
};

View File

@ -0,0 +1,7 @@
export default {
tree: 'Tree',
basic: '基础树',
editTree: '右键示例',
actionTree: '函数操作示例',
};

View File

@ -1,3 +0,0 @@
export default {
someentry: '一些文本',
};

View File

@ -0,0 +1,21 @@
export default {
operationFailed: '操作失败',
errorTip: '错误提示',
errorMessage: '操作失败,系统异常!',
timeoutMessage: '登录超时,请重新登录!',
apiTimeoutMessage: '接口请求超时,请刷新页面重试!',
networkException: '网络异常',
networkExceptionMsg: '网请检查您的网络连接是否正常!络异常',
errMsg401: '用户没有权限(令牌、用户名、密码错误)!',
errMsg403: '用户得到授权,但是访问是被禁止的。!',
errMsg404: '网络请求错误,未找到该资源!',
errMsg405: '网络请求错误,请求方法未允许!',
errMsg408: '网络请求超时!',
errMsg500: '服务器错误,请联系管理员!',
errMsg501: '网络未实现!',
errMsg502: '网络错误!',
errMsg503: '服务不可用,服务器暂时过载或维护!',
errMsg504: '网络超时!',
errMsg505: 'http版本不支持该请求!',
};

View File

@ -0,0 +1,5 @@
export default {
loginOutTip: '温馨提醒',
loginOutMessage: '是否确认退出系统?',
menuLoading: '菜单加载中...',
};

View File

@ -13,6 +13,7 @@ import { setTitle } from '/@/utils/browser';
import { AxiosCanceler } from '/@/utils/http/axios/axiosCancel'; import { AxiosCanceler } from '/@/utils/http/axios/axiosCancel';
import { tabStore } from '/@/store/modules/tab'; import { tabStore } from '/@/store/modules/tab';
import { useI18n } from '/@/hooks/web/useI18n';
const { closeMessageOnSwitch, removeAllHttpPending } = useProjectSetting(); const { closeMessageOnSwitch, removeAllHttpPending } = useProjectSetting();
const globSetting = useGlobSetting(); const globSetting = useGlobSetting();
@ -54,8 +55,9 @@ export function createGuard(router: Router) {
}); });
router.afterEach((to) => { router.afterEach((to) => {
const { t } = useI18n();
// change html title // change html title
setTitle(to.meta.title, globSetting.title); setTitle(t(to.meta.title), globSetting.title);
}); });
createProgressGuard(router); createProgressGuard(router);
createPermissionGuard(router); createPermissionGuard(router);

View File

@ -1,27 +1,22 @@
import type { MenuModule } from '/@/router/types.d'; import type { MenuModule } from '/@/router/types.d';
const menu: MenuModule = { const menu: MenuModule = {
orderNo: 10, orderNo: 10,
menu: { menu: {
name: 'Dashboard', name: 'routes.dashboard.dashboard',
path: '/dashboard', path: '/dashboard',
// tag: {
// dot: true,
// },
children: [ children: [
{ {
path: '/workbench', path: '/workbench',
name: '工作台', name: 'routes.dashboard.workbench',
// tag: {
// content: 'new',
// },
}, },
{ {
path: '/analysis', path: '/analysis',
name: '分析页', name: 'routes.dashboard.analysis',
}, },
{ {
path: '/welcome', path: '/welcome',
name: '首页', name: 'routes.dashboard.welcome',
}, },
], ],
}, },

View File

@ -1,13 +1,14 @@
import type { MenuModule } from '/@/router/types.d'; import type { MenuModule } from '/@/router/types.d';
const menu: MenuModule = { const menu: MenuModule = {
orderNo: 500, orderNo: 500,
menu: { menu: {
name: '图表', name: 'routes.demo.charts.charts',
path: '/charts', path: '/charts',
children: [ children: [
{ {
path: 'apexChart', path: 'apexChart',
name: 'ApexChart', name: 'routes.demo.charts.apexChart',
}, },
{ {
path: 'echarts', path: 'echarts',
@ -15,15 +16,15 @@ const menu: MenuModule = {
children: [ children: [
{ {
path: 'map', path: 'map',
name: '地图', name: 'routes.demo.charts.map',
}, },
{ {
path: 'line', path: 'line',
name: '折线图', name: 'routes.demo.charts.line',
}, },
{ {
path: 'pie', path: 'pie',
name: '饼图', name: 'routes.demo.charts.pie',
}, },
], ],
}, },

View File

@ -1,101 +1,92 @@
import type { MenuModule } from '/@/router/types.d'; import type { MenuModule } from '/@/router/types.d';
const menu: MenuModule = { const menu: MenuModule = {
orderNo: 30, orderNo: 30,
menu: { menu: {
name: '组件', name: 'routes.demo.comp.comp',
path: '/comp', path: '/comp',
children: [ children: [
{ {
path: 'basic', path: 'basic',
name: '基础组件', name: 'routes.demo.comp.basic',
}, },
{ {
path: 'countTo', path: 'countTo',
name: '数字动画', name: 'routes.demo.comp.countTo',
}, },
{ {
path: 'transition', path: 'transition',
name: '动画组件', name: 'routes.demo.comp.transition',
}, },
{ {
path: 'modal', path: 'modal',
name: '弹窗扩展', name: 'routes.demo.comp.modal',
}, },
{ {
path: 'drawer', path: 'drawer',
name: '抽屉扩展', name: 'routes.demo.comp.drawer',
}, },
{ {
path: 'desc', path: 'desc',
name: '详情组件', name: 'routes.demo.comp.desc',
}, },
{ {
path: 'qrcode', path: 'qrcode',
name: '二维码组件', name: 'routes.demo.comp.qrcode',
}, },
{ {
path: 'strength-meter', path: 'strength-meter',
name: '密码强度组件', name: 'routes.demo.comp.strength',
}, },
{ {
path: 'upload', path: 'upload',
name: '上传组件', name: 'routes.demo.comp.upload',
}, },
{ {
path: 'scroll', path: 'scroll',
name: '滚动组件', name: 'routes.demo.comp.scroll',
children: [ children: [
{ {
path: 'basic', path: 'basic',
name: '基础示例', name: 'routes.demo.comp.scrollBasic',
}, },
{ {
path: 'action', path: 'action',
name: '函数操作示例', name: 'routes.demo.comp.scrollAction',
}, },
{ {
path: 'virtualScroll', path: 'virtualScroll',
name: '虚拟滚动', name: 'routes.demo.comp.virtualScroll',
}, },
], ],
}, },
{ {
path: 'lazy', path: 'lazy',
name: '懒加载组件', name: 'routes.demo.comp.lazy',
children: [ children: [
{ {
path: 'basic', path: 'basic',
name: '基础示例', name: 'routes.demo.comp.lazyBasic',
}, },
{ {
path: 'transition', path: 'transition',
name: '动画效果', name: 'routes.demo.comp.lazyTransition',
}, },
], ],
}, },
{ {
path: 'verify', path: 'verify',
name: '验证组件', name: 'routes.demo.comp.verify',
children: [ children: [
{ {
path: 'drag', path: 'drag',
name: '拖拽校验', name: 'routes.demo.comp.verifyDrag',
}, },
{ {
path: 'rotate', path: 'rotate',
name: '图片还原校验', name: 'routes.demo.comp.verifyRotate',
},
],
},
{
path: '/form',
name: '验证组件',
children: [
{
path: '/base',
name: '拖拽校验',
}, },
], ],
}, },

View File

@ -1,25 +1,26 @@
import type { MenuModule } from '/@/router/types.d'; import type { MenuModule } from '/@/router/types.d';
const menu: MenuModule = { const menu: MenuModule = {
orderNo: 500, orderNo: 500,
menu: { menu: {
name: '编辑器', name: 'routes.demo.editor.editor',
path: '/editor', path: '/editor',
children: [ children: [
{ {
path: 'markdown', path: 'markdown',
name: 'markdown编辑器', name: 'routes.demo.editor.markdown',
}, },
{ {
path: 'tinymce', path: 'tinymce',
name: '富文本', name: 'routes.demo.editor.tinymce',
children: [ children: [
{ {
path: 'index', path: 'index',
name: '基础使用', name: 'routes.demo.editor.tinymceBasic',
}, },
{ {
path: 'editor', path: 'editor',
name: '嵌入form使用', name: 'routes.demo.editor.tinymceForm',
}, },
], ],
}, },

View File

@ -1,25 +1,26 @@
import type { MenuModule } from '/@/router/types.d'; import type { MenuModule } from '/@/router/types.d';
const menu: MenuModule = { const menu: MenuModule = {
orderNo: 500, orderNo: 500,
menu: { menu: {
name: 'Excel', name: 'routes.demo.excel.excel',
path: '/excel', path: '/excel',
children: [ children: [
{ {
path: 'customExport', path: 'customExport',
name: '选择导出格式', name: 'routes.demo.excel.customExport',
}, },
{ {
path: 'jsonExport', path: 'jsonExport',
name: 'JSON数据导出', name: 'routes.demo.excel.jsonExport',
}, },
{ {
path: 'arrayExport', path: 'arrayExport',
name: 'Array数据导出', name: 'routes.demo.excel.arrayExport',
}, },
{ {
path: 'importExcel', path: 'importExcel',
name: '导入', name: 'routes.demo.excel.importExcel',
}, },
], ],
}, },

View File

@ -1,66 +1,67 @@
import type { MenuModule } from '/@/router/types.d'; import type { MenuModule } from '/@/router/types.d';
const menu: MenuModule = { const menu: MenuModule = {
orderNo: 19, orderNo: 19,
menu: { menu: {
name: '功能', name: 'routes.demo.feat.feat',
path: '/feat', path: '/feat',
children: [ children: [
{ {
path: 'icon', path: 'icon',
name: '图标', name: 'routes.demo.feat.icon',
}, },
{ {
path: 'tabs', path: 'tabs',
name: '标签页操作', name: 'routes.demo.feat.tabs',
}, },
{ {
path: 'context-menu', path: 'context-menu',
name: '右键菜单', name: 'routes.demo.feat.contextMenu',
}, },
{ {
path: 'download', path: 'download',
name: '文件下载', name: 'routes.demo.feat.download',
}, },
{ {
path: 'click-out-side', path: 'click-out-side',
name: 'ClickOutSide', name: 'routes.demo.feat.clickOutSide',
}, },
{ {
path: 'img-preview', path: 'img-preview',
name: '图片预览', name: 'routes.demo.feat.imgPreview',
}, },
{ {
path: 'copy', path: 'copy',
name: '剪切板', name: 'routes.demo.feat.copy',
}, },
{ {
path: 'msg', path: 'msg',
name: '消息提示', name: 'routes.demo.feat.msg',
}, },
{ {
path: 'watermark', path: 'watermark',
name: '水印', name: 'routes.demo.feat.watermark',
}, },
{ {
path: 'full-screen', path: 'full-screen',
name: '全屏', name: 'routes.demo.feat.fullScreen',
}, },
{ {
path: 'error-log', path: 'error-log',
name: '错误日志', name: 'routes.demo.feat.errorLog',
}, },
{ {
path: 'testTab', path: 'testTab',
name: '带参Tab', name: 'routes.demo.feat.tab',
children: [ children: [
{ {
path: 'id1', path: 'id1',
name: '带参tab1', name: 'routes.demo.feat.tab1',
}, },
{ {
path: 'id2', path: 'id2',
name: '带参tab2', name: 'routes.demo.feat.tab2',
}, },
], ],
}, },

View File

@ -1,38 +1,39 @@
import type { MenuModule } from '/@/router/types.d'; import type { MenuModule } from '/@/router/types.d';
const menu: MenuModule = { const menu: MenuModule = {
orderNo: 40, orderNo: 40,
menu: { menu: {
path: '/form', path: '/form',
name: 'Form', name: 'routes.demo.form.form',
children: [ children: [
{ {
path: 'basic', path: 'basic',
name: '基础表单', name: 'routes.demo.form.basic',
}, },
{ {
path: 'useForm', path: 'useForm',
name: 'useForm', name: 'routes.demo.form.useForm',
}, },
{ {
path: 'refForm', path: 'refForm',
name: 'RefForm', name: 'routes.demo.form.refForm',
}, },
{ {
path: 'advancedForm', path: 'advancedForm',
name: '可收缩表单', name: 'routes.demo.form.advancedForm',
}, },
{ {
path: 'ruleForm', path: 'ruleForm',
name: '表单校验', name: 'routes.demo.form.ruleForm',
}, },
{ {
path: 'dynamicForm', path: 'dynamicForm',
name: '动态表单', name: 'routes.demo.form.dynamicForm',
}, },
{ {
path: 'customerForm', path: 'customerForm',
name: '自定义组件', name: 'routes.demo.form.customerForm',
}, },
], ],
}, },

View File

@ -1,21 +1,22 @@
import type { MenuModule } from '/@/router/types.d'; import type { MenuModule } from '/@/router/types.d';
const menu: MenuModule = { const menu: MenuModule = {
orderNo: 1000, orderNo: 1000,
menu: { menu: {
name: '外部页面', name: 'routes.demo.iframe.frame',
path: '/frame', path: '/frame',
children: [ children: [
{ {
path: 'antv', path: 'antv',
name: 'antVue文档(内嵌)', name: 'routes.demo.iframe.antv',
}, },
{ {
path: 'doc', path: 'doc',
name: '项目文档(内嵌)', name: 'routes.demo.iframe.doc',
}, },
{ {
path: 'docExternal', path: 'docExternal',
name: '项目文档(外链)', name: 'routes.demo.iframe.docExternal',
}, },
], ],
}, },

View File

@ -1,8 +1,9 @@
import type { MenuModule } from '/@/router/types.d'; import type { MenuModule } from '/@/router/types.d';
const menu: MenuModule = { const menu: MenuModule = {
orderNo: 20, orderNo: 20,
menu: { menu: {
name: '页面', name: 'routes.demo.page.page',
path: '/page-demo', path: '/page-demo',
tag: { tag: {
dot: true, dot: true,
@ -10,56 +11,56 @@ const menu: MenuModule = {
children: [ children: [
{ {
path: 'form', path: 'form',
name: '表单页', name: 'routes.demo.page.form',
children: [ children: [
{ {
path: 'basic', path: 'basic',
name: '基础表单', name: 'routes.demo.page.formBasic',
}, },
{ {
path: 'step', path: 'step',
name: '分步表单', name: 'routes.demo.page.formStep',
}, },
{ {
path: 'high', path: 'high',
name: '高级表单', name: 'routes.demo.page.formHigh',
}, },
], ],
}, },
{ {
path: 'desc', path: 'desc',
name: '详情页', name: 'routes.demo.page.desc',
children: [ children: [
{ {
path: 'basic', path: 'basic',
name: '基础详情页', name: 'routes.demo.page.descBasic',
}, },
{ {
path: 'high', path: 'high',
name: '高级详情页', name: 'routes.demo.page.descHigh',
}, },
], ],
}, },
{ {
path: 'result', path: 'result',
name: '结果页', name: 'routes.demo.page.result',
children: [ children: [
{ {
path: 'success', path: 'success',
name: '成功页', name: 'routes.demo.page.resultSuccess',
}, },
{ {
path: 'fail', path: 'fail',
name: '失败页', name: 'routes.demo.page.resultFail',
}, },
], ],
}, },
{ {
path: 'exception', path: 'exception',
name: '异常页', name: 'routes.demo.page.exception',
children: [ children: [
{ {
path: '403', path: '403',
@ -75,38 +76,38 @@ const menu: MenuModule = {
}, },
{ {
path: 'net-work-error', path: 'net-work-error',
name: '网络错误', name: 'routes.demo.page.netWorkError',
}, },
{ {
path: 'not-data', path: 'not-data',
name: '无数据', name: 'routes.demo.page.notData',
}, },
], ],
}, },
{ {
path: 'account', path: 'account',
name: '个人页', name: 'routes.demo.page.account',
children: [ children: [
{ {
path: 'center', path: 'center',
name: '个人中心', name: 'routes.demo.page.accountCenter',
}, },
{ {
path: 'setting', path: 'setting',
name: '个人设置', name: 'routes.demo.page.accountSetting',
}, },
], ],
}, },
{ {
path: 'list', path: 'list',
name: '列表页', name: 'routes.demo.page.list',
tag: { tag: {
content: 'new', content: 'new',
}, },
children: [ children: [
{ {
path: 'card', path: 'card',
name: '卡片列表', name: 'routes.demo.page.listCard',
}, },
], ],
}, },

View File

@ -1,43 +1,44 @@
import type { MenuModule } from '/@/router/types.d'; import type { MenuModule } from '/@/router/types.d';
const menu: MenuModule = { const menu: MenuModule = {
orderNo: 15, orderNo: 15,
menu: { menu: {
name: '权限管理', name: 'routes.demo.permission.permission',
path: '/permission', path: '/permission',
children: [ children: [
{ {
path: 'front', path: 'front',
name: '基于前端', name: 'routes.demo.permission.front',
children: [ children: [
{ {
path: 'page', path: 'page',
name: '页面权限', name: 'routes.demo.permission.frontPage',
}, },
{ {
path: 'btn', path: 'btn',
name: '按钮权限', name: 'routes.demo.permission.frontBtn',
}, },
{ {
path: 'auth-pageA', path: 'auth-pageA',
name: '权限测试页A', name: 'routes.demo.permission.frontTestA',
}, },
{ {
path: 'auth-pageB', path: 'auth-pageB',
name: '权限测试页B', name: 'routes.demo.permission.frontTestB',
}, },
], ],
}, },
{ {
path: 'back', path: 'back',
name: '基于后台', name: 'routes.demo.permission.back',
children: [ children: [
{ {
path: 'page', path: 'page',
name: '页面权限', name: 'routes.demo.permission.backPage',
}, },
{ {
path: 'btn', path: 'btn',
name: '按钮权限', name: 'routes.demo.permission.backBtn',
}, },
], ],
}, },

View File

@ -1,69 +1,70 @@
import type { MenuModule } from '/@/router/types.d'; import type { MenuModule } from '/@/router/types.d';
const menu: MenuModule = { const menu: MenuModule = {
orderNo: 30, orderNo: 30,
menu: { menu: {
path: '/table', path: '/table',
name: 'Table', name: 'routes.demo.table.table',
children: [ children: [
{ {
path: 'basic', path: 'basic',
name: '基础表格', name: 'routes.demo.table.basic',
}, },
{ {
path: 'treeTable', path: 'treeTable',
name: '树形表格', name: 'routes.demo.table.treeTable',
}, },
{ {
path: 'fetchTable', path: 'fetchTable',
name: '远程加载', name: 'routes.demo.table.fetchTable',
}, },
{ {
path: 'fixedColumn', path: 'fixedColumn',
name: '固定列', name: 'routes.demo.table.fixedColumn',
}, },
{ {
path: 'customerCell', path: 'customerCell',
name: '自定义列', name: 'routes.demo.table.customerCell',
}, },
{ {
path: 'formTable', path: 'formTable',
name: '开启搜索区域', name: 'routes.demo.table.formTable',
}, },
{ {
path: 'useTable', path: 'useTable',
name: 'UseTable', name: 'routes.demo.table.useTable',
}, },
{ {
path: 'refTable', path: 'refTable',
name: 'RefTable', name: 'routes.demo.table.refTable',
}, },
{ {
path: 'multipleHeader', path: 'multipleHeader',
name: '多级表头', name: 'routes.demo.table.multipleHeader',
}, },
{ {
path: 'mergeHeader', path: 'mergeHeader',
name: '合并单元格', name: 'routes.demo.table.mergeHeader',
}, },
{ {
path: 'expandTable', path: 'expandTable',
name: '可展开表格', name: 'routes.demo.table.expandTable',
}, },
{ {
path: 'fixedHeight', path: 'fixedHeight',
name: '定高/头部自定义', name: 'routes.demo.table.fixedHeight',
}, },
{ {
path: 'footerTable', path: 'footerTable',
name: '表尾行合计', name: 'routes.demo.table.footerTable',
}, },
{ {
path: 'editCellTable', path: 'editCellTable',
name: '可编辑单元格', name: 'routes.demo.table.editCellTable',
}, },
{ {
path: 'editRowTable', path: 'editRowTable',
name: '可编辑行', name: 'routes.demo.table.editRowTable',
}, },
], ],
}, },

View File

@ -1,21 +1,22 @@
import type { MenuModule } from '/@/router/types.d'; import type { MenuModule } from '/@/router/types.d';
const menu: MenuModule = { const menu: MenuModule = {
orderNo: 50, orderNo: 50,
menu: { menu: {
path: '/tree', path: '/tree',
name: 'Tree', name: 'routes.demo.tree.tree',
children: [ children: [
{ {
path: 'basic', path: 'basic',
name: '基础示例', name: 'routes.demo.tree.basic',
}, },
{ {
path: 'editTree', path: 'editTree',
name: '右键示例', name: 'routes.demo.tree.editTree',
}, },
{ {
path: 'actionTree', path: 'actionTree',
name: '函数操作示例', name: 'routes.demo.tree.actionTree',
}, },
], ],
}, },

View File

@ -33,7 +33,7 @@ export const LoginRoute: AppRouteRecordRaw = {
name: 'Login', name: 'Login',
component: () => import('/@/views/sys/login/Login.vue'), component: () => import('/@/views/sys/login/Login.vue'),
meta: { meta: {
title: '登录', title: 'routes.basic.login',
}, },
}; };

View File

@ -10,7 +10,7 @@ const dashboard: AppRouteModule = {
redirect: '/dashboard/workbench', redirect: '/dashboard/workbench',
meta: { meta: {
icon: 'ant-design:home-outlined', icon: 'ant-design:home-outlined',
title: 'Dashboard', title: 'routes.dashboard.dashboard',
}, },
}, },
@ -20,7 +20,7 @@ const dashboard: AppRouteModule = {
name: 'Welcome', name: 'Welcome',
component: () => import('/@/views/dashboard/welcome/index.vue'), component: () => import('/@/views/dashboard/welcome/index.vue'),
meta: { meta: {
title: '首页', title: 'routes.dashboard.welcome',
}, },
}, },
{ {
@ -28,7 +28,7 @@ const dashboard: AppRouteModule = {
name: 'Workbench', name: 'Workbench',
component: () => import('/@/views/dashboard/workbench/index.vue'), component: () => import('/@/views/dashboard/workbench/index.vue'),
meta: { meta: {
title: '工作台', title: 'routes.dashboard.workbench',
affix: true, affix: true,
}, },
}, },
@ -37,7 +37,7 @@ const dashboard: AppRouteModule = {
name: 'Analysis', name: 'Analysis',
component: () => import('/@/views/dashboard/analysis/index.vue'), component: () => import('/@/views/dashboard/analysis/index.vue'),
meta: { meta: {
title: '分析页', title: 'routes.dashboard.analysis',
}, },
}, },
], ],

View File

@ -10,7 +10,7 @@ const charts: AppRouteModule = {
redirect: '/charts/apexChart', redirect: '/charts/apexChart',
meta: { meta: {
icon: 'ant-design:area-chart-outlined', icon: 'ant-design:area-chart-outlined',
title: '图表库', title: 'routes.demo.charts.charts',
}, },
}, },
@ -27,7 +27,7 @@ const charts: AppRouteModule = {
name: 'Map', name: 'Map',
component: () => import('/@/views/demo/echarts/Map.vue'), component: () => import('/@/views/demo/echarts/Map.vue'),
meta: { meta: {
title: '地图', title: 'routes.demo.charts.map',
}, },
}, },
{ {
@ -35,7 +35,7 @@ const charts: AppRouteModule = {
name: 'Line', name: 'Line',
component: () => import('/@/views/demo/echarts/Line.vue'), component: () => import('/@/views/demo/echarts/Line.vue'),
meta: { meta: {
title: '折线图', title: 'routes.demo.charts.line',
}, },
}, },
{ {
@ -43,7 +43,7 @@ const charts: AppRouteModule = {
name: 'Pie', name: 'Pie',
component: () => import('/@/views/demo/echarts/Pie.vue'), component: () => import('/@/views/demo/echarts/Pie.vue'),
meta: { meta: {
title: '饼图', title: 'routes.demo.charts.pie',
}, },
}, },
], ],
@ -52,7 +52,7 @@ const charts: AppRouteModule = {
path: '/apexChart', path: '/apexChart',
name: 'ApexChart', name: 'ApexChart',
meta: { meta: {
title: 'ApexChart', title: 'routes.demo.charts.apexChart',
}, },
component: () => import('/@/views/demo/echarts/apex/index.vue'), component: () => import('/@/views/demo/echarts/apex/index.vue'),
}, },

View File

@ -10,7 +10,7 @@ const comp: AppRouteModule = {
redirect: '/comp/basic', redirect: '/comp/basic',
meta: { meta: {
icon: 'ant-design:table-outlined', icon: 'ant-design:table-outlined',
title: '组件', title: 'routes.demo.comp.comp',
}, },
}, },
@ -20,7 +20,7 @@ const comp: AppRouteModule = {
name: 'BasicDemo', name: 'BasicDemo',
component: () => import('/@/views/demo/comp/button/index.vue'), component: () => import('/@/views/demo/comp/button/index.vue'),
meta: { meta: {
title: '基础组件', title: 'routes.demo.comp.basic',
}, },
}, },
{ {
@ -28,7 +28,7 @@ const comp: AppRouteModule = {
name: 'transitionDemo', name: 'transitionDemo',
component: () => import('/@/views/demo/comp/transition/index.vue'), component: () => import('/@/views/demo/comp/transition/index.vue'),
meta: { meta: {
title: '动画组件', title: 'routes.demo.comp.transition',
}, },
}, },
{ {
@ -36,7 +36,7 @@ const comp: AppRouteModule = {
name: 'CountTo', name: 'CountTo',
component: () => import('/@/views/demo/comp/count-to/index.vue'), component: () => import('/@/views/demo/comp/count-to/index.vue'),
meta: { meta: {
title: '数字动画', title: 'routes.demo.comp.countTo',
}, },
}, },
@ -45,7 +45,7 @@ const comp: AppRouteModule = {
name: 'ScrollDemo', name: 'ScrollDemo',
redirect: '/comp/scroll/basic', redirect: '/comp/scroll/basic',
meta: { meta: {
title: '滚动组件', title: 'routes.demo.comp.scroll',
}, },
children: [ children: [
{ {
@ -53,7 +53,7 @@ const comp: AppRouteModule = {
name: 'BasicScrollDemo', name: 'BasicScrollDemo',
component: () => import('/@/views/demo/comp/scroll/index.vue'), component: () => import('/@/views/demo/comp/scroll/index.vue'),
meta: { meta: {
title: '基础滚动', title: 'routes.demo.comp.scrollBasic',
}, },
}, },
{ {
@ -61,7 +61,7 @@ const comp: AppRouteModule = {
name: 'ActionScrollDemo', name: 'ActionScrollDemo',
component: () => import('/@/views/demo/comp/scroll/Action.vue'), component: () => import('/@/views/demo/comp/scroll/Action.vue'),
meta: { meta: {
title: '滚动函数', title: 'routes.demo.comp.scrollAction',
}, },
}, },
{ {
@ -69,7 +69,7 @@ const comp: AppRouteModule = {
name: 'VirtualScrollDemo', name: 'VirtualScrollDemo',
component: () => import('/@/views/demo/comp/scroll/VirtualScroll.vue'), component: () => import('/@/views/demo/comp/scroll/VirtualScroll.vue'),
meta: { meta: {
title: '虚拟滚动', title: 'routes.demo.comp.virtualScroll',
}, },
}, },
], ],
@ -80,7 +80,7 @@ const comp: AppRouteModule = {
name: 'ModalDemo', name: 'ModalDemo',
component: () => import('/@/views/demo/comp/modal/index.vue'), component: () => import('/@/views/demo/comp/modal/index.vue'),
meta: { meta: {
title: '弹窗扩展', title: 'routes.demo.comp.modal',
}, },
}, },
{ {
@ -88,7 +88,7 @@ const comp: AppRouteModule = {
name: 'DrawerDemo', name: 'DrawerDemo',
component: () => import('/@/views/demo/comp/drawer/index.vue'), component: () => import('/@/views/demo/comp/drawer/index.vue'),
meta: { meta: {
title: '抽屉扩展', title: 'routes.demo.comp.drawer',
}, },
}, },
{ {
@ -96,7 +96,7 @@ const comp: AppRouteModule = {
name: 'DescDemo', name: 'DescDemo',
component: () => import('/@/views/demo/comp/desc/index.vue'), component: () => import('/@/views/demo/comp/desc/index.vue'),
meta: { meta: {
title: '详情组件', title: 'routes.demo.comp.desc',
}, },
}, },
@ -105,7 +105,7 @@ const comp: AppRouteModule = {
name: 'lazyDemo', name: 'lazyDemo',
redirect: '/comp/lazy/basic', redirect: '/comp/lazy/basic',
meta: { meta: {
title: '懒加载组件', title: 'routes.demo.comp.lazy',
}, },
children: [ children: [
{ {
@ -113,7 +113,7 @@ const comp: AppRouteModule = {
name: 'BasicLazyDemo', name: 'BasicLazyDemo',
component: () => import('/@/views/demo/comp/lazy/index.vue'), component: () => import('/@/views/demo/comp/lazy/index.vue'),
meta: { meta: {
title: '基础示例', title: 'routes.demo.comp.lazyBasic',
}, },
}, },
{ {
@ -121,7 +121,7 @@ const comp: AppRouteModule = {
name: 'BasicTransitionDemo', name: 'BasicTransitionDemo',
component: () => import('/@/views/demo/comp/lazy/Transition.vue'), component: () => import('/@/views/demo/comp/lazy/Transition.vue'),
meta: { meta: {
title: '动画效果', title: 'routes.demo.comp.lazyTransition',
}, },
}, },
], ],
@ -131,7 +131,7 @@ const comp: AppRouteModule = {
name: 'VerifyDemo', name: 'VerifyDemo',
redirect: '/comp/verify/drag', redirect: '/comp/verify/drag',
meta: { meta: {
title: '验证组件', title: 'routes.demo.comp.verify',
}, },
children: [ children: [
{ {
@ -139,7 +139,7 @@ const comp: AppRouteModule = {
name: 'VerifyDragDemo', name: 'VerifyDragDemo',
component: () => import('/@/views/demo/comp/verify/index.vue'), component: () => import('/@/views/demo/comp/verify/index.vue'),
meta: { meta: {
title: '拖拽校验', title: 'routes.demo.comp.verifyDrag',
}, },
}, },
{ {
@ -147,7 +147,7 @@ const comp: AppRouteModule = {
name: 'VerifyRotateDemo', name: 'VerifyRotateDemo',
component: () => import('/@/views/demo/comp/verify/Rotate.vue'), component: () => import('/@/views/demo/comp/verify/Rotate.vue'),
meta: { meta: {
title: '图片还原', title: 'routes.demo.comp.verifyRotate',
}, },
}, },
], ],
@ -159,7 +159,7 @@ const comp: AppRouteModule = {
name: 'QrCodeDemo', name: 'QrCodeDemo',
component: () => import('/@/views/demo/comp/qrcode/index.vue'), component: () => import('/@/views/demo/comp/qrcode/index.vue'),
meta: { meta: {
title: '二维码组件', title: 'routes.demo.comp.qrcode',
}, },
}, },
{ {
@ -167,7 +167,7 @@ const comp: AppRouteModule = {
name: 'StrengthMeterDemo', name: 'StrengthMeterDemo',
component: () => import('/@/views/demo/comp/strength-meter/index.vue'), component: () => import('/@/views/demo/comp/strength-meter/index.vue'),
meta: { meta: {
title: '密码强度组件', title: 'routes.demo.comp.strength',
}, },
}, },
{ {
@ -175,7 +175,7 @@ const comp: AppRouteModule = {
name: 'UploadDemo', name: 'UploadDemo',
component: () => import('/@/views/demo/comp/upload/index.vue'), component: () => import('/@/views/demo/comp/upload/index.vue'),
meta: { meta: {
title: '上传组件', title: 'routes.demo.comp.upload',
}, },
}, },
], ],

View File

@ -10,7 +10,7 @@ const editor: AppRouteModule = {
redirect: '/editor/markdown', redirect: '/editor/markdown',
meta: { meta: {
icon: 'ant-design:table-outlined', icon: 'ant-design:table-outlined',
title: '编辑器', title: 'routes.demo.editor.editor',
}, },
}, },
@ -20,14 +20,14 @@ const editor: AppRouteModule = {
name: 'MarkdownDemo', name: 'MarkdownDemo',
component: () => import('/@/views/demo/editor/Markdown.vue'), component: () => import('/@/views/demo/editor/Markdown.vue'),
meta: { meta: {
title: 'markdown编辑器', title: 'routes.demo.editor.markdown',
}, },
}, },
{ {
path: '/tinymce', path: '/tinymce',
name: 'TinymceDemo', name: 'TinymceDemo',
meta: { meta: {
title: '富文本', title: 'routes.demo.editor.tinymce',
}, },
redirect: '/editor/tinymce/index', redirect: '/editor/tinymce/index',
children: [ children: [
@ -36,7 +36,7 @@ const editor: AppRouteModule = {
name: 'TinymceBasicDemo', name: 'TinymceBasicDemo',
component: () => import('/@/views/demo/editor/tinymce/index.vue'), component: () => import('/@/views/demo/editor/tinymce/index.vue'),
meta: { meta: {
title: '基础使用', title: 'routes.demo.editor.tinymceBasic',
}, },
}, },
// TODO // TODO
@ -45,7 +45,7 @@ const editor: AppRouteModule = {
name: 'TinymceFormDemo', name: 'TinymceFormDemo',
component: () => import('/@/views/demo/editor/tinymce/Editor.vue'), component: () => import('/@/views/demo/editor/tinymce/Editor.vue'),
meta: { meta: {
title: '嵌入form使用', title: 'routes.demo.editor.tinymceForm',
}, },
}, },
], ],

View File

@ -10,7 +10,7 @@ const excel: AppRouteModule = {
redirect: '/excel/customExport', redirect: '/excel/customExport',
meta: { meta: {
icon: 'mdi:microsoft-excel', icon: 'mdi:microsoft-excel',
title: 'Excel', title: 'routes.demo.excel.excel',
}, },
}, },
@ -20,7 +20,7 @@ const excel: AppRouteModule = {
name: 'CustomExport', name: 'CustomExport',
component: () => import('/@/views/demo/excel/CustomExport.vue'), component: () => import('/@/views/demo/excel/CustomExport.vue'),
meta: { meta: {
title: '选择导出格式', title: 'routes.demo.excel.customExport',
}, },
}, },
{ {
@ -28,7 +28,7 @@ const excel: AppRouteModule = {
name: 'JsonExport', name: 'JsonExport',
component: () => import('/@/views/demo/excel/JsonExport.vue'), component: () => import('/@/views/demo/excel/JsonExport.vue'),
meta: { meta: {
title: 'JSON数据导出', title: 'routes.demo.excel.jsonExport',
}, },
}, },
{ {
@ -36,7 +36,7 @@ const excel: AppRouteModule = {
name: 'ArrayExport', name: 'ArrayExport',
component: () => import('/@/views/demo/excel/ArrayExport.vue'), component: () => import('/@/views/demo/excel/ArrayExport.vue'),
meta: { meta: {
title: 'Array数据导出', title: 'routes.demo.excel.arrayExport',
}, },
}, },
{ {
@ -44,7 +44,7 @@ const excel: AppRouteModule = {
name: 'ImportExcel', name: 'ImportExcel',
component: () => import('/@/views/demo/excel/ImportExcel.vue'), component: () => import('/@/views/demo/excel/ImportExcel.vue'),
meta: { meta: {
title: '导入', title: 'routes.demo.excel.importExcel',
}, },
}, },
], ],

View File

@ -10,7 +10,7 @@ const feat: AppRouteModule = {
redirect: '/feat/icon', redirect: '/feat/icon',
meta: { meta: {
icon: 'ic:outline-featured-play-list', icon: 'ic:outline-featured-play-list',
title: '页面功能', title: 'routes.demo.feat.feat',
}, },
}, },
@ -20,7 +20,7 @@ const feat: AppRouteModule = {
name: 'IconDemo', name: 'IconDemo',
component: () => import('/@/views/demo/feat/icon/index.vue'), component: () => import('/@/views/demo/feat/icon/index.vue'),
meta: { meta: {
title: '图标', title: 'routes.demo.feat.icon',
}, },
}, },
{ {
@ -28,7 +28,7 @@ const feat: AppRouteModule = {
name: 'TabsDemo', name: 'TabsDemo',
component: () => import('/@/views/demo/feat/tabs/index.vue'), component: () => import('/@/views/demo/feat/tabs/index.vue'),
meta: { meta: {
title: '标签页操作', title: 'routes.demo.feat.tabs',
}, },
}, },
@ -37,7 +37,7 @@ const feat: AppRouteModule = {
name: 'ContextMenuDemo', name: 'ContextMenuDemo',
component: () => import('/@/views/demo/feat/context-menu/index.vue'), component: () => import('/@/views/demo/feat/context-menu/index.vue'),
meta: { meta: {
title: '右键菜单', title: 'routes.demo.feat.contextMenu',
}, },
}, },
{ {
@ -45,7 +45,7 @@ const feat: AppRouteModule = {
name: 'DownLoadDemo', name: 'DownLoadDemo',
component: () => import('/@/views/demo/feat/download/index.vue'), component: () => import('/@/views/demo/feat/download/index.vue'),
meta: { meta: {
title: '文件下载', title: 'routes.demo.feat.download',
}, },
}, },
{ {
@ -53,7 +53,7 @@ const feat: AppRouteModule = {
name: 'ClickOutSideDemo', name: 'ClickOutSideDemo',
component: () => import('/@/views/demo/feat/click-out-side/index.vue'), component: () => import('/@/views/demo/feat/click-out-side/index.vue'),
meta: { meta: {
title: 'ClickOutSide组件', title: 'routes.demo.feat.clickOutSide',
}, },
}, },
{ {
@ -61,7 +61,7 @@ const feat: AppRouteModule = {
name: 'ImgPreview', name: 'ImgPreview',
component: () => import('/@/views/demo/feat/img-preview/index.vue'), component: () => import('/@/views/demo/feat/img-preview/index.vue'),
meta: { meta: {
title: '图片预览', title: 'routes.demo.feat.imgPreview',
}, },
}, },
{ {
@ -69,7 +69,7 @@ const feat: AppRouteModule = {
name: 'CopyDemo', name: 'CopyDemo',
component: () => import('/@/views/demo/feat/copy/index.vue'), component: () => import('/@/views/demo/feat/copy/index.vue'),
meta: { meta: {
title: '剪切板', title: 'routes.demo.feat.copy',
}, },
}, },
{ {
@ -77,7 +77,7 @@ const feat: AppRouteModule = {
name: 'MsgDemo', name: 'MsgDemo',
component: () => import('/@/views/demo/feat/msg/index.vue'), component: () => import('/@/views/demo/feat/msg/index.vue'),
meta: { meta: {
title: '消息提示', title: 'routes.demo.feat.msg',
}, },
}, },
{ {
@ -85,7 +85,7 @@ const feat: AppRouteModule = {
name: 'WatermarkDemo', name: 'WatermarkDemo',
component: () => import('/@/views/demo/feat/watermark/index.vue'), component: () => import('/@/views/demo/feat/watermark/index.vue'),
meta: { meta: {
title: '水印', title: 'routes.demo.feat.watermark',
}, },
}, },
{ {
@ -93,7 +93,7 @@ const feat: AppRouteModule = {
name: 'FullScreenDemo', name: 'FullScreenDemo',
component: () => import('/@/views/demo/feat/full-screen/index.vue'), component: () => import('/@/views/demo/feat/full-screen/index.vue'),
meta: { meta: {
title: '全屏', title: 'routes.demo.feat.fullScreen',
}, },
}, },
{ {
@ -101,7 +101,7 @@ const feat: AppRouteModule = {
name: 'ErrorLog', name: 'ErrorLog',
component: () => import('/@/views/sys/error-log/index.vue'), component: () => import('/@/views/sys/error-log/index.vue'),
meta: { meta: {
title: '错误日志', title: 'routes.demo.feat.errorLog',
}, },
}, },
{ {
@ -109,7 +109,7 @@ const feat: AppRouteModule = {
name: 'TestTab', name: 'TestTab',
component: () => import('/@/views/demo/feat/tab-params/index.vue'), component: () => import('/@/views/demo/feat/tab-params/index.vue'),
meta: { meta: {
title: 'Tab带参', title: 'routes.demo.feat.tab',
carryParam: true, carryParam: true,
}, },
}, },

View File

@ -10,7 +10,7 @@ const form: AppRouteModule = {
redirect: '/form/basic', redirect: '/form/basic',
meta: { meta: {
icon: 'ant-design:table-outlined', icon: 'ant-design:table-outlined',
title: 'Form', title: 'rroutes.demo.form.form',
}, },
}, },
@ -20,7 +20,7 @@ const form: AppRouteModule = {
name: 'FormBasicDemo', name: 'FormBasicDemo',
component: () => import('/@/views/demo/form/index.vue'), component: () => import('/@/views/demo/form/index.vue'),
meta: { meta: {
title: '基础表单', title: 'rroutes.demo.form.basic',
}, },
}, },
{ {
@ -28,7 +28,7 @@ const form: AppRouteModule = {
name: 'UseFormDemo', name: 'UseFormDemo',
component: () => import('/@/views/demo/form/UseForm.vue'), component: () => import('/@/views/demo/form/UseForm.vue'),
meta: { meta: {
title: 'useForm', title: 'rroutes.demo.form.useForm',
}, },
}, },
{ {
@ -36,7 +36,7 @@ const form: AppRouteModule = {
name: 'RefFormDemo', name: 'RefFormDemo',
component: () => import('/@/views/demo/form/RefForm.vue'), component: () => import('/@/views/demo/form/RefForm.vue'),
meta: { meta: {
title: 'RefForm', title: 'rroutes.demo.form.refForm',
}, },
}, },
{ {
@ -44,7 +44,7 @@ const form: AppRouteModule = {
name: 'AdvancedFormDemo', name: 'AdvancedFormDemo',
component: () => import('/@/views/demo/form/AdvancedForm.vue'), component: () => import('/@/views/demo/form/AdvancedForm.vue'),
meta: { meta: {
title: '可收缩表单', title: 'rroutes.demo.form.advancedForm',
}, },
}, },
{ {
@ -52,7 +52,7 @@ const form: AppRouteModule = {
name: 'RuleFormDemo', name: 'RuleFormDemo',
component: () => import('/@/views/demo/form/RuleForm.vue'), component: () => import('/@/views/demo/form/RuleForm.vue'),
meta: { meta: {
title: '表单验证', title: 'rroutes.demo.form.ruleForm',
}, },
}, },
{ {
@ -60,7 +60,7 @@ const form: AppRouteModule = {
name: 'DynamicFormDemo', name: 'DynamicFormDemo',
component: () => import('/@/views/demo/form/DynamicForm.vue'), component: () => import('/@/views/demo/form/DynamicForm.vue'),
meta: { meta: {
title: '动态表单', title: 'rroutes.demo.form.dynamicForm',
}, },
}, },
{ {
@ -68,7 +68,7 @@ const form: AppRouteModule = {
name: 'CustomerFormDemo', name: 'CustomerFormDemo',
component: () => import('/@/views/demo/form/CustomerForm.vue'), component: () => import('/@/views/demo/form/CustomerForm.vue'),
meta: { meta: {
title: '自定义组件', title: 'rroutes.demo.form.customerForm',
}, },
}, },
], ],

View File

@ -11,7 +11,7 @@ const iframe: AppRouteModule = {
redirect: '/frame/antv', redirect: '/frame/antv',
meta: { meta: {
icon: 'mdi:page-next-outline', icon: 'mdi:page-next-outline',
title: '外部页面', title: 'routes.demo.iframe.frame',
}, },
}, },
@ -22,7 +22,7 @@ const iframe: AppRouteModule = {
component: IFrame, component: IFrame,
meta: { meta: {
frameSrc: 'https://2x.antdv.com/docs/vue/introduce-cn/', frameSrc: 'https://2x.antdv.com/docs/vue/introduce-cn/',
title: 'antVue文档(内嵌)', title: 'routes.demo.iframe.antv',
afterCloseLoading: true, afterCloseLoading: true,
}, },
}, },
@ -32,7 +32,7 @@ const iframe: AppRouteModule = {
component: IFrame, component: IFrame,
meta: { meta: {
frameSrc: 'https://vvbin.cn/doc-next/', frameSrc: 'https://vvbin.cn/doc-next/',
title: '项目文档(内嵌)', title: 'routes.demo.iframe.doc',
afterCloseLoading: true, afterCloseLoading: true,
}, },
}, },
@ -42,7 +42,7 @@ const iframe: AppRouteModule = {
component: IFrame, component: IFrame,
meta: { meta: {
externalLink: 'https://vvbin.cn/doc-next/', externalLink: 'https://vvbin.cn/doc-next/',
title: '项目文档(外链)', title: 'routes.demo.iframe.docExternal',
}, },
}, },
], ],

View File

@ -12,7 +12,7 @@ const page: AppRouteModule = {
redirect: '/page-demo/exception', redirect: '/page-demo/exception',
meta: { meta: {
icon: 'mdi:page-next-outline', icon: 'mdi:page-next-outline',
title: '页面', title: 'routes.demo.page.page',
}, },
children: [ children: [
// =============================form start============================= // =============================form start=============================
@ -21,7 +21,7 @@ const page: AppRouteModule = {
name: 'FormPage', name: 'FormPage',
redirect: '/page-demo/form/basic', redirect: '/page-demo/form/basic',
meta: { meta: {
title: '表单页', title: 'routes.demo.page.form',
}, },
children: [ children: [
{ {
@ -29,7 +29,7 @@ const page: AppRouteModule = {
name: 'FormBasicPage', name: 'FormBasicPage',
component: () => import('/@/views/demo/page/form/basic/index.vue'), component: () => import('/@/views/demo/page/form/basic/index.vue'),
meta: { meta: {
title: '基础表单', title: 'routes.demo.page.formBasic',
}, },
}, },
{ {
@ -37,7 +37,7 @@ const page: AppRouteModule = {
name: 'FormStepPage', name: 'FormStepPage',
component: () => import('/@/views/demo/page/form/step/index.vue'), component: () => import('/@/views/demo/page/form/step/index.vue'),
meta: { meta: {
title: '分步表单', title: 'routes.demo.page.formStep',
}, },
}, },
{ {
@ -45,7 +45,7 @@ const page: AppRouteModule = {
name: 'FormHightPage', name: 'FormHightPage',
component: () => import('/@/views/demo/page/form/high/index.vue'), component: () => import('/@/views/demo/page/form/high/index.vue'),
meta: { meta: {
title: '高级表单', title: 'routes.demo.page.formHigh',
}, },
}, },
], ],
@ -57,7 +57,7 @@ const page: AppRouteModule = {
name: 'DescPage', name: 'DescPage',
redirect: '/page-demo/desc/basic', redirect: '/page-demo/desc/basic',
meta: { meta: {
title: '详情页', title: 'routes.demo.page.desc',
}, },
children: [ children: [
{ {
@ -65,7 +65,7 @@ const page: AppRouteModule = {
name: 'DescBasicPage', name: 'DescBasicPage',
component: () => import('/@/views/demo/page/desc/basic/index.vue'), component: () => import('/@/views/demo/page/desc/basic/index.vue'),
meta: { meta: {
title: '基础详情页', title: 'routes.demo.page.descBasic',
}, },
}, },
{ {
@ -73,7 +73,7 @@ const page: AppRouteModule = {
name: 'DescHighPage', name: 'DescHighPage',
component: () => import('/@/views/demo/page/desc/high/index.vue'), component: () => import('/@/views/demo/page/desc/high/index.vue'),
meta: { meta: {
title: '高级详情页', title: 'routes.demo.page.descHigh',
}, },
}, },
], ],
@ -86,7 +86,7 @@ const page: AppRouteModule = {
name: 'ResultPage', name: 'ResultPage',
redirect: '/page-demo/result/success', redirect: '/page-demo/result/success',
meta: { meta: {
title: '结果页', title: 'routes.demo.page.result',
}, },
children: [ children: [
{ {
@ -94,7 +94,7 @@ const page: AppRouteModule = {
name: 'ResultSuccessPage', name: 'ResultSuccessPage',
component: () => import('/@/views/demo/page/result/success/index.vue'), component: () => import('/@/views/demo/page/result/success/index.vue'),
meta: { meta: {
title: '成功页', title: 'routes.demo.page.resultSuccess',
}, },
}, },
{ {
@ -102,7 +102,7 @@ const page: AppRouteModule = {
name: 'ResultFailPage', name: 'ResultFailPage',
component: () => import('/@/views/demo/page/result/fail/index.vue'), component: () => import('/@/views/demo/page/result/fail/index.vue'),
meta: { meta: {
title: '失败页', title: 'routes.demo.page.resultFail',
}, },
}, },
], ],
@ -115,7 +115,7 @@ const page: AppRouteModule = {
name: 'AccountPage', name: 'AccountPage',
redirect: '/page-demo/account/setting', redirect: '/page-demo/account/setting',
meta: { meta: {
title: '个人页', title: 'routes.demo.page.account',
}, },
children: [ children: [
{ {
@ -123,7 +123,7 @@ const page: AppRouteModule = {
name: 'AccountCenterPage', name: 'AccountCenterPage',
component: () => import('/@/views/demo/page/account/center/index.vue'), component: () => import('/@/views/demo/page/account/center/index.vue'),
meta: { meta: {
title: '个人中心', title: 'routes.demo.page.accountCenter',
}, },
}, },
{ {
@ -131,7 +131,7 @@ const page: AppRouteModule = {
name: 'AccountSettingPage', name: 'AccountSettingPage',
component: () => import('/@/views/demo/page/account/setting/index.vue'), component: () => import('/@/views/demo/page/account/setting/index.vue'),
meta: { meta: {
title: '个人设置', title: 'routes.demo.page.accountSetting',
}, },
}, },
], ],
@ -143,7 +143,7 @@ const page: AppRouteModule = {
name: 'ExceptionPage', name: 'ExceptionPage',
redirect: '/page-demo/exception/404', redirect: '/page-demo/exception/404',
meta: { meta: {
title: '异常页', title: 'routes.demo.page.exception',
}, },
children: [ children: [
{ {
@ -190,7 +190,7 @@ const page: AppRouteModule = {
status: ExceptionEnum.NET_WORK_ERROR, status: ExceptionEnum.NET_WORK_ERROR,
}, },
meta: { meta: {
title: '网络错误', title: 'routes.demo.page.netWorkError',
afterCloseLoading: true, afterCloseLoading: true,
}, },
}, },
@ -202,7 +202,7 @@ const page: AppRouteModule = {
status: ExceptionEnum.PAGE_NOT_DATA, status: ExceptionEnum.PAGE_NOT_DATA,
}, },
meta: { meta: {
title: '无数据', title: 'routes.demo.page.notData',
afterCloseLoading: true, afterCloseLoading: true,
}, },
}, },
@ -215,7 +215,7 @@ const page: AppRouteModule = {
name: 'ListPage', name: 'ListPage',
redirect: '/page-demo/list/card', redirect: '/page-demo/list/card',
meta: { meta: {
title: '列表页', title: 'routes.demo.page.list',
}, },
children: [ children: [
{ {
@ -223,7 +223,7 @@ const page: AppRouteModule = {
name: 'ListCardPage', name: 'ListCardPage',
component: () => import('/@/views/demo/page/list/card/index.vue'), component: () => import('/@/views/demo/page/list/card/index.vue'),
meta: { meta: {
title: '卡片列表', title: 'routes.demo.page.listCard',
}, },
}, },
], ],

View File

@ -11,7 +11,7 @@ const permission: AppRouteModule = {
redirect: '/permission/front/page', redirect: '/permission/front/page',
meta: { meta: {
icon: 'carbon:user-role', icon: 'carbon:user-role',
title: '权限管理', title: 'routes.demo.permission.permission',
}, },
}, },
@ -20,7 +20,7 @@ const permission: AppRouteModule = {
path: '/front', path: '/front',
name: 'PermissionFrontDemo', name: 'PermissionFrontDemo',
meta: { meta: {
title: '基于前端权限', title: 'routes.demo.permission.front',
}, },
children: [ children: [
{ {
@ -28,7 +28,7 @@ const permission: AppRouteModule = {
name: 'FrontPageAuth', name: 'FrontPageAuth',
component: () => import('/@/views/demo/permission/front/index.vue'), component: () => import('/@/views/demo/permission/front/index.vue'),
meta: { meta: {
title: '页面权限', title: 'routes.demo.permission.frontPage',
}, },
}, },
{ {
@ -36,7 +36,7 @@ const permission: AppRouteModule = {
name: 'FrontBtnAuth', name: 'FrontBtnAuth',
component: () => import('/@/views/demo/permission/front/Btn.vue'), component: () => import('/@/views/demo/permission/front/Btn.vue'),
meta: { meta: {
title: '按钮权限', title: 'routes.demo.permission.frontBtn',
}, },
}, },
{ {
@ -44,7 +44,7 @@ const permission: AppRouteModule = {
name: 'FrontAuthPageA', name: 'FrontAuthPageA',
component: () => import('/@/views/demo/permission/front/AuthPageA.vue'), component: () => import('/@/views/demo/permission/front/AuthPageA.vue'),
meta: { meta: {
title: '权限测试页A', title: 'routes.demo.permission.frontTestA',
roles: [RoleEnum.SUPER], roles: [RoleEnum.SUPER],
}, },
}, },
@ -53,7 +53,7 @@ const permission: AppRouteModule = {
name: 'FrontAuthPageB', name: 'FrontAuthPageB',
component: () => import('/@/views/demo/permission/front/AuthPageB.vue'), component: () => import('/@/views/demo/permission/front/AuthPageB.vue'),
meta: { meta: {
title: '权限测试页B', title: 'routes.demo.permission.frontTestB',
roles: [RoleEnum.TEST], roles: [RoleEnum.TEST],
}, },
}, },
@ -63,7 +63,7 @@ const permission: AppRouteModule = {
path: '/back', path: '/back',
name: 'PermissionBackDemo', name: 'PermissionBackDemo',
meta: { meta: {
title: '基于后台权限', title: 'routes.demo.permission.back',
}, },
children: [ children: [
{ {
@ -71,7 +71,7 @@ const permission: AppRouteModule = {
name: 'BackAuthPage', name: 'BackAuthPage',
component: () => import('/@/views/demo/permission/back/index.vue'), component: () => import('/@/views/demo/permission/back/index.vue'),
meta: { meta: {
title: '页面权限', title: 'routes.demo.permission.backPage',
}, },
}, },
{ {
@ -79,7 +79,7 @@ const permission: AppRouteModule = {
name: 'BackAuthBtn', name: 'BackAuthBtn',
component: () => import('/@/views/demo/permission/back/Btn.vue'), component: () => import('/@/views/demo/permission/back/Btn.vue'),
meta: { meta: {
title: '按钮权限', title: 'routes.demo.permission.backBtn',
}, },
}, },
], ],

View File

@ -10,7 +10,7 @@ const table: AppRouteModule = {
redirect: '/table/basic', redirect: '/table/basic',
meta: { meta: {
icon: 'ant-design:table-outlined', icon: 'ant-design:table-outlined',
title: 'Table', title: 'routes.demo.table.table',
}, },
}, },
@ -20,7 +20,7 @@ const table: AppRouteModule = {
name: 'TableBasicDemo', name: 'TableBasicDemo',
component: () => import('/@/views/demo/table/Basic.vue'), component: () => import('/@/views/demo/table/Basic.vue'),
meta: { meta: {
title: '基础表格', title: 'routes.demo.table.basic',
}, },
}, },
{ {
@ -28,7 +28,7 @@ const table: AppRouteModule = {
name: 'TreeTableDemo', name: 'TreeTableDemo',
component: () => import('/@/views/demo/table/TreeTable.vue'), component: () => import('/@/views/demo/table/TreeTable.vue'),
meta: { meta: {
title: '树形表格', title: 'routes.demo.table.treeTable',
}, },
}, },
{ {
@ -36,7 +36,7 @@ const table: AppRouteModule = {
name: 'FetchTableDemo', name: 'FetchTableDemo',
component: () => import('/@/views/demo/table/FetchTable.vue'), component: () => import('/@/views/demo/table/FetchTable.vue'),
meta: { meta: {
title: '远程加载示例', title: 'routes.demo.table.fetchTable',
}, },
}, },
{ {
@ -44,7 +44,7 @@ const table: AppRouteModule = {
name: 'FixedColumnDemo', name: 'FixedColumnDemo',
component: () => import('/@/views/demo/table/FixedColumn.vue'), component: () => import('/@/views/demo/table/FixedColumn.vue'),
meta: { meta: {
title: '固定列', title: 'routes.demo.table.fixedColumn',
}, },
}, },
{ {
@ -52,7 +52,7 @@ const table: AppRouteModule = {
name: 'CustomerCellDemo', name: 'CustomerCellDemo',
component: () => import('/@/views/demo/table/CustomerCell.vue'), component: () => import('/@/views/demo/table/CustomerCell.vue'),
meta: { meta: {
title: '自定义列', title: 'routes.demo.table.customerCell',
}, },
}, },
{ {
@ -60,7 +60,7 @@ const table: AppRouteModule = {
name: 'FormTableDemo', name: 'FormTableDemo',
component: () => import('/@/views/demo/table/FormTable.vue'), component: () => import('/@/views/demo/table/FormTable.vue'),
meta: { meta: {
title: '开启搜索区域', title: 'routes.demo.table.formTable',
}, },
}, },
{ {
@ -68,7 +68,7 @@ const table: AppRouteModule = {
name: 'UseTableDemo', name: 'UseTableDemo',
component: () => import('/@/views/demo/table/UseTable.vue'), component: () => import('/@/views/demo/table/UseTable.vue'),
meta: { meta: {
title: 'UseTable', title: 'routes.demo.table.useTable',
}, },
}, },
{ {
@ -76,7 +76,7 @@ const table: AppRouteModule = {
name: 'RefTableDemo', name: 'RefTableDemo',
component: () => import('/@/views/demo/table/RefTable.vue'), component: () => import('/@/views/demo/table/RefTable.vue'),
meta: { meta: {
title: 'RefTable', title: 'routes.demo.table.refTable',
}, },
}, },
{ {
@ -84,7 +84,7 @@ const table: AppRouteModule = {
name: 'MultipleHeaderDemo', name: 'MultipleHeaderDemo',
component: () => import('/@/views/demo/table/MultipleHeader.vue'), component: () => import('/@/views/demo/table/MultipleHeader.vue'),
meta: { meta: {
title: '多级表头', title: 'routes.demo.table.multipleHeader',
}, },
}, },
{ {
@ -92,7 +92,7 @@ const table: AppRouteModule = {
name: 'MergeHeaderDemo', name: 'MergeHeaderDemo',
component: () => import('/@/views/demo/table/MergeHeader.vue'), component: () => import('/@/views/demo/table/MergeHeader.vue'),
meta: { meta: {
title: '合并单元格', title: 'routes.demo.table.mergeHeader',
}, },
}, },
{ {
@ -100,7 +100,7 @@ const table: AppRouteModule = {
name: 'ExpandTableDemo', name: 'ExpandTableDemo',
component: () => import('/@/views/demo/table/ExpandTable.vue'), component: () => import('/@/views/demo/table/ExpandTable.vue'),
meta: { meta: {
title: '可展开表格', title: 'routes.demo.table.expandTable',
}, },
}, },
{ {
@ -108,7 +108,7 @@ const table: AppRouteModule = {
name: 'FixedHeightDemo', name: 'FixedHeightDemo',
component: () => import('/@/views/demo/table/FixedHeight.vue'), component: () => import('/@/views/demo/table/FixedHeight.vue'),
meta: { meta: {
title: '定高/头部自定义', title: 'routes.demo.table.fixedHeight',
}, },
}, },
{ {
@ -116,7 +116,7 @@ const table: AppRouteModule = {
name: 'FooterTableDemo', name: 'FooterTableDemo',
component: () => import('/@/views/demo/table/FooterTable.vue'), component: () => import('/@/views/demo/table/FooterTable.vue'),
meta: { meta: {
title: '表尾行合计', title: 'routes.demo.table.footerTable',
}, },
}, },
{ {
@ -124,7 +124,7 @@ const table: AppRouteModule = {
name: 'EditCellTableDemo', name: 'EditCellTableDemo',
component: () => import('/@/views/demo/table/EditCellTable.vue'), component: () => import('/@/views/demo/table/EditCellTable.vue'),
meta: { meta: {
title: '可编辑单元格', title: 'routes.demo.table.editCellTable',
}, },
}, },
{ {
@ -132,7 +132,7 @@ const table: AppRouteModule = {
name: 'EditRowTableDemo', name: 'EditRowTableDemo',
component: () => import('/@/views/demo/table/EditRowTable.vue'), component: () => import('/@/views/demo/table/EditRowTable.vue'),
meta: { meta: {
title: '可编辑行', title: 'routes.demo.table.editRowTable',
}, },
}, },
], ],

View File

@ -10,7 +10,7 @@ const tree: AppRouteModule = {
redirect: '/tree/basic', redirect: '/tree/basic',
meta: { meta: {
icon: 'clarity:tree-view-line', icon: 'clarity:tree-view-line',
title: 'Tree', title: 'routes.demo.tree.tree',
}, },
}, },
routes: [ routes: [
@ -19,7 +19,7 @@ const tree: AppRouteModule = {
name: 'BasicTreeDemo', name: 'BasicTreeDemo',
component: () => import('/@/views/demo/tree/index.vue'), component: () => import('/@/views/demo/tree/index.vue'),
meta: { meta: {
title: '基础树', title: 'routes.demo.tree.basic',
}, },
}, },
{ {
@ -27,7 +27,7 @@ const tree: AppRouteModule = {
name: 'EditTreeDemo', name: 'EditTreeDemo',
component: () => import('/@/views/demo/tree/EditTree.vue'), component: () => import('/@/views/demo/tree/EditTree.vue'),
meta: { meta: {
title: '右键示例', title: 'routes.demo.tree.editTree',
}, },
}, },
{ {
@ -35,7 +35,7 @@ const tree: AppRouteModule = {
name: 'ActionTreeDemo', name: 'ActionTreeDemo',
component: () => import('/@/views/demo/tree/ActionTree.vue'), component: () => import('/@/views/demo/tree/ActionTree.vue'),
meta: { meta: {
title: '函数操作示例', title: 'routes.demo.tree.actionTree',
}, },
}, },
], ],

View File

@ -20,7 +20,7 @@ import {
} from '/@/setup/theme'; } from '/@/setup/theme';
import { appStore } from '/@/store/modules/app'; import { appStore } from '/@/store/modules/app';
import { deepMerge } from '../utils/index'; import { deepMerge } from '/@/utils';
// Used to share global app instances // Used to share global app instances
let app: App; let app: App;

View File

@ -1,20 +1,19 @@
import { App, unref } from 'vue'; import { App } from 'vue';
import type { I18n, I18nOptions } from 'vue-i18n'; import type { I18n, I18nOptions } from 'vue-i18n';
import { createI18n } from 'vue-i18n'; import { createI18n } from 'vue-i18n';
import localeMessages from '/@/locales'; import localeMessages from '/@/locales';
import { useLocale } from '/@/hooks/web/useLocale'; import { useLocale } from '/@/hooks/web/useLocale';
import { useLocaleSetting } from '/@/hooks/setting/useLocaleSetting'; import projectSetting from '/@/settings/projectSetting';
const { setupLocale } = useLocale(); const { setupLocale } = useLocale();
const { getLang, getAvailableLocales, getFallbackLocale } = useLocaleSetting(); const { lang, availableLocales, fallback } = projectSetting?.locale;
const localeData: I18nOptions = { const localeData: I18nOptions = {
legacy: false, legacy: false,
locale: unref(getLang), locale: lang,
fallbackLocale: unref(getFallbackLocale), fallbackLocale: fallback,
messages: localeMessages, messages: localeMessages,
availableLocales: unref(getAvailableLocales), availableLocales: availableLocales,
sync: true, //If you dont want to inherit locale from global scope, you need to set sync of i18n component option to false. sync: true, //If you dont want to inherit locale from global scope, you need to set sync of i18n component option to false.
silentTranslationWarn: false, // true - warning off silentTranslationWarn: false, // true - warning off
silentFallbackWarn: true, silentFallbackWarn: true,

View File

@ -20,6 +20,9 @@ import { transformRouteToMenu } from '/@/utils/helper/menuHelper';
import { useMessage } from '/@/hooks/web/useMessage'; import { useMessage } from '/@/hooks/web/useMessage';
// import { warn } from '/@/utils/log'; // import { warn } from '/@/utils/log';
import { useI18n } from '/@/hooks/web/useI18n';
const { t } = useI18n('sys.app');
const { createMessage } = useMessage(); const { createMessage } = useMessage();
const NAME = 'permission'; const NAME = 'permission';
@ -101,7 +104,7 @@ class Permission extends VuexModule {
} else if (permissionMode === PermissionModeEnum.BACK) { } else if (permissionMode === PermissionModeEnum.BACK) {
const messageKey = 'loadMenu'; const messageKey = 'loadMenu';
createMessage.loading({ createMessage.loading({
content: '菜单加载中...', content: t('menuLoading'),
key: messageKey, key: messageKey,
duration: 1, duration: 1,
}); });

View File

@ -21,6 +21,7 @@ import { loginApi, getUserInfoById } from '/@/api/sys/user';
import { setLocal, getLocal, getSession, setSession } from '/@/utils/helper/persistent'; import { setLocal, getLocal, getSession, setSession } from '/@/utils/helper/persistent';
import { useProjectSetting } from '/@/hooks/setting'; import { useProjectSetting } from '/@/hooks/setting';
import { useI18n } from '/@/hooks/web/useI18n';
export type UserInfo = Omit<GetUserInfoByUserIdModel, 'roles'>; export type UserInfo = Omit<GetUserInfoByUserIdModel, 'roles'>;
@ -29,6 +30,8 @@ hotModuleUnregisterModule(NAME);
const { permissionCacheType } = useProjectSetting(); const { permissionCacheType } = useProjectSetting();
const { t } = useI18n('sys.app');
function getCache<T>(key: string) { function getCache<T>(key: string) {
const fn = permissionCacheType === CacheTypeEnum.LOCAL ? getLocal : getSession; const fn = permissionCacheType === CacheTypeEnum.LOCAL ? getLocal : getSession;
return fn(key) as T; return fn(key) as T;
@ -144,8 +147,8 @@ class User extends VuexModule {
const { createConfirm } = useMessage(); const { createConfirm } = useMessage();
createConfirm({ createConfirm({
iconType: 'warning', iconType: 'warning',
title: '温馨提醒', title: t('loginOutTip'),
content: '是否确认退出系统?', content: t('loginOutMessage'),
onOk: async () => { onOk: async () => {
await this.loginOut(true); await this.loginOut(true);
}, },

View File

@ -1,7 +1,10 @@
import { useMessage } from '/@/hooks/web/useMessage'; import { useMessage } from '/@/hooks/web/useMessage';
import { userStore } from '/@/store/modules/user'; import { userStore } from '/@/store/modules/user';
import { useI18n } from '/@/hooks/web/useI18n';
const { createMessage } = useMessage(); const { createMessage } = useMessage();
const { t } = useI18n('sys.api');
const error = createMessage.error!; const error = createMessage.error!;
export function checkStatus(status: number, msg: string): void { export function checkStatus(status: number, msg: string): void {
switch (status) { switch (status) {
@ -12,39 +15,39 @@ export function checkStatus(status: number, msg: string): void {
// 未登录则跳转登录页面,并携带当前页面的路径 // 未登录则跳转登录页面,并携带当前页面的路径
// 在登录成功后返回当前页面,这一步需要在登录页操作。 // 在登录成功后返回当前页面,这一步需要在登录页操作。
case 401: case 401:
error('用户没有权限(令牌、用户名、密码错误)!'); error(t('errMsg401'));
userStore.loginOut(true); userStore.loginOut(true);
break; break;
case 403: case 403:
error('用户得到授权,但是访问是被禁止的。!'); error(t('errMsg403'));
break; break;
// 404请求不存在 // 404请求不存在
case 404: case 404:
error('网络请求错误,未找到该资源!'); error(t('errMsg404'));
break; break;
case 405: case 405:
error('网络请求错误,请求方法未允许!'); error(t('errMsg405'));
break; break;
case 408: case 408:
error('网络请求超时!'); error(t('errMsg408'));
break; break;
case 500: case 500:
error('服务器错误,请联系管理员!'); error(t('errMsg500'));
break; break;
case 501: case 501:
error('网络未实现!'); error(t('errMsg501'));
break; break;
case 502: case 502:
error('网络错误!'); error(t('errMsg502'));
break; break;
case 503: case 503:
error('服务不可用,服务器暂时过载或维护!'); error(t('errMsg503'));
break; break;
case 504: case 504:
error('网络超时!'); error(t('errMsg504'));
break; break;
case 505: case 505:
error('http版本不支持该请求!'); error(t('errMsg505'));
break; break;
default: default:
} }

View File

@ -20,7 +20,9 @@ import { formatRequestDate } from '/@/utils/dateUtil';
import { setObjToUrlParams, deepMerge } from '/@/utils'; import { setObjToUrlParams, deepMerge } from '/@/utils';
import { errorStore } from '/@/store/modules/error'; import { errorStore } from '/@/store/modules/error';
import { errorResult } from './const'; import { errorResult } from './const';
import { useI18n } from '/@/hooks/web/useI18n';
const { t } = useI18n('sys.api');
const globSetting = useGlobSetting(); const globSetting = useGlobSetting();
const prefix = globSetting.urlPrefix; const prefix = globSetting.urlPrefix;
const { createMessage, createErrorModal } = useMessage(); const { createMessage, createErrorModal } = useMessage();
@ -55,7 +57,7 @@ const transform: AxiosTransform = {
if (message) { if (message) {
// errorMessageMode=modal的时候会显示modal错误弹窗而不是消息提示用于一些比较重要的错误 // errorMessageMode=modal的时候会显示modal错误弹窗而不是消息提示用于一些比较重要的错误
if (options.errorMessageMode === 'modal') { if (options.errorMessageMode === 'modal') {
createErrorModal({ title: '错误提示', content: message }); createErrorModal({ title: t('errorTip'), content: message });
} else { } else {
createMessage.error(message); createMessage.error(message);
} }
@ -74,7 +76,7 @@ const transform: AxiosTransform = {
createMessage.error(data.message); createMessage.error(data.message);
Promise.reject(new Error(message)); Promise.reject(new Error(message));
} else { } else {
const msg = '操作失败,系统异常!'; const msg = t('errorMessage');
createMessage.error(msg); createMessage.error(msg);
Promise.reject(new Error(msg)); Promise.reject(new Error(msg));
} }
@ -82,9 +84,9 @@ const transform: AxiosTransform = {
} }
// 登录超时 // 登录超时
if (code === ResultEnum.TIMEOUT) { if (code === ResultEnum.TIMEOUT) {
const timeoutMsg = '登录超时,请重新登录!'; const timeoutMsg = t('timeoutMessage');
createErrorModal({ createErrorModal({
title: '操作失败', title: t('operationFailed'),
content: timeoutMsg, content: timeoutMsg,
}); });
Promise.reject(new Error(timeoutMsg)); Promise.reject(new Error(timeoutMsg));
@ -159,12 +161,12 @@ const transform: AxiosTransform = {
const err: string = error.toString(); const err: string = error.toString();
try { try {
if (code === 'ECONNABORTED' && message.indexOf('timeout') !== -1) { if (code === 'ECONNABORTED' && message.indexOf('timeout') !== -1) {
createMessage.error('接口请求超时,请刷新页面重试!'); createMessage.error(t('apiTimeoutMessage'));
} }
if (err && err.includes('Network Error')) { if (err && err.includes('Network Error')) {
createErrorModal({ createErrorModal({
title: '网络异常', title: t('networkException'),
content: '请检查您的网络连接是否正常!', content: t('networkExceptionMsg'),
}); });
} }
} catch (error) { } catch (error) {

View File

@ -3,8 +3,8 @@
<div class="login-mask" /> <div class="login-mask" />
<div class="login-form-wrap"> <div class="login-form-wrap">
<div class="login-form mx-6"> <div class="login-form mx-6">
<AppLocalePicker v-if="showLocale" class="login-form__locale" />
<div class="login-form__content px-2 py-10"> <div class="login-form__content px-2 py-10">
<AppLocalePicker v-if="showLocale" class="login-form__locale" />
<header> <header>
<img :src="logo" class="mr-4" /> <img :src="logo" class="mr-4" />
<h1>{{ title }}</h1> <h1>{{ title }}</h1>
@ -158,9 +158,16 @@
}, },
}); });
</script> </script>
<style lang="less" scoped> <style lang="less">
@import (reference) '../../../design/index.less'; @import (reference) '../../../design/index.less';
.login-form__locale {
position: absolute;
top: 14px;
right: 14px;
z-index: 1;
}
.login { .login {
position: relative; position: relative;
height: 100vh; height: 100vh;
@ -178,7 +185,9 @@
} }
&-form { &-form {
width: 520px; position: relative;
bottom: 60px;
width: 400px;
background: @white; background: @white;
border: 10px solid rgba(255, 255, 255, 0.5); border: 10px solid rgba(255, 255, 255, 0.5);
border-width: 8px; border-width: 8px;
@ -192,26 +201,20 @@
right: 0; right: 0;
display: flex; display: flex;
width: 100%; width: 100%;
height: 90%; height: 100%;
// height: 90%;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
.respond-to(large, { .respond-to(xlarge, {
width: 600px; justify-content: flex-end;
right: calc(50% - 270px);
}); });
.respond-to(xlarge, { width: 540px; right:0});
}
&__locale {
position: absolute;
top: 10px;
right: 10px;
} }
&__content { &__content {
position: relative; position: relative;
width: 100%; width: 100%;
height: 100%; height: 100%;
padding: 60px 0 40px 0;
border: 1px solid #999; border: 1px solid #999;
border-radius: 2px; border-radius: 2px;
@ -228,7 +231,6 @@
h1 { h1 {
margin-bottom: 0; margin-bottom: 0;
font-size: 24px; font-size: 24px;
// color: @primary-color;
text-align: center; text-align: center;
} }
} }