合并之前内容
This commit is contained in:
parent
f267e5e042
commit
d66544fc6e
|
@ -1,91 +0,0 @@
|
||||||
buttons:
|
|
||||||
pureLoginOut: LoginOut
|
|
||||||
pureLogin: Login
|
|
||||||
pureOpenSystemSet: Open System Configs
|
|
||||||
pureReload: Reload
|
|
||||||
pureCloseCurrentTab: Close CurrentTab
|
|
||||||
pureCloseLeftTabs: Close LeftTabs
|
|
||||||
pureCloseRightTabs: Close RightTabs
|
|
||||||
pureCloseOtherTabs: Close OtherTabs
|
|
||||||
pureCloseAllTabs: Close AllTabs
|
|
||||||
pureContentFullScreen: Content FullScreen
|
|
||||||
pureContentExitFullScreen: Content ExitFullScreen
|
|
||||||
pureClickCollapse: Collapse
|
|
||||||
pureClickExpand: Expand
|
|
||||||
pureConfirm: Confirm
|
|
||||||
pureSwitch: Switch
|
|
||||||
pureClose: Close
|
|
||||||
pureBackTop: BackTop
|
|
||||||
pureOpenText: Open
|
|
||||||
pureCloseText: Close
|
|
||||||
search:
|
|
||||||
pureTotal: Total
|
|
||||||
pureHistory: History
|
|
||||||
pureCollect: Collect
|
|
||||||
pureDragSort: (Drag Sort)
|
|
||||||
pureEmpty: Empty
|
|
||||||
purePlaceholder: Search Menu
|
|
||||||
panel:
|
|
||||||
pureSystemSet: System Configs
|
|
||||||
pureCloseSystemSet: Close System Configs
|
|
||||||
pureClearCacheAndToLogin: Clear cache and return to login page
|
|
||||||
pureClearCache: Clear Cache
|
|
||||||
pureOverallStyle: Overall Style
|
|
||||||
pureOverallStyleLight: Light
|
|
||||||
pureOverallStyleLightTip: Set sail freshly and light up the comfortable work interface
|
|
||||||
pureOverallStyleDark: Dark
|
|
||||||
pureOverallStyleDarkTip: Moonlight Overture, indulge in the tranquility and elegance of the night
|
|
||||||
pureOverallStyleSystem: Auto
|
|
||||||
pureOverallStyleSystemTip: Synchronize time, the interface naturally responds to morning and dusk
|
|
||||||
pureThemeColor: Theme Color
|
|
||||||
pureLayoutModel: Layout Model
|
|
||||||
pureVerticalTip: The menu on the left is familiar and friendly
|
|
||||||
pureHorizontalTip: Top menu, concise overview
|
|
||||||
pureMixTip: Mixed menu, flexible
|
|
||||||
pureStretch: Stretch Page
|
|
||||||
pureStretchFixed: Fixed
|
|
||||||
pureStretchFixedTip: Compact pages make it easy to find the information you need
|
|
||||||
pureStretchCustom: Custom
|
|
||||||
pureStretchCustomTip: Minimum 1280, maximum 1600
|
|
||||||
pureTagsStyle: Tags Style
|
|
||||||
pureTagsStyleSmart: Smart
|
|
||||||
pureTagsStyleSmartTip: Smart tags add fun and brilliance
|
|
||||||
pureTagsStyleCard: Card
|
|
||||||
pureTagsStyleCardTip: Card tags for efficient browsing
|
|
||||||
pureTagsStyleChrome: Chrome
|
|
||||||
pureTagsStyleChromeTip: Chrome style is classic and elegant
|
|
||||||
pureInterfaceDisplay: Interface Display
|
|
||||||
pureGreyModel: Grey Model
|
|
||||||
pureWeakModel: Weak Model
|
|
||||||
pureHiddenTags: Hidden Tags
|
|
||||||
pureHiddenFooter: Hidden Footer
|
|
||||||
pureMultiTagsCache: MultiTags Cache
|
|
||||||
menus:
|
|
||||||
pureHome: Home
|
|
||||||
pureLogin: Login
|
|
||||||
pureAbnormal: Abnormal Page
|
|
||||||
pureFourZeroFour: "404"
|
|
||||||
pureFourZeroOne: "403"
|
|
||||||
pureFive: "500"
|
|
||||||
purePermission: Permission Manage
|
|
||||||
purePermissionPage: Page Permission
|
|
||||||
purePermissionButton: Button Permission
|
|
||||||
purePermissionButtonRouter: Route return button permission
|
|
||||||
purePermissionButtonLogin: Login interface return button permission
|
|
||||||
status:
|
|
||||||
pureLoad: Loading...
|
|
||||||
pureMessage: Message
|
|
||||||
pureNotify: Notify
|
|
||||||
pureTodo: Todo
|
|
||||||
pureNoMessage: No Message
|
|
||||||
pureNoNotify: No Notify
|
|
||||||
pureNoTodo: No Todo
|
|
||||||
login:
|
|
||||||
pureUsername: Username
|
|
||||||
purePassword: Password
|
|
||||||
pureLogin: Login
|
|
||||||
pureLoginSuccess: Login Success
|
|
||||||
pureLoginFail: Login Fail
|
|
||||||
pureUsernameReg: Please enter username
|
|
||||||
purePassWordReg: Please enter password
|
|
||||||
purePassWordRuleReg: The password format should be any combination of 8-18 digits
|
|
|
@ -1,91 +0,0 @@
|
||||||
buttons:
|
|
||||||
pureLoginOut: 退出系统
|
|
||||||
pureLogin: 登录
|
|
||||||
pureOpenSystemSet: 打开系统配置
|
|
||||||
pureReload: 重新加载
|
|
||||||
pureCloseCurrentTab: 关闭当前标签页
|
|
||||||
pureCloseLeftTabs: 关闭左侧标签页
|
|
||||||
pureCloseRightTabs: 关闭右侧标签页
|
|
||||||
pureCloseOtherTabs: 关闭其他标签页
|
|
||||||
pureCloseAllTabs: 关闭全部标签页
|
|
||||||
pureContentFullScreen: 内容区全屏
|
|
||||||
pureContentExitFullScreen: 内容区退出全屏
|
|
||||||
pureClickCollapse: 点击折叠
|
|
||||||
pureClickExpand: 点击展开
|
|
||||||
pureConfirm: 确认
|
|
||||||
pureSwitch: 切换
|
|
||||||
pureClose: 关闭
|
|
||||||
pureBackTop: 回到顶部
|
|
||||||
pureOpenText: 开
|
|
||||||
pureCloseText: 关
|
|
||||||
search:
|
|
||||||
pureTotal: 共
|
|
||||||
pureHistory: 搜索历史
|
|
||||||
pureCollect: 收藏
|
|
||||||
pureDragSort: (可拖拽排序)
|
|
||||||
pureEmpty: 暂无搜索结果
|
|
||||||
purePlaceholder: 搜索菜单(支持拼音搜索)
|
|
||||||
panel:
|
|
||||||
pureSystemSet: 系统配置
|
|
||||||
pureCloseSystemSet: 关闭配置
|
|
||||||
pureClearCacheAndToLogin: 清空缓存并返回登录页
|
|
||||||
pureClearCache: 清空缓存
|
|
||||||
pureOverallStyle: 整体风格
|
|
||||||
pureOverallStyleLight: 浅色
|
|
||||||
pureOverallStyleLightTip: 清新启航,点亮舒适的工作界面
|
|
||||||
pureOverallStyleDark: 深色
|
|
||||||
pureOverallStyleDarkTip: 月光序曲,沉醉于夜的静谧雅致
|
|
||||||
pureOverallStyleSystem: 自动
|
|
||||||
pureOverallStyleSystemTip: 同步时光,界面随晨昏自然呼应
|
|
||||||
pureThemeColor: 主题色
|
|
||||||
pureLayoutModel: 导航模式
|
|
||||||
pureVerticalTip: 左侧菜单,亲切熟悉
|
|
||||||
pureHorizontalTip: 顶部菜单,简洁概览
|
|
||||||
pureMixTip: 混合菜单,灵活多变
|
|
||||||
pureStretch: 页宽
|
|
||||||
pureStretchFixed: 固定
|
|
||||||
pureStretchFixedTip: 紧凑页面,轻松找到所需信息
|
|
||||||
pureStretchCustom: 自定义
|
|
||||||
pureStretchCustomTip: 最小1280、最大1600
|
|
||||||
pureTagsStyle: 页签风格
|
|
||||||
pureTagsStyleSmart: 灵动
|
|
||||||
pureTagsStyleSmartTip: 灵动标签,添趣生辉
|
|
||||||
pureTagsStyleCard: 卡片
|
|
||||||
pureTagsStyleCardTip: 卡片标签,高效浏览
|
|
||||||
pureTagsStyleChrome: 谷歌
|
|
||||||
pureTagsStyleChromeTip: 谷歌风格,经典美观
|
|
||||||
pureInterfaceDisplay: 界面显示
|
|
||||||
pureGreyModel: 灰色模式
|
|
||||||
pureWeakModel: 色弱模式
|
|
||||||
pureHiddenTags: 隐藏标签页
|
|
||||||
pureHiddenFooter: 隐藏页脚
|
|
||||||
pureMultiTagsCache: 页签持久化
|
|
||||||
menus:
|
|
||||||
pureHome: 首页
|
|
||||||
pureLogin: 登录
|
|
||||||
pureAbnormal: 异常页面
|
|
||||||
pureFourZeroFour: "404"
|
|
||||||
pureFourZeroOne: "403"
|
|
||||||
pureFive: "500"
|
|
||||||
purePermission: 权限管理
|
|
||||||
purePermissionPage: 页面权限
|
|
||||||
purePermissionButton: 按钮权限
|
|
||||||
purePermissionButtonRouter: 路由返回按钮权限
|
|
||||||
purePermissionButtonLogin: 登录接口返回按钮权限
|
|
||||||
status:
|
|
||||||
pureLoad: 加载中...
|
|
||||||
pureMessage: 消息
|
|
||||||
pureNotify: 通知
|
|
||||||
pureTodo: 待办
|
|
||||||
pureNoMessage: 暂无消息
|
|
||||||
pureNoNotify: 暂无通知
|
|
||||||
pureNoTodo: 暂无待办
|
|
||||||
login:
|
|
||||||
pureUsername: 账号
|
|
||||||
purePassword: 密码
|
|
||||||
pureLogin: 登录
|
|
||||||
pureLoginSuccess: 登录成功
|
|
||||||
pureLoginFail: 登录失败
|
|
||||||
pureUsernameReg: 请输入账号
|
|
||||||
purePassWordReg: 请输入密码
|
|
||||||
purePassWordRuleReg: 密码格式应为8-18位数字、字母、符号的任意两种组合
|
|
|
@ -23,34 +23,25 @@ const permissionRouter = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/permission/button",
|
path: "/permission/button/router",
|
||||||
|
component: "permission/button/index",
|
||||||
|
name: "PermissionButtonRouter",
|
||||||
meta: {
|
meta: {
|
||||||
title: "menus.purePermissionButton",
|
title: "menus.purePermissionButtonRouter",
|
||||||
roles: ["admin", "common"]
|
auths: [
|
||||||
},
|
"permission:btn:add",
|
||||||
children: [
|
"permission:btn:edit",
|
||||||
{
|
"permission:btn:delete"
|
||||||
path: "/permission/button/router",
|
]
|
||||||
component: "permission/button/index",
|
}
|
||||||
name: "PermissionButtonRouter",
|
},
|
||||||
meta: {
|
{
|
||||||
title: "menus.purePermissionButtonRouter",
|
path: "/permission/button/login",
|
||||||
auths: [
|
component: "permission/button/perms",
|
||||||
"permission:btn:add",
|
name: "PermissionButtonLogin",
|
||||||
"permission:btn:edit",
|
meta: {
|
||||||
"permission:btn:delete"
|
title: "menus.purePermissionButtonLogin"
|
||||||
]
|
}
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: "/permission/button/login",
|
|
||||||
component: "permission/button/perms",
|
|
||||||
name: "PermissionButtonLogin",
|
|
||||||
meta: {
|
|
||||||
title: "menus.purePermissionButtonLogin"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { defineFakeRoute } from "vite-plugin-fake-server/client";
|
||||||
|
import en from "./i18n/en";
|
||||||
|
import zh from "./i18n/zh";
|
||||||
|
|
||||||
|
export default defineFakeRoute([
|
||||||
|
{
|
||||||
|
url: "/mock/getI18n",
|
||||||
|
method: "get",
|
||||||
|
response: () => {
|
||||||
|
return {
|
||||||
|
code: 200,
|
||||||
|
data: { zh, en, local: "zh" }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]);
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { buttons } from "./en/buttons";
|
||||||
|
import { search } from "./en/search";
|
||||||
|
import { panel } from "./en/panel";
|
||||||
|
import { menus } from "./en/menus";
|
||||||
|
import { status } from "./en/status";
|
||||||
|
import { login } from "./en/login";
|
||||||
|
import { style } from "./en/style";
|
||||||
|
import { system } from "./en/system";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "en",
|
||||||
|
buttons,
|
||||||
|
search,
|
||||||
|
panel,
|
||||||
|
menus,
|
||||||
|
status,
|
||||||
|
login,
|
||||||
|
style,
|
||||||
|
system
|
||||||
|
};
|
|
@ -0,0 +1,25 @@
|
||||||
|
export const buttons = {
|
||||||
|
openSystemSet: "Open System Configs",
|
||||||
|
pureOpenSystemSet: "pureOpenSystemSet",
|
||||||
|
|
||||||
|
pureAccountSettings: "Account",
|
||||||
|
pureLoginOut: "LoginOut",
|
||||||
|
pureLogin: "Login",
|
||||||
|
pureReload: "Reload",
|
||||||
|
pureCloseCurrentTab: "Close CurrentTab",
|
||||||
|
pureCloseLeftTabs: "Close LeftTabs",
|
||||||
|
pureCloseRightTabs: "Close RightTabs",
|
||||||
|
pureCloseOtherTabs: "Close OtherTabs",
|
||||||
|
pureCloseAllTabs: "Close AllTabs",
|
||||||
|
pureContentFullScreen: "Content FullScreen",
|
||||||
|
pureContentExitFullScreen: "Content ExitFullScreen",
|
||||||
|
pureClickCollapse: "Collapse",
|
||||||
|
pureClickExpand: "Expand",
|
||||||
|
confirm: "Confirm",
|
||||||
|
pureSwitch: "Switch",
|
||||||
|
close: "Close",
|
||||||
|
pureBackTop: "BackTop",
|
||||||
|
pureOpenText: "Open",
|
||||||
|
pureCloseText: "Close",
|
||||||
|
rest: "Rest"
|
||||||
|
};
|
|
@ -0,0 +1,40 @@
|
||||||
|
export const login = {
|
||||||
|
loginSuccess: "Login Success",
|
||||||
|
loginFail: "Login Fail",
|
||||||
|
usernameRegex: "please input username",
|
||||||
|
username: "input username",
|
||||||
|
password: "input password",
|
||||||
|
login: "Login",
|
||||||
|
|
||||||
|
email: "email",
|
||||||
|
repeatPassword: "Sure Password",
|
||||||
|
emailCode: "input email code",
|
||||||
|
verifyCode: "verify code",
|
||||||
|
emailRegex: "please input email",
|
||||||
|
passwordRegex: "please input password",
|
||||||
|
passwordSureRegex: "Please entr confirm password",
|
||||||
|
passwordDifferentRegex: "The two passwords do not match!",
|
||||||
|
emailCodeRegex: "please input email code",
|
||||||
|
getEmailCode: "get email code",
|
||||||
|
rememberMe: "days no need to login",
|
||||||
|
rememberInfo:
|
||||||
|
"After checking and logging in, will automatically log in to the system without entering your username and password within the specified number of days.",
|
||||||
|
forgetPassword: "Forget Password?",
|
||||||
|
getCodeInfo: "Seconds",
|
||||||
|
getVerifyCode: "Get VerifyCode",
|
||||||
|
definite: "definite",
|
||||||
|
back: "back",
|
||||||
|
passWordUpdateReg: "Password has been updated",
|
||||||
|
pureTip: 'After scanning the code, click "Confirm" to complete the login',
|
||||||
|
pureRegisterSuccess: "Regist Success",
|
||||||
|
pureTickPrivacy: "Please tick Privacy Policy",
|
||||||
|
pureReadAccept: "I have read it carefully and accept",
|
||||||
|
purePrivacyPolicy: "Privacy Policy",
|
||||||
|
pureVerifyCodeReg: "Please enter verify code",
|
||||||
|
pureVerifyCodeCorrectReg: "Please enter correct verify code",
|
||||||
|
pureVerifyCodeSixReg: "Please enter a 6-digit verify code",
|
||||||
|
purePhoneReg: "Please enter the phone",
|
||||||
|
purePhoneCorrectReg: "Please enter the correct phone number format",
|
||||||
|
purePassWordRuleReg:
|
||||||
|
"The password format should be any combination of 8-18 digits"
|
||||||
|
};
|
|
@ -0,0 +1,120 @@
|
||||||
|
export const menus = {
|
||||||
|
home: "Home",
|
||||||
|
purePermissionButtonRouter: "PermissionButtonRouter",
|
||||||
|
purePermissionButtonLogin: "purePermissionButtonLogin",
|
||||||
|
pureLogin: "Login",
|
||||||
|
pureEmpty: "Empty Page",
|
||||||
|
pureTable: "Table",
|
||||||
|
pureSysManagement: "System Manage",
|
||||||
|
pureUser: "User Manage",
|
||||||
|
pureRole: "Role Manage",
|
||||||
|
pureSystemMenu: "Menu Manage",
|
||||||
|
pureDept: "Dept Manage",
|
||||||
|
pureSysMonitor: "System Monitor",
|
||||||
|
pureOnlineUser: "Online User",
|
||||||
|
pureLoginLog: "Login Log",
|
||||||
|
pureOperationLog: "Operation Log",
|
||||||
|
pureSystemLog: "System Log",
|
||||||
|
pureEditor: "Editor",
|
||||||
|
pureAbnormal: "Abnormal Page",
|
||||||
|
pureFourZeroFour: "404",
|
||||||
|
pureFourZeroOne: "403",
|
||||||
|
pureFive: "500",
|
||||||
|
pureComponents: "Components",
|
||||||
|
pureDialog: "Dialog",
|
||||||
|
pureMessage: "Message Tips",
|
||||||
|
pureVideo: "Video",
|
||||||
|
pureSegmented: "Segmented",
|
||||||
|
pureWaterfall: "Waterfall",
|
||||||
|
pureMap: "Map",
|
||||||
|
pureDraggable: "Draggable",
|
||||||
|
pureSplitPane: "Split Pane",
|
||||||
|
pureText: "Text Ellipsis",
|
||||||
|
pureElButton: "Button",
|
||||||
|
pureButton: "Button Animation",
|
||||||
|
pureCheckButton: "Check Button",
|
||||||
|
pureCropping: "Picture Cropping",
|
||||||
|
pureAnimatecss: "AnimateCss Selector",
|
||||||
|
pureCountTo: "Digital Animation",
|
||||||
|
pureSelector: "Scope Selector",
|
||||||
|
pureFlowChart: "Flow Chart",
|
||||||
|
pureSeamless: "Seamless Scroll",
|
||||||
|
pureContextmenu: "Context Menu",
|
||||||
|
pureTypeit: "Typeit",
|
||||||
|
pureJsonEditor: "JSON Editor",
|
||||||
|
pureColorPicker: "Color Picker",
|
||||||
|
pureDatePicker: "Date Picker",
|
||||||
|
pureDateTimePicker: "DateTimePicker",
|
||||||
|
pureTimePicker: "TimePicker",
|
||||||
|
pureTag: "Tag",
|
||||||
|
pureStatistic: "Statistic",
|
||||||
|
pureCollapse: "Collapse",
|
||||||
|
pureGanttastic: "Gantt Chart",
|
||||||
|
pureProgress: "Progress",
|
||||||
|
pureUpload: "File Upload",
|
||||||
|
pureCheckCard: "CheckCard",
|
||||||
|
pureMenus: "MultiLevel Menu",
|
||||||
|
pureMenu1: "Menu1",
|
||||||
|
pureMenu2: "Menu2",
|
||||||
|
purePermission: "Permission Manage",
|
||||||
|
purePermissionPage: "Page Permission",
|
||||||
|
purePermissionButton: "Button Permission",
|
||||||
|
pureTabs: "Tabs Operate",
|
||||||
|
pureGuide: "Guide",
|
||||||
|
pureAble: "Able",
|
||||||
|
pureMenuTree: "Menu Tree",
|
||||||
|
pureVideoFrame: "Video Frame Capture",
|
||||||
|
pureWavesurfer: "Audio Visualization",
|
||||||
|
pureRipple: "Ripple",
|
||||||
|
pureMqtt: "Mqtt Client",
|
||||||
|
pureOptimize: "Debounce、Throttle、Copy、Longpress Directives",
|
||||||
|
pureVerify: "Captcha",
|
||||||
|
pureWatermark: "Water Mark",
|
||||||
|
purePrint: "Print",
|
||||||
|
pureDownload: "Download",
|
||||||
|
pureExternalPage: "External Page",
|
||||||
|
pureExternalDoc: "Docs External",
|
||||||
|
pureEmbeddedDoc: "Docs Embedded",
|
||||||
|
pureExternalLink: "Vue-Pure-Admin",
|
||||||
|
pureUtilsLink: "Pure-Admin-Utils",
|
||||||
|
pureColorHuntDoc: "ColorHunt",
|
||||||
|
pureUiGradients: "UiGradients",
|
||||||
|
pureEpDoc: "Element-Plus",
|
||||||
|
pureTailwindcssDoc: "Tailwindcss",
|
||||||
|
pureVueDoc: "Vue3",
|
||||||
|
pureViteDoc: "Vite",
|
||||||
|
purePiniaDoc: "Pinia",
|
||||||
|
pureRouterDoc: "Vue-Router",
|
||||||
|
pureAbout: "About",
|
||||||
|
pureResult: "Result Page",
|
||||||
|
pureSuccess: "Success Page",
|
||||||
|
pureFail: "Fail Page",
|
||||||
|
pureIconSelect: "Icon Select",
|
||||||
|
pureTimeline: "Time Line",
|
||||||
|
pureLineTree: "LineTree",
|
||||||
|
pureList: "List Page",
|
||||||
|
pureCardList: "Card List Page",
|
||||||
|
pureDebounce: "Debounce & Throttle",
|
||||||
|
pureFormDesign: "Form Design",
|
||||||
|
pureBarcode: "Barcode",
|
||||||
|
pureQrcode: "Qrcode",
|
||||||
|
pureCascader: "Area Cascader",
|
||||||
|
pureSwiper: "Swiper Plugin",
|
||||||
|
pureVirtualList: "Virtual List",
|
||||||
|
purePdf: "PDF Preview",
|
||||||
|
pureExcel: "Export Excel",
|
||||||
|
pureInfiniteScroll: "Table Infinite Scroll",
|
||||||
|
pureSensitive: "Sensitive Filter",
|
||||||
|
purePinyin: "PinYin",
|
||||||
|
pureDanmaku: "Danmaku",
|
||||||
|
pureSchemaForm: "Form",
|
||||||
|
pureTableBase: "Base Usage",
|
||||||
|
pureTableHigh: "High Usage",
|
||||||
|
pureTableEdit: "Edit Usage",
|
||||||
|
pureVxeTable: "Virtual Usage",
|
||||||
|
pureBoard: "Paint Board",
|
||||||
|
pureMindMap: "Mind Map",
|
||||||
|
pureMenuOverflow: "Menu Overflow Show Tooltip Text",
|
||||||
|
pureChildMenuOverflow: "Child Menu Overflow Show Tooltip Text",
|
||||||
|
systemctlTest: "Systemctl lTest"
|
||||||
|
};
|
|
@ -0,0 +1,38 @@
|
||||||
|
export const panel = {
|
||||||
|
pureSystemSet: "System Configs",
|
||||||
|
pureCloseSystemSet: "Close System Configs",
|
||||||
|
pureClearCacheAndToLogin: "Clear cache and return to login page",
|
||||||
|
pureClearCache: "Clear Cache",
|
||||||
|
pureOverallStyle: "Overall Style",
|
||||||
|
pureOverallStyleLight: "Light",
|
||||||
|
pureOverallStyleLightTip:
|
||||||
|
"Set sail freshly and light up the comfortable work interface",
|
||||||
|
pureOverallStyleDark: "Dark",
|
||||||
|
pureOverallStyleDarkTip:
|
||||||
|
"Moonlight Overture, indulge in the tranquility and elegance of the night",
|
||||||
|
pureOverallStyleSystem: "Auto",
|
||||||
|
pureOverallStyleSystemTip:
|
||||||
|
"Synchronize time, the interface naturally responds to morning and dusk",
|
||||||
|
pureThemeColor: "Theme Color",
|
||||||
|
pureLayoutModel: "Layout Model",
|
||||||
|
pureVerticalTip: "The menu on the left is familiar and friendly",
|
||||||
|
pureHorizontalTip: "Top menu, concise overview",
|
||||||
|
pureMixTip: "Mixed menu, flexible",
|
||||||
|
pureStretch: "Stretch Page",
|
||||||
|
pureStretchFixed: "Fixed",
|
||||||
|
pureStretchFixedTip:
|
||||||
|
"Compact pages make it easy to find the information you need",
|
||||||
|
pureStretchCustom: "Custom",
|
||||||
|
pureStretchCustomTip: "Minimum 1280, maximum 1600",
|
||||||
|
pureTagsStyle: "Tags Style",
|
||||||
|
pureTagsStyleSmart: "Smart",
|
||||||
|
pureTagsStyleSmartTip: "Smart tags add fun and brilliance",
|
||||||
|
pureTagsStyleCard: "Card",
|
||||||
|
pureTagsStyleCardTip: "Card tags for efficient browsing",
|
||||||
|
pureInterfaceDisplay: "Interface Display",
|
||||||
|
pureGreyModel: "Grey Model",
|
||||||
|
pureWeakModel: "Weak Model",
|
||||||
|
pureHiddenTags: "Hidden Tags",
|
||||||
|
pureHiddenFooter: "Hidden Footer",
|
||||||
|
pureMultiTagsCache: "MultiTags Cache"
|
||||||
|
};
|
|
@ -0,0 +1,8 @@
|
||||||
|
export const search = {
|
||||||
|
pureTotal: "Total",
|
||||||
|
pureHistory: "History",
|
||||||
|
pureCollect: "Collect",
|
||||||
|
pureDragSort: "(Drag Sort)",
|
||||||
|
pureEmpty: "Empty",
|
||||||
|
purePlaceholder: "Search Menu"
|
||||||
|
};
|
|
@ -0,0 +1,11 @@
|
||||||
|
export const status = {
|
||||||
|
pureLoad: "Loading...",
|
||||||
|
pureMessage: "Message",
|
||||||
|
pureNotify: "Notify",
|
||||||
|
pureTodo: "Todo",
|
||||||
|
pureNoMessage: "No Message",
|
||||||
|
pureNoNotify: "No Notify",
|
||||||
|
pureNoTodo: "No Todo",
|
||||||
|
enable: "enable",
|
||||||
|
disable: "disable"
|
||||||
|
};
|
|
@ -0,0 +1,5 @@
|
||||||
|
export const style = {
|
||||||
|
larger: "Larger",
|
||||||
|
default: "Default",
|
||||||
|
small: "Small"
|
||||||
|
};
|
|
@ -0,0 +1,8 @@
|
||||||
|
export const system = {
|
||||||
|
carousel: "carousel setting",
|
||||||
|
config: "system config",
|
||||||
|
favicon: "system favicon",
|
||||||
|
feedback: "system feedback",
|
||||||
|
emailUsers: "email users",
|
||||||
|
log: "system log"
|
||||||
|
};
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { buttons } from "./zh/buttons";
|
||||||
|
import { search } from "./zh/search";
|
||||||
|
import { panel } from "./zh/panel";
|
||||||
|
import { menus } from "./zh/menus";
|
||||||
|
import { status } from "./zh/status";
|
||||||
|
import { login } from "./zh/login";
|
||||||
|
import { style } from "./zh/style";
|
||||||
|
import { system } from "./zh/system";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "zh",
|
||||||
|
buttons,
|
||||||
|
search,
|
||||||
|
panel,
|
||||||
|
menus,
|
||||||
|
status,
|
||||||
|
login,
|
||||||
|
style,
|
||||||
|
system
|
||||||
|
};
|
|
@ -0,0 +1,26 @@
|
||||||
|
export const buttons = {
|
||||||
|
openSystemSet: "打开系统配置",
|
||||||
|
pureOpenSystemSet: "权限设定",
|
||||||
|
|
||||||
|
pureAccountSettings: "账户设置",
|
||||||
|
pureLoginOut: "退出系统",
|
||||||
|
pureLogin: "登录",
|
||||||
|
pureReload: "重新加载",
|
||||||
|
pureCloseCurrentTab: "关闭当前标签页",
|
||||||
|
pureCloseLeftTabs: "关闭左侧标签页",
|
||||||
|
pureCloseRightTabs: "关闭右侧标签页",
|
||||||
|
pureCloseOtherTabs: "关闭其他标签页",
|
||||||
|
pureCloseAllTabs: "关闭全部标签页",
|
||||||
|
pureContentFullScreen: "内容区全屏",
|
||||||
|
pureContentExitFullScreen: "内容区退出全屏",
|
||||||
|
pureClickCollapse: "点击折叠",
|
||||||
|
pureClickExpand: "点击展开",
|
||||||
|
confirm: "确认",
|
||||||
|
pureSwitch: "切换",
|
||||||
|
close: "关闭",
|
||||||
|
pureBackTop: "回到顶部",
|
||||||
|
pureOpenText: "开",
|
||||||
|
pureCloseText: "关",
|
||||||
|
rest: "重置",
|
||||||
|
search: "搜索"
|
||||||
|
};
|
|
@ -0,0 +1,38 @@
|
||||||
|
export const login = {
|
||||||
|
loginSuccess: "登录成功",
|
||||||
|
loginFail: "登录失败",
|
||||||
|
usernameRegex: "请输入账号",
|
||||||
|
username: "输入用户名",
|
||||||
|
password: "输入密码",
|
||||||
|
login: "登录",
|
||||||
|
|
||||||
|
email: "输入邮箱",
|
||||||
|
repeatPassword: "确认密码",
|
||||||
|
emailCode: "邮箱验证码",
|
||||||
|
verifyCode: "图形验证码",
|
||||||
|
emailRegex: "输入邮箱",
|
||||||
|
passwordRegex: "请输入密码",
|
||||||
|
passwordSureRegex: "请输入确认密码",
|
||||||
|
repeatPasswordRegex: "请输入确认密码",
|
||||||
|
passwordDifferentRegex: "两次密码不一致!",
|
||||||
|
emailCodeRegex: "请输入邮箱验证码",
|
||||||
|
verifyCodeRegex: "输入验证码",
|
||||||
|
getEmailCode: "获取邮箱验证码",
|
||||||
|
rememberMe: "天内免登录",
|
||||||
|
rememberInfo: "勾选并登录后,规定天数内无需输入用户名和密码会自动登入系统",
|
||||||
|
forgetPassword: "忘记密码?",
|
||||||
|
getVerifyCode: "获取验证码",
|
||||||
|
definite: "确定",
|
||||||
|
back: "返回",
|
||||||
|
getCodeInfo: "秒后重新获取",
|
||||||
|
passWordUpdateReg: "修改密码成功",
|
||||||
|
pureRegisterSuccess: "注册成功",
|
||||||
|
pureTickPrivacy: "请勾选隐私政策",
|
||||||
|
pureReadAccept: "我已仔细阅读并接受",
|
||||||
|
purePrivacyPolicy: "《隐私政策》",
|
||||||
|
pureVerifyCodeCorrectReg: "请输入正确的验证码",
|
||||||
|
pureVerifyCodeSixReg: "请输入6位数字验证码",
|
||||||
|
purePhoneReg: "请输入手机号码",
|
||||||
|
purePhoneCorrectReg: "请输入正确的手机号码格式",
|
||||||
|
purePassWordRuleReg: "密码格式应为8-18位数字、字母、符号的任意两种组合"
|
||||||
|
};
|
|
@ -0,0 +1,120 @@
|
||||||
|
export const menus = {
|
||||||
|
home: "首页",
|
||||||
|
purePermissionButtonRouter: "权限1",
|
||||||
|
purePermissionButtonLogin: "权限2",
|
||||||
|
pureLogin: "登录",
|
||||||
|
pureEmpty: "无Layout页",
|
||||||
|
pureTable: "表格",
|
||||||
|
pureSysManagement: "系统管理",
|
||||||
|
pureUser: "用户管理",
|
||||||
|
pureRole: "角色管理",
|
||||||
|
pureSystemMenu: "菜单管理",
|
||||||
|
pureDept: "部门管理",
|
||||||
|
pureSysMonitor: "系统监控",
|
||||||
|
pureOnlineUser: "在线用户",
|
||||||
|
pureLoginLog: "登录日志",
|
||||||
|
pureOperationLog: "操作日志",
|
||||||
|
pureSystemLog: "系统日志",
|
||||||
|
pureEditor: "编辑器",
|
||||||
|
pureAbnormal: "异常页面",
|
||||||
|
pureFourZeroFour: "404",
|
||||||
|
pureFourZeroOne: "403",
|
||||||
|
pureFive: "500",
|
||||||
|
pureComponents: "组件",
|
||||||
|
pureDialog: "函数式弹框",
|
||||||
|
pureMessage: "消息提示",
|
||||||
|
pureVideo: "视频",
|
||||||
|
pureSegmented: "分段控制器",
|
||||||
|
pureWaterfall: "瀑布流无限滚动",
|
||||||
|
pureMap: "地图",
|
||||||
|
pureDraggable: "拖拽",
|
||||||
|
pureSplitPane: "切割面板",
|
||||||
|
pureText: "文本省略",
|
||||||
|
pureElButton: "按钮",
|
||||||
|
pureCheckButton: "可选按钮",
|
||||||
|
pureButton: "按钮动效",
|
||||||
|
pureCropping: "图片裁剪",
|
||||||
|
pureAnimatecss: "animate.css选择器",
|
||||||
|
pureCountTo: "数字动画",
|
||||||
|
pureSelector: "范围选择器",
|
||||||
|
pureFlowChart: "流程图",
|
||||||
|
pureSeamless: "无缝滚动",
|
||||||
|
pureContextmenu: "右键菜单",
|
||||||
|
pureTypeit: "打字机",
|
||||||
|
pureJsonEditor: "JSON编辑器",
|
||||||
|
pureColorPicker: "颜色选择器",
|
||||||
|
pureDatePicker: "日期选择器",
|
||||||
|
pureDateTimePicker: "日期时间选择器",
|
||||||
|
pureTimePicker: "时间选择器",
|
||||||
|
pureTag: "标签",
|
||||||
|
pureStatistic: "统计组件",
|
||||||
|
pureCollapse: "折叠面板",
|
||||||
|
pureGanttastic: "甘特图",
|
||||||
|
pureProgress: "进度条",
|
||||||
|
pureUpload: "文件上传",
|
||||||
|
pureCheckCard: "多选卡片",
|
||||||
|
pureMenus: "多级菜单",
|
||||||
|
pureMenu1: "菜单1",
|
||||||
|
pureMenu2: "菜单2",
|
||||||
|
purePermission: "权限管理",
|
||||||
|
purePermissionPage: "页面权限",
|
||||||
|
purePermissionButton: "按钮权限",
|
||||||
|
pureTabs: "标签页操作",
|
||||||
|
pureGuide: "引导页",
|
||||||
|
pureAble: "功能",
|
||||||
|
pureMenuTree: "菜单树结构",
|
||||||
|
pureVideoFrame: "视频帧截取-wasm版",
|
||||||
|
pureWavesurfer: "音频可视化",
|
||||||
|
pureRipple: "波纹(Ripple)",
|
||||||
|
pureMqtt: "MQTT客户端(mqtt)",
|
||||||
|
pureOptimize: "防抖、截流、复制、长按指令",
|
||||||
|
pureVerify: "图形验证码",
|
||||||
|
pureWatermark: "水印",
|
||||||
|
purePrint: "打印",
|
||||||
|
pureDownload: "下载",
|
||||||
|
pureExternalPage: "外部页面",
|
||||||
|
pureExternalDoc: "文档外链",
|
||||||
|
pureEmbeddedDoc: "文档内嵌",
|
||||||
|
pureExternalLink: "vue-pure-admin",
|
||||||
|
pureUtilsLink: "pure-admin-utils",
|
||||||
|
pureColorHuntDoc: "调色板",
|
||||||
|
pureUiGradients: "渐变色",
|
||||||
|
pureEpDoc: "element-plus",
|
||||||
|
pureTailwindcssDoc: "tailwindcss",
|
||||||
|
pureVueDoc: "vue3",
|
||||||
|
pureViteDoc: "vite",
|
||||||
|
purePiniaDoc: "pinia",
|
||||||
|
pureRouterDoc: "vue-router",
|
||||||
|
pureAbout: "关于",
|
||||||
|
pureResult: "结果页面",
|
||||||
|
pureSuccess: "成功页面",
|
||||||
|
pureFail: "失败页面",
|
||||||
|
pureIconSelect: "图标选择器",
|
||||||
|
pureTimeline: "时间线",
|
||||||
|
pureLineTree: "树形连接线",
|
||||||
|
pureList: "列表页面",
|
||||||
|
pureCardList: "卡片列表页",
|
||||||
|
pureDebounce: "防抖节流",
|
||||||
|
pureFormDesign: "表单设计器",
|
||||||
|
pureBarcode: "条形码",
|
||||||
|
pureQrcode: "二维码",
|
||||||
|
pureCascader: "区域级联选择器",
|
||||||
|
pureSwiper: "Swiper插件",
|
||||||
|
pureVirtualList: "虚拟列表",
|
||||||
|
purePdf: "PDF预览",
|
||||||
|
pureExcel: "导出Excel",
|
||||||
|
pureInfiniteScroll: "表格无限滚动",
|
||||||
|
pureSensitive: "敏感词过滤",
|
||||||
|
purePinyin: "汉语拼音",
|
||||||
|
pureDanmaku: "弹幕",
|
||||||
|
pureSchemaForm: "表单",
|
||||||
|
pureTableBase: "基础用法",
|
||||||
|
pureTableHigh: "高级用法",
|
||||||
|
pureTableEdit: "可编辑用法",
|
||||||
|
pureVxeTable: "虚拟滚动",
|
||||||
|
pureBoard: "艺术画板",
|
||||||
|
pureMindMap: "思维导图",
|
||||||
|
pureMenuOverflow: "目录超出显示 Tooltip 文字提示",
|
||||||
|
pureChildMenuOverflow: "菜单超出显示 Tooltip 文字提示",
|
||||||
|
systemctlTest: "系统测试"
|
||||||
|
};
|
|
@ -0,0 +1,34 @@
|
||||||
|
export const panel = {
|
||||||
|
pureSystemSet: "系统配置",
|
||||||
|
pureCloseSystemSet: "关闭配置",
|
||||||
|
pureClearCacheAndToLogin: "清空缓存并返回登录页",
|
||||||
|
pureClearCache: "清空缓存",
|
||||||
|
pureOverallStyle: "整体风格",
|
||||||
|
pureOverallStyleLight: "浅色",
|
||||||
|
pureOverallStyleLightTip: "清新启航,点亮舒适的工作界面",
|
||||||
|
pureOverallStyleDark: "深色",
|
||||||
|
pureOverallStyleDarkTip: "月光序曲,沉醉于夜的静谧雅致",
|
||||||
|
pureOverallStyleSystem: "自动",
|
||||||
|
pureOverallStyleSystemTip: "同步时光,界面随晨昏自然呼应",
|
||||||
|
pureThemeColor: "主题色",
|
||||||
|
pureLayoutModel: "导航模式",
|
||||||
|
pureVerticalTip: "左侧菜单,亲切熟悉",
|
||||||
|
pureHorizontalTip: "顶部菜单,简洁概览",
|
||||||
|
pureMixTip: "混合菜单,灵活多变",
|
||||||
|
pureStretch: "页宽",
|
||||||
|
pureStretchFixed: "固定",
|
||||||
|
pureStretchFixedTip: "紧凑页面,轻松找到所需信息",
|
||||||
|
pureStretchCustom: "自定义",
|
||||||
|
pureStretchCustomTip: "最小1280、最大1600",
|
||||||
|
pureTagsStyle: "页签风格",
|
||||||
|
pureTagsStyleSmart: "灵动",
|
||||||
|
pureTagsStyleSmartTip: "灵动标签,添趣生辉",
|
||||||
|
pureTagsStyleCard: "卡片",
|
||||||
|
pureTagsStyleCardTip: "卡片标签,高效浏览",
|
||||||
|
pureInterfaceDisplay: "界面显示",
|
||||||
|
pureGreyModel: "灰色模式",
|
||||||
|
pureWeakModel: "色弱模式",
|
||||||
|
pureHiddenTags: "隐藏标签页",
|
||||||
|
pureHiddenFooter: "隐藏页脚",
|
||||||
|
pureMultiTagsCache: "页签持久化"
|
||||||
|
};
|
|
@ -0,0 +1,10 @@
|
||||||
|
export const search = {
|
||||||
|
search: {
|
||||||
|
pureTotal: "共",
|
||||||
|
pureHistory: "搜索历史",
|
||||||
|
pureCollect: "收藏",
|
||||||
|
pureDragSort: "(可拖拽排序)",
|
||||||
|
pureEmpty: "暂无搜索结果",
|
||||||
|
purePlaceholder: "搜索菜单(支持拼音搜索)"
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,11 @@
|
||||||
|
export const status = {
|
||||||
|
pureLoad: "加载中...",
|
||||||
|
pureMessage: "消息",
|
||||||
|
pureNotify: "通知",
|
||||||
|
pureTodo: "待办",
|
||||||
|
pureNoMessage: "暂无消息",
|
||||||
|
pureNoNotify: "暂无通知",
|
||||||
|
pureNoTodo: "暂无待办",
|
||||||
|
enable: "启用",
|
||||||
|
disable: "不启用"
|
||||||
|
};
|
|
@ -0,0 +1,5 @@
|
||||||
|
export const style = {
|
||||||
|
larger: "宽松",
|
||||||
|
default: "默认",
|
||||||
|
small: "紧凑"
|
||||||
|
};
|
|
@ -0,0 +1,8 @@
|
||||||
|
export const system = {
|
||||||
|
config: "系统设置",
|
||||||
|
carousel: "轮播图设置",
|
||||||
|
favicon: "图标设置",
|
||||||
|
feedback: "用户反馈",
|
||||||
|
emailUsers: "邮件用户",
|
||||||
|
log: "系统日志"
|
||||||
|
};
|
1181
pnpm-lock.yaml
1181
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
57
src/App.vue
57
src/App.vue
|
@ -5,23 +5,56 @@
|
||||||
</el-config-provider>
|
</el-config-provider>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts" setup>
|
||||||
import { defineComponent } from "vue";
|
|
||||||
import { ElConfigProvider } from "element-plus";
|
import { ElConfigProvider } from "element-plus";
|
||||||
|
import { computed, onMounted } from "vue";
|
||||||
import { ReDialog } from "@/components/BaseDialog";
|
import { ReDialog } from "@/components/BaseDialog";
|
||||||
import en from "element-plus/es/locale/lang/en";
|
import en from "element-plus/es/locale/lang/en";
|
||||||
import zhCn from "element-plus/es/locale/lang/zh-cn";
|
import zhCn from "element-plus/es/locale/lang/zh-cn";
|
||||||
|
import plusEn from "plus-pro-components/es/locale/lang/en";
|
||||||
|
import plusZhCn from "plus-pro-components/es/locale/lang/zh-cn";
|
||||||
|
import { useNav } from "@/layout/hooks/useNav";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
import { userI18nStore } from "@/store/i18n/i18n";
|
||||||
|
|
||||||
export default defineComponent({
|
const i18nStore = userI18nStore();
|
||||||
name: "app",
|
const i18n = useI18n();
|
||||||
components: {
|
const { $storage } = useNav();
|
||||||
[ElConfigProvider.name]: ElConfigProvider,
|
|
||||||
ReDialog
|
/**
|
||||||
},
|
* * 设置多语言内容
|
||||||
computed: {
|
*/
|
||||||
currentLocale() {
|
const setI18n = async () => {
|
||||||
return this.$storage.locale?.locale === "zh" ? zhCn : en;
|
await i18nStore.fetchI18n();
|
||||||
}
|
const languageData = JSON.parse(localStorage.getItem("i18nStore") as any);
|
||||||
|
// 初始化设置多语言内容
|
||||||
|
const locale = $storage.locale.locale;
|
||||||
|
// 如果本地没有语言版本,设置为服务端默认内容
|
||||||
|
if (locale == "" || locale == null || !locale) {
|
||||||
|
const local = languageData.i18n.local;
|
||||||
|
i18n.locale.value = local;
|
||||||
|
$storage.locale = { locale: local };
|
||||||
|
i18n.mergeLocaleMessage(local, languageData.i18n[local]);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i18n.locale.value = locale;
|
||||||
|
$storage.locale = { locale };
|
||||||
|
i18nStore.i18n.local = locale;
|
||||||
|
i18n.mergeLocaleMessage(locale, languageData.i18n[locale]);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* * 当前语言类别
|
||||||
|
*/
|
||||||
|
const currentLocale = computed(() => {
|
||||||
|
const languageData = JSON.parse(localStorage.getItem("i18nStore") as any);
|
||||||
|
const local = languageData ? languageData.i18n.local : {};
|
||||||
|
return local === "zh" ? { ...zhCn, ...plusZhCn } : { ...plusEn, ...en };
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
// 设置多语言
|
||||||
|
setI18n();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { http } from "@/api/service/mockRequest";
|
||||||
|
import type { Result } from "../../../../types/store/baseStoreState";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* * 获取多语言内容
|
||||||
|
*/
|
||||||
|
export const fetchGetI18n = () => {
|
||||||
|
return http.request<Result<object>>("get", "getI18n");
|
||||||
|
};
|
|
@ -1,4 +1,4 @@
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import { useNav } from "@/layout/hooks/useNav";
|
import { useNav } from "@/layout/hooks/useNav";
|
||||||
import LaySearch from "../lay-search/index.vue";
|
import LaySearch from "../lay-search/index.vue";
|
||||||
import LayNotice from "../lay-notice/index.vue";
|
import LayNotice from "../lay-notice/index.vue";
|
||||||
|
@ -9,10 +9,10 @@ import LaySidebarBreadCrumb from "../lay-sidebar/components/SidebarBreadCrumb.vu
|
||||||
import LaySidebarTopCollapse from "../lay-sidebar/components/SidebarTopCollapse.vue";
|
import LaySidebarTopCollapse from "../lay-sidebar/components/SidebarTopCollapse.vue";
|
||||||
|
|
||||||
import GlobalizationIcon from "@/assets/svg/globalization.svg?component";
|
import GlobalizationIcon from "@/assets/svg/globalization.svg?component";
|
||||||
import AccountSettingsIcon from "@iconify-icons/ri/user-settings-line";
|
|
||||||
import LogoutCircleRLine from "@iconify-icons/ri/logout-circle-r-line";
|
import LogoutCircleRLine from "@iconify-icons/ri/logout-circle-r-line";
|
||||||
import Setting from "@iconify-icons/ri/settings-3-line";
|
import Setting from "@iconify-icons/ri/settings-3-line";
|
||||||
import Check from "@iconify-icons/ep/check";
|
import Check from "@iconify-icons/ep/check";
|
||||||
|
import { $t } from "@/plugins/i18n";
|
||||||
|
|
||||||
const {
|
const {
|
||||||
layout,
|
layout,
|
||||||
|
@ -35,8 +35,8 @@ const { t, locale, translationCh, translationEn } = useTranslationLang();
|
||||||
<div class="navbar bg-[#fff] shadow-sm shadow-[rgba(0,21,41,0.08)]">
|
<div class="navbar bg-[#fff] shadow-sm shadow-[rgba(0,21,41,0.08)]">
|
||||||
<LaySidebarTopCollapse
|
<LaySidebarTopCollapse
|
||||||
v-if="device === 'mobile'"
|
v-if="device === 'mobile'"
|
||||||
class="hamburger-container"
|
|
||||||
:is-active="pureApp.sidebar.opened"
|
:is-active="pureApp.sidebar.opened"
|
||||||
|
class="hamburger-container"
|
||||||
@toggleClick="toggleSideBar"
|
@toggleClick="toggleSideBar"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
@ -58,20 +58,20 @@ const { t, locale, translationCh, translationEn } = useTranslationLang();
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<el-dropdown-menu class="translation">
|
<el-dropdown-menu class="translation">
|
||||||
<el-dropdown-item
|
<el-dropdown-item
|
||||||
:style="getDropdownItemStyle(locale, 'zh')"
|
|
||||||
:class="['dark:!text-white', getDropdownItemClass(locale, 'zh')]"
|
:class="['dark:!text-white', getDropdownItemClass(locale, 'zh')]"
|
||||||
|
:style="getDropdownItemStyle(locale, 'zh')"
|
||||||
@click="translationCh"
|
@click="translationCh"
|
||||||
>
|
>
|
||||||
<IconifyIconOffline
|
<IconifyIconOffline
|
||||||
v-show="locale === 'zh'"
|
v-show="locale === 'zh'"
|
||||||
class="check-zh"
|
|
||||||
:icon="Check"
|
:icon="Check"
|
||||||
|
class="check-zh"
|
||||||
/>
|
/>
|
||||||
简体中文
|
简体中文
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
<el-dropdown-item
|
<el-dropdown-item
|
||||||
:style="getDropdownItemStyle(locale, 'en')"
|
|
||||||
:class="['dark:!text-white', getDropdownItemClass(locale, 'en')]"
|
:class="['dark:!text-white', getDropdownItemClass(locale, 'en')]"
|
||||||
|
:style="getDropdownItemStyle(locale, 'en')"
|
||||||
@click="translationEn"
|
@click="translationEn"
|
||||||
>
|
>
|
||||||
<span v-show="locale === 'en'" class="check-en">
|
<span v-show="locale === 'en'" class="check-en">
|
||||||
|
@ -89,7 +89,7 @@ const { t, locale, translationCh, translationEn } = useTranslationLang();
|
||||||
<!-- 退出登录 -->
|
<!-- 退出登录 -->
|
||||||
<el-dropdown trigger="click">
|
<el-dropdown trigger="click">
|
||||||
<span class="el-dropdown-link navbar-bg-hover select-none">
|
<span class="el-dropdown-link navbar-bg-hover select-none">
|
||||||
<img :src="userAvatar" :style="avatarsStyle" />
|
<img :src="userAvatar" :style="avatarsStyle" alt="" />
|
||||||
<p v-if="username" class="dark:text-white">{{ username }}</p>
|
<p v-if="username" class="dark:text-white">{{ username }}</p>
|
||||||
</span>
|
</span>
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
|
@ -99,14 +99,14 @@ const { t, locale, translationCh, translationEn } = useTranslationLang();
|
||||||
:icon="LogoutCircleRLine"
|
:icon="LogoutCircleRLine"
|
||||||
style="margin: 5px"
|
style="margin: 5px"
|
||||||
/>
|
/>
|
||||||
{{ t("buttons.pureLoginOut") }}
|
{{ $t("buttons.pureLoginOut") }}
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
</el-dropdown-menu>
|
</el-dropdown-menu>
|
||||||
</template>
|
</template>
|
||||||
</el-dropdown>
|
</el-dropdown>
|
||||||
<span
|
<span
|
||||||
|
:title="$t('buttons.pureOpenSystemSet')"
|
||||||
class="set-icon navbar-bg-hover"
|
class="set-icon navbar-bg-hover"
|
||||||
:title="t('buttons.pureOpenSystemSet')"
|
|
||||||
@click="onPanel"
|
@click="onPanel"
|
||||||
>
|
>
|
||||||
<IconifyIconOffline :icon="Setting" />
|
<IconifyIconOffline :icon="Setting" />
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import { PropType } from "vue";
|
import { PropType } from "vue";
|
||||||
import { ListItem } from "../data";
|
import { ListItem } from "../data";
|
||||||
import NoticeItem from "./NoticeItem.vue";
|
import NoticeItem from "./NoticeItem.vue";
|
||||||
import { transformI18n } from "@/plugins/i18n";
|
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
list: {
|
list: {
|
||||||
|
@ -20,5 +19,5 @@ defineProps({
|
||||||
<div v-if="list.length">
|
<div v-if="list.length">
|
||||||
<NoticeItem v-for="(item, index) in list" :key="index" :noticeItem="item" />
|
<NoticeItem v-for="(item, index) in list" :key="index" :noticeItem="item" />
|
||||||
</div>
|
</div>
|
||||||
<el-empty v-else :description="transformI18n(emptyText)" />
|
<el-empty v-else :description="emptyText" />
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { ref, computed } from "vue";
|
import { computed, ref } from "vue";
|
||||||
import { noticesData } from "./data";
|
import { noticesData } from "./data";
|
||||||
import NoticeList from "./components/NoticeList.vue";
|
import NoticeList from "./components/NoticeList.vue";
|
||||||
import BellIcon from "@iconify-icons/ep/bell";
|
import BellIcon from "@iconify-icons/ep/bell";
|
||||||
|
@ -14,12 +14,12 @@ notices.value.map(v => (noticesNum.value += v.list.length));
|
||||||
|
|
||||||
const getLabel = computed(
|
const getLabel = computed(
|
||||||
() => item =>
|
() => item =>
|
||||||
t(item.name) + (item.list.length > 0 ? `(${item.list.length})` : "")
|
item.name + (item.list.length > 0 ? `(${item.list.length})` : "")
|
||||||
);
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<el-dropdown trigger="click" placement="bottom-end">
|
<el-dropdown placement="bottom-end" trigger="click">
|
||||||
<span
|
<span
|
||||||
:class="[
|
:class="[
|
||||||
'dropdown-badge',
|
'dropdown-badge',
|
||||||
|
@ -28,7 +28,7 @@ const getLabel = computed(
|
||||||
Number(noticesNum) !== 0 && 'mr-[10px]'
|
Number(noticesNum) !== 0 && 'mr-[10px]'
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
<el-badge :value="Number(noticesNum) === 0 ? '' : noticesNum" :max="99">
|
<el-badge :max="99" :value="Number(noticesNum) === 0 ? '' : noticesNum">
|
||||||
<span class="header-notice-icon">
|
<span class="header-notice-icon">
|
||||||
<IconifyIconOffline :icon="BellIcon" />
|
<IconifyIconOffline :icon="BellIcon" />
|
||||||
</span>
|
</span>
|
||||||
|
@ -39,8 +39,8 @@ const getLabel = computed(
|
||||||
<el-tabs
|
<el-tabs
|
||||||
v-model="activeKey"
|
v-model="activeKey"
|
||||||
:stretch="true"
|
:stretch="true"
|
||||||
class="dropdown-tabs"
|
|
||||||
:style="{ width: notices.length === 0 ? '200px' : '330px' }"
|
:style="{ width: notices.length === 0 ? '200px' : '330px' }"
|
||||||
|
class="dropdown-tabs"
|
||||||
>
|
>
|
||||||
<el-empty
|
<el-empty
|
||||||
v-if="notices.length === 0"
|
v-if="notices.length === 0"
|
||||||
|
@ -52,7 +52,7 @@ const getLabel = computed(
|
||||||
<el-tab-pane :label="getLabel(item)" :name="`${item.key}`">
|
<el-tab-pane :label="getLabel(item)" :name="`${item.key}`">
|
||||||
<el-scrollbar max-height="330px">
|
<el-scrollbar max-height="330px">
|
||||||
<div class="noticeList-container">
|
<div class="noticeList-container">
|
||||||
<NoticeList :list="item.list" :emptyText="item.emptyText" />
|
<NoticeList :emptyText="item.emptyText" :list="item.list" />
|
||||||
</div>
|
</div>
|
||||||
</el-scrollbar>
|
</el-scrollbar>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import { useRenderIcon } from "@/components/CommonIcon/src/hooks";
|
import { useRenderIcon } from "@/components/CommonIcon/src/hooks";
|
||||||
import { transformI18n } from "@/plugins/i18n";
|
|
||||||
import CloseIcon from "@iconify-icons/ep/close";
|
import CloseIcon from "@iconify-icons/ep/close";
|
||||||
import StarIcon from "@iconify-icons/ep/star";
|
import StarIcon from "@iconify-icons/ep/star";
|
||||||
import type { optionsItem } from "../types";
|
import type { optionsItem } from "../types";
|
||||||
|
import { $t } from "../../../../plugins/i18n";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
item: optionsItem;
|
item: optionsItem;
|
||||||
|
@ -11,6 +11,7 @@ interface Props {
|
||||||
|
|
||||||
interface Emits {
|
interface Emits {
|
||||||
(e: "collectItem", val: optionsItem): void;
|
(e: "collectItem", val: optionsItem): void;
|
||||||
|
|
||||||
(e: "deleteItem", val: optionsItem): void;
|
(e: "deleteItem", val: optionsItem): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +30,7 @@ function handleDelete(item) {
|
||||||
<template>
|
<template>
|
||||||
<component :is="useRenderIcon(item.meta?.icon)" />
|
<component :is="useRenderIcon(item.meta?.icon)" />
|
||||||
<span class="history-item-title">
|
<span class="history-item-title">
|
||||||
{{ transformI18n(item.meta?.title) }}
|
{{ $t(item.meta?.title) }}
|
||||||
</span>
|
</span>
|
||||||
<IconifyIconOffline
|
<IconifyIconOffline
|
||||||
v-show="item.type === 'history'"
|
v-show="item.type === 'history'"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import { match } from "pinyin-pro";
|
import { match } from "pinyin-pro";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { getConfig } from "@/config";
|
import { getConfig } from "@/config";
|
||||||
|
@ -6,14 +6,14 @@ import { useRouter } from "vue-router";
|
||||||
import SearchResult from "./SearchResult.vue";
|
import SearchResult from "./SearchResult.vue";
|
||||||
import SearchFooter from "./SearchFooter.vue";
|
import SearchFooter from "./SearchFooter.vue";
|
||||||
import { useNav } from "@/layout/hooks/useNav";
|
import { useNav } from "@/layout/hooks/useNav";
|
||||||
import { transformI18n } from "@/plugins/i18n";
|
|
||||||
import SearchHistory from "./SearchHistory.vue";
|
import SearchHistory from "./SearchHistory.vue";
|
||||||
import type { optionsItem, dragItem } from "../types";
|
import type { dragItem, optionsItem } from "../types";
|
||||||
import { ref, computed, shallowRef, watch } from "vue";
|
import { computed, ref, shallowRef, watch } from "vue";
|
||||||
import { useDebounceFn, onKeyStroke } from "@vueuse/core";
|
import { onKeyStroke, useDebounceFn } from "@vueuse/core";
|
||||||
import { usePermissionStoreHook } from "@/store/modules/permission";
|
import { usePermissionStoreHook } from "@/store/modules/permission";
|
||||||
import { cloneDeep, isAllEmpty, storageLocal } from "@pureadmin/utils";
|
import { cloneDeep, isAllEmpty, storageLocal } from "@pureadmin/utils";
|
||||||
import SearchIcon from "@iconify-icons/ri/search-line";
|
import SearchIcon from "@iconify-icons/ri/search-line";
|
||||||
|
import { $t } from "@/plugins/i18n";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
/** 弹窗显隐 */
|
/** 弹窗显隐 */
|
||||||
|
@ -95,12 +95,14 @@ function setStorageItem(key, value) {
|
||||||
/** 将菜单树形结构扁平化为一维数组,用于菜单查询 */
|
/** 将菜单树形结构扁平化为一维数组,用于菜单查询 */
|
||||||
function flatTree(arr) {
|
function flatTree(arr) {
|
||||||
const res = [];
|
const res = [];
|
||||||
|
|
||||||
function deep(arr) {
|
function deep(arr) {
|
||||||
arr.forEach(item => {
|
arr.forEach(item => {
|
||||||
res.push(item);
|
res.push(item);
|
||||||
item.children && deep(item.children);
|
item.children && deep(item.children);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
deep(arr);
|
deep(arr);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -110,13 +112,13 @@ function search() {
|
||||||
const flatMenusData = flatTree(menusData.value);
|
const flatMenusData = flatTree(menusData.value);
|
||||||
resultOptions.value = flatMenusData.filter(menu =>
|
resultOptions.value = flatMenusData.filter(menu =>
|
||||||
keyword.value
|
keyword.value
|
||||||
? transformI18n(menu.meta?.title)
|
? $t(menu.meta?.title)
|
||||||
.toLocaleLowerCase()
|
.toLocaleLowerCase()
|
||||||
.includes(keyword.value.toLocaleLowerCase().trim()) ||
|
.includes(keyword.value.toLocaleLowerCase().trim()) ||
|
||||||
(locale.value === "zh" &&
|
(locale.value === "zh" &&
|
||||||
!isAllEmpty(
|
!isAllEmpty(
|
||||||
match(
|
match(
|
||||||
transformI18n(menu.meta?.title).toLocaleLowerCase(),
|
$t(menu.meta?.title).toLocaleLowerCase(),
|
||||||
keyword.value.toLocaleLowerCase().trim()
|
keyword.value.toLocaleLowerCase().trim()
|
||||||
)
|
)
|
||||||
))
|
))
|
||||||
|
@ -276,24 +278,24 @@ onKeyStroke("ArrowDown", handleDown);
|
||||||
<template>
|
<template>
|
||||||
<el-dialog
|
<el-dialog
|
||||||
v-model="show"
|
v-model="show"
|
||||||
top="5vh"
|
|
||||||
class="pure-search-dialog"
|
|
||||||
:show-close="false"
|
|
||||||
:width="device === 'mobile' ? '80vw' : '40vw'"
|
|
||||||
:before-close="handleClose"
|
:before-close="handleClose"
|
||||||
|
:show-close="false"
|
||||||
:style="{
|
:style="{
|
||||||
borderRadius: '6px'
|
borderRadius: '6px'
|
||||||
}"
|
}"
|
||||||
|
:width="device === 'mobile' ? '80vw' : '40vw'"
|
||||||
append-to-body
|
append-to-body
|
||||||
@opened="inputRef.focus()"
|
class="pure-search-dialog"
|
||||||
|
top="5vh"
|
||||||
@closed="inputRef.blur()"
|
@closed="inputRef.blur()"
|
||||||
|
@opened="inputRef.focus()"
|
||||||
>
|
>
|
||||||
<el-input
|
<el-input
|
||||||
ref="inputRef"
|
ref="inputRef"
|
||||||
v-model="keyword"
|
v-model="keyword"
|
||||||
size="large"
|
|
||||||
clearable
|
|
||||||
:placeholder="t('search.purePlaceholder')"
|
:placeholder="t('search.purePlaceholder')"
|
||||||
|
clearable
|
||||||
|
size="large"
|
||||||
@input="handleSearch"
|
@input="handleSearch"
|
||||||
>
|
>
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
|
@ -312,8 +314,8 @@ onKeyStroke("ArrowDown", handleDown);
|
||||||
v-model:value="historyPath"
|
v-model:value="historyPath"
|
||||||
:options="historyOptions"
|
:options="historyOptions"
|
||||||
@click="handleEnter"
|
@click="handleEnter"
|
||||||
@delete="handleDelete"
|
|
||||||
@collect="handleCollect"
|
@collect="handleCollect"
|
||||||
|
@delete="handleDelete"
|
||||||
@drag="handleDrag"
|
@drag="handleDrag"
|
||||||
/>
|
/>
|
||||||
<SearchResult
|
<SearchResult
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import EnterOutlined from "@/assets/svg/enter_outlined.svg?component";
|
import EnterOutlined from "@/assets/svg/enter_outlined.svg?component";
|
||||||
import { useRenderIcon } from "@/components/CommonIcon/src/hooks";
|
import { useRenderIcon } from "@/components/CommonIcon/src/hooks";
|
||||||
import { transformI18n } from "@/plugins/i18n";
|
|
||||||
import { useEpThemeStoreHook } from "@/store/modules/epTheme";
|
import { useEpThemeStoreHook } from "@/store/modules/epTheme";
|
||||||
import { useResizeObserver } from "@pureadmin/utils";
|
import { useResizeObserver } from "@pureadmin/utils";
|
||||||
import { computed, getCurrentInstance, onMounted, ref } from "vue";
|
import { computed, getCurrentInstance, onMounted, ref } from "vue";
|
||||||
import type { Props } from "../types";
|
import type { Props } from "../types";
|
||||||
|
import { $t } from "../../../../plugins/i18n";
|
||||||
|
|
||||||
interface Emits {
|
interface Emits {
|
||||||
(e: "update:value", val: string): void;
|
(e: "update:value", val: string): void;
|
||||||
|
|
||||||
(e: "enter"): void;
|
(e: "enter"): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,14 +76,14 @@ defineExpose({ handleScroll });
|
||||||
v-for="(item, index) in options"
|
v-for="(item, index) in options"
|
||||||
:key="item.path"
|
:key="item.path"
|
||||||
:ref="'resultItemRef' + index"
|
:ref="'resultItemRef' + index"
|
||||||
class="result-item dark:bg-[#1d1d1d]"
|
|
||||||
:style="itemStyle(item)"
|
:style="itemStyle(item)"
|
||||||
|
class="result-item dark:bg-[#1d1d1d]"
|
||||||
@click="handleTo"
|
@click="handleTo"
|
||||||
@mouseenter="handleMouse(item)"
|
@mouseenter="handleMouse(item)"
|
||||||
>
|
>
|
||||||
<component :is="useRenderIcon(item.meta?.icon)" />
|
<component :is="useRenderIcon(item.meta?.icon)" />
|
||||||
<span class="result-item-title">
|
<span class="result-item-title">
|
||||||
{{ transformI18n(item.meta?.title) }}
|
{{ $t(item.meta?.title) }}
|
||||||
</span>
|
</span>
|
||||||
<EnterOutlined />
|
<EnterOutlined />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -234,8 +234,8 @@ const markOptions = computed<Array<OptionsType>>(() => {
|
||||||
value: "card"
|
value: "card"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t("panel.pureTagsStyleChrome"),
|
label: "panel.pureTagsStyleChrome",
|
||||||
tip: t("panel.pureTagsStyleChromeTip"),
|
tip: "panel.pureTagsStyleChromeTip",
|
||||||
value: "chrome"
|
value: "chrome"
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import { emitter } from "@/utils/mitt";
|
import { emitter } from "@/utils/mitt";
|
||||||
import { useNav } from "@/layout/hooks/useNav";
|
import { useNav } from "@/layout/hooks/useNav";
|
||||||
import LaySearch from "../lay-search/index.vue";
|
import LaySearch from "../lay-search/index.vue";
|
||||||
import LayNotice from "../lay-notice/index.vue";
|
import LayNotice from "../lay-notice/index.vue";
|
||||||
import { responsiveStorageNameSpace } from "@/config";
|
import { responsiveStorageNameSpace } from "@/config";
|
||||||
import { ref, nextTick, computed, onMounted } from "vue";
|
import { computed, nextTick, onMounted, ref } from "vue";
|
||||||
import { storageLocal, isAllEmpty } from "@pureadmin/utils";
|
import { isAllEmpty, storageLocal } from "@pureadmin/utils";
|
||||||
import { useTranslationLang } from "../../hooks/useTranslationLang";
|
import { useTranslationLang } from "../../hooks/useTranslationLang";
|
||||||
import { usePermissionStoreHook } from "@/store/modules/permission";
|
import { usePermissionStoreHook } from "@/store/modules/permission";
|
||||||
import LaySidebarItem from "../lay-sidebar/components/SidebarItem.vue";
|
import LaySidebarItem from "../lay-sidebar/components/SidebarItem.vue";
|
||||||
import LaySidebarFullScreen from "../lay-sidebar/components/SidebarFullScreen.vue";
|
import LaySidebarFullScreen from "../lay-sidebar/components/SidebarFullScreen.vue";
|
||||||
|
|
||||||
import GlobalizationIcon from "@/assets/svg/globalization.svg?component";
|
import GlobalizationIcon from "@/assets/svg/globalization.svg?component";
|
||||||
import AccountSettingsIcon from "@iconify-icons/ri/user-settings-line";
|
|
||||||
import LogoutCircleRLine from "@iconify-icons/ri/logout-circle-r-line";
|
import LogoutCircleRLine from "@iconify-icons/ri/logout-circle-r-line";
|
||||||
import Setting from "@iconify-icons/ri/settings-3-line";
|
import Setting from "@iconify-icons/ri/settings-3-line";
|
||||||
import Check from "@iconify-icons/ep/check";
|
import Check from "@iconify-icons/ep/check";
|
||||||
|
import { $t } from "@/plugins/i18n";
|
||||||
|
|
||||||
const menuRef = ref();
|
const menuRef = ref();
|
||||||
const showLogo = ref(
|
const showLogo = ref(
|
||||||
|
@ -65,16 +65,16 @@ onMounted(() => {
|
||||||
</div>
|
</div>
|
||||||
<el-menu
|
<el-menu
|
||||||
ref="menuRef"
|
ref="menuRef"
|
||||||
|
:default-active="defaultActive"
|
||||||
|
class="horizontal-header-menu"
|
||||||
mode="horizontal"
|
mode="horizontal"
|
||||||
popper-class="pure-scrollbar"
|
popper-class="pure-scrollbar"
|
||||||
class="horizontal-header-menu"
|
|
||||||
:default-active="defaultActive"
|
|
||||||
>
|
>
|
||||||
<LaySidebarItem
|
<LaySidebarItem
|
||||||
v-for="route in usePermissionStoreHook().wholeMenus"
|
v-for="route in usePermissionStoreHook().wholeMenus"
|
||||||
:key="route.path"
|
:key="route.path"
|
||||||
:item="route"
|
|
||||||
:base-path="route.path"
|
:base-path="route.path"
|
||||||
|
:item="route"
|
||||||
/>
|
/>
|
||||||
</el-menu>
|
</el-menu>
|
||||||
<div class="horizontal-header-right">
|
<div class="horizontal-header-right">
|
||||||
|
@ -88,8 +88,8 @@ onMounted(() => {
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<el-dropdown-menu class="translation">
|
<el-dropdown-menu class="translation">
|
||||||
<el-dropdown-item
|
<el-dropdown-item
|
||||||
:style="getDropdownItemStyle(locale, 'zh')"
|
|
||||||
:class="['dark:!text-white', getDropdownItemClass(locale, 'zh')]"
|
:class="['dark:!text-white', getDropdownItemClass(locale, 'zh')]"
|
||||||
|
:style="getDropdownItemStyle(locale, 'zh')"
|
||||||
@click="translationCh"
|
@click="translationCh"
|
||||||
>
|
>
|
||||||
<span v-show="locale === 'zh'" class="check-zh">
|
<span v-show="locale === 'zh'" class="check-zh">
|
||||||
|
@ -98,8 +98,8 @@ onMounted(() => {
|
||||||
简体中文
|
简体中文
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
<el-dropdown-item
|
<el-dropdown-item
|
||||||
:style="getDropdownItemStyle(locale, 'en')"
|
|
||||||
:class="['dark:!text-white', getDropdownItemClass(locale, 'en')]"
|
:class="['dark:!text-white', getDropdownItemClass(locale, 'en')]"
|
||||||
|
:style="getDropdownItemStyle(locale, 'en')"
|
||||||
@click="translationEn"
|
@click="translationEn"
|
||||||
>
|
>
|
||||||
<span v-show="locale === 'en'" class="check-en">
|
<span v-show="locale === 'en'" class="check-en">
|
||||||
|
@ -127,14 +127,14 @@ onMounted(() => {
|
||||||
:icon="LogoutCircleRLine"
|
:icon="LogoutCircleRLine"
|
||||||
style="margin: 5px"
|
style="margin: 5px"
|
||||||
/>
|
/>
|
||||||
{{ t("buttons.pureLoginOut") }}
|
{{ $t("buttons.pureLoginOut") }}
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
</el-dropdown-menu>
|
</el-dropdown-menu>
|
||||||
</template>
|
</template>
|
||||||
</el-dropdown>
|
</el-dropdown>
|
||||||
<span
|
<span
|
||||||
|
:title="$t('buttons.pureOpenSystemSet')"
|
||||||
class="set-icon navbar-bg-hover"
|
class="set-icon navbar-bg-hover"
|
||||||
:title="t('buttons.pureOpenSystemSet')"
|
|
||||||
@click="onPanel"
|
@click="onPanel"
|
||||||
>
|
>
|
||||||
<IconifyIconOffline :icon="Setting" />
|
<IconifyIconOffline :icon="Setting" />
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import { useRenderIcon } from "@/components/CommonIcon/src/hooks";
|
import { useRenderIcon } from "@/components/CommonIcon/src/hooks";
|
||||||
import { useNav } from "@/layout/hooks/useNav";
|
import { useNav } from "@/layout/hooks/useNav";
|
||||||
import { transformI18n } from "@/plugins/i18n";
|
|
||||||
import { findRouteByPath, getParentPaths } from "@/router/utils";
|
import { findRouteByPath, getParentPaths } from "@/router/utils";
|
||||||
import { usePermissionStoreHook } from "@/store/modules/permission";
|
import { usePermissionStoreHook } from "@/store/modules/permission";
|
||||||
import { isAllEmpty } from "@pureadmin/utils";
|
import { isAllEmpty } from "@pureadmin/utils";
|
||||||
|
@ -16,11 +15,13 @@ import GlobalizationIcon from "@/assets/svg/globalization.svg?component";
|
||||||
import Check from "@iconify-icons/ep/check";
|
import Check from "@iconify-icons/ep/check";
|
||||||
import LogoutCircleRLine from "@iconify-icons/ri/logout-circle-r-line";
|
import LogoutCircleRLine from "@iconify-icons/ri/logout-circle-r-line";
|
||||||
import Setting from "@iconify-icons/ri/settings-3-line";
|
import Setting from "@iconify-icons/ri/settings-3-line";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
import { $t } from "@/plugins/i18n";
|
||||||
|
|
||||||
const menuRef = ref();
|
const menuRef = ref();
|
||||||
const defaultActive = ref(null);
|
const defaultActive = ref(null);
|
||||||
|
const { t } = useI18n();
|
||||||
const { t, route, locale, translationCh, translationEn } =
|
const { route, locale, translationCh, translationEn } =
|
||||||
useTranslationLang(menuRef);
|
useTranslationLang(menuRef);
|
||||||
const {
|
const {
|
||||||
device,
|
device,
|
||||||
|
@ -68,11 +69,11 @@ watch(
|
||||||
>
|
>
|
||||||
<el-menu
|
<el-menu
|
||||||
ref="menuRef"
|
ref="menuRef"
|
||||||
router
|
:default-active="defaultActive"
|
||||||
|
class="horizontal-header-menu"
|
||||||
mode="horizontal"
|
mode="horizontal"
|
||||||
popper-class="pure-scrollbar"
|
popper-class="pure-scrollbar"
|
||||||
class="horizontal-header-menu"
|
router
|
||||||
:default-active="defaultActive"
|
|
||||||
>
|
>
|
||||||
<el-menu-item
|
<el-menu-item
|
||||||
v-for="route in usePermissionStoreHook().wholeMenus"
|
v-for="route in usePermissionStoreHook().wholeMenus"
|
||||||
|
@ -90,7 +91,7 @@ watch(
|
||||||
</div>
|
</div>
|
||||||
<div :style="getDivStyle">
|
<div :style="getDivStyle">
|
||||||
<span class="select-none">
|
<span class="select-none">
|
||||||
{{ transformI18n(route.meta.title) }}
|
{{ t(route.meta.title) }}
|
||||||
</span>
|
</span>
|
||||||
<LaySidebarExtraIcon :extraIcon="route.meta.extraIcon" />
|
<LaySidebarExtraIcon :extraIcon="route.meta.extraIcon" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -108,8 +109,8 @@ watch(
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<el-dropdown-menu class="translation">
|
<el-dropdown-menu class="translation">
|
||||||
<el-dropdown-item
|
<el-dropdown-item
|
||||||
:style="getDropdownItemStyle(locale, 'zh')"
|
|
||||||
:class="['dark:!text-white', getDropdownItemClass(locale, 'zh')]"
|
:class="['dark:!text-white', getDropdownItemClass(locale, 'zh')]"
|
||||||
|
:style="getDropdownItemStyle(locale, 'zh')"
|
||||||
@click="translationCh"
|
@click="translationCh"
|
||||||
>
|
>
|
||||||
<span v-show="locale === 'zh'" class="check-zh">
|
<span v-show="locale === 'zh'" class="check-zh">
|
||||||
|
@ -118,8 +119,8 @@ watch(
|
||||||
简体中文
|
简体中文
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
<el-dropdown-item
|
<el-dropdown-item
|
||||||
:style="getDropdownItemStyle(locale, 'en')"
|
|
||||||
:class="['dark:!text-white', getDropdownItemClass(locale, 'en')]"
|
:class="['dark:!text-white', getDropdownItemClass(locale, 'en')]"
|
||||||
|
:style="getDropdownItemStyle(locale, 'en')"
|
||||||
@click="translationEn"
|
@click="translationEn"
|
||||||
>
|
>
|
||||||
<span v-show="locale === 'en'" class="check-en">
|
<span v-show="locale === 'en'" class="check-en">
|
||||||
|
@ -147,14 +148,14 @@ watch(
|
||||||
:icon="LogoutCircleRLine"
|
:icon="LogoutCircleRLine"
|
||||||
style="margin: 5px"
|
style="margin: 5px"
|
||||||
/>
|
/>
|
||||||
{{ t("buttons.pureLoginOut") }}
|
{{ $t("buttons.pureLoginOut") }}
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
</el-dropdown-menu>
|
</el-dropdown-menu>
|
||||||
</template>
|
</template>
|
||||||
</el-dropdown>
|
</el-dropdown>
|
||||||
<span
|
<span
|
||||||
|
:title="$t('buttons.pureOpenSystemSet')"
|
||||||
class="set-icon navbar-bg-hover"
|
class="set-icon navbar-bg-hover"
|
||||||
:title="t('buttons.pureOpenSystemSet')"
|
|
||||||
@click="onPanel"
|
@click="onPanel"
|
||||||
>
|
>
|
||||||
<IconifyIconOffline :icon="Setting" />
|
<IconifyIconOffline :icon="Setting" />
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import { isEqual } from "@pureadmin/utils";
|
import { isEqual } from "@pureadmin/utils";
|
||||||
import { transformI18n } from "@/plugins/i18n";
|
|
||||||
import { useRoute, useRouter } from "vue-router";
|
import { useRoute, useRouter } from "vue-router";
|
||||||
import { ref, watch, onMounted, toRaw } from "vue";
|
import { onMounted, ref, toRaw, watch } from "vue";
|
||||||
import { getParentPaths, findRouteByPath } from "@/router/utils";
|
import { findRouteByPath, getParentPaths } from "@/router/utils";
|
||||||
import { useMultiTagsStoreHook } from "@/store/modules/multiTags";
|
import { useMultiTagsStoreHook } from "@/store/modules/multiTags";
|
||||||
|
import { $t } from "@/plugins/i18n";
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const levelList = ref([]);
|
const levelList = ref([]);
|
||||||
|
@ -113,7 +113,7 @@ watch(
|
||||||
class="!inline !items-stretch"
|
class="!inline !items-stretch"
|
||||||
>
|
>
|
||||||
<a @click.prevent="handleLink(item)">
|
<a @click.prevent="handleLink(item)">
|
||||||
{{ transformI18n(item.meta.title) }}
|
{{ $t(item.meta.title) }}
|
||||||
</a>
|
</a>
|
||||||
</el-breadcrumb-item>
|
</el-breadcrumb-item>
|
||||||
</transition-group>
|
</transition-group>
|
||||||
|
|
|
@ -4,7 +4,6 @@ import { ReText } from "@/components/Text";
|
||||||
import { getConfig } from "@/config";
|
import { getConfig } from "@/config";
|
||||||
import { useNav } from "@/layout/hooks/useNav";
|
import { useNav } from "@/layout/hooks/useNav";
|
||||||
import { menuType } from "@/layout/types";
|
import { menuType } from "@/layout/types";
|
||||||
import { transformI18n } from "@/plugins/i18n";
|
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import {
|
import {
|
||||||
computed,
|
computed,
|
||||||
|
@ -17,6 +16,7 @@ import {
|
||||||
import SidebarExtraIcon from "./SidebarExtraIcon.vue";
|
import SidebarExtraIcon from "./SidebarExtraIcon.vue";
|
||||||
import SidebarLinkItem from "./SidebarLinkItem.vue";
|
import SidebarLinkItem from "./SidebarLinkItem.vue";
|
||||||
|
|
||||||
|
import { $t } from "@/plugins/i18n";
|
||||||
import EpArrowDown from "@iconify-icons/ep/arrow-down-bold";
|
import EpArrowDown from "@iconify-icons/ep/arrow-down-bold";
|
||||||
import ArrowLeft from "@iconify-icons/ep/arrow-left-bold";
|
import ArrowLeft from "@iconify-icons/ep/arrow-left-bold";
|
||||||
import ArrowRight from "@iconify-icons/ep/arrow-right-bold";
|
import ArrowRight from "@iconify-icons/ep/arrow-right-bold";
|
||||||
|
@ -147,7 +147,7 @@ function resolvePath(routePath) {
|
||||||
class="!w-full !pl-4 !text-inherit"
|
class="!w-full !pl-4 !text-inherit"
|
||||||
truncated
|
truncated
|
||||||
>
|
>
|
||||||
{{ transformI18n(onlyOneChild.meta.title) }}
|
{{ $t(onlyOneChild.meta.title) }}
|
||||||
</el-text>
|
</el-text>
|
||||||
|
|
||||||
<template #title>
|
<template #title>
|
||||||
|
@ -159,7 +159,7 @@ function resolvePath(routePath) {
|
||||||
}"
|
}"
|
||||||
class="!w-full !text-inherit"
|
class="!w-full !text-inherit"
|
||||||
>
|
>
|
||||||
{{ transformI18n(onlyOneChild.meta.title) }}
|
{{ $t(onlyOneChild.meta.title) }}
|
||||||
</ReText>
|
</ReText>
|
||||||
<SidebarExtraIcon :extraIcon="onlyOneChild.meta.extraIcon" />
|
<SidebarExtraIcon :extraIcon="onlyOneChild.meta.extraIcon" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -206,7 +206,7 @@ function resolvePath(routePath) {
|
||||||
theme: tooltipEffect
|
theme: tooltipEffect
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
{{ transformI18n(item.meta.title) }}
|
{{ $t(item.meta.title) }}
|
||||||
</ReText>
|
</ReText>
|
||||||
<SidebarExtraIcon v-if="!isCollapse" :extraIcon="item.meta.extraIcon" />
|
<SidebarExtraIcon v-if="!isCollapse" :extraIcon="item.meta.extraIcon" />
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,28 +1,28 @@
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import { $t } from "@/plugins/i18n";
|
|
||||||
import { emitter } from "@/utils/mitt";
|
|
||||||
import { RouteConfigs } from "../../types";
|
|
||||||
import { useTags } from "../../hooks/useTag";
|
|
||||||
import { routerArrays } from "@/layout/types";
|
import { routerArrays } from "@/layout/types";
|
||||||
import { onClickOutside } from "@vueuse/core";
|
import { $t } from "@/plugins/i18n";
|
||||||
import TagChrome from "./components/TagChrome.vue";
|
import { getTopMenu, handleAliveRoute } from "@/router/utils";
|
||||||
import { handleAliveRoute, getTopMenu } from "@/router/utils";
|
|
||||||
import { useSettingStoreHook } from "@/store/modules/settings";
|
|
||||||
import { useMultiTagsStoreHook } from "@/store/modules/multiTags";
|
import { useMultiTagsStoreHook } from "@/store/modules/multiTags";
|
||||||
import { usePermissionStoreHook } from "@/store/modules/permission";
|
import { usePermissionStoreHook } from "@/store/modules/permission";
|
||||||
import { ref, watch, unref, toRaw, nextTick, onBeforeUnmount } from "vue";
|
import { useSettingStoreHook } from "@/store/modules/settings";
|
||||||
|
import { emitter } from "@/utils/mitt";
|
||||||
import {
|
import {
|
||||||
delay,
|
delay,
|
||||||
isEqual,
|
|
||||||
isAllEmpty,
|
isAllEmpty,
|
||||||
|
isEqual,
|
||||||
useResizeObserver
|
useResizeObserver
|
||||||
} from "@pureadmin/utils";
|
} from "@pureadmin/utils";
|
||||||
|
import { onClickOutside } from "@vueuse/core";
|
||||||
|
import { nextTick, onBeforeUnmount, ref, toRaw, unref, watch } from "vue";
|
||||||
|
import { useTags } from "../../hooks/useTag";
|
||||||
|
import { RouteConfigs } from "../../types";
|
||||||
|
import TagChrome from "./components/TagChrome.vue";
|
||||||
|
|
||||||
|
import ArrowDown from "@iconify-icons/ri/arrow-down-s-line";
|
||||||
|
import ArrowLeftSLine from "@iconify-icons/ri/arrow-left-s-line";
|
||||||
|
import ArrowRightSLine from "@iconify-icons/ri/arrow-right-s-line";
|
||||||
import ExitFullscreen from "@iconify-icons/ri/fullscreen-exit-fill";
|
import ExitFullscreen from "@iconify-icons/ri/fullscreen-exit-fill";
|
||||||
import Fullscreen from "@iconify-icons/ri/fullscreen-fill";
|
import Fullscreen from "@iconify-icons/ri/fullscreen-fill";
|
||||||
import ArrowDown from "@iconify-icons/ri/arrow-down-s-line";
|
|
||||||
import ArrowRightSLine from "@iconify-icons/ri/arrow-right-s-line";
|
|
||||||
import ArrowLeftSLine from "@iconify-icons/ri/arrow-left-s-line";
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
Close,
|
Close,
|
||||||
|
@ -51,7 +51,6 @@ const {
|
||||||
onMounted,
|
onMounted,
|
||||||
onMouseenter,
|
onMouseenter,
|
||||||
onMouseleave,
|
onMouseleave,
|
||||||
transformI18n,
|
|
||||||
onContentFullScreen
|
onContentFullScreen
|
||||||
} = useTags();
|
} = useTags();
|
||||||
|
|
||||||
|
@ -201,6 +200,7 @@ function dynamicRouteTag(value: string): void {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
concatPath(router.options.routes as any, value);
|
concatPath(router.options.routes as any, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -398,6 +398,7 @@ function showMenuModel(
|
||||||
} else {
|
} else {
|
||||||
currentIndex = allRoute.findIndex(v => isEqual(v.query, query));
|
currentIndex = allRoute.findIndex(v => isEqual(v.query, query));
|
||||||
}
|
}
|
||||||
|
|
||||||
function fixedTagDisabled() {
|
function fixedTagDisabled() {
|
||||||
if (allRoute[currentIndex]?.meta?.fixedTag) {
|
if (allRoute[currentIndex]?.meta?.fixedTag) {
|
||||||
Array.of(1, 2, 3, 4, 5).forEach(v => {
|
Array.of(1, 2, 3, 4, 5).forEach(v => {
|
||||||
|
@ -566,31 +567,31 @@ onBeforeUnmount(() => {
|
||||||
</span>
|
</span>
|
||||||
<div
|
<div
|
||||||
ref="scrollbarDom"
|
ref="scrollbarDom"
|
||||||
class="scroll-container"
|
|
||||||
:class="showModel === 'chrome' && 'chrome-scroll-container'"
|
:class="showModel === 'chrome' && 'chrome-scroll-container'"
|
||||||
|
class="scroll-container"
|
||||||
@wheel.prevent="handleWheel"
|
@wheel.prevent="handleWheel"
|
||||||
>
|
>
|
||||||
<div ref="tabDom" class="tab select-none" :style="getTabStyle">
|
<div ref="tabDom" :style="getTabStyle" class="tab select-none">
|
||||||
<div
|
<div
|
||||||
v-for="(item, index) in multiTags"
|
v-for="(item, index) in multiTags"
|
||||||
:ref="'dynamic' + index"
|
|
||||||
:key="index"
|
:key="index"
|
||||||
|
:ref="'dynamic' + index"
|
||||||
:class="[
|
:class="[
|
||||||
'scroll-item is-closable',
|
'scroll-item is-closable',
|
||||||
linkIsActive(item),
|
linkIsActive(item),
|
||||||
showModel === 'chrome' && 'chrome-item',
|
showModel === 'chrome' && 'chrome-item',
|
||||||
isFixedTag(item) && 'fixed-tag'
|
isFixedTag(item) && 'fixed-tag'
|
||||||
]"
|
]"
|
||||||
|
@click="tagOnClick(item)"
|
||||||
@contextmenu.prevent="openMenu(item, $event)"
|
@contextmenu.prevent="openMenu(item, $event)"
|
||||||
@mouseenter.prevent="onMouseenter(index)"
|
@mouseenter.prevent="onMouseenter(index)"
|
||||||
@mouseleave.prevent="onMouseleave(index)"
|
@mouseleave.prevent="onMouseleave(index)"
|
||||||
@click="tagOnClick(item)"
|
|
||||||
>
|
>
|
||||||
<template v-if="showModel !== 'chrome'">
|
<template v-if="showModel !== 'chrome'">
|
||||||
<span
|
<span
|
||||||
class="tag-title dark:!text-text_color_primary dark:hover:!text-primary"
|
class="tag-title dark:!text-text_color_primary dark:hover:!text-primary"
|
||||||
>
|
>
|
||||||
{{ transformI18n(item.meta.title) }}
|
{{ $t(item.meta.title) }}
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
v-if="
|
v-if="
|
||||||
|
@ -636,8 +637,8 @@ onBeforeUnmount(() => {
|
||||||
<transition name="el-zoom-in-top">
|
<transition name="el-zoom-in-top">
|
||||||
<ul
|
<ul
|
||||||
v-show="visible"
|
v-show="visible"
|
||||||
ref="contextmenuRef"
|
|
||||||
:key="Math.random()"
|
:key="Math.random()"
|
||||||
|
ref="contextmenuRef"
|
||||||
:style="getContextMenuStyle"
|
:style="getContextMenuStyle"
|
||||||
class="contextmenu"
|
class="contextmenu"
|
||||||
>
|
>
|
||||||
|
@ -648,15 +649,15 @@ onBeforeUnmount(() => {
|
||||||
>
|
>
|
||||||
<li v-if="item.show" @click="selectTag(key, item)">
|
<li v-if="item.show" @click="selectTag(key, item)">
|
||||||
<IconifyIconOffline :icon="item.icon" />
|
<IconifyIconOffline :icon="item.icon" />
|
||||||
{{ transformI18n(item.text) }}
|
{{ item.text }}
|
||||||
</li>
|
</li>
|
||||||
</div>
|
</div>
|
||||||
</ul>
|
</ul>
|
||||||
</transition>
|
</transition>
|
||||||
<!-- 右侧功能按钮 -->
|
<!-- 右侧功能按钮 -->
|
||||||
<el-dropdown
|
<el-dropdown
|
||||||
trigger="click"
|
|
||||||
placement="bottom-end"
|
placement="bottom-end"
|
||||||
|
trigger="click"
|
||||||
@command="handleCommand"
|
@command="handleCommand"
|
||||||
>
|
>
|
||||||
<span class="arrow-down">
|
<span class="arrow-down">
|
||||||
|
@ -668,11 +669,11 @@ onBeforeUnmount(() => {
|
||||||
v-for="(item, key) in tagsViews"
|
v-for="(item, key) in tagsViews"
|
||||||
:key="key"
|
:key="key"
|
||||||
:command="{ key, item }"
|
:command="{ key, item }"
|
||||||
:divided="item.divided"
|
|
||||||
:disabled="item.disabled"
|
:disabled="item.disabled"
|
||||||
|
:divided="item.divided"
|
||||||
>
|
>
|
||||||
<IconifyIconOffline :icon="item.icon" />
|
<IconifyIconOffline :icon="item.icon" />
|
||||||
{{ transformI18n(item.text) }}
|
{{ item.text }}
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
</el-dropdown-menu>
|
</el-dropdown-menu>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -6,7 +6,6 @@ import Avatar from "@/assets/user.jpg";
|
||||||
import { getTopMenu } from "@/router/utils";
|
import { getTopMenu } from "@/router/utils";
|
||||||
import { useFullscreen } from "@vueuse/core";
|
import { useFullscreen } from "@vueuse/core";
|
||||||
import type { routeMetaType } from "../types";
|
import type { routeMetaType } from "../types";
|
||||||
import { transformI18n } from "@/plugins/i18n";
|
|
||||||
import { remainingPaths, router } from "@/router";
|
import { remainingPaths, router } from "@/router";
|
||||||
import { computed, type CSSProperties } from "vue";
|
import { computed, type CSSProperties } from "vue";
|
||||||
import { useAppStoreHook } from "@/store/modules/app";
|
import { useAppStoreHook } from "@/store/modules/app";
|
||||||
|
@ -16,6 +15,7 @@ import { useEpThemeStoreHook } from "@/store/modules/epTheme";
|
||||||
import { usePermissionStoreHook } from "@/store/modules/permission";
|
import { usePermissionStoreHook } from "@/store/modules/permission";
|
||||||
import ExitFullscreen from "@iconify-icons/ri/fullscreen-exit-fill";
|
import ExitFullscreen from "@iconify-icons/ri/fullscreen-exit-fill";
|
||||||
import Fullscreen from "@iconify-icons/ri/fullscreen-fill";
|
import Fullscreen from "@iconify-icons/ri/fullscreen-fill";
|
||||||
|
import { $t } from "@/plugins/i18n";
|
||||||
|
|
||||||
const errorInfo =
|
const errorInfo =
|
||||||
"The current routing configuration is incorrect, please check the configuration";
|
"The current routing configuration is incorrect, please check the configuration";
|
||||||
|
@ -81,9 +81,7 @@ export function useNav() {
|
||||||
});
|
});
|
||||||
|
|
||||||
const { $storage, $config } = useGlobal<GlobalPropertiesApi>();
|
const { $storage, $config } = useGlobal<GlobalPropertiesApi>();
|
||||||
const layout = computed(() => {
|
const layout = computed(() => $storage?.layout?.layout);
|
||||||
return $storage?.layout?.layout;
|
|
||||||
});
|
|
||||||
|
|
||||||
const title = computed(() => {
|
const title = computed(() => {
|
||||||
return $config.Title;
|
return $config.Title;
|
||||||
|
@ -92,8 +90,8 @@ export function useNav() {
|
||||||
/** 动态title */
|
/** 动态title */
|
||||||
function changeTitle(meta: routeMetaType) {
|
function changeTitle(meta: routeMetaType) {
|
||||||
const Title = getConfig().Title;
|
const Title = getConfig().Title;
|
||||||
if (Title) document.title = `${transformI18n(meta.title)} | ${Title}`;
|
if (Title) document.title = `${meta.title} | ${Title}`;
|
||||||
else document.title = transformI18n(meta.title);
|
else document.title = $t(meta.title);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 退出登录 */
|
/** 退出登录 */
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
import {
|
import {
|
||||||
ref,
|
|
||||||
unref,
|
|
||||||
computed,
|
computed,
|
||||||
reactive,
|
|
||||||
onMounted,
|
|
||||||
type CSSProperties,
|
type CSSProperties,
|
||||||
getCurrentInstance
|
getCurrentInstance,
|
||||||
|
onMounted,
|
||||||
|
reactive,
|
||||||
|
ref,
|
||||||
|
unref
|
||||||
} from "vue";
|
} from "vue";
|
||||||
import type { tagsViewsType } from "../types";
|
import type { tagsViewsType } from "../types";
|
||||||
import { useRoute, useRouter } from "vue-router";
|
import { useRoute, useRouter } from "vue-router";
|
||||||
import { transformI18n, $t } from "@/plugins/i18n";
|
import { $t } from "@/plugins/i18n";
|
||||||
import { responsiveStorageNameSpace } from "@/config";
|
import { responsiveStorageNameSpace } from "@/config";
|
||||||
import { useSettingStoreHook } from "@/store/modules/settings";
|
import { useSettingStoreHook } from "@/store/modules/settings";
|
||||||
import { useMultiTagsStoreHook } from "@/store/modules/multiTags";
|
import { useMultiTagsStoreHook } from "@/store/modules/multiTags";
|
||||||
import {
|
import {
|
||||||
isEqual,
|
hasClass,
|
||||||
isBoolean,
|
isBoolean,
|
||||||
|
isEqual,
|
||||||
storageLocal,
|
storageLocal,
|
||||||
toggleClass,
|
toggleClass
|
||||||
hasClass
|
|
||||||
} from "@pureadmin/utils";
|
} from "@pureadmin/utils";
|
||||||
|
|
||||||
import Fullscreen from "@iconify-icons/ri/fullscreen-fill";
|
import Fullscreen from "@iconify-icons/ri/fullscreen-fill";
|
||||||
|
@ -73,35 +73,35 @@ export function useTags() {
|
||||||
icon: Close,
|
icon: Close,
|
||||||
text: $t("buttons.pureCloseCurrentTab"),
|
text: $t("buttons.pureCloseCurrentTab"),
|
||||||
divided: false,
|
divided: false,
|
||||||
disabled: multiTags.value.length > 1 ? false : true,
|
disabled: multiTags.value.length <= 1,
|
||||||
show: true
|
show: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: CloseLeftTags,
|
icon: CloseLeftTags,
|
||||||
text: $t("buttons.pureCloseLeftTabs"),
|
text: $t("buttons.pureCloseLeftTabs"),
|
||||||
divided: true,
|
divided: true,
|
||||||
disabled: multiTags.value.length > 1 ? false : true,
|
disabled: multiTags.value.length <= 1,
|
||||||
show: true
|
show: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: CloseRightTags,
|
icon: CloseRightTags,
|
||||||
text: $t("buttons.pureCloseRightTabs"),
|
text: $t("buttons.pureCloseRightTabs"),
|
||||||
divided: false,
|
divided: false,
|
||||||
disabled: multiTags.value.length > 1 ? false : true,
|
disabled: multiTags.value.length <= 1,
|
||||||
show: true
|
show: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: CloseOtherTags,
|
icon: CloseOtherTags,
|
||||||
text: $t("buttons.pureCloseOtherTabs"),
|
text: $t("buttons.pureCloseOtherTabs"),
|
||||||
divided: true,
|
divided: true,
|
||||||
disabled: multiTags.value.length > 2 ? false : true,
|
disabled: multiTags.value.length <= 2,
|
||||||
show: true
|
show: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: CloseAllTags,
|
icon: CloseAllTags,
|
||||||
text: $t("buttons.pureCloseAllTabs"),
|
text: $t("buttons.pureCloseAllTabs"),
|
||||||
divided: false,
|
divided: false,
|
||||||
disabled: multiTags.value.length > 1 ? false : true,
|
disabled: multiTags.value.length <= 1,
|
||||||
show: true
|
show: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -242,7 +242,6 @@ export function useTags() {
|
||||||
onMounted,
|
onMounted,
|
||||||
onMouseenter,
|
onMouseenter,
|
||||||
onMouseleave,
|
onMouseleave,
|
||||||
transformI18n,
|
|
||||||
onContentFullScreen
|
onContentFullScreen
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { useNav } from "./useNav";
|
import { useNav } from "./useNav";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { useRoute } from "vue-router";
|
import { useRoute } from "vue-router";
|
||||||
import { watch, onBeforeMount, type Ref } from "vue";
|
import { onBeforeMount, type Ref, watch } from "vue";
|
||||||
|
|
||||||
export function useTranslationLang(ref?: Ref) {
|
export function useTranslationLang(ref?: Ref) {
|
||||||
const { $storage, changeTitle, handleResize } = useNav();
|
const { $storage, changeTitle, handleResize } = useNav();
|
||||||
const { locale, t } = useI18n();
|
const { locale } = useI18n();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
||||||
function translationCh() {
|
function translationCh() {
|
||||||
|
@ -32,7 +32,6 @@ export function useTranslationLang(ref?: Ref) {
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
t,
|
|
||||||
route,
|
route,
|
||||||
locale,
|
locale,
|
||||||
translationCh,
|
translationCh,
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import type { IconifyIcon } from "@iconify/vue";
|
import type { IconifyIcon } from "@iconify/vue";
|
||||||
|
|
||||||
const { VITE_HIDE_HOME } = import.meta.env;
|
const { VITE_HIDE_HOME } = import.meta.env;
|
||||||
|
|
||||||
export const routerArrays: Array<RouteConfigs> =
|
export const routerArrays: Array<RouteConfigs> =
|
||||||
|
@ -7,7 +8,7 @@ export const routerArrays: Array<RouteConfigs> =
|
||||||
{
|
{
|
||||||
path: "/welcome",
|
path: "/welcome",
|
||||||
meta: {
|
meta: {
|
||||||
title: "menus.pureHome",
|
title: "menus.home",
|
||||||
icon: "ep:home-filled"
|
icon: "ep:home-filled"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,6 @@ Object.keys(directives).forEach(key => {
|
||||||
app.component("IconifyIconOffline", IconifyIconOffline);
|
app.component("IconifyIconOffline", IconifyIconOffline);
|
||||||
app.component("IconifyIconOnline", IconifyIconOnline);
|
app.component("IconifyIconOnline", IconifyIconOnline);
|
||||||
app.component("FontIcon", FontIcon);
|
app.component("FontIcon", FontIcon);
|
||||||
|
|
||||||
app.component("Auth", Auth);
|
app.component("Auth", Auth);
|
||||||
app.component("Perms", Perms);
|
app.component("Perms", Perms);
|
||||||
|
|
||||||
|
|
|
@ -1,116 +1,24 @@
|
||||||
// 多组件库的国际化和本地项目国际化兼容
|
// 多组件库的国际化和本地项目国际化兼容
|
||||||
import { type I18n, createI18n } from "vue-i18n";
|
import { createI18n } from "vue-i18n";
|
||||||
import type { App, WritableComputedRef } from "vue";
|
import type { App } from "vue";
|
||||||
import { responsiveStorageNameSpace } from "@/config";
|
|
||||||
import { storageLocal, isObject } from "@pureadmin/utils";
|
|
||||||
|
|
||||||
// element-plus国际化
|
// ? 从本地存储中获取数据
|
||||||
import enLocale from "element-plus/es/locale/lang/en";
|
const languageData = localStorage.getItem("i18nStore");
|
||||||
import zhLocale from "element-plus/es/locale/lang/zh-cn";
|
|
||||||
|
|
||||||
const siphonI18n = (function () {
|
// 配置多语言
|
||||||
// 仅初始化一次国际化配置
|
export const i18n = createI18n({
|
||||||
let cache = Object.fromEntries(
|
// 如果要支持 compositionAPI,此项必须设置为 false
|
||||||
Object.entries(
|
|
||||||
import.meta.glob("../../locales/*.y(a)?ml", { eager: true })
|
|
||||||
).map(([key, value]: any) => {
|
|
||||||
const matched = key.match(/([A-Za-z0-9-_]+)\./i)[1];
|
|
||||||
return [matched, value.default];
|
|
||||||
})
|
|
||||||
);
|
|
||||||
return (prefix = "zh-CN") => {
|
|
||||||
return cache[prefix];
|
|
||||||
};
|
|
||||||
})();
|
|
||||||
|
|
||||||
export const localesConfigs = {
|
|
||||||
zh: {
|
|
||||||
...siphonI18n("zh-CN"),
|
|
||||||
...zhLocale
|
|
||||||
},
|
|
||||||
en: {
|
|
||||||
...siphonI18n("en"),
|
|
||||||
...enLocale
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/** 获取对象中所有嵌套对象的key键,并将它们用点号分割组成字符串 */
|
|
||||||
function getObjectKeys(obj) {
|
|
||||||
const stack = [];
|
|
||||||
const keys: Set<string> = new Set();
|
|
||||||
|
|
||||||
stack.push({ obj, key: "" });
|
|
||||||
|
|
||||||
while (stack.length > 0) {
|
|
||||||
const { obj, key } = stack.pop();
|
|
||||||
|
|
||||||
for (const k in obj) {
|
|
||||||
const newKey = key ? `${key}.${k}` : k;
|
|
||||||
|
|
||||||
if (obj[k] && isObject(obj[k])) {
|
|
||||||
stack.push({ obj: obj[k], key: newKey });
|
|
||||||
} else {
|
|
||||||
keys.add(newKey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return keys;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 将展开的key缓存 */
|
|
||||||
const keysCache: Map<string, Set<string>> = new Map();
|
|
||||||
const flatI18n = (prefix = "zh-CN") => {
|
|
||||||
let cache = keysCache.get(prefix);
|
|
||||||
if (!cache) {
|
|
||||||
cache = getObjectKeys(siphonI18n(prefix));
|
|
||||||
keysCache.set(prefix, cache);
|
|
||||||
}
|
|
||||||
return cache;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 国际化转换工具函数(自动读取根目录locales文件夹下文件进行国际化匹配)
|
|
||||||
* @param message message
|
|
||||||
* @returns 转化后的message
|
|
||||||
*/
|
|
||||||
export function transformI18n(message: any = "") {
|
|
||||||
if (!message) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理存储动态路由的title,格式 {zh:"",en:""}
|
|
||||||
if (typeof message === "object") {
|
|
||||||
const locale: string | WritableComputedRef<string> | any =
|
|
||||||
i18n.global.locale;
|
|
||||||
return message[locale?.value];
|
|
||||||
}
|
|
||||||
|
|
||||||
const key = message.match(/(\S*)\./)?.input;
|
|
||||||
|
|
||||||
if (key && flatI18n("zh-CN").has(key)) {
|
|
||||||
return i18n.global.t.call(i18n.global.locale, message);
|
|
||||||
} else if (!key && Object.hasOwn(siphonI18n("zh-CN"), message)) {
|
|
||||||
// 兼容非嵌套形式的国际化写法
|
|
||||||
return i18n.global.t.call(i18n.global.locale, message);
|
|
||||||
} else {
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 此函数只是配合i18n Ally插件来进行国际化智能提示,并无实际意义(只对提示起作用),如果不需要国际化可删除 */
|
|
||||||
export const $t = (key: string) => key;
|
|
||||||
|
|
||||||
export const i18n: I18n = createI18n({
|
|
||||||
legacy: false,
|
legacy: false,
|
||||||
locale:
|
// locale: 'zh',
|
||||||
storageLocal().getItem<StorageConfigs>(
|
|
||||||
`${responsiveStorageNameSpace()}locale`
|
|
||||||
)?.locale ?? "zh",
|
|
||||||
fallbackLocale: "en",
|
fallbackLocale: "en",
|
||||||
messages: localesConfigs
|
// ? 全局注册$t方法
|
||||||
|
globalInjection: true,
|
||||||
|
// 本地内容存在时,首次加载如果本地存储没有多语言需要再刷新
|
||||||
|
messages: languageData ? JSON.parse(languageData).i18n : {}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const $t: any = (i18n.global as any).t as any;
|
||||||
|
|
||||||
export function useI18n(app: App) {
|
export function useI18n(app: App) {
|
||||||
app.use(i18n);
|
app.use(i18n);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,34 +2,34 @@
|
||||||
import Cookies from "js-cookie";
|
import Cookies from "js-cookie";
|
||||||
import { getConfig } from "@/config";
|
import { getConfig } from "@/config";
|
||||||
import NProgress from "@/utils/progress";
|
import NProgress from "@/utils/progress";
|
||||||
import { transformI18n } from "@/plugins/i18n";
|
import { $t } from "@/plugins/i18n";
|
||||||
import { buildHierarchyTree } from "@/utils/tree";
|
import { buildHierarchyTree } from "@/utils/tree";
|
||||||
import remainingRouter from "./modules/remaining";
|
import remainingRouter from "./modules/remaining";
|
||||||
import { useMultiTagsStoreHook } from "@/store/modules/multiTags";
|
import { useMultiTagsStoreHook } from "@/store/modules/multiTags";
|
||||||
import { usePermissionStoreHook } from "@/store/modules/permission";
|
import { usePermissionStoreHook } from "@/store/modules/permission";
|
||||||
import { isUrl, openLink, storageLocal, isAllEmpty } from "@pureadmin/utils";
|
import { isAllEmpty, isUrl, openLink, storageLocal } from "@pureadmin/utils";
|
||||||
import {
|
import {
|
||||||
ascending,
|
ascending,
|
||||||
getTopMenu,
|
|
||||||
initRouter,
|
|
||||||
isOneOfArray,
|
|
||||||
getHistoryMode,
|
|
||||||
findRouteByPath,
|
findRouteByPath,
|
||||||
handleAliveRoute,
|
formatFlatteningRoutes,
|
||||||
formatTwoStageRoutes,
|
formatTwoStageRoutes,
|
||||||
formatFlatteningRoutes
|
getHistoryMode,
|
||||||
|
getTopMenu,
|
||||||
|
handleAliveRoute,
|
||||||
|
initRouter,
|
||||||
|
isOneOfArray
|
||||||
} from "./utils";
|
} from "./utils";
|
||||||
import {
|
import {
|
||||||
type Router,
|
|
||||||
createRouter,
|
createRouter,
|
||||||
type RouteRecordRaw,
|
type RouteComponent,
|
||||||
type RouteComponent
|
type Router,
|
||||||
|
type RouteRecordRaw
|
||||||
} from "vue-router";
|
} from "vue-router";
|
||||||
import {
|
import {
|
||||||
type DataInfo,
|
type DataInfo,
|
||||||
userKey,
|
multipleTabsKey,
|
||||||
removeToken,
|
removeToken,
|
||||||
multipleTabsKey
|
userKey
|
||||||
} from "@/utils/auth";
|
} from "@/utils/auth";
|
||||||
|
|
||||||
/** 自动导入全部静态路由,无需再手动引入!匹配 src/router/modules 目录(任何嵌套级别)中具有 .ts 扩展名的所有文件,除了 remaining.ts 文件
|
/** 自动导入全部静态路由,无需再手动引入!匹配 src/router/modules 目录(任何嵌套级别)中具有 .ts 扩展名的所有文件,除了 remaining.ts 文件
|
||||||
|
@ -121,15 +121,16 @@ router.beforeEach((to: ToRouteType, _from, next) => {
|
||||||
to.matched.some(item => {
|
to.matched.some(item => {
|
||||||
if (!item.meta.title) return "";
|
if (!item.meta.title) return "";
|
||||||
const Title = getConfig().Title;
|
const Title = getConfig().Title;
|
||||||
if (Title)
|
if (Title) document.title = `${$t(item.meta.title)} | ${Title}`;
|
||||||
document.title = `${transformI18n(item.meta.title)} | ${Title}`;
|
else document.title = $t(item.meta.title);
|
||||||
else document.title = transformI18n(item.meta.title);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 如果已经登录并存在登录信息后不能跳转到路由白名单,而是继续保持在当前页面 */
|
/** 如果已经登录并存在登录信息后不能跳转到路由白名单,而是继续保持在当前页面 */
|
||||||
function toCorrectRoute() {
|
function toCorrectRoute() {
|
||||||
whiteList.includes(to.fullPath) ? next(_from.fullPath) : next();
|
whiteList.includes(to.fullPath) ? next(_from.fullPath) : next();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Cookies.get(multipleTabsKey) && userInfo) {
|
if (Cookies.get(multipleTabsKey) && userInfo) {
|
||||||
// 无权限跳转403页面
|
// 无权限跳转403页面
|
||||||
if (to.meta?.roles && !isOneOfArray(to.meta?.roles, userInfo?.roles)) {
|
if (to.meta?.roles && !isOneOfArray(to.meta?.roles, userInfo?.roles)) {
|
||||||
|
|
|
@ -5,8 +5,8 @@ export default {
|
||||||
redirect: "/error/403",
|
redirect: "/error/403",
|
||||||
meta: {
|
meta: {
|
||||||
icon: "ri:information-line",
|
icon: "ri:information-line",
|
||||||
// showLink: false,
|
showLink: false,
|
||||||
title: $t("menus.pureAbnormal"),
|
title: "menus.pureAbnormal",
|
||||||
rank: 9
|
rank: 9
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import { $t } from "@/plugins/i18n";
|
|
||||||
const { VITE_HIDE_HOME } = import.meta.env;
|
const { VITE_HIDE_HOME } = import.meta.env;
|
||||||
const Layout = () => import("@/layout/index.vue");
|
const Layout = () => import("@/layout/index.vue");
|
||||||
|
|
||||||
|
@ -9,7 +8,7 @@ export default {
|
||||||
redirect: "/welcome",
|
redirect: "/welcome",
|
||||||
meta: {
|
meta: {
|
||||||
icon: "ep:home-filled",
|
icon: "ep:home-filled",
|
||||||
title: $t("menus.pureHome"),
|
title: "menus.home",
|
||||||
rank: 0
|
rank: 0
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
|
@ -18,8 +17,8 @@ export default {
|
||||||
name: "Welcome",
|
name: "Welcome",
|
||||||
component: () => import("@/views/welcome/index.vue"),
|
component: () => import("@/views/welcome/index.vue"),
|
||||||
meta: {
|
meta: {
|
||||||
title: $t("menus.pureHome"),
|
title: "menus.home",
|
||||||
showLink: VITE_HIDE_HOME === "true" ? false : true
|
showLink: VITE_HIDE_HOME !== "true"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
// import { fetchGetI18n } from '@/api/mock/i18n';
|
||||||
|
import { defineStore } from "pinia";
|
||||||
|
import { fetchGetI18n } from "@/api/v1/i18n/i18n";
|
||||||
|
import type { I18nState } from "../../../types/store/i18n";
|
||||||
|
|
||||||
|
export const userI18nStore = defineStore("i18nStore", {
|
||||||
|
persist: true,
|
||||||
|
state(): I18nState {
|
||||||
|
return {
|
||||||
|
// ? 多语言内容
|
||||||
|
i18n: {}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
getters: {},
|
||||||
|
actions: {
|
||||||
|
/**
|
||||||
|
* * 获取多语言
|
||||||
|
*/
|
||||||
|
async fetchI18n() {
|
||||||
|
const result = await fetchGetI18n();
|
||||||
|
|
||||||
|
if (result.code === 200) {
|
||||||
|
localStorage.removeItem("i18nStore");
|
||||||
|
// 当前的返回参数
|
||||||
|
const data = result.data;
|
||||||
|
// 将返回对象中key设置name,后端不好设置
|
||||||
|
for (let key in data) if (key !== "local") data[key].name = key;
|
||||||
|
|
||||||
|
// 赋值返回参数
|
||||||
|
this.i18n = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
|
@ -1,8 +1,11 @@
|
||||||
import type { App } from "vue";
|
import type { App } from "vue";
|
||||||
import { createPinia } from "pinia";
|
import { createPinia } from "pinia";
|
||||||
|
import piniaPluginPersistedState from "pinia-plugin-persistedstate";
|
||||||
|
|
||||||
const store = createPinia();
|
const store = createPinia();
|
||||||
|
|
||||||
export function setupStore(app: App<Element>) {
|
export function setupStore(app: App<Element>) {
|
||||||
|
store.use(piniaPluginPersistedState);
|
||||||
app.use(store);
|
app.use(store);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { message } from "@/utils/message";
|
||||||
import { loginRules } from "./utils/rule";
|
import { loginRules } from "./utils/rule";
|
||||||
import { useNav } from "@/layout/hooks/useNav";
|
import { useNav } from "@/layout/hooks/useNav";
|
||||||
import type { FormInstance } from "element-plus";
|
import type { FormInstance } from "element-plus";
|
||||||
import { $t, transformI18n } from "@/plugins/i18n";
|
import { $t } from "@/plugins/i18n";
|
||||||
import { useLayout } from "@/layout/hooks/useLayout";
|
import { useLayout } from "@/layout/hooks/useLayout";
|
||||||
import { useUserStoreHook } from "@/store/modules/user";
|
import { useUserStoreHook } from "@/store/modules/user";
|
||||||
import { getTopMenu, initRouter } from "@/router/utils";
|
import { getTopMenu, initRouter } from "@/router/utils";
|
||||||
|
@ -56,11 +56,11 @@ const onLogin = async (formEl: FormInstance | undefined) => {
|
||||||
// 获取后端路由
|
// 获取后端路由
|
||||||
return initRouter().then(() => {
|
return initRouter().then(() => {
|
||||||
router.push(getTopMenu(true).path).then(() => {
|
router.push(getTopMenu(true).path).then(() => {
|
||||||
message(t("login.pureLoginSuccess"), { type: "success" });
|
message(t("login.loginSuccess"), { type: "success" });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
message(t("login.pureLoginFail"), { type: "error" });
|
message(t("login.loginFail"), { type: "error" });
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.finally(() => (loading.value = false));
|
.finally(() => (loading.value = false));
|
||||||
|
@ -86,7 +86,7 @@ onBeforeUnmount(() => {
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="select-none">
|
<div class="select-none">
|
||||||
<img :src="bg" class="wave" />
|
<img :src="bg" alt="" class="wave" />
|
||||||
<div class="flex-c absolute right-5 top-3">
|
<div class="flex-c absolute right-5 top-3">
|
||||||
<!-- 主题 -->
|
<!-- 主题 -->
|
||||||
<el-switch
|
<el-switch
|
||||||
|
@ -151,7 +151,7 @@ onBeforeUnmount(() => {
|
||||||
:rules="[
|
:rules="[
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: transformI18n($t('login.pureUsernameReg')),
|
message: $t('login.usernameRegex'),
|
||||||
trigger: 'blur'
|
trigger: 'blur'
|
||||||
}
|
}
|
||||||
]"
|
]"
|
||||||
|
@ -159,7 +159,7 @@ onBeforeUnmount(() => {
|
||||||
>
|
>
|
||||||
<el-input
|
<el-input
|
||||||
v-model="ruleForm.username"
|
v-model="ruleForm.username"
|
||||||
:placeholder="t('login.pureUsername')"
|
:placeholder="t('login.username')"
|
||||||
:prefix-icon="useRenderIcon(User)"
|
:prefix-icon="useRenderIcon(User)"
|
||||||
clearable
|
clearable
|
||||||
/>
|
/>
|
||||||
|
@ -170,7 +170,7 @@ onBeforeUnmount(() => {
|
||||||
<el-form-item prop="password">
|
<el-form-item prop="password">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="ruleForm.password"
|
v-model="ruleForm.password"
|
||||||
:placeholder="t('login.purePassword')"
|
:placeholder="t('login.password')"
|
||||||
:prefix-icon="useRenderIcon(Lock)"
|
:prefix-icon="useRenderIcon(Lock)"
|
||||||
clearable
|
clearable
|
||||||
show-password
|
show-password
|
||||||
|
@ -186,7 +186,7 @@ onBeforeUnmount(() => {
|
||||||
type="primary"
|
type="primary"
|
||||||
@click="onLogin(ruleFormRef)"
|
@click="onLogin(ruleFormRef)"
|
||||||
>
|
>
|
||||||
{{ t("login.pureLogin") }}
|
{{ t("login.login") }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</Motion>
|
</Motion>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { reactive } from "vue";
|
import { reactive } from "vue";
|
||||||
import type { FormRules } from "element-plus";
|
import type { FormRules } from "element-plus";
|
||||||
import { $t, transformI18n } from "@/plugins/i18n";
|
import { $t } from "@/plugins/i18n";
|
||||||
|
|
||||||
/** 密码正则(密码格式应为8-18位数字、字母、符号的任意两种组合) */
|
/** 密码正则(密码格式应为8-18位数字、字母、符号的任意两种组合) */
|
||||||
export const REGEXP_PWD =
|
export const REGEXP_PWD =
|
||||||
|
@ -12,9 +12,9 @@ const loginRules = reactive(<FormRules>{
|
||||||
{
|
{
|
||||||
validator: (rule, value, callback) => {
|
validator: (rule, value, callback) => {
|
||||||
if (value === "") {
|
if (value === "") {
|
||||||
callback(new Error(transformI18n($t("login.purePassWordReg"))));
|
callback(new Error($t("login.purePassWordReg")));
|
||||||
} else if (!REGEXP_PWD.test(value)) {
|
} else if (!REGEXP_PWD.test(value)) {
|
||||||
callback(new Error(transformI18n($t("login.purePassWordRuleReg"))));
|
callback(new Error($t("login.purePassWordRuleReg")));
|
||||||
} else {
|
} else {
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
// 返回响应内容
|
||||||
|
export interface Result<T> {
|
||||||
|
code: number;
|
||||||
|
data: T;
|
||||||
|
message: string;
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
// i18n 仓库state
|
||||||
|
export interface I18nState {
|
||||||
|
i18n: any;
|
||||||
|
}
|
Loading…
Reference in New Issue