Merge branch 'main' into gitee

This commit is contained in:
xiaoxian521 2024-04-17 15:47:06 +08:00
commit 3720c15712
40 changed files with 492 additions and 225 deletions

View File

@ -41,7 +41,7 @@
- 修复`windwos`下点击注册页面会出现滚动条问题 - 修复`windwos`下点击注册页面会出现滚动条问题
- 修复`windows`下页面切换,内容区会出现滚动条问题 - 修复`windows`下页面切换,内容区会出现滚动条问题
- 修复`pure-table`带状态表格在深色整体风格下状态样式消失的问题 - 修复`pure-table`带状态表格在深色整体风格下状态样式消失的问题
- 修复项目配置中开启灰色模式和深色整体风格,刷新页面整体风格异常 - 修复系统配置中开启灰色模式和深色整体风格,刷新页面整体风格异常
### 🍏 Perf ### 🍏 Perf
@ -84,7 +84,7 @@
- 所有`search`搜索图标统一替换为`@iconify-icons/ri/search-line`它比较常用将其放入全局离线图标中 - 所有`search`搜索图标统一替换为`@iconify-icons/ri/search-line`它比较常用将其放入全局离线图标中
- 移除`iframe`在暗模式下的滤镜效果 - 移除`iframe`在暗模式下的滤镜效果
- 带来更美观精致的首页 - 带来更美观精致的首页
- 更干净整洁的项目配置右侧弹出面板 - 更干净整洁的系统配置右侧弹出面板
- 重构关于页面,整体更紧致,关键信息更突出 - 重构关于页面,整体更紧致,关键信息更突出
### 🎫 Feat ### 🎫 Feat

View File

@ -2,7 +2,7 @@ buttons:
pureAccountSettings: Account pureAccountSettings: Account
pureLoginOut: LoginOut pureLoginOut: LoginOut
pureLogin: Login pureLogin: Login
pureSystemSet: Open ProjectConfig pureOpenSystemSet: Open System Configs
pureReload: Reload pureReload: Reload
pureCloseCurrentTab: Close CurrentTab pureCloseCurrentTab: Close CurrentTab
pureCloseLeftTabs: Close LeftTabs pureCloseLeftTabs: Close LeftTabs
@ -11,6 +11,54 @@ buttons:
pureCloseAllTabs: Close AllTabs pureCloseAllTabs: Close AllTabs
pureContentFullScreen: Content FullScreen pureContentFullScreen: Content FullScreen
pureContentExitFullScreen: Content ExitFullScreen 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
pureInterfaceDisplay: Interface Display
pureGreyModel: Grey Model
pureWeakModel: Weak Model
pureHiddenTags: Hidden Tags
pureHiddenFooter: Hidden Footer
pureMultiTagsCache: MultiTags Cache
menus: menus:
pureHome: Home pureHome: Home
pureLogin: Login pureLogin: Login
@ -136,6 +184,7 @@ menus:
pureChildMenuOverflow: Child Menu Overflow Show Tooltip Text pureChildMenuOverflow: Child Menu Overflow Show Tooltip Text
status: status:
pureLoad: Loading... pureLoad: Loading...
pureNoMessage: No Message
login: login:
pureUsername: Username pureUsername: Username
purePassword: Password purePassword: Password
@ -160,6 +209,7 @@ login:
pureTip: After scanning the code, click "Confirm" to complete the login pureTip: After scanning the code, click "Confirm" to complete the login
pureDefinite: Definite pureDefinite: Definite
pureLoginSuccess: Login Success pureLoginSuccess: Login Success
pureLoginFail: Login Fail
pureRegisterSuccess: Regist Success pureRegisterSuccess: Regist Success
pureTickPrivacy: Please tick Privacy Policy pureTickPrivacy: Please tick Privacy Policy
pureReadAccept: I have read it carefully and accept pureReadAccept: I have read it carefully and accept

View File

@ -2,7 +2,7 @@ buttons:
pureAccountSettings: 账户设置 pureAccountSettings: 账户设置
pureLoginOut: 退出系统 pureLoginOut: 退出系统
pureLogin: 登录 pureLogin: 登录
pureSystemSet: 打开项目配置 pureOpenSystemSet: 打开系统配置
pureReload: 重新加载 pureReload: 重新加载
pureCloseCurrentTab: 关闭当前标签页 pureCloseCurrentTab: 关闭当前标签页
pureCloseLeftTabs: 关闭左侧标签页 pureCloseLeftTabs: 关闭左侧标签页
@ -11,6 +11,54 @@ buttons:
pureCloseAllTabs: 关闭全部标签页 pureCloseAllTabs: 关闭全部标签页
pureContentFullScreen: 内容区全屏 pureContentFullScreen: 内容区全屏
pureContentExitFullScreen: 内容区退出全屏 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: 卡片标签,高效浏览
pureInterfaceDisplay: 界面显示
pureGreyModel: 灰色模式
pureWeakModel: 色弱模式
pureHiddenTags: 隐藏标签页
pureHiddenFooter: 隐藏页脚
pureMultiTagsCache: 页签持久化
menus: menus:
pureHome: 首页 pureHome: 首页
pureLogin: 登录 pureLogin: 登录
@ -136,6 +184,7 @@ menus:
pureChildMenuOverflow: 菜单超出显示 Tooltip 文字提示 pureChildMenuOverflow: 菜单超出显示 Tooltip 文字提示
status: status:
pureLoad: 加载中... pureLoad: 加载中...
pureNoMessage: 暂无消息
login: login:
pureUsername: 账号 pureUsername: 账号
purePassword: 密码 purePassword: 密码
@ -160,6 +209,7 @@ login:
pureTip: 扫码后点击"确认",即可完成登录 pureTip: 扫码后点击"确认",即可完成登录
pureDefinite: 确定 pureDefinite: 确定
pureLoginSuccess: 登录成功 pureLoginSuccess: 登录成功
pureLoginFail: 登录失败
pureRegisterSuccess: 注册成功 pureRegisterSuccess: 注册成功
pureTickPrivacy: 请勾选隐私政策 pureTickPrivacy: 请勾选隐私政策
pureReadAccept: 我已仔细阅读并接受 pureReadAccept: 我已仔细阅读并接受

View File

@ -13,7 +13,6 @@
"preview:build": "pnpm build && vite preview", "preview:build": "pnpm build && vite preview",
"typecheck": "tsc --noEmit && vue-tsc --noEmit --skipLibCheck", "typecheck": "tsc --noEmit && vue-tsc --noEmit --skipLibCheck",
"svgo": "svgo -f . -r", "svgo": "svgo -f . -r",
"cloc": "NODE_OPTIONS=--max-old-space-size=4096 cloc . --exclude-dir=node_modules --exclude-lang=YAML",
"clean:cache": "rimraf .eslintcache && rimraf pnpm-lock.yaml && rimraf node_modules && pnpm store prune && pnpm install", "clean:cache": "rimraf .eslintcache && rimraf pnpm-lock.yaml && rimraf node_modules && pnpm store prune && pnpm install",
"lint:eslint": "eslint --cache --max-warnings 0 \"{src,mock,build}/**/*.{vue,js,ts,tsx}\" --fix", "lint:eslint": "eslint --cache --max-warnings 0 \"{src,mock,build}/**/*.{vue,js,ts,tsx}\" --fix",
"lint:prettier": "prettier --write \"src/**/*.{js,ts,json,tsx,css,scss,vue,html,md}\"", "lint:prettier": "prettier --write \"src/**/*.{js,ts,json,tsx,css,scss,vue,html,md}\"",
@ -137,7 +136,6 @@
"@vitejs/plugin-vue-jsx": "^3.1.0", "@vitejs/plugin-vue-jsx": "^3.1.0",
"autoprefixer": "^10.4.19", "autoprefixer": "^10.4.19",
"boxen": "^7.1.1", "boxen": "^7.1.1",
"cloc": "^2.11.0",
"cssnano": "^6.1.2", "cssnano": "^6.1.2",
"dagre": "^0.8.5", "dagre": "^0.8.5",
"eslint": "^9.0.0", "eslint": "^9.0.0",

210
pnpm-lock.yaml generated
View File

