mirror of
				https://github.com/soybeanjs/soybean-admin.git
				synced 2025-11-01 06:13:44 +08:00 
			
		
		
		
	Compare commits
	
		
			137 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | ead48f4502 | ||
|  | 305d95672a | ||
|  | 8a792c7d63 | ||
|  | 93ed5ad085 | ||
|  | 41f23386b2 | ||
|  | c91644b829 | ||
|  | 073fd16bd7 | ||
|  | f92ee770e0 | ||
|  | 1e6d52357e | ||
|  | 751ded44f3 | ||
|  | 8567f3e34e | ||
|  | 83f2514403 | ||
|  | ad6ac7222c | ||
|  | 3ae1952624 | ||
|  | 3db549af40 | ||
|  | 94179ae552 | ||
|  | 7f35e87ed8 | ||
|  | 00da0009ef | ||
|  | cffc30afa3 | ||
|  | 24cf1d9284 | ||
|  | 9296e6987d | ||
|  | 809fa85706 | ||
|  | b3ae7605d3 | ||
|  | 864ec4737d | ||
|  | 854d0bcf20 | ||
|  | 458e387b68 | ||
|  | 56c770c49d | ||
|  | 946447394d | ||
|  | 44ba3273cb | ||
|  | 0f7b9d5e2b | ||
|  | 8a3f66db7b | ||
|  | 0eaa327d47 | ||
|  | 08e0cf5ad5 | ||
|  | d7aea9d11c | ||
|  | 135ce77288 | ||
|  | 19141a73d2 | ||
|  | 9d1051b0bd | ||
|  | c46a5920e5 | ||
|  | 43ac23f113 | ||
|  | 13f6cd8ef4 | ||
|  | 0e6d289128 | ||
|  | bba68bff29 | ||
|  | 6e0cce4d49 | ||
|  | d3ebe95076 | ||
|  | cbda4a38a3 | ||
|  | 3318041b92 | ||
|  | af53ec7625 | ||
|  | de2829fde7 | ||
|  | c1bee4046c | ||
|  | 473095b01b | ||
|  | e6abf93457 | ||
|  | 882f281482 | ||
|  | 0b2f68ac04 | ||
|  | 2ca2b766f8 | ||
|  | da611fb10b | ||
|  | eb8e49e23c | ||
|  | 0907d38c06 | ||
|  | 2a9b725c6a | ||
|  | 8f24a94ed3 | ||
|  | 4eefc95baa | ||
|  | 1681c34a52 | ||
|  | 47ab0184b7 | ||
|  | 58591f660a | ||
|  | 3c7e1cf442 | ||
|  | 055d4cce33 | ||
|  | a3dfe61a7b | ||
|  | f9d47c081f | ||
|  | ff5bf62989 | ||
|  | 1f6d079644 | ||
|  | 5c085a1986 | ||
|  | 9a23817473 | ||
|  | 56ea8937f6 | ||
|  | 4f51263501 | ||
|  | bb2eab60f4 | ||
|  | 44e4c04811 | ||
|  | b5839eab26 | ||
|  | 780ac75bf6 | ||
|  | a252138594 | ||
|  | 270a055072 | ||
|  | 08e194efe9 | ||
|  | 5f6caab338 | ||
|  | 5aaa318142 | ||
|  | cebbef680f | ||
|  | 0abde46ef4 | ||
|  | f2b518ed26 | ||
|  | c6207f35e1 | ||
|  | ee8fa04814 | ||
|  | 7b746fa053 | ||
|  | b7fea53107 | ||
|  | f89f3e6a38 | ||
|  | a0da2f6e16 | ||
|  | 3b5380e0d1 | ||
|  | 35276bfe41 | ||
|  | 215c1ecbd9 | ||
|  | 1698b21d7a | ||
|  | ca1e66be47 | ||
|  | 22bf2823e8 | ||
|  | 32e98f1b3a | ||
|  | c1c4335ce7 | ||
|  | 6c50662280 | ||
|  | f3a1707b94 | ||
|  | 6ea755f2a8 | ||
|  | a989b44a15 | ||
|  | 40f8587fd6 | ||
|  | 9f5638f16d | ||
|  | 9b19f96ff6 | ||
|  | 15da557892 | ||
|  | 2d23c9a2e6 | ||
|  | ab49afd3db | ||
|  | 86a370fd69 | ||
|  | 36fc74ce07 | ||
|  | 8da8843fd0 | ||
|  | f68285fbe5 | ||
|  | 85b8ef8f88 | ||
|  | 3d48aa8bbe | ||
|  | a765da6e28 | ||
|  | c57640acd0 | ||
|  | c264216053 | ||
|  | 9d3c732993 | ||
|  | 34f023c4b1 | ||
|  | 5a4f842774 | ||
|  | bae1767141 | ||
|  | 5957833a4f | ||
|  | 397092c21f | ||
|  | f309003e67 | ||
|  | eaf3678758 | ||
|  | f2e82da7c8 | ||
|  | 211ae1f905 | ||
|  | db629593c6 | ||
|  | 80d58cce2b | ||
|  | a0f55aca69 | ||
|  | d203a3586c | ||
|  | f74a6424d0 | ||
|  | 209ef3d890 | ||
|  | b549b32cbb | ||
|  | 54e2cb51cf | ||
|  | 42e6de395f | 
							
								
								
									
										8
									
								
								.env
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								.env
									
									
									
									
									
								
							| @@ -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 | ||||||
