Compare commits

...

137 Commits

Author SHA1 Message Date
Soybean
ead48f4502 chore(projects): release v0.10.4 2023-09-20 23:42:22 +08:00
Soybean
305d95672a chore(deps): update deps 2023-09-20 23:40:51 +08:00
Soybean
8a792c7d63 Merge pull request #278 from eltociear/patch-1
docs(projects): update README.md
2023-09-20 23:31:05 +08:00
Ikko Eltociear Ashimine
93ed5ad085 docs(projects): update README.md
github -> GitHub
2023-09-20 14:35:47 +09:00
Soybean
41f23386b2 fix(projects): fix reload button animate 2023-09-07 23:25:30 +08:00
Soybean
c91644b829 feat(projects): add plugin-web-update-notification 2023-09-06 01:27:39 +08:00
Soybean
073fd16bd7 refactor(projects): update soybean domain 2023-09-06 01:07:29 +08:00
Soybean
f92ee770e0 refactor(projects): add reCacheRoute method 2023-09-06 00:34:48 +08:00
Soybean
1e6d52357e Merge pull request #272 from linjiangl/main
chore(projects): When tab is switched, keep the page without refreshing
2023-09-06 00:18:04 +08:00
Soybean
751ded44f3 chore(deps): update deps 2023-09-06 00:14:35 +08:00
Soybean
8567f3e34e Merge pull request #271 from lapislazulisch/dynamicRoute
Dynamic route
2023-08-31 00:31:40 +08:00
linjiangl
83f2514403 chore(projects): When tab is switched, keep the page without refreshing 2023-08-24 16:26:49 +08:00
lapislazulisch
ad6ac7222c fix(components): 修复动态路由home页404 2023-08-23 16:03:19 +08:00
lapislazulisch
3ae1952624 fix(components): 修复动态路由主页404 2023-08-23 16:00:17 +08:00
lapislazulisch
3db549af40 fix:动态路由首页404 2023-08-23 15:41:40 +08:00
Soybean
94179ae552 Merge pull request #269 from snowords/main
Update Docker deployment method and git hooks init command
2023-08-11 16:49:32 +08:00
muzzyh
7f35e87ed8 docs(projects): update git hooks init command 2023-08-11 14:47:47 +08:00
muzzyh
00da0009ef docs(projects): update Docker deployment method 2023-08-11 11:08:05 +08:00
Soybean
cffc30afa3 chore(projects): correct word spell & eslint fix code 2023-08-04 01:55:00 +08:00
Soybean
24cf1d9284 style(projects): prettier format code 2023-08-04 01:39:12 +08:00
Soybean
9296e6987d chore(deps): update deps 2023-08-04 01:37:21 +08:00
Soybean
809fa85706 perf(hooks): perf useHookTable 2023-07-26 00:50:21 +08:00
Soybean
b3ae7605d3 feat(hooks): add useHookTable 2023-07-24 00:59:45 +08:00
Soybean
864ec4737d fix(projects): correct the lang file name & add recommend vscode plugin i18n-ally 2023-07-23 20:31:59 +08:00
Soybean
854d0bcf20 feat(projects): new i18n function $t & login page and setting drawer config i18n 2023-07-23 20:29:39 +08:00
Soybean
458e387b68 chore(projects): correct the word spell 2023-07-19 23:44:18 +08:00
Soybean
56c770c49d chore(projects): update VSCode setting 2023-07-19 23:28:32 +08:00
Soybean
946447394d chore(projects): update pnpm-lock.yaml 2023-07-19 23:25:29 +08:00
Soybean
44ba3273cb chore(deps): update deps 2023-07-19 23:15:27 +08:00
Soybean
0f7b9d5e2b fix(styles): 用户管理页面布局自适应屏幕高度 (fixed #253) 2023-07-19 23:14:33 +08:00
Soybean
8a3f66db7b Merge pull request #260 from eAliwei/issues/255
feat(auth): 防止多次刷新token
2023-07-15 01:06:43 +08:00
liwei
0eaa327d47 feat(auth): 防止多次刷新token 2023-07-13 21:34:34 +08:00
Soybean
08e0cf5ad5 chore(projects): update deps & fix eslint code 2023-07-09 13:40:33 +08:00
Soybean
d7aea9d11c chore(projects): update package.json 2023-07-07 01:50:05 +08:00
Soybean
135ce77288 chore(deps): update deps 2023-07-07 01:49:02 +08:00
Soybean
19141a73d2 docs(projects): update README.md logo 2023-07-07 01:33:34 +08:00
Soybean
9d1051b0bd chore(projects): update deps and fix swiper 2023-07-05 01:54:30 +08:00
Soybean
c46a5920e5 refactor(projects): 生产环境缓存主题变更为sessionStorage 2023-07-05 01:41:57 +08:00
Soybean
43ac23f113 style(projects): update default theme color 2023-07-05 01:37:29 +08:00
Soybean
13f6cd8ef4 fix(projects): fix set tab title (fixed #256) 2023-06-27 22:48:04 +08:00
Soybean
0e6d289128 chore(deps): update deps 2023-06-27 22:24:08 +08:00
Soybean
bba68bff29 chore(deps): update deps 2023-06-25 07:55:39 +08:00
Soybean
6e0cce4d49 feat(projects): add switch for customize darkmode transition 2023-06-20 22:33:22 +08:00
Soybean
d3ebe95076 perf(projects): add type declaration for document startViewTransition 2023-06-20 22:07:21 +08:00
Soybean
cbda4a38a3 style(projects): unify card border radius, 16px to 8px 2023-06-20 00:17:18 +08:00
Soybean
3318041b92 perf(hooks): perf use-table 2023-06-19 23:43:16 +08:00
Soybean
af53ec7625 feat(projects): add websocket demo 2023-06-18 22:24:21 +08:00
Soybean
de2829fde7 chore(projects): release v0.10.3 2023-06-15 19:26:12 +08:00
Soybean
c1bee4046c chore(projects): add vite-plugin-vue-devtools 2023-06-15 19:25:32 +08:00
Soybean
473095b01b fix(styles): fix toggle-lang bg 2023-06-15 01:00:14 +08:00
Soybean
e6abf93457 chore(deps): update deps 2023-06-14 23:59:43 +08:00
Soybean
882f281482 chore(deps): decrease vite-plugin-page-route 2023-06-12 13:35:05 +08:00
Soybean
0b2f68ac04 chore(projects): update deps & update package.json 2023-06-12 01:30:50 +08:00
Soybean
2ca2b766f8 fix(projects): fix userRoleOptions 2023-06-10 12:05:57 +08:00
Soybean
da611fb10b perf(projects): use transformObjectToOption to generate option of object labels 2023-06-08 23:56:27 +08:00
Soybean
eb8e49e23c perf(projects): remove useless code 2023-06-08 23:38:14 +08:00
Soybean
0907d38c06 chore(projects): update deps & update unocss deprecated api exclude 2023-06-08 23:05:08 +08:00
Soybean
2a9b725c6a docs(projects): update CHANGELOG.md by regenerate changelog 2023-06-07 22:50:59 +08:00
Soybean
8f24a94ed3 docs(projects): update README.md 2023-06-07 02:22:13 +08:00
Soybean
4eefc95baa docs(projects): update README.md picture url 2023-06-07 02:16:18 +08:00
Soybean
1681c34a52 docs(projects): update README.md 2023-06-07 02:06:40 +08:00
Soybean
47ab0184b7 chore(deps): update deps 2023-06-07 01:48:55 +08:00
Soybean
58591f660a chore(projects): update @soybeanjs/cli and generate total changelog 2023-06-07 01:46:09 +08:00
Soybean
3c7e1cf442 docs(projects): update README.md 2023-06-05 02:13:15 +08:00
Soybean
055d4cce33 docs(projects): generate full CHANGELOG.md 2023-06-05 02:00:59 +08:00
Soybean
a3dfe61a7b chore(projects): remove bumpp & add release script 2023-06-05 01:57:23 +08:00
Soybean
f9d47c081f chore(deps): update deps 2023-06-05 01:55:09 +08:00
Soybean
ff5bf62989 docs(projects): CHANGELOG.md 2023-05-31 18:25:40 +00:00
Soybean
1f6d079644 chore: release v0.10.2 2023-06-01 02:24:57 +08:00
Soybean
5c085a1986 fix(components): fix mix-menu layout when the locale is English (fixed 241) 2023-06-01 02:24:26 +08:00
Soybean
9a23817473 chore(projects): update deps and use soy lint-staged replace lint-staged 2023-06-01 02:10:07 +08:00
Soybean
56ea8937f6 docs(projects): fix README.md: example image link 2023-05-31 09:28:34 +08:00
Soybean
4f51263501 docs(projects): update README.md: update example image url [更新示例图片的链接] 2023-05-31 02:32:06 +08:00
Soybean
bb2eab60f4 docs(projects): CHANGELOG.md 2023-05-30 18:20:40 +00:00
Soybean
44e4c04811 chore: release v0.10.1 2023-05-31 02:19:56 +08:00
Soybean
b5839eab26 docs(projects): update README.md 2023-05-31 02:18:19 +08:00
Soybean
780ac75bf6 chore(projects): add switch for pageRoute plugin [添加自动生成路由的插件的开关] 2023-05-31 01:52:57 +08:00
Soybean
a252138594 docs(projects): CHANGELOG.md 2023-05-30 17:47:56 +00:00
Soybean
270a055072 chore: release v0.10.0 2023-05-31 01:47:13 +08:00
Soybean
08e194efe9 perf(projects): move changing document title by locale to global event of composables & add appLoading unmount 2023-05-31 01:44:49 +08:00
Soybean
5f6caab338 docs(projects): update CHANGELOG.md 2023-05-31 01:35:04 +08:00
Soybean
5aaa318142 chore(projects): remove useless packages, update lint-staged config, add githublogen 2023-05-31 01:33:46 +08:00
Soybean
cebbef680f chore(deps): update deps 2023-05-31 01:08:31 +08:00
Soybean
0abde46ef4 fix(projects): hide the drawer when it is initial mobile mode [初始化时为移动端布局则隐藏侧边栏] fixed #238 2023-05-26 13:08:35 +08:00
Soybean
f2b518ed26 feat(projects): support mobile layout [支持移动端布局] 2023-05-26 03:27:41 +08:00
Soybean
c6207f35e1 Merge pull request #237 from abstain23/fix-i18n
fix(projects): 修复面包屑导航下拉菜单语言显示问题
2023-05-25 21:13:45 +08:00
cc
ee8fa04814 fix(projects): 修复面包屑导航下拉菜单语言显示问题 2023-05-25 21:11:42 +08:00
Soybean
7b746fa053 perf(projects): complete dynamic route translate [补充动态路由的翻译] 2023-05-24 23:17:29 +08:00
Soybean
b7fea53107 Merge pull request #234 from chhinsras/main
Add Khmer Translation
2023-05-24 23:03:23 +08:00
Chhin Sras
f89f3e6a38 Added Khmer Translation 2023-05-24 21:07:35 +07:00
Chhin Sras
a0da2f6e16 Delete actions-template-sync.yml 2023-05-24 15:52:05 +07:00
Chhin Sras
3b5380e0d1 Update Sras.md 2023-05-24 15:38:43 +07:00
Chhin Sras
35276bfe41 Update and rename .github/workflows/actions-template-sync.yml to actions-template-sync.yml 2023-05-24 15:30:10 +07:00
Chhin Sras
215c1ecbd9 Update and rename sync-from-template.yml to actions-template-sync.yml 2023-05-24 15:24:51 +07:00
Chhin Sras
1698b21d7a Create Sras.md 2023-05-24 15:18:35 +07:00
Chhin Sras
ca1e66be47 Rename sync-from-template to sync-from-template.yml 2023-05-24 15:13:58 +07:00
Chhin Sras
22bf2823e8 Update and rename actions-template-sync to sync-from-template 2023-05-24 15:12:03 +07:00
Chhin Sras
32e98f1b3a Create actions-template-sync 2023-05-24 15:06:44 +07:00
Soybean
c1c4335ce7 build(projects): update deps and fix style [升级依赖&修复代码格式] 2023-05-24 00:17:00 +08:00
Soybean
6c50662280 Merge pull request #233 from fast-crud/优化README.md
优化readme.md
2023-05-24 00:12:44 +08:00
xiaojunnuo
f3a1707b94 docs(projects): readme.md 二次开发的项目内容换行 2023-05-23 17:52:06 +08:00
xiaojunnuo
6ea755f2a8 docs(projects): 优化README.md 2023-05-23 17:43:00 +08:00
Soybean
a989b44a15 docs(projects): update README.md [更新README.md] 2023-05-22 23:04:57 +08:00
Soybean
40f8587fd6 build(deps): update deps [升级依赖] 2023-05-21 22:35:30 +08:00
Soybean
9f5638f16d fix(projects): add prod mockjs switch [添加生产模式的mockjs的开关] 2023-05-17 07:55:12 +08:00
Soybean
9b19f96ff6 fix(projects): fix mockjs [修复mockjs] 2023-05-16 22:29:35 +08:00
Soybean
15da557892 Merge pull request #230 from kirklin/fix_tsconfig
fix(projects): tsconfig missing isolatedModules
2023-05-16 19:36:04 +08:00
Soybean
2d23c9a2e6 Merge pull request #229 from kirklin/vue3.3
refactor(projects): upgrade vue3.3, official support defineOptions
2023-05-16 19:34:16 +08:00
Kirk Lin
ab49afd3db fix(projects): tsconfig missing isolatedModules 2023-05-16 17:39:05 +08:00
Kirk Lin
86a370fd69 refactor(projects): upgrade vue3.3, official support defineOptions 2023-05-16 17:32:38 +08:00
Soybean
36fc74ce07 Merge pull request #226 from abstain23/feat/theme-transtion
feat(projects): 增加主题切换过渡效果
2023-05-14 16:49:26 +08:00
cc
8da8843fd0 feat(projects): 增加主题切换过渡效果 2023-05-14 16:35:38 +08:00
Soybean
f68285fbe5 feat(projects): add menu translate [翻译菜单] 2023-05-13 14:20:06 +08:00
Soybean
85b8ef8f88 Merge pull request #225 from abstain23/feat-i18n
feat(projects): 增加i18n支持翻译菜单,tab,title
2023-05-13 13:12:28 +08:00
cc
3d48aa8bbe feat(projects): 增加i18n支持翻译菜单,tab,title 2023-05-13 12:58:35 +08:00
Soybean
a765da6e28 docs(projects): update README.md [更新README.md] 2023-05-10 22:23:18 +08:00
Soybean
c57640acd0 fix(projects): fix better-mock usage [修复better-mock用法] 2023-05-06 19:41:55 +08:00
Soybean
c264216053 build(deps): update deps [升级依赖] 2023-05-06 19:35:54 +08:00
Soybean
9d3c732993 refactor(projects): use better-mock replace mockjs [用better-mock替换mockjs] 2023-05-06 19:34:31 +08:00
Soybean
34f023c4b1 build(projects): update deps and fix type error [升级依赖并修复类型问题] 2023-05-04 19:02:20 +08:00
Soybean
5a4f842774 docs(projects): update README.md [更新README.md] 2023-04-26 08:40:07 +08:00
Soybean
bae1767141 build(deps): update deps [升级依赖] 2023-04-26 08:32:54 +08:00
Soybean
5957833a4f fix(projects): fix router guide [修复路由跳转异常] fixed #216 2023-04-21 00:46:03 +08:00
Soybean
397092c21f docs(projects): update README.md [更新README.md] 2023-04-20 01:41:07 +08:00
Soybean
f309003e67 refactor(projects): remove page examples: tree [去除tree相关示例页面] 2023-04-20 01:37:52 +08:00
Soybean
eaf3678758 build(deps): update deps and remove vite-plugin-html [升级依赖,去除vite-plugin-html] 2023-04-20 01:32:53 +08:00
Soybean
f2e82da7c8 build(deps): update deps [升级依赖] 2023-04-19 09:10:36 +08:00
Soybean
211ae1f905 refactor(projects): update useTable 2023-04-04 19:19:13 +08:00
Soybean
db629593c6 build(deps): update deps 2023-04-02 12:57:36 +08:00
Soybean
80d58cce2b Merge pull request #210 from SonyLeo/feature/tree
Feature/tree
2023-04-02 12:56:00 +08:00
small_happy
a0f55aca69 feat(components): Add routing data related to tree components and page display optimization 2023-04-02 10:45:51 +08:00
small_happy
d203a3586c feat(components): Add tree related component instances 2023-04-02 10:07:50 +08:00
Soybean
f74a6424d0 docs(projects): add qq to README.md [文档添加QQ群] 2023-03-15 18:14:25 +08:00
Soybean
209ef3d890 style(projects): per style [完善样式] 2023-03-15 09:01:06 +08:00
Soybean
b549b32cbb Merge pull request #205 from yanbowe/main
feat(projects): fix to top [返回顶部功能适配新布局]
2023-03-14 22:31:41 +08:00
燕博文
54e2cb51cf feat(projects): 返回顶部功能适配新布局 2023-03-14 13:50:23 +08:00
Soybean
42e6de395f build(projects): remove old layout,tab package [去除旧的布局和页签依赖] 2023-03-14 00:34:47 +08:00
174 changed files with 8598 additions and 6530 deletions

8
.env
View File

@@ -13,8 +13,8 @@ VITE_AUTH_ROUTE_MODE=static
VITE_ROUTE_HOME_PATH=/dashboard/analysis VITE_ROUTE_HOME_PATH=/dashboard/analysis
# iconify图标作为组件的前缀 # iconify图标作为组件的前缀
VITE_ICON_PREFFIX=icon VITE_ICON_PREFIX=icon
# 本地SVG图标作为组件的前缀, 请注意一定要包含 VITE_ICON_PREFFIX # 本地SVG图标作为组件的前缀, 请注意一定要包含 VITE_ICON_PREFIX
# 格式 {VITE_ICON_PREFFIX}-{本地图标集合名称} # 格式 {VITE_ICON_PREFIX}-{本地图标集合名称}
VITE_ICON_LOCAL_PREFFIX=icon-local VITE_ICON_LOCAL_PREFIX=icon-local

View File

@@ -1 +1,2 @@
VITE_HTTP_PROXY=Y VITE_HTTP_PROXY=Y
VITE_SOYBEAN_ROUTE_PLUGIN=Y

View File

@@ -6,3 +6,5 @@ VITE_COMPRESS=N
VITE_COMPRESS_TYPE=gzip VITE_COMPRESS_TYPE=gzip
VITE_PWA=N VITE_PWA=N
VITE_PROD_MOCK=Y

View File

@@ -1,4 +1,3 @@
!.env-config.ts !.env-config.ts
components.d.ts
router-page.d.ts router-page.d.ts
*.svg

View File

@@ -10,7 +10,8 @@ module.exports = {
{ {
files: ['*.vue'], files: ['*.vue'],
rules: { rules: {
'no-undef': 'off' // use tsc to check the ts code of the vue 'no-undef': 'off', // use tsc to check the ts code of the vue
'vue/no-setup-props-destructure': 'off' // wait to fix this rule
} }
} }
], ],

View File

@@ -1,27 +1,25 @@
name: Release name: Release
on:
push:
tags:
- "v*.**"
permissions: permissions:
contents: write contents: write
on:
push:
tags:
- "v*"
jobs: jobs:
release: release:
name: Build
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Setup Node.js - uses: actions/setup-node@v3
uses: actions/setup-node@v3
with: with:
node-version: 16.x node-version: 16.x
- name: Create github releases - run: npx githublogen
run: npx changelogithub
env: env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}

1
.gitignore vendored
View File

@@ -34,3 +34,4 @@ stats.html
/src/typings/components.d.ts /src/typings/components.d.ts
package-lock.json package-lock.json
yarn.lock yarn.lock
pnpm-lock.yaml

2
.npmrc
View File

@@ -1,4 +1,2 @@
registry=https://registry.npmmirror.com/ registry=https://registry.npmmirror.com/
shamefully-hoist=true shamefully-hoist=true
strict-peer-dependencies=false
auto-install-peers=true

View File

@@ -1,27 +1,19 @@
{ {
"recommendations": [ "recommendations": [
"afzalsayed96.icones",
"antfu.iconify",
"antfu.unocss", "antfu.unocss",
"christian-kohler.path-intellisense",
"dbaeumer.vscode-eslint", "dbaeumer.vscode-eslint",
"eamodio.gitlens",
"editorconfig.editorconfig", "editorconfig.editorconfig",
"esbenp.prettier-vscode", "esbenp.prettier-vscode",
"formulahendry.auto-close-tag",
"formulahendry.auto-complete-tag", "formulahendry.auto-complete-tag",
"formulahendry.auto-close-tag",
"formulahendry.auto-rename-tag", "formulahendry.auto-rename-tag",
"kisstkondoros.vscode-gutter-preview", "kisstkondoros.vscode-gutter-preview",
"lokalise.i18n-ally", "lokalise.i18n-ally",
"mariusalchimavicius.json-to-ts", "mariusalchimavicius.json-to-ts",
"mhutchie.git-graph", "mhutchie.git-graph",
"mikestead.dotenv",
"naumovs.color-highlight",
"pkief.material-icon-theme",
"sdras.vue-vscode-snippets", "sdras.vue-vscode-snippets",
"streetsidesoftware.code-spell-checker",
"vue.volar", "vue.volar",
"vue.vscode-typescript-vue-plugin", "vue.vscode-typescript-vue-plugin"
"whtouche.vscode-js-console-utils",
"zhuangtongfa.material-theme"
] ]
} }

8
.vscode/launch.json vendored
View File

@@ -7,6 +7,14 @@
"name": "Vue debugger", "name": "Vue debugger",
"url": "http://localhost:3200", "url": "http://localhost:3200",
"webRoot": "${workspaceFolder}" "webRoot": "${workspaceFolder}"
},
{
"type": "node",
"request": "launch",
"name": "TS debugger",
"skipFiles": ["<node_internals>/**"],
"runtimeArgs": ["--loader", "tsx"],
"program": "${relativeFile}"
} }
] ]
} }

121
.vscode/settings.json vendored
View File

