feat: 提交非国际化版本代码

This commit is contained in:
xiaoxian521 2022-10-28 15:32:31 +08:00
parent b811256830
commit 761b0e5ec2
50 changed files with 95 additions and 854 deletions

View File

@ -7,7 +7,6 @@
"bradlc.vscode-tailwindcss",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"lokalise.i18n-ally",
"redhat.vscode-yaml",
"csstools.postcss",
"mikestead.dotenv",

View File

@ -27,13 +27,5 @@
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"i18n-ally.localesPaths": "locales",
"i18n-ally.keystyle": "nested",
"i18n-ally.sortKeys": true,
"i18n-ally.namespace": true,
"i18n-ally.enabledParsers": ["yaml", "js"],
"i18n-ally.sourceLanguage": "en",
"i18n-ally.displayLanguage": "zh-CN",
"i18n-ally.enabledFrameworks": ["vue"],
"iconify.excludes": ["el"]
}

View File

@ -1,4 +1,4 @@
<h1>vue-pure-admin Lite Edition</h1>
<h1>vue-pure-admin Lite Editionno i18n version</h1>
[![license](https://img.shields.io/github/license/xiaoxian521/vue-pure-admin.svg)](LICENSE)
@ -6,7 +6,7 @@
## introduce
The lite version is based on the shelf extracted from [vue-pure-admin](https://github.com/xiaoxian521/vue-pure-admin), which contains the main functions and is more suitable for actual project development, the packaged size is only `3MB`, and will permanently sync the full version of the code
The Lite version is based on the shelf extracted from [vue-pure-admin](https://github.com/xiaoxian521/vue-pure-admin), including the main functions, which is more suitable for actual project development, and the packaged size is lower than ` 3MB`, and will permanently sync the full version of the code. After enabling `brotli` compression and `cdn` to replace the native library mode, the package size is less than `500kb`
## Supporting Video
@ -42,7 +42,6 @@ bilibili: https://www.bilibili.com/video/BV1534y1S7HV/
## ⚠️ Attention
- The Lite version does not accept any issues and prs. If you have any questions, please go to the full version https://github.com/xiaoxian521/vue-pure-admin/issues/new/choose to mention, thank you! ! !
- Don't use the `delete-i18n` branch code, this branch is just for you to completely delete the internationalized references, it won't sync the code! ! ! [Completely remove the internationalization tutorial](https://www.bilibili.com/video/BV1Ru411B7k3/), please be sure to use the code from the `main` branch! ! !
## License

View File

@ -1,4 +1,4 @@
<h1>vue-pure-admin精简版</h1>
<h1>vue-pure-admin精简版(非国际化版本)</h1>
[![license](https://img.shields.io/github/license/xiaoxian521/vue-pure-admin.svg)](LICENSE)
@ -6,7 +6,7 @@
## 介绍
精简版是基于 [vue-pure-admin](https://github.com/xiaoxian521/vue-pure-admin) 提炼出的架子,包含主体功能,更适合实际项目开发,打包后的大小 `3MB`,并且会永久同步完整版的代码
精简版是基于 [vue-pure-admin](https://github.com/xiaoxian521/vue-pure-admin) 提炼出的架子,包含主体功能,更适合实际项目开发,打包后的大小低于 `3MB`,并且会永久同步完整版的代码。开启 `brotli` 压缩和 `cdn` 替换本地库模式后,打包大小低于 `500kb`
## 配套视频
@ -54,7 +54,6 @@ pnpm remove 包名
## ⚠️ 注意
- 精简版不接受任何 `issues``pr`,如果有问题请到完整版 [issues](https://github.com/xiaoxian521/vue-pure-admin/issues/new/choose) 去提,谢谢!!!
- 不要使用 `delete-i18n` 分支代码,这个分支只是给你们完全删除国际化的参考,不会同步代码的!!! [完全删除国际化教程](https://www.bilibili.com/video/BV1Ru411B7k3/) ,请务必使用 `main` 分支的代码!!!
## 许可证

View File

@ -20,11 +20,6 @@ export const cdn = importToCDN({
var: "VueRouter",
path: "vue-router.global.min.js"
},
{
name: "vue-i18n",
var: "VueI18n",
path: "vue-i18n.runtime.global.prod.min.js"
},
// 项目中没有直接安装vue-demi但是pinia用到了所以需要在引入pinia前引入vue-demihttps://github.com/vuejs/pinia/blob/v2/packages/pinia/package.json#L77
{
name: "vue-demi",

View File

@ -1,5 +1,4 @@
import { cdn } from "./cdn";
import { resolve } from "path";
import vue from "@vitejs/plugin-vue";
import { viteBuildInfo } from "./info";
import svgLoader from "vite-svg-loader";
@ -7,7 +6,6 @@ import legacy from "@vitejs/plugin-legacy";
import vueJsx from "@vitejs/plugin-vue-jsx";
import { viteMockServe } from "vite-plugin-mock";
import { configCompressPlugin } from "./compress";
import VueI18n from "@intlify/vite-plugin-vue-i18n";
// import ElementPlus from "unplugin-element-plus/vite";
import { visualizer } from "rollup-plugin-visualizer";
import removeConsole from "vite-plugin-remove-console";
@ -25,12 +23,6 @@ export function getPluginsList(
const lifecycle = process.env.npm_lifecycle_event;
return [
vue(),
// https://github.com/intlify/bundle-tools/tree/main/packages/vite-plugin-vue-i18n
VueI18n({
runtimeOnly: true,
compositionOnly: true,
include: [resolve("locales/**")]
}),
// jsx、tsx语法支持
vueJsx(),
VITE_CDN ? cdn : null,

View File

@ -1,43 +0,0 @@
buttons:
hsLoginOut: LoginOut
hsfullscreen: FullScreen
hsexitfullscreen: ExitFullscreen
hsrefreshRoute: RefreshRoute
hslogin: Login
hsadd: Add
hsmark: Mark/Cancel
hssave: Save
hssearch: Search
hsexpendAll: Expand All
hscollapseAll: Collapse All
hssystemSet: Open ProjectConfig
hsdelete: Delete
hsreload: Reload
hscloseCurrentTab: Close CurrentTab
hscloseLeftTabs: Close LeftTabs
hscloseRightTabs: Close RightTabs
hscloseOtherTabs: Close OtherTabs
hscloseAllTabs: Close AllTabs
hswholeFullScreen: Whole FullScreen
hswholeExitFullScreen: Whole ExitFullScreen
hscontentFullScreen: Content FullScreen
hscontentExitFullScreen: Content ExitFullScreen
menus:
hshome: Home
hslogin: Login
hsabnormal: Abnormal Page
hsfourZeroFour: "404"
hsfourZeroOne: "403"
hsFive: "500"
permission: Permission Manage
permissionPage: Page Permission
permissionButton: Button Permission
status:
hsLoad: Loading...
login:
username: Username
password: Password
login: Login
usernameReg: Please enter username
passwordReg: Please enter password
passwordRuleReg: The password format should be any combination of 8-18 digits

View File

@ -1,43 +0,0 @@
buttons:
hsLoginOut: 退出系统
hsfullscreen: 全屏
hsexitfullscreen: 退出全屏
hsrefreshRoute: 刷新路由
hslogin: 登录
hsadd: 新增
hsmark: 标记/取消
hssave: 保存
hssearch: 搜索
hsexpendAll: 全部展开
hscollapseAll: 全部折叠
hssystemSet: 打开项目配置
hsdelete: 删除
hsreload: 重新加载
hscloseCurrentTab: 关闭当前标签页
hscloseLeftTabs: 关闭左侧标签页
hscloseRightTabs: 关闭右侧标签页
hscloseOtherTabs: 关闭其他标签页
hscloseAllTabs: 关闭全部标签页
hswholeFullScreen: 整体页面全屏
hswholeExitFullScreen: 整体页面退出全屏
hscontentFullScreen: 内容区全屏
hscontentExitFullScreen: 内容区退出全屏
menus:
hshome: 首页
hslogin: 登录
hsabnormal: 异常页面
hsfourZeroFour: "404"
hsfourZeroOne: "403"
hsFive: "500"
permission: 权限管理
permissionPage: 页面权限
permissionButton: 按钮权限
status:
hsLoad: 加载中...
login:
username: 账号
password: 密码
login: 登录
usernameReg: 请输入账号
passwordReg: 请输入密码
passwordRuleReg: 密码格式应为8-18位数字、字母、符号的任意两种组合

View File

@ -10,7 +10,7 @@ import { MockMethod } from "vite-plugin-mock";
const permissionRouter = {
path: "/permission",
meta: {
title: "menus.permission",
title: "权限管理",
icon: "lollipop",
rank: 10
},
@ -19,15 +19,15 @@ const permissionRouter = {
path: "/permission/page/index",
name: "PermissionPage",
meta: {
roles: ["admin", "common"],
title: "menus.permissionPage"
title: "页面权限",
roles: ["admin", "common"]
}
},
{
path: "/permission/button/index",
name: "PermissionButton",
meta: {
title: "menus.permissionButton",
title: "按钮权限",
roles: ["admin", "common"],
auths: ["btn_add", "btn_edit", "btn_delete"]
}

View File

@ -12,7 +12,7 @@
"preview:build": "pnpm build && vite preview",
"typecheck": "tsc --noEmit && vue-tsc --noEmit --skipLibCheck",
"cloc": "NODE_OPTIONS=--max-old-space-size=4096 cloc . --exclude-dir=node_modules --exclude-lang=YAML",
"clean:cache": "rm -rf node_modules && rm -rf .eslintcache && pnpm install",
"clean:cache": "rm -rf node_modules && rm -rf .eslintcache && npm cache clean --force && pnpm install",
"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,less,scss,vue,html,md}\"",
"lint:stylelint": "stylelint --cache --fix \"**/*.{vue,css,scss,postcss,less}\" --cache --cache-location node_modules/.cache/stylelint/",
@ -55,7 +55,6 @@
"resize-observer-polyfill": "^1.5.1",
"responsive-storage": "^2.1.0",
"vue": "^3.2.40",
"vue-i18n": "^9.2.2",
"vue-router": "^4.1.6",
"vue-types": "^4.2.1",
"vxe-table": "^4.3.2",
@ -67,7 +66,6 @@
"@iconify-icons/ep": "^1.2.7",
"@iconify-icons/ri": "^1.2.3",
"@iconify/vue": "^3.2.1",
"@intlify/vite-plugin-vue-i18n": "^6.0.3",
"@pureadmin/theme": "^2.4.0",
"@types/element-resize-detector": "1.1.3",
"@types/js-cookie": "^3.0.1",

211
pnpm-lock.yaml generated
View File

@ -7,7 +7,6 @@ specifiers:
"@iconify-icons/ep": ^1.2.7
"@iconify-icons/ri": ^1.2.3
"@iconify/vue": ^3.2.1
"@intlify/vite-plugin-vue-i18n": ^6.0.3
"@pureadmin/components": ^1.1.0
"@pureadmin/descriptions": ^1.1.0
"@pureadmin/table": ^1.2.0
@ -88,7 +87,6 @@ specifiers:
vite-svg-loader: ^3.6.0
vue: ^3.2.40
vue-eslint-parser: ^8.2.0
vue-i18n: ^9.2.2
vue-router: ^4.1.6
vue-tsc: ^0.40.13
vue-types: ^4.2.1
@ -123,7 +121,6 @@ dependencies:
resize-observer-polyfill: 1.5.1
responsive-storage: 2.1.0
vue: 3.2.41
vue-i18n: 9.2.2_vue@3.2.41
vue-router: 4.1.6_vue@3.2.41
vue-types: 4.2.1_vue@3.2.41
vxe-table: 4.3.5_vue@3.2.41+xe-utils@3.5.7
@ -135,7 +132,6 @@ devDependencies:
"@iconify-icons/ep": 1.2.9
"@iconify-icons/ri": 1.2.3
"@iconify/vue": 3.2.1_vue@3.2.41
"@intlify/vite-plugin-vue-i18n": 6.0.3_vite@3.1.8+vue-i18n@9.2.2
"@pureadmin/theme": 2.4.0
"@types/element-resize-detector": 1.1.3
"@types/js-cookie": 3.0.2
@ -988,131 +984,6 @@ packages:
vue: 3.2.41
dev: true
/@intlify/bundle-utils/3.2.1_vue-i18n@9.2.2:
resolution:
{
integrity: sha512-rf4cLBOnbqmpXVcCdcYHilZpMt1m82syh3WLBJlZvGxN2KkH9HeHVH4+bnibF/SDXCHNh6lM6wTpS/qw+PkcMg==
}
engines: { node: ">= 12" }
peerDependencies:
petite-vue-i18n: "*"
vue-i18n: "*"
peerDependenciesMeta:
petite-vue-i18n:
optional: true
vue-i18n:
optional: true
dependencies:
"@intlify/message-compiler": 9.3.0-beta.6
"@intlify/shared": 9.3.0-beta.6
jsonc-eslint-parser: 1.4.1
source-map: 0.6.1
vue-i18n: 9.2.2_vue@3.2.41
yaml-eslint-parser: 0.3.2
dev: true
/@intlify/core-base/9.2.2:
resolution:
{
integrity: sha512-JjUpQtNfn+joMbrXvpR4hTF8iJQ2sEFzzK3KIESOx+f+uwIjgw20igOyaIdhfsVVBCds8ZM64MoeNSx+PHQMkA==
}
engines: { node: ">= 14" }
dependencies:
"@intlify/devtools-if": 9.2.2
"@intlify/message-compiler": 9.2.2
"@intlify/shared": 9.2.2
"@intlify/vue-devtools": 9.2.2
dev: false
/@intlify/devtools-if/9.2.2:
resolution:
{
integrity: sha512-4ttr/FNO29w+kBbU7HZ/U0Lzuh2cRDhP8UlWOtV9ERcjHzuyXVZmjyleESK6eVP60tGC9QtQW9yZE+JeRhDHkg==
}
engines: { node: ">= 14" }
dependencies:
"@intlify/shared": 9.2.2
dev: false
/@intlify/message-compiler/9.2.2:
resolution:
{
integrity: sha512-IUrQW7byAKN2fMBe8z6sK6riG1pue95e5jfokn8hA5Q3Bqy4MBJ5lJAofUsawQJYHeoPJ7svMDyBaVJ4d0GTtA==
}
engines: { node: ">= 14" }
dependencies:
"@intlify/shared": 9.2.2
source-map: 0.6.1
dev: false
/@intlify/message-compiler/9.3.0-beta.6:
resolution:
{
integrity: sha512-3PJqRJoqvFHExA9DCkf7fZYKbvYne1tYQ0fptJAhUOZsELarh8wr4aPLKWCkQSRuutdrtZ/n5CcPgJgUmVthDw==
}
engines: { node: ">= 14" }
dependencies:
"@intlify/shared": 9.3.0-beta.6
source-map: 0.6.1
dev: true
/@intlify/shared/9.2.2:
resolution:
{
integrity: sha512-wRwTpsslgZS5HNyM7uDQYZtxnbI12aGiBZURX3BTR9RFIKKRWpllTsgzHWvj3HKm3Y2Sh5LPC1r0PDCKEhVn9Q==
}
engines: { node: ">= 14" }
dev: false
/@intlify/shared/9.3.0-beta.6:
resolution:
{
integrity: sha512-ITA1R4tvJYwZXT5x6QCSwxcwQ4dU52zrzVm/EUbgsp8oWzYS1xexBrxyNM80PSQudYvL2rvcZJKQ7yBh7b0LkQ==
}
engines: { node: ">= 14" }
dev: true
/@intlify/vite-plugin-vue-i18n/6.0.3_vite@3.1.8+vue-i18n@9.2.2:
resolution:
{
integrity: sha512-6SgNzPAOCR90wvt368lKzi7f/5ZEWJn22UCGvhFsP3XvKqlF3cVzojahgQ6o+LTdCkExeM6wPgd+haFf28E9VQ==
}
engines: { node: ">= 14.6" }
peerDependencies:
petite-vue-i18n: "*"
vite: ^2.9.0 || ^3.0.0
vue-i18n: "*"
peerDependenciesMeta:
petite-vue-i18n:
optional: true
vite:
optional: true
vue-i18n:
optional: true
dependencies:
"@intlify/bundle-utils": 3.2.1_vue-i18n@9.2.2
"@intlify/shared": 9.3.0-beta.6
"@rollup/pluginutils": 4.2.1
debug: 4.3.4
fast-glob: 3.2.12
source-map: 0.6.1
vite: 3.1.8_sass@1.55.0+terser@5.15.1
vue-i18n: 9.2.2_vue@3.2.41
transitivePeerDependencies:
- supports-color
dev: true
/@intlify/vue-devtools/9.2.2:
resolution:
{
integrity: sha512-+dUyqyCHWHb/UcvY1MlIpO87munedm3Gn6E9WWYdWrMuYLcoIoOEVDWSS8xSwtlPU+kA+MEQTP6Q1iI/ocusJg==
}
engines: { node: ">= 14" }
dependencies:
"@intlify/core-base": 9.2.2
"@intlify/shared": 9.2.2
dev: false
/@jridgewell/gen-mapping/0.1.1:
resolution:
{
@ -2060,17 +1931,6 @@ packages:
through: 2.3.8
dev: true
/acorn-jsx/5.3.2_acorn@7.4.1:
resolution:
{
integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
}
peerDependencies:
acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
dependencies:
acorn: 7.4.1
dev: true
/acorn-jsx/5.3.2_acorn@8.8.0:
resolution:
{
@ -3736,16 +3596,6 @@ packages:
estraverse: 5.3.0
dev: true
/eslint-utils/2.1.0:
resolution:
{
integrity: sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==
}
engines: { node: ">=6" }
dependencies:
eslint-visitor-keys: 1.3.0
dev: true
/eslint-utils/3.0.0_eslint@8.25.0:
resolution:
{
@ -3759,14 +3609,6 @@ packages:
eslint-visitor-keys: 2.1.0
dev: true
/eslint-visitor-keys/1.3.0:
resolution:
{
integrity: sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==
}
engines: { node: ">=4" }
dev: true
/eslint-visitor-keys/2.1.0:
resolution:
{
@ -3833,18 +3675,6 @@ packages:
- supports-color
dev: true
/espree/6.2.1:
resolution:
{
integrity: sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==
}
engines: { node: ">=6.0.0" }
dependencies:
acorn: 7.4.1
acorn-jsx: 5.3.2_acorn@7.4.1
eslint-visitor-keys: 1.3.0
dev: true
/espree/9.4.0:
resolution:
{
@ -4819,20 +4649,6 @@ packages:
hasBin: true
dev: true
/jsonc-eslint-parser/1.4.1:
resolution:
{
integrity: sha512-hXBrvsR1rdjmB2kQmUjf1rEIa+TqHBGMge8pwi++C+Si1ad7EjZrJcpgwym+QGK/pqTx+K7keFAtLlVNdLRJOg==
}
engines: { node: ">=8.10.0" }
dependencies:
acorn: 7.4.1
eslint-utils: 2.1.0
eslint-visitor-keys: 1.3.0
espree: 6.2.1
semver: 6.3.0
dev: true
/jsonfile/6.1.0:
resolution:
{
@ -7670,22 +7486,6 @@ packages:
- supports-color
dev: true
/vue-i18n/9.2.2_vue@3.2.41:
resolution:
{
integrity: sha512-yswpwtj89rTBhegUAv9Mu37LNznyu3NpyLQmozF3i1hYOhwpG8RjcjIFIIfnu+2MDZJGSZPXaKWvnQA71Yv9TQ==
}
engines: { node: ">= 14" }
peerDependencies:
vue: ^3.0.0
dependencies:
"@intlify/core-base": 9.2.2
"@intlify/shared": 9.2.2
"@intlify/vue-devtools": 9.2.2
"@vue/devtools-api": 6.4.5
vue: 3.2.41
dev: false
/vue-router/4.1.6_vue@3.2.41:
resolution:
{
@ -7867,17 +7667,6 @@ packages:
}
dev: true
/yaml-eslint-parser/0.3.2:
resolution:
{
integrity: sha512-32kYO6kJUuZzqte82t4M/gB6/+11WAuHiEnK7FreMo20xsCKPeFH5tDBU7iWxR7zeJpNnMXfJyXwne48D0hGrg==
}
dependencies:
eslint-visitor-keys: 1.3.0
lodash: 4.17.21
yaml: 1.10.2
dev: true
/yaml/1.10.2:
resolution:
{

View File

@ -5,7 +5,6 @@
"HiddenSideBar": false,
"MultiTagsCache": false,
"KeepAlive": true,
"Locale": "zh",
"Layout": "vertical",
"Theme": "default",
"DarkMode": false,

View File

@ -8,7 +8,6 @@
import { defineComponent } from "vue";
import { ElConfigProvider } from "element-plus";
import zhCn from "element-plus/lib/locale/lang/zh-cn";
import en from "element-plus/lib/locale/lang/en";
export default defineComponent({
name: "app",
components: {
@ -16,7 +15,7 @@ export default defineComponent({
},
computed: {
currentLocale() {
return this.$storage.locale?.locale === "zh" ? zhCn : en;
return zhCn;
}
}
});

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="globalization" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 512 512"><path d="M478.33 433.6l-90-218a22 22 0 0 0-40.67 0l-90 218a22 22 0 1 0 40.67 16.79L316.66 406h102.67l18.33 44.39A22 22 0 0 0 458 464a22 22 0 0 0 20.32-30.4zM334.83 362L368 281.65L401.17 362z" fill="currentColor"></path><path d="M267.84 342.92a22 22 0 0 0-4.89-30.7c-.2-.15-15-11.13-36.49-34.73c39.65-53.68 62.11-114.75 71.27-143.49H330a22 22 0 0 0 0-44H214V70a22 22 0 0 0-44 0v20H54a22 22 0 0 0 0 44h197.25c-9.52 26.95-27.05 69.5-53.79 108.36c-31.41-41.68-43.08-68.65-43.17-68.87a22 22 0 0 0-40.58 17c.58 1.38 14.55 34.23 52.86 83.93c.92 1.19 1.83 2.35 2.74 3.51c-39.24 44.35-77.74 71.86-93.85 80.74a22 22 0 1 0 21.07 38.63c2.16-1.18 48.6-26.89 101.63-85.59c22.52 24.08 38 35.44 38.93 36.1a22 22 0 0 0 30.75-4.9z" fill="currentColor"></path></svg>

Before

Width:  |  Height:  |  Size: 965 B

View File

Before

Width:  |  Height:  |  Size: 477 B

After

Width:  |  Height:  |  Size: 477 B

View File

@ -2,12 +2,9 @@
import Search from "./search/index.vue";
import Notice from "./notice/index.vue";
import mixNav from "./sidebar/mixNav.vue";
import avatars from "@/assets/avatars.jpg";
import { useNav } from "@/layout/hooks/useNav";
import Breadcrumb from "./sidebar/breadCrumb.vue";
import topCollapse from "./sidebar/topCollapse.vue";
import { useTranslationLang } from "../hooks/useTranslationLang";
import globalization from "@/assets/svg/globalization.svg?component";
const {
layout,
@ -17,12 +14,8 @@ const {
pureApp,
username,
avatarsStyle,
toggleSideBar,
getDropdownItemStyle,
getDropdownItemClass
toggleSideBar
} = useNav();
const { t, locale, translationCh, translationEn } = useTranslationLang();
</script>
<template>
@ -48,42 +41,13 @@ const { t, locale, translationCh, translationEn } = useTranslationLang();
<Search />
<!-- 通知 -->
<Notice id="header-notice" />
<!-- 国际化 -->
<el-dropdown id="header-translation" trigger="click">
<globalization
class="navbar-bg-hover w-[40px] h-[48px] p-[11px] cursor-pointer outline-none"
/>
<template #dropdown>
<el-dropdown-menu class="translation">
<el-dropdown-item
:style="getDropdownItemStyle(locale, 'zh')"
:class="['dark:!text-white', getDropdownItemClass(locale, 'zh')]"
@click="translationCh"
>
<IconifyIconOffline
class="check-zh"
v-show="locale === 'zh'"
icon="check"
/>
简体中文
</el-dropdown-item>
<el-dropdown-item
:style="getDropdownItemStyle(locale, 'en')"
:class="['dark:!text-white', getDropdownItemClass(locale, 'en')]"
@click="translationEn"
>
<span class="check-en" v-show="locale === 'en'">
<IconifyIconOffline icon="check" />
</span>
English
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<!-- 退出登录 -->
<el-dropdown trigger="click">
<span class="el-dropdown-link navbar-bg-hover select-none">
<img v-if="avatars" :src="avatars" :style="avatarsStyle" />
<img
src="https://avatars.githubusercontent.com/u/44761321?v=4"
:style="avatarsStyle"
/>
<p v-if="username" class="dark:text-white">{{ username }}</p>
</span>
<template #dropdown>
@ -93,14 +57,14 @@ const { t, locale, translationCh, translationEn } = useTranslationLang();
icon="logout-circle-r-line"
style="margin: 5px"
/>
{{ t("buttons.hsLoginOut") }}
退出系统
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<span
class="set-icon navbar-bg-hover"
:title="t('buttons.hssystemSet')"
title="打开项目配置"
@click="onPanel"
>
<IconifyIconOffline icon="setting" />
@ -157,22 +121,6 @@ const { t, locale, translationCh, translationEn } = useTranslationLang();
}
}
.translation {
::v-deep(.el-dropdown-menu__item) {
padding: 5px 40px;
}
.check-zh {
position: absolute;
left: 20px;
}
.check-en {
position: absolute;
left: 20px;
}
}
.logout {
max-width: 120px;

View File

@ -1,8 +1,6 @@
<script setup lang="ts">
import { useI18n } from "vue-i18n";
import { useFullscreen } from "@vueuse/core";
const { t } = useI18n();
const { isFullscreen, toggle } = useFullscreen();
</script>
@ -12,9 +10,7 @@ const { isFullscreen, toggle } = useFullscreen();
@click="toggle"
>
<FontIcon
:title="
isFullscreen ? t('buttons.hsexitfullscreen') : t('buttons.hsfullscreen')
"
:title="isFullscreen ? '退出全屏' : '全屏'"
:icon="isFullscreen ? 'team-iconexit-fullscreen' : 'team-iconfullscreen'"
/>
</div>

View File

@ -18,7 +18,7 @@
<script lang="ts" setup>
import enterOutlined from "@/assets/svg/enter_outlined.svg?component";
import mdiKeyboardEsc from "@/assets/svg/mdi_keyboard_esc.svg?component";
import mdiKeyboardEsc from "@/assets/svg/keyboard_esc.svg?component";
</script>
<style lang="scss" scoped>
.search-footer {

View File

@ -4,7 +4,6 @@ import { cloneDeep } from "lodash-unified";
import SearchResult from "./SearchResult.vue";
import SearchFooter from "./SearchFooter.vue";
import { useNav } from "@/layout/hooks/useNav";
import { transformI18n } from "@/plugins/i18n";
import { deleteChildren } from "@pureadmin/utils";
import { useDebounceFn, onKeyStroke } from "@vueuse/core";
import { ref, watch, computed, nextTick, shallowRef } from "vue";
@ -71,7 +70,7 @@ function search() {
resultOptions.value = flatMenusData.filter(
menu =>
keyword.value &&
transformI18n(menu.meta?.title)
menu.meta?.title
.toLocaleLowerCase()
.includes(keyword.value.toLocaleLowerCase().trim())
);

View File

@ -1,12 +1,9 @@
<script lang="ts" setup>
import { computed } from "vue";
import { useI18n } from "vue-i18n";
import { useEpThemeStoreHook } from "@/store/modules/epTheme";
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
import enterOutlined from "@/assets/svg/enter_outlined.svg?component";
const { t } = useI18n();
interface optionsItem {
path: string;
meta?: {
@ -68,7 +65,7 @@ function handleTo() {
@mouseenter="handleMouse(item)"
>
<component :is="useRenderIcon(item.meta?.icon ?? 'bookmark-2-line')" />
<span class="result-item-title">{{ t(item.meta?.title) }}</span>
<span class="result-item-title">{{ item.meta?.title }}</span>
<enterOutlined />
</div>
</template>

View File

@ -1,6 +1,5 @@
<script setup lang="ts">
import { isEqual } from "lodash-unified";
import { transformI18n } from "@/plugins/i18n";
import { ref, watch, onMounted, toRaw } from "vue";
import { getParentPaths, findRouteByPath } from "@/router/utils";
import { useMultiTagsStoreHook } from "@/store/modules/multiTags";
@ -53,7 +52,7 @@ const getBreadcrumb = (): void => {
{
path: "/welcome",
parentPath: "/",
meta: { title: "menus.hshome" }
meta: { title: "首页" }
} as unknown as RouteLocationMatched
].concat(matched);
}
@ -100,7 +99,7 @@ watch(
<transition-group appear name="breadcrumb">
<el-breadcrumb-item v-for="item in levelList" :key="item.path">
<a @click.prevent="handleLink(item)">
{{ transformI18n(item.meta.title) }}
{{ item.meta.title }}
</a>
</el-breadcrumb-item>
</transition-group>

View File

@ -3,17 +3,13 @@ import Search from "../search/index.vue";
import Notice from "../notice/index.vue";
import { ref, watch, nextTick } from "vue";
import SidebarItem from "./sidebarItem.vue";
import avatars from "@/assets/avatars.jpg";
import { useNav } from "@/layout/hooks/useNav";
import { useTranslationLang } from "../../hooks/useTranslationLang";
import { usePermissionStoreHook } from "@/store/modules/permission";
import globalization from "@/assets/svg/globalization.svg?component";
const menuRef = ref();
const { t, route, locale, translationCh, translationEn } =
useTranslationLang(menuRef);
const {
route,
title,
routers,
logout,
@ -21,9 +17,7 @@ const {
onPanel,
menuSelect,
username,
avatarsStyle,
getDropdownItemStyle,
getDropdownItemClass
avatarsStyle
} = useNav();
nextTick(() => {
@ -64,40 +58,13 @@ watch(
<Search />
<!-- 通知 -->
<Notice id="header-notice" />
<!-- 国际化 -->
<el-dropdown id="header-translation" trigger="click">
<globalization
class="navbar-bg-hover w-[40px] h-[48px] p-[11px] cursor-pointer outline-none"
/>
<template #dropdown>
<el-dropdown-menu class="translation">
<el-dropdown-item
:style="getDropdownItemStyle(locale, 'zh')"
:class="['dark:!text-white', getDropdownItemClass(locale, 'zh')]"
@click="translationCh"
>
<span class="check-zh" v-show="locale === 'zh'">
<IconifyIconOffline icon="check" />
</span>
简体中文
</el-dropdown-item>
<el-dropdown-item
:style="getDropdownItemStyle(locale, 'en')"
:class="['dark:!text-white', getDropdownItemClass(locale, 'en')]"
@click="translationEn"
>
<span class="check-en" v-show="locale === 'en'">
<IconifyIconOffline icon="check" />
</span>
English
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<!-- 退出登录 -->
<el-dropdown trigger="click">
<span class="el-dropdown-link navbar-bg-hover">
<img v-if="avatars" :src="avatars" :style="avatarsStyle" />
<img
src="https://avatars.githubusercontent.com/u/44761321?v=4"
:style="avatarsStyle"
/>
<p v-if="username" class="dark:text-white">{{ username }}</p>
</span>
<template #dropdown>
@ -107,14 +74,14 @@ watch(
icon="logout-circle-r-line"
style="margin: 5px"
/>
{{ t("buttons.hsLoginOut") }}
退出系统
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<span
class="set-icon navbar-bg-hover"
:title="t('buttons.hssystemSet')"
title="打开项目配置"
@click="onPanel"
>
<IconifyIconOffline icon="setting" />
@ -124,22 +91,6 @@ watch(
</template>
<style lang="scss" scoped>
.translation {
::v-deep(.el-dropdown-menu__item) {
padding: 5px 40px;
}
.check-zh {
position: absolute;
left: 20px;
}
.check-en {
position: absolute;
left: 20px;
}
}
.logout {
max-width: 120px;

View File

@ -1,22 +1,17 @@
<script setup lang="ts">
import Search from "../search/index.vue";
import Notice from "../notice/index.vue";
import avatars from "@/assets/avatars.jpg";
import { useNav } from "@/layout/hooks/useNav";
import { transformI18n } from "@/plugins/i18n";
import { ref, toRaw, watch, onMounted, nextTick } from "vue";
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
import { getParentPaths, findRouteByPath } from "@/router/utils";
import { useTranslationLang } from "../../hooks/useTranslationLang";
import { usePermissionStoreHook } from "@/store/modules/permission";
import globalization from "@/assets/svg/globalization.svg?component";
const menuRef = ref();
let defaultActive = ref(null);
const { t, route, locale, translationCh, translationEn } =
useTranslationLang(menuRef);
const {
route,
device,
routers,
logout,
@ -24,9 +19,7 @@ const {
menuSelect,
resolvePath,
username,
avatarsStyle,
getDropdownItemStyle,
getDropdownItemClass
avatarsStyle
} = useNav();
function getDefaultActive(routePath) {
@ -79,7 +72,7 @@ watch(
:is="useRenderIcon(route.meta && toRaw(route.meta.icon))"
/>
</div>
<span class="select-none">{{ transformI18n(route.meta.title) }}</span>
<span class="select-none">{{ route.meta.title }}</span>
<FontIcon
v-if="route.meta.extraIcon"
width="30px"
@ -96,40 +89,13 @@ watch(
<Search />
<!-- 通知 -->
<Notice id="header-notice" />
<!-- 国际化 -->
<el-dropdown id="header-translation" trigger="click">
<globalization
class="navbar-bg-hover w-[40px] h-[48px] p-[11px] cursor-pointer outline-none"
/>
<template #dropdown>
<el-dropdown-menu class="translation">
<el-dropdown-item
:style="getDropdownItemStyle(locale, 'zh')"
:class="['dark:!text-white', getDropdownItemClass(locale, 'zh')]"
@click="translationCh"
>
<span class="check-zh" v-show="locale === 'zh'">
<IconifyIconOffline icon="check" />
</span>
简体中文
</el-dropdown-item>
<el-dropdown-item
:style="getDropdownItemStyle(locale, 'en')"
:class="['dark:!text-white', getDropdownItemClass(locale, 'en')]"
@click="translationEn"
>
<span class="check-en" v-show="locale === 'en'">
<IconifyIconOffline icon="check" />
</span>
English
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<!-- 退出登录 -->
<el-dropdown trigger="click">
<span class="el-dropdown-link navbar-bg-hover select-none">
<img v-if="avatars" :src="avatars" :style="avatarsStyle" />
<img
src="https://avatars.githubusercontent.com/u/44761321?v=4"
:style="avatarsStyle"
/>
<p v-if="username" class="dark:text-white">{{ username }}</p>
</span>
<template #dropdown>
@ -139,14 +105,14 @@ watch(
icon="logout-circle-r-line"
style="margin: 5px"
/>
{{ t("buttons.hsLoginOut") }}
退出系统
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<span
class="set-icon navbar-bg-hover"
:title="t('buttons.hssystemSet')"
title="打开项目配置"
@click="onPanel"
>
<IconifyIconOffline icon="setting" />
@ -156,22 +122,6 @@ watch(
</template>
<style lang="scss" scoped>
.translation {
::v-deep(.el-dropdown-menu__item) {
padding: 5px 40px;
}
.check-zh {
position: absolute;
left: 20px;
}
.check-en {
position: absolute;
left: 20px;
}
}
.logout {
max-width: 120px;

View File

@ -2,7 +2,6 @@
import path from "path";
import { childrenType } from "../../types";
import { useNav } from "@/layout/hooks/useNav";
import { transformI18n } from "@/plugins/i18n";
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
import { ref, toRaw, PropType, nextTick, computed, CSSProperties } from "vue";
@ -164,7 +163,7 @@ function resolvePath(routePath) {
:style="getDivStyle"
>
<span :style="getMenuTextStyle">
{{ transformI18n(onlyOneChild.meta.title) }}
{{ onlyOneChild.meta.title }}
</span>
</div>
<div
@ -174,13 +173,13 @@ function resolvePath(routePath) {
:style="getDivStyle"
>
<span :style="getMenuTextStyle">
{{ transformI18n(onlyOneChild.meta.title) }}
{{ onlyOneChild.meta.title }}
</span>
</div>
<template #title>
<div :style="getDivStyle">
<span v-if="layout === 'horizontal'">
{{ transformI18n(onlyOneChild.meta.title) }}
{{ onlyOneChild.meta.title }}
</span>
<el-tooltip
v-else
@ -189,14 +188,14 @@ function resolvePath(routePath) {
:disabled="!onlyOneChild.showTooltip"
>
<template #content>
{{ transformI18n(onlyOneChild.meta.title) }}
{{ onlyOneChild.meta.title }}
</template>
<span
ref="menuTextRef"
:style="getMenuTextStyle"
@mouseover="hoverMenu(onlyOneChild)"
>
{{ transformI18n(onlyOneChild.meta.title) }}
{{ onlyOneChild.meta.title }}
</span>
</el-tooltip>
<FontIcon
@ -220,7 +219,7 @@ function resolvePath(routePath) {
/>
</div>
<span v-if="layout === 'horizontal'">
{{ transformI18n(props.item.meta.title) }}
{{ props.item.meta.title }}
</span>
<el-tooltip
v-else
@ -229,7 +228,7 @@ function resolvePath(routePath) {
:disabled="!isCollapse || !props.item.showTooltip"
>
<template #content>
{{ transformI18n(props.item.meta.title) }}
{{ props.item.meta.title }}
</template>
<div
ref="menuTextRef"
@ -237,7 +236,7 @@ function resolvePath(routePath) {
@mouseover="hoverMenu(props.item)"
>
<span :style="getSpanStyle">
{{ transformI18n(props.item.meta.title) }}
{{ props.item.meta.title }}
</span>
</div>
</el-tooltip>

View File

@ -1,5 +1,4 @@
<script setup lang="ts">
import { $t } from "@/plugins/i18n";
import { emitter } from "@/utils/mitt";
import { RouteConfigs } from "../../types";
import { useTags } from "../../hooks/useTag";
@ -35,7 +34,6 @@ const {
onMounted,
onMouseenter,
onMouseleave,
transformI18n,
onContentFullScreen
} = useTags();
@ -285,10 +283,10 @@ function onClickDrop(key, item, selectRoute?: RouteConfigs) {
setTimeout(() => {
if (isFullscreen.value) {
tagsViews[6].icon = "exit-fullscreen";
tagsViews[6].text = $t("buttons.hswholeExitFullScreen");
tagsViews[6].text = "整体页面退出全屏";
} else {
tagsViews[6].icon = "fullscreen";
tagsViews[6].text = $t("buttons.hswholeFullScreen");
tagsViews[6].text = "整体页面全屏";
}
}, 100);
break;
@ -298,10 +296,10 @@ function onClickDrop(key, item, selectRoute?: RouteConfigs) {
setTimeout(() => {
if (pureSetting.hiddenSideBar) {
tagsViews[7].icon = "exit-fullscreen";
tagsViews[7].text = $t("buttons.hscontentExitFullScreen");
tagsViews[7].text = "内容区退出全屏";
} else {
tagsViews[7].icon = "fullscreen";
tagsViews[7].text = $t("buttons.hscontentFullScreen");
tagsViews[7].text = "内容区全屏";
}
}, 100);
break;
@ -520,7 +518,7 @@ onMounted(() => {
:to="item.path"
class="dark:!text-text_color_primary dark:hover:!text-primary"
>
{{ transformI18n(item.meta.title) }}
{{ item.meta.title }}
</router-link>
<span
v-if="
@ -561,7 +559,7 @@ onMounted(() => {
>
<li v-if="item.show" @click="selectTag(key, item)">
<IconifyIconOffline :icon="item.icon" />
{{ transformI18n(item.text) }}
{{ item.text }}
</li>
</div>
</ul>
@ -585,7 +583,7 @@ onMounted(() => {
:disabled="item.disabled"
>
<IconifyIconOffline :icon="item.icon" />
{{ transformI18n(item.text) }}
{{ item.text }}
</el-dropdown-item>
</el-dropdown-menu>
</template>

View File

@ -1,5 +1,4 @@
<script lang="ts" setup>
import { useI18n } from "vue-i18n";
import { useRoute } from "vue-router";
import { ref, unref, onMounted, nextTick } from "vue";
@ -7,7 +6,6 @@ defineOptions({
name: "FrameView"
});
const { t } = useI18n();
const loading = ref(true);
const currentRoute = useRoute();
const frameSrc = ref<string>("");
@ -45,11 +43,7 @@ onMounted(() => {
</script>
<template>
<div
class="frame"
v-loading="loading"
:element-loading-text="t('status.hsLoad')"
>
<div class="frame" v-loading="loading" element-loading-text="加载中...">
<iframe :src="frameSrc" class="frame-iframe" ref="frameRef" />
</div>
</template>

View File

@ -1,5 +1,4 @@
import { computed } from "vue";
import { useI18n } from "vue-i18n";
import { routerArrays } from "../types";
import { useGlobal } from "@pureadmin/utils";
import { useMultiTagsStore } from "@/store/modules/multiTags";
@ -15,11 +14,6 @@ export function useLayout() {
) {
$storage.tags = routerArrays;
}
/** 国际化 */
if (!$storage.locale) {
$storage.locale = { locale: $config?.Locale ?? "zh" };
useI18n().locale.value = $config?.Locale ?? "zh";
}
/** 导航 */
if (!$storage.layout) {
$storage.layout = {

View File

@ -1,18 +1,17 @@
import { computed } from "vue";
import { getConfig } from "@/config";
import { useRouter } from "vue-router";
import { emitter } from "@/utils/mitt";
import { routeMetaType } from "../types";
import { useGlobal } from "@pureadmin/utils";
import { transformI18n } from "@/plugins/i18n";
import { useRouter, useRoute } from "vue-router";
import { router, remainingPaths } from "@/router";
import { useAppStoreHook } from "@/store/modules/app";
import { useUserStoreHook } from "@/store/modules/user";
import { useEpThemeStoreHook } from "@/store/modules/epTheme";
const errorInfo = "当前路由配置不正确,请检查配置";
export function useNav() {
const route = useRoute();
const pureApp = useAppStoreHook();
const routers = useRouter().options.routes;
@ -21,22 +20,6 @@ export function useNav() {
return useUserStoreHook()?.username;
});
/** 设置国际化选中后的样式 */
const getDropdownItemStyle = computed(() => {
return (locale, t) => {
return {
background: locale === t ? useEpThemeStoreHook().epThemeColor : "",
color: locale === t ? "#f4f4f5" : "#000"
};
};
});
const getDropdownItemClass = computed(() => {
return (locale, t) => {
return locale === t ? "" : "dark:hover:!text-primary";
};
});
const avatarsStyle = computed(() => {
return username.value ? { marginRight: "10px" } : "";
});
@ -61,8 +44,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 = meta.title;
}
/** 退出登录 */
@ -132,6 +115,7 @@ export function useNav() {
}
return {
route,
title,
device,
layout,
@ -148,8 +132,6 @@ export function useNav() {
isCollapse,
pureApp,
username,
avatarsStyle,
getDropdownItemStyle,
getDropdownItemClass
avatarsStyle
};
}

View File

@ -13,7 +13,6 @@ import { isEqual } from "lodash-unified";
import type { StorageConfigs } from "/#/index";
import { useEventListener } from "@vueuse/core";
import { useRoute, useRouter } from "vue-router";
import { transformI18n, $t } from "@/plugins/i18n";
import { useSettingStoreHook } from "@/store/modules/settings";
import { useMultiTagsStoreHook } from "@/store/modules/multiTags";
import { storageLocal, toggleClass, hasClass } from "@pureadmin/utils";
@ -49,56 +48,56 @@ export function useTags() {
const tagsViews = reactive<Array<tagsViewsType>>([
{
icon: "refresh-right",
text: $t("buttons.hsreload"),
text: "重新加载",
divided: false,
disabled: false,
show: true
},
{
icon: "close",
text: $t("buttons.hscloseCurrentTab"),
text: "关闭当前标签页",
divided: false,
disabled: multiTags.value.length > 1 ? false : true,
show: true
},
{
icon: "close-left-tags",
text: $t("buttons.hscloseLeftTabs"),
text: "关闭左侧标签页",
divided: true,
disabled: multiTags.value.length > 1 ? false : true,
show: true
},
{
icon: "close-right-tags",
text: $t("buttons.hscloseRightTabs"),
text: "关闭右侧标签页",
divided: false,
disabled: multiTags.value.length > 1 ? false : true,
show: true
},
{
icon: "close-other-tags",
text: $t("buttons.hscloseOtherTabs"),
text: "关闭其他标签页",
divided: true,
disabled: multiTags.value.length > 2 ? false : true,
show: true
},
{
icon: "close-all-tags",
text: $t("buttons.hscloseAllTabs"),
text: "关闭全部标签页",
divided: false,
disabled: multiTags.value.length > 1 ? false : true,
show: true
},
{
icon: "fullscreen",
text: $t("buttons.hswholeFullScreen"),
text: "整体页面全屏",
divided: true,
disabled: false,
show: true
},
{
icon: "fullscreen",
text: $t("buttons.hscontentFullScreen"),
text: "内容区全屏",
divided: false,
disabled: false,
show: true
@ -224,12 +223,10 @@ export function useTags() {
currentSelect,
scheduleIsActive,
getContextMenuStyle,
$t,
closeMenu,
onMounted,
onMouseenter,
onMouseleave,
transformI18n,
onContentFullScreen
};
}

View File

@ -1,37 +0,0 @@
import { useNav } from "./useNav";
import { useI18n } from "vue-i18n";
import { useRoute } from "vue-router";
import { watch, type Ref } from "vue";
export function useTranslationLang(ref?: Ref) {
const { $storage, changeTitle, handleResize } = useNav();
const { locale, t } = useI18n();
const route = useRoute();
function translationCh() {
$storage.locale = { locale: "zh" };
locale.value = "zh";
ref && handleResize(ref.value);
}
function translationEn() {
$storage.locale = { locale: "en" };
locale.value = "en";
ref && handleResize(ref.value);
}
watch(
() => locale.value,
() => {
changeTitle(route.meta);
}
);
return {
t,
route,
locale,
translationCh,
translationEn
};
}

View File

@ -3,7 +3,7 @@ export const routerArrays: Array<RouteConfigs> = [
path: "/welcome",
parentPath: "/",
meta: {
title: "menus.hshome",
title: "首页",
icon: "home-filled"
}
}

View File

@ -2,7 +2,6 @@ import App from "./App.vue";
import router from "./router";
import { setupStore } from "@/store";
import ElementPlus from "element-plus";
import { useI18n } from "@/plugins/i18n";
import { getServerConfig } from "./config";
import { createApp, Directive } from "vue";
import { MotionPlugin } from "@vueuse/motion";
@ -53,7 +52,7 @@ getServerConfig(app).then(async config => {
await router.isReady();
injectResponsiveStorage(app, config);
setupStore(app);
app.use(MotionPlugin).use(useI18n).use(ElementPlus);
app.use(MotionPlugin).use(ElementPlus);
// .use(useEcharts);
// .use(Table);
// .use(PureDescriptions);

View File

@ -1,74 +0,0 @@
// 多组件库的国际化和本地项目国际化兼容
import { App, WritableComputedRef } from "vue";
import type { StorageConfigs } from "/#/index";
import { storageLocal } from "@pureadmin/utils";
import { type I18n, createI18n } from "vue-i18n";
// element-plus国际化
import enLocale from "element-plus/lib/locale/lang/en";
import zhLocale from "element-plus/lib/locale/lang/zh-cn";
function siphonI18n(prefix = "zh-CN") {
return 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];
})
)[prefix];
}
export const localesConfigs = {
zh: {
...siphonI18n("zh-CN"),
...zhLocale
},
en: {
...siphonI18n("en"),
...enLocale
}
};
/**
* 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*)\./)?.[1];
if (key && Object.keys(siphonI18n("zh-CN")).includes(key)) {
return i18n.global.t.call(i18n.global.locale, message);
} else if (!key && Object.keys(siphonI18n("zh-CN")).includes(message)) {
// 兼容非嵌套形式的国际化写法
return i18n.global.t.call(i18n.global.locale, message);
} else {
return message;
}
}
/** 此函数只是配合i18n Ally插件来进行国际化智能提示并无实际意义只对提示起作用如果不需要国际化可删除 */
export const $t = (key: string) => key;
export const i18n: I18n = createI18n({
legacy: false,
locale:
storageLocal.getItem<StorageConfigs>("responsive-locale")?.locale ?? "zh",
fallbackLocale: "en",
messages: localesConfigs
});
export function useI18n(app: App) {
app.use(i18n);
}

View File

@ -1,11 +1,7 @@
import "xe-utils";
import "./index.scss";
import XEUtils from "xe-utils";
import { App, unref } from "vue";
import { i18n } from "@/plugins/i18n";
import { App } from "vue";
import "font-awesome/css/font-awesome.min.css";
import zh from "vxe-table/lib/locale/lang/zh-CN";
import en from "vxe-table/lib/locale/lang/en-US";
import {
// 核心
@ -60,18 +56,6 @@ VXETable.setup({
},
input: {
clearable: true
},
i18n: (key, args) => {
return unref(i18n.global.locale) === "zh"
? XEUtils.toFormatString(XEUtils.get(zh, key), args)
: XEUtils.toFormatString(XEUtils.get(en, key), args);
},
translate(key) {
const NAMESPACED = ["el.", "buttons."];
if (key && NAMESPACED.findIndex(v => key.includes(v)) !== -1) {
return i18n.global.t.call(i18n.global.locale, key);
}
return key;
}
});

View File

@ -2,7 +2,6 @@ import { getConfig } from "@/config";
import { toRouteType } from "./types";
import NProgress from "@/utils/progress";
import { findIndex } from "lodash-unified";
import { transformI18n } from "@/plugins/i18n";
import { sessionKey, type DataInfo } from "@/utils/auth";
import { useMultiTagsStoreHook } from "@/store/modules/multiTags";
import { usePermissionStoreHook } from "@/store/modules/permission";
@ -104,9 +103,8 @@ 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 = `${item.meta.title} | ${Title}`;
else document.title = item.meta.title as string;
});
}
if (userInfo) {

View File

@ -1,4 +1,3 @@
import { $t } from "@/plugins/i18n";
import type { RouteConfigsTable } from "/#/index";
const errorRouter: RouteConfigsTable = {
@ -6,7 +5,7 @@ const errorRouter: RouteConfigsTable = {
redirect: "/error/403",
meta: {
icon: "information-line",
title: $t("menus.hsabnormal"),
title: "异常页面",
rank: 9
},
children: [
@ -15,7 +14,7 @@ const errorRouter: RouteConfigsTable = {
name: "403",
component: () => import("@/views/error/403.vue"),
meta: {
title: $t("menus.hsfourZeroOne")
title: "403"
}
},
{
@ -23,7 +22,7 @@ const errorRouter: RouteConfigsTable = {
name: "404",
component: () => import("@/views/error/404.vue"),
meta: {
title: $t("menus.hsfourZeroFour")
title: "404"
}
},
{
@ -31,7 +30,7 @@ const errorRouter: RouteConfigsTable = {
name: "500",
component: () => import("@/views/error/500.vue"),
meta: {
title: $t("menus.hsFive")
title: "500"
}
}
]

View File

@ -1,4 +1,3 @@
import { $t } from "@/plugins/i18n";
import type { RouteConfigsTable } from "/#/index";
const Layout = () => import("@/layout/index.vue");
@ -9,7 +8,7 @@ const homeRouter: RouteConfigsTable = {
redirect: "/welcome",
meta: {
icon: "home-filled",
title: $t("menus.hshome"),
title: "首页",
rank: 0
},
children: [
@ -18,7 +17,7 @@ const homeRouter: RouteConfigsTable = {
name: "Welcome",
component: () => import("@/views/welcome/index.vue"),
meta: {
title: $t("menus.hshome")
title: "首页"
}
}
]

View File

@ -1,4 +1,3 @@
import { $t } from "@/plugins/i18n";
import type { RouteConfigsTable } from "/#/index";
const Layout = () => import("@/layout/index.vue");
@ -8,7 +7,7 @@ const remainingRouter: Array<RouteConfigsTable> = [
name: "Login",
component: () => import("@/views/login/index.vue"),
meta: {
title: $t("menus.hslogin"),
title: "登录",
showLink: false,
rank: 101
}
@ -18,7 +17,7 @@ const remainingRouter: Array<RouteConfigsTable> = [
component: Layout,
meta: {
icon: "home-filled",
title: $t("menus.hshome"),
title: "首页",
showLink: false,
rank: 104
},

View File

@ -12,6 +12,7 @@ import { type DataInfo, setToken, removeToken, sessionKey } from "@/utils/auth";
export const useUserStore = defineStore({
id: "pure-user",
state: (): userType => ({
// 用户名
username:
storageSession.getItem<DataInfo<number>>(sessionKey)?.username ?? "",
// 页面级别权限

View File

@ -235,8 +235,6 @@
.dropdown-badge,
/* 全屏 */
.screen-full,
/* 国际化 */
.globalization,
/* 登录名 */
.el-dropdown-link,
/* 设置 */
@ -251,15 +249,6 @@
color: $subMenuActiveText;
}
.globalization {
width: 40px;
height: 48px;
padding: 11px;
outline: none;
cursor: pointer;
color: $subMenuActiveText;
}
.el-dropdown-link {
height: 48px;
padding: 10px;
@ -589,8 +578,6 @@ body[layout="vertical"] {
.dropdown-badge,
/* 全屏 */
.screen-full,
/* 国际化 */
.globalization,
/* 登录名 */
.el-dropdown-link,
/* 设置 */

View File

@ -1,5 +0,0 @@
### 注意
- [文档](https://pure-admin-utils-docs.vercel.app/)
- [npm](https://www.npmjs.com/package/@pureadmin/utils)
- vue-pure-admin 从 3.3.0 版本之后(不包括 3.3.0 版本),大部分工具和 hooks 都集成到了[@pureadmin/utils](https://pure-admin-utils-docs.vercel.app/)

View File

@ -1,25 +0,0 @@
## 用法
### Get 请求
```
import { http } from "@/utils/http";
// params传参
http.request('get', '/xxx', { params: param });
// url拼接传参
http.request('get', '/xxx?message=' + msg);
```
### Post 请求
```
import { http } from "@/utils/http";
// params传参
http.request('post', '/xxx', { params: param });
// data传参
http.request('post', '/xxx', { data: param });
```

View File

@ -8,10 +8,6 @@ const nameSpace = "responsive-";
export const injectResponsiveStorage = (app: App, config: ServerConfigs) => {
const configObj = Object.assign(
{
// 国际化 默认中文zh
locale: Storage.getData("locale", nameSpace) ?? {
locale: config.Locale ?? "zh"
},
// layout模式以及主题
layout: Storage.getData("layout", nameSpace) ?? {
layout: config.Layout ?? "vertical",

View File

@ -1,5 +1,4 @@
<script setup lang="ts">
import { useI18n } from "vue-i18n";
import Motion from "./utils/motion";
import { useRouter } from "vue-router";
import { loginRules } from "./utils/rule";
@ -7,18 +6,15 @@ import { initRouter } from "@/router/utils";
import { useNav } from "@/layout/hooks/useNav";
import { message } from "@pureadmin/components";
import type { FormInstance } from "element-plus";
import { $t, transformI18n } from "@/plugins/i18n";
import { useLayout } from "@/layout/hooks/useLayout";
import { useUserStoreHook } from "@/store/modules/user";
import { bg, avatar, illustration } from "./utils/static";
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
import { ref, reactive, toRaw, onMounted, onBeforeUnmount } from "vue";
import { useTranslationLang } from "@/layout/hooks/useTranslationLang";
import { useDataThemeChange } from "@/layout/hooks/useDataThemeChange";
import dayIcon from "@/assets/svg/day.svg?component";
import darkIcon from "@/assets/svg/dark.svg?component";
import globalization from "@/assets/svg/globalization.svg?component";
defineOptions({
name: "Login"
@ -30,11 +26,9 @@ const ruleFormRef = ref<FormInstance>();
const { initStorage } = useLayout();
initStorage();
const { t } = useI18n();
const { dataTheme, dataThemeChange } = useDataThemeChange();
dataThemeChange();
const { title, getDropdownItemStyle, getDropdownItemClass } = useNav();
const { locale, translationCh, translationEn } = useTranslationLang();
const { title } = useNav();
const ruleForm = reactive({
username: "admin",
@ -92,38 +86,6 @@ onBeforeUnmount(() => {
:inactive-icon="darkIcon"
@change="dataThemeChange"
/>
<!-- 国际化 -->
<el-dropdown trigger="click">
<globalization
class="hover:text-primary hover:!bg-[transparent] w-[20px] h-[20px] ml-1.5 cursor-pointer outline-none duration-300"
/>
<template #dropdown>
<el-dropdown-menu class="translation">
<el-dropdown-item
:style="getDropdownItemStyle(locale, 'zh')"
:class="['dark:!text-white', getDropdownItemClass(locale, 'zh')]"
@click="translationCh"
>
<IconifyIconOffline
class="check-zh"
v-show="locale === 'zh'"
icon="check"
/>
简体中文
</el-dropdown-item>
<el-dropdown-item
:style="getDropdownItemStyle(locale, 'en')"
:class="['dark:!text-white', getDropdownItemClass(locale, 'en')]"
@click="translationEn"
>
<span class="check-en" v-show="locale === 'en'">
<IconifyIconOffline icon="check" />
</span>
English
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
<div class="login-container">
<div class="img">
@ -147,7 +109,7 @@ onBeforeUnmount(() => {
:rules="[
{
required: true,
message: transformI18n($t('login.usernameReg')),
message: '请输入账号',
trigger: 'blur'
}
]"
@ -156,7 +118,7 @@ onBeforeUnmount(() => {
<el-input
clearable
v-model="ruleForm.username"
:placeholder="t('login.username')"
placeholder="账号"
:prefix-icon="useRenderIcon('user')"
/>
</el-form-item>
@ -168,7 +130,7 @@ onBeforeUnmount(() => {
clearable
show-password
v-model="ruleForm.password"
:placeholder="t('login.password')"
placeholder="密码"
:prefix-icon="useRenderIcon('lock')"
/>
</el-form-item>
@ -182,7 +144,7 @@ onBeforeUnmount(() => {
:loading="loading"
@click="onLogin(ruleFormRef)"
>
{{ t("login.login") }}
登录
</el-button>
</Motion>
</el-form>
@ -200,20 +162,4 @@ onBeforeUnmount(() => {
:deep(.el-input-group__append, .el-input-group__prepend) {
padding: 0;
}
.translation {
::v-deep(.el-dropdown-menu__item) {
padding: 5px 40px;
}
.check-zh {
position: absolute;
left: 20px;
}
.check-en {
position: absolute;
left: 20px;
}
}
</style>

View File

@ -1,6 +1,5 @@
import { reactive } from "vue";
import type { FormRules } from "element-plus";
import { $t, transformI18n } from "@/plugins/i18n";
/** 密码正则密码格式应为8-18位数字、字母、符号的任意两种组合 */
export const REGEXP_PWD =
@ -12,9 +11,11 @@ const loginRules = reactive(<FormRules>{
{
validator: (rule, value, callback) => {
if (value === "") {
callback(new Error(transformI18n($t("login.passwordReg"))));
callback(new Error("请输入密码"));
} else if (!REGEXP_PWD.test(value)) {
callback(new Error(transformI18n($t("login.passwordRuleReg"))));
callback(
new Error("密码格式应为8-18位数字、字母、符号的任意两种组合")
);
} else {
callback();
}

View File

@ -5,5 +5,5 @@ defineOptions({
</script>
<template>
<h1>Pure-Admin-Thin</h1>
<h1>Pure-Admin-Thin非国际化版本</h1>
</template>

1
types/global.d.ts vendored
View File

@ -101,7 +101,6 @@ declare global {
HiddenSideBar?: boolean;
MultiTagsCache?: boolean;
KeepAlive?: boolean;
Locale?: string;
Layout?: string;
Theme?: string;
DarkMode?: boolean;

View File

@ -7,7 +7,6 @@ export interface StorageConfigs {
hiddenSideBar?: boolean;
multiTagsCache?: boolean;
keepAlive?: boolean;
locale?: string;
layout?: string;
theme?: string;
darkMode?: boolean;
@ -30,9 +29,6 @@ export interface StorageConfigs {
}
export interface ResponsiveStorage {
locale: {
locale?: string;
};
layout: {
layout?: string;
theme?: string;

View File

@ -63,7 +63,7 @@ export default ({ command, mode }: ConfigEnv): UserConfigExport => {
},
plugins: getPluginsList(command, VITE_LEGACY, VITE_CDN, VITE_COMPRESSION),
optimizeDeps: {
include: ["pinia", "vue-i18n", "lodash-es", "@vueuse/core", "dayjs"],
include: ["pinia", "lodash-es", "@vueuse/core", "dayjs"],
exclude: ["@pureadmin/theme/dist/browser-utils"]
},
build: {