Compare commits

...

8 Commits

Author SHA1 Message Date
xiaoxian521
1bafbeaab7 release: update 3.6.4 2022-11-10 12:28:10 +08:00
xiaoxian521
9a802296c7 perf: 优化路由守卫 2022-11-08 18:17:33 +08:00
xiaoxian521
e183ea75a0 feat: 菜单图标 icon 支持使用在线图标 2022-11-08 12:10:54 +08:00
xiaoxian521
969775c7cf perf: 优化代码 2022-11-08 01:25:44 +08:00
xiaoxian521
841c5bd53a release: update 3.6.3 2022-11-01 16:29:32 +08:00
xiaoxian521
761b0e5ec2 feat: 提交非国际化版本代码 2022-10-28 15:32:31 +08:00
xiaoxian521
b811256830 feat: 静态资源分类打包 2022-10-27 15:51:06 +08:00
xiaoxian521
6019739c16 chore: 同步完整版代码 2022-10-27 14:51:32 +08:00
67 changed files with 254 additions and 1028 deletions

View File

@@ -4,11 +4,5 @@ VITE_PORT = 8848
# 开发环境读取配置文件路径
VITE_PUBLIC_PATH = /
# 开发环境代理
VITE_PROXY_DOMAIN = /api
# 开发环境路由历史模式
VITE_ROUTER_HISTORY = "hash"
# 开发环境后端地址
VITE_PROXY_DOMAIN_REAL = "http://127.0.0.1:3000"

View File

@@ -4,9 +4,6 @@ VITE_PUBLIC_PATH = /
# 线上环境路由历史模式
VITE_ROUTER_HISTORY = "hash"
# 线上环境后端地址
VITE_PROXY_DOMAIN_REAL = ""
# 是否为打包后的文件提供传统浏览器兼容性支持 支持 true 不支持 false
VITE_LEGACY = false

View File

