Merge pull request 'optimize: ♻️ 将多语言单独拆分出来' (#7) from dev into master
Reviewed-on: Bunny-Cli/bunny-admin-element-thin#7
This commit is contained in:
commit
bdea37649d
|
@ -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: {
|
||||
title: "menus.purePermissionButton",
|
||||
roles: ["admin", "common"]
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: "/permission/button/router",
|
||||
component: "permission/button/index",
|
||||
name: "PermissionButtonRouter",
|
||||
meta: {
|
||||
title: "menus.purePermissionButtonRouter",
|
||||
auths: [
|
||||
"permission:btn:add",
|
||||
"permission:btn:edit",
|
||||
"permission:btn:delete"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
path: "/permission/button/login",
|
||||
component: "permission/button/perms",
|
||||
name: "PermissionButtonLogin",
|
||||
meta: {
|
||||
title: "menus.purePermissionButtonLogin"
|
||||
}
|
||||
}
|
||||
]
|
||||
title: "menus.purePermissionButtonRouter",
|
||||
auths: [
|
||||
"permission:btn:add",
|
||||
"permission:btn:edit",
|
||||
"permission:btn:delete"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
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: "系统日志"
|
||||
};
|
57
src/App.vue
57
src/App.vue
|
@ -5,23 +5,56 @@
|
|||
</el-config-provider>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from "vue";
|
||||
<script lang="ts" setup>
|
||||
import { ElConfigProvider } from "element-plus";
|
||||
import { computed, onMounted } from "vue";
|
||||
import { ReDialog } from "@/components/BaseDialog";
|
||||
import en from "element-plus/es/locale/lang/en";
|
||||
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({
|
||||
name: "app",
|
||||
components: {
|
||||
[ElConfigProvider.name]: ElConfigProvider,
|
||||
ReDialog
|
||||
},
|
||||
computed: {
|
||||
currentLocale() {
|
||||
return this.$storage.locale?.locale === "zh" ? zhCn : en;
|
||||
}
|
||||
const i18nStore = userI18nStore();
|
||||
const i18n = useI18n();
|
||||
const { $storage } = useNav();
|
||||
|
||||
/**
|
||||
* * 设置多语言内容
|
||||
*/
|
||||
const setI18n = async () => {
|
||||
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>
|
||||
|
|
|
@ -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 LaySearch from "../lay-search/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 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 Setting from "@iconify-icons/ri/settings-3-line";
|
||||
import Check from "@iconify-icons/ep/check";
|
||||
import { $t } from "@/plugins/i18n";
|
||||
|
||||
const {
|
||||
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)]">
|
||||
<LaySidebarTopCollapse
|
||||
v-if="device === 'mobile'"
|
||||
class="hamburger-container"
|
||||
:is-active="pureApp.sidebar.opened"
|
||||
class="hamburger-container"
|
||||
@toggleClick="toggleSideBar"
|
||||
/>
|
||||
|
||||
|
@ -58,20 +58,20 @@ const { t, locale, translationCh, translationEn } = useTranslationLang();
|
|||
<template #dropdown>
|
||||
<el-dropdown-menu class="translation">
|
||||
<el-dropdown-item
|
||||
:style="getDropdownItemStyle(locale, 'zh')"
|
||||
:class="['dark:!text-white', getDropdownItemClass(locale, 'zh')]"
|
||||
:style="getDropdownItemStyle(locale, 'zh')"
|
||||
@click="translationCh"
|
||||
>
|
||||
<IconifyIconOffline
|
||||
v-show="locale === 'zh'"
|
||||
class="check-zh"
|
||||
:icon="Check"
|
||||
class="check-zh"
|
||||
/>
|
||||
简体中文
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
:style="getDropdownItemStyle(locale, 'en')"
|
||||
:class="['dark:!text-white', getDropdownItemClass(locale, 'en')]"
|
||||
:style="getDropdownItemStyle(locale, 'en')"
|
||||
@click="translationEn"
|
||||
>
|
||||
<span v-show="locale === 'en'" class="check-en">
|
||||
|
@ -89,7 +89,7 @@ const { t, locale, translationCh, translationEn } = useTranslationLang();
|
|||
<!-- 退出登录 -->
|
||||
<el-dropdown trigger="click">
|
||||
<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>
|
||||
</span>
|
||||
<template #dropdown>
|
||||
|
@ -99,14 +99,14 @@ const { t, locale, translationCh, translationEn } = useTranslationLang();
|
|||
:icon="LogoutCircleRLine"
|
||||
style="margin: 5px"
|
||||
/>
|
||||
{{ t("buttons.pureLoginOut") }}
|
||||
{{ $t("buttons.pureLoginOut") }}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
<span
|
||||
:title="$t('buttons.pureOpenSystemSet')"
|
||||
class="set-icon navbar-bg-hover"
|
||||
:title="t('buttons.pureOpenSystemSet')"
|
||||
@click="onPanel"
|
||||
>
|
||||
<IconifyIconOffline :icon="Setting" />
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
<script setup lang="ts">
|
||||
<script lang="ts" setup>
|
||||
import { PropType } from "vue";
|
||||
import { ListItem } from "../data";
|
||||
import NoticeItem from "./NoticeItem.vue";
|
||||
import { transformI18n } from "@/plugins/i18n";
|
||||
|
||||
defineProps({
|
||||
list: {
|
||||
|
@ -20,5 +19,5 @@ defineProps({
|
|||
<div v-if="list.length">
|
||||
<NoticeItem v-for="(item, index) in list" :key="index" :noticeItem="item" />
|
||||
</div>
|
||||
<el-empty v-else :description="transformI18n(emptyText)" />
|
||||
<el-empty v-else :description="emptyText" />
|
||||
</template>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
<script lang="ts" setup>
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { ref, computed } from "vue";
|
||||
import { computed, ref } from "vue";
|
||||
import { noticesData } from "./data";
|
||||
import NoticeList from "./components/NoticeList.vue";
|
||||
import BellIcon from "@iconify-icons/ep/bell";
|
||||
|
@ -14,12 +14,12 @@ notices.value.map(v => (noticesNum.value += v.list.length));
|
|||
|
||||
const getLabel = computed(
|
||||
() => item =>
|
||||
t(item.name) + (item.list.length > 0 ? `(${item.list.length})` : "")
|
||||
item.name + (item.list.length > 0 ? `(${item.list.length})` : "")
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-dropdown trigger="click" placement="bottom-end">
|
||||
<el-dropdown placement="bottom-end" trigger="click">
|
||||
<span
|
||||
:class="[
|
||||
'dropdown-badge',
|
||||
|
@ -28,7 +28,7 @@ const getLabel = computed(
|
|||
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">
|
||||
<IconifyIconOffline :icon="BellIcon" />
|
||||
</span>
|
||||
|
@ -39,8 +39,8 @@ const getLabel = computed(
|
|||
<el-tabs
|
||||
v-model="activeKey"
|
||||
:stretch="true"
|
||||
class="dropdown-tabs"
|
||||
:style="{ width: notices.length === 0 ? '200px' : '330px' }"
|
||||
class="dropdown-tabs"
|
||||
>
|
||||
<el-empty
|
||||
v-if="notices.length === 0"
|
||||
|
@ -52,7 +52,7 @@ const getLabel = computed(
|
|||
<el-tab-pane :label="getLabel(item)" :name="`${item.key}`">
|
||||
<el-scrollbar max-height="330px">
|
||||
<div class="noticeList-container">
|
||||
<NoticeList :list="item.list" :emptyText="item.emptyText" />
|
||||
<NoticeList :emptyText="item.emptyText" :list="item.list" />
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
</el-tab-pane>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<script setup lang="ts">
|
||||
<script lang="ts" setup>
|
||||
import { useRenderIcon } from "@/components/CommonIcon/src/hooks";
|
||||
import { transformI18n } from "@/plugins/i18n";
|
||||
import CloseIcon from "@iconify-icons/ep/close";
|
||||
import StarIcon from "@iconify-icons/ep/star";
|
||||
import type { optionsItem } from "../types";
|
||||
import { $t } from "../../../../plugins/i18n";
|
||||
|
||||
interface Props {
|
||||
item: optionsItem;
|
||||
|
@ -11,6 +11,7 @@ interface Props {
|
|||
|
||||
interface Emits {
|
||||
(e: "collectItem", val: optionsItem): void;
|
||||
|
||||
(e: "deleteItem", val: optionsItem): void;
|
||||
}
|
||||
|
||||
|
@ -29,7 +30,7 @@ function handleDelete(item) {
|
|||
<template>
|
||||
<component :is="useRenderIcon(item.meta?.icon)" />
|
||||
<span class="history-item-title">
|
||||
{{ transformI18n(item.meta?.title) }}
|
||||
{{ $t(item.meta?.title) }}
|
||||
</span>
|
||||
<IconifyIconOffline
|
||||
v-show="item.type === 'history'"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<script setup lang="ts">
|
||||
<script lang="ts" setup>
|
||||
import { match } from "pinyin-pro";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { getConfig } from "@/config";
|
||||
|
@ -6,14 +6,14 @@ import { useRouter } from "vue-router";
|
|||
import SearchResult from "./SearchResult.vue";
|
||||
import SearchFooter from "./SearchFooter.vue";
|
||||
import { useNav } from "@/layout/hooks/useNav";
|
||||
import { transformI18n } from "@/plugins/i18n";
|
||||
import SearchHistory from "./SearchHistory.vue";
|
||||
import type { optionsItem, dragItem } from "../types";
|
||||
import { ref, computed, shallowRef, watch } from "vue";
|
||||
import { useDebounceFn, onKeyStroke } from "@vueuse/core";
|
||||
import type { dragItem, optionsItem } from "../types";
|
||||
import { computed, ref, shallowRef, watch } from "vue";
|
||||
import { onKeyStroke, useDebounceFn } from "@vueuse/core";
|
||||
import { usePermissionStoreHook } from "@/store/modules/permission";
|
||||
import { cloneDeep, isAllEmpty, storageLocal } from "@pureadmin/utils";
|
||||
import SearchIcon from "@iconify-icons/ri/search-line";
|
||||
import { $t } from "@/plugins/i18n";
|
||||
|
||||
interface Props {
|
||||
/** 弹窗显隐 */
|
||||
|
@ -95,12 +95,14 @@ function setStorageItem(key, value) {
|
|||
/** 将菜单树形结构扁平化为一维数组,用于菜单查询 */
|
||||
function flatTree(arr) {
|
||||
const res = [];
|
||||
|
||||
function deep(arr) {
|
||||
arr.forEach(item => {
|
||||
res.push(item);
|
||||
item.children && deep(item.children);
|
||||
});
|
||||
}
|
||||
|
||||
deep(arr);
|
||||
return res;
|
||||
}
|
||||
|
@ -110,13 +112,13 @@ function search() {
|
|||
const flatMenusData = flatTree(menusData.value);
|
||||
resultOptions.value = flatMenusData.filter(menu =>
|
||||
keyword.value
|
||||
? transformI18n(menu.meta?.title)
|
||||
? $t(menu.meta?.title)
|
||||
.toLocaleLowerCase()
|
||||
.includes(keyword.value.toLocaleLowerCase().trim()) ||
|
||||
(locale.value === "zh" &&
|
||||
!isAllEmpty(
|
||||
match(
|
||||
transformI18n(menu.meta?.title).toLocaleLowerCase(),
|
||||
$t(menu.meta?.title).toLocaleLowerCase(),
|
||||
keyword.value.toLocaleLowerCase().trim()
|
||||
)
|
||||
))
|
||||
|
@ -276,24 +278,24 @@ onKeyStroke("ArrowDown", handleDown);
|
|||
<template>
|
||||
<el-dialog
|
||||
v-model="show"
|
||||
top="5vh"
|
||||
class="pure-search-dialog"
|
||||
:show-close="false"
|
||||
:width="device === 'mobile' ? '80vw' : '40vw'"
|
||||
:before-close="handleClose"
|
||||
:show-close="false"
|
||||
:style="{
|
||||
borderRadius: '6px'
|
||||
}"
|
||||
:width="device === 'mobile' ? '80vw' : '40vw'"
|
||||
append-to-body
|
||||
@opened="inputRef.focus()"
|
||||
class="pure-search-dialog"
|
||||
top="5vh"
|
||||
@closed="inputRef.blur()"
|
||||
@opened="inputRef.focus()"
|
||||
>
|
||||
<el-input
|
||||
ref="inputRef"
|
||||
v-model="keyword"
|
||||
size="large"
|
||||
clearable
|
||||
:placeholder="t('search.purePlaceholder')"
|
||||
clearable
|
||||
size="large"
|
||||
@input="handleSearch"
|
||||
>
|
||||
<template #prefix>
|
||||
|
@ -312,8 +314,8 @@ onKeyStroke("ArrowDown", handleDown);
|
|||
v-model:value="historyPath"
|
||||
:options="historyOptions"
|
||||
@click="handleEnter"
|
||||
@delete="handleDelete"
|
||||
@collect="handleCollect"
|
||||
@delete="handleDelete"
|
||||
@drag="handleDrag"
|
||||
/>
|
||||
<SearchResult
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
<script setup lang="ts">
|
||||
<script lang="ts" setup>
|
||||
import EnterOutlined from "@/assets/svg/enter_outlined.svg?component";
|
||||
import { useRenderIcon } from "@/components/CommonIcon/src/hooks";
|
||||
import { transformI18n } from "@/plugins/i18n";
|
||||
import { useEpThemeStoreHook } from "@/store/modules/epTheme";
|
||||
import { useResizeObserver } from "@pureadmin/utils";
|
||||
import { computed, getCurrentInstance, onMounted, ref } from "vue";
|
||||
import type { Props } from "../types";
|
||||
import { $t } from "../../../../plugins/i18n";
|
||||
|
||||
interface Emits {
|
||||
(e: "update:value", val: string): void;
|
||||
|
||||
(e: "enter"): void;
|
||||
}
|
||||
|
||||
|
@ -75,14 +76,14 @@ defineExpose({ handleScroll });
|
|||
v-for="(item, index) in options"
|
||||
:key="item.path"
|
||||
:ref="'resultItemRef' + index"
|
||||
class="result-item dark:bg-[#1d1d1d]"
|
||||
:style="itemStyle(item)"
|
||||
class="result-item dark:bg-[#1d1d1d]"
|
||||
@click="handleTo"
|
||||
@mouseenter="handleMouse(item)"
|
||||
>
|
||||
<component :is="useRenderIcon(item.meta?.icon)" />
|
||||
<span class="result-item-title">
|
||||
{{ transformI18n(item.meta?.title) }}
|
||||
{{ $t(item.meta?.title) }}
|
||||
</span>
|
||||
<EnterOutlined />
|
||||
</div>
|
||||
|
|
|
@ -234,8 +234,8 @@ const markOptions = computed<Array<OptionsType>>(() => {
|
|||
value: "card"
|
||||
},
|
||||
{
|
||||
label: t("panel.pureTagsStyleChrome"),
|
||||
tip: t("panel.pureTagsStyleChromeTip"),
|
||||
label: "panel.pureTagsStyleChrome",
|
||||
tip: "panel.pureTagsStyleChromeTip",
|
||||
value: "chrome"
|
||||
}
|
||||
];
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
<script setup lang="ts">
|
||||
<script lang="ts" setup>
|
||||
import { emitter } from "@/utils/mitt";
|
||||
import { useNav } from "@/layout/hooks/useNav";
|
||||
import LaySearch from "../lay-search/index.vue";
|
||||
import LayNotice from "../lay-notice/index.vue";
|
||||
import { responsiveStorageNameSpace } from "@/config";
|
||||
import { ref, nextTick, computed, onMounted } from "vue";
|
||||
import { storageLocal, isAllEmpty } from "@pureadmin/utils";
|
||||
import { computed, nextTick, onMounted, ref } from "vue";
|
||||
import { isAllEmpty, storageLocal } from "@pureadmin/utils";
|
||||
import { useTranslationLang } from "../../hooks/useTranslationLang";
|
||||
import { usePermissionStoreHook } from "@/store/modules/permission";
|
||||
import LaySidebarItem from "../lay-sidebar/components/SidebarItem.vue";
|
||||
import LaySidebarFullScreen from "../lay-sidebar/components/SidebarFullScreen.vue";
|
||||
|
||||
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 Setting from "@iconify-icons/ri/settings-3-line";
|
||||
import Check from "@iconify-icons/ep/check";
|
||||
import { $t } from "@/plugins/i18n";
|
||||
|
||||
const menuRef = ref();
|
||||
const showLogo = ref(
|
||||
|
@ -65,16 +65,16 @@ onMounted(() => {
|
|||
</div>
|
||||
<el-menu
|
||||
ref="menuRef"
|
||||
:default-active="defaultActive"
|
||||
class="horizontal-header-menu"
|
||||
mode="horizontal"
|
||||
popper-class="pure-scrollbar"
|
||||
class="horizontal-header-menu"
|
||||
:default-active="defaultActive"
|
||||
>
|
||||
<LaySidebarItem
|
||||
v-for="route in usePermissionStoreHook().wholeMenus"
|
||||
:key="route.path"
|
||||
:item="route"
|
||||
:base-path="route.path"
|
||||
:item="route"
|
||||
/>
|
||||
</el-menu>
|
||||
<div class="horizontal-header-right">
|
||||
|
@ -88,8 +88,8 @@ onMounted(() => {
|
|||
<template #dropdown>
|
||||
<el-dropdown-menu class="translation">
|
||||
<el-dropdown-item
|
||||
:style="getDropdownItemStyle(locale, 'zh')"
|
||||
:class="['dark:!text-white', getDropdownItemClass(locale, 'zh')]"
|
||||
:style="getDropdownItemStyle(locale, 'zh')"
|
||||
@click="translationCh"
|
||||
>
|
||||
<span v-show="locale === 'zh'" class="check-zh">
|
||||
|
@ -98,8 +98,8 @@ onMounted(() => {
|
|||
简体中文
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
:style="getDropdownItemStyle(locale, 'en')"
|
||||
:class="['dark:!text-white', getDropdownItemClass(locale, 'en')]"
|
||||
:style="getDropdownItemStyle(locale, 'en')"
|
||||
@click="translationEn"
|
||||
>
|
||||
<span v-show="locale === 'en'" class="check-en">
|
||||
|
@ -127,14 +127,14 @@ onMounted(() => {
|
|||
:icon="LogoutCircleRLine"
|
||||
style="margin: 5px"
|
||||
/>
|
||||
{{ t("buttons.pureLoginOut") }}
|
||||
{{ $t("buttons.pureLoginOut") }}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
<span
|
||||
:title="$t('buttons.pureOpenSystemSet')"
|
||||
class="set-icon navbar-bg-hover"
|
||||
:title="t('buttons.pureOpenSystemSet')"
|
||||
@click="onPanel"
|
||||
>
|
||||
<IconifyIconOffline :icon="Setting" />
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
<script lang="ts" setup>
|
||||
import { useRenderIcon } from "@/components/CommonIcon/src/hooks";
|
||||
import { useNav } from "@/layout/hooks/useNav";
|
||||
import { transformI18n } from "@/plugins/i18n";
|
||||
import { findRouteByPath, getParentPaths } from "@/router/utils";
|
||||
import { usePermissionStoreHook } from "@/store/modules/permission";
|
||||
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 LogoutCircleRLine from "@iconify-icons/ri/logout-circle-r-line";
|
||||
import Setting from "@iconify-icons/ri/settings-3-line";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { $t } from "@/plugins/i18n";
|
||||
|
||||
const menuRef = ref();
|
||||
const defaultActive = ref(null);
|
||||
|
||||
const { t, route, locale, translationCh, translationEn } =
|
||||
const { t } = useI18n();
|
||||
const { route, locale, translationCh, translationEn } =
|
||||
useTranslationLang(menuRef);
|
||||
const {
|
||||
device,
|
||||
|
@ -68,11 +69,11 @@ watch(
|
|||
>
|
||||
<el-menu
|
||||
ref="menuRef"
|
||||
router
|
||||
:default-active="defaultActive"
|
||||
class="horizontal-header-menu"
|
||||
mode="horizontal"
|
||||
popper-class="pure-scrollbar"
|
||||
class="horizontal-header-menu"
|
||||
:default-active="defaultActive"
|
||||
router
|
||||
>
|
||||
<el-menu-item
|
||||
v-for="route in usePermissionStoreHook().wholeMenus"
|
||||
|
@ -90,7 +91,7 @@ watch(
|
|||
</div>
|
||||
<div :style="getDivStyle">
|
||||
<span class="select-none">
|
||||
{{ transformI18n(route.meta.title) }}
|
||||
{{ t(route.meta.title) }}
|
||||
</span>
|
||||
<LaySidebarExtraIcon :extraIcon="route.meta.extraIcon" />
|
||||
</div>
|
||||
|
@ -108,8 +109,8 @@ watch(
|
|||
<template #dropdown>
|
||||
<el-dropdown-menu class="translation">
|
||||
<el-dropdown-item
|
||||
:style="getDropdownItemStyle(locale, 'zh')"
|
||||
:class="['dark:!text-white', getDropdownItemClass(locale, 'zh')]"
|
||||
:style="getDropdownItemStyle(locale, 'zh')"
|
||||
@click="translationCh"
|
||||
>
|
||||
<span v-show="locale === 'zh'" class="check-zh">
|
||||
|
@ -118,8 +119,8 @@ watch(
|
|||
简体中文
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
:style="getDropdownItemStyle(locale, 'en')"
|
||||
:class="['dark:!text-white', getDropdownItemClass(locale, 'en')]"
|
||||
:style="getDropdownItemStyle(locale, 'en')"
|
||||
@click="translationEn"
|
||||
>
|
||||
<span v-show="locale === 'en'" class="check-en">
|
||||
|
@ -147,14 +148,14 @@ watch(
|
|||
:icon="LogoutCircleRLine"
|
||||
style="margin: 5px"
|
||||
/>
|
||||
{{ t("buttons.pureLoginOut") }}
|
||||
{{ $t("buttons.pureLoginOut") }}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
<span
|
||||
:title="$t('buttons.pureOpenSystemSet')"
|
||||
class="set-icon navbar-bg-hover"
|
||||
:title="t('buttons.pureOpenSystemSet')"
|
||||
@click="onPanel"
|
||||
>
|
||||
<IconifyIconOffline :icon="Setting" />
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<script setup lang="ts">
|
||||
<script lang="ts" setup>
|
||||
import { isEqual } from "@pureadmin/utils";
|
||||
import { transformI18n } from "@/plugins/i18n";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { ref, watch, onMounted, toRaw } from "vue";
|
||||
import { getParentPaths, findRouteByPath } from "@/router/utils";
|
||||
import { onMounted, ref, toRaw, watch } from "vue";
|
||||
import { findRouteByPath, getParentPaths } from "@/router/utils";
|
||||
import { useMultiTagsStoreHook } from "@/store/modules/multiTags";
|
||||
import { $t } from "@/plugins/i18n";
|
||||
|
||||
const route = useRoute();
|
||||
const levelList = ref([]);
|
||||
|
@ -113,7 +113,7 @@ watch(
|
|||
class="!inline !items-stretch"
|
||||
>
|
||||
<a @click.prevent="handleLink(item)">
|
||||
{{ transformI18n(item.meta.title) }}
|
||||
{{ $t(item.meta.title) }}
|
||||
</a>
|
||||
</el-breadcrumb-item>
|
||||
</transition-group>
|
||||
|
|
|
@ -4,7 +4,6 @@ import { ReText } from "@/components/Text";
|
|||
import { getConfig } from "@/config";
|
||||
import { useNav } from "@/layout/hooks/useNav";
|
||||
import { menuType } from "@/layout/types";
|
||||
import { transformI18n } from "@/plugins/i18n";
|
||||
import path from "path";
|
||||
import {
|
||||
computed,
|
||||
|
@ -17,6 +16,7 @@ import {
|
|||
import SidebarExtraIcon from "./SidebarExtraIcon.vue";
|
||||
import SidebarLinkItem from "./SidebarLinkItem.vue";
|
||||
|
||||
import { $t } from "@/plugins/i18n";
|
||||
import EpArrowDown from "@iconify-icons/ep/arrow-down-bold";
|
||||
import ArrowLeft from "@iconify-icons/ep/arrow-left-bold";
|
||||
import ArrowRight from "@iconify-icons/ep/arrow-right-bold";
|
||||
|
@ -147,7 +147,7 @@ function resolvePath(routePath) {
|
|||
class="!w-full !pl-4 !text-inherit"
|
||||
truncated
|
||||
>
|
||||
{{ transformI18n(onlyOneChild.meta.title) }}
|
||||
{{ $t(onlyOneChild.meta.title) }}
|
||||
</el-text>
|
||||
|
||||
<template #title>
|
||||
|
@ -159,7 +159,7 @@ function resolvePath(routePath) {
|
|||
}"
|
||||
class="!w-full !text-inherit"
|
||||
>
|
||||
{{ transformI18n(onlyOneChild.meta.title) }}
|
||||
{{ $t(onlyOneChild.meta.title) }}
|
||||
</ReText>
|
||||
<SidebarExtraIcon :extraIcon="onlyOneChild.meta.extraIcon" />
|
||||
</div>
|
||||
|
@ -206,7 +206,7 @@ function resolvePath(routePath) {
|
|||
theme: tooltipEffect
|
||||
}"
|
||||
>
|
||||
{{ transformI18n(item.meta.title) }}
|
||||
{{ $t(item.meta.title) }}
|
||||
</ReText>
|
||||
<SidebarExtraIcon v-if="!isCollapse" :extraIcon="item.meta.extraIcon" />
|
||||
</template>
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
<script setup lang="ts">
|
||||
import { $t } from "@/plugins/i18n";
|
||||
import { emitter } from "@/utils/mitt";
|
||||
import { RouteConfigs } from "../../types";
|
||||
import { useTags } from "../../hooks/useTag";
|
||||
<script lang="ts" setup>
|
||||
import { routerArrays } from "@/layout/types";
|
||||
import { onClickOutside } from "@vueuse/core";
|
||||
import TagChrome from "./components/TagChrome.vue";
|
||||
import { handleAliveRoute, getTopMenu } from "@/router/utils";
|
||||
import { useSettingStoreHook } from "@/store/modules/settings";
|
||||
import { $t } from "@/plugins/i18n";
|
||||
import { getTopMenu, handleAliveRoute } from "@/router/utils";
|
||||
import { useMultiTagsStoreHook } from "@/store/modules/multiTags";
|
||||
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 {
|
||||
delay,
|
||||
isEqual,
|
||||
isAllEmpty,
|
||||
isEqual,
|
||||
useResizeObserver
|
||||
} 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 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 {
|
||||
Close,
|
||||
|
@ -51,7 +51,6 @@ const {
|
|||
onMounted,
|
||||
onMouseenter,
|
||||
onMouseleave,
|
||||
transformI18n,
|
||||
onContentFullScreen
|
||||
} = useTags();
|
||||
|
||||
|
@ -201,6 +200,7 @@ function dynamicRouteTag(value: string): void {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
concatPath(router.options.routes as any, value);
|
||||
}
|
||||
|
||||
|
@ -398,6 +398,7 @@ function showMenuModel(
|
|||
} else {
|
||||
currentIndex = allRoute.findIndex(v => isEqual(v.query, query));
|
||||
}
|
||||
|
||||
function fixedTagDisabled() {
|
||||
if (allRoute[currentIndex]?.meta?.fixedTag) {
|
||||
Array.of(1, 2, 3, 4, 5).forEach(v => {
|
||||
|
@ -566,31 +567,31 @@ onBeforeUnmount(() => {
|
|||
</span>
|
||||
<div
|
||||
ref="scrollbarDom"
|
||||
class="scroll-container"
|
||||
:class="showModel === 'chrome' && 'chrome-scroll-container'"
|
||||
class="scroll-container"
|
||||
@wheel.prevent="handleWheel"
|
||||
>
|
||||
<div ref="tabDom" class="tab select-none" :style="getTabStyle">
|
||||
<div ref="tabDom" :style="getTabStyle" class="tab select-none">
|
||||
<div
|
||||
v-for="(item, index) in multiTags"
|
||||
:ref="'dynamic' + index"
|
||||
:key="index"
|
||||
:ref="'dynamic' + index"
|
||||
:class="[
|
||||
'scroll-item is-closable',
|
||||
linkIsActive(item),
|
||||
showModel === 'chrome' && 'chrome-item',
|
||||
isFixedTag(item) && 'fixed-tag'
|
||||
]"
|
||||
@click="tagOnClick(item)"
|
||||
@contextmenu.prevent="openMenu(item, $event)"
|
||||
@mouseenter.prevent="onMouseenter(index)"
|
||||
@mouseleave.prevent="onMouseleave(index)"
|
||||
@click="tagOnClick(item)"
|
||||
>
|
||||
<template v-if="showModel !== 'chrome'">
|
||||
<span
|
||||
class="tag-title dark:!text-text_color_primary dark:hover:!text-primary"
|
||||
>
|
||||
{{ transformI18n(item.meta.title) }}
|
||||
{{ $t(item.meta.title) }}
|
||||
</span>
|
||||
<span
|
||||
v-if="
|
||||
|
@ -636,8 +637,8 @@ onBeforeUnmount(() => {
|
|||
<transition name="el-zoom-in-top">
|
||||
<ul
|
||||
v-show="visible"
|
||||
ref="contextmenuRef"
|
||||
:key="Math.random()"
|
||||
ref="contextmenuRef"
|
||||
:style="getContextMenuStyle"
|
||||
class="contextmenu"
|
||||
>
|
||||
|
@ -648,15 +649,15 @@ onBeforeUnmount(() => {
|
|||
>
|
||||
<li v-if="item.show" @click="selectTag(key, item)">
|
||||
<IconifyIconOffline :icon="item.icon" />
|
||||
{{ transformI18n(item.text) }}
|
||||
{{ item.text }}
|
||||
</li>
|
||||
</div>
|
||||
</ul>
|
||||
</transition>
|
||||
<!-- 右侧功能按钮 -->
|
||||
<el-dropdown
|
||||
trigger="click"
|
||||
placement="bottom-end"
|
||||
trigger="click"
|
||||
@command="handleCommand"
|
||||
>
|
||||
<span class="arrow-down">
|
||||
|
@ -668,11 +669,11 @@ onBeforeUnmount(() => {
|
|||
v-for="(item, key) in tagsViews"
|
||||
:key="key"
|
||||
:command="{ key, item }"
|
||||
:divided="item.divided"
|
||||
:disabled="item.disabled"
|
||||
:divided="item.divided"
|
||||
>
|
||||
<IconifyIconOffline :icon="item.icon" />
|
||||
{{ transformI18n(item.text) }}
|
||||
{{ item.text }}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
|
|
|
@ -6,7 +6,6 @@ import Avatar from "@/assets/user.jpg";
|
|||
import { getTopMenu } from "@/router/utils";
|
||||
import { useFullscreen } from "@vueuse/core";
|
||||
import type { routeMetaType } from "../types";
|
||||
import { transformI18n } from "@/plugins/i18n";
|
||||
import { remainingPaths, router } from "@/router";
|
||||
import { computed, type CSSProperties } from "vue";
|
||||
import { useAppStoreHook } from "@/store/modules/app";
|
||||
|
@ -16,6 +15,7 @@ import { useEpThemeStoreHook } from "@/store/modules/epTheme";
|
|||
import { usePermissionStoreHook } from "@/store/modules/permission";
|
||||
import ExitFullscreen from "@iconify-icons/ri/fullscreen-exit-fill";
|
||||
import Fullscreen from "@iconify-icons/ri/fullscreen-fill";
|
||||
import { $t } from "@/plugins/i18n";
|
||||
|
||||
const errorInfo =
|
||||
"The current routing configuration is incorrect, please check the configuration";
|
||||
|
@ -81,9 +81,7 @@ export function useNav() {
|
|||
});
|
||||
|
||||
const { $storage, $config } = useGlobal<GlobalPropertiesApi>();
|
||||
const layout = computed(() => {
|
||||
return $storage?.layout?.layout;
|
||||
});
|
||||
const layout = computed(() => $storage?.layout?.layout);
|
||||
|
||||
const title = computed(() => {
|
||||
return $config.Title;
|
||||
|
@ -92,8 +90,8 @@ export function useNav() {
|
|||
/** 动态title */
|
||||
function changeTitle(meta: routeMetaType) {
|
||||
const Title = getConfig().Title;
|
||||
if (Title) document.title = `${transformI18n(meta.title)} | ${Title}`;
|
||||
else document.title = transformI18n(meta.title);
|
||||
if (Title) document.title = `${meta.title} | ${Title}`;
|
||||
else document.title = $t(meta.title);
|
||||
}
|
||||
|
||||
/** 退出登录 */
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
import {
|
||||
ref,
|
||||
unref,
|
||||
computed,
|
||||
reactive,
|
||||
onMounted,
|
||||
type CSSProperties,
|
||||
getCurrentInstance
|
||||
getCurrentInstance,
|
||||
onMounted,
|
||||
reactive,
|
||||
ref,
|
||||
unref
|
||||
} from "vue";
|
||||
import type { tagsViewsType } from "../types";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { transformI18n, $t } from "@/plugins/i18n";
|
||||
import { $t } from "@/plugins/i18n";
|
||||
import { responsiveStorageNameSpace } from "@/config";
|
||||
import { useSettingStoreHook } from "@/store/modules/settings";
|
||||
import { useMultiTagsStoreHook } from "@/store/modules/multiTags";
|
||||
import {
|
||||
isEqual,
|
||||
hasClass,
|
||||
isBoolean,
|
||||
isEqual,
|
||||
storageLocal,
|
||||
toggleClass,
|
||||
hasClass
|
||||
toggleClass
|
||||
} from "@pureadmin/utils";
|
||||
|
||||
import Fullscreen from "@iconify-icons/ri/fullscreen-fill";
|
||||
|
@ -73,35 +73,35 @@ export function useTags() {
|
|||
icon: Close,
|
||||
text: $t("buttons.pureCloseCurrentTab"),
|
||||
divided: false,
|
||||
disabled: multiTags.value.length > 1 ? false : true,
|
||||
disabled: multiTags.value.length <= 1,
|
||||
show: true
|
||||
},
|
||||
{
|
||||
icon: CloseLeftTags,
|
||||
text: $t("buttons.pureCloseLeftTabs"),
|
||||
divided: true,
|
||||
disabled: multiTags.value.length > 1 ? false : true,
|
||||
disabled: multiTags.value.length <= 1,
|
||||
show: true
|
||||
},
|
||||
{
|
||||
icon: CloseRightTags,
|
||||
text: $t("buttons.pureCloseRightTabs"),
|
||||
divided: false,
|
||||
disabled: multiTags.value.length > 1 ? false : true,
|
||||
disabled: multiTags.value.length <= 1,
|
||||
show: true
|
||||
},
|
||||
{
|
||||
icon: CloseOtherTags,
|
||||
text: $t("buttons.pureCloseOtherTabs"),
|
||||
divided: true,
|
||||
disabled: multiTags.value.length > 2 ? false : true,
|
||||
disabled: multiTags.value.length <= 2,
|
||||
show: true
|
||||
},
|
||||
{
|
||||
icon: CloseAllTags,
|
||||
text: $t("buttons.pureCloseAllTabs"),
|
||||
divided: false,
|
||||
disabled: multiTags.value.length > 1 ? false : true,
|
||||
disabled: multiTags.value.length <= 1,
|
||||
show: true
|
||||
},
|
||||
{
|
||||
|
@ -242,7 +242,6 @@ export function useTags() {
|
|||
onMounted,
|
||||
onMouseenter,
|
||||
onMouseleave,
|
||||
transformI18n,
|
||||
onContentFullScreen
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import { useNav } from "./useNav";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useRoute } from "vue-router";
|
||||
import { watch, onBeforeMount, type Ref } from "vue";
|
||||
import { onBeforeMount, type Ref, watch } from "vue";
|
||||
|
||||
export function useTranslationLang(ref?: Ref) {
|
||||
const { $storage, changeTitle, handleResize } = useNav();
|
||||
const { locale, t } = useI18n();
|
||||
const { locale } = useI18n();
|
||||
const route = useRoute();
|
||||
|
||||
function translationCh() {
|
||||
|
@ -32,7 +32,6 @@ export function useTranslationLang(ref?: Ref) {
|
|||
});
|
||||
|
||||
return {
|
||||
t,
|
||||
route,
|
||||
locale,
|
||||
translationCh,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import type { IconifyIcon } from "@iconify/vue";
|
||||
|
||||
const { VITE_HIDE_HOME } = import.meta.env;
|
||||
|
||||
export const routerArrays: Array<RouteConfigs> =
|
||||
|
@ -7,7 +8,7 @@ export const routerArrays: Array<RouteConfigs> =
|
|||
{
|
||||
path: "/welcome",
|
||||
meta: {
|
||||
title: "menus.pureHome",
|
||||
title: "menus.home",
|
||||
icon: "ep:home-filled"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,6 @@ Object.keys(directives).forEach(key => {
|
|||
app.component("IconifyIconOffline", IconifyIconOffline);
|
||||
app.component("IconifyIconOnline", IconifyIconOnline);
|
||||
app.component("FontIcon", FontIcon);
|
||||
|
||||
app.component("Auth", Auth);
|
||||
app.component("Perms", Perms);
|
||||
|
||||
|
|
|
@ -1,116 +1,24 @@
|
|||
// 多组件库的国际化和本地项目国际化兼容
|
||||
import { type I18n, createI18n } from "vue-i18n";
|
||||
import type { App, WritableComputedRef } from "vue";
|
||||
import { responsiveStorageNameSpace } from "@/config";
|
||||
import { storageLocal, isObject } from "@pureadmin/utils";
|
||||
import { createI18n } from "vue-i18n";
|
||||
import type { App } from "vue";
|
||||
|
||||
// element-plus国际化
|
||||
import enLocale from "element-plus/es/locale/lang/en";
|
||||
import zhLocale from "element-plus/es/locale/lang/zh-cn";
|
||||
// ? 从本地存储中获取数据
|
||||
const languageData = localStorage.getItem("i18nStore");
|
||||
|
||||
const siphonI18n = (function () {
|
||||
// 仅初始化一次国际化配置
|
||||
let cache = Object.fromEntries(
|
||||
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({
|
||||
// 配置多语言
|
||||
export const i18n = createI18n({
|
||||
// 如果要支持 compositionAPI,此项必须设置为 false
|
||||
legacy: false,
|
||||
locale:
|
||||
storageLocal().getItem<StorageConfigs>(
|
||||
`${responsiveStorageNameSpace()}locale`
|
||||
)?.locale ?? "zh",
|
||||
// locale: 'zh',
|
||||
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) {
|
||||
app.use(i18n);
|
||||
}
|
||||
|
|
|
@ -2,34 +2,34 @@
|
|||
import Cookies from "js-cookie";
|
||||
import { getConfig } from "@/config";
|
||||
import NProgress from "@/utils/progress";
|
||||
import { transformI18n } from "@/plugins/i18n";
|
||||
import { $t } from "@/plugins/i18n";
|
||||
import { buildHierarchyTree } from "@/utils/tree";
|
||||
import remainingRouter from "./modules/remaining";
|
||||
import { useMultiTagsStoreHook } from "@/store/modules/multiTags";
|
||||
import { usePermissionStoreHook } from "@/store/modules/permission";
|
||||
import { isUrl, openLink, storageLocal, isAllEmpty } from "@pureadmin/utils";
|
||||
import { isAllEmpty, isUrl, openLink, storageLocal } from "@pureadmin/utils";
|
||||
import {
|
||||
ascending,
|
||||
getTopMenu,
|
||||
initRouter,
|
||||
isOneOfArray,
|
||||
getHistoryMode,
|
||||
findRouteByPath,
|
||||
handleAliveRoute,
|
||||
formatFlatteningRoutes,
|
||||
formatTwoStageRoutes,
|
||||
formatFlatteningRoutes
|
||||
getHistoryMode,
|
||||
getTopMenu,
|
||||
handleAliveRoute,
|
||||
initRouter,
|
||||
isOneOfArray
|
||||
} from "./utils";
|
||||
import {
|
||||
type Router,
|
||||
createRouter,
|
||||
type RouteRecordRaw,
|
||||
type RouteComponent
|
||||
type RouteComponent,
|
||||
type Router,
|
||||
type RouteRecordRaw
|
||||
} from "vue-router";
|
||||
import {
|
||||
type DataInfo,
|
||||
userKey,
|
||||
multipleTabsKey,
|
||||
removeToken,
|
||||
multipleTabsKey
|
||||
userKey
|
||||
} from "@/utils/auth";
|
||||
|
||||
/** 自动导入全部静态路由,无需再手动引入!匹配 src/router/modules 目录(任何嵌套级别)中具有 .ts 扩展名的所有文件,除了 remaining.ts 文件
|
||||
|
@ -121,15 +121,16 @@ router.beforeEach((to: ToRouteType, _from, next) => {
|
|||
to.matched.some(item => {
|
||||
if (!item.meta.title) return "";
|
||||
const Title = getConfig().Title;
|
||||
if (Title)
|
||||
document.title = `${transformI18n(item.meta.title)} | ${Title}`;
|
||||
else document.title = transformI18n(item.meta.title);
|
||||
if (Title) document.title = `${$t(item.meta.title)} | ${Title}`;
|
||||
else document.title = $t(item.meta.title);
|
||||
});
|
||||
}
|
||||
|
||||
/** 如果已经登录并存在登录信息后不能跳转到路由白名单,而是继续保持在当前页面 */
|
||||
function toCorrectRoute() {
|
||||
whiteList.includes(to.fullPath) ? next(_from.fullPath) : next();
|
||||
}
|
||||
|
||||
if (Cookies.get(multipleTabsKey) && userInfo) {
|
||||
// 无权限跳转403页面
|
||||
if (to.meta?.roles && !isOneOfArray(to.meta?.roles, userInfo?.roles)) {
|
||||
|
|
|
@ -5,8 +5,8 @@ export default {
|
|||
redirect: "/error/403",
|
||||
meta: {
|
||||
icon: "ri:information-line",
|
||||
// showLink: false,
|
||||
title: $t("menus.pureAbnormal"),
|
||||
showLink: false,
|
||||
title: "menus.pureAbnormal",
|
||||
rank: 9
|
||||
},
|
||||
children: [
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { $t } from "@/plugins/i18n";
|
||||
const { VITE_HIDE_HOME } = import.meta.env;
|
||||
const Layout = () => import("@/layout/index.vue");
|
||||
|
||||
|
@ -9,7 +8,7 @@ export default {
|
|||
redirect: "/welcome",
|
||||
meta: {
|
||||
icon: "ep:home-filled",
|
||||
title: $t("menus.pureHome"),
|
||||
title: "menus.home",
|
||||
rank: 0
|
||||
},
|
||||
children: [
|
||||
|
@ -18,8 +17,8 @@ export default {
|
|||
name: "Welcome",
|
||||
component: () => import("@/views/welcome/index.vue"),
|
||||
meta: {
|
||||
title: $t("menus.pureHome"),
|
||||
showLink: VITE_HIDE_HOME === "true" ? false : true
|
||||
title: "menus.home",
|
||||
showLink: VITE_HIDE_HOME !== "true"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { $t } from "@/plugins/i18n";
|
||||
|
||||
const Layout = () => import("@/layout/index.vue");
|
||||
|
||||
export default [
|
||||
|
@ -7,7 +8,7 @@ export default [
|
|||
name: "Login",
|
||||
component: () => import("@/views/login/index.vue"),
|
||||
meta: {
|
||||
title: $t("menus.pureLogin"),
|
||||
title: "menus.pureLogin",
|
||||
showLink: false,
|
||||
rank: 101
|
||||
}
|
||||
|
|
|
@ -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 { createPinia } from "pinia";
|
||||
import piniaPluginPersistedState from "pinia-plugin-persistedstate";
|
||||
|
||||
const store = createPinia();
|
||||
|
||||
export function setupStore(app: App<Element>) {
|
||||
store.use(piniaPluginPersistedState);
|
||||
app.use(store);
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ import { message } from "@/utils/message";
|
|||
import { loginRules } from "./utils/rule";
|
||||
import { useNav } from "@/layout/hooks/useNav";
|
||||
import type { FormInstance } from "element-plus";
|
||||
import { $t, transformI18n } from "@/plugins/i18n";
|
||||
import { $t } from "@/plugins/i18n";
|
||||
import { useLayout } from "@/layout/hooks/useLayout";
|
||||
import { useUserStoreHook } from "@/store/modules/user";
|
||||
import { getTopMenu, initRouter } from "@/router/utils";
|
||||
|
@ -56,11 +56,11 @@ const onLogin = async (formEl: FormInstance | undefined) => {
|
|||
// 获取后端路由
|
||||
return initRouter().then(() => {
|
||||
router.push(getTopMenu(true).path).then(() => {
|
||||
message(t("login.pureLoginSuccess"), { type: "success" });
|
||||
message(t("login.loginSuccess"), { type: "success" });
|
||||
});
|
||||
});
|
||||
} else {
|
||||
message(t("login.pureLoginFail"), { type: "error" });
|
||||
message(t("login.loginFail"), { type: "error" });
|
||||
}
|
||||
})
|
||||
.finally(() => (loading.value = false));
|
||||
|
@ -86,7 +86,7 @@ onBeforeUnmount(() => {
|
|||
|
||||
<template>
|
||||
<div class="select-none">
|
||||
<img :src="bg" class="wave" />
|
||||
<img :src="bg" alt="" class="wave" />
|
||||
<div class="flex-c absolute right-5 top-3">
|
||||
<!-- 主题 -->
|
||||
<el-switch
|
||||
|
@ -151,7 +151,7 @@ onBeforeUnmount(() => {
|
|||
:rules="[
|
||||
{
|
||||
required: true,
|
||||
message: transformI18n($t('login.pureUsernameReg')),
|
||||
message: $t('login.usernameRegex'),
|
||||
trigger: 'blur'
|
||||
}
|
||||
]"
|
||||
|
@ -159,7 +159,7 @@ onBeforeUnmount(() => {
|
|||
>
|
||||
<el-input
|
||||
v-model="ruleForm.username"
|
||||
:placeholder="t('login.pureUsername')"
|
||||
:placeholder="t('login.username')"
|
||||
:prefix-icon="useRenderIcon(User)"
|
||||
clearable
|
||||
/>
|
||||
|
@ -170,7 +170,7 @@ onBeforeUnmount(() => {
|
|||
<el-form-item prop="password">
|
||||
<el-input
|
||||
v-model="ruleForm.password"
|
||||
:placeholder="t('login.purePassword')"
|
||||
:placeholder="t('login.password')"
|
||||
:prefix-icon="useRenderIcon(Lock)"
|
||||
clearable
|
||||
show-password
|
||||
|
@ -186,7 +186,7 @@ onBeforeUnmount(() => {
|
|||
type="primary"
|
||||
@click="onLogin(ruleFormRef)"
|
||||
>
|
||||
{{ t("login.pureLogin") }}
|
||||
{{ t("login.login") }}
|
||||
</el-button>
|
||||
</Motion>
|
||||
</el-form>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { reactive } from "vue";
|
||||
import type { FormRules } from "element-plus";
|
||||
import { $t, transformI18n } from "@/plugins/i18n";
|
||||
import { $t } from "@/plugins/i18n";
|
||||
|
||||
/** 密码正则(密码格式应为8-18位数字、字母、符号的任意两种组合) */
|
||||
export const REGEXP_PWD =
|
||||
|
@ -12,9 +12,9 @@ const loginRules = reactive(<FormRules>{
|
|||
{
|
||||
validator: (rule, value, callback) => {
|
||||
if (value === "") {
|
||||
callback(new Error(transformI18n($t("login.purePassWordReg"))));
|
||||
callback(new Error($t("login.purePassWordReg")));
|
||||
} else if (!REGEXP_PWD.test(value)) {
|
||||
callback(new Error(transformI18n($t("login.purePassWordRuleReg"))));
|
||||
callback(new Error($t("login.purePassWordRuleReg")));
|
||||
} else {
|
||||
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