@@ -1,75 +1,76 @@
{ {
"cSpell.ignorePaths": [
"package.json",
"package-lock.json",
"yarn.lock",
"pnpm-lock.yaml",
"node_modules",
"vscode-extension",
".git/objects",
".vscode",
".vscode-insiders",
"CHANGELOG.md",
"dist",
"public",
"styles"
],
"cSpell.words": [
"AMAP",
"antdesign",
"antv",
"apacheecharts",
"areaspline",
"bmapgl",
"colord",
"echarts",
"gitee",
"gridicons",
"iconify",
"jsapi",
"naiveui",
"Popconfirm",
"Posva",
"Shenzhen",
"Sider",
"tauri",
"unocss",
"unplugin",
"vditor",
"VERCEL",
"Vite",
"vitejs",
"vuedraggable",
"vueuse",
"wangeditor",
"wechat",
"xgplayer",
"yanbowe",
"ភាសាខ្មែរ"
],
"editor.codeActionsOnSave": { "editor.codeActionsOnSave": {
"source.fixAll.eslint": true "source.fixAll.eslint": true
}, },
"editor.fontLigatures": true, "editor.fontLigatures": true,
"editor.formatOnSave": false, "editor.formatOnSave": false,
"editor.guides.bracketPairs": "active",
"editor.quickSuggestions": { "editor.quickSuggestions": {
"strings": true "strings": true
}, },
"editor.tabSize": 2, "editor.tabSize": 2,
"eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact", "vue", "json"], "eslint.validate": ["json"],
"files.associations": { "files.associations": {
"*.env.*": "dotenv" "*.env.*": "dotenv",
"*.svg": "html"
}, },
"files.eol": "\n", "files.eol": "\n",
"git.enableSmartCommit": true, "i18n-ally.displayLanguage": "zh-CN",
"gutterpreview.paths": { "i18n-ally.enabledParsers": ["ts"],
"@": "/src", "i18n-ally.enabledFrameworks": ["vue"],
"~@": "/src" "i18n-ally.editor.preferEditor": true,
}, "i18n-ally.keystyle": "nested",
"material-icon-theme.activeIconPack": "angular", "i18n-ally.localesPaths": ["src/locales/lang"],
"material-icon-theme.files.associations": {}, "material-icon-theme.activeIconPack": "vue",
"material-icon-theme.folders.associations": { "[html][css][less][scss][sass][markdown][yaml][yml][jsonc]": {
"src-tauri": "src", "editor.defaultFormatter": "esbenp.prettier-vscode",
"enum": "typescript", "editor.formatOnSave": true
"enums": "typescript",
"store": "context",
"stores": "context",
"composable": "hook",
"composables": "hook",
"directive": "tools",
"directives": "tools",
"business": "core",
"request": "api",
"adapter": "middleware"
},
"path-intellisense.mappings": {
"@": "${workspaceFolder}/src",
"~@": "${workspaceFolder}/src"
},
"terminal.integrated.cursorStyle": "line",
"terminal.integrated.fontSize": 14,
"terminal.integrated.fontWeight": 500,
"terminal.integrated.tabs.enabled": true,
"workbench.iconTheme": "material-icon-theme",
"workbench.colorTheme": "One Dark Pro",
"[html]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[jsonc]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[javascriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[markdown]": {
"editor.defaultFormatter": "yzhang.markdown-all-in-one"
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[vue]": {
"editor.defaultFormatter": "Vue.volar"
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
<div align="center"> <div align="center">
<img src="https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybean.svg" style="width: 160px;"/> <img src="./public/favicon.svg" style="width: 160px;"/>
<h1>Soybean Admin</h1> <h1>Soybean Admin</h1>
</div> </div>
@@ -19,22 +19,35 @@
- **权限路由**:提供前端静态和后端动态两种路由模式,基于 mock 的动态路由能快速实现后端动态路由 - **权限路由**:提供前端静态和后端动态两种路由模式,基于 mock 的动态路由能快速实现后端动态路由
- **请求函数**:基于 axios 的完善的请求函数封装,提供 Promise 和 hooks 两种请求函数,加入请求结果数据转换的适配器 - **请求函数**:基于 axios 的完善的请求函数封装,提供 Promise 和 hooks 两种请求函数,加入请求结果数据转换的适配器
## SoybeanJS 工具库
- [@soybeanjs/cli](https://github.com/soybeanjs/cli): SoybeanJS 命令行工具包含发布、git 和依赖等相关的实用命令
- [@soybeanjs/changelog](https://github.com/soybeanjs/changelog): 根据 git tags 和 commits 生成 changelog [示例](./CHANGELOG.md)
- [eslint-config-soybeanjs](https://github.com/soybeanjs/eslint-config): SoybeanJS 的 eslint 预设配置
- [@soybeanjs/materials](https://github.com/soybeanjs/materials): SoybeanJS 的物料仓库
- [@soybeanjs/vite-plugin-vue-page-route](https://github.com/soybeanjs/vite-plugin-vue-page-route): SoybeanAdmin 的路由插件
## 基于 SoybeanAdmin 二次开发的项目
- [electron-mock-admin](https://github.com/lixin59/electron-mock-api): 一个 Mock Api 管理系统,帮助前端开发伙伴快速实现接口的 mock。
- [T-Shell](https://github.com/TheBlindM/T-Shell): 是一个可配置命令提示的终端模拟器和 SSH 客户端。
## 在线预览 ## 在线预览
- [Soybean Admin 预览地址](https://soybean.pro/) - [Soybean Admin 预览地址](https://admin.soybeanjs.cn/)
## 文档 ## 文档
- [项目文档预览地址](https://docs.soybean.pro) - [项目文档预览地址](https://admin-docs.soybeanjs.cn/)
## 代码仓库 ## 代码仓库
- [github](https://github.com/honghuangdc/soybean-admin) | 仓库 | GitHub 地址 | gitee 镜像 | 预览 |
- [tauri 版](https://github.com/honghuangdc/soybean-admin/tree/tauri) | -------------- | ----------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | --------------------------------------------------------- |
- [精简版](https://github.com/honghuangdc/soybean-admin/tree/thin) | soybean-admin | [GitHub](https://github.com/honghuangdc/soybean-admin) | [gitee](https://gitee.com/honghuangdc/soybean-admin) | [预览](https://admin.soybeanjs.cn/) |
- [gitee](https://gitee.com/honghuangdc/soybean-admin) | tauri 版 | [tauri 版](https://github.com/honghuangdc/soybean-admin/tree/tauri) | [tauri 版](https://gitee.com/honghuangdc/soybean-admin/tree/tauri) | |
- [tauri 版](https://gitee.com/honghuangdc/soybean-admin/tree/tauri) | 精简版 | [精简版](https://github.com/honghuangdc/soybean-admin/tree/thin) | [精简版](https://gitee.com/honghuangdc/soybean-admin/tree/thin) | |
- [精简版](https://gitee.com/honghuangdc/soybean-admin/tree/thin) | 集成 fast-crud | [集成 fast-crud](https://github.com/honghuangdc/soybean-admin/tree/fast-crud) | [集成 fast-crud](https://gitee.com/honghuangdc/soybean-admin/tree/fast-crud) | [预览](http://fast-crud.docmirror.cn/soybean/#/crud/demo) |
## 更新日志 ## 更新日志
@@ -54,13 +67,15 @@
![](https://s2.loli.net/2022/05/16/rSnNHLdpuvkKxWq.png) ![](https://s2.loli.net/2022/05/16/rSnNHLdpuvkKxWq.png)
![](https://s2.loli.net/2023/06/07/O39EKNa675FZIuS.png)
![](https://s2.loli.net/2022/05/18/Mt6YZqmDxO8v4uR.png) ![](https://s2.loli.net/2022/05/18/Mt6YZqmDxO8v4uR.png)
![](https://s2.loli.net/2022/05/16/ktH5dcG3fuFOoKA.png) ![](https://s2.loli.net/2023/06/07/zhmWnFlPTfDpot8.png)
![](https://s2.loli.net/2022/05/16/VPl6Ru1iCAhLcS4.png) ![](https://s2.loli.net/2022/05/16/VPl6Ru1iCAhLcS4.png)
![](https://s2.loli.net/2022/05/16/bRlAKuHW7ZVh9DT.png) ![](https://s2.loli.net/2023/06/07/n6Dy1HXBvuPc9oT.png)
![](https://s2.loli.net/2022/06/07/rY8TyAftM5dxspv.png) ![](https://s2.loli.net/2022/06/07/rY8TyAftM5dxspv.png)
@@ -68,6 +83,12 @@
![](https://s2.loli.net/2022/06/07/rRSG6mEZpujOACT.png) ![](https://s2.loli.net/2022/06/07/rRSG6mEZpujOACT.png)
<div align="center">
<img style="width:380px;margin-right:18px;border:1px solid #dedede;" src="https://s2.loli.net/2023/06/07/A5Nonc9vI6pB1lr.png" />
&nbsp;
<img style="width:380px;border:1px solid #dedede;" src="https://s2.loli.net/2023/06/07/VwBjqEhTke3OxXF.png" />
</div>
## 安装使用 ## 安装使用
- 环境配置 - 环境配置
@@ -102,7 +123,8 @@ pnpm build
- Docker 部署 Soybean - Docker 部署 Soybean
```bash ```bash
docker run --name soybean -p 80:80 -d soybeanjs/soybean-admin:v0.9.6 docker build -t soybean-admin-image -f docker/Dockerfile .
docker run -d -p 80:80 soybean-admin-image
``` ```
- 访问 SoybeanAdmin - 访问 SoybeanAdmin
@@ -117,10 +139,7 @@ docker run --name soybean -p 80:80 -d soybeanjs/soybean-admin:v0.9.6
项目已经内置 Angular 提交规范,直接执行 commit 命令即可生成符合 Angular 提交规范的 commit。 项目已经内置 Angular 提交规范,直接执行 commit 命令即可生成符合 Angular 提交规范的 commit。
项目已用 simple-git-hooks 代替了 husky, 旧版本用了 husky执行 pnpm soy init-git-hooks 进行初始化配置 项目已用 simple-git-hooks 代替了 husky, 旧版本用了 husky执行 pnpm soy init-simple-git-hooks 进行初始化配置
## 基于 SoybeanAdmin 二次开发的项目
[electron-mock-admin](https://github.com/lixin59/electron-mock-api): 一个 Mock Api 管理系统帮助前端开发伙伴快速实现接口的mock。
## 浏览器支持 ## 浏览器支持
@@ -138,16 +157,16 @@ docker run --name soybean -p 80:80 -d soybeanjs/soybean-admin:v0.9.6
## 交流 ## 交流
`Soybean Admin` 是完全开源免费的项目,在帮助开发者更方便地进行中大型管理系统开发,同时也提供微信和 QQ 交流群(人员已满),使用问题欢迎在群内提问。 `Soybean Admin` 是完全开源免费的项目,在帮助开发者更方便地进行中大型管理系统开发,同时也提供微信和 QQ 交流群,使用问题欢迎在群内提问。
<div style="display:flex;"> <div style="display:flex;">
<div style="padding-right:24px;"> <div style="padding-right:24px;">
<p>微信交流群</p> <p>QQ交流群</p>
<img src="https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybeanjs-wechat2.jpeg" style="width:200px" /> <img src="https://i.loli.net/2021/11/24/1J6REWXiHomU2kM.jpg" style="width:200px" />
</div> </div>
<div> <div>
<p>添加本人微信,欢迎来技术交流,业务咨询</p> <p>添加本人微信,欢迎来技术交流,业务咨询</p>
<img src="https://soybeanjs-1300612522.cos.ap-guangzhou.myqcloud.com/uPic/soybeanjs.jpeg" style="width:180px" /> <img src="https://s2.loli.net/2023/06/07/sVyCUFBvzQ9f5b7.jpg" style="width:200px" />
</div> </div>
</div> </div>
@@ -159,4 +178,4 @@ docker run --name soybean -p 80:80 -d soybeanjs/soybean-admin:v0.9.6
## License ## License
[MIT © Soybean-2021](./LICENSE) 本项目基于[MIT © Soybean-2021](./LICENSE) 协议,仅供参考学习,商用时请保留作者的版权信息,作者不对软件做担保和负责。

View File

@@ -1,14 +0,0 @@
import type { PluginOption } from 'vite';
import { createHtmlPlugin } from 'vite-plugin-html';
export default (viteEnv: ImportMetaEnv): PluginOption[] => {
return createHtmlPlugin({
minify: true,
inject: {
data: {
appName: viteEnv.VITE_APP_NAME,
appTitle: viteEnv.VITE_APP_TITLE
}
}
});
};

View File

@@ -3,8 +3,9 @@ import vue from '@vitejs/plugin-vue';
import vueJsx from '@vitejs/plugin-vue-jsx'; import vueJsx from '@vitejs/plugin-vue-jsx';
import unocss from '@unocss/vite'; import unocss from '@unocss/vite';
import progress from 'vite-plugin-progress'; import progress from 'vite-plugin-progress';
import VueDevtools from 'vite-plugin-vue-devtools';
import pageRoute from '@soybeanjs/vite-plugin-vue-page-route'; import pageRoute from '@soybeanjs/vite-plugin-vue-page-route';
import html from './html'; import { webUpdateNotice } from '@plugin-web-update-notification/vite';
import unplugin from './unplugin'; import unplugin from './unplugin';
import mock from './mock'; import mock from './mock';
import visualizer from './visualizer'; import visualizer from './visualizer';
@@ -16,7 +17,27 @@ import pwa from './pwa';
* @param viteEnv - 环境变量配置 * @param viteEnv - 环境变量配置
*/ */
export function setupVitePlugins(viteEnv: ImportMetaEnv): (PluginOption | PluginOption[])[] { export function setupVitePlugins(viteEnv: ImportMetaEnv): (PluginOption | PluginOption[])[] {
const plugins = [vue(), vueJsx(), html(viteEnv), ...unplugin(viteEnv), unocss(), mock, progress(), pageRoute()]; const plugins = [
vue({
script: {
defineModel: true
}
}),
vueJsx(),
VueDevtools(),
...unplugin(viteEnv),
unocss(),
mock(viteEnv),
progress(),
webUpdateNotice({
notificationProps: {
title: '👋 有新版本了',
description: '点击刷新页面获取最新版本',
buttonText: '刷新',
dismissButtonText: '忽略'
}
})
];
if (viteEnv.VITE_VISUALIZER === 'Y') { if (viteEnv.VITE_VISUALIZER === 'Y') {
plugins.push(visualizer as PluginOption); plugins.push(visualizer as PluginOption);
@@ -27,6 +48,9 @@ export function setupVitePlugins(viteEnv: ImportMetaEnv): (PluginOption | Plugin
if (viteEnv.VITE_PWA === 'Y' || viteEnv.VITE_VERCEL === 'Y') { if (viteEnv.VITE_PWA === 'Y' || viteEnv.VITE_VERCEL === 'Y') {
plugins.push(pwa()); plugins.push(pwa());
} }
if (viteEnv.VITE_SOYBEAN_ROUTE_PLUGIN === 'Y') {
plugins.push(pageRoute());
}
return plugins; return plugins;
} }

View File

@@ -1,9 +1,14 @@
import { viteMockServe } from 'vite-plugin-mock'; import { viteMockServe } from 'vite-plugin-mock';
export default viteMockServe({ export default (viteEnv: ImportMetaEnv) => {
mockPath: 'mock', const prodMock = viteEnv.VITE_PROD_MOCK === 'Y';
injectCode: `
import { setupMockServer } from '../mock'; return viteMockServe({
setupMockServer(); mockPath: 'mock',
` prodEnabled: prodMock,
}); injectCode: `
import { setupMockServer } from '../mock';
setupMockServer();
`
});
};

View File

@@ -1,4 +1,3 @@
import VueMacros from 'unplugin-vue-macros/vite';
import Icons from 'unplugin-icons/vite'; import Icons from 'unplugin-icons/vite';
import IconsResolver from 'unplugin-icons/resolver'; import IconsResolver from 'unplugin-icons/resolver';
import Components from 'unplugin-vue-components/vite'; import Components from 'unplugin-vue-components/vite';
@@ -8,16 +7,15 @@ import { createSvgIconsPlugin } from 'vite-plugin-svg-icons';
import { getSrcPath } from '../utils'; import { getSrcPath } from '../utils';
export default function unplugin(viteEnv: ImportMetaEnv) { export default function unplugin(viteEnv: ImportMetaEnv) {
const { VITE_ICON_PREFFIX, VITE_ICON_LOCAL_PREFFIX } = viteEnv; const { VITE_ICON_PREFIX, VITE_ICON_LOCAL_PREFIX } = viteEnv;
const srcPath = getSrcPath(); const srcPath = getSrcPath();
const localIconPath = `${srcPath}/assets/svg-icon`; const localIconPath = `${srcPath}/assets/svg-icon`;
/** 本地svg图标集合名称 */ /** 本地svg图标集合名称 */
const collectionName = VITE_ICON_LOCAL_PREFFIX.replace(`${VITE_ICON_PREFFIX}-`, ''); const collectionName = VITE_ICON_LOCAL_PREFIX.replace(`${VITE_ICON_PREFIX}-`, '');
return [ return [
VueMacros({}),
Icons({ Icons({
compiler: 'vue3', compiler: 'vue3',
customCollections: { customCollections: {
@@ -33,12 +31,12 @@ export default function unplugin(viteEnv: ImportMetaEnv) {
types: [{ from: 'vue-router', names: ['RouterLink', 'RouterView'] }], types: [{ from: 'vue-router', names: ['RouterLink', 'RouterView'] }],
resolvers: [ resolvers: [
NaiveUiResolver(), NaiveUiResolver(),
IconsResolver({ customCollections: [collectionName], componentPrefix: VITE_ICON_PREFFIX }) IconsResolver({ customCollections: [collectionName], componentPrefix: VITE_ICON_PREFIX })
] ]
}), }),
createSvgIconsPlugin({ createSvgIconsPlugin({
iconDirs: [localIconPath], iconDirs: [localIconPath],
symbolId: `${VITE_ICON_LOCAL_PREFFIX}-[dir]-[name]`, symbolId: `${VITE_ICON_LOCAL_PREFIX}-[dir]-[name]`,
inject: 'body-last', inject: 'body-last',
customDomId: '__SVG_ICON_LOCAL__' customDomId: '__SVG_ICON_LOCAL__'
}) })

View File

@@ -1,21 +0,0 @@
{
"types": {
"feat": { "title": "🚀 Features" },
"perf": { "title": "🔥 Performance" },
"fix": { "title": "🩹 Fixes" },
"refactor": { "title": "💅 Refactors" },
"docs": { "title": "📖 Documentation" },
"types": { "title": "🌊 Types" },
"chore": { "title": "🏡 Chore" },
"test": { "title": "🧪 Tests" },
"style": { "title": "🎨 Styles" },
"ci": { "title": "🤖 CI" }
},
"scopeMap": {},
"titles": {
"breakingChanges": "🚨 Breaking Changes"
},
"contributors": true,
"capitalize": true,
"group": true
}

View File

@@ -1,10 +1,15 @@
<!-- prettier-ignore -->
<!DOCTYPE html> <!DOCTYPE html>
<html lang="zh-cmn-Hans"> <html lang="zh-cmn-Hans">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta http-equiv="Expires" content="0" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Cache-control" content="no-cache" />
<meta http-equiv="Cache" content="no-cache" />
<link rel="icon" href="/favicon.svg" /> <link rel="icon" href="/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title><%= appName %></title> <title>%VITE_APP_NAME%</title>
</head> </head>
<body> <body>
<div id="app"> <div id="app">

View File

@@ -12,7 +12,8 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
meta: { meta: {
title: '分析页', title: '分析页',
requiresAuth: true, requiresAuth: true,
icon: 'icon-park-outline:analysis' icon: 'icon-park-outline:analysis',
i18nTitle: 'routes.dashboard.analysis'
} }
}, },
{ {
@@ -22,14 +23,16 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
meta: { meta: {
title: '工作台', title: '工作台',
requiresAuth: true, requiresAuth: true,
icon: 'icon-park-outline:workbench' icon: 'icon-park-outline:workbench',
i18nTitle: 'routes.dashboard.workbench'
} }
} }
], ],
meta: { meta: {
title: '仪表盘', title: '仪表盘',
icon: 'mdi:monitor-dashboard', icon: 'mdi:monitor-dashboard',
order: 1 order: 1,
i18nTitle: 'routes.dashboard._value'
} }
}, },
{ {
@@ -43,6 +46,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: 'vue文档', title: 'vue文档',
i18nTitle: 'routes.document.vue',
requiresAuth: true, requiresAuth: true,
icon: 'logos:vue' icon: 'logos:vue'
} }
@@ -53,6 +57,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: 'vite文档', title: 'vite文档',
i18nTitle: 'routes.document.vite',
requiresAuth: true, requiresAuth: true,
icon: 'logos:vitejs' icon: 'logos:vitejs'
} }
@@ -63,6 +68,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: 'naive文档', title: 'naive文档',
i18nTitle: 'routes.document.naive',
requiresAuth: true, requiresAuth: true,
icon: 'logos:naiveui' icon: 'logos:naiveui'
} }
@@ -73,6 +79,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '项目文档', title: '项目文档',
i18nTitle: 'routes.document.project',
requiresAuth: true, requiresAuth: true,
localIcon: 'logo' localIcon: 'logo'
} }
@@ -82,14 +89,16 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
path: '/document/project-link', path: '/document/project-link',
meta: { meta: {
title: '项目文档(外链)', title: '项目文档(外链)',
i18nTitle: 'routes.document.project-link',
requiresAuth: true, requiresAuth: true,
localIcon: 'logo', localIcon: 'logo',
href: 'https://docs.soybean.pro/' href: 'https://admin-docs.soybeanjs.cn/'
} }
} }
], ],
meta: { meta: {
title: '文档', title: '文档',
i18nTitle: 'routes.document._value',
icon: 'mdi:file-document-multiple-outline', icon: 'mdi:file-document-multiple-outline',
order: 2 order: 2
} }
@@ -105,6 +114,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '按钮', title: '按钮',
i18nTitle: 'routes.component.button',
requiresAuth: true, requiresAuth: true,
icon: 'mdi:button-cursor' icon: 'mdi:button-cursor'
} }
@@ -115,6 +125,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '卡片', title: '卡片',
i18nTitle: 'routes.component.card',
requiresAuth: true, requiresAuth: true,
icon: 'mdi:card-outline' icon: 'mdi:card-outline'
} }
@@ -125,6 +136,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '表格', title: '表格',
i18nTitle: 'routes.component.table',
requiresAuth: true, requiresAuth: true,
icon: 'mdi:table-large' icon: 'mdi:table-large'
} }
@@ -132,6 +144,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
], ],
meta: { meta: {
title: '组件示例', title: '组件示例',
i18nTitle: 'routes.component._value',
icon: 'cib:app-store', icon: 'cib:app-store',
order: 3 order: 3
} }
@@ -152,6 +165,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: 'ECharts', title: 'ECharts',
i18nTitle: 'routes.plugin.charts.echarts',
requiresAuth: true, requiresAuth: true,
icon: 'simple-icons:apacheecharts' icon: 'simple-icons:apacheecharts'
} }
@@ -162,6 +176,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: 'AntV', title: 'AntV',
i18nTitle: 'routes.plugin.charts.antv',
requiresAuth: true, requiresAuth: true,
icon: 'simple-icons:antdesign' icon: 'simple-icons:antdesign'
} }
@@ -169,6 +184,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
], ],
meta: { meta: {
title: '图表', title: '图表',
i18nTitle: 'routes.plugin.charts._value',
icon: 'mdi:chart-areaspline' icon: 'mdi:chart-areaspline'
} }
}, },
@@ -178,6 +194,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '地图', title: '地图',
i18nTitle: 'routes.plugin.map',
requiresAuth: true, requiresAuth: true,
icon: 'mdi:map' icon: 'mdi:map'
} }
@@ -188,6 +205,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '视频', title: '视频',
i18nTitle: 'routes.plugin.video',
requiresAuth: true, requiresAuth: true,
icon: 'mdi:video' icon: 'mdi:video'
} }
@@ -203,6 +221,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '富文本编辑器', title: '富文本编辑器',
i18nTitle: 'routes.plugin.editor.quill',
requiresAuth: true, requiresAuth: true,
icon: 'mdi:file-document-edit-outline' icon: 'mdi:file-document-edit-outline'
} }
@@ -213,6 +232,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: 'markdown编辑器', title: 'markdown编辑器',
i18nTitle: 'routes.plugin.editor.markdown',
requiresAuth: true, requiresAuth: true,
icon: 'ri:markdown-line' icon: 'ri:markdown-line'
} }
@@ -220,6 +240,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
], ],
meta: { meta: {
title: '编辑器', title: '编辑器',
i18nTitle: 'routes.plugin.editor._value',
icon: 'icon-park-outline:editor' icon: 'icon-park-outline:editor'
} }
}, },
@@ -229,6 +250,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: 'Swiper插件', title: 'Swiper插件',
i18nTitle: 'routes.plugin.swiper',
requiresAuth: true, requiresAuth: true,
icon: 'simple-icons:swiper' icon: 'simple-icons:swiper'
} }
@@ -239,6 +261,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '剪贴板', title: '剪贴板',
i18nTitle: 'routes.plugin.copy',
requiresAuth: true, requiresAuth: true,
icon: 'mdi:clipboard-outline' icon: 'mdi:clipboard-outline'
} }
@@ -249,6 +272,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '图标', title: '图标',
i18nTitle: 'routes.plugin.icon',
requiresAuth: true, requiresAuth: true,
localIcon: 'custom-icon' localIcon: 'custom-icon'
} }
@@ -259,6 +283,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '打印', title: '打印',
i18nTitle: 'routes.plugin.print',
requiresAuth: true, requiresAuth: true,
icon: 'mdi:printer' icon: 'mdi:printer'
} }
@@ -266,6 +291,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
], ],
meta: { meta: {
title: '插件示例', title: '插件示例',
i18nTitle: 'routes.plugin._value',
icon: 'clarity:plugin-line', icon: 'clarity:plugin-line',
order: 4 order: 4
} }
@@ -281,6 +307,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '权限切换', title: '权限切换',
i18nTitle: 'routes.auth-demo.permission',
requiresAuth: true, requiresAuth: true,
icon: 'ic:round-construction' icon: 'ic:round-construction'
} }
@@ -291,6 +318,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '超级管理员可见', title: '超级管理员可见',
i18nTitle: 'routes.auth-demo.super',
requiresAuth: true, requiresAuth: true,
icon: 'ic:round-supervisor-account' icon: 'ic:round-supervisor-account'
} }
@@ -298,6 +326,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
], ],
meta: { meta: {
title: '权限示例', title: '权限示例',
i18nTitle: 'routes.auth-demo._value',
icon: 'ic:baseline-security', icon: 'ic:baseline-security',
order: 5 order: 5
} }
@@ -313,6 +342,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: 'Tab', title: 'Tab',
i18nTitle: 'routes.function.tab',
requiresAuth: true, requiresAuth: true,
icon: 'ic:round-tab' icon: 'ic:round-tab'
} }
@@ -345,6 +375,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
], ],
meta: { meta: {
title: '功能', title: '功能',
i18nTitle: 'routes.function._value',
icon: 'icon-park-outline:all-application', icon: 'icon-park-outline:all-application',
order: 6 order: 6
} }
@@ -360,6 +391,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '异常页403', title: '异常页403',
i18nTitle: 'routes.exception.403',
requiresAuth: true, requiresAuth: true,
icon: 'ic:baseline-block' icon: 'ic:baseline-block'
} }
@@ -370,6 +402,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '异常页404', title: '异常页404',
i18nTitle: 'routes.exception.404',
requiresAuth: true, requiresAuth: true,
icon: 'ic:baseline-web-asset-off' icon: 'ic:baseline-web-asset-off'
} }
@@ -380,12 +413,14 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '异常页500', title: '异常页500',
i18nTitle: 'routes.exception.500',
requiresAuth: true, requiresAuth: true,
icon: 'ic:baseline-wifi-off' icon: 'ic:baseline-wifi-off'
} }
} }
], ],
meta: { meta: {
i18nTitle: 'routes.exception._value',
title: '异常页', title: '异常页',
icon: 'ant-design:exception-outlined', icon: 'ant-design:exception-outlined',
order: 7 order: 7
@@ -407,6 +442,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '二级菜单', title: '二级菜单',
i18nTitle: 'routes.multi-menu.first.second',
requiresAuth: true, requiresAuth: true,
icon: 'mdi:menu' icon: 'mdi:menu'
} }
@@ -422,6 +458,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '三级菜单', title: '三级菜单',
i18nTitle: 'routes.multi-menu.first.second-new.third',
requiresAuth: true, requiresAuth: true,
icon: 'mdi:menu' icon: 'mdi:menu'
} }
@@ -429,18 +466,21 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
], ],
meta: { meta: {
title: '二级菜单(有子菜单)', title: '二级菜单(有子菜单)',
i18nTitle: 'routes.multi-menu.first.second-new._value',
icon: 'mdi:menu' icon: 'mdi:menu'
} }
} }
], ],
meta: { meta: {
title: '一级菜单', title: '一级菜单',
i18nTitle: 'routes.multi-menu.first._value',
icon: 'mdi:menu' icon: 'mdi:menu'
} }
} }
], ],
meta: { meta: {
title: '多级菜单', title: '多级菜单',
i18nTitle: 'routes.multi-menu._value',
icon: 'carbon:menu', icon: 'carbon:menu',
order: 8 order: 8
} }
@@ -456,6 +496,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '权限管理', title: '权限管理',
i18nTitle: 'routes.management.auth',
requiresAuth: true, requiresAuth: true,
icon: 'ic:baseline-security' icon: 'ic:baseline-security'
} }
@@ -466,6 +507,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '角色管理', title: '角色管理',
i18nTitle: 'routes.management.role',
requiresAuth: true, requiresAuth: true,
icon: 'carbon:user-role' icon: 'carbon:user-role'
} }
@@ -476,6 +518,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '用户管理', title: '用户管理',
i18nTitle: 'routes.management.user',
requiresAuth: true, requiresAuth: true,
icon: 'ic:round-manage-accounts' icon: 'ic:round-manage-accounts'
} }
@@ -486,6 +529,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '路由管理', title: '路由管理',
i18nTitle: 'routes.management.route',
requiresAuth: true, requiresAuth: true,
icon: 'material-symbols:route' icon: 'material-symbols:route'
} }
@@ -493,6 +537,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
], ],
meta: { meta: {
title: '系统管理', title: '系统管理',
i18nTitle: 'routes.management._value',
icon: 'carbon:cloud-service-management', icon: 'carbon:cloud-service-management',
order: 9 order: 9
} }
@@ -503,7 +548,9 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '关于', title: '关于',
i18nTitle: 'routes.about',
requiresAuth: true, requiresAuth: true,
keepAlive: true,
singleLayout: 'basic', singleLayout: 'basic',
icon: 'fluent:book-information-24-regular', icon: 'fluent:book-information-24-regular',
order: 10 order: 10
@@ -523,7 +570,8 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
meta: { meta: {
title: '分析页', title: '分析页',
requiresAuth: true, requiresAuth: true,
icon: 'icon-park-outline:analysis' icon: 'icon-park-outline:analysis',
i18nTitle: 'routes.dashboard.analysis'
} }
}, },
{ {
@@ -533,14 +581,16 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
meta: { meta: {
title: '工作台', title: '工作台',
requiresAuth: true, requiresAuth: true,
icon: 'icon-park-outline:workbench' icon: 'icon-park-outline:workbench',
i18nTitle: 'routes.dashboard.workbench'
} }
} }
], ],
meta: { meta: {
title: '仪表盘', title: '仪表盘',
icon: 'mdi:monitor-dashboard', icon: 'mdi:monitor-dashboard',
order: 1 order: 1,
i18nTitle: 'routes.dashboard._value'
} }
}, },
{ {
@@ -554,6 +604,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: 'vue文档', title: 'vue文档',
i18nTitle: 'routes.document.vue',
requiresAuth: true, requiresAuth: true,
icon: 'logos:vue' icon: 'logos:vue'
} }
@@ -564,6 +615,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: 'vite文档', title: 'vite文档',
i18nTitle: 'routes.document.vite',
requiresAuth: true, requiresAuth: true,
icon: 'logos:vitejs' icon: 'logos:vitejs'
} }
@@ -574,6 +626,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: 'naive文档', title: 'naive文档',
i18nTitle: 'routes.document.naive',
requiresAuth: true, requiresAuth: true,
icon: 'logos:naiveui' icon: 'logos:naiveui'
} }
@@ -584,6 +637,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '项目文档', title: '项目文档',
i18nTitle: 'routes.document.project',
requiresAuth: true, requiresAuth: true,
localIcon: 'logo' localIcon: 'logo'
} }
@@ -593,14 +647,16 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
path: '/document/project-link', path: '/document/project-link',
meta: { meta: {
title: '项目文档(外链)', title: '项目文档(外链)',
i18nTitle: 'routes.document.project-link',
requiresAuth: true, requiresAuth: true,
localIcon: 'logo', localIcon: 'logo',
href: 'https://docs.soybean.pro/' href: 'https://admin-docs.soybeanjs.cn/'
} }
} }
], ],
meta: { meta: {
title: '文档', title: '文档',
i18nTitle: 'routes.document._value',
icon: 'mdi:file-document-multiple-outline', icon: 'mdi:file-document-multiple-outline',
order: 2 order: 2
} }
@@ -616,6 +672,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '按钮', title: '按钮',
i18nTitle: 'routes.component.button',
requiresAuth: true, requiresAuth: true,
icon: 'mdi:button-cursor' icon: 'mdi:button-cursor'
} }
@@ -626,6 +683,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '卡片', title: '卡片',
i18nTitle: 'routes.component.card',
requiresAuth: true, requiresAuth: true,
icon: 'mdi:card-outline' icon: 'mdi:card-outline'
} }
@@ -636,6 +694,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '表格', title: '表格',
i18nTitle: 'routes.component.table',
requiresAuth: true, requiresAuth: true,
icon: 'mdi:table-large' icon: 'mdi:table-large'
} }
@@ -643,6 +702,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
], ],
meta: { meta: {
title: '组件示例', title: '组件示例',
i18nTitle: 'routes.component._value',
icon: 'cib:app-store', icon: 'cib:app-store',
order: 3 order: 3
} }
@@ -663,6 +723,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: 'ECharts', title: 'ECharts',
i18nTitle: 'routes.plugin.charts.echarts',
requiresAuth: true, requiresAuth: true,
icon: 'simple-icons:apacheecharts' icon: 'simple-icons:apacheecharts'
} }
@@ -673,6 +734,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: 'AntV', title: 'AntV',
i18nTitle: 'routes.plugin.charts.antv',
requiresAuth: true, requiresAuth: true,
icon: 'simple-icons:antdesign' icon: 'simple-icons:antdesign'
} }
@@ -680,6 +742,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
], ],
meta: { meta: {
title: '图表', title: '图表',
i18nTitle: 'routes.plugin.charts._value',
icon: 'mdi:chart-areaspline' icon: 'mdi:chart-areaspline'
} }
}, },
@@ -689,6 +752,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '地图', title: '地图',
i18nTitle: 'routes.plugin.map',
requiresAuth: true, requiresAuth: true,
icon: 'mdi:map' icon: 'mdi:map'
} }
@@ -699,6 +763,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '视频', title: '视频',
i18nTitle: 'routes.plugin.video',
requiresAuth: true, requiresAuth: true,
icon: 'mdi:video' icon: 'mdi:video'
} }
@@ -714,6 +779,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '富文本编辑器', title: '富文本编辑器',
i18nTitle: 'routes.plugin.editor.quill',
requiresAuth: true, requiresAuth: true,
icon: 'mdi:file-document-edit-outline' icon: 'mdi:file-document-edit-outline'
} }
@@ -724,6 +790,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: 'markdown编辑器', title: 'markdown编辑器',
i18nTitle: 'routes.plugin.editor.markdown',
requiresAuth: true, requiresAuth: true,
icon: 'ri:markdown-line' icon: 'ri:markdown-line'
} }
@@ -731,6 +798,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
], ],
meta: { meta: {
title: '编辑器', title: '编辑器',
i18nTitle: 'routes.plugin.editor._value',
icon: 'icon-park-outline:editor' icon: 'icon-park-outline:editor'
} }
}, },
@@ -740,6 +808,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: 'Swiper插件', title: 'Swiper插件',
i18nTitle: 'routes.plugin.swiper',
requiresAuth: true, requiresAuth: true,
icon: 'simple-icons:swiper' icon: 'simple-icons:swiper'
} }
@@ -750,6 +819,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '剪贴板', title: '剪贴板',
i18nTitle: 'routes.plugin.copy',
requiresAuth: true, requiresAuth: true,
icon: 'mdi:clipboard-outline' icon: 'mdi:clipboard-outline'
} }
@@ -760,6 +830,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '图标', title: '图标',
i18nTitle: 'routes.plugin.icon',
requiresAuth: true, requiresAuth: true,
localIcon: 'custom-icon' localIcon: 'custom-icon'
} }
@@ -770,6 +841,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '打印', title: '打印',
i18nTitle: 'routes.plugin.print',
requiresAuth: true, requiresAuth: true,
icon: 'mdi:printer' icon: 'mdi:printer'
} }
@@ -777,6 +849,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
], ],
meta: { meta: {
title: '插件示例', title: '插件示例',
i18nTitle: 'routes.plugin._value',
icon: 'clarity:plugin-line', icon: 'clarity:plugin-line',
order: 4 order: 4
} }
@@ -792,13 +865,26 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '权限切换', title: '权限切换',
i18nTitle: 'routes.auth-demo.permission',
requiresAuth: true, requiresAuth: true,
icon: 'ic:round-construction' icon: 'ic:round-construction'
} }
},
{
name: 'auth-demo_super',
path: '/auth-demo/super',
component: 'self',
meta: {
title: '超级管理员可见',
i18nTitle: 'routes.auth-demo.super',
requiresAuth: true,
icon: 'ic:round-supervisor-account'
}
} }
], ],
meta: { meta: {
title: '权限示例', title: '权限示例',
i18nTitle: 'routes.auth-demo._value',
icon: 'ic:baseline-security', icon: 'ic:baseline-security',
order: 5 order: 5
} }
@@ -814,6 +900,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: 'Tab', title: 'Tab',
i18nTitle: 'routes.function.tab',
requiresAuth: true, requiresAuth: true,
icon: 'ic:round-tab' icon: 'ic:round-tab'
} }
@@ -846,6 +933,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
], ],
meta: { meta: {
title: '功能', title: '功能',
i18nTitle: 'routes.function._value',
icon: 'icon-park-outline:all-application', icon: 'icon-park-outline:all-application',
order: 6 order: 6
} }
@@ -861,6 +949,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '异常页403', title: '异常页403',
i18nTitle: 'routes.exception.403',
requiresAuth: true, requiresAuth: true,
icon: 'ic:baseline-block' icon: 'ic:baseline-block'
} }
@@ -871,6 +960,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '异常页404', title: '异常页404',
i18nTitle: 'routes.exception.404',
requiresAuth: true, requiresAuth: true,
icon: 'ic:baseline-web-asset-off' icon: 'ic:baseline-web-asset-off'
} }
@@ -881,12 +971,14 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '异常页500', title: '异常页500',
i18nTitle: 'routes.exception.500',
requiresAuth: true, requiresAuth: true,
icon: 'ic:baseline-wifi-off' icon: 'ic:baseline-wifi-off'
} }
} }
], ],
meta: { meta: {
i18nTitle: 'routes.exception._value',
title: '异常页', title: '异常页',
icon: 'ant-design:exception-outlined', icon: 'ant-design:exception-outlined',
order: 7 order: 7
@@ -908,6 +1000,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '二级菜单', title: '二级菜单',
i18nTitle: 'routes.multi-menu.first.second',
requiresAuth: true, requiresAuth: true,
icon: 'mdi:menu' icon: 'mdi:menu'
} }
@@ -923,6 +1016,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '三级菜单', title: '三级菜单',
i18nTitle: 'routes.multi-menu.first.second-new.third',
requiresAuth: true, requiresAuth: true,
icon: 'mdi:menu' icon: 'mdi:menu'
} }
@@ -930,18 +1024,21 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
], ],
meta: { meta: {
title: '二级菜单(有子菜单)', title: '二级菜单(有子菜单)',
i18nTitle: 'routes.multi-menu.first.second-new._value',
icon: 'mdi:menu' icon: 'mdi:menu'
} }
} }
], ],
meta: { meta: {
title: '一级菜单', title: '一级菜单',
i18nTitle: 'routes.multi-menu.first._value',
icon: 'mdi:menu' icon: 'mdi:menu'
} }
} }
], ],
meta: { meta: {
title: '多级菜单', title: '多级菜单',
i18nTitle: 'routes.multi-menu._value',
icon: 'carbon:menu', icon: 'carbon:menu',
order: 8 order: 8
} }
@@ -957,6 +1054,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '权限管理', title: '权限管理',
i18nTitle: 'routes.management.auth',
requiresAuth: true, requiresAuth: true,
icon: 'ic:baseline-security' icon: 'ic:baseline-security'
} }
@@ -967,6 +1065,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '角色管理', title: '角色管理',
i18nTitle: 'routes.management.role',
requiresAuth: true, requiresAuth: true,
icon: 'carbon:user-role' icon: 'carbon:user-role'
} }
@@ -977,6 +1076,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '用户管理', title: '用户管理',
i18nTitle: 'routes.management.user',
requiresAuth: true, requiresAuth: true,
icon: 'ic:round-manage-accounts' icon: 'ic:round-manage-accounts'
} }
@@ -987,6 +1087,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '路由管理', title: '路由管理',
i18nTitle: 'routes.management.route',
requiresAuth: true, requiresAuth: true,
icon: 'material-symbols:route' icon: 'material-symbols:route'
} }
@@ -994,6 +1095,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
], ],
meta: { meta: {
title: '系统管理', title: '系统管理',
i18nTitle: 'routes.management._value',
icon: 'carbon:cloud-service-management', icon: 'carbon:cloud-service-management',
order: 9 order: 9
} }
@@ -1004,7 +1106,9 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '关于', title: '关于',
i18nTitle: 'routes.about',
requiresAuth: true, requiresAuth: true,
keepAlive: true,
singleLayout: 'basic', singleLayout: 'basic',
icon: 'fluent:book-information-24-regular', icon: 'fluent:book-information-24-regular',
order: 10 order: 10
@@ -1024,14 +1128,27 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
meta: { meta: {
title: '分析页', title: '分析页',
requiresAuth: true, requiresAuth: true,
icon: 'icon-park-outline:analysis' icon: 'icon-park-outline:analysis',
i18nTitle: 'routes.dashboard.analysis'
}
},
{
name: 'dashboard_workbench',
path: '/dashboard/workbench',
component: 'self',
meta: {
title: '工作台',
requiresAuth: true,
icon: 'icon-park-outline:workbench',
i18nTitle: 'routes.dashboard.workbench'
} }
} }
], ],
meta: { meta: {
title: '仪表盘', title: '仪表盘',
icon: 'mdi:monitor-dashboard', icon: 'mdi:monitor-dashboard',
order: 1 order: 1,
i18nTitle: 'routes.dashboard._value'
} }
}, },
{ {
@@ -1045,13 +1162,26 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '权限切换', title: '权限切换',
i18nTitle: 'routes.auth-demo.permission',
requiresAuth: true, requiresAuth: true,
icon: 'ic:round-construction' icon: 'ic:round-construction'
} }
},
{
name: 'auth-demo_super',
path: '/auth-demo/super',
component: 'self',
meta: {
title: '超级管理员可见',
i18nTitle: 'routes.auth-demo.super',
requiresAuth: true,
icon: 'ic:round-supervisor-account'
}
} }
], ],
meta: { meta: {
title: '权限示例', title: '权限示例',
i18nTitle: 'routes.auth-demo._value',
icon: 'ic:baseline-security', icon: 'ic:baseline-security',
order: 5 order: 5
} }
@@ -1072,6 +1202,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '二级菜单', title: '二级菜单',
i18nTitle: 'routes.multi-menu.first.second',
requiresAuth: true, requiresAuth: true,
icon: 'mdi:menu' icon: 'mdi:menu'
} }
@@ -1087,6 +1218,7 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '三级菜单', title: '三级菜单',
i18nTitle: 'routes.multi-menu.first.second-new.third',
requiresAuth: true, requiresAuth: true,
icon: 'mdi:menu' icon: 'mdi:menu'
} }
@@ -1094,20 +1226,23 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
], ],
meta: { meta: {
title: '二级菜单(有子菜单)', title: '二级菜单(有子菜单)',
i18nTitle: 'routes.multi-menu.first.second-new._value',
icon: 'mdi:menu' icon: 'mdi:menu'
} }
} }
], ],
meta: { meta: {
title: '一级菜单', title: '一级菜单',
i18nTitle: 'routes.multi-menu.first._value',
icon: 'mdi:menu' icon: 'mdi:menu'
} }
} }
], ],
meta: { meta: {
title: '多级菜单', title: '多级菜单',
i18nTitle: 'routes.multi-menu._value',
icon: 'carbon:menu', icon: 'carbon:menu',
order: 7 order: 8
} }
}, },
{ {
@@ -1116,10 +1251,12 @@ export const routeModel: Record<Auth.RoleType, AuthRoute.Route[]> = {
component: 'self', component: 'self',
meta: { meta: {
title: '关于', title: '关于',
i18nTitle: 'routes.about',
requiresAuth: true, requiresAuth: true,
keepAlive: true,
singleLayout: 'basic', singleLayout: 'basic',
icon: 'fluent:book-information-24-regular', icon: 'fluent:book-information-24-regular',
order: 8 order: 10
} }
} }
] ]

View File