|   | |||||||
| @@ -1 +1,2 @@ | |||||||
| VITE_HTTP_PROXY=Y | VITE_HTTP_PROXY=Y | ||||||
|  | VITE_SOYBEAN_ROUTE_PLUGIN=Y | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -1,4 +1,3 @@ | |||||||
| !.env-config.ts | !.env-config.ts | ||||||
| components.d.ts |  | ||||||
| router-page.d.ts | router-page.d.ts | ||||||
| *.svg |  | ||||||
|   | |||||||
| @@ -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 | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   ], |   ], | ||||||
|   | |||||||
							
								
								
									
										16
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										16
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							| @@ -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
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -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
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								.npmrc
									
									
									
									
									
								
							| @@ -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 |  | ||||||
|   | |||||||
							
								
								
									
										14
									
								
								.vscode/extensions.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								.vscode/extensions.json
									
									
									
									
										vendored
									
									
								
							| @@ -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
									
									
								
							
							
						
						
									
										8
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
								
							| @@ -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
									
									
								
							
							
						
						
									
										121
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							| @@ -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" |  | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										1393
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										1393
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										61
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										61
									
								
								README.md
									
									
									
									
									
								
							| @@ -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 @@ | |||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -68,6 +83,12 @@ | |||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | <div align="center"> | ||||||