@ -268,9 +268,6 @@ devDependencies:
boxen: boxen:
specifier: ^7.1.1 specifier: ^7.1.1
version: 7.1.1 version: 7.1.1
cloc:
specifier: ^2.11.0
version: 2.11.0
cssnano: cssnano:
specifier: ^6.1.2 specifier: ^6.1.2
version: 6.1.2(postcss@8.4.38) version: 6.1.2(postcss@8.4.38)
@ -805,7 +802,7 @@ packages:
hasBin: true hasBin: true
dependencies: dependencies:
'@commitlint/format': 19.0.3 '@commitlint/format': 19.0.3
'@commitlint/lint': 19.1.0 '@commitlint/lint': 19.2.2
'@commitlint/load': 19.2.0(@types/node@20.12.7)(typescript@5.4.5) '@commitlint/load': 19.2.0(@types/node@20.12.7)(typescript@5.4.5)
'@commitlint/read': 19.2.1 '@commitlint/read': 19.2.1
'@commitlint/types': 19.0.3 '@commitlint/types': 19.0.3
@ -857,19 +854,19 @@ packages:
chalk: 5.3.0 chalk: 5.3.0
dev: true dev: true
/@commitlint/is-ignored@19.0.3: /@commitlint/is-ignored@19.2.2:
resolution: {integrity: sha512-MqDrxJaRSVSzCbPsV6iOKG/Lt52Y+PVwFVexqImmYYFhe51iVJjK2hRhOG2jUAGiUHk4jpdFr0cZPzcBkSzXDQ==} resolution: {integrity: sha512-eNX54oXMVxncORywF4ZPFtJoBm3Tvp111tg1xf4zWXGfhBPKpfKG6R+G3G4v5CPlRROXpAOpQ3HMhA9n1Tck1g==}
engines: {node: '>=v18'} engines: {node: '>=v18'}
dependencies: dependencies:
'@commitlint/types': 19.0.3 '@commitlint/types': 19.0.3
semver: 7.6.0 semver: 7.6.0
dev: true dev: true
/@commitlint/lint@19.1.0: /@commitlint/lint@19.2.2:
resolution: {integrity: sha512-ESjaBmL/9cxm+eePyEr6SFlBUIYlYpI80n+Ltm7IA3MAcrmiP05UMhJdAD66sO8jvo8O4xdGn/1Mt2G5VzfZKw==} resolution: {integrity: sha512-xrzMmz4JqwGyKQKTpFzlN0dx0TAiT7Ran1fqEBgEmEj+PU98crOFtysJgY+QdeSagx6EDRigQIXJVnfrI0ratA==}
engines: {node: '>=v18'} engines: {node: '>=v18'}
dependencies: dependencies:
'@commitlint/is-ignored': 19.0.3 '@commitlint/is-ignored': 19.2.2
'@commitlint/parse': 19.0.3 '@commitlint/parse': 19.0.3
'@commitlint/rules': 19.0.3 '@commitlint/rules': 19.0.3
'@commitlint/types': 19.0.3 '@commitlint/types': 19.0.3
@ -1572,8 +1569,8 @@ packages:
vue-i18n: vue-i18n:
optional: true optional: true
dependencies: dependencies:
'@intlify/message-compiler': 9.12.0 '@intlify/message-compiler': 9.12.1
'@intlify/shared': 9.12.0 '@intlify/shared': 9.12.1
acorn: 8.11.3 acorn: 8.11.3
escodegen: 2.1.0 escodegen: 2.1.0
estree-walker: 2.0.2 estree-walker: 2.0.2
@ -1598,10 +1595,23 @@ packages:
'@intlify/shared': 9.12.0 '@intlify/shared': 9.12.0
source-map-js: 1.2.0 source-map-js: 1.2.0
/@intlify/message-compiler@9.12.1:
resolution: {integrity: sha512-6QrMGdqKUJSkctyg56nvE+h86tjQZTjYFEfx3ghQAXKPXUd1v5josZXrwnSbIEWWeAentlwtB5qW1FE5r2S8AQ==}
engines: {node: '>= 16'}
dependencies:
'@intlify/shared': 9.12.1
source-map-js: 1.2.0
dev: true
/@intlify/shared@9.12.0: /@intlify/shared@9.12.0:
resolution: {integrity: sha512-uBcH55x5CfZynnerWHQxrXbT6yD6j6T7Nt+R2+dHAOAneoMd6BoGvfEzfYscE94rgmjoDqdr+PdGDBLk5I5EjA==} resolution: {integrity: sha512-uBcH55x5CfZynnerWHQxrXbT6yD6j6T7Nt+R2+dHAOAneoMd6BoGvfEzfYscE94rgmjoDqdr+PdGDBLk5I5EjA==}
engines: {node: '>= 16'} engines: {node: '>= 16'}
/@intlify/shared@9.12.1:
resolution: {integrity: sha512-xAAAxaMS7yUCkwXwqUVQmGCPbXSm6oHqMzcqr2IrxJQmC0DmuqoaW0yBeWyd/pG03PPXqGtWhJLnefsiVElzAQ==}
engines: {node: '>= 16'}
dev: true
/@intlify/unplugin-vue-i18n@4.0.0(rollup@2.79.1)(vue-i18n@9.12.0): /@intlify/unplugin-vue-i18n@4.0.0(rollup@2.79.1)(vue-i18n@9.12.0):
resolution: {integrity: sha512-q2Mhqa/mLi0tulfLFO4fMXXvEbkSZpI5yGhNNsLTNJJ41icEGUuyDe+j5zRZIKSkOJRgX6YbCyibTDJdRsukmw==} resolution: {integrity: sha512-q2Mhqa/mLi0tulfLFO4fMXXvEbkSZpI5yGhNNsLTNJJ41icEGUuyDe+j5zRZIKSkOJRgX6YbCyibTDJdRsukmw==}
engines: {node: '>= 14.16'} engines: {node: '>= 14.16'}
@ -1618,9 +1628,9 @@ packages:
optional: true optional: true
dependencies: dependencies:
'@intlify/bundle-utils': 8.0.0(vue-i18n@9.12.0) '@intlify/bundle-utils': 8.0.0(vue-i18n@9.12.0)
'@intlify/shared': 9.12.0 '@intlify/shared': 9.12.1
'@rollup/pluginutils': 5.1.0(rollup@2.79.1) '@rollup/pluginutils': 5.1.0(rollup@2.79.1)
'@vue/compiler-sfc': 3.4.21 '@vue/compiler-sfc': 3.4.22
debug: 4.3.4 debug: 4.3.4
fast-glob: 3.3.2 fast-glob: 3.3.2
js-yaml: 4.1.0 js-yaml: 4.1.0
@ -2084,48 +2094,56 @@ packages:
picomatch: 2.3.1 picomatch: 2.3.1
rollup: 2.79.1 rollup: 2.79.1
/@rollup/rollup-android-arm-eabi@4.14.2: /@rollup/rollup-android-arm-eabi@4.14.3:
resolution: {integrity: sha512-ahxSgCkAEk+P/AVO0vYr7DxOD3CwAQrT0Go9BJyGQ9Ef0QxVOfjDZMiF4Y2s3mLyPrjonchIMH/tbWHucJMykQ==} resolution: {integrity: sha512-X9alQ3XM6I9IlSlmC8ddAvMSyG1WuHk5oUnXGw+yUBs3BFoTizmG1La/Gr8fVJvDWAq+zlYTZ9DBgrlKRVY06g==}
cpu: [arm] cpu: [arm]
os: [android] os: [android]
requiresBuild: true requiresBuild: true
dev: true dev: true
optional: true optional: true
/@rollup/rollup-android-arm64@4.14.2: /@rollup/rollup-android-arm64@4.14.3:
resolution: {integrity: sha512-lAarIdxZWbFSHFSDao9+I/F5jDaKyCqAPMq5HqnfpBw8dKDiCaaqM0lq5h1pQTLeIqueeay4PieGR5jGZMWprw==} resolution: {integrity: sha512-eQK5JIi+POhFpzk+LnjKIy4Ks+pwJ+NXmPxOCSvOKSNRPONzKuUvWE+P9JxGZVxrtzm6BAYMaL50FFuPe0oWMQ==}
cpu: [arm64] cpu: [arm64]
os: [android] os: [android]
requiresBuild: true requiresBuild: true
dev: true dev: true
optional: true optional: true
/@rollup/rollup-darwin-arm64@4.14.2: /@rollup/rollup-darwin-arm64@4.14.3:
resolution: {integrity: sha512-SWsr8zEUk82KSqquIMgZEg2GE5mCSfr9sE/thDROkX6pb3QQWPp8Vw8zOq2GyxZ2t0XoSIUlvHDkrf5Gmf7x3Q==} resolution: {integrity: sha512-Od4vE6f6CTT53yM1jgcLqNfItTsLt5zE46fdPaEmeFHvPs5SjZYlLpHrSiHEKR1+HdRfxuzXHjDOIxQyC3ptBA==}
cpu: [arm64] cpu: [arm64]
os: [darwin] os: [darwin]
requiresBuild: true requiresBuild: true
dev: true dev: true
optional: true optional: true
/@rollup/rollup-darwin-x64@4.14.2: /@rollup/rollup-darwin-x64@4.14.3:
resolution: {integrity: sha512-o/HAIrQq0jIxJAhgtIvV5FWviYK4WB0WwV91SLUnsliw1lSAoLsmgEEgRWzDguAFeUEUUoIWXiJrPqU7vGiVkA==} resolution: {integrity: sha512-0IMAO21axJeNIrvS9lSe/PGthc8ZUS+zC53O0VhF5gMxfmcKAP4ESkKOCwEi6u2asUrt4mQv2rjY8QseIEb1aw==}
cpu: [x64] cpu: [x64]
os: [darwin] os: [darwin]
requiresBuild: true requiresBuild: true
dev: true dev: true
optional: true optional: true
/@rollup/rollup-linux-arm-gnueabihf@4.14.2: /@rollup/rollup-linux-arm-gnueabihf@4.14.3:
resolution: {integrity: sha512-nwlJ65UY9eGq91cBi6VyDfArUJSKOYt5dJQBq8xyLhvS23qO+4Nr/RreibFHjP6t+5ap2ohZrUJcHv5zk5ju/g==} resolution: {integrity: sha512-ge2DC7tHRHa3caVEoSbPRJpq7azhG+xYsd6u2MEnJ6XzPSzQsTKyXvh6iWjXRf7Rt9ykIUWHtl0Uz3T6yXPpKw==}
cpu: [arm] cpu: [arm]
os: [linux] os: [linux]
requiresBuild: true requiresBuild: true
dev: true dev: true
optional: true optional: true
/@rollup/rollup-linux-arm64-gnu@4.14.2: /@rollup/rollup-linux-arm-musleabihf@4.14.3:
resolution: {integrity: sha512-Pg5TxxO2IVlMj79+c/9G0LREC9SY3HM+pfAwX7zj5/cAuwrbfj2Wv9JbMHIdPCfQpYsI4g9mE+2Bw/3aeSs2rQ==} resolution: {integrity: sha512-ljcuiDI4V3ySuc7eSk4lQ9wU8J8r8KrOUvB2U+TtK0TiW6OFDmJ+DdIjjwZHIw9CNxzbmXY39wwpzYuFDwNXuw==}
cpu: [arm]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@rollup/rollup-linux-arm64-gnu@4.14.3:
resolution: {integrity: sha512-Eci2us9VTHm1eSyn5/eEpaC7eP/mp5n46gTRB3Aar3BgSvDQGJZuicyq6TsH4HngNBgVqC5sDYxOzTExSU+NjA==}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
libc: [glibc] libc: [glibc]
@ -2133,8 +2151,8 @@ packages:
dev: true dev: true
optional: true optional: true
/@rollup/rollup-linux-arm64-musl@4.14.2: /@rollup/rollup-linux-arm64-musl@4.14.3:
resolution: {integrity: sha512-cAOTjGNm84gc6tS02D1EXtG7tDRsVSDTBVXOLbj31DkwfZwgTPYZ6aafSU7rD/4R2a34JOwlF9fQayuTSkoclA==} resolution: {integrity: sha512-UrBoMLCq4E92/LCqlh+blpqMz5h1tJttPIniwUgOFJyjWI1qrtrDhhpHPuFxULlUmjFHfloWdixtDhSxJt5iKw==}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
libc: [musl] libc: [musl]
@ -2142,8 +2160,8 @@ packages:
dev: true dev: true
optional: true optional: true
/@rollup/rollup-linux-powerpc64le-gnu@4.14.2: /@rollup/rollup-linux-powerpc64le-gnu@4.14.3:
resolution: {integrity: sha512-4RyT6v1kXb7C0fn6zV33rvaX05P0zHoNzaXI/5oFHklfKm602j+N4mn2YvoezQViRLPnxP8M1NaY4s/5kXO5cw==} resolution: {integrity: sha512-5aRjvsS8q1nWN8AoRfrq5+9IflC3P1leMoy4r2WjXyFqf3qcqsxRCfxtZIV58tCxd+Yv7WELPcO9mY9aeQyAmw==}
cpu: [ppc64] cpu: [ppc64]
os: [linux] os: [linux]
libc: [glibc] libc: [glibc]
@ -2151,8 +2169,8 @@ packages:
dev: true dev: true
optional: true optional: true
/@rollup/rollup-linux-riscv64-gnu@4.14.2: /@rollup/rollup-linux-riscv64-gnu@4.14.3:
resolution: {integrity: sha512-KNUH6jC/vRGAKSorySTyc/yRYlCwN/5pnMjXylfBniwtJx5O7X17KG/0efj8XM3TZU7raYRXJFFReOzNmL1n1w==} resolution: {integrity: sha512-sk/Qh1j2/RJSX7FhEpJn8n0ndxy/uf0kI/9Zc4b1ELhqULVdTfN6HL31CDaTChiBAOgLcsJ1sgVZjWv8XNEsAQ==}
cpu: [riscv64] cpu: [riscv64]
os: [linux] os: [linux]
libc: [glibc] libc: [glibc]
@ -2160,8 +2178,8 @@ packages:
dev: true dev: true
optional: true optional: true
/@rollup/rollup-linux-s390x-gnu@4.14.2: /@rollup/rollup-linux-s390x-gnu@4.14.3:
resolution: {integrity: sha512-xPV4y73IBEXToNPa3h5lbgXOi/v0NcvKxU0xejiFw6DtIYQqOTMhZ2DN18/HrrP0PmiL3rGtRG9gz1QE8vFKXQ==} resolution: {integrity: sha512-jOO/PEaDitOmY9TgkxF/TQIjXySQe5KVYB57H/8LRP/ux0ZoO8cSHCX17asMSv3ruwslXW/TLBcxyaUzGRHcqg==}
cpu: [s390x] cpu: [s390x]
os: [linux] os: [linux]
libc: [glibc] libc: [glibc]
@ -2169,8 +2187,8 @@ packages:
dev: true dev: true
optional: true optional: true
/@rollup/rollup-linux-x64-gnu@4.14.2: /@rollup/rollup-linux-x64-gnu@4.14.3:
resolution: {integrity: sha512-QBhtr07iFGmF9egrPOWyO5wciwgtzKkYPNLVCFZTmr4TWmY0oY2Dm/bmhHjKRwZoGiaKdNcKhFtUMBKvlchH+Q==} resolution: {integrity: sha512-8ybV4Xjy59xLMyWo3GCfEGqtKV5M5gCSrZlxkPGvEPCGDLNla7v48S662HSGwRd6/2cSneMQWiv+QzcttLrrOA==}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
libc: [glibc] libc: [glibc]
@ -2178,8 +2196,8 @@ packages:
dev: true dev: true
optional: true optional: true
/@rollup/rollup-linux-x64-musl@4.14.2: /@rollup/rollup-linux-x64-musl@4.14.3:
resolution: {integrity: sha512-8zfsQRQGH23O6qazZSFY5jP5gt4cFvRuKTpuBsC1ZnSWxV8ZKQpPqOZIUtdfMOugCcBvFGRa1pDC/tkf19EgBw==} resolution: {integrity: sha512-s+xf1I46trOY10OqAtZ5Rm6lzHre/UiLA1J2uOhCFXWkbZrJRkYBPO6FhvGfHmdtQ3Bx793MNa7LvoWFAm93bg==}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
libc: [musl] libc: [musl]
@ -2187,24 +2205,24 @@ packages:
dev: true dev: true
optional: true optional: true
/@rollup/rollup-win32-arm64-msvc@4.14.2: /@rollup/rollup-win32-arm64-msvc@4.14.3:
resolution: {integrity: sha512-H4s8UjgkPnlChl6JF5empNvFHp77Jx+Wfy2EtmYPe9G22XV+PMuCinZVHurNe8ggtwoaohxARJZbaH/3xjB/FA==} resolution: {integrity: sha512-+4h2WrGOYsOumDQ5S2sYNyhVfrue+9tc9XcLWLh+Kw3UOxAvrfOrSMFon60KspcDdytkNDh7K2Vs6eMaYImAZg==}
cpu: [arm64] cpu: [arm64]
os: [win32] os: [win32]
requiresBuild: true requiresBuild: true
dev: true dev: true
optional: true optional: true
/@rollup/rollup-win32-ia32-msvc@4.14.2: /@rollup/rollup-win32-ia32-msvc@4.14.3:
resolution: {integrity: sha512-djqpAjm/i8erWYF0K6UY4kRO3X5+T4TypIqw60Q8MTqSBaQNpNXDhxdjpZ3ikgb+wn99svA7jxcXpiyg9MUsdw==} resolution: {integrity: sha512-T1l7y/bCeL/kUwh9OD4PQT4aM7Bq43vX05htPJJ46RTI4r5KNt6qJRzAfNfM+OYMNEVBWQzR2Gyk+FXLZfogGw==}
cpu: [ia32] cpu: [ia32]
os: [win32] os: [win32]
requiresBuild: true requiresBuild: true
dev: true dev: true
optional: true optional: true
/@rollup/rollup-win32-x64-msvc@4.14.2: /@rollup/rollup-win32-x64-msvc@4.14.3:
resolution: {integrity: sha512-teAqzLT0yTYZa8ZP7zhFKEx4cotS8Tkk5XiqNMJhD4CpaWB1BHARE4Qy+RzwnXvSAYv+Q3jAqCVBS+PS+Yee8Q==} resolution: {integrity: sha512-/BypzV0H1y1HzgYpxqRaXGBRqfodgoBBCcsrujT6QRcakDQdfU+Lq9PENPh5jB4I44YWq+0C2eHsHya+nZY1sA==}
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
requiresBuild: true requiresBuild: true
@ -2724,7 +2742,7 @@ packages:
'@babel/helper-module-imports': 7.22.15 '@babel/helper-module-imports': 7.22.15
'@babel/helper-plugin-utils': 7.24.0 '@babel/helper-plugin-utils': 7.24.0
'@babel/parser': 7.24.4 '@babel/parser': 7.24.4
'@vue/compiler-sfc': 3.4.21 '@vue/compiler-sfc': 3.4.22
dev: true dev: true
/@vue/compiler-core@3.4.21: /@vue/compiler-core@3.4.21:
@ -2736,12 +2754,29 @@ packages:
estree-walker: 2.0.2 estree-walker: 2.0.2
source-map-js: 1.2.0 source-map-js: 1.2.0
/@vue/compiler-core@3.4.22:
resolution: {integrity: sha512-FBDRCBE/rFPA8OfTUrARx2c49N7zoImlGT7hsFikv0pZxQlFhffQwewpEXaLynZW0/DspVXmNA+QQ9dXINpWmg==}
dependencies:
'@babel/parser': 7.24.4
'@vue/shared': 3.4.22
entities: 4.5.0
estree-walker: 2.0.2
source-map-js: 1.2.0
dev: true
/@vue/compiler-dom@3.4.21: /@vue/compiler-dom@3.4.21:
resolution: {integrity: sha512-IZC6FKowtT1sl0CR5DpXSiEB5ayw75oT2bma1BEhV7RRR1+cfwLrxc2Z8Zq/RGFzJ8w5r9QtCOvTjQgdn0IKmA==} resolution: {integrity: sha512-IZC6FKowtT1sl0CR5DpXSiEB5ayw75oT2bma1BEhV7RRR1+cfwLrxc2Z8Zq/RGFzJ8w5r9QtCOvTjQgdn0IKmA==}
dependencies: dependencies:
'@vue/compiler-core': 3.4.21 '@vue/compiler-core': 3.4.21
'@vue/shared': 3.4.21 '@vue/shared': 3.4.21
/@vue/compiler-dom@3.4.22:
resolution: {integrity: sha512-YkAS+jZc6Ip360kT3lZbMQZteiYBbHDSVKr94Jdd8Zjr7VjSkkXKAFFR/FW+2tNtBYXOps6xrWlOquy3GeYB0w==}
dependencies:
'@vue/compiler-core': 3.4.22
'@vue/shared': 3.4.22
dev: true
/@vue/compiler-sfc@3.4.21: /@vue/compiler-sfc@3.4.21:
resolution: {integrity: sha512-me7epoTxYlY+2CUM7hy9PCDdpMPfIwrOvAXud2Upk10g4YLv9UBW7kL798TvMeDhPthkZ0CONNrK2GoeI1ODiQ==} resolution: {integrity: sha512-me7epoTxYlY+2CUM7hy9PCDdpMPfIwrOvAXud2Upk10g4YLv9UBW7kL798TvMeDhPthkZ0CONNrK2GoeI1ODiQ==}
dependencies: dependencies:
@ -2755,12 +2790,33 @@ packages:
postcss: 8.4.38 postcss: 8.4.38
source-map-js: 1.2.0 source-map-js: 1.2.0
/@vue/compiler-sfc@3.4.22:
resolution: {integrity: sha512-Pncp5Vc8E2Ef1o5uveO8WA1IqM7rt0R1jN8D4qitQYOUxC97iITGYA8oMInQ3UcDS7ip+SegyA2HbAEB4V6NMQ==}
dependencies:
'@babel/parser': 7.24.4
'@vue/compiler-core': 3.4.22
'@vue/compiler-dom': 3.4.22
'@vue/compiler-ssr': 3.4.22
'@vue/shared': 3.4.22
estree-walker: 2.0.2
magic-string: 0.30.9
postcss: 8.4.38
source-map-js: 1.2.0
dev: true
/@vue/compiler-ssr@3.4.21: /@vue/compiler-ssr@3.4.21:
resolution: {integrity: sha512-M5+9nI2lPpAsgXOGQobnIueVqc9sisBFexh5yMIMRAPYLa7+5wEJs8iqOZc1WAa9WQbx9GR2twgznU8LTIiZ4Q==} resolution: {integrity: sha512-M5+9nI2lPpAsgXOGQobnIueVqc9sisBFexh5yMIMRAPYLa7+5wEJs8iqOZc1WAa9WQbx9GR2twgznU8LTIiZ4Q==}
dependencies: dependencies:
'@vue/compiler-dom': 3.4.21 '@vue/compiler-dom': 3.4.21
'@vue/shared': 3.4.21 '@vue/shared': 3.4.21
/@vue/compiler-ssr@3.4.22:
resolution: {integrity: sha512-ycb2sL0SW6AkgVMrvaU/TIAEk7FQWyv/oYya44E/V9xURM+ij9Oev5bVobSS7GLJzkUieWW3SrYcK/PZpb5i4A==}
dependencies:
'@vue/compiler-dom': 3.4.22
'@vue/shared': 3.4.22
dev: true
/@vue/devtools-api@6.6.1: /@vue/devtools-api@6.6.1:
resolution: {integrity: sha512-LgPscpE3Vs0x96PzSSB4IGVSZXZBZHpfxs+ZA1d+VEPwHdOXowy/Y2CsvCAIFrf+ssVU1pD1jidj505EpUnfbA==} resolution: {integrity: sha512-LgPscpE3Vs0x96PzSSB4IGVSZXZBZHpfxs+ZA1d+VEPwHdOXowy/Y2CsvCAIFrf+ssVU1pD1jidj505EpUnfbA==}
@ -2774,8 +2830,8 @@ packages:
dependencies: dependencies:
'@volar/language-core': 1.11.1 '@volar/language-core': 1.11.1
'@volar/source-map': 1.11.1 '@volar/source-map': 1.11.1
'@vue/compiler-dom': 3.4.21 '@vue/compiler-dom': 3.4.22
'@vue/shared': 3.4.21 '@vue/shared': 3.4.22
computeds: 0.0.1 computeds: 0.0.1
minimatch: 9.0.4 minimatch: 9.0.4
muggle-string: 0.3.1 muggle-string: 0.3.1
@ -2814,6 +2870,10 @@ packages:
/@vue/shared@3.4.21: /@vue/shared@3.4.21:
resolution: {integrity: sha512-PuJe7vDIi6VYSinuEbUIQgMIRZGgM8e4R+G+/dQTk0X1NEdvgvvgv7m+rfmDH1gZzyA1OjjoWskvHlfRNfQf3g==} resolution: {integrity: sha512-PuJe7vDIi6VYSinuEbUIQgMIRZGgM8e4R+G+/dQTk0X1NEdvgvvgv7m+rfmDH1gZzyA1OjjoWskvHlfRNfQf3g==}
/@vue/shared@3.4.22:
resolution: {integrity: sha512-cg7R9XNk4ovV3bKka/1a464O2oY0l5Fyt0rwGR4hSJRPjUJ0WVjrPdsr4W0JbUriwiM8EKcCcCjeKN5pRMs2Zg==}
dev: true
/@vueuse/core@10.9.0(vue@3.4.21): /@vueuse/core@10.9.0(vue@3.4.21):
resolution: {integrity: sha512-/1vjTol8SXnx6xewDEKfS0Ra//ncg4Hb0DaZiwKf7drgfMsKFExQ+FnnENcN6efPen+1kIzhLQoGSy0eDUVOMg==} resolution: {integrity: sha512-/1vjTol8SXnx6xewDEKfS0Ra//ncg4Hb0DaZiwKf7drgfMsKFExQ+FnnENcN6efPen+1kIzhLQoGSy0eDUVOMg==}
dependencies: dependencies:
@ -3334,7 +3394,7 @@ packages:
postcss: ^8.1.0 postcss: ^8.1.0
dependencies: dependencies:
browserslist: 4.23.0 browserslist: 4.23.0
caniuse-lite: 1.0.30001609 caniuse-lite: 1.0.30001610
fraction.js: 4.3.7 fraction.js: 4.3.7
normalize-range: 0.1.2 normalize-range: 0.1.2
picocolors: 1.0.0 picocolors: 1.0.0
@ -3502,8 +3562,8 @@ packages:
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true hasBin: true
dependencies: dependencies:
caniuse-lite: 1.0.30001609 caniuse-lite: 1.0.30001610
electron-to-chromium: 1.4.735 electron-to-chromium: 1.4.736
node-releases: 2.0.14 node-releases: 2.0.14
update-browserslist-db: 1.0.13(browserslist@4.23.0) update-browserslist-db: 1.0.13(browserslist@4.23.0)
@ -3593,13 +3653,13 @@ packages:
resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==}
dependencies: dependencies:
browserslist: 4.23.0 browserslist: 4.23.0
caniuse-lite: 1.0.30001609 caniuse-lite: 1.0.30001610
lodash.memoize: 4.1.2 lodash.memoize: 4.1.2
lodash.uniq: 4.5.0 lodash.uniq: 4.5.0
dev: true dev: true
/caniuse-lite@1.0.30001609: /caniuse-lite@1.0.30001610:
resolution: {integrity: sha512-JFPQs34lHKx1B5t1EpQpWH4c+29zIyn/haGsbpfq3suuV9v56enjFt23zqijxGTMwy1p/4H2tjnQMY+p1WoAyA==} resolution: {integrity: sha512-QFutAY4NgaelojVMjY63o6XlZyORPaLfyMnsl3HgnWdJUcX6K0oaJymHjH8PT5Gk7sTm8rvC/c5COUQKXqmOMA==}
/canvas@2.11.2: /canvas@2.11.2:
resolution: {integrity: sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==} resolution: {integrity: sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==}
@ -3735,11 +3795,6 @@ packages:
wrap-ansi: 7.0.0 wrap-ansi: 7.0.0
dev: true dev: true
/cloc@2.11.0:
resolution: {integrity: sha512-+mxuCHo7ESOQadlsyMjmPZ4hGBtvQzmNGHfLdBNvXKbnRhtmOTslU4XF2cyFSaOCHaaF26ba2CGjU6lpeIFB0w==}
hasBin: true
dev: true
/co@4.6.0: /co@4.6.0:
resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==}
engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'}
@ -4547,8 +4602,8 @@ packages:
- typescript - typescript
dev: false dev: false
/electron-to-chromium@1.4.735: /electron-to-chromium@1.4.736:
resolution: {integrity: sha512-pkYpvwg8VyOTQAeBqZ7jsmpCjko1Qc6We1ZtZCjRyYbT5v4AIUKDy5cQTRotQlSSZmMr8jqpEt6JtOj5k7lR7A==} resolution: {integrity: sha512-Rer6wc3ynLelKNM4lOCg7/zPQj8tPOCB2hzD32PX9wd3hgRRi9MxEbmkFCokzcEhRVMiOVLjnL9ig9cefJ+6+Q==}
/element-plus@2.1.4(@types/lodash-es@4.17.12)(vue@3.4.21): /element-plus@2.1.4(@types/lodash-es@4.17.12)(vue@3.4.21):
resolution: {integrity: sha512-pcwgDbKUrzyWbixYB/zIbLPLBQ/NPGPJnGXJ+jYozUSthPW4SuriaUGJKgbAE6PDBAtw3IodiT2E2GbiaZLxww==} resolution: {integrity: sha512-pcwgDbKUrzyWbixYB/zIbLPLBQ/NPGPJnGXJ+jYozUSthPW4SuriaUGJKgbAE6PDBAtw3IodiT2E2GbiaZLxww==}
@ -8343,28 +8398,29 @@ packages:
optionalDependencies: optionalDependencies:
fsevents: 2.3.3 fsevents: 2.3.3
/rollup@4.14.2: /rollup@4.14.3:
resolution: {integrity: sha512-WkeoTWvuBoFjFAhsEOHKRoZ3r9GfTyhh7Vff1zwebEFLEFjT1lG3784xEgKiTa7E+e70vsC81roVL2MP4tgEEQ==} resolution: {integrity: sha512-ag5tTQKYsj1bhrFC9+OEWqb5O6VYgtQDO9hPDBMmIbePwhfSr+ExlcU741t8Dhw5DkPCQf6noz0jb36D6W9/hw==}
engines: {node: '>=18.0.0', npm: '>=8.0.0'} engines: {node: '>=18.0.0', npm: '>=8.0.0'}
hasBin: true hasBin: true
dependencies: dependencies:
'@types/estree': 1.0.5 '@types/estree': 1.0.5
optionalDependencies: optionalDependencies:
'@rollup/rollup-android-arm-eabi': 4.14.2 '@rollup/rollup-android-arm-eabi': 4.14.3
'@rollup/rollup-android-arm64': 4.14.2 '@rollup/rollup-android-arm64': 4.14.3
'@rollup/rollup-darwin-arm64': 4.14.2 '@rollup/rollup-darwin-arm64': 4.14.3
'@rollup/rollup-darwin-x64': 4.14.2 '@rollup/rollup-darwin-x64': 4.14.3
'@rollup/rollup-linux-arm-gnueabihf': 4.14.2 '@rollup/rollup-linux-arm-gnueabihf': 4.14.3
'@rollup/rollup-linux-arm64-gnu': 4.14.2 '@rollup/rollup-linux-arm-musleabihf': 4.14.3
'@rollup/rollup-linux-arm64-musl': 4.14.2 '@rollup/rollup-linux-arm64-gnu': 4.14.3
'@rollup/rollup-linux-powerpc64le-gnu': 4.14.2 '@rollup/rollup-linux-arm64-musl': 4.14.3
'@rollup/rollup-linux-riscv64-gnu': 4.14.2 '@rollup/rollup-linux-powerpc64le-gnu': 4.14.3
'@rollup/rollup-linux-s390x-gnu': 4.14.2 '@rollup/rollup-linux-riscv64-gnu': 4.14.3
'@rollup/rollup-linux-x64-gnu': 4.14.2 '@rollup/rollup-linux-s390x-gnu': 4.14.3
'@rollup/rollup-linux-x64-musl': 4.14.2 '@rollup/rollup-linux-x64-gnu': 4.14.3
'@rollup/rollup-win32-arm64-msvc': 4.14.2 '@rollup/rollup-linux-x64-musl': 4.14.3
'@rollup/rollup-win32-ia32-msvc': 4.14.2 '@rollup/rollup-win32-arm64-msvc': 4.14.3
'@rollup/rollup-win32-x64-msvc': 4.14.2 '@rollup/rollup-win32-ia32-msvc': 4.14.3
'@rollup/rollup-win32-x64-msvc': 4.14.3
fsevents: 2.3.3 fsevents: 2.3.3
dev: true dev: true
@ -9484,7 +9540,7 @@ packages:
'@types/node': 20.12.7 '@types/node': 20.12.7
esbuild: 0.20.2 esbuild: 0.20.2
postcss: 8.4.38 postcss: 8.4.38
rollup: 4.14.2 rollup: 4.14.3
sass: 1.75.0 sass: 1.75.0
optionalDependencies: optionalDependencies:
fsevents: 2.3.3 fsevents: 2.3.3