@@ -1,11 +1,11 @@
{ {
"name": "soybean-admin", "name": "soybean-admin",
"version": "0.9.9", "version": "0.10.4",
"description": "A fresh and elegant admin template, based on Vue3、Vite3、TypeScript、NaiveUI and UnoCSS. 一个基于Vue3、Vite3、TypeScript、NaiveUI and UnoCSS的清新优雅的中后台模版。", "description": "A fresh and elegant admin template, based on Vue3、Vite3、TypeScript、NaiveUI and UnoCSS. 一个基于Vue3、Vite3、TypeScript、NaiveUI and UnoCSS的清新优雅的中后台模版。",
"author": { "author": {
"name": "Soybean", "name": "Soybean",
"email": "honghuangdc@gmail.com", "email": "soybeanjs@outlook.com",
"url": "https://github.com/honghuangdc" "url": "https://github.com/soybeanjs"
}, },
"license": "MIT", "license": "MIT",
"homepage": "https://github.com/honghuangdc/soybean-admin", "homepage": "https://github.com/honghuangdc/soybean-admin",
@@ -44,86 +44,81 @@
"build:vercel": "cross-env VITE_HASH_ROUTE=Y VITE_VERCEL=Y vite build", "build:vercel": "cross-env VITE_HASH_ROUTE=Y VITE_VERCEL=Y vite build",
"preview": "vite preview", "preview": "vite preview",
"typecheck": "vue-tsc --noEmit --skipLibCheck", "typecheck": "vue-tsc --noEmit --skipLibCheck",
"lint": "eslint . --fix --ext .js,.jsx,.mjs,.json,.ts,.tsx,.vue", "lint": "eslint . --fix",
"format": "soy prettier-format", "format": "soy prettier-write",
"commit": "soy git-commit", "commit": "soy git-commit",
"cleanup": "soy cleanup", "cleanup": "soy cleanup",
"update-pkg": "soy update-pkg", "update-pkg": "soy ncu",
"release": "soy release",
"tsx": "tsx", "tsx": "tsx",
"logo": "tsx ./scripts/logo.ts", "logo": "tsx ./scripts/logo.ts",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s", "prepare": "soy init-simple-git-hooks"
"release": "standard-version",
"prepare": "soy init-git-hooks"
}, },
"dependencies": { "dependencies": {
"@antv/data-set": "^0.11.8", "@antv/data-set": "0.11.8",
"@antv/g2": "^4.2.9", "@antv/g2": "4.2.10",
"@better-scroll/core": "^2.5.0", "@better-scroll/core": "2.5.1",
"@soybeanjs/vue-admin-layout": "^1.1.1", "@soybeanjs/vue-materials": "0.2.0",
"@soybeanjs/vue-admin-tab": "^1.0.5", "@vueuse/core": "10.4.1",
"@soybeanjs/vue-materials": "^0.1.8", "axios": "1.5.0",
"@vueuse/core": "^9.13.0", "clipboard": "2.0.11",
"axios": "0.27.2", "colord": "2.9.3",
"clipboard": "^2.0.11", "crypto-js": "4.1.1",
"colord": "^2.9.3", "dayjs": "1.11.10",
"crypto-js": "^4.1.1", "echarts": "5.4.3",
"dayjs": "^1.11.7", "form-data": "4.0.0",
"echarts": "^5.4.1", "lodash-es": "4.17.21",
"form-data": "^4.0.0", "naive-ui": "2.34.4",
"lodash-es": "^4.17.21", "pinia": "2.1.6",
"naive-ui": "2.34.3", "print-js": "1.6.0",
"pinia": "^2.0.33", "qs": "6.11.2",
"print-js": "^1.6.0", "socket.io-client": "4.7.2",
"qs": "^6.11.1", "swiper": "10.2.0",
"swiper": "^9.1.0", "ua-parser-js": "1.0.36",
"ua-parser-js": "^1.0.34", "vditor": "3.9.5",
"vditor": "^3.9.0", "vue": "3.3.4",
"vue": "3.2.47", "vue-i18n": "9.4.1",
"vue-i18n": "^9.2.2", "vue-router": "4.2.4",
"vue-router": "^4.1.6", "vuedraggable": "4.1.0",
"vuedraggable": "^4.1.0", "wangeditor": "4.7.15",
"wangeditor": "^4.7.15", "xgplayer": "3.0.9"
"xgplayer": "^2.32.2"
}, },
"devDependencies": { "devDependencies": {
"@amap/amap-jsapi-types": "^0.0.13", "@amap/amap-jsapi-types": "0.0.13",
"@iconify/json": "^2.2.33", "@iconify/json": "2.2.118",
"@iconify/vue": "^4.1.0", "@iconify/vue": "4.1.1",
"@soybeanjs/cli": "^0.1.7", "@plugin-web-update-notification/vite": "^1.6.5",
"@soybeanjs/vite-plugin-vue-page-route": "^0.0.5", "@soybeanjs/cli": "0.7.1",
"@types/bmapgl": "^0.0.5", "@soybeanjs/vite-plugin-vue-page-route": "0.0.10",
"@types/crypto-js": "^4.1.1", "@types/bmapgl": "0.0.7",
"@types/node": "18.15.0", "@types/crypto-js": "4.1.2",
"@types/qs": "^6.9.7", "@types/node": "20.6.3",
"@types/ua-parser-js": "^0.7.36", "@types/qs": "6.9.8",
"@unocss/preset-uno": "^0.50.4", "@types/ua-parser-js": "0.7.37",
"@unocss/transformer-directives": "^0.50.4", "@unocss/preset-uno": "0.56.0",
"@unocss/vite": "^0.50.4", "@unocss/transformer-directives": "0.56.0",
"@vitejs/plugin-vue": "^4.0.0", "@unocss/vite": "0.56.0",
"@vitejs/plugin-vue-jsx": "^3.0.0", "@vitejs/plugin-vue": "4.3.4",
"conventional-changelog": "^3.1.25", "@vitejs/plugin-vue-jsx": "3.0.2",
"cross-env": "^7.0.3", "cross-env": "7.0.3",
"eslint": "^8.36.0", "eslint": "8.49.0",
"eslint-config-soybeanjs": "^0.3.1", "eslint-config-soybeanjs": "0.5.6",
"lint-staged": "12.5.0", "mockjs": "1.1.0",
"mockjs": "^1.1.0", "rollup-plugin-visualizer": "5.9.2",
"rollup-plugin-visualizer": "^5.9.0", "sass": "1.67.0",
"sass": "^1.59.2", "simple-git-hooks": "2.9.0",
"simple-git-hooks": "^2.8.1", "tsx": "3.12.10",
"standard-version": "^9.5.0", "typescript": "5.2.2",
"tsx": "^3.12.4", "unplugin-icons": "0.17.0",
"typescript": "4.9.5", "unplugin-vue-components": "0.25.2",
"unplugin-icons": "^0.15.3", "vite": "4.4.9",
"unplugin-vue-components": "0.24.1", "vite-plugin-compression": "0.5.1",
"unplugin-vue-macros": "1.6.4", "vite-plugin-mock": "2.9.8",
"vite": "^4.1.4", "vite-plugin-progress": "0.0.7",
"vite-plugin-compression": "^0.5.1", "vite-plugin-pwa": "0.16.5",
"vite-plugin-html": "^3.2.0", "vite-plugin-svg-icons": "2.0.1",
"vite-plugin-mock": "^2.9.6", "vite-plugin-vue-devtools": "1.0.0-rc.4",
"vite-plugin-progress": "^0.0.6", "vue-tsc": "1.8.13"
"vite-plugin-pwa": "^0.14.4",
"vite-plugin-svg-icons": "^2.0.1",
"vue-tsc": "^1.2.0"
}, },
"pnpm": { "pnpm": {
"patchedDependencies": { "patchedDependencies": {
@@ -132,9 +127,9 @@
}, },
"simple-git-hooks": { "simple-git-hooks": {
"commit-msg": "pnpm soy git-commit-verify", "commit-msg": "pnpm soy git-commit-verify",
"pre-commit": "pnpm typecheck && pnpm lint-staged" "pre-commit": "pnpm typecheck && pnpm soy lint-staged"
}, },
"lint-staged": { "soybean": {
"*.{js,jsx,mjs,json,ts,tsx,vue}": "eslint . --fix" "useSoybeanToken": true
} }
} }

View File