|  | 	<img style="width:380px;margin-right:18px;border:1px solid #dedede;" src="https://s2.loli.net/2023/06/07/A5Nonc9vI6pB1lr.png" /> | ||||||
|  | 	  | ||||||
|  | 	<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) 协议,仅供参考学习,商用时请保留作者的版权信息,作者不对软件做担保和负责。 | ||||||
|   | |||||||
| @@ -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 |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   }); |  | ||||||
| }; |  | ||||||
| @@ -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; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -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(); | ||||||
|  | 		` | ||||||
|  |   }); | ||||||
|  | }; | ||||||
|   | |||||||
| @@ -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__' | ||||||
|     }) |     }) | ||||||
|   | |||||||
| @@ -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 |  | ||||||
| } |  | ||||||
| @@ -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"> | ||||||
|   | |||||||
| @@ -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 | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   ] |   ] | ||||||
|   | |||||||
							
								
								
									
										151
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										151
									
								
								package.json
									
									
									
									
									
								
							| @@ -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 | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -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
									
									
									
								
							
							
						
						
									
										10028
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -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 | 
| @@ -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 | ||||||
| }); | }); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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> | ||||||
|   | |||||||
| @@ -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> | ||||||
|   | |||||||
| @@ -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'" /> | ||||||
|   | |||||||
| @@ -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> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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>(), { | ||||||
|   | |||||||
| @@ -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> | ||||||
|   | |||||||
| @@ -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 */ | ||||||
|   | |||||||
| @@ -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(); | ||||||
|  |   }); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -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'; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 图标渲染 |  * 图标渲染 | ||||||
|   | |||||||
| @@ -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'; | ||||||
|   | |||||||
| @@ -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, | ||||||
|   | |||||||
| @@ -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(); | ||||||
|   | |||||||
							
								
								
									
										50
									
								
								src/composables/websocket.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								src/composables/websocket.ts
									
									
									
									
									
										Normal 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 | ||||||
|  |   }; | ||||||
|  | } | ||||||
| @@ -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
									
								
							
							
						
						
									
										6
									
								
								src/constants/_shared.ts
									
									
									
									
									
										Normal 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>[]; | ||||||
|  | } | ||||||
| @@ -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'] } |  | ||||||
| ]; |  | ||||||
|   | |||||||
| @@ -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'] |  | ||||||
|   } |  | ||||||
| ]; |  | ||||||
|   | |||||||
							
								
								
									
										180
									
								
								src/hooks/business/use-hook-table.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										180
									
								
								src/hooks/business/use-hook-table.ts
									
									
									
									
									
										Normal 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 | ||||||
|  |   }; | ||||||
|  | } | ||||||
| @@ -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 |  | ||||||
|   }; |  | ||||||
| } |  | ||||||
| @@ -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> | ||||||
|   | |||||||
| @@ -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> |  | ||||||
| @@ -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> | ||||||
|   | |||||||
| @@ -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> | ||||||
|   | |||||||
| @@ -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) { | ||||||
|   | |||||||
| @@ -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) { | ||||||
|   | |||||||
| @@ -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 | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -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 }"> | ||||||
|   | |||||||
| @@ -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> | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										39
									
								
								src/layouts/common/global-header/components/toggle-lang.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								src/layouts/common/global-header/components/toggle-lang.vue
									
									
									
									
									
										Normal 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> | ||||||
| @@ -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' }); | ||||||
|   | |||||||
| @@ -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> | ||||||
|   | |||||||
| @@ -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> | ||||||
|   | |||||||
| @@ -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> | ||||||
|   | |||||||
| @@ -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' : '' | ||||||
|   | |||||||
| @@ -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; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -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); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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; | ||||||
|   }); |   }); | ||||||
|   | |||||||
| @@ -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[]>([]); | ||||||
|   | |||||||
| @@ -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); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -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' }); | ||||||
|   | |||||||
| @@ -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 }; | ||||||
|   | |||||||
| @@ -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' }); | ||||||
|   | |||||||
| @@ -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> | ||||||
|   | |||||||
| @@ -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' }); | ||||||
|   | |||||||
| @@ -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' }); | ||||||
|   | |||||||
| @@ -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' }); | ||||||
|   | |||||||
| @@ -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' }); | ||||||
|   | |||||||
| @@ -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') | ||||||
|     }); |     }); | ||||||
|   }); |   }); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -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' }); | ||||||
|   | |||||||
| @@ -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; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -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' | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -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
									
								
							
							
						
						
									
										219
									
								
								src/locales/lang/km-KH.ts
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										219
									
								
								src/locales/lang/zh-CN.ts
									
									
									
									
									
										Normal 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; | ||||||
| @@ -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
									
								
							
							
						
						
									
										11
									
								
								src/locales/locale.ts
									
									
									
									
									
										Normal 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; | ||||||
| @@ -29,6 +29,8 @@ async function setupApp() { | |||||||
|  |  | ||||||
|   setupI18n(app); |   setupI18n(app); | ||||||
|  |  | ||||||
|  |   appLoading.unmount(); | ||||||
|  |  | ||||||
|   // mount app |   // mount app | ||||||
|   app.mount('#app'); |   app.mount('#app'); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -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() { | ||||||
|  |   // | ||||||
|  | } | ||||||
|   | |||||||
| @@ -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(); | ||||||
|   }); |   }); | ||||||
|   | |||||||
| @@ -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; | ||||||
|   | |||||||
| @@ -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 | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -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 | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -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' | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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 | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -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 | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -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 | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -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 | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -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); | ||||||
|   | |||||||
| @@ -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, | ||||||
|   | |||||||
| @@ -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, | ||||||
|   | |||||||
| @@ -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; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| }); | }); | ||||||
|   | |||||||
| @@ -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
		Reference in New Issue
	
	Block a user