View File

@ -5,7 +5,7 @@ export type UserResult = {
data: { data: {
/** 用户名 */ /** 用户名 */
username: string; username: string;
/** 当前登用户的角色 */ /** 当前登用户的角色 */
roles: Array<string>; roles: Array<string>;
/** `token` */ /** `token` */
accessToken: string; accessToken: string;

View File

@ -42,6 +42,11 @@ const props = {
disabled: { disabled: {
type: Boolean, type: Boolean,
default: false default: false
},
/** 当内容发生变化时,设置 `resize` 可使其自适应容器位置 */
resize: {
type: Boolean,
default: false
} }
}; };
@ -108,7 +113,7 @@ export default defineComponent({
}); });
} }
props.block && handleResizeInit(); (props.block || props.resize) && handleResizeInit();
watch( watch(
() => curIndex.value, () => curIndex.value,

View File

@ -35,7 +35,7 @@ export const getPlatformConfig = async (app: App): Promise<undefined> => {
}) })
.then(({ data: config }) => { .then(({ data: config }) => {
let $config = app.config.globalProperties.$config; let $config = app.config.globalProperties.$config;
// 自动注入项目配置 // 自动注入系统配置
if (app && $config && typeof config === "object") { if (app && $config && typeof config === "object") {
$config = Object.assign($config, config); $config = Object.assign($config, config);
app.config.globalProperties.$config = $config; app.config.globalProperties.$config = $config;

View File

@ -1,4 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { useI18n } from "vue-i18n";
import Footer from "./footer/index.vue"; import Footer from "./footer/index.vue";
import { useGlobal, isNumber } from "@pureadmin/utils"; import { useGlobal, isNumber } from "@pureadmin/utils";
import KeepAliveFrame from "./keepAliveFrame/index.vue"; import KeepAliveFrame from "./keepAliveFrame/index.vue";
@ -10,6 +11,7 @@ const props = defineProps({
fixedHeader: Boolean fixedHeader: Boolean
}); });
const { t } = useI18n();
const { $storage, $config } = useGlobal<GlobalPropertiesApi>(); const { $storage, $config } = useGlobal<GlobalPropertiesApi>();
const isKeepAlive = computed(() => { const isKeepAlive = computed(() => {
@ -121,7 +123,7 @@ const transitionMain = defineComponent({
}" }"
> >
<el-backtop <el-backtop
title="回到顶部" :title="t('buttons.pureBackTop')"
target=".app-main .el-scrollbar__wrap" target=".app-main .el-scrollbar__wrap"
> >
<backTop /> <backTop />

View File

@ -113,7 +113,7 @@ const { t, locale, translationCh, translationEn } = useTranslationLang();
</el-dropdown> </el-dropdown>
<span <span
class="set-icon navbar-bg-hover" class="set-icon navbar-bg-hover"
:title="t('buttons.pureSystemSet')" :title="t('buttons.pureOpenSystemSet')"
@click="onPanel" @click="onPanel"
> >
<IconifyIconOffline :icon="Setting" /> <IconifyIconOffline :icon="Setting" />

View File

@ -1,9 +1,11 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref } from "vue"; import { ref } from "vue";
import { useI18n } from "vue-i18n";
import { noticesData } from "./data"; import { noticesData } from "./data";
import NoticeList from "./noticeList.vue"; import NoticeList from "./noticeList.vue";
import Bell from "@iconify-icons/ep/bell"; import Bell from "@iconify-icons/ep/bell";
const { t } = useI18n();
const noticesNum = ref(0); const noticesNum = ref(0);
const notices = ref(noticesData); const notices = ref(noticesData);
const activeKey = ref(noticesData[0].key); const activeKey = ref(noticesData[0].key);
@ -30,7 +32,7 @@ notices.value.map(v => (noticesNum.value += v.list.length));
> >
<el-empty <el-empty
v-if="notices.length === 0" v-if="notices.length === 0"
description="暂无消息" :description="t('status.pureNoMessage')"
:image-size="60" :image-size="60"
/> />
<span v-else> <span v-else>

View File

@ -1,6 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { PropType } from "vue"; import { PropType } from "vue";
import { ListItem } from "./data"; import { ListItem } from "./data";
import { useI18n } from "vue-i18n";
import NoticeItem from "./noticeItem.vue"; import NoticeItem from "./noticeItem.vue";
const props = defineProps({ const props = defineProps({
@ -9,6 +10,8 @@ const props = defineProps({
default: () => [] default: () => []
} }
}); });
const { t } = useI18n();
</script> </script>
<template> <template>
@ -19,5 +22,5 @@ const props = defineProps({
:noticeItem="item" :noticeItem="item"
/> />
</div> </div>
<el-empty v-else description="暂无消息" /> <el-empty v-else :description="t('status.pureNoMessage')" />
</template> </template>

View File

@ -1,4 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { useI18n } from "vue-i18n";
import { emitter } from "@/utils/mitt"; import { emitter } from "@/utils/mitt";
import { onClickOutside } from "@vueuse/core"; import { onClickOutside } from "@vueuse/core";
import { ref, computed, onMounted, onBeforeUnmount } from "vue"; import { ref, computed, onMounted, onBeforeUnmount } from "vue";
@ -25,6 +26,7 @@ const iconClass = computed(() => {
]; ];
}); });
const { t } = useI18n();
const { onReset } = useDataThemeChange(); const { onReset } = useDataThemeChange();
onClickOutside(target, (event: any) => { onClickOutside(target, (event: any) => {
@ -51,10 +53,12 @@ onBeforeUnmount(() => {
<div <div
class="project-configuration border-b-[1px] border-solid border-[var(--pure-border-color)]" class="project-configuration border-b-[1px] border-solid border-[var(--pure-border-color)]"
> >
<h4 class="dark:text-white">项目配置</h4> <h4 class="dark:text-white">
{{ t("panel.pureSystemSet") }}
</h4>
<span <span
v-tippy="{ v-tippy="{
content: '关闭配置', content: t('panel.pureCloseSystemSet'),
placement: 'bottom-start', placement: 'bottom-start',
zIndex: 41000 zIndex: 41000
}" }"
@ -78,7 +82,7 @@ onBeforeUnmount(() => {
> >
<el-button <el-button
v-tippy="{ v-tippy="{
content: '清空缓存并返回登录页', content: t('panel.pureClearCacheAndToLogin'),
placement: 'left-start', placement: 'left-start',
zIndex: 41000 zIndex: 41000
}" }"
@ -87,7 +91,7 @@ onBeforeUnmount(() => {
bg bg
@click="onReset" @click="onReset"
> >
清空缓存 {{ t("panel.pureClearCache") }}
</el-button> </el-button>
</div> </div>
</div> </div>

View File

@ -1,4 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { useI18n } from "vue-i18n";
import { useNav } from "@/layout/hooks/useNav"; import { useNav } from "@/layout/hooks/useNav";
import mdiKeyboardEsc from "@/assets/svg/keyboard_esc.svg?component"; import mdiKeyboardEsc from "@/assets/svg/keyboard_esc.svg?component";
import enterOutlined from "@/assets/svg/enter_outlined.svg?component"; import enterOutlined from "@/assets/svg/enter_outlined.svg?component";
@ -9,6 +10,7 @@ const props = withDefaults(defineProps<{ total: number }>(), {
total: 0 total: 0
}); });
const { t } = useI18n();
const { device } = useNav(); const { device } = useNav();
</script> </script>
@ -16,22 +18,22 @@ const { device } = useNav();
<div class="search-footer text-[#333] dark:text-white"> <div class="search-footer text-[#333] dark:text-white">
<span class="search-footer-item"> <span class="search-footer-item">
<enterOutlined class="icon" /> <enterOutlined class="icon" />
确认 {{ t("buttons.pureConfirm") }}
</span> </span>
<span class="search-footer-item"> <span class="search-footer-item">
<IconifyIconOffline :icon="ArrowUpLine" class="icon" /> <IconifyIconOffline :icon="ArrowUpLine" class="icon" />
<IconifyIconOffline :icon="ArrowDownLine" class="icon" /> <IconifyIconOffline :icon="ArrowDownLine" class="icon" />
切换 {{ t("buttons.pureSwitch") }}
</span> </span>
<span class="search-footer-item"> <span class="search-footer-item">
<mdiKeyboardEsc class="icon" /> <mdiKeyboardEsc class="icon" />
关闭 {{ t("buttons.pureClose") }}
</span> </span>
<p <p
v-if="device !== 'mobile' && props.total > 0" v-if="device !== 'mobile' && props.total > 0"
class="search-footer-total" class="search-footer-total"
> >
{{ props.total }} {{ `${t("search.pureTotal")} ${props.total}` }}
</p> </p>
</div> </div>
</template> </template>

View File

@ -1,5 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import Sortable from "sortablejs"; import Sortable from "sortablejs";
import { useI18n } from "vue-i18n";
import SearchHistoryItem from "./SearchHistoryItem.vue"; import SearchHistoryItem from "./SearchHistoryItem.vue";
import type { optionsItem, dragItem, Props } from "../types"; import type { optionsItem, dragItem, Props } from "../types";
import { useEpThemeStoreHook } from "@/store/modules/epTheme"; import { useEpThemeStoreHook } from "@/store/modules/epTheme";
@ -19,6 +20,7 @@ const innerHeight = ref();
/** 判断是否停止鼠标移入事件处理 */ /** 判断是否停止鼠标移入事件处理 */
const stopMouseEvent = ref(false); const stopMouseEvent = ref(false);
const { t } = useI18n();
const emit = defineEmits<Emits>(); const emit = defineEmits<Emits>();
const instance = getCurrentInstance()!; const instance = getCurrentInstance()!;
const props = withDefaults(defineProps<Props>(), {}); const props = withDefaults(defineProps<Props>(), {});
@ -141,7 +143,9 @@ defineExpose({ handleScroll });
<template> <template>
<div ref="historyRef" class="history"> <div ref="historyRef" class="history">
<template v-if="historyList.length"> <template v-if="historyList.length">
<div :style="titleStyle">搜索历史</div> <div :style="titleStyle">
{{ t("search.pureHistory") }}
</div>
<div <div
v-for="(item, index) in historyList" v-for="(item, index) in historyList"
:key="item.path" :key="item.path"
@ -160,7 +164,9 @@ defineExpose({ handleScroll });
</template> </template>
<template v-if="collectList.length"> <template v-if="collectList.length">
<div :style="titleStyle"> <div :style="titleStyle">
收藏{{ collectList.length > 1 ? "(可拖拽排序)" : "" }} {{
`${t("search.pureCollect")}${collectList.length > 1 ? t("search.pureDragSort") : ""}`
}}
</div> </div>
<div class="collect-container"> <div class="collect-container">
<div <div

View File

@ -6,8 +6,8 @@ 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 { transformI18n, $t } from "@/plugins/i18n";
import type { optionsItem, dragItem } from "../types"; import type { optionsItem, dragItem } from "../types";
import { ref, computed, shallowRef, watch } from "vue"; import { ref, computed, shallowRef, watch } from "vue";
import { useDebounceFn, onKeyStroke } from "@vueuse/core"; import { useDebounceFn, onKeyStroke } from "@vueuse/core";
@ -29,7 +29,7 @@ const emit = defineEmits<Emits>();
const props = withDefaults(defineProps<Props>(), {}); const props = withDefaults(defineProps<Props>(), {});
const router = useRouter(); const router = useRouter();
const { locale } = useI18n(); const { t, locale } = useI18n();
const HISTORY_TYPE = "history"; const HISTORY_TYPE = "history";
const COLLECT_TYPE = "collect"; const COLLECT_TYPE = "collect";
@ -293,7 +293,7 @@ onKeyStroke("ArrowDown", handleDown);
v-model="keyword" v-model="keyword"
size="large" size="large"
clearable clearable
placeholder="搜索菜单(中文模式下支持拼音搜索)" :placeholder="t('search.purePlaceholder')"
@input="handleSearch" @input="handleSearch"
> >
<template #prefix> <template #prefix>
@ -305,7 +305,7 @@ onKeyStroke("ArrowDown", handleDown);
</el-input> </el-input>
<div class="search-content"> <div class="search-content">
<el-scrollbar ref="scrollbarRef" max-height="calc(90vh - 140px)"> <el-scrollbar ref="scrollbarRef" max-height="calc(90vh - 140px)">
<el-empty v-if="showEmpty" description="暂无搜索结果" /> <el-empty v-if="showEmpty" :description="t('search.pureEmpty')" />
<SearchHistory <SearchHistory
v-if="showSearchHistory" v-if="showSearchHistory"
ref="historyRef" ref="historyRef"

View File

@ -9,6 +9,7 @@ import {
onUnmounted, onUnmounted,
onBeforeMount onBeforeMount
} from "vue"; } from "vue";
import { useI18n } from "vue-i18n";
import panel from "../panel/index.vue"; import panel from "../panel/index.vue";
import { emitter } from "@/utils/mitt"; import { emitter } from "@/utils/mitt";
import { useNav } from "@/layout/hooks/useNav"; import { useNav } from "@/layout/hooks/useNav";
@ -26,6 +27,7 @@ import dayIcon from "@/assets/svg/day.svg?component";
import darkIcon from "@/assets/svg/dark.svg?component"; import darkIcon from "@/assets/svg/dark.svg?component";
import systemIcon from "@/assets/svg/system.svg?component"; import systemIcon from "@/assets/svg/system.svg?component";
const { t } = useI18n();
const { device } = useNav(); const { device } = useNav();
const { isDark } = useDark(); const { isDark } = useDark();
const { $storage } = useGlobal<GlobalPropertiesApi>(); const { $storage } = useGlobal<GlobalPropertiesApi>();
@ -145,18 +147,20 @@ function setFalse(Doms): any {
} }
/** 页宽 */ /** 页宽 */
const stretchTypeOptions: Array<OptionsType> = [ const stretchTypeOptions = computed<Array<OptionsType>>(() => {
{ return [
label: "固定", {
tip: "紧凑页面,轻松找到所需信息", label: t("panel.pureStretchFixed"),
value: "fixed" tip: t("panel.pureStretchFixedTip"),
}, value: "fixed"
{ },
label: "自定义", {
tip: "最小1280、最大1600", label: t("panel.pureStretchCustom"),
value: "custom" tip: t("panel.pureStretchCustomTip"),
} value: "custom"
]; }
];
});
const setStretch = value => { const setStretch = value => {
settings.stretch = value; settings.stretch = value;
@ -194,41 +198,43 @@ const pClass = computed(() => {
const themeOptions = computed<Array<OptionsType>>(() => { const themeOptions = computed<Array<OptionsType>>(() => {
return [ return [
{ {
label: "浅色", label: t("panel.pureOverallStyleLight"),
icon: dayIcon, icon: dayIcon,
theme: "light", theme: "light",
tip: "清新启航,点亮舒适的工作界面", tip: t("panel.pureOverallStyleLightTip"),
iconAttrs: { fill: isDark.value ? "#fff" : "#000" } iconAttrs: { fill: isDark.value ? "#fff" : "#000" }
}, },
{ {
label: "深色", label: t("panel.pureOverallStyleDark"),
icon: darkIcon, icon: darkIcon,
theme: "dark", theme: "dark",
tip: "月光序曲,沉醉于夜的静谧雅致", tip: t("panel.pureOverallStyleDarkTip"),
iconAttrs: { fill: isDark.value ? "#fff" : "#000" } iconAttrs: { fill: isDark.value ? "#fff" : "#000" }
}, },
{ {
label: "自动", label: t("panel.pureOverallStyleSystem"),
icon: systemIcon, icon: systemIcon,
theme: "system", theme: "system",
tip: "同步时光,界面随晨昏自然呼应", tip: t("panel.pureOverallStyleSystemTip"),
iconAttrs: { fill: isDark.value ? "#fff" : "#000" } iconAttrs: { fill: isDark.value ? "#fff" : "#000" }
} }
]; ];
}); });
const markOptions: Array<OptionsType> = [ const markOptions = computed<Array<OptionsType>>(() => {
{ return [
label: "灵动", {
tip: "灵动标签,添趣生辉", label: t("panel.pureTagsStyleSmart"),
value: "smart" tip: t("panel.pureTagsStyleSmartTip"),
}, value: "smart"
{ },
label: "卡片", {
tip: "卡片标签,高效浏览", label: t("panel.pureTagsStyleCard"),
value: "card" tip: t("panel.pureTagsStyleCardTip"),
} value: "card"
]; }
];
});
/** 设置导航模式 */ /** 设置导航模式 */
function setLayoutModel(layout: string) { function setLayoutModel(layout: string) {
@ -291,7 +297,7 @@ function watchSystemThemeChange() {
} }
onBeforeMount(() => { onBeforeMount(() => {
/* 初始化项目配置 */ /* 初始化系统配置 */
nextTick(() => { nextTick(() => {
watchSystemThemeChange(); watchSystemThemeChange();
settings.greyVal && settings.greyVal &&
@ -309,8 +315,9 @@ onUnmounted(() => removeMatchMedia);
<template> <template>
<panel> <panel>
<div class="p-5"> <div class="p-5">
<p :class="pClass">整体风格</p> <p :class="pClass">{{ t("panel.pureOverallStyle") }}</p>
<Segmented <Segmented
resize
class="select-none" class="select-none"
:modelValue="overallStyle === 'system' ? 2 : dataTheme ? 1 : 0" :modelValue="overallStyle === 'system' ? 2 : dataTheme ? 1 : 0"
:options="themeOptions" :options="themeOptions"
@ -326,7 +333,7 @@ onUnmounted(() => removeMatchMedia);
" "
/> />
<p :class="['mt-5', pClass]">主题色</p> <p :class="['mt-5', pClass]">{{ t("panel.pureThemeColor") }}</p>
<ul class="theme-color"> <ul class="theme-color">
<li <li
v-for="(item, index) in themeColors" v-for="(item, index) in themeColors"
@ -345,12 +352,12 @@ onUnmounted(() => removeMatchMedia);
</li> </li>
</ul> </ul>
<p :class="['mt-5', pClass]">导航模式</p> <p :class="['mt-5', pClass]">{{ t("panel.pureLayoutModel") }}</p>
<ul class="pure-theme"> <ul class="pure-theme">
<li <li
ref="verticalRef" ref="verticalRef"
v-tippy="{ v-tippy="{
content: '左侧菜单,亲切熟悉', content: t('panel.pureVerticalTip'),
zIndex: 41000 zIndex: 41000
}" }"
:class="layoutTheme.layout === 'vertical' ? 'is-select' : ''" :class="layoutTheme.layout === 'vertical' ? 'is-select' : ''"
@ -363,7 +370,7 @@ onUnmounted(() => removeMatchMedia);
v-if="device !== 'mobile'" v-if="device !== 'mobile'"
ref="horizontalRef" ref="horizontalRef"
v-tippy="{ v-tippy="{
content: '顶部菜单,简洁概览', content: t('panel.pureHorizontalTip'),
zIndex: 41000 zIndex: 41000
}" }"
:class="layoutTheme.layout === 'horizontal' ? 'is-select' : ''" :class="layoutTheme.layout === 'horizontal' ? 'is-select' : ''"
@ -376,7 +383,7 @@ onUnmounted(() => removeMatchMedia);
v-if="device !== 'mobile'" v-if="device !== 'mobile'"
ref="mixRef" ref="mixRef"
v-tippy="{ v-tippy="{
content: '混合菜单,灵活多变', content: t('panel.pureMixTip'),
zIndex: 41000 zIndex: 41000
}" }"
:class="layoutTheme.layout === 'mix' ? 'is-select' : ''" :class="layoutTheme.layout === 'mix' ? 'is-select' : ''"
@ -388,8 +395,9 @@ onUnmounted(() => removeMatchMedia);
</ul> </ul>
<span v-if="useAppStoreHook().getViewportWidth > 1280"> <span v-if="useAppStoreHook().getViewportWidth > 1280">
<p :class="['mt-5', pClass]">页宽</p> <p :class="['mt-5', pClass]">{{ t("panel.pureStretch") }}</p>
<Segmented <Segmented
resize
class="mb-2 select-none" class="mb-2 select-none"
:modelValue="isNumber(settings.stretch) ? 1 : 0" :modelValue="isNumber(settings.stretch) ? 1 : 0"
:options="stretchTypeOptions" :options="stretchTypeOptions"
@ -430,53 +438,56 @@ onUnmounted(() => removeMatchMedia);
</button> </button>
</span> </span>
<p :class="['mt-4', pClass]">页签风格</p> <p :class="['mt-4', pClass]">{{ t("panel.pureTagsStyle") }}</p>
<Segmented <Segmented
resize
class="select-none" class="select-none"
:modelValue="markValue === 'smart' ? 0 : 1" :modelValue="markValue === 'smart' ? 0 : 1"
:options="markOptions" :options="markOptions"
@change="onChange" @change="onChange"
/> />
<p class="mt-5 font-medium text-sm dark:text-white">界面显示</p> <p class="mt-5 font-medium text-sm dark:text-white">
{{ t("panel.pureInterfaceDisplay") }}
</p>
<ul class="setting"> <ul class="setting">
<li> <li>
<span class="dark:text-white">灰色模式</span> <span class="dark:text-white">{{ t("panel.pureGreyModel") }}</span>
<el-switch <el-switch
v-model="settings.greyVal" v-model="settings.greyVal"
inline-prompt inline-prompt
active-text="" :active-text="t('buttons.pureOpenText')"
inactive-text="" :inactive-text="t('buttons.pureCloseText')"
@change="greyChange" @change="greyChange"
/> />
</li> </li>
<li> <li>
<span class="dark:text-white">色弱模式</span> <span class="dark:text-white">{{ t("panel.pureWeakModel") }}</span>
<el-switch <el-switch
v-model="settings.weakVal" v-model="settings.weakVal"
inline-prompt inline-prompt
active-text="" :active-text="t('buttons.pureOpenText')"
inactive-text="" :inactive-text="t('buttons.pureCloseText')"
@change="weekChange" @change="weekChange"
/> />
</li> </li>
<li> <li>
<span class="dark:text-white">隐藏标签页</span> <span class="dark:text-white">{{ t("panel.pureHiddenTags") }}</span>
<el-switch <el-switch
v-model="settings.tabsVal" v-model="settings.tabsVal"
inline-prompt inline-prompt
active-text="" :active-text="t('buttons.pureOpenText')"
inactive-text="" :inactive-text="t('buttons.pureCloseText')"
@change="tagsChange" @change="tagsChange"
/> />
</li> </li>
<li> <li>
<span class="dark:text-white">隐藏页脚</span> <span class="dark:text-white">{{ t("panel.pureHiddenFooter") }}</span>
<el-switch <el-switch
v-model="settings.hideFooter" v-model="settings.hideFooter"
inline-prompt inline-prompt
active-text="" :active-text="t('buttons.pureOpenText')"
inactive-text="" :inactive-text="t('buttons.pureCloseText')"
@change="hideFooterChange" @change="hideFooterChange"
/> />
</li> </li>
@ -487,18 +498,20 @@ onUnmounted(() => removeMatchMedia);
inline-prompt inline-prompt
:active-value="true" :active-value="true"
:inactive-value="false" :inactive-value="false"
active-text="" :active-text="t('buttons.pureOpenText')"
inactive-text="" :inactive-text="t('buttons.pureCloseText')"
@change="logoChange" @change="logoChange"
/> />
</li> </li>
<li> <li>
<span class="dark:text-white">页签持久化</span> <span class="dark:text-white">
{{ t("panel.pureMultiTagsCache") }}
</span>
<el-switch <el-switch
v-model="settings.multiTagsCache" v-model="settings.multiTagsCache"
inline-prompt inline-prompt
active-text="" :active-text="t('buttons.pureOpenText')"
inactive-text="" :inactive-text="t('buttons.pureCloseText')"
@change="multiTagsCacheChange" @change="multiTagsCacheChange"
/> />
</li> </li>

View File

@ -1,5 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed } from "vue"; import { computed } from "vue";
import { useI18n } from "vue-i18n";
import { useGlobal } from "@pureadmin/utils"; import { useGlobal } from "@pureadmin/utils";
import { useNav } from "@/layout/hooks/useNav"; import { useNav } from "@/layout/hooks/useNav";
@ -13,6 +14,7 @@ const props = withDefaults(defineProps<Props>(), {
isActive: false isActive: false
}); });
const { t } = useI18n();
const { tooltipEffect } = useNav(); const { tooltipEffect } = useNav();
const iconClass = computed(() => { const iconClass = computed(() => {
@ -34,7 +36,9 @@ const toggleClick = () => {
<template> <template>
<div <div
v-tippy="{ v-tippy="{
content: props.isActive ? '点击折叠' : '点击展开', content: props.isActive
? t('buttons.pureClickCollapse')
: t('buttons.pureClickExpand'),
theme: tooltipEffect, theme: tooltipEffect,
hideOnClick: 'toggle', hideOnClick: 'toggle',
placement: 'right' placement: 'right'

View File

@ -129,7 +129,7 @@ nextTick(() => {
</el-dropdown> </el-dropdown>
<span <span
class="set-icon navbar-bg-hover" class="set-icon navbar-bg-hover"
:title="t('buttons.pureSystemSet')" :title="t('buttons.pureOpenSystemSet')"
@click="onPanel" @click="onPanel"
> >
<IconifyIconOffline :icon="Setting" /> <IconifyIconOffline :icon="Setting" />

View File

@ -1,5 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed } from "vue"; import { computed } from "vue";
import { useI18n } from "vue-i18n";
import { useGlobal } from "@pureadmin/utils"; import { useGlobal } from "@pureadmin/utils";
import { useNav } from "@/layout/hooks/useNav"; import { useNav } from "@/layout/hooks/useNav";
@ -13,6 +14,7 @@ const props = withDefaults(defineProps<Props>(), {
isActive: false isActive: false
}); });
const { t } = useI18n();
const { tooltipEffect } = useNav(); const { tooltipEffect } = useNav();
const iconClass = computed(() => { const iconClass = computed(() => {
@ -44,7 +46,9 @@ const toggleClick = () => {
<div class="left-collapse"> <div class="left-collapse">
<IconifyIconOffline <IconifyIconOffline
v-tippy="{ v-tippy="{
content: props.isActive ? '点击折叠' : '点击展开', content: props.isActive
? t('buttons.pureClickCollapse')
: t('buttons.pureClickExpand'),
theme: tooltipEffect, theme: tooltipEffect,
hideOnClick: 'toggle', hideOnClick: 'toggle',
placement: 'right' placement: 'right'

View File

@ -162,7 +162,7 @@ watch(
</el-dropdown> </el-dropdown>
<span <span
class="set-icon navbar-bg-hover" class="set-icon navbar-bg-hover"
:title="t('buttons.pureSystemSet')" :title="t('buttons.pureOpenSystemSet')"
@click="onPanel" @click="onPanel"
> >
<IconifyIconOffline :icon="Setting" /> <IconifyIconOffline :icon="Setting" />

View File

@ -1,4 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { useI18n } from "vue-i18n";
import MenuFold from "@iconify-icons/ri/menu-fold-fill"; import MenuFold from "@iconify-icons/ri/menu-fold-fill";
import MenuUnfold from "@iconify-icons/ri/menu-unfold-fill"; import MenuUnfold from "@iconify-icons/ri/menu-unfold-fill";
@ -10,6 +11,8 @@ const props = withDefaults(defineProps<Props>(), {
isActive: false isActive: false
}); });
const { t } = useI18n();
const emit = defineEmits<{ const emit = defineEmits<{
(e: "toggleClick"): void; (e: "toggleClick"): void;
}>(); }>();
@ -22,7 +25,11 @@ const toggleClick = () => {
<template> <template>
<div <div
class="px-3 mr-1 navbar-bg-hover" class="px-3 mr-1 navbar-bg-hover"
:title="props.isActive ? '点击折叠' : '点击展开'" :title="
props.isActive
? t('buttons.pureClickCollapse')
: t('buttons.pureClickExpand')
"
@click="toggleClick" @click="toggleClick"
> >
<IconifyIconOffline <IconifyIconOffline

View File

@ -17,7 +17,8 @@ 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";
const errorInfo = "当前路由配置不正确,请检查配置"; const errorInfo =
"The current routing configuration is incorrect, please check the configuration";
export function useNav() { export function useNav() {
const pureApp = useAppStoreHook(); const pureApp = useAppStoreHook();

View File

@ -3,6 +3,7 @@ import "animate.css";
// src/components/ReIcon/src/offlineIcon.ts 使addIcon // src/components/ReIcon/src/offlineIcon.ts 使addIcon
import "@/components/ReIcon/src/offlineIcon"; import "@/components/ReIcon/src/offlineIcon";
import { setType } from "./types"; import { setType } from "./types";
import { useI18n } from "vue-i18n";
import { useLayout } from "./hooks/useLayout"; import { useLayout } from "./hooks/useLayout";
import { useAppStoreHook } from "@/store/modules/app"; import { useAppStoreHook } from "@/store/modules/app";
import { useSettingStoreHook } from "@/store/modules/settings"; import { useSettingStoreHook } from "@/store/modules/settings";
@ -31,6 +32,7 @@ import Vertical from "./components/sidebar/vertical.vue";
import Horizontal from "./components/sidebar/horizontal.vue"; import Horizontal from "./components/sidebar/horizontal.vue";
import backTop from "@/assets/svg/back_top.svg?component"; import backTop from "@/assets/svg/back_top.svg?component";
const { t } = useI18n();
const appWrapperRef = ref(); const appWrapperRef = ref();
const { isDark } = useDark(); const { isDark } = useDark();
const { layout } = useLayout(); const { layout } = useLayout();
@ -185,7 +187,7 @@ const layoutHeader = defineComponent({
</div> </div>
<el-scrollbar v-else> <el-scrollbar v-else>
<el-backtop <el-backtop
title="回到顶部" :title="t('buttons.pureBackTop')"
target=".main-container .el-scrollbar__wrap" target=".main-container .el-scrollbar__wrap"
> >
<backTop /> <backTop />

View File

@ -81,7 +81,7 @@ function isOneOfArray(a: Array<string>, b: Array<string>) {
: true; : true;
} }
/** 从localStorage里取出当前登用户的角色roles过滤无权限的菜单 */ /** 从localStorage里取出当前登用户的角色roles过滤无权限的菜单 */
function filterNoPermissionTree(data: RouteComponent[]) { function filterNoPermissionTree(data: RouteComponent[]) {
const currentRoles = const currentRoles =
storageLocal().getItem<DataInfo<number>>(userKey)?.roles ?? []; storageLocal().getItem<DataInfo<number>>(userKey)?.roles ?? [];

View File

@ -1,8 +1,12 @@
import { store } from "@/store"; import {
import { defineStore } from "pinia"; type appType,
import type { appType } from "./types"; store,
import { getConfig, responsiveStorageNameSpace } from "@/config"; getConfig,
import { deviceDetection, storageLocal } from "@pureadmin/utils"; defineStore,
storageLocal,
deviceDetection,
responsiveStorageNameSpace
} from "../utils";
export const useAppStore = defineStore({ export const useAppStore = defineStore({
id: "pure-app", id: "pure-app",

View File

@ -1,7 +1,10 @@
import { store } from "@/store"; import {
import { defineStore } from "pinia"; store,
import { storageLocal } from "@pureadmin/utils"; getConfig,
import { getConfig, responsiveStorageNameSpace } from "@/config"; defineStore,
storageLocal,
responsiveStorageNameSpace
} from "../utils";
export const useEpThemeStore = defineStore({ export const useEpThemeStore = defineStore({
id: "pure-epTheme", id: "pure-epTheme",

View File

@ -1,10 +1,18 @@
import { defineStore } from "pinia"; import {
import { store } from "@/store"; type multiType,
import { routerArrays } from "@/layout/types"; type positionType,
store,
isUrl,
isEqual,
isNumber,
isBoolean,
getConfig,
defineStore,
routerArrays,
storageLocal,
responsiveStorageNameSpace
} from "../utils";
import { usePermissionStoreHook } from "./permission"; import { usePermissionStoreHook } from "./permission";
import { responsiveStorageNameSpace } from "@/config";
import type { multiType, positionType } from "./types";
import { isEqual, isBoolean, isUrl, storageLocal } from "@pureadmin/utils";
export const useMultiTagsStore = defineStore({ export const useMultiTagsStore = defineStore({
id: "pure-multiTags", id: "pure-multiTags",
@ -106,6 +114,14 @@ export const useMultiTagsStore = defineStore({
} }
this.multiTags.push(value); this.multiTags.push(value);
this.tagsCache(this.multiTags); this.tagsCache(this.multiTags);
if (
getConfig()?.MaxTagsLevel &&
isNumber(getConfig().MaxTagsLevel)
) {
if (this.multiTags.length > getConfig().MaxTagsLevel) {
this.multiTags.splice(1, 1);
}
}
} }
break; break;
case "splice": case "splice":

View File

@ -1,15 +1,16 @@
import { defineStore } from "pinia";
import { store } from "@/store";
import type { cacheType } from "./types";
import { constantMenus } from "@/router";
import { useMultiTagsStoreHook } from "./multiTags";
import { debounce, getKeyList } from "@pureadmin/utils";
import { import {
type cacheType,
store,
debounce,
ascending, ascending,
getKeyList,
filterTree, filterTree,
defineStore,
constantMenus,
filterNoPermissionTree, filterNoPermissionTree,
formatFlatteningRoutes formatFlatteningRoutes
} from "@/router/utils"; } from "../utils";
import { useMultiTagsStoreHook } from "./multiTags";
export const usePermissionStore = defineStore({ export const usePermissionStore = defineStore({
id: "pure-permission", id: "pure-permission",

View File

@ -1,7 +1,4 @@
import { defineStore } from "pinia"; import { type setType, store, defineStore, getConfig } from "../utils";
import { store } from "@/store";
import { getConfig } from "@/config";
import type { setType } from "./types";
export const useSettingStore = defineStore({ export const useSettingStore = defineStore({
id: "pure-setting", id: "pure-setting",

View File

@ -1,12 +1,19 @@
import { defineStore } from "pinia"; import {
import { store } from "@/store"; type userType,
import type { userType } from "./types"; store,
import { routerArrays } from "@/layout/types"; router,
import { router, resetRouter } from "@/router"; defineStore,
import { storageLocal } from "@pureadmin/utils"; resetRouter,
import { getLogin, refreshTokenApi } from "@/api/user"; routerArrays,
import type { UserResult, RefreshTokenResult } from "@/api/user"; storageLocal
import { useMultiTagsStoreHook } from "@/store/modules/multiTags"; } from "../utils";
import {
type UserResult,
type RefreshTokenResult,
getLogin,
refreshTokenApi
} from "@/api/user";
import { useMultiTagsStoreHook } from "./multiTags";
import { type DataInfo, setToken, removeToken, userKey } from "@/utils/auth"; import { type DataInfo, setToken, removeToken, userKey } from "@/utils/auth";
export const useUserStore = defineStore({ export const useUserStore = defineStore({

29
src/store/utils.ts Normal file
View File

@ -0,0 +1,29 @@
export { store } from "@/store";
export { defineStore } from "pinia";
export { routerArrays } from "@/layout/types";
export { router, resetRouter, constantMenus } from "@/router";
export { getConfig, responsiveStorageNameSpace } from "@/config";
export {
ascending,
filterTree,
filterNoPermissionTree,
formatFlatteningRoutes
} from "@/router/utils";
export {
isUrl,
isEqual,
isNumber,
debounce,
isBoolean,
getKeyList,
storageLocal,
deviceDetection
} from "@pureadmin/utils";
export type {
setType,
appType,
userType,
multiType,
cacheType,
positionType
} from "./types";

View File

@ -117,7 +117,7 @@ html.dark {
} }
} }
/* 项目配置面板 */ /* 系统配置面板 */
.right-panel-items { .right-panel-items {
.el-divider__text { .el-divider__text {
--el-bg-color: var(--el-bg-color); --el-bg-color: var(--el-bg-color);

View File

@ -15,7 +15,7 @@ export interface DataInfo<T> {
username?: string; username?: string;
/** 昵称 */ /** 昵称 */
nickname?: string; nickname?: string;
/** 当前登用户的角色 */ /** 当前登用户的角色 */
roles?: Array<string>; roles?: Array<string>;
} }

View File

@ -35,16 +35,16 @@ class PureHttp {
this.httpInterceptorsResponse(); this.httpInterceptorsResponse();
} }
/** token过期后暂存待执行的请求 */ /** `token`过期后,暂存待执行的请求 */
private static requests = []; private static requests = [];
/** 防止重复刷新token */ /** 防止重复刷新`token` */
private static isRefreshing = false; private static isRefreshing = false;
/** 初始化配置对象 */ /** 初始化配置对象 */
private static initConfig: PureHttpRequestConfig = {}; private static initConfig: PureHttpRequestConfig = {};
/** 保存当前Axios实例对象 */ /** 保存当前`Axios`实例对象 */
private static axiosInstance: AxiosInstance = Axios.create(defaultConfig); private static axiosInstance: AxiosInstance = Axios.create(defaultConfig);
/** 重连原始请求 */ /** 重连原始请求 */
@ -72,7 +72,7 @@ class PureHttp {
PureHttp.initConfig.beforeRequestCallback(config); PureHttp.initConfig.beforeRequestCallback(config);
return config; return config;
} }
/** 请求白名单,放置一些不需要token的接口通过设置请求白名单防止token过期后再请求造成的死循环问题 */ /** 请求白名单,放置一些不需要`token`的接口(通过设置请求白名单,防止`token`过期后再请求造成的死循环问题) */
const whiteList = ["/refresh-token", "/login"]; const whiteList = ["/refresh-token", "/login"];
return whiteList.some(url => config.url.endsWith(url)) return whiteList.some(url => config.url.endsWith(url))
? config ? config
@ -172,22 +172,22 @@ class PureHttp {
}); });
} }
/** 单独抽离的post工具函数 */ /** 单独抽离的`post`工具函数 */
public post<T, P>( public post<T, P>(
url: string, url: string,
params?: AxiosRequestConfig<T>, params?: AxiosRequestConfig<P>,
config?: PureHttpRequestConfig config?: PureHttpRequestConfig
): Promise<P> { ): Promise<T> {
return this.request<P>("post", url, params, config); return this.request<T>("post", url, params, config);
} }
/** 单独抽离的get工具函数 */ /** 单独抽离的`get`工具函数 */
public get<T, P>( public get<T, P>(
url: string, url: string,
params?: AxiosRequestConfig<T>, params?: AxiosRequestConfig<P>,
config?: PureHttpRequestConfig config?: PureHttpRequestConfig
): Promise<P> { ): Promise<T> {
return this.request<P>("get", url, params, config); return this.request<T>("get", url, params, config);
} }
} }

View File

@ -19,10 +19,10 @@ export const injectResponsiveStorage = (app: App, config: PlatformConfigs) => {
darkMode: config.DarkMode ?? false, darkMode: config.DarkMode ?? false,
sidebarStatus: config.SidebarStatus ?? true, sidebarStatus: config.SidebarStatus ?? true,
epThemeColor: config.EpThemeColor ?? "#409EFF", epThemeColor: config.EpThemeColor ?? "#409EFF",
themeColor: config.Theme ?? "light", // 主题色(对应项目配置中的主题色与theme不同的是它不会受到浅色、深色整体风格切换的影响只会在手动点击主题色时改变 themeColor: config.Theme ?? "light", // 主题色(对应系统配置中的主题色与theme不同的是它不会受到浅色、深色整体风格切换的影响只会在手动点击主题色时改变
overallStyle: config.OverallStyle ?? "light" // 整体风格浅色light、深色dark、自动system overallStyle: config.OverallStyle ?? "light" // 整体风格浅色light、深色dark、自动system
}, },
// 项目配置-界面显示 // 系统配置-界面显示
configure: Storage.getData("configure", nameSpace) ?? { configure: Storage.getData("configure", nameSpace) ?? {
grey: config.Grey ?? false, grey: config.Grey ?? false,
weak: config.Weak ?? false, weak: config.Weak ?? false,

View File

@ -51,8 +51,8 @@ const GUIDE_STEPS = [
}, },
{ {
element: document.querySelector(".set-icon") as string | HTMLElement, element: document.querySelector(".set-icon") as string | HTMLElement,
title: "项目配置", title: "系统配置",
intro: "您可以在这里查看项目配置", intro: "您可以在这里查看系统配置",
position: "left" position: "left"
}, },
{ {

View File

@ -77,12 +77,12 @@ const onLogin = async (formEl: FormInstance | undefined) => {
router router
.push(getTopMenu(true).path) .push(getTopMenu(true).path)
.then(() => { .then(() => {
message("登录成功", { type: "success" }); message(t("login.pureLoginSuccess"), { type: "success" });
}) })
.finally(() => (disabled.value = false)); .finally(() => (disabled.value = false));
}); });
} else { } else {
message("登录失败", { type: "error" }); message(t("login.pureLoginFail"), { type: "error" });
} }
}) })
.finally(() => (loading.value = false)); .finally(() => (loading.value = false));

1
types/global.d.ts vendored
View File

@ -87,6 +87,7 @@ declare global {
FixedHeader?: boolean; FixedHeader?: boolean;
HiddenSideBar?: boolean; HiddenSideBar?: boolean;
MultiTagsCache?: boolean; MultiTagsCache?: boolean;
MaxTagsLevel?: number;
KeepAlive?: boolean; KeepAlive?: boolean;
Locale?: string; Locale?: string;
Layout?: string; Layout?: string;