@@ -7,16 +7,13 @@ VITE_PUBLIC_PATH = /
# 线上环境路由历史模式
VITE_ROUTER_HISTORY = "hash"
# 线上环境后端地址
VITE_PROXY_DOMAIN_REAL = ""
# 是否为打包后的文件提供传统浏览器兼容性支持 支持 true 不支持 false
VITE_LEGACY = false
# 是否在打包时使用cdn替换本地库 替换 true 不替换 false
VITE_CDN = false
VITE_CDN = true
# 是否启用gzip压缩或brotli压缩分两种情况删除原始文件和不删除原始文件
# 压缩时不删除原始文件的配置gzip、brotli、both同时开启 gzip 与 brotli 压缩、none不开启压缩默认
# 压缩时删除原始文件的配置gzip-clear、brotli-clear、both-clear同时开启 gzip 与 brotli 压缩、none不开启压缩默认
VITE_COMPRESSION = "none"
VITE_COMPRESSION = "both-clear"

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
@@ -15,9 +15,8 @@ The lite version is based on the shelf extracted from [vue-pure-admin](https://g
## Docs
- [Click me to view the domestic documentation site](http://yiming_chang.gitee.io/pure-admin-doc)
- [Click me to view foreign document site 1](https://xiaoxian521.github.io/pure-admin-doc)
- [Click me to view foreign document site 2](https://pure-admin-doc.vercel.app)
- [Click me to view the domestic documentation site](https://yiming_chang.gitee.io/pure-admin-doc)
- [Click me to view foreign document site](https://xiaoxian521.github.io/pure-admin-doc)
## Usage
@@ -42,7 +41,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`
## 配套视频
@@ -15,9 +15,8 @@
## 配套文档
- [点我查看国内文档站](http://yiming_chang.gitee.io/pure-admin-doc)
- [点我查看国外文档站 1](https://xiaoxian521.github.io/pure-admin-doc)
- [点我查看国外文档站 2](https://pure-admin-doc.vercel.app)
- [点我查看国内文档站](https://yiming_chang.gitee.io/pure-admin-doc)
- [点我查看国外文档站](https://xiaoxian521.github.io/pure-admin-doc)
## 维护者
@@ -54,7 +53,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

@@ -4,8 +4,6 @@ const warpperEnv = (envConf: Recordable): ViteEnv => {
const ret: ViteEnv = {
VITE_PORT: 8848,
VITE_PUBLIC_PATH: "",
VITE_PROXY_DOMAIN: "",
VITE_PROXY_DOMAIN_REAL: "",
VITE_ROUTER_HISTORY: "",
VITE_LEGACY: false,
VITE_CDN: false,
@@ -30,14 +28,9 @@ const warpperEnv = (envConf: Recordable): ViteEnv => {
return ret;
};
/** 跨域代理重写 */
const regExps = (value: string, reg: string): string => {
return value.replace(new RegExp(`^${reg}`, "g"), "");
};
/** 环境变量 */
const loadEnv = (): ViteEnv => {
return import.meta.env;
};
export { warpperEnv, regExps, loadEnv };
export { warpperEnv, loadEnv };

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

@@ -10,8 +10,8 @@ export default [
return {
success: true,
data: {
accessToken: "eyJhbGciOiJIUzUxMiJ9.admin",
refreshToken: "eyJhbGciOiJIUzUxMiJ9.adminRefresh",
accessToken: "eyJhbGciOiJIUzUxMiJ9.newAdmin",
refreshToken: "eyJhbGciOiJIUzUxMiJ9.newAdminRefresh",
// `expires`选择这种日期格式是为了方便调试,后端直接设置时间戳或许更方便(每次都应该递增)。如果后端返回的是时间戳格式,前端开发请来到这个目录`src/utils/auth.ts`,把第`38`行的代码换成expires = data.expires即可。
expires: "2023/10/30 23:59:59"
}

View File

@@ -1,6 +1,6 @@
{
"name": "pure-admin-thin",
"version": "3.6.2",
"version": "3.6.3",
"private": true,
"scripts": {
"dev": "NODE_OPTIONS=--max-old-space-size=4096 vite",
@@ -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",
@@ -85,9 +83,9 @@
"@vue/eslint-config-prettier": "^7.0.0",
"@vue/eslint-config-typescript": "^10.0.0",
"@vue/runtime-core": "^3.2.40",
"autoprefixer": "^10.4.12",
"autoprefixer": "^10.4.13",
"cloc": "^2.10.0",
"cssnano": "^5.1.13",
"cssnano": "^5.1.14",
"eslint": "^8.8.0",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-vue": "^8.4.1",
@@ -95,14 +93,14 @@
"husky": "^7.0.4",
"lint-staged": "11.1.2",
"picocolors": "^1.0.0",
"postcss": "^8.4.17",
"postcss": "^8.4.18",
"postcss-html": "^1.5.0",
"postcss-import": "^15.0.0",
"postcss-scss": "^4.0.5",
"prettier": "^2.5.1",
"pretty-quick": "3.1.1",
"rimraf": "3.0.2",
"rollup-plugin-visualizer": "^5.8.2",
"rollup-plugin-visualizer": "^5.8.3",
"sass": "^1.53.0",
"sass-loader": "^13.0.2",
"stylelint": "^14.3.0",
@@ -111,15 +109,15 @@
"stylelint-config-recommended": "^6.0.0",
"stylelint-config-standard": "^24.0.0",
"stylelint-order": "^5.0.0",
"tailwindcss": "^3.2.1",
"terser": "^5.15.0",
"tailwindcss": "^3.2.3",
"terser": "^5.15.1",
"typescript": "^4.7.4",
"unplugin-vue-define-options": "0.7.3",
"vite": "^3.1.8",
"vite-plugin-cdn-import": "^0.3.5",
"vite-plugin-compression": "^0.5.1",
"vite-plugin-mock": "^2.9.6",
"vite-plugin-remove-console": "^1.1.0",
"vite-plugin-remove-console": "^1.2.0",
"vite-svg-loader": "^3.6.0",
"vue-eslint-parser": "^8.2.0",
"vue-tsc": "^0.40.13"

309
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
@@ -33,10 +32,10 @@ specifiers:
"@vueuse/motion": ^2.0.0-beta.12
"@vueuse/shared": ^9.4.0
animate.css: ^4.1.1
autoprefixer: ^10.4.12
autoprefixer: ^10.4.13
axios: ^1.1.3
cloc: ^2.10.0
cssnano: ^5.1.13
cssnano: ^5.1.14
dayjs: ^1.11.4
echarts: ^5.3.3
element-plus: ^2.2.16
@@ -57,7 +56,7 @@ specifiers:
path: ^0.12.7
picocolors: ^1.0.0
pinia: ^2.0.21
postcss: ^8.4.17
postcss: ^8.4.18
postcss-html: ^1.5.0
postcss-import: ^15.0.0
postcss-scss: ^4.0.5
@@ -67,7 +66,7 @@ specifiers:
resize-observer-polyfill: ^1.5.1
responsive-storage: ^2.1.0
rimraf: 3.0.2
rollup-plugin-visualizer: ^5.8.2
rollup-plugin-visualizer: ^5.8.3
sass: ^1.53.0
sass-loader: ^13.0.2
stylelint: ^14.3.0
@@ -76,19 +75,18 @@ specifiers:
stylelint-config-recommended: ^6.0.0
stylelint-config-standard: ^24.0.0
stylelint-order: ^5.0.0
tailwindcss: ^3.2.1
terser: ^5.15.0
tailwindcss: ^3.2.3
terser: ^5.15.1
typescript: ^4.7.4
unplugin-vue-define-options: 0.7.3
vite: ^3.1.8
vite-plugin-cdn-import: ^0.3.5
vite-plugin-compression: ^0.5.1
vite-plugin-mock: ^2.9.6
vite-plugin-remove-console: ^1.1.0
vite-plugin-remove-console: ^1.2.0
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
@@ -153,9 +149,9 @@ devDependencies:
"@vue/eslint-config-prettier": 7.0.0_eslint@8.25.0+prettier@2.7.1
"@vue/eslint-config-typescript": 10.0.0_07d3deb2283d82fbf0376bf257049d49
"@vue/runtime-core": 3.2.41
autoprefixer: 10.4.12_postcss@8.4.18
autoprefixer: 10.4.13_postcss@8.4.18
cloc: 2.10.0
cssnano: 5.1.13_postcss@8.4.18
cssnano: 5.1.14_postcss@8.4.18
eslint: 8.25.0
eslint-plugin-prettier: 4.2.1_eslint@8.25.0+prettier@2.7.1
eslint-plugin-vue: 8.7.1_eslint@8.25.0
@@ -179,7 +175,7 @@ devDependencies:
stylelint-config-recommended: 6.0.0_stylelint@14.14.0
stylelint-config-standard: 24.0.0_stylelint@14.14.0
stylelint-order: 5.0.0_stylelint@14.14.0
tailwindcss: 3.2.1
tailwindcss: 3.2.3
terser: 5.15.1
typescript: 4.8.4
unplugin-vue-define-options: 0.7.3_vite@3.1.8+vue@3.2.41
@@ -187,7 +183,7 @@ devDependencies:
vite-plugin-cdn-import: 0.3.5
vite-plugin-compression: 0.5.1_vite@3.1.8
vite-plugin-mock: 2.9.6_mockjs@1.1.0+vite@3.1.8
vite-plugin-remove-console: 1.1.0
vite-plugin-remove-console: 1.2.0
vite-svg-loader: 3.6.0
vue-eslint-parser: 8.3.0_eslint@8.25.0
vue-tsc: 0.40.13_typescript@4.8.4
@@ -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:
{
@@ -2041,7 +1912,7 @@ packages:
dependencies:
cac: 6.7.14
color: 4.2.3
cssnano: 5.1.13_postcss@8.4.18
cssnano: 5.1.14_postcss@8.4.18
cssnano-preset-lite: 2.1.3_postcss@8.4.18
fs-extra: 10.1.0
postcss: 8.4.18
@@ -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:
{
@@ -2300,10 +2160,10 @@ packages:
}
dev: false
/autoprefixer/10.4.12_postcss@8.4.18:
/autoprefixer/10.4.13_postcss@8.4.18:
resolution:
{
integrity: sha512-WrCGV9/b97Pa+jtwf5UGaRjgQIg7OK3D06GnoYoZNcG1Xb8Gt3EfuKjlhh9i/VtT16g6PYjZ69jdJ2g8FxSC4Q==
integrity: sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg==
}
engines: { node: ^10 || ^12 || >=14 }
hasBin: true
@@ -2311,7 +2171,7 @@ packages:
postcss: ^8.1.0
dependencies:
browserslist: 4.21.4
caniuse-lite: 1.0.30001422
caniuse-lite: 1.0.30001431
fraction.js: 4.2.0
normalize-range: 0.1.2
picocolors: 1.0.0
@@ -2393,7 +2253,7 @@ packages:
engines: { node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7 }
hasBin: true
dependencies:
caniuse-lite: 1.0.30001422
caniuse-lite: 1.0.30001431
electron-to-chromium: 1.4.284
node-releases: 2.0.6
update-browserslist-db: 1.0.10_browserslist@4.21.4
@@ -2483,15 +2343,15 @@ packages:
}
dependencies:
browserslist: 4.21.4
caniuse-lite: 1.0.30001422
caniuse-lite: 1.0.30001431
lodash.memoize: 4.1.2
lodash.uniq: 4.5.0
dev: true
/caniuse-lite/1.0.30001422:
/caniuse-lite/1.0.30001431:
resolution:
{
integrity: sha512-hSesn02u1QacQHhaxl/kNMZwqVG35Sz/8DgvmgedxSH8z9UUpcDYSPYgsj3x5dQNRcNp6BwpSfQfVzYUTm+fog==
integrity: sha512-zBUoFU0ZcxpvSt9IU66dXVT/3ctO1cy4y9cscs1szkPlcWb6pasYM144GqrUygUbT+k7cmUCW61cvskjcv0enQ==
}
dev: true
@@ -2874,10 +2734,10 @@ packages:
hasBin: true
dev: true
/cssnano-preset-default/5.2.12_postcss@8.4.18:
/cssnano-preset-default/5.2.13_postcss@8.4.18:
resolution:
{
integrity: sha512-OyCBTZi+PXgylz9HAA5kHyoYhfGcYdwFmyaJzWnzxuGRtnMw/kR6ilW9XzlzlRAtB6PLT/r+prYgkef7hngFew==
integrity: sha512-PX7sQ4Pb+UtOWuz8A1d+Rbi+WimBIxJTRyBdgGp1J75VU0r/HFQeLnMYgHiCAp6AR4rqrc7Y4R+1Rjk3KJz6DQ==
}
engines: { node: ^10 || ^12 || >=14.0 }
peerDependencies:
@@ -2888,16 +2748,16 @@ packages:
postcss: 8.4.18
postcss-calc: 8.2.4_postcss@8.4.18
postcss-colormin: 5.3.0_postcss@8.4.18
postcss-convert-values: 5.1.2_postcss@8.4.18
postcss-convert-values: 5.1.3_postcss@8.4.18
postcss-discard-comments: 5.1.2_postcss@8.4.18
postcss-discard-duplicates: 5.1.0_postcss@8.4.18
postcss-discard-empty: 5.1.1_postcss@8.4.18
postcss-discard-overridden: 5.1.0_postcss@8.4.18
postcss-merge-longhand: 5.1.6_postcss@8.4.18
postcss-merge-rules: 5.1.2_postcss@8.4.18
postcss-merge-longhand: 5.1.7_postcss@8.4.18
postcss-merge-rules: 5.1.3_postcss@8.4.18
postcss-minify-font-values: 5.1.0_postcss@8.4.18
postcss-minify-gradients: 5.1.1_postcss@8.4.18
postcss-minify-params: 5.1.3_postcss@8.4.18
postcss-minify-params: 5.1.4_postcss@8.4.18
postcss-minify-selectors: 5.2.1_postcss@8.4.18
postcss-normalize-charset: 5.1.0_postcss@8.4.18
postcss-normalize-display-values: 5.1.0_postcss@8.4.18
@@ -2905,11 +2765,11 @@ packages:
postcss-normalize-repeat-style: 5.1.1_postcss@8.4.18
postcss-normalize-string: 5.1.0_postcss@8.4.18
postcss-normalize-timing-functions: 5.1.0_postcss@8.4.18
postcss-normalize-unicode: 5.1.0_postcss@8.4.18
postcss-normalize-unicode: 5.1.1_postcss@8.4.18
postcss-normalize-url: 5.1.0_postcss@8.4.18
postcss-normalize-whitespace: 5.1.1_postcss@8.4.18
postcss-ordered-values: 5.1.3_postcss@8.4.18
postcss-reduce-initial: 5.1.0_postcss@8.4.18
postcss-reduce-initial: 5.1.1_postcss@8.4.18
postcss-reduce-transforms: 5.1.0_postcss@8.4.18
postcss-svgo: 5.1.0_postcss@8.4.18
postcss-unique-selectors: 5.1.1_postcss@8.4.18
@@ -2943,16 +2803,16 @@ packages:
postcss: 8.4.18
dev: true
/cssnano/5.1.13_postcss@8.4.18:
/cssnano/5.1.14_postcss@8.4.18:
resolution:
{
integrity: sha512-S2SL2ekdEz6w6a2epXn4CmMKU4K3KpcyXLKfAYc9UQQqJRkD/2eLUG0vJ3Db/9OvO5GuAdgXw3pFbR6abqghDQ==
integrity: sha512-Oou7ihiTocbKqi0J1bB+TRJIQX5RMR3JghA8hcWSw9mjBLQ5Y3RWqEDoYG3sRNlAbCIXpqMoZGbq5KDR3vdzgw==
}
engines: { node: ^10 || ^12 || >=14.0 }
peerDependencies:
postcss: ^8.2.15
dependencies:
cssnano-preset-default: 5.2.12_postcss@8.4.18
cssnano-preset-default: 5.2.13_postcss@8.4.18
lilconfig: 2.0.6
postcss: 8.4.18
yaml: 1.10.2
@@ -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:
{
@@ -5730,10 +5546,10 @@ packages:
postcss-value-parser: 4.2.0
dev: true
/postcss-convert-values/5.1.2_postcss@8.4.18:
/postcss-convert-values/5.1.3_postcss@8.4.18:
resolution:
{
integrity: sha512-c6Hzc4GAv95B7suy4udszX9Zy4ETyMCgFPUDtWjdFTKH1SE9eFY/jEpHSwTH1QPuwxHpWslhckUQWbNRM4ho5g==
integrity: sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==
}
engines: { node: ^10 || ^12 || >=14.0 }
peerDependencies:
@@ -5875,10 +5691,10 @@ packages:
}
dev: true
/postcss-merge-longhand/5.1.6_postcss@8.4.18:
/postcss-merge-longhand/5.1.7_postcss@8.4.18:
resolution:
{
integrity: sha512-6C/UGF/3T5OE2CEbOuX7iNO63dnvqhGZeUnKkDeifebY0XqkkvrctYSZurpNE902LDf2yKwwPFgotnfSoPhQiw==
integrity: sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==
}
engines: { node: ^10 || ^12 || >=14.0 }
peerDependencies:
@@ -5886,13 +5702,13 @@ packages:
dependencies:
postcss: 8.4.18
postcss-value-parser: 4.2.0
stylehacks: 5.1.0_postcss@8.4.18
stylehacks: 5.1.1_postcss@8.4.18
dev: true
/postcss-merge-rules/5.1.2_postcss@8.4.18:
/postcss-merge-rules/5.1.3_postcss@8.4.18:
resolution:
{
integrity: sha512-zKMUlnw+zYCWoPN6yhPjtcEdlJaMUZ0WyVcxTAmw3lkkN/NDMRkOkiuctQEoWAOvH7twaxUUdvBWl0d4+hifRQ==
integrity: sha512-LbLd7uFC00vpOuMvyZop8+vvhnfRGpp2S+IMQKeuOZZapPRY4SMq5ErjQeHbHsjCUgJkRNrlU+LmxsKIqPKQlA==
}
engines: { node: ^10 || ^12 || >=14.0 }
peerDependencies:
@@ -5933,10 +5749,10 @@ packages:
postcss-value-parser: 4.2.0
dev: true
/postcss-minify-params/5.1.3_postcss@8.4.18:
/postcss-minify-params/5.1.4_postcss@8.4.18:
resolution:
{
integrity: sha512-bkzpWcjykkqIujNL+EVEPOlLYi/eZ050oImVtHU7b4lFS82jPnsCb44gvC6pxaNt38Els3jWYDHTjHKf0koTgg==
integrity: sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==
}
engines: { node: ^10 || ^12 || >=14.0 }
peerDependencies:
@@ -6051,10 +5867,10 @@ packages:
postcss-value-parser: 4.2.0
dev: true
/postcss-normalize-unicode/5.1.0_postcss@8.4.18:
/postcss-normalize-unicode/5.1.1_postcss@8.4.18:
resolution:
{
integrity: sha512-J6M3MizAAZ2dOdSjy2caayJLQT8E8K9XjLce8AUQMwOrCvjCHv24aLC/Lps1R1ylOfol5VIDMaM/Lo9NGlk1SQ==
integrity: sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==
}
engines: { node: ^10 || ^12 || >=14.0 }
peerDependencies:
@@ -6106,10 +5922,10 @@ packages:
postcss-value-parser: 4.2.0
dev: true
/postcss-reduce-initial/5.1.0_postcss@8.4.18:
/postcss-reduce-initial/5.1.1_postcss@8.4.18:
resolution:
{
integrity: sha512-5OgTUviz0aeH6MtBjHfbr57tml13PuedK/Ecg8szzd4XRMbYxH4572JFG067z+FqBIf6Zp/d+0581glkvvWMFw==
integrity: sha512-//jeDqWcHPuXGZLoolFrUXBDyuEGbr9S2rMo19bkTIjBQ4PqkaO+oI8wua5BOUxpfi97i3PCoInsiFIEBfkm9w==
}
engines: { node: ^10 || ^12 || >=14.0 }
peerDependencies:
@@ -6970,10 +6786,10 @@ packages:
tslib: 2.4.0
dev: false
/stylehacks/5.1.0_postcss@8.4.18:
/stylehacks/5.1.1_postcss@8.4.18:
resolution:
{
integrity: sha512-SzLmvHQTrIWfSgljkQCw2++C9+Ne91d/6Sp92I8c5uHTcy/PgeHamwITIbBW9wnFTY/3ZfSXR9HIL6Ikqmcu6Q==
integrity: sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==
}
engines: { node: ^10 || ^12 || >=14.0 }
peerDependencies:
@@ -7181,10 +6997,10 @@ packages:
strip-ansi: 6.0.1
dev: true
/tailwindcss/3.2.1:
/tailwindcss/3.2.3:
resolution:
{
integrity: sha512-Uw+GVSxp5CM48krnjHObqoOwlCt5Qo6nw1jlCRwfGy68dSYb/LwS9ZFidYGRiM+w6rMawkZiu1mEMAsHYAfoLg==
integrity: sha512-Xt9D4PK4zuuQCEB8bwK9JUCKmTgUwyac/6b0/42Vqhgl6YJkep+Wf5wq+5uXYfmrupdAD0YY2NY1hyZp1HjRrg==
}
engines: { node: ">=12.13.0" }
hasBin: true
@@ -7582,10 +7398,10 @@ packages:
- supports-color
dev: true
/vite-plugin-remove-console/1.1.0:
/vite-plugin-remove-console/1.2.0:
resolution:
{
integrity: sha512-FZ0gLEsRqgHPCl+blHpT3h004+InKrGddmBXTfs7Cj/xWY7FdHpL9Zc9kgjxh8zIzjZ/MblsPDDEqg5BVHIXDA==
integrity: sha512-1fm50pJswSeTJZZ6wBPp9Q0xUhdMqo5+drd39XRVrJ/9LmSvZ90JXf1P7P68aCTNJSf6C1KTAo7sq0PctYZURg==
}
dev: true
@@ -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

@@ -1,11 +1,10 @@
{
"Version": "3.6.2",
"Version": "3.6.3",
"Title": "PureAdmin",
"FixedHeader": true,
"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;
}
}
});

View File

@@ -1,4 +1,4 @@
import { http } from "../utils/http";
import { http } from "@/utils/http";
type Result = {
success: boolean;

View File

@@ -1,4 +1,4 @@
import { http } from "../utils/http";
import { http } from "@/utils/http";
export type UserResult = {
success: boolean;

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,7 +2,7 @@ import iconifyIconOffline from "./src/iconifyIconOffline";
import iconifyIconOnline from "./src/iconifyIconOnline";
import fontIcon from "./src/iconfont";
/** 离线图标组件 */
/** 本地图标组件 */
const IconifyIconOffline = iconifyIconOffline;
/** 在线图标组件 */
const IconifyIconOnline = iconifyIconOnline;

View File

@@ -3,7 +3,8 @@ import { h, defineComponent, Component } from "vue";
import { IconifyIconOnline, IconifyIconOffline, FontIcon } from "../index";
/**
* 支持fontawesome4、5+、iconfont、remixicon、element-plus的icons、自定义svg
* 支持 `iconfont`、自定义 `svg` 以及 `iconify` 中所有的图标
* @see 点击查看文档图标篇 {@link https://yiming_chang.gitee.io/pure-admin-doc/pages/icon/}
* @param icon 必传 图标
* @param attrs 可选 iconType 属性
* @returns Component
@@ -34,11 +35,12 @@ export function useRenderIcon(icon: any, attrs?: iconType): Component {
// svg
return icon;
} else {
// 通过是否存在 : 符号来判断是在线还是本地图标,存在即是在线图标,反之
return defineComponent({
name: "Icon",
render() {
const IconifyIcon =
attrs && attrs["online"] ? IconifyIconOnline : IconifyIconOffline;
icon && icon.includes(":") ? IconifyIconOnline : IconifyIconOffline;
return h(IconifyIcon, {
icon: icon,
...attrs

View File

@@ -59,7 +59,7 @@ addIcon("close-all-tags", CloseAllTags);
addIcon("fullscreen", Fullscreen);
addIcon("exit-fullscreen", ExitFullscreen);
// Iconify Icon在Vue里离线使用用于内网环境https://docs.iconify.design/icon-components/vue/offline.html
// Iconify Icon在Vue里本地使用用于内网环境https://docs.iconify.design/icon-components/vue/offline.html
export default defineComponent({
name: "IconifyIconOffline",
components: { IconifyIcon },

View File

@@ -11,7 +11,6 @@ export interface iconType {
horizontalAlign?: boolean;
verticalAlign?: boolean;
align?: string;
online?: boolean;
onLoad?: Function;
includes?: Function;

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">
<img v-if="avatars" :src="avatars" :style="avatarsStyle" />
<span class="el-dropdown-link navbar-bg-hover select-none">
<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

@@ -9,7 +9,7 @@ const { title } = useNav();
</script>
<template>
<div class="sidebar-logo-container" :class="{ collapse: props.collapse }">
<div class="sidebar-logo-container" :class="{ collapses: props.collapse }">
<transition name="sidebarLogoFade">
<router-link
v-if="props.collapse"
@@ -65,7 +65,7 @@ const { title } = useNav();
}
}
.collapse {
.collapses {
.sidebar-logo {
margin-right: 0;
}

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">
<img v-if="avatars" :src="avatars" :style="avatarsStyle" />
<span class="el-dropdown-link navbar-bg-hover select-none">
<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;
@@ -499,7 +497,7 @@ onMounted(() => {
<IconifyIconOffline icon="arrow-left-s-line" @click="handleScroll(200)" />
</span>
<div ref="scrollbarDom" class="scroll-container">
<div class="tab" ref="tabDom" :style="getTabStyle">
<div class="tab select-none" ref="tabDom" :style="getTabStyle">
<div
:ref="'dynamic' + index"
v-for="(item, index) in multiTags"
@@ -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

@@ -69,7 +69,7 @@ export function useDataThemeChange() {
return new TinyColor(color).shade(10).toString();
};
/** 设置ep主题色 */
/** 设置 `element-plus` 主题色 */
const setEpThemeColor = (color: string) => {
useEpThemeStoreHook().setEpThemeColor(color);
body.style.setProperty("--el-color-primary-active", shadeBgColor(color));

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

@@ -20,7 +20,6 @@ const themeColors = {
menuHover: "#4091f7",
subMenuBg: "#0f0303",
subMenuActiveBg: "#4091f7",
navTextColor: "#fff",
menuText: "rgb(254 254 254 / 65%)",
sidebarLogo: "#002140",
menuTitleHover: "#fff",
@@ -33,7 +32,6 @@ const themeColors = {
menuHover: "#e0ebf6",
subMenuBg: "#fff",
subMenuActiveBg: "#e0ebf6",
navTextColor: "#7a80b4",
menuText: "#7a80b4",
sidebarLogo: "#fff",
menuTitleHover: "#000",
@@ -46,7 +44,6 @@ const themeColors = {
menuHover: "#e13c39",
subMenuBg: "#000",
subMenuActiveBg: "#e13c39",
navTextColor: "#red",
menuText: "rgb(254 254 254 / 65.1%)",
sidebarLogo: "#42090c",
menuTitleHover: "#fff",
@@ -59,7 +56,6 @@ const themeColors = {
menuHover: "#e85f33",
subMenuBg: "#0f0603",
subMenuActiveBg: "#e85f33",
navTextColor: "#fff",
menuText: "rgb(254 254 254 / 65%)",
sidebarLogo: "#441708",
menuTitleHover: "#fff",
@@ -72,7 +68,6 @@ const themeColors = {
menuHover: "#f6da4d",
subMenuBg: "#0f0603",
subMenuActiveBg: "#f6da4d",
navTextColor: "#fff",
menuText: "rgb(254 254 254 / 65%)",
sidebarLogo: "#443b05",
menuTitleHover: "#fff",
@@ -85,7 +80,6 @@ const themeColors = {
menuHover: "#59bfc1",
subMenuBg: "#000",
subMenuActiveBg: "#59bfc1",
navTextColor: "#7a80b4",
menuText: "#7a80b4",
sidebarLogo: "#053434",
menuTitleHover: "#fff",
@@ -98,7 +92,6 @@ const themeColors = {
menuHover: "#60ac80",
subMenuBg: "#000",
subMenuActiveBg: "#60ac80",
navTextColor: "#7a80b4",
menuText: "#7a80b4",
sidebarLogo: "#112f21",
menuTitleHover: "#fff",
@@ -111,7 +104,6 @@ const themeColors = {
menuHover: "#d84493",
subMenuBg: "#000",
subMenuActiveBg: "#d84493",
navTextColor: "#7a80b4",
menuText: "#7a80b4",
sidebarLogo: "#3f0d29",
menuTitleHover: "#fff",
@@ -124,7 +116,6 @@ const themeColors = {
menuHover: "#693ac9",
subMenuBg: "#000",
subMenuActiveBg: "#693ac9",
navTextColor: "#7a80b4",
menuText: "#7a80b4",
sidebarLogo: "#1f0c38",
menuTitleHover: "#fff",
@@ -147,7 +138,6 @@ export const genScssMultipleScopeVars = (): MultipleScopeVarsItem[] => {
$menuHover: ${themeColors[key].menuHover} !default;
$subMenuBg: ${themeColors[key].subMenuBg} !default;
$subMenuActiveBg: ${themeColors[key].subMenuActiveBg} !default;
$navTextColor: ${themeColors[key].navTextColor} !default;
$menuText: ${themeColors[key].menuText} !default;
$sidebarLogo: ${themeColors[key].sidebarLogo} !default;
$menuTitleHover: ${themeColors[key].menuTitleHover} !default;

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,11 +103,14 @@ 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;
});
}
/** 如果已经登录并存在登录信息后不能跳转到路由白名单,而是继续保持在当前页面 */
function toCorrectRoute() {
whiteList.includes(to.fullPath) ? next(_from.fullPath) : next();
}
if (userInfo) {
// 无权限跳转403页面
if (to.meta?.roles && !isOneOfArray(to.meta?.roles, userInfo?.roles)) {
@@ -120,7 +122,7 @@ router.beforeEach((to: toRouteType, _from, next) => {
openLink(to?.name as string);
NProgress.done();
} else {
next();
toCorrectRoute();
}
} else {
// 刷新
@@ -150,7 +152,7 @@ router.beforeEach((to: toRouteType, _from, next) => {
}
router.push(to.fullPath);
});
next();
toCorrectRoute();
}
} else {
if (to.path !== "/login") {

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

@@ -68,10 +68,6 @@
}
}
.el-popper.is-light {
border: none !important;
}
.sidebar-container {
/* 展开动画 */
transition: width var(--pure-transition-duration);
@@ -233,11 +229,7 @@
.search-container,
/* 告警 */
.dropdown-badge,
/* 全屏 */
.screen-full,
/* 国际化 */
.globalization,
/* 登录名 */
/* 用户名 */
.el-dropdown-link,
/* 设置 */
.set-icon {
@@ -251,15 +243,6 @@
color: $subMenuActiveText;
}
.globalization {
width: 40px;
height: 48px;
padding: 11px;
outline: none;
cursor: pointer;
color: $subMenuActiveText;
}
.el-dropdown-link {
height: 48px;
padding: 10px;
@@ -587,11 +570,7 @@ body[layout="vertical"] {
.search-container,
/* 告警 */
.dropdown-badge,
/* 全屏 */
.screen-full,
/* 国际化 */
.globalization,
/* 登录名 */
/* 用户名 */
.el-dropdown-link,
/* 设置 */
.set-icon {

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

@@ -70,3 +70,8 @@ export function removeToken() {
Cookies.remove(TokenKey);
sessionStorage.removeItem(sessionKey);
}
/** 格式化tokenjwt格式 */
export const formatToken = (token: string): string => {
return "Bearer " + token;
};

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

@@ -11,21 +11,12 @@ import {
} from "./types.d";
import { stringify } from "qs";
import NProgress from "../progress";
// import { loadEnv } from "@build/index";
import { getToken } from "@/utils/auth";
import { getToken, formatToken } from "@/utils/auth";
import { useUserStoreHook } from "@/store/modules/user";
// 加载环境变量 VITE_PROXY_DOMAIN开发环境 VITE_PROXY_DOMAIN_REAL打包后的线上环境
// const { VITE_PROXY_DOMAIN, VITE_PROXY_DOMAIN_REAL } = loadEnv();
// 相关配置请参考www.axios-js.com/zh-cn/docs/#axios-request-config-1
const defaultConfig: AxiosRequestConfig = {
// baseURL:
// process.env.NODE_ENV === "production"
// ? VITE_PROXY_DOMAIN_REAL
// : VITE_PROXY_DOMAIN,
// 当前使用mock模拟请求将baseURL制空如果你的环境用到了http请求请删除下面的baseURL启用上面的baseURL并将第14行、19行代码注释取消
baseURL: "",
// 请求超时时间
timeout: 10000,
headers: {
Accept: "application/json, text/plain, */*",
@@ -43,27 +34,43 @@ class PureHttp {
this.httpInterceptorsRequest();
this.httpInterceptorsResponse();
}
/** token过期后暂存待执行的请求 */
private static requests = [];
/** 防止重复刷新token */
private static isRefreshing = false;
/** 初始化配置对象 */
private static initConfig: PureHttpRequestConfig = {};
/** 保存当前Axios实例对象 */
private static axiosInstance: AxiosInstance = Axios.create(defaultConfig);
/** 重连原始请求 */
private static retryOriginalRequest(config: PureHttpRequestConfig) {
return new Promise(resolve => {
PureHttp.requests.push((token: string) => {
config.headers["Authorization"] = formatToken(token);
resolve(config);
});
});
}
/** 请求拦截 */
private httpInterceptorsRequest(): void {
PureHttp.axiosInstance.interceptors.request.use(
async (config: PureHttpRequestConfig) => {
const $config = config;
// 开启进度条动画
NProgress.start();
// 优先判断post/get等方法是否传入回掉否则执行初始化设置等回掉
if (typeof config.beforeRequestCallback === "function") {
config.beforeRequestCallback($config);
return $config;
config.beforeRequestCallback(config);
return config;
}
if (PureHttp.initConfig.beforeRequestCallback) {
PureHttp.initConfig.beforeRequestCallback($config);
return $config;
PureHttp.initConfig.beforeRequestCallback(config);
return config;
}
/** 请求白名单放置一些不需要token的接口通过设置请求白名单防止token过期后再请求造成的死循环问题 */
const whiteList = ["/refreshToken", "/login"];
@@ -75,21 +82,30 @@ class PureHttp {
const now = new Date().getTime();
const expired = parseInt(data.expires) - now <= 0;
if (expired) {
// token过期刷新
useUserStoreHook()
.handRefreshToken({ refreshToken: data.refreshToken })
.then(res => {
config.headers["Authorization"] =
"Bearer " + res.data.accessToken;
resolve($config);
});
if (!PureHttp.isRefreshing) {
PureHttp.isRefreshing = true;
// token过期刷新
useUserStoreHook()
.handRefreshToken({ refreshToken: data.refreshToken })
.then(res => {
const token = res.data.accessToken;
config.headers["Authorization"] = formatToken(token);
PureHttp.requests.forEach(cb => cb(token));
PureHttp.requests = [];
})
.finally(() => {
PureHttp.isRefreshing = false;
});
}
resolve(PureHttp.retryOriginalRequest(config));
} else {
config.headers["Authorization"] =
"Bearer " + data.accessToken;
resolve($config);
config.headers["Authorization"] = formatToken(
data.accessToken
);
resolve(config);
}
} else {
resolve($config);
resolve(config);
}
});
},

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",
@@ -47,7 +41,7 @@ const onLogin = async (formEl: FormInstance | undefined) => {
await formEl.validate((valid, fields) => {
if (valid) {
useUserStoreHook()
.loginByUsername({ username: ruleForm.username })
.loginByUsername({ username: ruleForm.username, password: "admin123" })
.then(res => {
if (res.success) {
// 获取后端路由
@@ -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

@@ -30,7 +30,7 @@ const options = [
function onChange() {
useUserStoreHook()
.loginByUsername({ username: username.value })
.loginByUsername({ username: username.value, password: "admin123" })
.then(res => {
if (res.success) {
usePermissionStoreHook().clearAllCachePage();

View File

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

3
types/global.d.ts vendored
View File

@@ -86,8 +86,6 @@ declare global {
declare interface ViteEnv {
VITE_PORT: number;
VITE_PUBLIC_PATH: string;
VITE_PROXY_DOMAIN: string;
VITE_PROXY_DOMAIN_REAL: string;
VITE_ROUTER_HISTORY: string;
VITE_LEGACY: boolean;
VITE_CDN: boolean;
@@ -101,7 +99,6 @@ declare global {
HiddenSideBar?: boolean;
MultiTagsCache?: boolean;
KeepAlive?: boolean;
Locale?: string;
Layout?: string;
Theme?: string;
DarkMode?: boolean;

View File

@@ -1,3 +1,4 @@
import { type FunctionalComponent } from "vue";
import { type RouteComponent } from "vue-router";
export interface StorageConfigs {
@@ -7,7 +8,6 @@ export interface StorageConfigs {
hiddenSideBar?: boolean;
multiTagsCache?: boolean;
keepAlive?: boolean;
locale?: string;
layout?: string;
theme?: string;
darkMode?: boolean;
@@ -30,9 +30,6 @@ export interface StorageConfigs {
}
export interface ResponsiveStorage {
locale: {
locale?: string;
};
layout: {
layout?: string;
theme?: string;
@@ -64,7 +61,7 @@ export interface RouteChildrenConfigsTable {
/** 菜单名称(兼容国际化、非国际化,如何用国际化的写法就必须在根目录的`locales`文件夹下对应添加) `必填` */
title: string;
/** 菜单图标 `可选` */
icon?: string;
icon?: string | FunctionalComponent;
/** 菜单名称右侧的额外图标,支持`fontawesome`、`iconfont`、`element-plus-icon` `可选` */
extraIcon?: {
svg?: boolean;
@@ -122,7 +119,7 @@ export interface RouteConfigsTable {
/** 菜单名称(兼容国际化、非国际化,如何用国际化的写法就必须在根目录的`locales`文件夹下对应添加)`必填` */
title: string;
/** 菜单图标 `可选` */
icon?: string;
icon?: string | FunctionalComponent;
/** 是否在菜单中显示(默认`true``可选` */
showLink?: boolean;
/** 菜单升序排序,值越高排的越后(只针对顶级路由)`可选` */

View File

@@ -1,7 +1,7 @@
import dayjs from "dayjs";
import { resolve } from "path";
import pkg from "./package.json";
import { warpperEnv, regExps } from "./build";
import { warpperEnv } from "./build";
import { getPluginsList } from "./build/plugins";
import { UserConfigExport, ConfigEnv, loadEnv } from "vite";
@@ -31,9 +31,7 @@ export default ({ command, mode }: ConfigEnv): UserConfigExport => {
VITE_PORT,
VITE_LEGACY,
VITE_COMPRESSION,
VITE_PUBLIC_PATH,
VITE_PROXY_DOMAIN,
VITE_PROXY_DOMAIN_REAL
VITE_PUBLIC_PATH
} = warpperEnv(loadEnv(mode, root));
return {
base: VITE_PUBLIC_PATH,
@@ -48,28 +46,29 @@ export default ({ command, mode }: ConfigEnv): UserConfigExport => {
// 端口号
port: VITE_PORT,
host: "0.0.0.0",
// 本地跨域代理
proxy:
VITE_PROXY_DOMAIN_REAL.length > 0
? {
[VITE_PROXY_DOMAIN]: {
target: VITE_PROXY_DOMAIN_REAL,
// ws: true,
changeOrigin: true,
rewrite: (path: string) => regExps(path, VITE_PROXY_DOMAIN)
}
}
: null
// 本地跨域代理 https://cn.vitejs.dev/config/server-options.html#server-proxy
proxy: {}
},
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: {
sourcemap: false,
// 消除打包大小超过500kb警告
chunkSizeWarningLimit: 4000
chunkSizeWarningLimit: 4000,
rollupOptions: {
input: {
index: pathResolve("index.html")
},
// 静态资源分类打包
output: {
chunkFileNames: "static/js/[name]-[hash].js",
entryFileNames: "static/js/[name]-[hash].js",
assetFileNames: "static/[ext]/[name]-[hash].[ext]"
}
}
},
define: {
__INTLIFY_PROD_DEVTOOLS__: false,