yarn add vue-i18n
yarn add js-cookie
yarn add @types/js-cookie
src下新建i18n
文件夹,该文件夹下新建lang和pages文件夹,
lang文件夹下新建en.ts
// 定义内容
export default {
router: {
home: 'home',
system: {
system: 'system',
menu: 'systemMenu',
role: 'systemRole',
user: 'systemUser',
dic: 'systemDic',
city: 'systemDept'
},
personal: 'personal',
},
staticRoutes: {
signIn: 'signIn',
notFound: 'notFound',
noPower: 'noPower',
},
user: {
title0: 'Component size',
title1: 'Language switching',
title2: 'Menu search',
title3: 'Layout configuration',
title4: 'news',
title5: 'Full screen on',
title6: 'Full screen off',
dropdownLarge: 'large',
dropdownDefault: 'default',
dropdownSmall: 'small',
dropdown1: 'home page',
dropdown2: 'Personal Center',
dropdown3: '404',
dropdown4: '401',
dropdown5: 'Log out',
dropdown6: 'Code warehouse',
searchPlaceholder: 'Menu search: support Chinese, routing path',
newTitle: 'notice',
newBtn: 'All read',
newGo: 'Go to the notification center',
newDesc: 'No notice',
logOutTitle: 'Tips',
logOutMessage: 'This operation will log out. Do you want to continue?',
logOutConfirm: 'determine',
logOutCancel: 'cancel',
logOutExit: 'Exiting',
},
tagsView: {
refresh: 'refresh',
close: 'close',
closeOther: 'closeOther',
closeAll: 'closeAll',
fullscreen: 'fullscreen',
closeFullscreen: 'closeFullscreen',
},
notFound: {
foundTitle: 'Wrong address input, please re-enter the address~',
foundMsg: 'You can check the web address first, and then re-enter or give us feedback.',
foundBtn: 'Back to home page',
},
noAccess: {
accessTitle: 'You are not authorized to operate~',
accessMsg: 'Contact information: add QQ group discussion 665452019',
accessBtn: 'Reauthorization',
},
layout: {
configTitle: 'Layout configuration',
oneTitle: 'Global Themes',
twoTopTitle: 'top bar set up',
twoMenuTitle: 'Menu set up',
twoColumnsTitle: 'Columns set up',
twoTopBar: 'Top bar background',
twoTopBarColor: 'Top bar default font color',
twoIsTopBarColorGradual: 'Top bar gradient',
twoMenuBar: 'Menu background',
twoMenuBarColor: 'Menu default font color',
twoIsMenuBarColorGradual: 'Menu gradient',
twoColumnsMenuBar: 'Column menu background',
twoColumnsMenuBarColor: 'Default font color bar menu',
twoIsColumnsMenuBarColorGradual: 'Column gradient',
twoIsColumnsMenuHoverPreload: 'Column Menu Hover Preload',
threeTitle: 'Interface settings',
threeIsCollapse: 'Menu horizontal collapse',
threeIsUniqueOpened: 'Menu accordion',
threeIsFixedHeader: 'Fixed header',
threeIsClassicSplitMenu: 'Classic layout split menu',
threeIsLockScreen: 'Open the lock screen',
threeLockScreenTime: 'screen locking(s/s)',
fourTitle: 'Interface display',
fourIsShowLogo: 'Sidebar logo',
fourIsBreadcrumb: 'Open breadcrumb',
fourIsBreadcrumbIcon: 'Open breadcrumb icon',
fourIsTagsview: 'Open tagsview',
fourIsTagsviewIcon: 'Open tagsview Icon',
fourIsCacheTagsView: 'Enable tagsview cache',
fourIsSortableTagsView: 'Enable tagsview drag',
fourIsShareTagsView: 'Enable tagsview sharing',
fourIsFooter: 'Open footer',
fourIsGrayscale: 'Grey model',
fourIsInvert: 'Color weak mode',
fourIsDark: 'Dark Mode',
fourIsWartermark: 'Turn on watermark',
fourWartermarkText: 'Watermark copy',
fiveTitle: 'Other settings',
fiveTagsStyle: 'Tagsview style',
fiveAnimation: 'page animation',
fiveColumnsAsideStyle: 'Column style',
fiveColumnsAsideLayout: 'Column layout',
sixTitle: 'Layout switch',
sixDefaults: 'One',
sixClassic: 'Two',
sixTransverse: 'Three',
sixColumns: 'Four',
tipText: 'Click the button below to copy the layout configuration to `/src/stores/themeConfig.ts` It has been modified in.',
copyText: 'replication configuration',
resetText: 'restore default',
copyTextSuccess: 'Copy succeeded!',
copyTextError: 'Copy failed!',
},
};
lang文件夹下新建zh-cn.ts
// 定义内容
export default {
router: {
home: '首页',
system: {
system: '系统设置',
menu: '菜单管理',
role: '角色管理',
user: '用户管理',
dic: '字典管理',
city: '城市管理'
},
personal: '个人中心',
},
staticRoutes: {
signIn: '登录',
notFound: '找不到此页面',
noPower: '没有权限',
},
user: {
title0: '组件大小',
title1: '语言切换',
title2: '菜单搜索',
title3: '布局配置',
title4: '消息',
title5: '开全屏',
title6: '关全屏',
dropdownLarge: '大型',
dropdownDefault: '默认',
dropdownSmall: '小型',
dropdown1: '首页',
dropdown2: '个人中心',
dropdown3: '404',
dropdown4: '401',
dropdown5: '退出登录',
dropdown6: '代码仓库',
searchPlaceholder: '菜单搜索:支持中文、路由路径',
newTitle: '通知',
newBtn: '全部已读',
newGo: '前往通知中心',
newDesc: '暂无通知',
logOutTitle: '提示',
logOutMessage: '此操作将退出登录, 是否继续?',
logOutConfirm: '确定',
logOutCancel: '取消',
logOutExit: '退出中',
},
tagsView: {
refresh: '刷新',
close: '关闭',
closeOther: '关闭其它',
closeAll: '全部关闭',
fullscreen: '当前页全屏',
closeFullscreen: '关闭全屏',
},
notFound: {
foundTitle: '地址输入错误,请重新输入地址~',
foundMsg: '您可以先检查网址,然后重新输入或给我们反馈问题。',
foundBtn: '返回首页',
},
noAccess: {
accessTitle: '您未被授权,没有操作权限~',
accessMsg: '联系方式:加QQ群探讨 665452019',
accessBtn: '重新授权',
},
layout: {
configTitle: '布局配置',
oneTitle: '全局主题',
twoTopTitle: '顶栏设置',
twoMenuTitle: '菜单设置',
twoColumnsTitle: '分栏设置',
twoTopBar: '顶栏背景',
twoTopBarColor: '顶栏默认字体颜色',
twoIsTopBarColorGradual: '顶栏背景渐变',
twoMenuBar: '菜单背景',
twoMenuBarColor: '菜单默认字体颜色',
twoIsMenuBarColorGradual: '菜单背景渐变',
twoColumnsMenuBar: '分栏菜单背景',
twoColumnsMenuBarColor: '分栏菜单默认字体颜色',
twoIsColumnsMenuBarColorGradual: '分栏菜单背景渐变',
twoIsColumnsMenuHoverPreload: '分栏菜单鼠标悬停预加载',
threeTitle: '界面设置',
threeIsCollapse: '菜单水平折叠',
threeIsUniqueOpened: '菜单手风琴',
threeIsFixedHeader: '固定 Header',
threeIsClassicSplitMenu: '经典布局分割菜单',
threeIsLockScreen: '开启锁屏',
threeLockScreenTime: '自动锁屏(s/秒)',
fourTitle: '界面显示',
fourIsShowLogo: '侧边栏 Logo',
fourIsBreadcrumb: '开启 Breadcrumb',
fourIsBreadcrumbIcon: '开启 Breadcrumb 图标',
fourIsTagsview: '开启 Tagsview',
fourIsTagsviewIcon: '开启 Tagsview 图标',
fourIsCacheTagsView: '开启 TagsView 缓存',
fourIsSortableTagsView: '开启 TagsView 拖拽',
fourIsShareTagsView: '开启 TagsView 共用',
fourIsFooter: '开启 Footer',
fourIsGrayscale: '灰色模式',
fourIsInvert: '色弱模式',
fourIsDark: '深色模式',
fourIsWartermark: '开启水印',
fourWartermarkText: '水印文案',
fiveTitle: '其它设置',
fiveTagsStyle: 'Tagsview 风格',
fiveAnimation: '主页面切换动画',
fiveColumnsAsideStyle: '分栏高亮风格',
fiveColumnsAsideLayout: '分栏布局风格',
sixTitle: '布局切换',
sixDefaults: '默认',
sixClassic: '经典',
sixTransverse: '横向',
sixColumns: '分栏',
tipText: '点击下方按钮,复制布局配置去 `src/stores/themeConfig.ts` 中修改。',
copyText: '一键复制配置',
resetText: '一键恢复默认',
copyTextSuccess: '复制成功!',
copyTextError: '复制失败!',
},
};
pages下新建login文件夹,该文件下新建en.ts和zh-cn.ts
// 定义内容
export default {
label: {
one1: 'User name login',
two2: 'Mobile number',
},
link: {
one3: 'Third party login',
two4: 'Links',
},
account: {
accountPlaceholder1: 'The user name admin or not is common',
accountPlaceholder2: 'Password: 123456',
accountPlaceholder3: 'Please enter the verification code',
accountBtnText: 'Sign in',
},
mobile: {
placeholder1: 'Please input mobile phone number',
placeholder2: 'Please enter the verification code',
codeText: 'Get code',
btnText: 'Sign in',
msgText:
'Warm tip: it is recommended to use Google, Microsoft edge, version 79.0.1072.62 and above browsers, and 360 browser, please use speed mode',
},
scan: {
text: 'Open the mobile phone to scan and quickly log in / register',
},
signInText: 'welcome back!',
};
zh-cn.ts
// 定义内容
export default {
label: {
one1: '用户名登录',
two2: '手机号登录',
},
link: {
one3: '第三方登录',
two4: '友情链接',
},
account: {
accountPlaceholder1: '用户名 admin 或不输均为 common',
accountPlaceholder2: '密码:123456',
accountPlaceholder3: '请输入验证码',
accountBtnText: '登 录',
},
mobile: {
placeholder1: '请输入手机号',
placeholder2: '请输入验证码',
codeText: '获取验证码',
btnText: '登 录',
msgText: '* 温馨提示:建议使用谷歌、Microsoft Edge,版本 79.0.1072.62 及以上浏览器,360浏览器请使用极速模式',
},
scan: {
text: '打开手机扫一扫,快速登录/注册',
},
signInText: '欢迎回来!',
};
stores下interface下新建index.ts
//定义接口来定义对象的类型 `stores` 全部类型定义在这里
/**
* 用户信息
*/
export interface UserInfosState {
authBtnList: string[];
photo: string;
time: number;
userName: string;
roleId: number;
}
export interface UserInfosStates {
userInfos: UserInfosState;
}
/**
* 路由缓存列表
*/
export interface KeepAliveNamesState {
keepAliveNames: string[];
cachedViews: string[];
}
/**
* 后端返回原始路由(未处理时)
*/
export interface RequestOldRoutesState {
requestOldRoutes: string[];
}
/**
* TagsView 路由列表
*/
export interface TagsViewRoutesState {
tagsViewRoutes: string[];
isTagsViewCurrenFull: Boolean;
}
/**
* 路由列表
*/
export interface RoutesListState {
routesList: string[];
isColumnsMenuHover: Boolean;
isColumnsNavHover: Boolean;
}
/**
* 布局配置
*/
export interface ThemeConfigState {
passwordKey: string;
isDrawer: boolean;
primary: string;
topBar: string;
topBarColor: string;
isTopBarColorGradual: boolean;
menuBar: string;
menuBarColor: string;
isMenuBarColorGradual: boolean;
columnsMenuBar: string;
columnsMenuBarColor: string;
isColumnsMenuBarColorGradual: boolean;
isColumnsMenuHoverPreload: boolean;
isCollapse: boolean;
isUniqueOpened: boolean;
isFixedHeader: boolean;
isFixedHeaderChange: boolean;
isClassicSplitMenu: boolean;
isLockScreen: boolean;
lockScreenTime: number;
isShowLogo: boolean;
isShowLogoChange: boolean;
isBreadcrumb: boolean;
isTagsview: boolean;
isBreadcrumbIcon: boolean;
isTagsviewIcon: boolean;
isCacheTagsView: boolean;
isSortableTagsView: boolean;
isShareTagsView: boolean;
isFooter: boolean;
isGrayscale: boolean;
isInvert: boolean;
isIsDark: boolean;
isWartermark: boolean;
wartermarkText: string;
tagsStyle: string;
animation: string;
columnsAsideStyle: string;
columnsAsideLayout: string;
layout: string;
isRequestRoutes: boolean;
globalTitle: string;
globalViceTitle: string;
globalViceTitleMsg: string;
globalI18n: string;
globalComponentSize: string;
}
/**
* 布局配置
*/
export interface ThemeConfigStates {
themeConfig: ThemeConfigState;
}
stores下新建themeConfig.ts
import { defineStore } from 'pinia';
import { ThemeConfigStates, ThemeConfigState } from './interface';
export const useThemeConfig = defineStore('themeConfig', {
state: (): ThemeConfigStates => ({
themeConfig: {
//密码加密盐
passwordKey: `4vRk^ga52xVP$B2vYK$%r8a8hctLgbU9`,
isDrawer: false,
primary: '#409eff',
isIsDark: false,
topBar: '#ffffff',
topBarColor: '#606266',
isTopBarColorGradual: false,
menuBar: '#545c64',
menuBarColor: '#eaeaea',
isMenuBarColorGradual: false,
columnsMenuBar: '#545c64',
columnsMenuBarColor: '#e6e6e6',
isColumnsMenuBarColorGradual: false,
isColumnsMenuHoverPreload: false,
isCollapse: false,
isUniqueOpened: true,
isFixedHeader: false,
isFixedHeaderChange: false,
isClassicSplitMenu: false,
isLockScreen: false,
lockScreenTime: 30,
isShowLogo: true,
isShowLogoChange: false,
isBreadcrumb: true,
isTagsview: true,
isBreadcrumbIcon: true,
isTagsviewIcon: true,
isCacheTagsView: false,
isSortableTagsView: true,
isShareTagsView: false,
isFooter: true,
isGrayscale: false,
isInvert: false,
isWartermark: false,
wartermarkText: 'vue-next-admin',
tagsStyle: 'tags-style-five',
animation: 'opacitys',
columnsAsideStyle: 'columns-round',
columnsAsideLayout: 'columns-vertical',
layout: 'defaults',
isRequestRoutes: true,
globalTitle: '甜蜜蜜开放平台',
globalViceTitle: '甜蜜蜜开放平台',
globalViceTitleMsg: '专注、免费、开源、维护、解疑',
globalI18n: 'zh-cn',
globalComponentSize: 'large',
},
}),
actions: {
setThemeConfig(data: ThemeConfigState) {
this.themeConfig = data;
},
},
});
i18n文件下新建index.ts
import { createI18n } from 'vue-i18n';
import pinia from '@/stores/index';
import { storeToRefs } from 'pinia';
import { useThemeConfig } from '@/stores/themeConfig';
import zhcnLocale from 'element-plus/es/locale/lang/zh-cn';
import enLocale from 'element-plus/es/locale/lang/en';
import nextZhcn from '@/i18n/lang/zh-cn';
import nextEn from '@/i18n/lang/en';
import pagesLoginZhcn from '@/i18n/pages/login/zh-cn';
import pagesLoginEn from '@/i18n/pages/login/en';
// 定义语言国际化内容
/**
* 说明:
* /src/i18n/lang 下的 ts 为框架的国际化内容
* /src/i18n/pages 下的 ts 为各页面的国际化内容
*/
const messages = {
[zhcnLocale.name]: {
...zhcnLocale,
message: {
...nextZhcn,
...pagesLoginZhcn,
},
},
[enLocale.name]: {
...enLocale,
message: {
...nextEn,
...pagesLoginEn,
},
},
};
// 读取 pinia 默认语言
const stores = useThemeConfig(pinia);
const { themeConfig } = storeToRefs(stores);
// 导出语言国际化
//https://vue-i18n.intlify.dev/
// https://vue-i18n.intlify.dev/guide/essentials/fallback.html#explicit-fallback-with-one-locale
export const i18n = createI18n({
//是否在您的 Vue 应用程序上使用 vue-i18n Legacy API 模式,默认使用 Legacy API 模式。如果要使用Composition API模式,需要将其设置为false。
legacy: false,
//是否抑制本地化失败时输出的警告。如果为 true,则抑制本地化失败警告。如果您使用正则表达式,则可以抑制与翻译键(例如 t)匹配的本地化失败警告。
silentTranslationWarn: true,
//丢失的警告
missingWarn: false,
//当您的语言缺少键的翻译时,是否对翻译键进行模板插值。如果为 true,则跳过为您的“基本”语言编写模板;key是你的模板。
silentFallbackWarn: true,
//失败时的警告
fallbackWarn: false,
//当前语言,本地化的语言环境
locale: themeConfig.value.globalI18n,
//都失败的情况下使用的语言,此 VueI18n 实例正在使用的当前后备区域设置。
fallbackLocale: zhcnLocale.name,
messages,
});
utils下新建storage.ts
import Cookies from 'js-cookie';
/**
* window.localStorage 浏览器永久缓存
* @method set 设置永久缓存
* @method get 获取永久缓存
* @method remove 移除永久缓存
* @method clear 移除全部永久缓存
*/
export const Local = {
// 设置永久缓存
set(key: string, val: any) {
window.localStorage.setItem(key, JSON.stringify(val));
},
// 获取永久缓存
get(key: string) {
const json: any = window.localStorage.getItem(key);
return JSON.parse(json);
},
// 移除永久缓存
remove(key: string) {
window.localStorage.removeItem(key);
},
// 移除全部永久缓存
clear() {
window.localStorage.clear();
},
};
/**
* window.sessionStorage 浏览器临时缓存
* @method set 设置临时缓存
* @method get 获取临时缓存
* @method remove 移除临时缓存
* @method clear 移除全部临时缓存
*/
export const Session = {
// 设置临时缓存
set(key: string, val: any) {
if (key === 'token') return Cookies.set(key, val);
window.sessionStorage.setItem(key, JSON.stringify(val));
},
// 获取临时缓存
get(key: string) {
if (key === 'token') return Cookies.get(key);
const json: any = window.sessionStorage.getItem(key);
return JSON.parse(json);
},
// 移除临时缓存
remove(key: string) {
if (key === 'token') return Cookies.remove(key);
window.sessionStorage.removeItem(key);
},
// 移除全部临时缓存
clear() {
Cookies.remove('token');
window.sessionStorage.clear();
},
};
components下新建svgIcon该文件夹下新建index.vue
<template>
<i v-if="isShowIconSvg" class="el-icon" :style="setIconSvgStyle">
<component :is="getIconName" />
</i>
<div v-else-if="isShowIconImg" :style="setIconImgOutStyle">
<img :src="getIconName" :style="setIconSvgInsStyle" />
</div>
<i v-else :class="getIconName" :style="setIconSvgStyle" />
</template>
<script lang="ts">
import { computed, defineComponent } from 'vue';
export default defineComponent({
name: 'svgIcon',
props: {
// svg 图标组件名字
name: {
type: String,
},
// svg 大小
size: {
type: Number,
default: () => 14,
},
// svg 颜色
color: {
type: String,
},
},
setup(props) {
// 在线链接、本地引入地址前缀
const linesString = ['https', 'http', '/src', '/assets', import.meta.env.VITE_PUBLIC_PATH];
// 获取 icon 图标名称
const getIconName = computed(() => {
return props?.name;
});
// 用于判断 element plus 自带 svg 图标的显示、隐藏
const isShowIconSvg = computed(() => {
return props?.name?.startsWith('ele-');
});
// 用于判断在线链接、本地引入等图标显示、隐藏
const isShowIconImg = computed(() => {
return linesString.find((str) => props.name?.startsWith(str));
});
// 设置图标样式
const setIconSvgStyle = computed(() => {
return `font-size: ${props.size}px;color: ${props.color};`;
});
// 设置图片样式
const setIconImgOutStyle = computed(() => {
return `width: ${props.size}px;height: ${props.size}px;display: inline-block;overflow: hidden;`;
});
// 设置图片样式
// https://gitee.com/lyt-top/vue-next-admin/issues/I59ND0
const setIconSvgInsStyle = computed(() => {
const filterStyle: string[] = [];
const compatibles: string[] = ['-webkit', '-ms', '-o', '-moz'];
compatibles.forEach((j) => filterStyle.push(`${j}-filter: drop-shadow(${props.color} 30px 0);`));
return `width: ${props.size}px;height: ${props.size}px;position: relative;left: -${props.size}px;${filterStyle.join('')}`;
});
return {
getIconName,
isShowIconSvg,
isShowIconImg,
setIconSvgStyle,
setIconImgOutStyle,
setIconSvgInsStyle,
};
},
});
</script>
utils下新建other.ts
import { nextTick } from 'vue';
import type { App } from 'vue';
import * as svg from '@element-plus/icons-vue';
import router from '@/router/index';
import pinia from '@/stores/index';
import { storeToRefs } from 'pinia';
import { useThemeConfig } from '@/stores/themeConfig';
import { i18n } from '@/i18n/index';
import { Local } from '@/utils/storage';
import SvgIcon from '@/components/svgIcon/index.vue';
/**
* 导出全局注册 element plus svg 图标
* @param app vue 实例
* @description 使用:https://element-plus.gitee.io/zh-CN/component/icon.html
*/
export function elSvg(app: App) {
const icons = svg as any;
for (const i in icons) {
app.component(`ele-${icons[i].name}`, icons[i]);
}
app.component('SvgIcon', SvgIcon);
}
/**
* 设置浏览器标题国际化
* @method const title = useTitle(); ==> title()
*/
export function useTitle() {
const stores = useThemeConfig(pinia);
const { themeConfig } = storeToRefs(stores);
nextTick(() => {
let webTitle = '';
const globalTitle: string = themeConfig.value.globalTitle;
const { path, meta } = router.currentRoute.value;
if (path === '/login') {
webTitle = <any>meta.title;
} else {
webTitle = setTagsViewNameI18n(router.currentRoute.value);
}
document.title = `${webTitle} - ${globalTitle}` || globalTitle;
});
}
/**
* 设置 自定义 tagsView 名称、 自定义 tagsView 名称国际化
* @param params 路由 query、params 中的 tagsViewName
* @returns 返回当前 tagsViewName 名称
*/
export function setTagsViewNameI18n(item: any) {
let tagsViewName: any = '';
const { query, params, meta } = item;
if (query?.tagsViewName || params?.tagsViewName) {
if (/\/zh-cn|en|zh-tw\//.test(query?.tagsViewName) || /\/zh-cn|en|zh-tw\//.test(params?.tagsViewName)) {
// 国际化
const urlTagsParams = (query?.tagsViewName && JSON.parse(query?.tagsViewName)) || (params?.tagsViewName && JSON.parse(params?.tagsViewName));
tagsViewName = urlTagsParams[i18n.global.locale.value];
} else {
// 非国际化
tagsViewName = query?.tagsViewName || params?.tagsViewName;
}
} else {
// 非自定义 tagsView 名称
tagsViewName = i18n.global.t(<any>meta.title);
}
return tagsViewName;
}
/**
* 图片懒加载
* @param el dom 目标元素
* @param arr 列表数据
* @description data-xxx 属性用于存储页面或应用程序的私有自定义数据
*/
export const lazyImg = (el: any, arr: any) => {
const io = new IntersectionObserver((res) => {
res.forEach((v: any) => {
if (v.isIntersecting) {
const { img, key } = v.target.dataset;
v.target.src = img;
v.target.onload = () => {
io.unobserve(v.target);
arr[key]['loading'] = false;
};
}
});
});
nextTick(() => {
document.querySelectorAll(el).forEach((img) => io.observe(img));
});
};
/**
* 全局组件大小
* @returns 返回 `window.localStorage` 中读取的缓存值 `globalComponentSize`
*/
export const globalComponentSize = (): string => {
const stores = useThemeConfig(pinia);
const { themeConfig } = storeToRefs(stores);
return Local.get('themeConfig')?.globalComponentSize || themeConfig.value?.globalComponentSize;
};
/**
* 对象深克隆
* @param obj 源对象
* @returns 克隆后的对象
*/
export function deepClone(obj: any) {
let newObj: any;
try {
newObj = obj.push ? [] : {};
} catch (error) {
newObj = {};
}
for (const attr in obj) {
if (obj[attr] && typeof obj[attr] === 'object') {
newObj[attr] = deepClone(obj[attr]);
} else {
newObj[attr] = obj[attr];
}
}
return newObj;
}
/**
* 判断是否是移动端
*/
export function isMobile() {
if (
navigator.userAgent.match(
/('phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone')/i
)
) {
return true;
} else {
return false;
}
}
/**
* 判断数组对象中所有属性是否为空,为空则删除当前行对象
* @description @感谢大黄
* @param list 数组对象
* @returns 删除空值后的数组对象
*/
export function handleEmpty(list: any) {
const arr = [];
for (const i in list) {
const d = [];
for (const j in list[i]) {
d.push(list[i][j]);
}
const leng = d.filter((item) => item === '').length;
if (leng !== d.length) {
arr.push(list[i]);
}
}
return arr;
}
/**
* 统一批量导出
* @method elSvg 导出全局注册 element plus svg 图标
* @method useTitle 设置浏览器标题国际化
* @method setTagsViewNameI18n 设置 自定义 tagsView 名称、 自定义 tagsView 名称国际化
* @method lazyImg 图片懒加载
* @method globalComponentSize() element plus 全局组件大小
* @method deepClone 对象深克隆
* @method isMobile 判断是否是移动端
* @method handleEmpty 判断数组对象中所有属性是否为空,为空则删除当前行对象
*/
const other = {
elSvg: (app: App) => {
elSvg(app);
},
useTitle: () => {
useTitle();
},
setTagsViewNameI18n(route: any) {
return setTagsViewNameI18n(route);
},
lazyImg: (el: any, arr: any) => {
lazyImg(el, arr);
},
globalComponentSize: () => {
return globalComponentSize();
},
deepClone: (obj: any) => {
return deepClone(obj);
},
isMobile: () => {
return isMobile();
},
handleEmpty: (list: any) => {
return handleEmpty(list);
},
};
// 统一批量导出
export default other;
修改main.ts
import { createApp } from 'vue';
import pinia from '@/stores/index';
import App from './App.vue';
import router from '@/router/index';
import { i18n } from '@/i18n/index';
import ElementPlus from 'element-plus';
import 'element-plus/dist/index.css';
const app = createApp(App);
app.use(pinia).use(router).use(ElementPlus).use(i18n);
app.mount('#app');
修改App.vue
<script setup lang="ts">
import { useI18n } from 'vue-i18n';
import { computed } from 'vue';
import other from '@/utils/other';
// 获取全局组件大小
const getGlobalComponentSize = computed(() => {
return other.globalComponentSize();
});
const { messages, locale } = useI18n();
// 获取全局 i18n
const getGlobalI18n = computed(() => {
return messages.value[locale.value];
});
</script>
<template>
<!--https://element-plus.org/zh-CN/component/config-provider.html#api-->
<el-config-provider :size="getGlobalComponentSize" :locale="getGlobalI18n">
<el-table mb-1 :data="[]" />
<el-pagination :total="100" />
</el-config-provider>
</template>
<style scoped></style>
运行项目查看结果
yarn dev
修改为en就会变成英文
参考学习代码地址vue-next-admin