@@ -5,56 +5,56 @@ index 35d5b9af3eff34324656879705dcb81470fc9697..3e6a52e0fbfdd39d3aaf1592ffd19ecd
@@ -126,17 +126,17 @@ return /******/ (function(modules) { // webpackBootstrap @@ -126,17 +126,17 @@ return /******/ (function(modules) { // webpackBootstrap
/* 1 */ /* 1 */
/***/ (function(module, exports, __webpack_require__) { /***/ (function(module, exports, __webpack_require__) {
- /* - /*
+ /* + /*
## Handler ## Handler
处理数据模板。 处理数据模板。
- -
+ +
* Handler.gen( template, name?, context? ) * Handler.gen( template, name?, context? )
入口方法。 入口方法。
* Data Template Definition, DTD * Data Template Definition, DTD
- -
+ +
处理数据模板定义。 处理数据模板定义。
* Handler.array( options ) * Handler.array( options )
@@ -146,7 +146,7 @@ return /******/ (function(modules) { // webpackBootstrap @@ -146,7 +146,7 @@ return /******/ (function(modules) { // webpackBootstrap
* Handler.string( options ) * Handler.string( options )
* Handler.function( options ) * Handler.function( options )
* Handler.regexp( options ) * Handler.regexp( options )
- -
+ +
处理路径(相对和绝对)。 处理路径(相对和绝对)。
* Handler.getValueByKeyPath( key, options ) * Handler.getValueByKeyPath( key, options )
@@ -177,7 +177,7 @@ return /******/ (function(modules) { // webpackBootstrap @@ -177,7 +177,7 @@ return /******/ (function(modules) { // webpackBootstrap
Handle.gen(template, name, options) Handle.gen(template, name, options)
context context
- currentContext, templateCurrentContext, - currentContext, templateCurrentContext,
+ currentContext, templateCurrentContext, + currentContext, templateCurrentContext,
path, templatePath path, templatePath
root, templateRoot root, templateRoot
*/ */
@@ -456,7 +456,7 @@ return /******/ (function(modules) { // webpackBootstrap @@ -456,7 +456,7 @@ return /******/ (function(modules) { // webpackBootstrap
phed = Handler.placeholder(ph, options.context.currentContext, options.context.templateCurrentContext, options) phed = Handler.placeholder(ph, options.context.currentContext, options.context.templateCurrentContext, options)
// 只有一个占位符,并且没有其他字符 // 只有一个占位符,并且没有其他字符
- if (placeholders.length === 1 && ph === result && typeof phed !== typeof result) { // - if (placeholders.length === 1 && ph === result && typeof phed !== typeof result) { //
+ if (placeholders.length === 1 && ph === result && typeof phed !== typeof result) { // + if (placeholders.length === 1 && ph === result && typeof phed !== typeof result) { //
result = phed result = phed
break break
@@ -627,7 +627,7 @@ return /******/ (function(modules) { // webpackBootstrap @@ -627,7 +627,7 @@ return /******/ (function(modules) { // webpackBootstrap
} }
// 引用的值已经计算好 // 引用的值已经计算好
if (currentContext && (key in currentContext)) return currentContext[key] if (currentContext && (key in currentContext)) return currentContext[key]
- -
+ +
// 尚未计算,递归引用数据模板中的属性 // 尚未计算,递归引用数据模板中的属性
if (templateCurrentContext && if (templateCurrentContext &&
@@ -63,41 +63,41 @@ index 35d5b9af3eff34324656879705dcb81470fc9697..3e6a52e0fbfdd39d3aaf1592ffd19ecd
var tpl = Mock.heredoc(function() { var tpl = Mock.heredoc(function() {
/*! /*!
{{email}}{{age}} {{email}}{{age}}
- <!-- Mock { - <!-- Mock {
+ <!-- Mock { + <!-- Mock {
email: '@EMAIL', email: '@EMAIL',
age: '@INT(1,100)' age: '@INT(1,100)'
} --> } -->
*\/ *\/
}) })
- -
+ +
**相关阅读** **相关阅读**
* [Creating multiline strings in JavaScript](http://stackoverflow.com/questions/805107/creating-multiline-strings-in-javascript)、 * [Creating multiline strings in JavaScript](http://stackoverflow.com/questions/805107/creating-multiline-strings-in-javascript)、
*/ */
@@ -850,7 +850,7 @@ return /******/ (function(modules) { // webpackBootstrap @@ -850,7 +850,7 @@ return /******/ (function(modules) { // webpackBootstrap
解析数据模板(属性名部分)。 解析数据模板(属性名部分)。
* Parser.parse( name ) * Parser.parse( name )
- -
+ +
```json ```json
{ {
parameters: [ name, inc, range, decimal ], parameters: [ name, inc, range, decimal ],
@@ -922,7 +922,7 @@ return /******/ (function(modules) { // webpackBootstrap @@ -922,7 +922,7 @@ return /******/ (function(modules) { // webpackBootstrap
/* /*
## Mock.Random ## Mock.Random
- -
+ +
工具类,用于生成各种随机数据。 工具类,用于生成各种随机数据。
*/ */
@@ -1251,7 +1251,7 @@ return /******/ (function(modules) { // webpackBootstrap @@ -1251,7 +1251,7 @@ return /******/ (function(modules) { // webpackBootstrap
替代图片源 替代图片源
http://fpoimg.com/ http://fpoimg.com/
- 参考自 - 参考自
+ 参考自 + 参考自
http://rensanning.iteye.com/blog/1933310 http://rensanning.iteye.com/blog/1933310
http://code.tutsplus.com/articles/the-top-8-placeholders-for-web-designers--net-19485 http://code.tutsplus.com/articles/the-top-8-placeholders-for-web-designers--net-19485
@@ -106,16 +106,16 @@ index 35d5b9af3eff34324656879705dcb81470fc9697..3e6a52e0fbfdd39d3aaf1592ffd19ecd
var bg_colour = Math.floor(Math.random() * 16777215).toString(16); var bg_colour = Math.floor(Math.random() * 16777215).toString(16);
bg_colour = "#" + ("000000" + bg_colour).slice(-6); bg_colour = "#" + ("000000" + bg_colour).slice(-6);
document.bgColor = bg_colour; document.bgColor = bg_colour;
- -
+ +
http://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/ http://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/
Creating random colors is actually more difficult than it seems. The randomness itself is easy, but aesthetically pleasing randomness is more difficult. Creating random colors is actually more difficult than it seems. The randomness itself is easy, but aesthetically pleasing randomness is more difficult.
https://github.com/devongovett/color-generator https://github.com/devongovett/color-generator
@@ -1561,7 +1561,7 @@ return /******/ (function(modules) { // webpackBootstrap @@ -1561,7 +1561,7 @@ return /******/ (function(modules) { // webpackBootstrap
http://tool.c7sky.com/webcolor http://tool.c7sky.com/webcolor
网页设计常用色彩搭配表 网页设计常用色彩搭配表
- -
+ +
https://github.com/One-com/one-color https://github.com/One-com/one-color
An OO-based JavaScript color parser/computation toolkit with support for RGB, HSV, HSL, CMYK, and alpha channels. An OO-based JavaScript color parser/computation toolkit with support for RGB, HSV, HSL, CMYK, and alpha channels.
@@ -124,7 +124,7 @@ index 35d5b9af3eff34324656879705dcb81470fc9697..3e6a52e0fbfdd39d3aaf1592ffd19ecd
color += letters[Math.floor(Math.random() * 16)] color += letters[Math.floor(Math.random() * 16)]
} }
return color return color
- -
+ +
// 随机生成一个无脑的颜色,格式为 '#RRGGBB'。 // 随机生成一个无脑的颜色,格式为 '#RRGGBB'。
// _brainlessColor() // _brainlessColor()
@@ -133,24 +133,24 @@ index 35d5b9af3eff34324656879705dcb81470fc9697..3e6a52e0fbfdd39d3aaf1592ffd19ecd
} }
return result.join(' ') return result.join(' ')
}, },
- // - //
+ // + //
cparagraph: function(min, max) { cparagraph: function(min, max) {
var len = range(3, 7, min, max) var len = range(3, 7, min, max)
var result = [] var result = []
@@ -2282,17 +2282,17 @@ return /******/ (function(modules) { // webpackBootstrap @@ -2282,17 +2282,17 @@ return /******/ (function(modules) { // webpackBootstrap
随机生成一个 URL。 随机生成一个 URL。
[URL 规范](http://www.w3.org/Addressing/URL/url-spec.txt) [URL 规范](http://www.w3.org/Addressing/URL/url-spec.txt)
- http Hypertext Transfer Protocol - http Hypertext Transfer Protocol
- ftp File Transfer protocol - ftp File Transfer protocol
- gopher The Gopher protocol - gopher The Gopher protocol
- mailto Electronic mail address - mailto Electronic mail address
- mid Message identifiers for electronic mail - mid Message identifiers for electronic mail
- cid Content identifiers for MIME body part - cid Content identifiers for MIME body part
- news Usenet news - news Usenet news
- nntp Usenet news for local NNTP access only - nntp Usenet news for local NNTP access only
- prospero Access using the prospero protocols - prospero Access using the prospero protocols
+ http Hypertext Transfer Protocol + http Hypertext Transfer Protocol
+ ftp File Transfer protocol + ftp File Transfer protocol
+ gopher The Gopher protocol + gopher The Gopher protocol
@@ -161,7 +161,7 @@ index 35d5b9af3eff34324656879705dcb81470fc9697..3e6a52e0fbfdd39d3aaf1592ffd19ecd
+ nntp Usenet news for local NNTP access only + nntp Usenet news for local NNTP access only
+ prospero Access using the prospero protocols + prospero Access using the prospero protocols
telnet rlogin tn3270 Reference to interactive sessions telnet rlogin tn3270 Reference to interactive sessions
- wais Wide Area Information Servers - wais Wide Area Information Servers
+ wais Wide Area Information Servers + wais Wide Area Information Servers
*/ */
url: function(protocol, host) { url: function(protocol, host) {
@@ -170,10 +170,10 @@ index 35d5b9af3eff34324656879705dcb81470fc9697..3e6a52e0fbfdd39d3aaf1592ffd19ecd
西南 重庆市 四川省 贵州省 云南省 西藏自治区 西南 重庆市 四川省 贵州省 云南省 西藏自治区
西北 陕西省 甘肃省 青海省 宁夏回族自治区 新疆维吾尔自治区 西北 陕西省 甘肃省 青海省 宁夏回族自治区 新疆维吾尔自治区
港澳台 香港特别行政区 澳门特别行政区 台湾省 港澳台 香港特别行政区 澳门特别行政区 台湾省
- -
+ +
**排序** **排序**
- -
+ +
```js ```js
var map = {} var map = {}
@@ -182,25 +182,25 @@ index 35d5b9af3eff34324656879705dcb81470fc9697..3e6a52e0fbfdd39d3aaf1592ffd19ecd
"0" / "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9" / "0" / "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9" /
"a" / "b" / "c" / "d" / "e" / "f" / "a" / "b" / "c" / "d" / "e" / "f" /
"A" / "B" / "C" / "D" / "E" / "F" "A" / "B" / "C" / "D" / "E" / "F"
- -
+ +
https://github.com/victorquinn/chancejs/blob/develop/chance.js#L1349 https://github.com/victorquinn/chancejs/blob/develop/chance.js#L1349
*/ */
guid: function() { guid: function() {
@@ -6629,7 +6629,7 @@ return /******/ (function(modules) { // webpackBootstrap @@ -6629,7 +6629,7 @@ return /******/ (function(modules) { // webpackBootstrap
} }
function CaptureGroup(n) { function CaptureGroup(n) {
- Group.call(this, "capture-group"), this.index = cgs[this.offset] || (cgs[this.offset] = index++), - Group.call(this, "capture-group"), this.index = cgs[this.offset] || (cgs[this.offset] = index++),
+ Group.call(this, "capture-group"), this.index = cgs[this.offset] || (cgs[this.offset] = index++), + Group.call(this, "capture-group"), this.index = cgs[this.offset] || (cgs[this.offset] = index++),
this.body = n; this.body = n;
} }
@@ -6711,7 +6711,7 @@ return /******/ (function(modules) { // webpackBootstrap @@ -6711,7 +6711,7 @@ return /******/ (function(modules) { // webpackBootstrap
} }
return r = l ? '"' + u(l) + '"' : "end of input", "Expected " + t + " but " + r + " found."; return r = l ? '"' + u(l) + '"' : "end of input", "Expected " + t + " but " + r + " found.";
} }
- this.expected = n, this.found = l, this.offset = u, this.line = t, this.column = r, - this.expected = n, this.found = l, this.offset = u, this.line = t, this.column = r,
+ this.expected = n, this.found = l, this.offset = u, this.line = t, this.column = r, + this.expected = n, this.found = l, this.offset = u, this.line = t, this.column = r,
this.name = "SyntaxError", this.message = e(n, l); this.name = "SyntaxError", this.message = e(n, l);
} }
@@ -209,8 +209,8 @@ index 35d5b9af3eff34324656879705dcb81470fc9697..3e6a52e0fbfdd39d3aaf1592ffd19ecd
function r(l) { function r(l) {
function u(l, u, t) { function u(l, u, t) {
var r, e; var r, e;
- for (r = u; t > r; r++) e = n.charAt(r), "\n" === e ? (l.seenCR || l.line++, l.column = 1, - for (r = u; t > r; r++) e = n.charAt(r), "\n" === e ? (l.seenCR || l.line++, l.column = 1,
- l.seenCR = !1) : "\r" === e || "\u2028" === e || "\u2029" === e ? (l.line++, l.column = 1, - l.seenCR = !1) : "\r" === e || "\u2028" === e || "\u2029" === e ? (l.line++, l.column = 1,
+ for (r = u; t > r; r++) e = n.charAt(r), "\n" === e ? (l.seenCR || l.line++, l.column = 1, + for (r = u; t > r; r++) e = n.charAt(r), "\n" === e ? (l.seenCR || l.line++, l.column = 1,
+ l.seenCR = !1) : "\r" === e || "\u2028" === e || "\u2029" === e ? (l.line++, l.column = 1, + l.seenCR = !1) : "\r" === e || "\u2028" === e || "\u2029" === e ? (l.line++, l.column = 1,
l.seenCR = !0) : (l.column++, l.seenCR = !1); l.seenCR = !0) : (l.column++, l.seenCR = !1);
@@ -220,10 +220,10 @@ index 35d5b9af3eff34324656879705dcb81470fc9697..3e6a52e0fbfdd39d3aaf1592ffd19ecd
} }
function c() { function c() {
var l, u, t, r, o; var l, u, t, r, o;
- return l = qt, u = i(), null !== u ? (t = qt, 124 === n.charCodeAt(qt) ? (r = fl, - return l = qt, u = i(), null !== u ? (t = qt, 124 === n.charCodeAt(qt) ? (r = fl,
- qt++) : (r = null, 0 === Wt && e(sl)), null !== r ? (o = c(), null !== o ? (r = [ r, o ], - qt++) : (r = null, 0 === Wt && e(sl)), null !== r ? (o = c(), null !== o ? (r = [ r, o ],
- t = r) : (qt = t, t = il)) : (qt = t, t = il), null === t && (t = al), null !== t ? (Lt = l, - t = r) : (qt = t, t = il)) : (qt = t, t = il), null === t && (t = al), null !== t ? (Lt = l,
- u = hl(u, t), null === u ? (qt = l, l = u) : l = u) : (qt = l, l = il)) : (qt = l, - u = hl(u, t), null === u ? (qt = l, l = u) : l = u) : (qt = l, l = il)) : (qt = l,
+ return l = qt, u = i(), null !== u ? (t = qt, 124 === n.charCodeAt(qt) ? (r = fl, + return l = qt, u = i(), null !== u ? (t = qt, 124 === n.charCodeAt(qt) ? (r = fl,
+ qt++) : (r = null, 0 === Wt && e(sl)), null !== r ? (o = c(), null !== o ? (r = [ r, o ], + qt++) : (r = null, 0 === Wt && e(sl)), null !== r ? (o = c(), null !== o ? (r = [ r, o ],
+ t = r) : (qt = t, t = il)) : (qt = t, t = il), null === t && (t = al), null !== t ? (Lt = l, + t = r) : (qt = t, t = il)) : (qt = t, t = il), null === t && (t = al), null !== t ? (Lt = l,
@@ -232,13 +232,13 @@ index 35d5b9af3eff34324656879705dcb81470fc9697..3e6a52e0fbfdd39d3aaf1592ffd19ecd
} }
function i() { function i() {
var n, l, u, t, r; var n, l, u, t, r;
- if (n = qt, l = f(), null === l && (l = al), null !== l) if (u = qt, Wt++, t = d(), - if (n = qt, l = f(), null === l && (l = al), null !== l) if (u = qt, Wt++, t = d(),
+ if (n = qt, l = f(), null === l && (l = al), null !== l) if (u = qt, Wt++, t = d(), + if (n = qt, l = f(), null === l && (l = al), null !== l) if (u = qt, Wt++, t = d(),
Wt--, null === t ? u = al : (qt = u, u = il), null !== u) { Wt--, null === t ? u = al : (qt = u, u = il), null !== u) {
- for (t = [], r = h(), null === r && (r = a()); null !== r; ) t.push(r), r = h(), - for (t = [], r = h(), null === r && (r = a()); null !== r; ) t.push(r), r = h(),
+ for (t = [], r = h(), null === r && (r = a()); null !== r; ) t.push(r), r = h(), + for (t = [], r = h(), null === r && (r = a()); null !== r; ) t.push(r), r = h(),
null === r && (r = a()); null === r && (r = a());
- null !== t ? (r = s(), null === r && (r = al), null !== r ? (Lt = n, l = dl(l, t, r), - null !== t ? (r = s(), null === r && (r = al), null !== r ? (Lt = n, l = dl(l, t, r),
+ null !== t ? (r = s(), null === r && (r = al), null !== r ? (Lt = n, l = dl(l, t, r), + null !== t ? (r = s(), null === r && (r = al), null !== r ? (Lt = n, l = dl(l, t, r),
null === l ? (qt = n, n = l) : n = l) : (qt = n, n = il)) : (qt = n, n = il); null === l ? (qt = n, n = l) : n = l) : (qt = n, n = il)) : (qt = n, n = il);
} else qt = n, n = il; else qt = n, n = il; } else qt = n, n = il; else qt = n, n = il;
@@ -247,43 +247,43 @@ index 35d5b9af3eff34324656879705dcb81470fc9697..3e6a52e0fbfdd39d3aaf1592ffd19ecd
} }
function f() { function f() {
var l, u; var l, u;
- return l = qt, 94 === n.charCodeAt(qt) ? (u = pl, qt++) : (u = null, 0 === Wt && e(vl)), - return l = qt, 94 === n.charCodeAt(qt) ? (u = pl, qt++) : (u = null, 0 === Wt && e(vl)),
+ return l = qt, 94 === n.charCodeAt(qt) ? (u = pl, qt++) : (u = null, 0 === Wt && e(vl)), + return l = qt, 94 === n.charCodeAt(qt) ? (u = pl, qt++) : (u = null, 0 === Wt && e(vl)),
null !== u && (Lt = l, u = wl()), null === u ? (qt = l, l = u) : l = u, l; null !== u && (Lt = l, u = wl()), null === u ? (qt = l, l = u) : l = u, l;
} }
function s() { function s() {
var l, u; var l, u;
- return l = qt, 36 === n.charCodeAt(qt) ? (u = Al, qt++) : (u = null, 0 === Wt && e(Cl)), - return l = qt, 36 === n.charCodeAt(qt) ? (u = Al, qt++) : (u = null, 0 === Wt && e(Cl)),
+ return l = qt, 36 === n.charCodeAt(qt) ? (u = Al, qt++) : (u = null, 0 === Wt && e(Cl)), + return l = qt, 36 === n.charCodeAt(qt) ? (u = Al, qt++) : (u = null, 0 === Wt && e(Cl)),
null !== u && (Lt = l, u = gl()), null === u ? (qt = l, l = u) : l = u, l; null !== u && (Lt = l, u = gl()), null === u ? (qt = l, l = u) : l = u, l;
} }
function h() { function h() {
var n, l, u; var n, l, u;
- return n = qt, l = a(), null !== l ? (u = d(), null !== u ? (Lt = n, l = bl(l, u), - return n = qt, l = a(), null !== l ? (u = d(), null !== u ? (Lt = n, l = bl(l, u),
+ return n = qt, l = a(), null !== l ? (u = d(), null !== u ? (Lt = n, l = bl(l, u), + return n = qt, l = a(), null !== l ? (u = d(), null !== u ? (Lt = n, l = bl(l, u),
null === l ? (qt = n, n = l) : n = l) : (qt = n, n = il)) : (qt = n, n = il), n; null === l ? (qt = n, n = l) : n = l) : (qt = n, n = il)) : (qt = n, n = il), n;
} }
function d() { function d() {
var n, l, u; var n, l, u;
- return Wt++, n = qt, l = p(), null !== l ? (u = k(), null === u && (u = al), null !== u ? (Lt = n, - return Wt++, n = qt, l = p(), null !== l ? (u = k(), null === u && (u = al), null !== u ? (Lt = n,
- l = Tl(l, u), null === l ? (qt = n, n = l) : n = l) : (qt = n, n = il)) : (qt = n, - l = Tl(l, u), null === l ? (qt = n, n = l) : n = l) : (qt = n, n = il)) : (qt = n,
+ return Wt++, n = qt, l = p(), null !== l ? (u = k(), null === u && (u = al), null !== u ? (Lt = n, + return Wt++, n = qt, l = p(), null !== l ? (u = k(), null === u && (u = al), null !== u ? (Lt = n,
+ l = Tl(l, u), null === l ? (qt = n, n = l) : n = l) : (qt = n, n = il)) : (qt = n, + l = Tl(l, u), null === l ? (qt = n, n = l) : n = l) : (qt = n, n = il)) : (qt = n,
n = il), Wt--, null === n && (l = null, 0 === Wt && e(kl)), n; n = il), Wt--, null === n && (l = null, 0 === Wt && e(kl)), n;
} }
function p() { function p() {
var n; var n;
- return n = v(), null === n && (n = w(), null === n && (n = A(), null === n && (n = C(), - return n = v(), null === n && (n = w(), null === n && (n = A(), null === n && (n = C(),
+ return n = v(), null === n && (n = w(), null === n && (n = A(), null === n && (n = C(), + return n = v(), null === n && (n = w(), null === n && (n = A(), null === n && (n = C(),
null === n && (n = g(), null === n && (n = b()))))), n; null === n && (n = g(), null === n && (n = b()))))), n;
} }
function v() { function v() {
var l, u, t, r, o, c; var l, u, t, r, o, c;
- return l = qt, 123 === n.charCodeAt(qt) ? (u = xl, qt++) : (u = null, 0 === Wt && e(yl)), - return l = qt, 123 === n.charCodeAt(qt) ? (u = xl, qt++) : (u = null, 0 === Wt && e(yl)),
- null !== u ? (t = T(), null !== t ? (44 === n.charCodeAt(qt) ? (r = ml, qt++) : (r = null, - null !== u ? (t = T(), null !== t ? (44 === n.charCodeAt(qt) ? (r = ml, qt++) : (r = null,
- 0 === Wt && e(Rl)), null !== r ? (o = T(), null !== o ? (125 === n.charCodeAt(qt) ? (c = Fl, - 0 === Wt && e(Rl)), null !== r ? (o = T(), null !== o ? (125 === n.charCodeAt(qt) ? (c = Fl,
- qt++) : (c = null, 0 === Wt && e(Ql)), null !== c ? (Lt = l, u = Sl(t, o), null === u ? (qt = l, - qt++) : (c = null, 0 === Wt && e(Ql)), null !== c ? (Lt = l, u = Sl(t, o), null === u ? (qt = l,
- l = u) : l = u) : (qt = l, l = il)) : (qt = l, l = il)) : (qt = l, l = il)) : (qt = l, - l = u) : l = u) : (qt = l, l = il)) : (qt = l, l = il)) : (qt = l, l = il)) : (qt = l,
+ return l = qt, 123 === n.charCodeAt(qt) ? (u = xl, qt++) : (u = null, 0 === Wt && e(yl)), + return l = qt, 123 === n.charCodeAt(qt) ? (u = xl, qt++) : (u = null, 0 === Wt && e(yl)),
+ null !== u ? (t = T(), null !== t ? (44 === n.charCodeAt(qt) ? (r = ml, qt++) : (r = null, + null !== u ? (t = T(), null !== t ? (44 === n.charCodeAt(qt) ? (r = ml, qt++) : (r = null,
+ 0 === Wt && e(Rl)), null !== r ? (o = T(), null !== o ? (125 === n.charCodeAt(qt) ? (c = Fl, + 0 === Wt && e(Rl)), null !== r ? (o = T(), null !== o ? (125 === n.charCodeAt(qt) ? (c = Fl,
@@ -293,9 +293,9 @@ index 35d5b9af3eff34324656879705dcb81470fc9697..3e6a52e0fbfdd39d3aaf1592ffd19ecd
} }
function w() { function w() {
var l, u, t, r; var l, u, t, r;
- return l = qt, 123 === n.charCodeAt(qt) ? (u = xl, qt++) : (u = null, 0 === Wt && e(yl)), - return l = qt, 123 === n.charCodeAt(qt) ? (u = xl, qt++) : (u = null, 0 === Wt && e(yl)),
- null !== u ? (t = T(), null !== t ? (n.substr(qt, 2) === Ul ? (r = Ul, qt += 2) : (r = null, - null !== u ? (t = T(), null !== t ? (n.substr(qt, 2) === Ul ? (r = Ul, qt += 2) : (r = null,
- 0 === Wt && e(El)), null !== r ? (Lt = l, u = Gl(t), null === u ? (qt = l, l = u) : l = u) : (qt = l, - 0 === Wt && e(El)), null !== r ? (Lt = l, u = Gl(t), null === u ? (qt = l, l = u) : l = u) : (qt = l,
+ return l = qt, 123 === n.charCodeAt(qt) ? (u = xl, qt++) : (u = null, 0 === Wt && e(yl)), + return l = qt, 123 === n.charCodeAt(qt) ? (u = xl, qt++) : (u = null, 0 === Wt && e(yl)),
+ null !== u ? (t = T(), null !== t ? (n.substr(qt, 2) === Ul ? (r = Ul, qt += 2) : (r = null, + null !== u ? (t = T(), null !== t ? (n.substr(qt, 2) === Ul ? (r = Ul, qt += 2) : (r = null,
+ 0 === Wt && e(El)), null !== r ? (Lt = l, u = Gl(t), null === u ? (qt = l, l = u) : l = u) : (qt = l, + 0 === Wt && e(El)), null !== r ? (Lt = l, u = Gl(t), null === u ? (qt = l, l = u) : l = u) : (qt = l,
@@ -303,9 +303,9 @@ index 35d5b9af3eff34324656879705dcb81470fc9697..3e6a52e0fbfdd39d3aaf1592ffd19ecd
} }
function A() { function A() {
var l, u, t, r; var l, u, t, r;
- return l = qt, 123 === n.charCodeAt(qt) ? (u = xl, qt++) : (u = null, 0 === Wt && e(yl)), - return l = qt, 123 === n.charCodeAt(qt) ? (u = xl, qt++) : (u = null, 0 === Wt && e(yl)),
- null !== u ? (t = T(), null !== t ? (125 === n.charCodeAt(qt) ? (r = Fl, qt++) : (r = null, - null !== u ? (t = T(), null !== t ? (125 === n.charCodeAt(qt) ? (r = Fl, qt++) : (r = null,
- 0 === Wt && e(Ql)), null !== r ? (Lt = l, u = Bl(t), null === u ? (qt = l, l = u) : l = u) : (qt = l, - 0 === Wt && e(Ql)), null !== r ? (Lt = l, u = Bl(t), null === u ? (qt = l, l = u) : l = u) : (qt = l,
+ return l = qt, 123 === n.charCodeAt(qt) ? (u = xl, qt++) : (u = null, 0 === Wt && e(yl)), + return l = qt, 123 === n.charCodeAt(qt) ? (u = xl, qt++) : (u = null, 0 === Wt && e(yl)),
+ null !== u ? (t = T(), null !== t ? (125 === n.charCodeAt(qt) ? (r = Fl, qt++) : (r = null, + null !== u ? (t = T(), null !== t ? (125 === n.charCodeAt(qt) ? (r = Fl, qt++) : (r = null,
+ 0 === Wt && e(Ql)), null !== r ? (Lt = l, u = Bl(t), null === u ? (qt = l, l = u) : l = u) : (qt = l, + 0 === Wt && e(Ql)), null !== r ? (Lt = l, u = Bl(t), null === u ? (qt = l, l = u) : l = u) : (qt = l,
@@ -313,45 +313,45 @@ index 35d5b9af3eff34324656879705dcb81470fc9697..3e6a52e0fbfdd39d3aaf1592ffd19ecd
} }
function C() { function C() {
var l, u; var l, u;
- return l = qt, 43 === n.charCodeAt(qt) ? (u = jl, qt++) : (u = null, 0 === Wt && e($l)), - return l = qt, 43 === n.charCodeAt(qt) ? (u = jl, qt++) : (u = null, 0 === Wt && e($l)),
+ return l = qt, 43 === n.charCodeAt(qt) ? (u = jl, qt++) : (u = null, 0 === Wt && e($l)), + return l = qt, 43 === n.charCodeAt(qt) ? (u = jl, qt++) : (u = null, 0 === Wt && e($l)),
null !== u && (Lt = l, u = ql()), null === u ? (qt = l, l = u) : l = u, l; null !== u && (Lt = l, u = ql()), null === u ? (qt = l, l = u) : l = u, l;
} }
function g() { function g() {
var l, u; var l, u;
- return l = qt, 42 === n.charCodeAt(qt) ? (u = Ll, qt++) : (u = null, 0 === Wt && e(Ml)), - return l = qt, 42 === n.charCodeAt(qt) ? (u = Ll, qt++) : (u = null, 0 === Wt && e(Ml)),
+ return l = qt, 42 === n.charCodeAt(qt) ? (u = Ll, qt++) : (u = null, 0 === Wt && e(Ml)), + return l = qt, 42 === n.charCodeAt(qt) ? (u = Ll, qt++) : (u = null, 0 === Wt && e(Ml)),
null !== u && (Lt = l, u = Dl()), null === u ? (qt = l, l = u) : l = u, l; null !== u && (Lt = l, u = Dl()), null === u ? (qt = l, l = u) : l = u, l;
} }
function b() { function b() {
var l, u; var l, u;
- return l = qt, 63 === n.charCodeAt(qt) ? (u = Hl, qt++) : (u = null, 0 === Wt && e(Ol)), - return l = qt, 63 === n.charCodeAt(qt) ? (u = Hl, qt++) : (u = null, 0 === Wt && e(Ol)),
+ return l = qt, 63 === n.charCodeAt(qt) ? (u = Hl, qt++) : (u = null, 0 === Wt && e(Ol)), + return l = qt, 63 === n.charCodeAt(qt) ? (u = Hl, qt++) : (u = null, 0 === Wt && e(Ol)),
null !== u && (Lt = l, u = Wl()), null === u ? (qt = l, l = u) : l = u, l; null !== u && (Lt = l, u = Wl()), null === u ? (qt = l, l = u) : l = u, l;
} }
function k() { function k() {
var l; var l;
- return 63 === n.charCodeAt(qt) ? (l = Hl, qt++) : (l = null, 0 === Wt && e(Ol)), - return 63 === n.charCodeAt(qt) ? (l = Hl, qt++) : (l = null, 0 === Wt && e(Ol)),
+ return 63 === n.charCodeAt(qt) ? (l = Hl, qt++) : (l = null, 0 === Wt && e(Ol)), + return 63 === n.charCodeAt(qt) ? (l = Hl, qt++) : (l = null, 0 === Wt && e(Ol)),
l; l;
} }
function T() { function T() {
var l, u, t; var l, u, t;
- if (l = qt, u = [], zl.test(n.charAt(qt)) ? (t = n.charAt(qt), qt++) : (t = null, - if (l = qt, u = [], zl.test(n.charAt(qt)) ? (t = n.charAt(qt), qt++) : (t = null,
- 0 === Wt && e(Il)), null !== t) for (;null !== t; ) u.push(t), zl.test(n.charAt(qt)) ? (t = n.charAt(qt), - 0 === Wt && e(Il)), null !== t) for (;null !== t; ) u.push(t), zl.test(n.charAt(qt)) ? (t = n.charAt(qt),
+ if (l = qt, u = [], zl.test(n.charAt(qt)) ? (t = n.charAt(qt), qt++) : (t = null, + if (l = qt, u = [], zl.test(n.charAt(qt)) ? (t = n.charAt(qt), qt++) : (t = null,
+ 0 === Wt && e(Il)), null !== t) for (;null !== t; ) u.push(t), zl.test(n.charAt(qt)) ? (t = n.charAt(qt), + 0 === Wt && e(Il)), null !== t) for (;null !== t; ) u.push(t), zl.test(n.charAt(qt)) ? (t = n.charAt(qt),
qt++) : (t = null, 0 === Wt && e(Il)); else u = il; qt++) : (t = null, 0 === Wt && e(Il)); else u = il;
- return null !== u && (Lt = l, u = Jl(u)), null === u ? (qt = l, l = u) : l = u, - return null !== u && (Lt = l, u = Jl(u)), null === u ? (qt = l, l = u) : l = u,
+ return null !== u && (Lt = l, u = Jl(u)), null === u ? (qt = l, l = u) : l = u, + return null !== u && (Lt = l, u = Jl(u)), null === u ? (qt = l, l = u) : l = u,
l; l;
} }
function x() { function x() {
var l, u, t, r; var l, u, t, r;
- return l = qt, 40 === n.charCodeAt(qt) ? (u = Kl, qt++) : (u = null, 0 === Wt && e(Nl)), - return l = qt, 40 === n.charCodeAt(qt) ? (u = Kl, qt++) : (u = null, 0 === Wt && e(Nl)),
- null !== u ? (t = R(), null === t && (t = F(), null === t && (t = m(), null === t && (t = y()))), - null !== u ? (t = R(), null === t && (t = F(), null === t && (t = m(), null === t && (t = y()))),
- null !== t ? (41 === n.charCodeAt(qt) ? (r = Pl, qt++) : (r = null, 0 === Wt && e(Vl)), - null !== t ? (41 === n.charCodeAt(qt) ? (r = Pl, qt++) : (r = null, 0 === Wt && e(Vl)),
- null !== r ? (Lt = l, u = Xl(t), null === u ? (qt = l, l = u) : l = u) : (qt = l, - null !== r ? (Lt = l, u = Xl(t), null === u ? (qt = l, l = u) : l = u) : (qt = l,
+ return l = qt, 40 === n.charCodeAt(qt) ? (u = Kl, qt++) : (u = null, 0 === Wt && e(Nl)), + return l = qt, 40 === n.charCodeAt(qt) ? (u = Kl, qt++) : (u = null, 0 === Wt && e(Nl)),
+ null !== u ? (t = R(), null === t && (t = F(), null === t && (t = m(), null === t && (t = y()))), + null !== u ? (t = R(), null === t && (t = F(), null === t && (t = m(), null === t && (t = y()))),
+ null !== t ? (41 === n.charCodeAt(qt) ? (r = Pl, qt++) : (r = null, 0 === Wt && e(Vl)), + null !== t ? (41 === n.charCodeAt(qt) ? (r = Pl, qt++) : (r = null, 0 === Wt && e(Vl)),
@@ -360,46 +360,46 @@ index 35d5b9af3eff34324656879705dcb81470fc9697..3e6a52e0fbfdd39d3aaf1592ffd19ecd
} }
function y() { function y() {
var n, l; var n, l;
- return n = qt, l = c(), null !== l && (Lt = n, l = Yl(l)), null === l ? (qt = n, - return n = qt, l = c(), null !== l && (Lt = n, l = Yl(l)), null === l ? (qt = n,
+ return n = qt, l = c(), null !== l && (Lt = n, l = Yl(l)), null === l ? (qt = n, + return n = qt, l = c(), null !== l && (Lt = n, l = Yl(l)), null === l ? (qt = n,
n = l) : n = l, n; n = l) : n = l, n;
} }
function m() { function m() {
var l, u, t; var l, u, t;
- return l = qt, n.substr(qt, 2) === Zl ? (u = Zl, qt += 2) : (u = null, 0 === Wt && e(_l)), - return l = qt, n.substr(qt, 2) === Zl ? (u = Zl, qt += 2) : (u = null, 0 === Wt && e(_l)),
- null !== u ? (t = c(), null !== t ? (Lt = l, u = nu(t), null === u ? (qt = l, l = u) : l = u) : (qt = l, - null !== u ? (t = c(), null !== t ? (Lt = l, u = nu(t), null === u ? (qt = l, l = u) : l = u) : (qt = l,
+ return l = qt, n.substr(qt, 2) === Zl ? (u = Zl, qt += 2) : (u = null, 0 === Wt && e(_l)), + return l = qt, n.substr(qt, 2) === Zl ? (u = Zl, qt += 2) : (u = null, 0 === Wt && e(_l)),
+ null !== u ? (t = c(), null !== t ? (Lt = l, u = nu(t), null === u ? (qt = l, l = u) : l = u) : (qt = l, + null !== u ? (t = c(), null !== t ? (Lt = l, u = nu(t), null === u ? (qt = l, l = u) : l = u) : (qt = l,
l = il)) : (qt = l, l = il), l; l = il)) : (qt = l, l = il), l;
} }
function R() { function R() {
var l, u, t; var l, u, t;
- return l = qt, n.substr(qt, 2) === lu ? (u = lu, qt += 2) : (u = null, 0 === Wt && e(uu)), - return l = qt, n.substr(qt, 2) === lu ? (u = lu, qt += 2) : (u = null, 0 === Wt && e(uu)),
- null !== u ? (t = c(), null !== t ? (Lt = l, u = tu(t), null === u ? (qt = l, l = u) : l = u) : (qt = l, - null !== u ? (t = c(), null !== t ? (Lt = l, u = tu(t), null === u ? (qt = l, l = u) : l = u) : (qt = l,
+ return l = qt, n.substr(qt, 2) === lu ? (u = lu, qt += 2) : (u = null, 0 === Wt && e(uu)), + return l = qt, n.substr(qt, 2) === lu ? (u = lu, qt += 2) : (u = null, 0 === Wt && e(uu)),
+ null !== u ? (t = c(), null !== t ? (Lt = l, u = tu(t), null === u ? (qt = l, l = u) : l = u) : (qt = l, + null !== u ? (t = c(), null !== t ? (Lt = l, u = tu(t), null === u ? (qt = l, l = u) : l = u) : (qt = l,
l = il)) : (qt = l, l = il), l; l = il)) : (qt = l, l = il), l;
} }
function F() { function F() {
var l, u, t; var l, u, t;
- return l = qt, n.substr(qt, 2) === ru ? (u = ru, qt += 2) : (u = null, 0 === Wt && e(eu)), - return l = qt, n.substr(qt, 2) === ru ? (u = ru, qt += 2) : (u = null, 0 === Wt && e(eu)),
- null !== u ? (t = c(), null !== t ? (Lt = l, u = ou(t), null === u ? (qt = l, l = u) : l = u) : (qt = l, - null !== u ? (t = c(), null !== t ? (Lt = l, u = ou(t), null === u ? (qt = l, l = u) : l = u) : (qt = l,
+ return l = qt, n.substr(qt, 2) === ru ? (u = ru, qt += 2) : (u = null, 0 === Wt && e(eu)), + return l = qt, n.substr(qt, 2) === ru ? (u = ru, qt += 2) : (u = null, 0 === Wt && e(eu)),
+ null !== u ? (t = c(), null !== t ? (Lt = l, u = ou(t), null === u ? (qt = l, l = u) : l = u) : (qt = l, + null !== u ? (t = c(), null !== t ? (Lt = l, u = ou(t), null === u ? (qt = l, l = u) : l = u) : (qt = l,
l = il)) : (qt = l, l = il), l; l = il)) : (qt = l, l = il), l;
} }
function Q() { function Q() {
var l, u, t, r, o; var l, u, t, r, o;
- if (Wt++, l = qt, 91 === n.charCodeAt(qt) ? (u = iu, qt++) : (u = null, 0 === Wt && e(au)), - if (Wt++, l = qt, 91 === n.charCodeAt(qt) ? (u = iu, qt++) : (u = null, 0 === Wt && e(au)),
- null !== u) if (94 === n.charCodeAt(qt) ? (t = pl, qt++) : (t = null, 0 === Wt && e(vl)), - null !== u) if (94 === n.charCodeAt(qt) ? (t = pl, qt++) : (t = null, 0 === Wt && e(vl)),
+ if (Wt++, l = qt, 91 === n.charCodeAt(qt) ? (u = iu, qt++) : (u = null, 0 === Wt && e(au)), + if (Wt++, l = qt, 91 === n.charCodeAt(qt) ? (u = iu, qt++) : (u = null, 0 === Wt && e(au)),
+ null !== u) if (94 === n.charCodeAt(qt) ? (t = pl, qt++) : (t = null, 0 === Wt && e(vl)), + null !== u) if (94 === n.charCodeAt(qt) ? (t = pl, qt++) : (t = null, 0 === Wt && e(vl)),
null === t && (t = al), null !== t) { null === t && (t = al), null !== t) {
- for (r = [], o = S(), null === o && (o = U()); null !== o; ) r.push(o), o = S(), - for (r = [], o = S(), null === o && (o = U()); null !== o; ) r.push(o), o = S(),
+ for (r = [], o = S(), null === o && (o = U()); null !== o; ) r.push(o), o = S(), + for (r = [], o = S(), null === o && (o = U()); null !== o; ) r.push(o), o = S(),
null === o && (o = U()); null === o && (o = U());
- null !== r ? (93 === n.charCodeAt(qt) ? (o = fu, qt++) : (o = null, 0 === Wt && e(su)), - null !== r ? (93 === n.charCodeAt(qt) ? (o = fu, qt++) : (o = null, 0 === Wt && e(su)),
- null !== o ? (Lt = l, u = hu(t, r), null === u ? (qt = l, l = u) : l = u) : (qt = l, - null !== o ? (Lt = l, u = hu(t, r), null === u ? (qt = l, l = u) : l = u) : (qt = l,
+ null !== r ? (93 === n.charCodeAt(qt) ? (o = fu, qt++) : (o = null, 0 === Wt && e(su)), + null !== r ? (93 === n.charCodeAt(qt) ? (o = fu, qt++) : (o = null, 0 === Wt && e(su)),
+ null !== o ? (Lt = l, u = hu(t, r), null === u ? (qt = l, l = u) : l = u) : (qt = l, + null !== o ? (Lt = l, u = hu(t, r), null === u ? (qt = l, l = u) : l = u) : (qt = l,
l = il)) : (qt = l, l = il); l = il)) : (qt = l, l = il);
@@ -408,9 +408,9 @@ index 35d5b9af3eff34324656879705dcb81470fc9697..3e6a52e0fbfdd39d3aaf1592ffd19ecd
} }
function S() { function S() {
var l, u, t, r; var l, u, t, r;
- return Wt++, l = qt, u = U(), null !== u ? (45 === n.charCodeAt(qt) ? (t = pu, qt++) : (t = null, - return Wt++, l = qt, u = U(), null !== u ? (45 === n.charCodeAt(qt) ? (t = pu, qt++) : (t = null,
- 0 === Wt && e(vu)), null !== t ? (r = U(), null !== r ? (Lt = l, u = wu(u, r), null === u ? (qt = l, - 0 === Wt && e(vu)), null !== t ? (r = U(), null !== r ? (Lt = l, u = wu(u, r), null === u ? (qt = l,
- l = u) : l = u) : (qt = l, l = il)) : (qt = l, l = il)) : (qt = l, l = il), Wt--, - l = u) : l = u) : (qt = l, l = il)) : (qt = l, l = il)) : (qt = l, l = il), Wt--,
+ return Wt++, l = qt, u = U(), null !== u ? (45 === n.charCodeAt(qt) ? (t = pu, qt++) : (t = null, + return Wt++, l = qt, u = U(), null !== u ? (45 === n.charCodeAt(qt) ? (t = pu, qt++) : (t = null,
+ 0 === Wt && e(vu)), null !== t ? (r = U(), null !== r ? (Lt = l, u = wu(u, r), null === u ? (qt = l, + 0 === Wt && e(vu)), null !== t ? (r = U(), null !== r ? (Lt = l, u = wu(u, r), null === u ? (qt = l,
+ l = u) : l = u) : (qt = l, l = il)) : (qt = l, l = il)) : (qt = l, l = il), Wt--, + l = u) : l = u) : (qt = l, l = il)) : (qt = l, l = il)) : (qt = l, l = il), Wt--,
@@ -418,22 +418,22 @@ index 35d5b9af3eff34324656879705dcb81470fc9697..3e6a52e0fbfdd39d3aaf1592ffd19ecd
} }
function U() { function U() {
var n, l; var n, l;
- return Wt++, n = G(), null === n && (n = E()), Wt--, null === n && (l = null, 0 === Wt && e(Au)), - return Wt++, n = G(), null === n && (n = E()), Wt--, null === n && (l = null, 0 === Wt && e(Au)),
+ return Wt++, n = G(), null === n && (n = E()), Wt--, null === n && (l = null, 0 === Wt && e(Au)), + return Wt++, n = G(), null === n && (n = E()), Wt--, null === n && (l = null, 0 === Wt && e(Au)),
n; n;
} }
function E() { function E() {
var l, u; var l, u;
- return l = qt, Cu.test(n.charAt(qt)) ? (u = n.charAt(qt), qt++) : (u = null, 0 === Wt && e(gu)), - return l = qt, Cu.test(n.charAt(qt)) ? (u = n.charAt(qt), qt++) : (u = null, 0 === Wt && e(gu)),
+ return l = qt, Cu.test(n.charAt(qt)) ? (u = n.charAt(qt), qt++) : (u = null, 0 === Wt && e(gu)), + return l = qt, Cu.test(n.charAt(qt)) ? (u = n.charAt(qt), qt++) : (u = null, 0 === Wt && e(gu)),
null !== u && (Lt = l, u = bu(u)), null === u ? (qt = l, l = u) : l = u, l; null !== u && (Lt = l, u = bu(u)), null === u ? (qt = l, l = u) : l = u, l;
} }
function G() { function G() {
var n; var n;
- return n = L(), null === n && (n = Y(), null === n && (n = H(), null === n && (n = O(), - return n = L(), null === n && (n = Y(), null === n && (n = H(), null === n && (n = O(),
- null === n && (n = W(), null === n && (n = z(), null === n && (n = I(), null === n && (n = J(), - null === n && (n = W(), null === n && (n = z(), null === n && (n = I(), null === n && (n = J(),
- null === n && (n = K(), null === n && (n = N(), null === n && (n = P(), null === n && (n = V(), - null === n && (n = K(), null === n && (n = N(), null === n && (n = P(), null === n && (n = V(),
- null === n && (n = X(), null === n && (n = _(), null === n && (n = nl(), null === n && (n = ll(), - null === n && (n = X(), null === n && (n = _(), null === n && (n = nl(), null === n && (n = ll(),
+ return n = L(), null === n && (n = Y(), null === n && (n = H(), null === n && (n = O(), + return n = L(), null === n && (n = Y(), null === n && (n = H(), null === n && (n = O(),
+ null === n && (n = W(), null === n && (n = z(), null === n && (n = I(), null === n && (n = J(), + null === n && (n = W(), null === n && (n = z(), null === n && (n = I(), null === n && (n = J(),
+ null === n && (n = K(), null === n && (n = N(), null === n && (n = P(), null === n && (n = V(), + null === n && (n = K(), null === n && (n = N(), null === n && (n = P(), null === n && (n = V(),
@@ -445,25 +445,25 @@ index 35d5b9af3eff34324656879705dcb81470fc9697..3e6a52e0fbfdd39d3aaf1592ffd19ecd
} }
function j() { function j() {
var l, u; var l, u;
- return l = qt, 46 === n.charCodeAt(qt) ? (u = ku, qt++) : (u = null, 0 === Wt && e(Tu)), - return l = qt, 46 === n.charCodeAt(qt) ? (u = ku, qt++) : (u = null, 0 === Wt && e(Tu)),
+ return l = qt, 46 === n.charCodeAt(qt) ? (u = ku, qt++) : (u = null, 0 === Wt && e(Tu)), + return l = qt, 46 === n.charCodeAt(qt) ? (u = ku, qt++) : (u = null, 0 === Wt && e(Tu)),
null !== u && (Lt = l, u = xu()), null === u ? (qt = l, l = u) : l = u, l; null !== u && (Lt = l, u = xu()), null === u ? (qt = l, l = u) : l = u, l;
} }
function $() { function $() {
var l, u; var l, u;
- return Wt++, l = qt, mu.test(n.charAt(qt)) ? (u = n.charAt(qt), qt++) : (u = null, - return Wt++, l = qt, mu.test(n.charAt(qt)) ? (u = n.charAt(qt), qt++) : (u = null,
- 0 === Wt && e(Ru)), null !== u && (Lt = l, u = bu(u)), null === u ? (qt = l, l = u) : l = u, - 0 === Wt && e(Ru)), null !== u && (Lt = l, u = bu(u)), null === u ? (qt = l, l = u) : l = u,
+ return Wt++, l = qt, mu.test(n.charAt(qt)) ? (u = n.charAt(qt), qt++) : (u = null, + return Wt++, l = qt, mu.test(n.charAt(qt)) ? (u = n.charAt(qt), qt++) : (u = null,
+ 0 === Wt && e(Ru)), null !== u && (Lt = l, u = bu(u)), null === u ? (qt = l, l = u) : l = u, + 0 === Wt && e(Ru)), null !== u && (Lt = l, u = bu(u)), null === u ? (qt = l, l = u) : l = u,
Wt--, null === l && (u = null, 0 === Wt && e(yu)), l; Wt--, null === l && (u = null, 0 === Wt && e(yu)), l;
} }
function q() { function q() {
var n; var n;
- return n = M(), null === n && (n = D(), null === n && (n = Y(), null === n && (n = H(), - return n = M(), null === n && (n = D(), null === n && (n = Y(), null === n && (n = H(),
- null === n && (n = O(), null === n && (n = W(), null === n && (n = z(), null === n && (n = I(), - null === n && (n = O(), null === n && (n = W(), null === n && (n = z(), null === n && (n = I(),
- null === n && (n = J(), null === n && (n = K(), null === n && (n = N(), null === n && (n = P(), - null === n && (n = J(), null === n && (n = K(), null === n && (n = N(), null === n && (n = P(),
- null === n && (n = V(), null === n && (n = X(), null === n && (n = Z(), null === n && (n = _(), - null === n && (n = V(), null === n && (n = X(), null === n && (n = Z(), null === n && (n = _(),
- null === n && (n = nl(), null === n && (n = ll(), null === n && (n = ul(), null === n && (n = tl()))))))))))))))))))), - null === n && (n = nl(), null === n && (n = ll(), null === n && (n = ul(), null === n && (n = tl()))))))))))))))))))),
+ return n = M(), null === n && (n = D(), null === n && (n = Y(), null === n && (n = H(), + return n = M(), null === n && (n = D(), null === n && (n = Y(), null === n && (n = H(),
+ null === n && (n = O(), null === n && (n = W(), null === n && (n = z(), null === n && (n = I(), + null === n && (n = O(), null === n && (n = W(), null === n && (n = z(), null === n && (n = I(),
+ null === n && (n = J(), null === n && (n = K(), null === n && (n = N(), null === n && (n = P(), + null === n && (n = J(), null === n && (n = K(), null === n && (n = N(), null === n && (n = P(),
@@ -473,93 +473,93 @@ index 35d5b9af3eff34324656879705dcb81470fc9697..3e6a52e0fbfdd39d3aaf1592ffd19ecd
} }
function L() { function L() {
var l, u; var l, u;
- return l = qt, n.substr(qt, 2) === Fu ? (u = Fu, qt += 2) : (u = null, 0 === Wt && e(Qu)), - return l = qt, n.substr(qt, 2) === Fu ? (u = Fu, qt += 2) : (u = null, 0 === Wt && e(Qu)),
+ return l = qt, n.substr(qt, 2) === Fu ? (u = Fu, qt += 2) : (u = null, 0 === Wt && e(Qu)), + return l = qt, n.substr(qt, 2) === Fu ? (u = Fu, qt += 2) : (u = null, 0 === Wt && e(Qu)),
null !== u && (Lt = l, u = Su()), null === u ? (qt = l, l = u) : l = u, l; null !== u && (Lt = l, u = Su()), null === u ? (qt = l, l = u) : l = u, l;
} }
function M() { function M() {
var l, u; var l, u;
- return l = qt, n.substr(qt, 2) === Fu ? (u = Fu, qt += 2) : (u = null, 0 === Wt && e(Qu)), - return l = qt, n.substr(qt, 2) === Fu ? (u = Fu, qt += 2) : (u = null, 0 === Wt && e(Qu)),
+ return l = qt, n.substr(qt, 2) === Fu ? (u = Fu, qt += 2) : (u = null, 0 === Wt && e(Qu)), + return l = qt, n.substr(qt, 2) === Fu ? (u = Fu, qt += 2) : (u = null, 0 === Wt && e(Qu)),
null !== u && (Lt = l, u = Uu()), null === u ? (qt = l, l = u) : l = u, l; null !== u && (Lt = l, u = Uu()), null === u ? (qt = l, l = u) : l = u, l;
} }
function D() { function D() {
var l, u; var l, u;
- return l = qt, n.substr(qt, 2) === Eu ? (u = Eu, qt += 2) : (u = null, 0 === Wt && e(Gu)), - return l = qt, n.substr(qt, 2) === Eu ? (u = Eu, qt += 2) : (u = null, 0 === Wt && e(Gu)),
+ return l = qt, n.substr(qt, 2) === Eu ? (u = Eu, qt += 2) : (u = null, 0 === Wt && e(Gu)), + return l = qt, n.substr(qt, 2) === Eu ? (u = Eu, qt += 2) : (u = null, 0 === Wt && e(Gu)),
null !== u && (Lt = l, u = Bu()), null === u ? (qt = l, l = u) : l = u, l; null !== u && (Lt = l, u = Bu()), null === u ? (qt = l, l = u) : l = u, l;
} }
function H() { function H() {
var l, u; var l, u;
- return l = qt, n.substr(qt, 2) === ju ? (u = ju, qt += 2) : (u = null, 0 === Wt && e($u)), - return l = qt, n.substr(qt, 2) === ju ? (u = ju, qt += 2) : (u = null, 0 === Wt && e($u)),
+ return l = qt, n.substr(qt, 2) === ju ? (u = ju, qt += 2) : (u = null, 0 === Wt && e($u)), + return l = qt, n.substr(qt, 2) === ju ? (u = ju, qt += 2) : (u = null, 0 === Wt && e($u)),
null !== u && (Lt = l, u = qu()), null === u ? (qt = l, l = u) : l = u, l; null !== u && (Lt = l, u = qu()), null === u ? (qt = l, l = u) : l = u, l;
} }
function O() { function O() {
var l, u; var l, u;
- return l = qt, n.substr(qt, 2) === Lu ? (u = Lu, qt += 2) : (u = null, 0 === Wt && e(Mu)), - return l = qt, n.substr(qt, 2) === Lu ? (u = Lu, qt += 2) : (u = null, 0 === Wt && e(Mu)),
+ return l = qt, n.substr(qt, 2) === Lu ? (u = Lu, qt += 2) : (u = null, 0 === Wt && e(Mu)), + return l = qt, n.substr(qt, 2) === Lu ? (u = Lu, qt += 2) : (u = null, 0 === Wt && e(Mu)),
null !== u && (Lt = l, u = Du()), null === u ? (qt = l, l = u) : l = u, l; null !== u && (Lt = l, u = Du()), null === u ? (qt = l, l = u) : l = u, l;
} }
function W() { function W() {
var l, u; var l, u;
- return l = qt, n.substr(qt, 2) === Hu ? (u = Hu, qt += 2) : (u = null, 0 === Wt && e(Ou)), - return l = qt, n.substr(qt, 2) === Hu ? (u = Hu, qt += 2) : (u = null, 0 === Wt && e(Ou)),
+ return l = qt, n.substr(qt, 2) === Hu ? (u = Hu, qt += 2) : (u = null, 0 === Wt && e(Ou)), + return l = qt, n.substr(qt, 2) === Hu ? (u = Hu, qt += 2) : (u = null, 0 === Wt && e(Ou)),
null !== u && (Lt = l, u = Wu()), null === u ? (qt = l, l = u) : l = u, l; null !== u && (Lt = l, u = Wu()), null === u ? (qt = l, l = u) : l = u, l;
} }
function z() { function z() {
var l, u; var l, u;
- return l = qt, n.substr(qt, 2) === zu ? (u = zu, qt += 2) : (u = null, 0 === Wt && e(Iu)), - return l = qt, n.substr(qt, 2) === zu ? (u = zu, qt += 2) : (u = null, 0 === Wt && e(Iu)),
+ return l = qt, n.substr(qt, 2) === zu ? (u = zu, qt += 2) : (u = null, 0 === Wt && e(Iu)), + return l = qt, n.substr(qt, 2) === zu ? (u = zu, qt += 2) : (u = null, 0 === Wt && e(Iu)),
null !== u && (Lt = l, u = Ju()), null === u ? (qt = l, l = u) : l = u, l; null !== u && (Lt = l, u = Ju()), null === u ? (qt = l, l = u) : l = u, l;
} }
function I() { function I() {
var l, u; var l, u;
- return l = qt, n.substr(qt, 2) === Ku ? (u = Ku, qt += 2) : (u = null, 0 === Wt && e(Nu)), - return l = qt, n.substr(qt, 2) === Ku ? (u = Ku, qt += 2) : (u = null, 0 === Wt && e(Nu)),
+ return l = qt, n.substr(qt, 2) === Ku ? (u = Ku, qt += 2) : (u = null, 0 === Wt && e(Nu)), + return l = qt, n.substr(qt, 2) === Ku ? (u = Ku, qt += 2) : (u = null, 0 === Wt && e(Nu)),
null !== u && (Lt = l, u = Pu()), null === u ? (qt = l, l = u) : l = u, l; null !== u && (Lt = l, u = Pu()), null === u ? (qt = l, l = u) : l = u, l;
} }
function J() { function J() {
var l, u; var l, u;
- return l = qt, n.substr(qt, 2) === Vu ? (u = Vu, qt += 2) : (u = null, 0 === Wt && e(Xu)), - return l = qt, n.substr(qt, 2) === Vu ? (u = Vu, qt += 2) : (u = null, 0 === Wt && e(Xu)),
+ return l = qt, n.substr(qt, 2) === Vu ? (u = Vu, qt += 2) : (u = null, 0 === Wt && e(Xu)), + return l = qt, n.substr(qt, 2) === Vu ? (u = Vu, qt += 2) : (u = null, 0 === Wt && e(Xu)),
null !== u && (Lt = l, u = Yu()), null === u ? (qt = l, l = u) : l = u, l; null !== u && (Lt = l, u = Yu()), null === u ? (qt = l, l = u) : l = u, l;
} }
function K() { function K() {
var l, u; var l, u;
- return l = qt, n.substr(qt, 2) === Zu ? (u = Zu, qt += 2) : (u = null, 0 === Wt && e(_u)), - return l = qt, n.substr(qt, 2) === Zu ? (u = Zu, qt += 2) : (u = null, 0 === Wt && e(_u)),
+ return l = qt, n.substr(qt, 2) === Zu ? (u = Zu, qt += 2) : (u = null, 0 === Wt && e(_u)), + return l = qt, n.substr(qt, 2) === Zu ? (u = Zu, qt += 2) : (u = null, 0 === Wt && e(_u)),
null !== u && (Lt = l, u = nt()), null === u ? (qt = l, l = u) : l = u, l; null !== u && (Lt = l, u = nt()), null === u ? (qt = l, l = u) : l = u, l;
} }
function N() { function N() {
var l, u; var l, u;
- return l = qt, n.substr(qt, 2) === lt ? (u = lt, qt += 2) : (u = null, 0 === Wt && e(ut)), - return l = qt, n.substr(qt, 2) === lt ? (u = lt, qt += 2) : (u = null, 0 === Wt && e(ut)),
+ return l = qt, n.substr(qt, 2) === lt ? (u = lt, qt += 2) : (u = null, 0 === Wt && e(ut)), + return l = qt, n.substr(qt, 2) === lt ? (u = lt, qt += 2) : (u = null, 0 === Wt && e(ut)),
null !== u && (Lt = l, u = tt()), null === u ? (qt = l, l = u) : l = u, l; null !== u && (Lt = l, u = tt()), null === u ? (qt = l, l = u) : l = u, l;
} }
function P() { function P() {
var l, u; var l, u;
- return l = qt, n.substr(qt, 2) === rt ? (u = rt, qt += 2) : (u = null, 0 === Wt && e(et)), - return l = qt, n.substr(qt, 2) === rt ? (u = rt, qt += 2) : (u = null, 0 === Wt && e(et)),
+ return l = qt, n.substr(qt, 2) === rt ? (u = rt, qt += 2) : (u = null, 0 === Wt && e(et)), + return l = qt, n.substr(qt, 2) === rt ? (u = rt, qt += 2) : (u = null, 0 === Wt && e(et)),
null !== u && (Lt = l, u = ot()), null === u ? (qt = l, l = u) : l = u, l; null !== u && (Lt = l, u = ot()), null === u ? (qt = l, l = u) : l = u, l;
} }
function V() { function V() {
var l, u; var l, u;
- return l = qt, n.substr(qt, 2) === ct ? (u = ct, qt += 2) : (u = null, 0 === Wt && e(it)), - return l = qt, n.substr(qt, 2) === ct ? (u = ct, qt += 2) : (u = null, 0 === Wt && e(it)),
+ return l = qt, n.substr(qt, 2) === ct ? (u = ct, qt += 2) : (u = null, 0 === Wt && e(it)), + return l = qt, n.substr(qt, 2) === ct ? (u = ct, qt += 2) : (u = null, 0 === Wt && e(it)),
null !== u && (Lt = l, u = at()), null === u ? (qt = l, l = u) : l = u, l; null !== u && (Lt = l, u = at()), null === u ? (qt = l, l = u) : l = u, l;
} }
function X() { function X() {
var l, u; var l, u;
- return l = qt, n.substr(qt, 2) === ft ? (u = ft, qt += 2) : (u = null, 0 === Wt && e(st)), - return l = qt, n.substr(qt, 2) === ft ? (u = ft, qt += 2) : (u = null, 0 === Wt && e(st)),
+ return l = qt, n.substr(qt, 2) === ft ? (u = ft, qt += 2) : (u = null, 0 === Wt && e(st)), + return l = qt, n.substr(qt, 2) === ft ? (u = ft, qt += 2) : (u = null, 0 === Wt && e(st)),
null !== u && (Lt = l, u = ht()), null === u ? (qt = l, l = u) : l = u, l; null !== u && (Lt = l, u = ht()), null === u ? (qt = l, l = u) : l = u, l;
} }
function Y() { function Y() {
var l, u, t; var l, u, t;
- return l = qt, n.substr(qt, 2) === dt ? (u = dt, qt += 2) : (u = null, 0 === Wt && e(pt)), - return l = qt, n.substr(qt, 2) === dt ? (u = dt, qt += 2) : (u = null, 0 === Wt && e(pt)),
- null !== u ? (n.length > qt ? (t = n.charAt(qt), qt++) : (t = null, 0 === Wt && e(vt)), - null !== u ? (n.length > qt ? (t = n.charAt(qt), qt++) : (t = null, 0 === Wt && e(vt)),
- null !== t ? (Lt = l, u = wt(t), null === u ? (qt = l, l = u) : l = u) : (qt = l, - null !== t ? (Lt = l, u = wt(t), null === u ? (qt = l, l = u) : l = u) : (qt = l,
+ return l = qt, n.substr(qt, 2) === dt ? (u = dt, qt += 2) : (u = null, 0 === Wt && e(pt)), + return l = qt, n.substr(qt, 2) === dt ? (u = dt, qt += 2) : (u = null, 0 === Wt && e(pt)),
+ null !== u ? (n.length > qt ? (t = n.charAt(qt), qt++) : (t = null, 0 === Wt && e(vt)), + null !== u ? (n.length > qt ? (t = n.charAt(qt), qt++) : (t = null, 0 === Wt && e(vt)),
+ null !== t ? (Lt = l, u = wt(t), null === u ? (qt = l, l = u) : l = u) : (qt = l, + null !== t ? (Lt = l, u = wt(t), null === u ? (qt = l, l = u) : l = u) : (qt = l,
@@ -567,9 +567,9 @@ index 35d5b9af3eff34324656879705dcb81470fc9697..3e6a52e0fbfdd39d3aaf1592ffd19ecd
} }
function Z() { function Z() {
var l, u, t; var l, u, t;
- return l = qt, 92 === n.charCodeAt(qt) ? (u = At, qt++) : (u = null, 0 === Wt && e(Ct)), - return l = qt, 92 === n.charCodeAt(qt) ? (u = At, qt++) : (u = null, 0 === Wt && e(Ct)),
- null !== u ? (gt.test(n.charAt(qt)) ? (t = n.charAt(qt), qt++) : (t = null, 0 === Wt && e(bt)), - null !== u ? (gt.test(n.charAt(qt)) ? (t = n.charAt(qt), qt++) : (t = null, 0 === Wt && e(bt)),
- null !== t ? (Lt = l, u = kt(t), null === u ? (qt = l, l = u) : l = u) : (qt = l, - null !== t ? (Lt = l, u = kt(t), null === u ? (qt = l, l = u) : l = u) : (qt = l,
+ return l = qt, 92 === n.charCodeAt(qt) ? (u = At, qt++) : (u = null, 0 === Wt && e(Ct)), + return l = qt, 92 === n.charCodeAt(qt) ? (u = At, qt++) : (u = null, 0 === Wt && e(Ct)),
+ null !== u ? (gt.test(n.charAt(qt)) ? (t = n.charAt(qt), qt++) : (t = null, 0 === Wt && e(bt)), + null !== u ? (gt.test(n.charAt(qt)) ? (t = n.charAt(qt), qt++) : (t = null, 0 === Wt && e(bt)),
+ null !== t ? (Lt = l, u = kt(t), null === u ? (qt = l, l = u) : l = u) : (qt = l, + null !== t ? (Lt = l, u = kt(t), null === u ? (qt = l, l = u) : l = u) : (qt = l,
@@ -577,15 +577,15 @@ index 35d5b9af3eff34324656879705dcb81470fc9697..3e6a52e0fbfdd39d3aaf1592ffd19ecd
} }
function _() { function _() {
var l, u, t, r; var l, u, t, r;
- if (l = qt, n.substr(qt, 2) === Tt ? (u = Tt, qt += 2) : (u = null, 0 === Wt && e(xt)), - if (l = qt, n.substr(qt, 2) === Tt ? (u = Tt, qt += 2) : (u = null, 0 === Wt && e(xt)),
+ if (l = qt, n.substr(qt, 2) === Tt ? (u = Tt, qt += 2) : (u = null, 0 === Wt && e(xt)), + if (l = qt, n.substr(qt, 2) === Tt ? (u = Tt, qt += 2) : (u = null, 0 === Wt && e(xt)),
null !== u) { null !== u) {
- if (t = [], yt.test(n.charAt(qt)) ? (r = n.charAt(qt), qt++) : (r = null, 0 === Wt && e(mt)), - if (t = [], yt.test(n.charAt(qt)) ? (r = n.charAt(qt), qt++) : (r = null, 0 === Wt && e(mt)),
- null !== r) for (;null !== r; ) t.push(r), yt.test(n.charAt(qt)) ? (r = n.charAt(qt), - null !== r) for (;null !== r; ) t.push(r), yt.test(n.charAt(qt)) ? (r = n.charAt(qt),
+ if (t = [], yt.test(n.charAt(qt)) ? (r = n.charAt(qt), qt++) : (r = null, 0 === Wt && e(mt)), + if (t = [], yt.test(n.charAt(qt)) ? (r = n.charAt(qt), qt++) : (r = null, 0 === Wt && e(mt)),
+ null !== r) for (;null !== r; ) t.push(r), yt.test(n.charAt(qt)) ? (r = n.charAt(qt), + null !== r) for (;null !== r; ) t.push(r), yt.test(n.charAt(qt)) ? (r = n.charAt(qt),
qt++) : (r = null, 0 === Wt && e(mt)); else t = il; qt++) : (r = null, 0 === Wt && e(mt)); else t = il;
- null !== t ? (Lt = l, u = Rt(t), null === u ? (qt = l, l = u) : l = u) : (qt = l, - null !== t ? (Lt = l, u = Rt(t), null === u ? (qt = l, l = u) : l = u) : (qt = l,
+ null !== t ? (Lt = l, u = Rt(t), null === u ? (qt = l, l = u) : l = u) : (qt = l, + null !== t ? (Lt = l, u = Rt(t), null === u ? (qt = l, l = u) : l = u) : (qt = l,
l = il); l = il);
} else qt = l, l = il; } else qt = l, l = il;
@@ -593,15 +593,15 @@ index 35d5b9af3eff34324656879705dcb81470fc9697..3e6a52e0fbfdd39d3aaf1592ffd19ecd
} }
function nl() { function nl() {
var l, u, t, r; var l, u, t, r;
- if (l = qt, n.substr(qt, 2) === Ft ? (u = Ft, qt += 2) : (u = null, 0 === Wt && e(Qt)), - if (l = qt, n.substr(qt, 2) === Ft ? (u = Ft, qt += 2) : (u = null, 0 === Wt && e(Qt)),
+ if (l = qt, n.substr(qt, 2) === Ft ? (u = Ft, qt += 2) : (u = null, 0 === Wt && e(Qt)), + if (l = qt, n.substr(qt, 2) === Ft ? (u = Ft, qt += 2) : (u = null, 0 === Wt && e(Qt)),
null !== u) { null !== u) {
- if (t = [], St.test(n.charAt(qt)) ? (r = n.charAt(qt), qt++) : (r = null, 0 === Wt && e(Ut)), - if (t = [], St.test(n.charAt(qt)) ? (r = n.charAt(qt), qt++) : (r = null, 0 === Wt && e(Ut)),
- null !== r) for (;null !== r; ) t.push(r), St.test(n.charAt(qt)) ? (r = n.charAt(qt), - null !== r) for (;null !== r; ) t.push(r), St.test(n.charAt(qt)) ? (r = n.charAt(qt),
+ if (t = [], St.test(n.charAt(qt)) ? (r = n.charAt(qt), qt++) : (r = null, 0 === Wt && e(Ut)), + if (t = [], St.test(n.charAt(qt)) ? (r = n.charAt(qt), qt++) : (r = null, 0 === Wt && e(Ut)),
+ null !== r) for (;null !== r; ) t.push(r), St.test(n.charAt(qt)) ? (r = n.charAt(qt), + null !== r) for (;null !== r; ) t.push(r), St.test(n.charAt(qt)) ? (r = n.charAt(qt),
qt++) : (r = null, 0 === Wt && e(Ut)); else t = il; qt++) : (r = null, 0 === Wt && e(Ut)); else t = il;
- null !== t ? (Lt = l, u = Et(t), null === u ? (qt = l, l = u) : l = u) : (qt = l, - null !== t ? (Lt = l, u = Et(t), null === u ? (qt = l, l = u) : l = u) : (qt = l,
+ null !== t ? (Lt = l, u = Et(t), null === u ? (qt = l, l = u) : l = u) : (qt = l, + null !== t ? (Lt = l, u = Et(t), null === u ? (qt = l, l = u) : l = u) : (qt = l,
l = il); l = il);
} else qt = l, l = il; } else qt = l, l = il;
@@ -609,15 +609,15 @@ index 35d5b9af3eff34324656879705dcb81470fc9697..3e6a52e0fbfdd39d3aaf1592ffd19ecd
} }
function ll() { function ll() {
var l, u, t, r; var l, u, t, r;
- if (l = qt, n.substr(qt, 2) === Gt ? (u = Gt, qt += 2) : (u = null, 0 === Wt && e(Bt)), - if (l = qt, n.substr(qt, 2) === Gt ? (u = Gt, qt += 2) : (u = null, 0 === Wt && e(Bt)),
+ if (l = qt, n.substr(qt, 2) === Gt ? (u = Gt, qt += 2) : (u = null, 0 === Wt && e(Bt)), + if (l = qt, n.substr(qt, 2) === Gt ? (u = Gt, qt += 2) : (u = null, 0 === Wt && e(Bt)),
null !== u) { null !== u) {
- if (t = [], St.test(n.charAt(qt)) ? (r = n.charAt(qt), qt++) : (r = null, 0 === Wt && e(Ut)), - if (t = [], St.test(n.charAt(qt)) ? (r = n.charAt(qt), qt++) : (r = null, 0 === Wt && e(Ut)),
- null !== r) for (;null !== r; ) t.push(r), St.test(n.charAt(qt)) ? (r = n.charAt(qt), - null !== r) for (;null !== r; ) t.push(r), St.test(n.charAt(qt)) ? (r = n.charAt(qt),
+ if (t = [], St.test(n.charAt(qt)) ? (r = n.charAt(qt), qt++) : (r = null, 0 === Wt && e(Ut)), + if (t = [], St.test(n.charAt(qt)) ? (r = n.charAt(qt), qt++) : (r = null, 0 === Wt && e(Ut)),
+ null !== r) for (;null !== r; ) t.push(r), St.test(n.charAt(qt)) ? (r = n.charAt(qt), + null !== r) for (;null !== r; ) t.push(r), St.test(n.charAt(qt)) ? (r = n.charAt(qt),
qt++) : (r = null, 0 === Wt && e(Ut)); else t = il; qt++) : (r = null, 0 === Wt && e(Ut)); else t = il;
- null !== t ? (Lt = l, u = jt(t), null === u ? (qt = l, l = u) : l = u) : (qt = l, - null !== t ? (Lt = l, u = jt(t), null === u ? (qt = l, l = u) : l = u) : (qt = l,
+ null !== t ? (Lt = l, u = jt(t), null === u ? (qt = l, l = u) : l = u) : (qt = l, + null !== t ? (Lt = l, u = jt(t), null === u ? (qt = l, l = u) : l = u) : (qt = l,
l = il); l = il);
} else qt = l, l = il; } else qt = l, l = il;
@@ -625,15 +625,15 @@ index 35d5b9af3eff34324656879705dcb81470fc9697..3e6a52e0fbfdd39d3aaf1592ffd19ecd
} }
function ul() { function ul() {
var l, u; var l, u;
- return l = qt, n.substr(qt, 2) === Tt ? (u = Tt, qt += 2) : (u = null, 0 === Wt && e(xt)), - return l = qt, n.substr(qt, 2) === Tt ? (u = Tt, qt += 2) : (u = null, 0 === Wt && e(xt)),
+ return l = qt, n.substr(qt, 2) === Tt ? (u = Tt, qt += 2) : (u = null, 0 === Wt && e(xt)), + return l = qt, n.substr(qt, 2) === Tt ? (u = Tt, qt += 2) : (u = null, 0 === Wt && e(xt)),
null !== u && (Lt = l, u = $t()), null === u ? (qt = l, l = u) : l = u, l; null !== u && (Lt = l, u = $t()), null === u ? (qt = l, l = u) : l = u, l;
} }
function tl() { function tl() {
var l, u, t; var l, u, t;
- return l = qt, 92 === n.charCodeAt(qt) ? (u = At, qt++) : (u = null, 0 === Wt && e(Ct)), - return l = qt, 92 === n.charCodeAt(qt) ? (u = At, qt++) : (u = null, 0 === Wt && e(Ct)),
- null !== u ? (n.length > qt ? (t = n.charAt(qt), qt++) : (t = null, 0 === Wt && e(vt)), - null !== u ? (n.length > qt ? (t = n.charAt(qt), qt++) : (t = null, 0 === Wt && e(vt)),
- null !== t ? (Lt = l, u = bu(t), null === u ? (qt = l, l = u) : l = u) : (qt = l, - null !== t ? (Lt = l, u = bu(t), null === u ? (qt = l, l = u) : l = u) : (qt = l,
+ return l = qt, 92 === n.charCodeAt(qt) ? (u = At, qt++) : (u = null, 0 === Wt && e(Ct)), + return l = qt, 92 === n.charCodeAt(qt) ? (u = At, qt++) : (u = null, 0 === Wt && e(Ct)),
+ null !== u ? (n.length > qt ? (t = n.charAt(qt), qt++) : (t = null, 0 === Wt && e(vt)), + null !== u ? (n.length > qt ? (t = n.charAt(qt), qt++) : (t = null, 0 === Wt && e(vt)),
+ null !== t ? (Lt = l, u = bu(t), null === u ? (qt = l, l = u) : l = u) : (qt = l, + null !== t ? (Lt = l, u = bu(t), null === u ? (qt = l, l = u) : l = u) : (qt = l,
@@ -644,7 +644,7 @@ index 35d5b9af3eff34324656879705dcb81470fc9697..3e6a52e0fbfdd39d3aaf1592ffd19ecd
var Util = __webpack_require__(3) var Util = __webpack_require__(3)
var Random = __webpack_require__(5) var Random = __webpack_require__(5)
/* /*
- -
+ +
*/ */
var Handler = { var Handler = {
@@ -653,21 +653,21 @@ index 35d5b9af3eff34324656879705dcb81470fc9697..3e6a52e0fbfdd39d3aaf1592ffd19ecd
return Random.integer(min, max) return Random.integer(min, max)
}, },
/* /*
- -
+ +
*/ */
charset: function(node, result, cache) { charset: function(node, result, cache) {
// node.invert // node.invert
@@ -7642,11 +7642,11 @@ return /******/ (function(modules) { // webpackBootstrap @@ -7642,11 +7642,11 @@ return /******/ (function(modules) { // webpackBootstrap
## valid(template, data) ## valid(template, data)
校验真实数据 data 是否与数据模板 template 匹配。 校验真实数据 data 是否与数据模板 template 匹配。
- -
+ +
实现思路: 实现思路:
1. 解析规则。 1. 解析规则。
先把数据模板 template 解析为更方便机器解析的 JSON-Schame 先把数据模板 template 解析为更方便机器解析的 JSON-Schame
- name 属性名 - name 属性名
+ name 属性名 + name 属性名
type 属性值类型 type 属性值类型
template 属性值模板 template 属性值模板
@@ -675,8 +675,8 @@ index 35d5b9af3eff34324656879705dcb81470fc9697..3e6a52e0fbfdd39d3aaf1592ffd19ecd
@@ -7655,7 +7655,7 @@ return /******/ (function(modules) { // webpackBootstrap @@ -7655,7 +7655,7 @@ return /******/ (function(modules) { // webpackBootstrap
2. 递归验证规则。 2. 递归验证规则。
然后用 JSON-Schema 校验真实数据,校验项包括属性名、值类型、值、值生成规则。 然后用 JSON-Schema 校验真实数据,校验项包括属性名、值类型、值、值生成规则。
- 提示信息 - 提示信息
+ 提示信息 + 提示信息
https://github.com/fge/json-schema-validator/blob/master/src/main/resources/com/github/fge/jsonschema/validator/validation.properties https://github.com/fge/json-schema-validator/blob/master/src/main/resources/com/github/fge/jsonschema/validator/validation.properties
[JSON-Schama validator](http://json-schema-validator.herokuapp.com/) [JSON-Schama validator](http://json-schema-validator.herokuapp.com/)
@@ -685,25 +685,25 @@ index 35d5b9af3eff34324656879705dcb81470fc9697..3e6a52e0fbfdd39d3aaf1592ffd19ecd
+step +step
整数部分 整数部分
小数部分 小数部分
- boolean - boolean
- string - string
+ boolean + boolean
+ string + string
min-max min-max
count count
## properties ## properties
@@ -7949,9 +7949,9 @@ return /******/ (function(modules) { // webpackBootstrap @@ -7949,9 +7949,9 @@ return /******/ (function(modules) { // webpackBootstrap
/* /*
完善、友好的提示信息 完善、友好的提示信息
- -
+ +
Equal, not equal to, greater than, less than, greater than or equal to, less than or equal to Equal, not equal to, greater than, less than, greater than or equal to, less than or equal to
- 路径 验证类型 描述 - 路径 验证类型 描述
+ 路径 验证类型 描述 + 路径 验证类型 描述
Expect path.name is less than or equal to expected, but path.name is actual. Expect path.name is less than or equal to expected, but path.name is actual.
@@ -8264,7 +8264,7 @@ return /******/ (function(modules) { // webpackBootstrap @@ -8264,7 +8264,7 @@ return /******/ (function(modules) { // webpackBootstrap
Util.extend(MockXMLHttpRequest.prototype, { Util.extend(MockXMLHttpRequest.prototype, {
// https://xhr.spec.whatwg.org/#the-open()-method // https://xhr.spec.whatwg.org/#the-open()-method
@@ -711,22 +711,22 @@ index 35d5b9af3eff34324656879705dcb81470fc9697..3e6a52e0fbfdd39d3aaf1592ffd19ecd
- open: function(method, url, async, username, password) { - open: function(method, url, async, username, password) {
+ open: function(method, url, async = true, username, password) { + open: function(method, url, async = true, username, password) {
var that = this var that = this
Util.extend(this.custom, { Util.extend(this.custom, {
@@ -8310,6 +8310,8 @@ return /******/ (function(modules) { // webpackBootstrap @@ -8310,6 +8310,8 @@ return /******/ (function(modules) { // webpackBootstrap
var xhr = createNativeXMLHttpRequest() var xhr = createNativeXMLHttpRequest()
this.custom.xhr = xhr this.custom.xhr = xhr
+ MockXMLHttpRequest.prototype.upload = xhr.upload + MockXMLHttpRequest.prototype.upload = xhr.upload
+ +
// 初始化所有事件,用于监听原生 XHR 对象的事件 // 初始化所有事件,用于监听原生 XHR 对象的事件
for (var i = 0; i < XHR_EVENTS.length; i++) { for (var i = 0; i < XHR_EVENTS.length; i++) {
xhr.addEventListener(XHR_EVENTS[i], handle) xhr.addEventListener(XHR_EVENTS[i], handle)
@@ -8360,6 +8362,7 @@ return /******/ (function(modules) { // webpackBootstrap @@ -8360,6 +8362,7 @@ return /******/ (function(modules) { // webpackBootstrap
// 原生 XHR // 原生 XHR
if (!this.match) { if (!this.match) {
+ this.custom.xhr.responseType = this.responseType || '' + this.custom.xhr.responseType = this.responseType || ''
this.custom.xhr.send(data) this.custom.xhr.send(data)
return return
} }

10028
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -1 +1 @@
<svg viewBox="0 0 160 160" xmlns="http://www.w3.org/2000/svg"><path d="M81.28 55.9c-.1-11.67-2.93-22.55-9.37-32.38-1-1.5-2.14-2.86-2.5-4.71a8.1 8.1 0 014-8.61 7.89 7.89 0 019.3 1.23 35.999 35.999 0 015.9 8.83 75.18 75.18 0 018.44 28.58 83.211 83.211 0 01-5.23 36.74 102.983 102.983 0 01-3 7.28 1.2 1.2 0 000 1.41c9.58 13.3 21.76 23 37.85 27.24a54.37 54.37 0 0019.68 1.57 7.72 7.72 0 018.36 6.9 7.903 7.903 0 01-6.7 9 64.744 64.744 0 01-23-1.33 77.68 77.68 0 01-36.93-19.88 93.628 93.628 0 01-11.91-13.71 2.18 2.18 0 00-2.3-1.06 72.744 72.744 0 00-27.38 7.55c-11.6 6-20.67 14.58-26.4 26.45a10.134 10.134 0 01-3.7 4.7 8 8 0 01-9.19-.7 7.86 7.86 0 01-2.36-9.28 60.324 60.324 0 018.72-14.52c12.2-15.43 28.21-24.59 47.32-28.57A85.085 85.085 0 0173.07 87c.524.015 1-.307 1.18-.8a76.06 76.06 0 006.53-22.3c.351-2.652.518-5.325.5-8z" fill="#1890ff"/><path d="M136.26 108.34a44.742 44.742 0 01-11.13-2.87 46.108 46.108 0 01-19.66-13.76 8 8 0 015.72-13.22 7.93 7.93 0 016.54 2.93 33.27 33.27 0 0018.87 10.75c1.546.155 3.058.553 4.48 1.18a8.08 8.08 0 013.84 9.21c-.92 3.52-4.13 5.81-8.66 5.78zm-80.6-75.02a7.61 7.61 0 016.64 5 49.139 49.139 0 013.64 17 46.33 46.33 0 01-2.46 17.28c-2 5.77-8.24 7.79-12.89 4.15a8.1 8.1 0 01-2.39-9 31.679 31.679 0 001.68-12.36 35.77 35.77 0 00-2.43-11c-2.1-5.45 1.75-11.07 8.21-11.07zm22.26 93.25a8 8 0 01-6.68 7.86 32.88 32.88 0 00-19.7 12.19 8.13 8.13 0 01-11.21 1.62 8 8 0 01-1.41-11.58A51.043 51.043 0 0154 123.81a45.842 45.842 0 0114-5.1c5.35-1.04 9.91 2.56 9.92 7.86z" fill="#1890ff"/></svg> <svg viewBox="0 0 160 160" xmlns="http://www.w3.org/2000/svg"><path d="M81.28 55.9c-.1-11.67-2.93-22.55-9.37-32.38-1-1.5-2.14-2.86-2.5-4.71a8.1 8.1 0 014-8.61 7.89 7.89 0 019.3 1.23 35.999 35.999 0 015.9 8.83 75.18 75.18 0 018.44 28.58 83.211 83.211 0 01-5.23 36.74 102.983 102.983 0 01-3 7.28 1.2 1.2 0 000 1.41c9.58 13.3 21.76 23 37.85 27.24a54.37 54.37 0 0019.68 1.57 7.72 7.72 0 018.36 6.9 7.903 7.903 0 01-6.7 9 64.744 64.744 0 01-23-1.33 77.68 77.68 0 01-36.93-19.88 93.628 93.628 0 01-11.91-13.71 2.18 2.18 0 00-2.3-1.06 72.744 72.744 0 00-27.38 7.55c-11.6 6-20.67 14.58-26.4 26.45a10.134 10.134 0 01-3.7 4.7 8 8 0 01-9.19-.7 7.86 7.86 0 01-2.36-9.28 60.324 60.324 0 018.72-14.52c12.2-15.43 28.21-24.59 47.32-28.57A85.085 85.085 0 0173.07 87c.524.015 1-.307 1.18-.8a76.06 76.06 0 006.53-22.3c.351-2.652.518-5.325.5-8z" fill="#646cff"/><path d="M136.26 108.34a44.742 44.742 0 01-11.13-2.87 46.108 46.108 0 01-19.66-13.76 8 8 0 015.72-13.22 7.93 7.93 0 016.54 2.93 33.27 33.27 0 0018.87 10.75c1.546.155 3.058.553 4.48 1.18a8.08 8.08 0 013.84 9.21c-.92 3.52-4.13 5.81-8.66 5.78zm-80.6-75.02a7.61 7.61 0 016.64 5 49.139 49.139 0 013.64 17 46.33 46.33 0 01-2.46 17.28c-2 5.77-8.24 7.79-12.89 4.15a8.1 8.1 0 01-2.39-9 31.679 31.679 0 001.68-12.36 35.77 35.77 0 00-2.43-11c-2.1-5.45 1.75-11.07 8.21-11.07zm22.26 93.25a8 8 0 01-6.68 7.86 32.88 32.88 0 00-19.7 12.19 8.13 8.13 0 01-11.21 1.62 8 8 0 01-1.41-11.58A51.043 51.043 0 0154 123.81a45.842 45.842 0 0114-5.1c5.35-1.04 9.91 2.56 9.92 7.86z" fill="#646cff"/></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -54,7 +54,7 @@ const props = withDefaults(defineProps<Props>(), {
placeholderClass: 'bg-white dark:bg-dark transition-background-color duration-300 ease-in-out', placeholderClass: 'bg-white dark:bg-dark transition-background-color duration-300 ease-in-out',
emptyDesc: '暂无数据', emptyDesc: '暂无数据',
iconClass: 'text-320px text-primary', iconClass: 'text-320px text-primary',
descClass: 'text-16px text-[#666]', descClass: 'text-16px text-#666',
showNetworkReload: false showNetworkReload: false
}); });

View File

@@ -4,25 +4,23 @@
<div class="w-56px h-56px my-36px"> <div class="w-56px h-56px my-36px">
<div class="relative h-full animate-spin"> <div class="relative h-full animate-spin">
<div <div
v-for="(item, index) in lodingClasses" v-for="(item, index) in loadingClasses"
:key="index" :key="index"
class="absolute w-16px h-16px bg-primary rounded-8px animate-pulse" class="absolute w-16px h-16px bg-primary rounded-8px animate-pulse"
:class="item" :class="item"
></div> ></div>
</div> </div>
</div> </div>
<h2 class="text-28px font-500 text-#646464">{{ title }}</h2> <h2 class="text-28px font-500 text-#646464">{{ $t('system.title') }}</h2>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useAppInfo } from '@/composables'; import { sessionStg, getRgbOfColor } from '@/utils';
import { localStg, getRgbOfColor } from '@/utils'; import { $t } from '@/locales';
import themeSettings from '@/settings/theme.json'; import themeSettings from '@/settings/theme.json';
const { title } = useAppInfo(); const loadingClasses = [
const lodingClasses = [
'left-0 top-0', 'left-0 top-0',
'left-0 bottom-0 animate-delay-500', 'left-0 bottom-0 animate-delay-500',
'right-0 top-0 animate-delay-1000', 'right-0 top-0 animate-delay-1000',
@@ -31,7 +29,7 @@ const lodingClasses = [
function addThemeColorCssVars() { function addThemeColorCssVars() {
const defaultColor = themeSettings.themeColor; const defaultColor = themeSettings.themeColor;
const themeColor = localStg.get('themeColor') || defaultColor; const themeColor = sessionStg.get('themeColor') || defaultColor;
const { r, g, b } = getRgbOfColor(themeColor); const { r, g, b } = getRgbOfColor(themeColor);

View File

@@ -1,7 +1,7 @@
<template> <template>
<div <div
class="dark:bg-[#18181c] dark:text-white dark:text-opacity-82 transition-all" class="dark:bg-dark dark:text-white dark:text-opacity-82 transition-all"
:class="inverted ? 'bg-[#001428] text-white' : 'bg-white text-[#333639]'" :class="inverted ? 'bg-#001428 text-white' : 'bg-white text-#333639'"
> >
<slot></slot> <slot></slot>
</div> </div>

View File

@@ -13,6 +13,8 @@ defineOptions({ name: 'DarkModeSwitch' });
interface Props { interface Props {
/** 暗黑模式 */ /** 暗黑模式 */
dark?: boolean; dark?: boolean;
/** 自定义暗黑模式动画过渡 */
customizeTransition?: boolean;
} }
const props = withDefaults(defineProps<Props>(), { const props = withDefaults(defineProps<Props>(), {
@@ -34,9 +36,54 @@ const darkMode = computed({
} }
}); });
function handleSwitch() { async function handleSwitch(event: MouseEvent) {
darkMode.value = !darkMode.value; const x = event.clientX;
const y = event.clientY;
if (!props.customizeTransition || !document.startViewTransition) {
darkMode.value = !darkMode.value;
return;
}
const endRadius = Math.hypot(Math.max(x, innerWidth - x), Math.max(y, innerHeight - y));
const transition = document.startViewTransition(() => {
darkMode.value = !darkMode.value;
});
await transition.ready;
const clipPath = [`circle(0px at ${x}px ${y}px)`, `circle(${endRadius}px at ${x}px ${y}px)`];
document.documentElement.animate(
{
clipPath: darkMode.value ? clipPath : [...clipPath].reverse()
},
{
duration: 300,
easing: 'ease-in',
pseudoElement: darkMode.value ? '::view-transition-new(root)' : '::view-transition-old(root)'
}
);
} }
</script> </script>
<style scoped></style> <style>
::view-transition-old(root),
::view-transition-new(root) {
animation: none;
mix-blend-mode: normal;
}
::view-transition-old(root) {
z-index: 9999;
}
::view-transition-new(root) {
z-index: 1;
}
.dark::view-transition-old(root) {
z-index: 1;
}
.dark::view-transition-new(root) {
z-index: 9999;
}
</style>

View File

@@ -1,6 +1,6 @@
<template> <template>
<div class="flex-col-center wh-full"> <div class="flex-col-center gap-24px min-h-520px wh-full overflow-hidden">
<div class="text-400px text-primary"> <div class="flex text-400px text-primary">
<icon-local-no-permission v-if="type === '403'" /> <icon-local-no-permission v-if="type === '403'" />
<icon-local-not-found v-if="type === '404'" /> <icon-local-not-found v-if="type === '404'" />
<icon-local-service-error v-if="type === '500'" /> <icon-local-service-error v-if="type === '500'" />

View File

@@ -2,14 +2,14 @@
<div v-if="showTooltip"> <div v-if="showTooltip">
<n-tooltip :placement="placement" trigger="hover"> <n-tooltip :placement="placement" trigger="hover">
<template #trigger> <template #trigger>
<div class="flex-center h-full cursor-pointer dark:hover:bg-[#333]" :class="contentClassName"> <div class="flex-center h-full cursor-pointer dark:hover:bg-#333" :class="contentClassName">
<slot></slot> <slot></slot>
</div> </div>
</template> </template>
{{ tooltipContent }} {{ tooltipContent }}
</n-tooltip> </n-tooltip>
</div> </div>
<div v-else class="flex-center cursor-pointer dark:hover:bg-[#333]" :class="contentClassName"> <div v-else class="flex-center cursor-pointer dark:hover:bg-#333" :class="contentClassName">
<slot></slot> <slot></slot>
</div> </div>
</template> </template>
@@ -41,7 +41,7 @@ const props = withDefaults(defineProps<Props>(), {
const showTooltip = computed(() => Boolean(props.tooltipContent)); const showTooltip = computed(() => Boolean(props.tooltipContent));
const contentClassName = computed( const contentClassName = computed(
() => `${props.contentClass} ${props.inverted ? 'hover:bg-primary' : 'hover:bg-[#f6f6f6]'}` () => `${props.contentClass} ${props.inverted ? 'hover:bg-primary' : 'hover:bg-#f6f6f6'}`
); );
</script> </script>

View File

@@ -8,7 +8,7 @@ import { isNumber } from '@/utils';
defineOptions({ name: 'CountTo' }); defineOptions({ name: 'CountTo' });
type TansitionKey = keyof typeof TransitionPresets; type TransitionKey = keyof typeof TransitionPresets;
interface Props { interface Props {
/** 初始值 */ /** 初始值 */
@@ -32,7 +32,7 @@ interface Props {
/** 使用缓冲动画函数 */ /** 使用缓冲动画函数 */
useEasing?: boolean; useEasing?: boolean;
/** 缓冲动画函数类型 */ /** 缓冲动画函数类型 */
transition?: TansitionKey; transition?: TransitionKey;
} }
const props = withDefaults(defineProps<Props>(), { const props = withDefaults(defineProps<Props>(), {

View File

@@ -14,7 +14,7 @@
<span v-for="iconItem in iconsList" :key="iconItem" @click="handleChange(iconItem)"> <span v-for="iconItem in iconsList" :key="iconItem" @click="handleChange(iconItem)">
<svg-icon <svg-icon
:icon="iconItem" :icon="iconItem"
class="border-1px border-[#d9d9d9] text-30px m-2px p-5px cursor-pointer" class="border-1px border-#d9d9d9 text-30px m-2px p-5px cursor-pointer"
:class="{ 'border-primary': modelValue === iconItem }" :class="{ 'border-primary': modelValue === iconItem }"
/> />
</span> </span>

View File

@@ -37,13 +37,13 @@ const bindAttrs = computed<{ class: string; style: string }>(() => ({
})); }));
const symbolId = computed(() => { const symbolId = computed(() => {
const { VITE_ICON_LOCAL_PREFFIX: preffix } = import.meta.env; const { VITE_ICON_LOCAL_PREFIX: prefix } = import.meta.env;
const defaultLocalIcon = 'no-icon'; const defaultLocalIcon = 'no-icon';
const icon = props.localIcon || defaultLocalIcon; const icon = props.localIcon || defaultLocalIcon;
return `#${preffix}-${icon}`; return `#${prefix}-${icon}`;
}); });
/** 渲染本地icon */ /** 渲染本地icon */

View File

@@ -1,14 +1,34 @@
import { effectScope, onScopeDispose, watch } from 'vue';
import { useRoute } from 'vue-router';
import { useEventListener } from '@vueuse/core'; import { useEventListener } from '@vueuse/core';
import { useI18n } from 'vue-i18n';
import { useTabStore, useThemeStore } from '@/store'; import { useTabStore, useThemeStore } from '@/store';
/** 全局事件 */ /** 全局事件 */
export function useGlobalEvents() { export function useGlobalEvents() {
const theme = useThemeStore(); const theme = useThemeStore();
const tab = useTabStore(); const tab = useTabStore();
const route = useRoute();
const { locale, t } = useI18n();
const scope = effectScope();
/** 页面离开时缓存多页签数据 */ /** 页面离开时缓存多页签数据 */
useEventListener(window, 'beforeunload', () => { useEventListener(window, 'beforeunload', () => {
theme.cacheThemeSettings(); theme.cacheThemeSettings();
tab.cacheTabRoutes(); tab.cacheTabRoutes();
}); });
scope.run(() => {
// 国际化切换时更新浏览器标签文本
watch(
() => locale.value,
() => {
document.title = route.meta.i18nTitle ? t(route.meta.i18nTitle) : route.meta.title;
}
);
});
onScopeDispose(() => {
scope.stop();
});
} }

View File

@@ -1,5 +1,5 @@
import { h } from 'vue'; import { h } from 'vue';
import SvgIcon from '~/src/components/custom/svg-icon.vue'; import SvgIcon from '@/components/custom/svg-icon.vue';
/** /**
* 图标渲染 * 图标渲染

View File

@@ -4,3 +4,4 @@ export * from './layout';
export * from './events'; export * from './events';
export * from './echarts'; export * from './echarts';
export * from './icon'; export * from './icon';
export * from './websocket';

View File

@@ -1,4 +1,4 @@
import { computed } from 'vue'; import { computed, watch } from 'vue';
import { breakpointsTailwind, useBreakpoints } from '@vueuse/core'; import { breakpointsTailwind, useBreakpoints } from '@vueuse/core';
import { useAppStore, useThemeStore } from '@/store'; import { useAppStore, useThemeStore } from '@/store';
@@ -63,6 +63,16 @@ export function useBasicLayout() {
return w; return w;
}); });
watch(
isMobile,
newValue => {
if (newValue) {
app.setSiderCollapse(true);
}
},
{ immediate: true }
);
return { return {
mode, mode,
isMobile, isMobile,

View File

@@ -2,26 +2,6 @@ import UAParser from 'ua-parser-js';
import { useAuthStore } from '@/store'; import { useAuthStore } from '@/store';
import { isArray, isString } from '@/utils'; import { isArray, isString } from '@/utils';
interface AppInfo {
/** 项目名称 */
name: string;
/** 项目标题 */
title: string;
/** 项目描述 */
desc: string;
}
/** 项目信息 */
export function useAppInfo(): AppInfo {
const { VITE_APP_NAME: name, VITE_APP_TITLE: title, VITE_APP_DESC: desc } = import.meta.env;
return {
name,
title,
desc
};
}
/** 获取设备信息 */ /** 获取设备信息 */
export function useDeviceInfo() { export function useDeviceInfo() {
const parser = new UAParser(); const parser = new UAParser();

View File

@@ -0,0 +1,50 @@
import { io } from 'socket.io-client';
import type { Socket } from 'socket.io-client';
import { useAppStore } from '../store';
type ListenEvents = {
update: (id: string, data: { name: string; age: number }) => void;
};
type EmitEvents = {
update: (id: string, data: { name: string; age: number }) => void;
};
export function useWebsocket() {
const app = useAppStore();
const socket: Socket<ListenEvents, EmitEvents> = (app.socket || io('ws://localhost:8080')) as Socket<
ListenEvents,
EmitEvents
>;
if (!app.socket) {
app.setSocket(socket);
}
function init() {
window.console.log('[socket.io] connecting...');
socket.on('connect', () => {
window.console.log('[socket.io] connected.');
});
socket.on('disconnect', () => {
window.console.log('[socket.io] disconnected.');
});
socket.on('update', (id, data) => {
window.console.log('[socket.io] update', id, data);
});
}
function handleUpdate(id: string, data: { name: string; age: number }) {
socket.emit('update', id, data);
}
init();
return {
handleUpdate
};
}

View File

@@ -2,7 +2,7 @@
export const BAIDU_MAP_SDK_URL = `https://api.map.baidu.com/getscript?v=3.0&ak=KSezYymXPth1DIGILRX3oYN9PxbOQQmU&services=&t=20210201100830&s=1`; export const BAIDU_MAP_SDK_URL = `https://api.map.baidu.com/getscript?v=3.0&ak=KSezYymXPth1DIGILRX3oYN9PxbOQQmU&services=&t=20210201100830&s=1`;
/** 高德地图sdk地址 */ /** 高德地图sdk地址 */
export const GAODE_MAP_SDK_URL = 'https://webapi.amap.com/maps?v=2.0&key=e7bd02bd504062087e6563daf4d6721d'; export const AMAP_SDK_URL = 'https://webapi.amap.com/maps?v=2.0&key=e7bd02bd504062087e6563daf4d6721d';
/** 腾讯地图sdk地址 */ /** 腾讯地图sdk地址 */
export const TENCENT_MAP_SDK_URL = 'https://map.qq.com/api/gljs?v=1.exp&key=A6DBZ-KXPLW-JKSRY-ONZF4-CPHY3-K6BL7'; export const TENCENT_MAP_SDK_URL = 'https://map.qq.com/api/gljs?v=1.exp&key=A6DBZ-KXPLW-JKSRY-ONZF4-CPHY3-K6BL7';

6
src/constants/_shared.ts Normal file
View File

@@ -0,0 +1,6 @@
export function transformObjectToOption<T extends object>(obj: T) {
return Object.entries(obj).map(([value, label]) => ({
value,
label
})) as Common.OptionWithKey<keyof T>[];
}

View File

@@ -1,33 +1,27 @@
import { $t } from '@/locales';
import { transformObjectToOption } from './_shared';
export const loginModuleLabels: Record<UnionKey.LoginModule, string> = { export const loginModuleLabels: Record<UnionKey.LoginModule, string> = {
'pwd-login': '账密登录', 'pwd-login': $t('page.login.pwdLogin.title'),
'code-login': '手机验证码登录', 'code-login': $t('page.login.codeLogin.title'),
register: '注册', register: $t('page.login.register.title'),
'reset-pwd': '重置密码', 'reset-pwd': $t('page.login.resetPwd.title'),
'bind-wechat': '微信绑定' 'bind-wechat': $t('page.login.bindWeChat.title')
}; };
export const userRoleLabels: Record<Auth.RoleType, string> = { export const userRoleLabels: Record<Auth.RoleType, string> = {
super: '超级管理员', super: $t('page.login.pwdLogin.superAdmin'),
admin: '管理员', admin: $t('page.login.pwdLogin.admin'),
user: '普通用户' user: $t('page.login.pwdLogin.user')
}; };
export const userRoleOptions = transformObjectToOption(userRoleLabels);
export const userRoleOptions: Common.OptionWithKey<Auth.RoleType>[] = [
{ value: 'super', label: userRoleLabels.super },
{ value: 'admin', label: userRoleLabels.admin },
{ value: 'user', label: userRoleLabels.user }
];
/** 用户性别 */ /** 用户性别 */
export const genderLabels: Record<UserManagement.GenderKey, string> = { export const genderLabels: Record<UserManagement.GenderKey, string> = {
0: '女', 0: '女',
1: '男' 1: '男'
}; };
export const genderOptions = transformObjectToOption(genderLabels);
export const genderOptions: Common.OptionWithKey<UserManagement.GenderKey>[] = [
{ value: '0', label: genderLabels['0'] },
{ value: '1', label: genderLabels['1'] }
];
/** 用户状态 */ /** 用户状态 */
export const userStatusLabels: Record<UserManagement.UserStatusKey, string> = { export const userStatusLabels: Record<UserManagement.UserStatusKey, string> = {
@@ -36,10 +30,4 @@ export const userStatusLabels: Record<UserManagement.UserStatusKey, string> = {
3: '冻结', 3: '冻结',
4: '软删除' 4: '软删除'
}; };
export const userStatusOptions = transformObjectToOption(userStatusLabels);
export const userStatusOptions: Common.OptionWithKey<UserManagement.UserStatusKey>[] = [
{ value: '1', label: userStatusLabels['1'] },
{ value: '2', label: userStatusLabels['2'] },
{ value: '3', label: userStatusLabels['3'] },
{ value: '4', label: userStatusLabels['4'] }
];

View File

@@ -1,81 +1,31 @@
import { transformObjectToOption } from './_shared';
export const themeLayoutModeLabels: Record<UnionKey.ThemeLayoutMode, string> = { export const themeLayoutModeLabels: Record<UnionKey.ThemeLayoutMode, string> = {
vertical: '左侧菜单模式', vertical: '左侧菜单模式',
horizontal: '顶部菜单模式', horizontal: '顶部菜单模式',
'vertical-mix': '左侧菜单混合模式', 'vertical-mix': '左侧菜单混合模式',
'horizontal-mix': '顶部菜单混合模式' 'horizontal-mix': '顶部菜单混合模式'
}; };
export const themeLayoutModeOptions = transformObjectToOption(themeLayoutModeLabels);
export const themeLayoutModeOptions: Common.OptionWithKey<UnionKey.ThemeLayoutMode>[] = [
{
value: 'vertical',
label: themeLayoutModeLabels.vertical
},
{
value: 'horizontal',
label: themeLayoutModeLabels.horizontal
},
{
value: 'vertical-mix',
label: themeLayoutModeLabels['vertical-mix']
},
{
value: 'horizontal-mix',
label: themeLayoutModeLabels['horizontal-mix']
}
];
export const themeScrollModeLabels: Record<UnionKey.ThemeScrollMode, string> = { export const themeScrollModeLabels: Record<UnionKey.ThemeScrollMode, string> = {
wrapper: '外层滚动', wrapper: '外层滚动',
content: '主体滚动' content: '主体滚动'
}; };
export const themeScrollModeOptions = transformObjectToOption(themeScrollModeLabels);
export const themeScrollModeOptions: Common.OptionWithKey<UnionKey.ThemeScrollMode>[] = [
{
value: 'wrapper',
label: themeScrollModeLabels.wrapper
},
{
value: 'content',
label: themeScrollModeLabels.content
}
];
export const themeTabModeLabels: Record<UnionKey.ThemeTabMode, string> = { export const themeTabModeLabels: Record<UnionKey.ThemeTabMode, string> = {
chrome: '谷歌风格', chrome: '谷歌风格',
button: '按钮风格' button: '按钮风格'
}; };
export const themeTabModeOptions = transformObjectToOption(themeTabModeLabels);
export const themeTabModeOptions: Common.OptionWithKey<UnionKey.ThemeTabMode>[] = [
{
value: 'chrome',
label: themeTabModeLabels.chrome
},
{
value: 'button',
label: themeTabModeLabels.button
}
];
export const themeHorizontalMenuPositionLabels: Record<UnionKey.ThemeHorizontalMenuPosition, string> = { export const themeHorizontalMenuPositionLabels: Record<UnionKey.ThemeHorizontalMenuPosition, string> = {
'flex-start': '居左', 'flex-start': '居左',
center: '居中', center: '居中',
'flex-end': '居右' 'flex-end': '居右'
}; };
export const themeHorizontalMenuPositionOptions = transformObjectToOption(themeHorizontalMenuPositionLabels);
export const themeHorizontalMenuPositionOptions: Common.OptionWithKey<UnionKey.ThemeHorizontalMenuPosition>[] = [
{
value: 'flex-start',
label: themeHorizontalMenuPositionLabels['flex-start']
},
{
value: 'center',
label: themeHorizontalMenuPositionLabels.center
},
{
value: 'flex-end',
label: themeHorizontalMenuPositionLabels['flex-end']
}
];
export const themeAnimateModeLabels: Record<UnionKey.ThemeAnimateMode, string> = { export const themeAnimateModeLabels: Record<UnionKey.ThemeAnimateMode, string> = {
'zoom-fade': '渐变', 'zoom-fade': '渐变',
@@ -85,30 +35,4 @@ export const themeAnimateModeLabels: Record<UnionKey.ThemeAnimateMode, string> =
'fade-bottom': '底部消退', 'fade-bottom': '底部消退',
'fade-scale': '缩放消退' 'fade-scale': '缩放消退'
}; };
export const themeAnimateModeOptions = transformObjectToOption(themeAnimateModeLabels);
export const themeAnimateModeOptions: Common.OptionWithKey<UnionKey.ThemeAnimateMode>[] = [
{
value: 'zoom-fade',
label: themeAnimateModeLabels['zoom-fade']
},
{
value: 'zoom-out',
label: themeAnimateModeLabels['zoom-out']
},
{
value: 'fade-slide',
label: themeAnimateModeLabels['fade-slide']
},
{
value: 'fade',
label: themeAnimateModeLabels.fade
},
{
value: 'fade-bottom',
label: themeAnimateModeLabels['fade-bottom']
},
{
value: 'fade-scale',
label: themeAnimateModeLabels['fade-scale']
}
];

View File

@@ -0,0 +1,180 @@
import { ref, reactive } from 'vue';
import type { Ref } from 'vue';
import type { PaginationProps, DataTableBaseColumn, DataTableSelectionColumn, DataTableExpandColumn } from 'naive-ui';
import type { TableColumnGroup } from 'naive-ui/es/data-table/src/interface';
import { useLoadingEmpty } from '../common';
/**
* 接口请求函数
*/
type ApiFn<T = any, R = any> = (args: T) => Promise<Service.RequestResult<R>>;
/**
* 接口请求函数的参数
*/
type GetApiFnParameters<T extends ApiFn, R = any> = T extends (args: infer P) => Promise<Service.RequestResult<R>>
? P
: never;
/**
* 接口请求函数的返回值
*/
type GetApiFnReturnType<T extends ApiFn, P = any> = T extends (args: P) => Promise<Service.RequestResult<infer R>>
? R
: never;
/**
* 表格接口请求后转换后的数据
*/
type Transformer<TableData, Response> = (response: Response) => {
data: TableData[];
pageNum: number;
pageSize: number;
total: number;
};
/**
* 列表接口参数更新
*/
type ApiParamsUpdater<P, R> = (params: P) => R;
/**
* 分页参数
*/
type PagePropsOfPagination = Pick<PaginationProps, 'page' | 'pageSize'>;
/**
* 自定义的列 key
*/
type CustomColumnKey<K = never> = K | 'action';
/**
* 表格的列
*/
type HookTableColumn<T = Record<string, unknown>> =
| (Omit<TableColumnGroup<T>, 'key'> & { key: CustomColumnKey<keyof T> })
| (Omit<DataTableBaseColumn<T>, 'key'> & { key: CustomColumnKey<keyof T> })
| DataTableSelectionColumn<T>
| DataTableExpandColumn<T>;
/**
* 表格配置
*/
type HookTableConfig<TableData, Fn extends ApiFn> = {
/**
* 列表接口参数
*/
apiParams: GetApiFnParameters<Fn>;
/**
* 列表接口返回数据转换
*/
transformer: Transformer<TableData, GetApiFnReturnType<Fn>>;
/**
* 列表列
*/
columns: () => HookTableColumn<TableData>[];
/**
* 列表接口参数更新
* @description 用于更新分页参数, 如果列表接口的参数不包含同名分页参数属性 `page` 和 `pageSize`, 需要通过此函数更新
* @default p => p
*/
apiParamsUpdater?: ApiParamsUpdater<GetApiFnParameters<Fn> & Partial<PagePropsOfPagination>, GetApiFnParameters<Fn>>;
/**
* 列表分页参数
*/
pagination?: PaginationProps;
/**
* 是否立即请求
* @default true
*/
immediate?: boolean;
};
/**
* 通用表格 hook
* @param apiFn 接口请求函数
* @param config 表格配置
*/
export default function useHookTable<TableData, Fn extends ApiFn>(apiFn: Fn, config: HookTableConfig<TableData, Fn>) {
const { loading, startLoading, endLoading, empty, setEmpty } = useLoadingEmpty();
const { apiParams, transformer, apiParamsUpdater = p => p, immediate = true } = config;
const data: Ref<TableData[]> = ref([]);
function updateData(update: TableData[]) {
data.value = update;
}
const columns = ref(config.columns()) as Ref<HookTableColumn<TableData>[]>;
const requestParams = ref(apiParams) as Ref<HookTableConfig<TableData, Fn>['apiParams']>;
function updateRequestParamsByPagination(p: PagePropsOfPagination) {
requestParams.value = apiParamsUpdater({ ...requestParams.value, ...p });
}
const pagination = reactive({
page: 1,
pageSize: 10,
showSizePicker: true,
pageSizes: [10, 15, 20, 25, 30],
onChange: (page: number) => {
pagination.page = page;
updateRequestParamsByPagination({ page });
getData();
},
onUpdatePageSize: (pageSize: number) => {
pagination.pageSize = pageSize;
pagination.page = 1;
updateRequestParamsByPagination({ pageSize });
getData();
},
...config.pagination
}) as PaginationProps;
function updatePagination(update: Partial<PaginationProps>) {
Object.assign(pagination, update);
updateRequestParamsByPagination({ page: pagination.page, pageSize: pagination.pageSize });
}
async function getData() {
startLoading();
const { data: apiData, error } = await apiFn(requestParams.value);
if (!error && data) {
const { data: tableData, pageNum, pageSize, total } = transformer(apiData);
updateData(tableData);
setEmpty(tableData.length === 0);
updatePagination({ page: pageNum, pageSize, itemCount: total });
}
endLoading();
}
function reloadColumns() {
columns.value = config.columns();
}
if (immediate) {
getData();
}
return {
data,
columns,
loading,
empty,
pagination,
getData,
updatePagination,
reloadColumns
};
}

View File

@@ -1,89 +0,0 @@
import { ref, reactive } from 'vue';
import type { Ref } from 'vue';
import type { DataTableBaseColumn, DataTableSelectionColumn, DataTableExpandColumn, PaginationProps } from 'naive-ui';
import type { MaybeComputedRef } from '@vueuse/core';
import type { TableColumnGroup, InternalRowData } from 'naive-ui/es/data-table/src/interface';
import { useLoadingEmpty } from '../common';
/**
* 表格的列
*/
type DataTableColumn<T = InternalRowData> =
| (Omit<TableColumnGroup<T>, 'key'> & { key: keyof T })
| (Omit<DataTableBaseColumn<T>, 'key'> & { key: keyof T })
| DataTableSelectionColumn<T>
| DataTableExpandColumn<T>;
/**
* 表格分页参数
*/
type TablePaginationParams = Pick<PaginationProps, 'page' | 'pageSize'>;
/**
* 表格接口的请求参数
*/
type TableApiParams = Record<string, unknown> & TablePaginationParams;
/**
* 表格接口的请求数据
*/
type TableApiData<T = InternalRowData> = {
data: T[];
pageNum: number;
pageSize: number;
total: number;
};
/**
* 表格接口的请求函数
*/
type TableApiFn<P extends TableApiParams, T extends InternalRowData> = (
params: P
) => Promise<Service.SuccessResult<TableApiData<T>>>;
export function useNaiveTable<TableData extends InternalRowData, P extends TableApiParams>(
apiFn: TableApiFn<P, TableData>,
apiParams: P,
columns: MaybeComputedRef<DataTableColumn<TableData>[]>
) {
const { loading, startLoading, endLoading, empty, setEmpty } = useLoadingEmpty();
const tableData: Ref<TableData[]> = ref([]);
async function getTableData(paginationParams?: TablePaginationParams) {
startLoading();
const params = { ...apiParams, ...paginationParams };
const { data } = await apiFn(params);
if (data) {
tableData.value = data.data;
setEmpty(data.data.length === 0);
}
endLoading();
}
const pagination: PaginationProps = reactive({
page: 1,
pageSize: 10,
showSizePicker: true,
pageSizes: [10, 15, 20, 25, 30],
onChange: (page: number) => {
pagination.page = page;
},
onUpdatePageSize: (pageSize: number) => {
pagination.pageSize = pageSize;
pagination.page = 1;
}
});
return {
tableData,
columns,
loading,
empty,
pagination,
start: getTableData
};
}

View File

@@ -1,6 +1,7 @@
<template> <template>
<admin-layout <admin-layout
:mode="mode" :mode="mode"
:is-mobile="isMobile"
:scroll-mode="theme.scrollMode" :scroll-mode="theme.scrollMode"
:scroll-el-id="app.scrollElId" :scroll-el-id="app.scrollElId"
:full-content="app.contentFull" :full-content="app.contentFull"
@@ -15,6 +16,8 @@
:sider-collapsed-width="siderCollapsedWidth" :sider-collapsed-width="siderCollapsedWidth"
:footer-visible="theme.footer.visible" :footer-visible="theme.footer.visible"
:fixed-footer="theme.footer.fixed" :fixed-footer="theme.footer.fixed"
:right-footer="theme.footer.right"
@click-mobile-sider-mask="app.setSiderCollapse(true)"
> >
<template #header> <template #header>
<global-header v-bind="headerProps" /> <global-header v-bind="headerProps" />
@@ -30,7 +33,7 @@
<global-footer /> <global-footer />
</template> </template>
</admin-layout> </admin-layout>
<global-back-top /> <n-back-top :key="theme.scrollMode" :listen-to="`#${app.scrollElId}`" class="z-100" />
<setting-drawer /> <setting-drawer />
</template> </template>
@@ -38,22 +41,22 @@
import { AdminLayout } from '@soybeanjs/vue-materials'; import { AdminLayout } from '@soybeanjs/vue-materials';
import { useAppStore, useThemeStore } from '@/store'; import { useAppStore, useThemeStore } from '@/store';
import { useBasicLayout } from '@/composables'; import { useBasicLayout } from '@/composables';
import { import { GlobalContent, GlobalFooter, GlobalHeader, GlobalSider, GlobalTab, SettingDrawer } from '../common';
GlobalBackTop,
GlobalContent,
GlobalFooter,
GlobalHeader,
GlobalSider,
GlobalTab,
SettingDrawer
} from '../common';
defineOptions({ name: 'BasicLayout' }); defineOptions({ name: 'BasicLayout' });
const app = useAppStore(); const app = useAppStore();
const theme = useThemeStore(); const theme = useThemeStore();
const { mode, headerProps, siderVisible, siderWidth, siderCollapsedWidth } = useBasicLayout(); const { mode, isMobile, headerProps, siderVisible, siderWidth, siderCollapsedWidth } = useBasicLayout();
</script> </script>
<style scoped></style> <style lang="scss">
#__SCROLL_EL_ID__ {
@include scrollbar(8px, #e1e1e1);
}
.dark #__SCROLL_EL_ID__ {
@include scrollbar(8px, #555);
}
</style>

View File

@@ -1,15 +0,0 @@
<template>
<n-back-top :show="show" class="z-1000" />
</template>
<script lang="ts" setup>
import { computed } from 'vue';
import { useWindowScroll } from '@vueuse/core';
defineOptions({ name: 'GlobalBackTop' });
const { y: scrollY } = useWindowScroll();
const show = computed(() => scrollY.value > 180);
</script>
<style scoped></style>

View File

@@ -13,7 +13,7 @@
v-if="app.reloadFlag" v-if="app.reloadFlag"
:key="route.fullPath" :key="route.fullPath"
:class="{ 'p-16px': showPadding }" :class="{ 'p-16px': showPadding }"
class="flex-grow bg-[#f6f9f8] dark:bg-[#101014] transition duration-300 ease-in-out" class="flex-grow bg-#f6f9f8 dark:bg-#101014 transition duration-300 ease-in-out"
/> />
</keep-alive> </keep-alive>
</transition> </transition>

View File

@@ -1,11 +1,15 @@
<template> <template>
<dark-mode-container class="flex-center h-full"> <dark-mode-container class="flex-center h-full" :inverted="theme.footer.inverted">
<span>Copyright ©2021 Soybean Admin</span> <span>Copyright ©2021 Soybean Admin</span>
</dark-mode-container> </dark-mode-container>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useThemeStore } from '@/store';
defineOptions({ name: 'GlobalFooter' }); defineOptions({ name: 'GlobalFooter' });
const theme = useThemeStore();
</script> </script>
<style scoped></style> <style scoped></style>

View File

@@ -2,7 +2,7 @@
<n-breadcrumb class="px-12px"> <n-breadcrumb class="px-12px">
<template v-for="breadcrumb in breadcrumbs" :key="breadcrumb.key"> <template v-for="breadcrumb in breadcrumbs" :key="breadcrumb.key">
<n-breadcrumb-item> <n-breadcrumb-item>
<n-dropdown v-if="breadcrumb.hasChildren" :options="breadcrumb.children" @select="dropdownSelect"> <n-dropdown v-if="breadcrumb.hasChildren" :options="breadcrumb.options" @select="dropdownSelect">
<span> <span>
<component <component
:is="breadcrumb.icon" :is="breadcrumb.icon"
@@ -19,7 +19,9 @@
class="inline-block align-text-bottom mr-4px text-16px" class="inline-block align-text-bottom mr-4px text-16px"
:class="{ 'text-#BBBBBB': theme.header.inverted }" :class="{ 'text-#BBBBBB': theme.header.inverted }"
/> />
<span :class="{ 'text-#BBBBBB': theme.header.inverted }">{{ breadcrumb.label }}</span> <span :class="{ 'text-#BBBBBB': theme.header.inverted }">
{{ breadcrumb.label }}
</span>
</template> </template>
</n-breadcrumb-item> </n-breadcrumb-item>
</template> </template>
@@ -33,6 +35,7 @@ import { routePath } from '@/router';
import { useRouteStore, useThemeStore } from '@/store'; import { useRouteStore, useThemeStore } from '@/store';
import { useRouterPush } from '@/composables'; import { useRouterPush } from '@/composables';
import { getBreadcrumbByRouteKey } from '@/utils'; import { getBreadcrumbByRouteKey } from '@/utils';
import { $t } from '@/locales';
defineOptions({ name: 'GlobalBreadcrumb' }); defineOptions({ name: 'GlobalBreadcrumb' });
@@ -42,7 +45,13 @@ const routeStore = useRouteStore();
const { routerPush } = useRouterPush(); const { routerPush } = useRouterPush();
const breadcrumbs = computed(() => const breadcrumbs = computed(() =>
getBreadcrumbByRouteKey(route.name as string, routeStore.menus as App.GlobalMenuOption[], routePath('root')) getBreadcrumbByRouteKey(route.name as string, routeStore.menus as App.GlobalMenuOption[], routePath('root')).map(
item => ({
...item,
label: item.i18nTitle ? $t(item.i18nTitle) : item.label,
options: item.options?.map(oItem => ({ ...oItem, label: oItem.i18nTitle ? $t(oItem.i18nTitle) : oItem.label }))
})
)
); );
function dropdownSelect(key: string) { function dropdownSelect(key: string) {

View File

@@ -20,6 +20,7 @@ import { useRoute } from 'vue-router';
import type { MenuOption } from 'naive-ui'; import type { MenuOption } from 'naive-ui';
import { useRouteStore, useThemeStore } from '@/store'; import { useRouteStore, useThemeStore } from '@/store';
import { useRouterPush } from '@/composables'; import { useRouterPush } from '@/composables';
import { translateMenuLabel } from '@/utils';
defineOptions({ name: 'HeaderMenu' }); defineOptions({ name: 'HeaderMenu' });
@@ -28,7 +29,7 @@ const routeStore = useRouteStore();
const theme = useThemeStore(); const theme = useThemeStore();
const { routerPush } = useRouterPush(); const { routerPush } = useRouterPush();
const menus = computed(() => routeStore.menus as App.GlobalMenuOption[]); const menus = computed(() => translateMenuLabel(routeStore.menus as App.GlobalMenuOption[]));
const activeKey = computed(() => (route.meta?.activeMenu ? route.meta.activeMenu : route.name) as string); const activeKey = computed(() => (route.meta?.activeMenu ? route.meta.activeMenu : route.name) as string);
function handleUpdateMenu(_key: string, item: MenuOption) { function handleUpdateMenu(_key: string, item: MenuOption) {

View File

@@ -7,6 +7,7 @@ import ThemeMode from './theme-mode.vue';
import UserAvatar from './user-avatar.vue'; import UserAvatar from './user-avatar.vue';
import SystemMessage from './system-message.vue'; import SystemMessage from './system-message.vue';
import SettingButton from './setting-button.vue'; import SettingButton from './setting-button.vue';
import ToggleLang from './toggle-lang.vue';
export { export {
MenuCollapse, MenuCollapse,
@@ -17,5 +18,6 @@ export {
ThemeMode, ThemeMode,
UserAvatar, UserAvatar,
SystemMessage, SystemMessage,
SettingButton SettingButton,
ToggleLang
}; };

View File

@@ -4,7 +4,7 @@
<n-list-item <n-list-item
v-for="(item, index) in list" v-for="(item, index) in list"
:key="item.id" :key="item.id"
class="hover:bg-[#f6f6f6] dark:hover:bg-dark cursor-pointer" class="hover:bg-#f6f6f6 dark:hover:bg-dark cursor-pointer"
@click="handleRead(index)" @click="handleRead(index)"
> >
<n-thing class="px-15px" :class="{ 'opacity-30': item.isRead }"> <n-thing class="px-15px" :class="{ 'opacity-30': item.isRead }">

View File

@@ -1,6 +1,11 @@
<template> <template>
<hover-container class="w-40px" :inverted="theme.header.inverted" tooltip-content="主题模式"> <hover-container class="w-40px" :inverted="theme.header.inverted" tooltip-content="主题模式">
<dark-mode-switch :dark="theme.darkMode" class="wh-full" @update:dark="theme.setDarkMode" /> <dark-mode-switch
:dark="theme.darkMode"
:customize-transition="theme.isCustomizeDarkModeTransition"
class="wh-full"
@update:dark="theme.setDarkMode"
/>
</hover-container> </hover-container>
</template> </template>

View File

@@ -0,0 +1,39 @@
<template>
<hover-container class="w-40px h-full" :inverted="theme.header.inverted">
<n-dropdown :options="options" trigger="hover" :value="language" @select="handleSelect">
<icon-cil:language class="text-18px outline-transparent" />
</n-dropdown>
</hover-container>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { useI18n } from 'vue-i18n';
import { useThemeStore } from '@/store';
import { localStg } from '@/utils';
const theme = useThemeStore();
const { locale } = useI18n();
const language = ref<I18nType.LangType>(localStg.get('lang') || 'zh-CN');
const options = [
{
label: '中文',
key: 'zh-CN'
},
{
label: 'English',
key: 'en'
},
{
label: 'ភាសាខ្មែរ',
key: 'km-KH'
}
];
const handleSelect = (key: string) => {
language.value = key as I18nType.LangType;
locale.value = key;
localStg.set('lang', key as I18nType.LangType);
};
</script>
<style scoped></style>

View File

@@ -11,6 +11,7 @@
<github-site /> <github-site />
<full-screen /> <full-screen />
<theme-mode /> <theme-mode />
<toggle-lang />
<system-message /> <system-message />
<setting-button v-if="showButton" /> <setting-button v-if="showButton" />
<user-avatar /> <user-avatar />
@@ -32,7 +33,8 @@ import {
SettingButton, SettingButton,
SystemMessage, SystemMessage,
ThemeMode, ThemeMode,
UserAvatar UserAvatar,
ToggleLang
} from './components'; } from './components';
defineOptions({ name: 'GlobalHeader' }); defineOptions({ name: 'GlobalHeader' });

View File

@@ -1,19 +1,15 @@
<template> <template>
<router-link :to="routeHomePath" class="flex-center w-full nowrap-hidden"> <router-link :to="routeHomePath" class="flex-center w-full nowrap-hidden">
<system-logo class="text-32px text-primary" /> <system-logo class="text-32px text-primary" />
<h2 <h2 v-show="showTitle" class="pl-8px text-16px font-bold text-primary transition duration-300 ease-in-out">
v-show="showTitle" {{ $t('system.title') }}
class="pl-8px text-16px font-bold text-primary transition duration-300 ease-in-out"
@click="toggleLocal"
>
{{ t('message.system.title') }}
</h2> </h2>
</router-link> </router-link>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { routePath } from '@/router'; import { routePath } from '@/router';
import { t, setLocale } from '@/locales'; import { $t } from '@/locales';
defineOptions({ name: 'GlobalLogo' }); defineOptions({ name: 'GlobalLogo' });
@@ -25,12 +21,6 @@ interface Props {
defineProps<Props>(); defineProps<Props>();
const routeHomePath = routePath('root'); const routeHomePath = routePath('root');
let flag = true;
function toggleLocal() {
flag = !flag;
setLocale(flag ? 'en' : 'zh-CN');
}
</script> </script>
<style scoped></style> <style scoped></style>

View File

@@ -22,6 +22,9 @@ defineOptions({ name: 'SearchFooter' });
<style lang="scss" scoped> <style lang="scss" scoped>
.icon { .icon {
box-shadow: inset 0 -2px #cdcde6, inset 0 0 1px 1px #fff, 0 1px 2px 1px #1e235a66; box-shadow:
inset 0 -2px #cdcde6,
inset 0 0 1px 1px #fff,
0 1px 2px 1px #1e235a66;
} }
</style> </style>

View File

@@ -12,7 +12,7 @@
<n-input-group> <n-input-group>
<n-input ref="inputRef" v-model:value="keyword" clearable placeholder="请输入关键词搜索" @input="handleSearch"> <n-input ref="inputRef" v-model:value="keyword" clearable placeholder="请输入关键词搜索" @input="handleSearch">
<template #prefix> <template #prefix>
<icon-uil-search class="text-15px text-[#c2c2c2]" /> <icon-uil-search class="text-15px text-#c2c2c2" />
</template> </template>
</n-input> </n-input>
<n-button v-if="isMobile" type="primary" ghost @click="handleClose">取消</n-button> <n-button v-if="isMobile" type="primary" ghost @click="handleClose">取消</n-button>

View File

@@ -3,7 +3,7 @@
<div class="pb-12px"> <div class="pb-12px">
<template v-for="item in options" :key="item.path"> <template v-for="item in options" :key="item.path">
<div <div
class="bg-[#e5e7eb] dark:bg-dark h-56px mt-8px px-14px rounded-4px cursor-pointer flex-y-center justify-between" class="bg-#e5e7eb dark:bg-dark h-56px mt-8px px-14px rounded-4px cursor-pointer flex-y-center justify-between"
:style="{ :style="{
background: item.path === active ? theme.themeColor : '', background: item.path === active ? theme.themeColor : '',
color: item.path === active ? '#fff' : '' color: item.path === active ? '#fff' : ''

View File

@@ -6,7 +6,7 @@
> >
<component :is="icon" :class="[isMini ? 'text-16px' : 'text-20px']" /> <component :is="icon" :class="[isMini ? 'text-16px' : 'text-20px']" />
<p <p
class="text-12px overflow-hidden transition-height duration-300 ease-in-out" class="w-full text-center ellipsis-text text-12px transition-height duration-300 ease-in-out"
:class="[isMini ? 'h-0 pt-0' : 'h-24px pt-4px']" :class="[isMini ? 'h-0 pt-0' : 'h-24px pt-4px']"
> >
{{ label }} {{ label }}
@@ -17,7 +17,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue'; import { computed } from 'vue';
import type { VNodeChild } from 'vue'; import type { Component } from 'vue';
import { useBoolean } from '@/hooks'; import { useBoolean } from '@/hooks';
defineOptions({ name: 'MixMenuDetail' }); defineOptions({ name: 'MixMenuDetail' });
@@ -30,7 +30,7 @@ interface Props {
/** 当前激活状态的理由名称 */ /** 当前激活状态的理由名称 */
activeRouteName: string; activeRouteName: string;
/** 路由图标 */ /** 路由图标 */
icon?: () => VNodeChild; icon?: Component;
/** mini尺寸的路由 */ /** mini尺寸的路由 */
isMini?: boolean; isMini?: boolean;
} }

View File

@@ -5,10 +5,11 @@
> >
<dark-mode-container <dark-mode-container
class="drawer-shadow absolute-lt flex-col-stretch h-full nowrap-hidden" class="drawer-shadow absolute-lt flex-col-stretch h-full nowrap-hidden"
:inverted="theme.sider.inverted"
:style="{ width: showDrawer ? theme.sider.mixChildMenuWidth + 'px' : '0px' }" :style="{ width: showDrawer ? theme.sider.mixChildMenuWidth + 'px' : '0px' }"
> >
<header class="header-height flex-y-center justify-between" :style="{ height: theme.header.height + 'px' }"> <header class="header-height flex-y-center justify-between" :style="{ height: theme.header.height + 'px' }">
<h2 class="text-primary pl-8px text-16px font-bold">{{ title }}</h2> <h2 class="text-primary pl-8px text-16px font-bold">{{ $t('system.title') }}</h2>
<div class="px-8px text-16px text-gray-600 cursor-pointer" @click="app.toggleMixSiderFixed"> <div class="px-8px text-16px text-gray-600 cursor-pointer" @click="app.toggleMixSiderFixed">
<icon-mdi-pin-off v-if="app.mixSiderFixed" /> <icon-mdi-pin-off v-if="app.mixSiderFixed" />
<icon-mdi-pin v-else /> <icon-mdi-pin v-else />
@@ -20,6 +21,7 @@
:options="menus" :options="menus"
:expanded-keys="expandedKeys" :expanded-keys="expandedKeys"
:indent="18" :indent="18"
:inverted="!theme.darkMode && theme.sider.inverted"
@update:value="handleUpdateMenu" @update:value="handleUpdateMenu"
@update:expanded-keys="handleUpdateExpandedKeys" @update:expanded-keys="handleUpdateExpandedKeys"
/> />
@@ -33,8 +35,9 @@ import { computed, ref, watch } from 'vue';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import type { MenuOption } from 'naive-ui'; import type { MenuOption } from 'naive-ui';
import { useAppStore, useThemeStore } from '@/store'; import { useAppStore, useThemeStore } from '@/store';
import { useAppInfo, useRouterPush } from '@/composables'; import { useRouterPush } from '@/composables';
import { getActiveKeyPathsOfMenus } from '@/utils'; import { getActiveKeyPathsOfMenus } from '@/utils';
import { $t } from '@/locales';
defineOptions({ name: 'MixMenuDrawer' }); defineOptions({ name: 'MixMenuDrawer' });
@@ -51,7 +54,6 @@ const route = useRoute();
const app = useAppStore(); const app = useAppStore();
const theme = useThemeStore(); const theme = useThemeStore();
const { routerPush } = useRouterPush(); const { routerPush } = useRouterPush();
const { title } = useAppInfo();
const showDrawer = computed(() => (props.visible && props.menus.length) || app.mixSiderFixed); const showDrawer = computed(() => (props.visible && props.menus.length) || app.mixSiderFixed);

View File

@@ -1,6 +1,6 @@
<template> <template>
<dark-mode-container class="flex h-full" :inverted="theme.sider.inverted" @mouseleave="resetFirstDegreeMenus"> <dark-mode-container class="flex h-full" :inverted="theme.sider.inverted" @mouseleave="resetFirstDegreeMenus">
<div class="flex-1 flex-col-stretch h-full"> <div class="flex-1-hidden flex-col-stretch h-full">
<global-logo :show-title="false" :style="{ height: theme.header.height + 'px' }" /> <global-logo :show-title="false" :style="{ height: theme.header.height + 'px' }" />
<n-scrollbar class="flex-1-hidden"> <n-scrollbar class="flex-1-hidden">
<mix-menu-detail <mix-menu-detail
@@ -26,7 +26,9 @@ import { useRoute } from 'vue-router';
import { useAppStore, useRouteStore, useThemeStore } from '@/store'; import { useAppStore, useRouteStore, useThemeStore } from '@/store';
import { useRouterPush } from '@/composables'; import { useRouterPush } from '@/composables';
import { useBoolean } from '@/hooks'; import { useBoolean } from '@/hooks';
import { translateMenuLabel } from '@/utils';
import { GlobalLogo } from '@/layouts/common'; import { GlobalLogo } from '@/layouts/common';
import { $t } from '@/locales';
import { MixMenuCollapse, MixMenuDetail, MixMenuDrawer } from './components'; import { MixMenuCollapse, MixMenuDetail, MixMenuDrawer } from './components';
defineOptions({ name: 'VerticalMixSider' }); defineOptions({ name: 'VerticalMixSider' });
@@ -45,13 +47,13 @@ function setActiveParentRouteName(routeName: string) {
const firstDegreeMenus = computed(() => const firstDegreeMenus = computed(() =>
routeStore.menus.map(item => { routeStore.menus.map(item => {
const { routeName, label } = item; const { routeName, label, i18nTitle } = item;
const icon = item?.icon; const icon = item?.icon;
const hasChildren = Boolean(item.children && item.children.length); const hasChildren = Boolean(item.children && item.children.length);
return { return {
routeName, routeName,
label, label: i18nTitle ? $t(i18nTitle) : label,
icon, icon,
hasChildren hasChildren
}; };
@@ -88,7 +90,7 @@ const activeChildMenus = computed(() => {
routeStore.menus.some(item => { routeStore.menus.some(item => {
const flag = item.routeName === activeParentRouteName.value && Boolean(item.children?.length); const flag = item.routeName === activeParentRouteName.value && Boolean(item.children?.length);
if (flag) { if (flag) {
menus.push(...(item.children || [])); menus.push(...translateMenuLabel((item.children || []) as App.GlobalMenuOption[]));
} }
return flag; return flag;
}); });

View File

@@ -8,7 +8,7 @@
:options="menus" :options="menus"
:expanded-keys="expandedKeys" :expanded-keys="expandedKeys"
:indent="18" :indent="18"
:inverted="theme.sider.inverted" :inverted="!theme.darkMode && theme.sider.inverted"
@update:value="handleUpdateMenu" @update:value="handleUpdateMenu"
@update:expanded-keys="handleUpdateExpandedKeys" @update:expanded-keys="handleUpdateExpandedKeys"
/> />
@@ -21,7 +21,7 @@ import { useRoute } from 'vue-router';
import type { MenuOption } from 'naive-ui'; import type { MenuOption } from 'naive-ui';
import { useAppStore, useRouteStore, useThemeStore } from '@/store'; import { useAppStore, useRouteStore, useThemeStore } from '@/store';
import { useRouterPush } from '@/composables'; import { useRouterPush } from '@/composables';
import { getActiveKeyPathsOfMenus } from '@/utils'; import { getActiveKeyPathsOfMenus, translateMenuLabel } from '@/utils';
defineOptions({ name: 'VerticalMenu' }); defineOptions({ name: 'VerticalMenu' });
@@ -31,7 +31,7 @@ const theme = useThemeStore();
const routeStore = useRouteStore(); const routeStore = useRouteStore();
const { routerPush } = useRouterPush(); const { routerPush } = useRouterPush();
const menus = computed(() => routeStore.menus as App.GlobalMenuOption[]); const menus = computed(() => translateMenuLabel(routeStore.menus as App.GlobalMenuOption[]));
const activeKey = computed(() => (route.meta?.activeMenu ? route.meta.activeMenu : route.name) as string); const activeKey = computed(() => (route.meta?.activeMenu ? route.meta.activeMenu : route.name) as string);
const expandedKeys = ref<string[]>([]); const expandedKeys = ref<string[]>([]);

View File

@@ -6,26 +6,21 @@
<script setup lang="ts"> <script setup lang="ts">
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { useAppStore, useRouteStore } from '@/store'; import { useRouteStore } from '@/store';
import { useLoading } from '@/hooks'; import { useLoading } from '@/hooks';
defineOptions({ name: 'ReloadButton' }); defineOptions({ name: 'ReloadButton' });
const app = useAppStore(); const { reCacheRoute } = useRouteStore();
const routeStore = useRouteStore();
const route = useRoute(); const route = useRoute();
const { loading, startLoading, endLoading } = useLoading(); const { loading, startLoading, endLoading } = useLoading();
function handleRefresh() { async function handleRefresh() {
const isCached = routeStore.cacheRoutes.includes(String(route.name));
if (isCached) {
routeStore.removeCacheRoute(route.name as AuthRoute.AllRouteKey);
}
startLoading(); startLoading();
app.reloadPage();
await reCacheRoute(route.name as AuthRoute.AllRouteKey);
setTimeout(() => { setTimeout(() => {
if (isCached) {
routeStore.addCacheRoute(route.name as AuthRoute.AllRouteKey);
}
endLoading(); endLoading();
}, 1000); }, 1000);
} }

View File

@@ -1,6 +1,6 @@
<template> <template>
<div ref="tabRef" class="flex h-full pr-18px" :class="[isChromeMode ? 'items-end' : 'items-center gap-12px']"> <div ref="tabRef" class="flex h-full pr-18px" :class="[isChromeMode ? 'items-end' : 'items-center gap-12px']">
<AdminTab <PageTab
v-for="item in tab.tabs" v-for="item in tab.tabs"
:key="item.fullPath" :key="item.fullPath"
:mode="theme.tab.mode" :mode="theme.tab.mode"
@@ -19,8 +19,8 @@
class="inline-block align-text-bottom text-16px" class="inline-block align-text-bottom text-16px"
/> />
</template> </template>
{{ item.meta.title }} {{ item.meta.i18nTitle ? $t(item.meta.i18nTitle) : item.meta.title }}
</AdminTab> </PageTab>
</div> </div>
<context-menu <context-menu
:visible="dropdown.visible" :visible="dropdown.visible"
@@ -34,8 +34,9 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, nextTick, reactive, ref, watch } from 'vue'; import { computed, nextTick, reactive, ref, watch } from 'vue';
import { AdminTab } from '@soybeanjs/vue-materials'; import { PageTab } from '@soybeanjs/vue-materials';
import { useTabStore, useThemeStore } from '@/store'; import { useTabStore, useThemeStore } from '@/store';
import { $t } from '@/locales';
import { ContextMenu } from './components'; import { ContextMenu } from './components';
defineOptions({ name: 'TabDetail' }); defineOptions({ name: 'TabDetail' });

View File

@@ -5,6 +5,5 @@ import GlobalSider from './global-sider/index.vue';
import GlobalContent from './global-content/index.vue'; import GlobalContent from './global-content/index.vue';
import GlobalFooter from './global-footer/index.vue'; import GlobalFooter from './global-footer/index.vue';
import GlobalLogo from './global-logo/index.vue'; import GlobalLogo from './global-logo/index.vue';
import GlobalBackTop from './global-back-top/index.vue';
export { SettingDrawer, GlobalHeader, GlobalTab, GlobalSider, GlobalContent, GlobalFooter, GlobalLogo, GlobalBackTop }; export { SettingDrawer, GlobalHeader, GlobalTab, GlobalSider, GlobalContent, GlobalFooter, GlobalLogo };

View File

@@ -1,7 +1,7 @@
<template> <template>
<n-divider title-placement="center">主题模式</n-divider> <n-divider title-placement="center">{{ $t('layout.settingDrawer.themeModeTitle') }}</n-divider>
<n-space vertical size="large"> <n-space vertical size="large">
<setting-menu label="深色主题"> <setting-menu :label="$t('layout.settingDrawer.darkMode')">
<n-switch :value="theme.darkMode" @update:value="theme.setDarkMode"> <n-switch :value="theme.darkMode" @update:value="theme.setDarkMode">
<template #checked> <template #checked>
<icon-mdi-white-balance-sunny class="text-14px text-white" /> <icon-mdi-white-balance-sunny class="text-14px text-white" />
@@ -11,7 +11,7 @@
</template> </template>
</n-switch> </n-switch>
</setting-menu> </setting-menu>
<setting-menu label="跟随系统"> <setting-menu :label="$t('layout.settingDrawer.followSystemTheme')">
<n-switch :value="theme.followSystemTheme" @update:value="theme.setFollowSystemTheme"> <n-switch :value="theme.followSystemTheme" @update:value="theme.setFollowSystemTheme">
<template #checked> <template #checked>
<icon-ic-baseline-do-not-disturb class="text-14px text-white" /> <icon-ic-baseline-do-not-disturb class="text-14px text-white" />
@@ -21,17 +21,31 @@
</template> </template>
</n-switch> </n-switch>
</setting-menu> </setting-menu>
<setting-menu label="侧边栏深色主题"> <setting-menu :label="$t('layout.settingDrawer.isCustomizeDarkModeTransition')">
<n-switch :value="theme.isCustomizeDarkModeTransition" @update:value="theme.setIsCustomizeDarkModeTransition">
<template #checked>
<icon-ic-baseline-do-not-disturb class="text-14px text-white" />
</template>
<template #unchecked>
<icon-ic-round-hdr-auto class="text-14px text-white" />
</template>
</n-switch>
</setting-menu>
<setting-menu :label="$t('layout.settingDrawer.sider.inverted')">
<n-switch :value="theme.sider.inverted" @update:value="theme.setSiderInverted" /> <n-switch :value="theme.sider.inverted" @update:value="theme.setSiderInverted" />
</setting-menu> </setting-menu>
<setting-menu label="头部深色主题"> <setting-menu :label="$t('layout.settingDrawer.header.inverted')">
<n-switch :value="theme.header.inverted" @update:value="theme.setHeaderInverted" /> <n-switch :value="theme.header.inverted" @update:value="theme.setHeaderInverted" />
</setting-menu> </setting-menu>
<setting-menu :label="$t('layout.settingDrawer.footer.inverted')">
<n-switch :value="theme.footer.inverted" @update:value="theme.setFooterInverted" />
</setting-menu>
</n-space> </n-space>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { useThemeStore } from '@/store'; import { useThemeStore } from '@/store';
import { $t } from '@/locales';
import SettingMenu from '../setting-menu/index.vue'; import SettingMenu from '../setting-menu/index.vue';
defineOptions({ name: 'DarkMode' }); defineOptions({ name: 'DarkMode' });

View File

@@ -6,8 +6,8 @@
<n-tooltip :placement="activeConfig.placement" trigger="hover"> <n-tooltip :placement="activeConfig.placement" trigger="hover">
<template #trigger> <template #trigger>
<div class="layout-checkbox__shadow relative w-56px h-48px bg-white rounded-4px overflow-hidden"> <div class="layout-checkbox__shadow relative w-56px h-48px bg-white rounded-4px overflow-hidden">
<div class="absolute-lt bg-[#273352]" :class="activeConfig.menuClass"></div> <div class="absolute-lt bg-#273352" :class="activeConfig.menuClass"></div>
<div class="absolute-rb bg-[#f0f2f5]" :class="activeConfig.mainClass"></div> <div class="absolute-rb bg-#f0f2f5" :class="activeConfig.mainClass"></div>
</div> </div>
</template> </template>
<span>{{ label }}</span> <span>{{ label }}</span>

View File

@@ -1,5 +1,5 @@
<template> <template>
<n-divider title-placement="center">布局模式</n-divider> <n-divider title-placement="center">{{ $t('layout.settingDrawer.layoutModelTitle') }}</n-divider>
<n-space justify="space-around" :wrap="true" :size="24" class="px-12px"> <n-space justify="space-around" :wrap="true" :size="24" class="px-12px">
<layout-card <layout-card
v-for="item in theme.layout.modeList" v-for="item in theme.layout.modeList"
@@ -43,6 +43,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { useThemeStore } from '@/store'; import { useThemeStore } from '@/store';
import { $t } from '@/locales';
import { LayoutCard } from './components'; import { LayoutCard } from './components';
defineOptions({ name: 'LayoutMode' }); defineOptions({ name: 'LayoutMode' });

View File

@@ -1,7 +1,7 @@
<template> <template>
<n-divider title-placement="center">界面功能</n-divider> <n-divider title-placement="center">{{ $t('layout.settingDrawer.pageFunctionsTitle') }}</n-divider>
<n-space vertical size="large"> <n-space vertical size="large">
<setting-menu label="滚动模式"> <setting-menu :label="$t('layout.settingDrawer.scrollMode')">
<n-select <n-select
class="w-120px" class="w-120px"
size="small" size="small"
@@ -10,10 +10,10 @@
@update:value="theme.setScrollMode" @update:value="theme.setScrollMode"
/> />
</setting-menu> </setting-menu>
<setting-menu label="固定头部和多页签"> <setting-menu :label="$t('layout.settingDrawer.fixedHeaderAndTab')">
<n-switch :value="theme.fixedHeaderAndTab" @update:value="theme.setIsFixedHeaderAndTab" /> <n-switch :value="theme.fixedHeaderAndTab" @update:value="theme.setIsFixedHeaderAndTab" />
</setting-menu> </setting-menu>
<setting-menu label="顶部菜单位置"> <setting-menu :label="$t('layout.settingDrawer.menu.horizontalPosition')">
<n-select <n-select
class="w-120px" class="w-120px"
size="small" size="small"
@@ -22,7 +22,7 @@
@update:value="theme.setHorizontalMenuPosition" @update:value="theme.setHorizontalMenuPosition"
/> />
</setting-menu> </setting-menu>
<setting-menu label="头部高度"> <setting-menu :label="$t('layout.settingDrawer.header.height')">
<n-input-number <n-input-number
class="w-120px" class="w-120px"
size="small" size="small"
@@ -31,7 +31,7 @@
@update:value="theme.setHeaderHeight" @update:value="theme.setHeaderHeight"
/> />
</setting-menu> </setting-menu>
<setting-menu label="多页签高度"> <setting-menu :label="$t('layout.settingDrawer.tab.height')">
<n-input-number <n-input-number
class="w-120px" class="w-120px"
size="small" size="small"
@@ -40,10 +40,10 @@
@update:value="theme.setTabHeight" @update:value="theme.setTabHeight"
/> />
</setting-menu> </setting-menu>
<setting-menu label="多页签缓存"> <setting-menu :label="$t('layout.settingDrawer.tab.isCache')">
<n-switch :value="theme.tab.isCache" @update:value="theme.setTabIsCache" /> <n-switch :value="theme.tab.isCache" @update:value="theme.setTabIsCache" />
</setting-menu> </setting-menu>
<setting-menu label="侧边栏展开宽度"> <setting-menu :label="$t('layout.settingDrawer.sider.width')">
<n-input-number <n-input-number
class="w-120px" class="w-120px"
size="small" size="small"
@@ -52,7 +52,7 @@
@update:value="theme.setSiderWidth" @update:value="theme.setSiderWidth"
/> />
</setting-menu> </setting-menu>
<setting-menu label="左侧混合侧边栏展开宽度"> <setting-menu :label="$t('layout.settingDrawer.sider.mixWidth')">
<n-input-number <n-input-number
class="w-120px" class="w-120px"
size="small" size="small"
@@ -61,17 +61,21 @@
@update:value="theme.setMixSiderWidth" @update:value="theme.setMixSiderWidth"
/> />
</setting-menu> </setting-menu>
<setting-menu label="固定底部"> <setting-menu :label="$t('layout.settingDrawer.footer.visible')">
<n-switch :value="theme.footer.visible" @update:value="theme.setFooterVisible" />
</setting-menu>
<setting-menu :label="$t('layout.settingDrawer.footer.fixed')">
<n-switch :value="theme.footer.fixed" @update:value="theme.setFooterIsFixed" /> <n-switch :value="theme.footer.fixed" @update:value="theme.setFooterIsFixed" />
</setting-menu> </setting-menu>
<setting-menu label="显示底部"> <setting-menu :label="$t('layout.settingDrawer.footer.right')">
<n-switch :value="theme.footer.visible" @update:value="theme.setFooterVisible" /> <n-switch :value="theme.footer.right" @update:value="theme.setFooterIsRight" />
</setting-menu> </setting-menu>
</n-space> </n-space>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { useThemeStore } from '@/store'; import { useThemeStore } from '@/store';
import { $t } from '@/locales';
import SettingMenu from '../setting-menu/index.vue'; import SettingMenu from '../setting-menu/index.vue';
defineOptions({ name: 'PageFunc' }); defineOptions({ name: 'PageFunc' });

View File

@@ -1,16 +1,16 @@
<template> <template>
<n-divider title-placement="center">界面显示</n-divider> <n-divider title-placement="center">{{ $t('layout.settingDrawer.pageViewTitle') }}</n-divider>
<n-space vertical size="large"> <n-space vertical size="large">
<setting-menu label="面包屑"> <setting-menu :label="$t('layout.settingDrawer.header.crumb.visible')">
<n-switch :value="theme.header.crumb.visible" @update:value="theme.setHeaderCrumbVisible" /> <n-switch :value="theme.header.crumb.visible" @update:value="theme.setHeaderCrumbVisible" />
</setting-menu> </setting-menu>
<setting-menu label="面包屑图标"> <setting-menu :label="$t('layout.settingDrawer.header.crumb.icon')">
<n-switch :value="theme.header.crumb.showIcon" @update:value="theme.setHeaderCrumbIconVisible" /> <n-switch :value="theme.header.crumb.showIcon" @update:value="theme.setHeaderCrumbIconVisible" />
</setting-menu> </setting-menu>
<setting-menu label="多页签"> <setting-menu :label="$t('layout.settingDrawer.tab.visible')">
<n-switch :value="theme.tab.visible" @update:value="theme.setTabVisible" /> <n-switch :value="theme.tab.visible" @update:value="theme.setTabVisible" />
</setting-menu> </setting-menu>
<setting-menu label="多页签风格"> <setting-menu :label="$t('layout.settingDrawer.tab.modeList.mode')">
<n-select <n-select
class="w-120px" class="w-120px"
size="small" size="small"
@@ -19,10 +19,10 @@
@update:value="theme.setTabMode" @update:value="theme.setTabMode"
/> />
</setting-menu> </setting-menu>
<setting-menu label="页面切换动画"> <setting-menu :label="$t('layout.settingDrawer.page.animate')">
<n-switch :value="theme.page.animate" @update:value="theme.setPageIsAnimate" /> <n-switch :value="theme.page.animate" @update:value="theme.setPageIsAnimate" />
</setting-menu> </setting-menu>
<setting-menu label="页面切换动画类型"> <setting-menu :label="$t('layout.settingDrawer.page.animateMode')">
<n-select <n-select
class="w-120px" class="w-120px"
size="small" size="small"
@@ -36,6 +36,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import { useThemeStore } from '@/store'; import { useThemeStore } from '@/store';
import { $t } from '@/locales';
import SettingMenu from '../setting-menu/index.vue'; import SettingMenu from '../setting-menu/index.vue';
defineOptions({ name: 'PageView' }); defineOptions({ name: 'PageView' });

View File

@@ -1,5 +1,5 @@
<template> <template>
<n-divider title-placement="center">系统主题</n-divider> <n-divider title-placement="center">{{ $t('layout.settingDrawer.systemThemeTitle') }}</n-divider>
<n-grid :cols="8" :x-gap="8" :y-gap="12"> <n-grid :cols="8" :x-gap="8" :y-gap="12">
<n-grid-item v-for="color in theme.themeColorList" :key="color" class="flex-x-center"> <n-grid-item v-for="color in theme.themeColorList" :key="color" class="flex-x-center">
<color-checkbox :color="color" :checked="color === theme.themeColor" @click="theme.setThemeColor(color)" /> <color-checkbox :color="color" :checked="color === theme.themeColor" @click="theme.setThemeColor(color)" />
@@ -7,7 +7,9 @@
</n-grid> </n-grid>
<n-space :vertical="true" class="pt-12px"> <n-space :vertical="true" class="pt-12px">
<n-color-picker :value="theme.themeColor" :show-alpha="false" @update-value="theme.setThemeColor" /> <n-color-picker :value="theme.themeColor" :show-alpha="false" @update-value="theme.setThemeColor" />
<n-button :block="true" :type="otherColorBtnType" @click="openModal">更多颜色</n-button> <n-button :block="true" :type="otherColorBtnType" @click="openModal">
{{ $t('layout.settingDrawer.systemTheme.moreColors') }}
</n-button>
</n-space> </n-space>
<color-modal :visible="visible" @close="closeModal" /> <color-modal :visible="visible" @close="closeModal" />
</template> </template>
@@ -17,6 +19,7 @@ import { computed } from 'vue';
import { isInTraditionColors } from '@/settings'; import { isInTraditionColors } from '@/settings';
import { useThemeStore } from '@/store'; import { useThemeStore } from '@/store';
import { useBoolean } from '@/hooks'; import { useBoolean } from '@/hooks';
import { $t } from '@/locales';
import { ColorCheckbox, ColorModal } from './components'; import { ColorCheckbox, ColorModal } from './components';
defineOptions({ name: 'ThemeColorSelect' }); defineOptions({ name: 'ThemeColorSelect' });

View File

@@ -1,11 +1,13 @@
<template> <template>
<n-divider title-placement="center">主题配置</n-divider> <n-divider title-placement="center">{{ $t('layout.settingDrawer.themeConfiguration.title') }}</n-divider>
<textarea id="themeConfigCopyTarget" v-model="dataClipboardText" class="absolute opacity-0" /> <textarea id="themeConfigCopyTarget" v-model="dataClipboardText" class="absolute opacity-0" />
<n-space vertical> <n-space vertical>
<div ref="copyRef" data-clipboard-target="#themeConfigCopyTarget"> <div ref="copyRef" data-clipboard-target="#themeConfigCopyTarget">
<n-button type="primary" :block="true">拷贝当前配置</n-button> <n-button type="primary" :block="true">{{ $t('layout.settingDrawer.themeConfiguration.copy') }}</n-button>
</div> </div>
<n-button type="warning" :block="true" @click="handleResetConfig">重置当前配置</n-button> <n-button type="warning" :block="true" @click="handleResetConfig">
{{ $t('layout.settingDrawer.themeConfiguration.reset') }}
</n-button>
</n-space> </n-space>
</template> </template>
@@ -13,6 +15,7 @@
import { onMounted, onUnmounted, ref, watch } from 'vue'; import { onMounted, onUnmounted, ref, watch } from 'vue';
import Clipboard from 'clipboard'; import Clipboard from 'clipboard';
import { useThemeStore } from '@/store'; import { useThemeStore } from '@/store';
import { $t } from '@/locales';
defineOptions({ name: 'ThemeConfig' }); defineOptions({ name: 'ThemeConfig' });
@@ -28,7 +31,7 @@ function getClipboardText() {
function handleResetConfig() { function handleResetConfig() {
theme.resetThemeStore(); theme.resetThemeStore();
window.$message?.success('已重置配置,请重新拷贝!'); window.$message?.success($t('layout.settingDrawer.themeConfiguration.resetSuccess'));
} }
function clipboardEventListener() { function clipboardEventListener() {
@@ -36,9 +39,9 @@ function clipboardEventListener() {
const copy = new Clipboard(copyRef.value); const copy = new Clipboard(copyRef.value);
copy.on('success', () => { copy.on('success', () => {
window.$dialog?.success({ window.$dialog?.success({
title: '操作成功', title: $t('layout.settingDrawer.themeConfiguration.operateSuccess'),
content: '复制成功,请替换 src/settings/theme.json的内容', content: $t('layout.settingDrawer.themeConfiguration.copySuccess'),
positiveText: '确定' positiveText: $t('layout.settingDrawer.themeConfiguration.confirmCopy')
}); });
}); });
} }

View File

@@ -1,6 +1,6 @@
<template> <template>
<n-drawer :show="app.settingDrawerVisible" display-directive="show" :width="330" @mask-click="app.closeSettingDrawer"> <n-drawer :show="app.settingDrawerVisible" display-directive="show" :width="330" @mask-click="app.closeSettingDrawer">
<n-drawer-content title="主题配置" :native-scrollbar="false"> <n-drawer-content :title="$t('layout.settingDrawer.title')" :native-scrollbar="false">
<dark-mode /> <dark-mode />
<layout-mode /> <layout-mode />
<theme-color-select /> <theme-color-select />
@@ -14,6 +14,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { useAppStore } from '@/store'; import { useAppStore } from '@/store';
import { $t } from '@/locales';
import { DarkMode, DrawerButton, LayoutMode, PageFunc, PageView, ThemeColorSelect, ThemeConfig } from './components'; import { DarkMode, DrawerButton, LayoutMode, PageFunc, PageView, ThemeColorSelect, ThemeConfig } from './components';
defineOptions({ name: 'SettingDrawer' }); defineOptions({ name: 'SettingDrawer' });

View File

@@ -1,22 +1,34 @@
import type { App } from 'vue'; import type { App } from 'vue';
import { createI18n } from 'vue-i18n'; import { createI18n } from 'vue-i18n';
import messages from './lang'; import type { TranslateOptions } from 'vue-i18n';
import type { LocaleKey } from './lang'; import { localStg } from '@/utils/storage';
import messages from './locale';
const i18n = createI18n({ const i18n = createI18n({
locale: 'zh-CN', locale: localStg.get('lang') || 'zh-CN',
fallbackLocale: 'en', fallbackLocale: 'en',
messages messages,
legacy: false
}); });
export function setupI18n(app: App) { export function setupI18n(app: App) {
app.use(i18n); app.use(i18n);
} }
export function t(key: string) { interface T {
return i18n.global.t(key); (key: I18nType.I18nKey): string;
(key: I18nType.I18nKey, plural: number, options?: TranslateOptions<I18nType.LangType>): string;
(key: I18nType.I18nKey, defaultMsg: string, options?: TranslateOptions<I18nType.I18nKey>): string;
(key: I18nType.I18nKey, list: unknown[], options?: TranslateOptions<I18nType.I18nKey>): string;
(key: I18nType.I18nKey, list: unknown[], plural: number): string;
(key: I18nType.I18nKey, list: unknown[], defaultMsg: string): string;
(key: I18nType.I18nKey, named: Record<string, unknown>, options?: TranslateOptions<I18nType.LangType>): string;
(key: I18nType.I18nKey, named: Record<string, unknown>, plural: number): string;
(key: I18nType.I18nKey, named: Record<string, unknown>, defaultMsg: string): string;
} }
export function setLocale(locale: LocaleKey) { export const $t = i18n.global.t as T;
i18n.global.locale = locale;
export function setLocale(locale: I18nType.LangType) {
i18n.global.locale.value = locale;
} }

View File

@@ -1,18 +1,216 @@
import type { LocaleMessages } from 'vue-i18n'; const locale: I18nType.Schema = {
system: {
const locale: LocaleMessages<I18nType.Schema> = { title: 'SoybeanAdmin'
message: { },
system: { common: {
title: 'SoybeanAdmin' add: 'Add',
addSuccess: 'Add Success',
edit: 'Edit',
editSuccess: 'Edit Success',
delete: 'Delete',
deleteSuccess: 'Delete Success',
batchDelete: 'Batch Delete',
confirm: 'Confirm',
cancel: 'Cancel',
pleaseCheckValue: 'Please check the value is valid',
action: 'Action'
},
routes: {
dashboard: {
_value: 'Dashboard',
analysis: 'Analysis',
workbench: 'Workbench'
}, },
routes: { document: {
dashboard: { _value: 'Document',
dashboard: 'Dashboard', vue: 'Vue Document',
analysis: 'Analysis', vite: 'Vite Document',
workbench: 'Workbench' naive: 'NaiveUI Document',
project: 'Project Document',
'project-link': 'Project Document(href)'
},
component: {
_value: 'Component',
button: 'Button',
card: 'Card',
table: 'Table'
},
plugin: {
_value: 'Plugin',
charts: {
_value: 'Chart',
echarts: 'ECharts',
antv: 'AntV'
}, },
about: { copy: 'Copy',
about: 'About' editor: {
_value: 'Editor',
quill: 'Quill',
markdown: 'Markdown'
},
icon: 'Icon',
map: 'Map',
print: 'Print',
swiper: 'Swiper',
video: 'Video'
},
'auth-demo': {
_value: 'Auth Demo',
permission: 'Toggle Permission',
super: 'Super Auth'
},
function: {
_value: 'Function',
tab: 'System Tab'
},
exception: {
_value: 'Exception',
403: '403',
404: '404',
500: '500'
},
'multi-menu': {
_value: 'Multi Degree Menu',
first: {
_value: 'First Degree',
second: 'Second Degree',
'second-new': {
_value: 'Second Degree With Children',
third: 'Third Degree'
}
}
},
management: {
_value: 'System Management',
auth: 'Auth',
role: 'Role',
route: 'Route',
user: 'User'
},
about: 'About'
},
layout: {
settingDrawer: {
title: 'Theme configuration',
themeModeTitle: 'Theme mode',
darkMode: 'Dark mode',
layoutModelTitle: 'Layout mode',
systemThemeTitle: 'System theme',
pageFunctionsTitle: 'Page functions',
pageViewTitle: 'Page view',
followSystemTheme: 'Follow the system',
isCustomizeDarkModeTransition: 'Custom dark theme animation transition',
scrollMode: 'scrollMode',
scrollModeList: {
wrapper: 'Outer layer scroll',
content: 'Main body scroll'
},
fixedHeaderAndTab: 'Fixed header and multiple tabs',
header: {
inverted: 'darkHead',
height: 'Head Height',
crumb: {
visible: 'Crumb',
icon: 'Crumb icon'
}
},
tab: {
visible: 'Multi-page tab',
height: 'Multiple tab height',
modeList: {
mode: 'Multi-tab style',
chrome: 'Google style',
button: 'Button style'
},
isCache: 'Multiple tab caching'
},
sider: {
inverted: 'Dark sidebar',
width: 'Sidebar expanded width',
mixWidth: 'Left hybrid sidebar expanded width'
},
menu: {
horizontalPosition: 'Top menu position',
horizontalPositionList: {
flexStart: 'Right',
center: 'center',
flexEnd: 'Left'
}
},
footer: {
inverted: 'Dark bottom',
visible: 'Show bottom',
fixed: 'Fixed bottom',
right: 'Bottom to the right'
},
page: {
animate: 'switch animation',
animateMode: 'switch animation type',
animateModeList: {
zoomFade: 'Gradual change',
zoomOut: 'Flash',
fadeSlide: 'Slide',
fade: 'Fade away',
fadeBottom: 'Bottom fade',
fadeScale: 'Resizing fade away'
}
},
systemTheme: {
moreColors: 'More colors'
},
themeConfiguration: {
title: 'Theme configuration',
copy: 'Copy the current configuration',
reset: 'Reset the current configuration',
resetSuccess: 'The configuration has been reset, please copy it again!',
operateSuccess: 'Successful operation',
copySuccess: 'Copy success, please replace the content of src/settings/theme.json!',
confirmCopy: 'Confirm'
}
}
},
page: {
login: {
common: {
userNamePlaceholder: 'Please enter user name',
phonePlaceholder: 'Please enter phone number',
codePlaceholder: 'Please enter verification code',
passwordPlaceholder: 'Please enter password',
confirmPasswordPlaceholder: 'Please enter password again',
codeLogin: 'Verification code login',
confirm: 'Confirm',
back: 'Back',
validateSuccess: 'Verification passed',
loginSuccess: 'Login success',
welcomeBack: 'Welcome back, {userName}!'
},
pwdLogin: {
title: 'Password Login',
rememberMe: 'Remember me',
forgetPassword: 'Forget password?',
register: 'Register account',
otherAccountLogin: 'Other Account Login',
otherLoginMode: 'Other Login Mode',
superAdmin: 'Super Administrator',
admin: 'Administrator',
user: 'Ordinary User'
},
codeLogin: {
title: 'Verification Code Login',
getCode: 'Get verification code',
imageCodePlaceholder: 'Please enter image verification code'
},
register: {
title: 'Register Account',
agreement: 'I have read and agree to',
protocol: '《User Agreement》',
policy: '《Privacy Policy》'
},
resetPwd: {
title: 'Reset Password'
},
bindWeChat: {
title: 'Bind WeChat'
} }
} }
} }

View File

@@ -1,11 +0,0 @@
import zhCN from './zh-cn';
import en from './en';
const locales = {
'zh-CN': zhCN,
en
};
export type LocaleKey = keyof typeof locales;
export default locales;

219
src/locales/lang/km-KH.ts Normal file
View File

@@ -0,0 +1,219 @@
const locale: I18nType.Schema = {
system: {
title: 'ប្រព័ន្ធគ្រប់គ្រង'
},
common: {
add: 'បន្ថែម',
addSuccess: 'បន្ថែមជោគជ័យ',
edit: 'កែប្រែ',
editSuccess: 'កែប្រែជោគជ័យ',
delete: 'លុប',
deleteSuccess: 'លុបជោគជ័យ',
batchDelete: 'លុបច្រើន',
confirm: 'យល់ព្រម',
cancel: 'បោះបង់',
pleaseCheckValue: 'សូមពិនិត្យមើលតម្លៃដែលបានបញ្ចូលដើម្បីបញ្ជាក់ថាត្រូវប្រើប្រាស់បាន',
action: 'សកម្មភាព'
},
routes: {
dashboard: {
_value: 'ផ្ទាំងទិន្នន័យ',
analysis: 'ផ្ទាំងវិភាគ',
workbench: 'ផ្ទាំងការងារ'
},
document: {
_value: 'ឯកសារ',
vue: 'ឯកសារ​ Vue',
vite: 'ឯកសារ​ Vite',
naive: 'ឯកសារ NaiveUI',
project: 'ឯកសារគម្រោង',
'project-link': 'ឯកសារគម្រោង(href)'
},
component: {
_value: 'សមាស​ភាគ',
button: 'ប៊ូតុង',
card: 'កាត',
table: 'តារាង'
},
plugin: {
_value: 'មុខងារជំនួយ',
charts: {
_value: 'តារាង​ Chart',
echarts: 'តារាង ECharts',
antv: 'AntV'
},
copy: 'ចម្លង',
editor: {
_value: 'កែប្រែ',
quill: 'Quill',
markdown: 'Markdown'
},
icon: 'អាយខន',
map: 'ផែនទី',
print: 'បោះពុម្ភ',
swiper: 'Swiper',
video: 'វីដេអូ'
},
'auth-demo': {
_value: 'ឌីមូ Auth',
permission: 'បិទ/បើកការអនុញ្ញាត',
super: 'Super Auth'
},
function: {
_value: 'មុខងារ',
tab: 'ថេបប្រព័ន្ធ'
},
exception: {
_value: 'ករណីពិេសស',
403: '403',
404: '404',
500: '500'
},
'multi-menu': {
_value: 'ម៉ឺនុយពហុដឺក្រេ',
first: {
_value: 'ដឺក្រេទី១',
second: 'ដែក្រេទី២',
'second-new': {
_value: 'ដឺក្រេទី២មានអនុក្រោម',
third: 'ដឺក្រេទី៣'
}
}
},
management: {
_value: 'ការគ្រប់គ្រងប្រព័ន្ធ',
auth: 'Auth',
role: 'សិទ្ធី',
route: 'ផ្លូវប្រព័ន្ធ',
user: 'អ្នកប្រើប្រាស់'
},
about: 'អំពីប្រព័ន្ធ'
},
layout: {
settingDrawer: {
title: 'ការកំណត់ស្បែក',
themeModeTitle: 'ស្បែករបស់របស់អ្នក',
darkMode: 'របៀបងារស្បែកងងឹត',
layoutModelTitle: 'របៀបប្រើប្រាស់របស់អ្នក',
systemThemeTitle: 'ស្បែករបស់ប្រព័ន្ធគ្រប់គ្រង',
pageFunctionsTitle: 'មុខងារទំនាក់ទំនងរបស់ទំព័រ',
pageViewTitle: 'ទំព័រទស្សន៍ទាយ',
followSystemTheme: 'តាមដានស្បែកប្រព័ន្ធគ្រប់គ្រង',
isCustomizeDarkModeTransition: 'ប្រើប្រាស់របៀបងារស្បែកងងឹតផ្ទាល់ខ្លួន',
scrollMode: 'របៀបរុករក',
scrollModeList: {
wrapper: 'រុករកជាក់លាក់',
content: 'រុករកមានមុខងារ'
},
fixedHeaderAndTab: 'បិទការរុករកជាក់លាក់និងរុករកមានមុខងារ',
header: {
inverted: 'បង្កើតការរុករកជាក់លាក់',
height: 'កម្ពស់',
crumb: {
visible: 'បង្ហាញរុករកជាក់លាក់',
icon: 'រុករកជាក់លាក់រូបតំណាង'
}
},
tab: {
visible: 'បង្ហាញរុករកជាក់លាក់',
height: 'កម្ពស់',
modeList: {
mode: 'របៀប',
chrome: 'ក្រុមហ៊ុន',
button: 'ប៊ូតុង'
},
isCache: 'រក្សាទុកការរុករកជាក់លាក់'
},
sider: {
inverted: 'បង្កើតការរុករកជាក់លាក់',
width: 'ទទឹង',
mixWidth: 'ទទឹងបញ្ចូល'
},
menu: {
horizontalPosition: 'ទីតាំងផ្ដេក',
horizontalPositionList: {
flexStart: 'ចាប់ផ្ដើមឈុត',
center: 'កណ្តាល',
flexEnd: 'ចាប់ផ្ដើមចុងក្រោយ'
}
},
footer: {
inverted: 'បង្កើតការរុករកជាក់លាក់',
visible: 'បង្ហាញការរុករកជាក់លាក់',
fixed: 'ការរុករកជាក់លាក់',
right: 'ត្រឡប់ទៅស្តាំ'
},
page: {
animate: 'ការផ្លាស់ប្តូរ',
animateMode: 'របៀបផ្លាស់ប្តូរ',
animateModeList: {
zoomFade: 'ពង្រីកបង្ហាញនិងលាស់ប្តូរ',
zoomOut: 'ពង្រីកបង្ហាញនិងលាស់ប្តូរ',
fadeSlide: 'ពង្រីកបង្ហាញនិងលាស់ប្តូរ',
fade: 'ពង្រីកបង្ហាញនិងលាស់ប្តូរ',
fadeBottom: 'ពង្រីកបង្ហាញនិងលាស់ប្តូរ',
fadeScale: 'ពង្រីកបង្ហាញនិងលាស់ប្តូរ'
}
},
systemTheme: {
moreColors: 'ពន្លឺច្រើនទៀត'
},
themeConfiguration: {
title: 'ការកំណត់ស្បែក',
copy: 'ចម្លង',
reset: 'កំណត់ឡើងវិញ',
resetSuccess: 'កំណត់ឡើងវិញជោគជ័យ, សូមចម្លងឯកសារស្បែកឡើងវិញ!',
operateSuccess: 'សម្រាប់ការប្រើប្រាស់ជោគជ័យ',
copySuccess: 'ចម្លងជោគជ័យ, សូមជោគជ័យឯកសារ src/settings/theme.json!',
confirmCopy: 'យល់ព្រម'
}
}
},
page: {
login: {
common: {
userNamePlaceholder: 'ឈ្មោះអ្នកប្រើប្រាស់',
phonePlaceholder: 'លេខទូរស័ព្ទ',
codePlaceholder: 'លេខកូដ',
passwordPlaceholder: 'លេខសម្ងាត់',
confirmPasswordPlaceholder: 'បញ្ជាក់លេខសម្ងាត់',
codeLogin: 'ចូលតាមលេខកូដ',
confirm: 'យល់ព្រម',
back: 'ត្រឡប់ក្រោយ',
validateSuccess: 'បញ្ជាក់ជោគជ័យ',
loginSuccess: 'ចូលជោគជ័យ',
welcomeBack: 'សូមស្វាគមន៍ម្តងទៀត, {userName}!'
},
pwdLogin: {
title: 'ចូលគណនី',
rememberMe: 'ចងចាំខ្ញុំ',
forgetPassword: 'ភ្លេចលេខសម្ងាត់',
register: 'ចុះឈ្មោះ',
otherAccountLogin: 'ចូលតាមគណនីផ្សេងទៀត',
otherLoginMode: 'របៀបចូលគណនីផ្សេងទៀត',
superAdmin: 'អ្នកគ្រប់គ្រងសុវត្ថិភាព',
admin: 'អ្នកគ្រប់គ្រង',
user: 'អ្នកប្រើប្រាស់'
},
codeLogin: {
title: 'ចូលតាមលេខកូដ',
getCode: 'ទទួលលេខកូដ',
imageCodePlaceholder: 'លេខកូដរូបភាព'
},
register: {
title: 'ចុះឈ្មោះ',
agreement: 'យល់ព្រមនឹង',
protocol: 'សម្រាប់ការប្រើប្រាស់',
policy: 'គោលការណ៍ផ្សេងៗ'
},
resetPwd: {
title: 'កំណត់លេខសម្ងាត់ថ្មី'
},
bindWeChat: {
title: 'ភ្ជាប់គណនីរបស់អ្នកជាមួយគណនីរបស់អ្នក'
}
}
}
};
export default locale;

219
src/locales/lang/zh-CN.ts Normal file
View File

@@ -0,0 +1,219 @@
const locale: I18nType.Schema = {
system: {
title: 'Soybean管理系统'
},
common: {
add: '添加',
addSuccess: '添加成功',
edit: '修改',
editSuccess: '修改成功',
delete: '删除',
deleteSuccess: '删除成功',
batchDelete: '批量删除',
confirm: '确认',
cancel: '取消',
pleaseCheckValue: '请检查输入的值是否合法',
action: '操作'
},
routes: {
dashboard: {
_value: '仪表盘',
analysis: '分析页',
workbench: '工作台'
},
document: {
_value: '文档',
vue: 'Vue文档',
vite: 'Vite文档',
naive: 'NaiveUI文档',
project: '项目文档',
'project-link': '项目文档(外链)'
},
component: {
_value: '组件示例',
button: '按钮',
card: '卡片',
table: '表格'
},
plugin: {
_value: '插件示例',
charts: {
_value: '图表',
echarts: 'ECharts',
antv: 'AntV'
},
copy: '剪贴板',
editor: {
_value: '编辑器',
quill: '富文本',
markdown: 'Markdown'
},
icon: '图标',
map: '地图',
print: '打印',
swiper: 'Swiper',
video: '视频'
},
'auth-demo': {
_value: '权限示例',
permission: '切换权限',
super: '超级管理员可见'
},
function: {
_value: '功能',
tab: 'Tab页签'
},
exception: {
_value: '异常页',
403: '403',
404: '404',
500: '500'
},
'multi-menu': {
_value: '多级菜单',
first: {
_value: '一级菜单',
second: '二级菜单',
'second-new': {
_value: '二级菜单(有子菜单)',
third: '三级菜单'
}
}
},
management: {
_value: '系统管理',
auth: '权限管理',
role: '角色管理',
route: '路由管理',
user: '用户管理'
},
about: '关于'
},
layout: {
settingDrawer: {
title: '主题配置',
themeModeTitle: '主题模式',
darkMode: '深色主题',
layoutModelTitle: '布局模式',
systemThemeTitle: '系统主题',
pageFunctionsTitle: '界面功能',
pageViewTitle: '界面显示',
followSystemTheme: '跟随系统',
isCustomizeDarkModeTransition: '自定义暗黑主题动画过渡',
scrollMode: '滚动模式',
scrollModeList: {
wrapper: '外层滚动',
content: '主体滚动'
},
fixedHeaderAndTab: '固定头部和多页签',
header: {
inverted: '头部深色',
height: '头部高度',
crumb: {
visible: '面包屑',
icon: '面包屑图标'
}
},
tab: {
visible: '多页签',
height: '多页签高度',
modeList: {
mode: '多页签风格',
chrome: '谷歌风格',
button: '按钮风格'
},
isCache: '多页签缓存'
},
sider: {
inverted: '侧边栏深色',
width: '侧边栏展开宽度',
mixWidth: '左侧混合侧边栏展开宽度'
},
menu: {
horizontalPosition: '顶部菜单位置',
horizontalPositionList: {
flexStart: '居左',
center: '居中',
flexEnd: '居右'
}
},
footer: {
inverted: '底部深色',
visible: '显示底部',
fixed: '固定底部',
right: '底部居右'
},
page: {
animate: '页面切换动画',
animateMode: '页面切换动画类型',
animateModeList: {
zoomFade: '渐变',
zoomOut: '闪现',
fadeSlide: '滑动',
fade: '消退',
fadeBottom: '底部消退',
fadeScale: '缩放消退'
}
},
systemTheme: {
moreColors: '更多颜色'
},
themeConfiguration: {
title: '主题配置',
copy: '拷贝当前配置',
reset: '重置当前配置',
resetSuccess: '已重置配置,请重新拷贝!',
operateSuccess: '操作成功',
copySuccess: '复制成功,请替换 src/settings/theme.json的内容',
confirmCopy: '确认'
}
}
},
page: {
login: {
common: {
userNamePlaceholder: '请输入用户名',
phonePlaceholder: '请输入手机号',
codePlaceholder: '请输入验证码',
passwordPlaceholder: '请输入密码',
confirmPasswordPlaceholder: '请再次输入密码',
codeLogin: '验证码登录',
confirm: '确定',
back: '返回',
validateSuccess: '验证成功',
loginSuccess: '登录成功',
welcomeBack: '欢迎回来,{userName}!'
},
pwdLogin: {
title: '密码登录',
rememberMe: '记住我',
forgetPassword: '忘记密码?',
register: '注册账号',
otherAccountLogin: '其他账号登录',
otherLoginMode: '其他登录方式',
superAdmin: '超级管理员',
admin: '管理员',
user: '普通用户'
},
codeLogin: {
title: '验证码登录',
getCode: '获取验证码',
imageCodePlaceholder: '请输入图片验证码'
},
register: {
title: '注册账号',
agreement: '我已经仔细阅读并接受',
protocol: '《用户协议》',
policy: '《隐私权政策》'
},
resetPwd: {
title: '重置密码'
},
bindWeChat: {
title: '绑定微信'
}
}
}
};
export default locale;

View File

@@ -1,21 +0,0 @@
import type { LocaleMessages } from 'vue-i18n';
const locale: LocaleMessages<I18nType.Schema> = {
message: {
system: {
title: 'Soybean管理系统'
},
routes: {
dashboard: {
dashboard: '仪表盘',
analysis: '分析页',
workbench: '工作台'
},
about: {
about: '关于'
}
}
}
};
export default locale;

11
src/locales/locale.ts Normal file
View File

@@ -0,0 +1,11 @@
import zhCN from './lang/zh-CN';
import en from './lang/en';
import kmKH from './lang/km-KH';
const locales: Record<I18nType.LangType, I18nType.Schema> = {
'zh-CN': zhCN,
en,
'km-KH': kmKH
};
export default locales;

View File

@@ -29,6 +29,8 @@ async function setupApp() {
setupI18n(app); setupI18n(app);
appLoading.unmount();
// mount app // mount app
app.mount('#app'); app.mount('#app');
} }

View File

@@ -7,4 +7,6 @@ import 'virtual:svg-icons-register';
import '../styles/css/global.css'; import '../styles/css/global.css';
/** import static assets: css, js , font and so on. - [引入静态资源css、js和字体文件等] */ /** import static assets: css, js , font and so on. - [引入静态资源css、js和字体文件等] */
export default function setupAssets() {} export default function setupAssets() {
//
}

View File

@@ -1,5 +1,6 @@
import type { Router } from 'vue-router'; import type { Router } from 'vue-router';
import { useTitle } from '@vueuse/core'; import { useTitle } from '@vueuse/core';
import { $t } from '@/locales';
import { createPermissionGuard } from './permission'; import { createPermissionGuard } from './permission';
/** /**
@@ -15,7 +16,7 @@ export function createRouterGuard(router: Router) {
}); });
router.afterEach(to => { router.afterEach(to => {
// 设置document title // 设置document title
useTitle(to.meta.title); useTitle(to.meta.i18nTitle ? $t(to.meta.i18nTitle) : to.meta.title);
// 结束 loadingBar // 结束 loadingBar
window.$loadingBar?.finish(); window.$loadingBar?.finish();
}); });

View File

@@ -1,9 +1,10 @@
const about1: AuthRoute.Route = { const about: AuthRoute.Route = {
name: 'about', name: 'about',
path: '/about', path: '/about',
component: 'self', component: 'self',
meta: { meta: {
title: '关于', title: '关于',
i18nTitle: 'routes.about',
requiresAuth: true, requiresAuth: true,
keepAlive: true, keepAlive: true,
singleLayout: 'basic', singleLayout: 'basic',
@@ -13,4 +14,4 @@ const about1: AuthRoute.Route = {
} }
}; };
export default about1; export default about;

View File

@@ -9,6 +9,7 @@ const authDemo: AuthRoute.Route = {
component: 'self', component: 'self',
meta: { meta: {
title: '权限切换', title: '权限切换',
i18nTitle: 'routes.auth-demo.permission',
requiresAuth: true, requiresAuth: true,
icon: 'ic:round-construction' icon: 'ic:round-construction'
} }
@@ -19,6 +20,7 @@ const authDemo: AuthRoute.Route = {
component: 'self', component: 'self',
meta: { meta: {
title: '超级管理员可见', title: '超级管理员可见',
i18nTitle: 'routes.auth-demo.super',
requiresAuth: true, requiresAuth: true,
permissions: ['super'], permissions: ['super'],
icon: 'ic:round-supervisor-account' icon: 'ic:round-supervisor-account'
@@ -27,6 +29,7 @@ const authDemo: AuthRoute.Route = {
], ],
meta: { meta: {
title: '权限示例', title: '权限示例',
i18nTitle: 'routes.auth-demo._value',
icon: 'ic:baseline-security', icon: 'ic:baseline-security',
order: 5 order: 5
} }

View File

@@ -9,6 +9,7 @@ const component: AuthRoute.Route = {
component: 'self', component: 'self',
meta: { meta: {
title: '按钮', title: '按钮',
i18nTitle: 'routes.component.button',
requiresAuth: true, requiresAuth: true,
icon: 'mdi:button-cursor' icon: 'mdi:button-cursor'
} }
@@ -19,6 +20,7 @@ const component: AuthRoute.Route = {
component: 'self', component: 'self',
meta: { meta: {
title: '卡片', title: '卡片',
i18nTitle: 'routes.component.card',
requiresAuth: true, requiresAuth: true,
icon: 'mdi:card-outline' icon: 'mdi:card-outline'
} }
@@ -29,6 +31,7 @@ const component: AuthRoute.Route = {
component: 'self', component: 'self',
meta: { meta: {
title: '表格', title: '表格',
i18nTitle: 'routes.component.table',
requiresAuth: true, requiresAuth: true,
icon: 'mdi:table-large' icon: 'mdi:table-large'
} }
@@ -36,6 +39,7 @@ const component: AuthRoute.Route = {
], ],
meta: { meta: {
title: '组件示例', title: '组件示例',
i18nTitle: 'routes.component._value',
icon: 'cib:app-store', icon: 'cib:app-store',
order: 3 order: 3
} }

View File

@@ -10,7 +10,8 @@ const dashboard: AuthRoute.Route = {
meta: { meta: {
title: '分析页', title: '分析页',
requiresAuth: true, requiresAuth: true,
icon: 'icon-park-outline:analysis' icon: 'icon-park-outline:analysis',
i18nTitle: 'routes.dashboard.analysis'
} }
}, },
{ {
@@ -20,14 +21,16 @@ const dashboard: AuthRoute.Route = {
meta: { meta: {
title: '工作台', title: '工作台',
requiresAuth: true, requiresAuth: true,
icon: 'icon-park-outline:workbench' icon: 'icon-park-outline:workbench',
i18nTitle: 'routes.dashboard.workbench'
} }
} }
], ],
meta: { meta: {
title: '仪表盘', title: '仪表盘',
icon: 'mdi:monitor-dashboard', icon: 'mdi:monitor-dashboard',
order: 1 order: 1,
i18nTitle: 'routes.dashboard._value'
} }
}; };

View File

@@ -9,6 +9,7 @@ const document: AuthRoute.Route = {
component: 'self', component: 'self',
meta: { meta: {
title: 'vue文档', title: 'vue文档',
i18nTitle: 'routes.document.vue',
requiresAuth: true, requiresAuth: true,
icon: 'logos:vue' icon: 'logos:vue'
} }
@@ -19,6 +20,7 @@ const document: AuthRoute.Route = {
component: 'self', component: 'self',
meta: { meta: {
title: 'vite文档', title: 'vite文档',
i18nTitle: 'routes.document.vite',
requiresAuth: true, requiresAuth: true,
icon: 'logos:vitejs' icon: 'logos:vitejs'
} }
@@ -29,6 +31,7 @@ const document: AuthRoute.Route = {
component: 'self', component: 'self',
meta: { meta: {
title: 'naive文档', title: 'naive文档',
i18nTitle: 'routes.document.naive',
requiresAuth: true, requiresAuth: true,
icon: 'logos:naiveui' icon: 'logos:naiveui'
} }
@@ -39,6 +42,7 @@ const document: AuthRoute.Route = {
component: 'self', component: 'self',
meta: { meta: {
title: '项目文档', title: '项目文档',
i18nTitle: 'routes.document.project',
requiresAuth: true, requiresAuth: true,
localIcon: 'logo' localIcon: 'logo'
} }
@@ -48,14 +52,16 @@ const document: AuthRoute.Route = {
path: '/document/project-link', path: '/document/project-link',
meta: { meta: {
title: '项目文档(外链)', title: '项目文档(外链)',
i18nTitle: 'routes.document.project-link',
requiresAuth: true, requiresAuth: true,
localIcon: 'logo', localIcon: 'logo',
href: 'https://docs.soybean.pro/' href: 'https://admin-docs.soybeanjs.cn/'
} }
} }
], ],
meta: { meta: {
title: '文档', title: '文档',
i18nTitle: 'routes.document._value',
icon: 'mdi:file-document-multiple-outline', icon: 'mdi:file-document-multiple-outline',
order: 2 order: 2
} }

View File

@@ -9,6 +9,7 @@ const exception: AuthRoute.Route = {
component: 'self', component: 'self',
meta: { meta: {
title: '异常页403', title: '异常页403',
i18nTitle: 'routes.exception.403',
requiresAuth: true, requiresAuth: true,
icon: 'ic:baseline-block' icon: 'ic:baseline-block'
} }
@@ -19,6 +20,7 @@ const exception: AuthRoute.Route = {
component: 'self', component: 'self',
meta: { meta: {
title: '异常页404', title: '异常页404',
i18nTitle: 'routes.exception.404',
requiresAuth: true, requiresAuth: true,
icon: 'ic:baseline-web-asset-off' icon: 'ic:baseline-web-asset-off'
} }
@@ -29,12 +31,14 @@ const exception: AuthRoute.Route = {
component: 'self', component: 'self',
meta: { meta: {
title: '异常页500', title: '异常页500',
i18nTitle: 'routes.exception.500',
requiresAuth: true, requiresAuth: true,
icon: 'ic:baseline-wifi-off' icon: 'ic:baseline-wifi-off'
} }
} }
], ],
meta: { meta: {
i18nTitle: 'routes.exception._value',
title: '异常页', title: '异常页',
icon: 'ant-design:exception-outlined', icon: 'ant-design:exception-outlined',
order: 7 order: 7

View File

@@ -9,6 +9,7 @@ const functionRoute: AuthRoute.Route = {
component: 'self', component: 'self',
meta: { meta: {
title: 'Tab', title: 'Tab',
i18nTitle: 'routes.function.tab',
requiresAuth: true, requiresAuth: true,
icon: 'ic:round-tab' icon: 'ic:round-tab'
} }
@@ -41,6 +42,7 @@ const functionRoute: AuthRoute.Route = {
], ],
meta: { meta: {
title: '功能', title: '功能',
i18nTitle: 'routes.function._value',
icon: 'icon-park-outline:all-application', icon: 'icon-park-outline:all-application',
order: 6 order: 6
} }

View File

@@ -9,7 +9,9 @@ const management: AuthRoute.Route = {
component: 'self', component: 'self',
meta: { meta: {
title: '权限管理', title: '权限管理',
i18nTitle: 'routes.management.auth',
requiresAuth: true, requiresAuth: true,
keepAlive: true,
icon: 'ic:baseline-security' icon: 'ic:baseline-security'
} }
}, },
@@ -19,7 +21,9 @@ const management: AuthRoute.Route = {
component: 'self', component: 'self',
meta: { meta: {
title: '角色管理', title: '角色管理',
i18nTitle: 'routes.management.role',
requiresAuth: true, requiresAuth: true,
keepAlive: true,
icon: 'carbon:user-role' icon: 'carbon:user-role'
} }
}, },
@@ -29,7 +33,9 @@ const management: AuthRoute.Route = {
component: 'self', component: 'self',
meta: { meta: {
title: '用户管理', title: '用户管理',
i18nTitle: 'routes.management.user',
requiresAuth: true, requiresAuth: true,
keepAlive: true,
icon: 'ic:round-manage-accounts' icon: 'ic:round-manage-accounts'
} }
}, },
@@ -39,13 +45,16 @@ const management: AuthRoute.Route = {
component: 'self', component: 'self',
meta: { meta: {
title: '路由管理', title: '路由管理',
i18nTitle: 'routes.management.route',
requiresAuth: true, requiresAuth: true,
keepAlive: true,
icon: 'material-symbols:route' icon: 'material-symbols:route'
} }
} }
], ],
meta: { meta: {
title: '系统管理', title: '系统管理',
i18nTitle: 'routes.management._value',
icon: 'carbon:cloud-service-management', icon: 'carbon:cloud-service-management',
order: 9 order: 9
} }

View File

@@ -14,6 +14,7 @@ const multiMenu: AuthRoute.Route = {
component: 'self', component: 'self',
meta: { meta: {
title: '二级菜单', title: '二级菜单',
i18nTitle: 'routes.multi-menu.first.second',
requiresAuth: true, requiresAuth: true,
icon: 'mdi:menu' icon: 'mdi:menu'
} }
@@ -29,6 +30,7 @@ const multiMenu: AuthRoute.Route = {
component: 'self', component: 'self',
meta: { meta: {
title: '三级菜单', title: '三级菜单',
i18nTitle: 'routes.multi-menu.first.second-new.third',
requiresAuth: true, requiresAuth: true,
icon: 'mdi:menu' icon: 'mdi:menu'
} }
@@ -36,18 +38,21 @@ const multiMenu: AuthRoute.Route = {
], ],
meta: { meta: {
title: '二级菜单(有子菜单)', title: '二级菜单(有子菜单)',
i18nTitle: 'routes.multi-menu.first.second-new._value',
icon: 'mdi:menu' icon: 'mdi:menu'
} }
} }
], ],
meta: { meta: {
title: '一级菜单', title: '一级菜单',
i18nTitle: 'routes.multi-menu.first._value',
icon: 'mdi:menu' icon: 'mdi:menu'
} }
} }
], ],
meta: { meta: {
title: '多级菜单', title: '多级菜单',
i18nTitle: 'routes.multi-menu._value',
icon: 'carbon:menu', icon: 'carbon:menu',
order: 8 order: 8
} }

View File

@@ -14,6 +14,7 @@ const plugin: AuthRoute.Route = {
component: 'self', component: 'self',
meta: { meta: {
title: 'ECharts', title: 'ECharts',
i18nTitle: 'routes.plugin.charts.echarts',
requiresAuth: true, requiresAuth: true,
icon: 'simple-icons:apacheecharts' icon: 'simple-icons:apacheecharts'
} }
@@ -24,6 +25,7 @@ const plugin: AuthRoute.Route = {
component: 'self', component: 'self',
meta: { meta: {
title: 'AntV', title: 'AntV',
i18nTitle: 'routes.plugin.charts.antv',
requiresAuth: true, requiresAuth: true,
icon: 'simple-icons:antdesign' icon: 'simple-icons:antdesign'
} }
@@ -31,6 +33,7 @@ const plugin: AuthRoute.Route = {
], ],
meta: { meta: {
title: '图表', title: '图表',
i18nTitle: 'routes.plugin.charts._value',
icon: 'mdi:chart-areaspline' icon: 'mdi:chart-areaspline'
} }
}, },
@@ -40,6 +43,7 @@ const plugin: AuthRoute.Route = {
component: 'self', component: 'self',
meta: { meta: {
title: '地图', title: '地图',
i18nTitle: 'routes.plugin.map',
requiresAuth: true, requiresAuth: true,
icon: 'mdi:map' icon: 'mdi:map'
} }
@@ -50,6 +54,7 @@ const plugin: AuthRoute.Route = {
component: 'self', component: 'self',
meta: { meta: {
title: '视频', title: '视频',
i18nTitle: 'routes.plugin.video',
requiresAuth: true, requiresAuth: true,
icon: 'mdi:video' icon: 'mdi:video'
} }
@@ -65,6 +70,7 @@ const plugin: AuthRoute.Route = {
component: 'self', component: 'self',
meta: { meta: {
title: '富文本编辑器', title: '富文本编辑器',
i18nTitle: 'routes.plugin.editor.quill',
requiresAuth: true, requiresAuth: true,
icon: 'mdi:file-document-edit-outline' icon: 'mdi:file-document-edit-outline'
} }
@@ -75,6 +81,7 @@ const plugin: AuthRoute.Route = {
component: 'self', component: 'self',
meta: { meta: {
title: 'markdown编辑器', title: 'markdown编辑器',
i18nTitle: 'routes.plugin.editor.markdown',
requiresAuth: true, requiresAuth: true,
icon: 'ri:markdown-line' icon: 'ri:markdown-line'
} }
@@ -82,6 +89,7 @@ const plugin: AuthRoute.Route = {
], ],
meta: { meta: {
title: '编辑器', title: '编辑器',
i18nTitle: 'routes.plugin.editor._value',
icon: 'icon-park-outline:editor' icon: 'icon-park-outline:editor'
} }
}, },
@@ -91,6 +99,7 @@ const plugin: AuthRoute.Route = {
component: 'self', component: 'self',
meta: { meta: {
title: 'Swiper插件', title: 'Swiper插件',
i18nTitle: 'routes.plugin.swiper',
requiresAuth: true, requiresAuth: true,
icon: 'simple-icons:swiper' icon: 'simple-icons:swiper'
} }
@@ -101,6 +110,7 @@ const plugin: AuthRoute.Route = {
component: 'self', component: 'self',
meta: { meta: {
title: '剪贴板', title: '剪贴板',
i18nTitle: 'routes.plugin.copy',
requiresAuth: true, requiresAuth: true,
icon: 'mdi:clipboard-outline' icon: 'mdi:clipboard-outline'
} }
@@ -111,6 +121,7 @@ const plugin: AuthRoute.Route = {
component: 'self', component: 'self',
meta: { meta: {
title: '图标', title: '图标',
i18nTitle: 'routes.plugin.icon',
requiresAuth: true, requiresAuth: true,
localIcon: 'custom-icon' localIcon: 'custom-icon'
} }
@@ -121,6 +132,7 @@ const plugin: AuthRoute.Route = {
component: 'self', component: 'self',
meta: { meta: {
title: '打印', title: '打印',
i18nTitle: 'routes.plugin.print',
requiresAuth: true, requiresAuth: true,
icon: 'mdi:printer' icon: 'mdi:printer'
} }
@@ -128,6 +140,7 @@ const plugin: AuthRoute.Route = {
], ],
meta: { meta: {
title: '插件示例', title: '插件示例',
i18nTitle: 'routes.plugin._value',
icon: 'clarity:plugin-line', icon: 'clarity:plugin-line',
order: 4 order: 4
} }

View File

@@ -1,5 +1,5 @@
import axios from 'axios'; import axios from 'axios';
import type { AxiosError, AxiosInstance, AxiosRequestConfig } from 'axios'; import type { AxiosResponse, AxiosError, AxiosInstance, AxiosRequestConfig } from 'axios';
import { REFRESH_TOKEN_CODE } from '@/config'; import { REFRESH_TOKEN_CODE } from '@/config';
import { import {
localStg, localStg,
@@ -11,6 +11,8 @@ import {
} from '@/utils'; } from '@/utils';
import { handleRefreshToken } from './helpers'; import { handleRefreshToken } from './helpers';
type RefreshRequestQueue = (config: AxiosRequestConfig) => void;
/** /**
* 封装axios请求类 * 封装axios请求类
* @author Soybean<honghuangdc@gmail.com> * @author Soybean<honghuangdc@gmail.com>
@@ -20,6 +22,10 @@ export default class CustomAxiosInstance {
backendConfig: Service.BackendResultConfig; backendConfig: Service.BackendResultConfig;
isRefreshing: boolean;
retryQueues: RefreshRequestQueue[];
/** /**
* *
* @param axiosConfig - axios配置 * @param axiosConfig - axios配置
@@ -37,6 +43,8 @@ export default class CustomAxiosInstance {
this.backendConfig = backendConfig; this.backendConfig = backendConfig;
this.instance = axios.create(axiosConfig); this.instance = axios.create(axiosConfig);
this.setInterceptor(); this.setInterceptor();
this.isRefreshing = false;
this.retryQueues = [];
} }
/** 设置请求拦截器 */ /** 设置请求拦截器 */
@@ -59,8 +67,8 @@ export default class CustomAxiosInstance {
} }
); );
this.instance.interceptors.response.use( this.instance.interceptors.response.use(
async response => { (async response => {
const { status } = response; const { status, config } = response;
if (status === 200 || status < 300 || status === 304) { if (status === 200 || status < 300 || status === 304) {
const backend = response.data; const backend = response.data;
const { codeKey, dataKey, successCode } = this.backendConfig; const { codeKey, dataKey, successCode } = this.backendConfig;
@@ -71,10 +79,24 @@ export default class CustomAxiosInstance {
// token失效, 刷新token // token失效, 刷新token
if (REFRESH_TOKEN_CODE.includes(backend[codeKey])) { if (REFRESH_TOKEN_CODE.includes(backend[codeKey])) {
const config = await handleRefreshToken(response.config); // 原始请求
if (config) { const originRequest = new Promise(resolve => {
return this.instance.request(config); this.retryQueues.push((refreshConfig: AxiosRequestConfig) => {
config.headers.Authorization = refreshConfig.headers?.Authorization;
resolve(this.instance.request(config));
});
});
if (!this.isRefreshing) {
this.isRefreshing = true;
const refreshConfig = await handleRefreshToken(response.config);
if (refreshConfig) {
this.retryQueues.map(cb => cb(refreshConfig));
}
this.retryQueues = [];
this.isRefreshing = false;
} }
return originRequest;
} }
const error = handleBackendError(backend, this.backendConfig); const error = handleBackendError(backend, this.backendConfig);
@@ -82,7 +104,7 @@ export default class CustomAxiosInstance {
} }
const error = handleResponseError(response); const error = handleResponseError(response);
return handleServiceResult(error, null); return handleServiceResult(error, null);
}, }) as (response: AxiosResponse<any, any>) => Promise<AxiosResponse<any, any>>,
(axiosError: AxiosError) => { (axiosError: AxiosError) => {
const error = handleAxiosError(axiosError); const error = handleAxiosError(axiosError);
return handleServiceResult(error, null); return handleServiceResult(error, null);

View File

@@ -1,6 +1,7 @@
{ {
"darkMode": false, "darkMode": false,
"followSystemTheme": true, "followSystemTheme": true,
"isCustomizeDarkModeTransition": false,
"layout": { "layout": {
"minWidth": 900, "minWidth": 900,
"mode": "vertical", "mode": "vertical",
@@ -34,15 +35,15 @@
"label": "主体滚动" "label": "主体滚动"
} }
], ],
"themeColor": "#1890ff", "themeColor": "#646cff",
"themeColorList": [ "themeColorList": [
"#1890ff", "#1890ff",
"#409EFF", "#409EFF",
"#2d8cf0",
"#007AFF", "#007AFF",
"#5ac8fa", "#5ac8fa",
"#5856D6", "#5856D6",
"#536dfe", "#536dfe",
"#646cff",
"#9c27b0", "#9c27b0",
"#AF52DE", "#AF52DE",
"#0096c7", "#0096c7",
@@ -120,9 +121,11 @@
] ]
}, },
"footer": { "footer": {
"visible": true,
"fixed": false, "fixed": false,
"right": true,
"height": 48, "height": 48,
"visible": true "inverted": false
}, },
"page": { "page": {
"animate": true, "animate": true,

View File

@@ -10,11 +10,11 @@ import jsonSetting from './theme.json';
const themeColorList = [ const themeColorList = [
'#1890ff', '#1890ff',
'#409EFF', '#409EFF',
'#2d8cf0',
'#007AFF', '#007AFF',
'#5ac8fa', '#5ac8fa',
'#5856D6', '#5856D6',
'#536dfe', '#536dfe',
'#646cff',
'#9c27b0', '#9c27b0',
'#AF52DE', '#AF52DE',
'#0096c7', '#0096c7',
@@ -37,6 +37,7 @@ const themeColorList = [
const defaultThemeSetting: Theme.Setting = { const defaultThemeSetting: Theme.Setting = {
darkMode: false, darkMode: false,
followSystemTheme: true, followSystemTheme: true,
isCustomizeDarkModeTransition: false,
layout: { layout: {
minWidth: 900, minWidth: 900,
mode: 'vertical', mode: 'vertical',
@@ -44,7 +45,7 @@ const defaultThemeSetting: Theme.Setting = {
}, },
scrollMode: 'content', scrollMode: 'content',
scrollModeList: themeScrollModeOptions, scrollModeList: themeScrollModeOptions,
themeColor: themeColorList[0], themeColor: themeColorList[6],
themeColorList, themeColorList,
otherColor: { otherColor: {
info: '#2080f0', info: '#2080f0',
@@ -83,9 +84,11 @@ const defaultThemeSetting: Theme.Setting = {
horizontalPositionList: themeHorizontalMenuPositionOptions horizontalPositionList: themeHorizontalMenuPositionOptions
}, },
footer: { footer: {
visible: true,
fixed: false, fixed: false,
right: true,
height: 48, height: 48,
visible: true inverted: false
}, },
page: { page: {
animate: true, animate: true,

View File

@@ -1,6 +1,7 @@
import { nextTick } from 'vue'; import { nextTick } from 'vue';
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import { SCROLL_EL_ID } from '@soybeanjs/vue-materials'; import type { Socket } from 'socket.io-client';
import { LAYOUT_SCROLL_EL_ID } from '@soybeanjs/vue-materials';
interface AppState { interface AppState {
/** 滚动元素的id */ /** 滚动元素的id */
@@ -17,17 +18,20 @@ interface AppState {
siderCollapse: boolean; siderCollapse: boolean;
/** vertical-mix模式下 侧边栏的固定状态 */ /** vertical-mix模式下 侧边栏的固定状态 */
mixSiderFixed: boolean; mixSiderFixed: boolean;
/** socket.io 实例 */
socket: Socket | null;
} }
export const useAppStore = defineStore('app-store', { export const useAppStore = defineStore('app-store', {
state: (): AppState => ({ state: (): AppState => ({
scrollElId: SCROLL_EL_ID, scrollElId: LAYOUT_SCROLL_EL_ID,
contentFull: false, contentFull: false,
disableMainXScroll: false, disableMainXScroll: false,
reloadFlag: true, reloadFlag: true,
settingDrawerVisible: false, settingDrawerVisible: false,
siderCollapse: false, siderCollapse: false,
mixSiderFixed: false mixSiderFixed: false,
socket: null
}), }),
actions: { actions: {
/** /**
@@ -97,6 +101,10 @@ export const useAppStore = defineStore('app-store', {
/** 设置主体内容全屏 */ /** 设置主体内容全屏 */
setContentFull(full: boolean) { setContentFull(full: boolean) {
this.contentFull = full; this.contentFull = full;
},
/** 设置socket实例 */
setSocket<T extends Socket = Socket>(socket: T) {
this.socket = socket;
} }
} }
}); });

View File

@@ -4,6 +4,7 @@ import { router } from '@/router';
import { fetchLogin, fetchUserInfo } from '@/service'; import { fetchLogin, fetchUserInfo } from '@/service';
import { useRouterPush } from '@/composables'; import { useRouterPush } from '@/composables';
import { localStg } from '@/utils'; import { localStg } from '@/utils';
import { $t } from '@/locales';
import { useTabStore } from '../tab'; import { useTabStore } from '../tab';
import { useRouteStore } from '../route'; import { useRouteStore } from '../route';
import { getToken, getUserInfo, clearAuthStorage } from './helpers'; import { getToken, getUserInfo, clearAuthStorage } from './helpers';
@@ -68,8 +69,8 @@ export const useAuthStore = defineStore('auth-store', {
// 登录成功弹出欢迎提示 // 登录成功弹出欢迎提示
if (route.isInitAuthRoute) { if (route.isInitAuthRoute) {
window.$notification?.success({ window.$notification?.success({
title: '登录成功!', title: $t('page.login.common.loginSuccess'),
content: `欢迎回来,${this.userInfo.userName}!`, content: $t('page.login.common.welcomeBack', { userName: this.userInfo.userName }),
duration: 3000 duration: 3000
}); });
} }

Some files were not shown because too many files have changed in this diff Show More