mirror of
https://github.com/pure-admin/vue-pure-admin.git
synced 2025-11-09 13:53:38 +08:00
Compare commits
16 Commits
915e01c15c
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
244211c4eb | ||
|
|
e01ad0a5df | ||
|
|
ac61eb807b | ||
|
|
68decd01b8 | ||
|
|
c0fd7419c5 | ||
|
|
6b179e6ff1 | ||
|
|
e1fde7d386 | ||
|
|
fc30039a40 | ||
|
|
880963c683 | ||
|
|
36ec0ebd0d | ||
|
|
339d68ffc5 | ||
|
|
fa606b429b | ||
|
|
5b14db8785 | ||
|
|
0c53e84ee7 | ||
|
|
bf1f5b9f3f | ||
|
|
faf24f300b |
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"tailwindCSS.experimental.configFile": "src/style/tailwind.css",
|
||||||
"editor.formatOnType": true,
|
"editor.formatOnType": true,
|
||||||
"editor.formatOnSave": true,
|
"editor.formatOnSave": true,
|
||||||
"[vue]": {
|
"[vue]": {
|
||||||
|
|||||||
@@ -1,3 +1,23 @@
|
|||||||
|
# 6.2.0 (2025-10-16)
|
||||||
|
|
||||||
|
### 🎫 Features
|
||||||
|
|
||||||
|
- Added full-screen `403`, `404`, and `500` error pages. These full-screen error pages are clear and secure, improving the user experience.
|
||||||
|
|
||||||
|
### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- Fixed an issue where the built-in homepage did not have a `name` configured, causing cache invalidation after setting the page cache.
|
||||||
|
- Fixed an issue where, in an embedded same-origin `iframe` page, when the `beforeunload` event was registered, right-clicking a tab and reloading it would cause the browser to prompt two confirmation blocks.
|
||||||
|
- Fixed an issue where pages with `keepAlive: true` set to cache invalidation when the initial load was slow.
|
||||||
|
- Fixed an issue where multiple tabs could be activated simultaneously when using the same parameters in different routes.
|
||||||
|
- Fixed an issue where the right-click menu on a tab displayed incorrectly when passing `params` parameters.
|
||||||
|
|
||||||
|
### 🍏 Perf
|
||||||
|
|
||||||
|
- Optimized the `nprogress` progress bar. It no longer displays when reloading a page or requesting an interface, improving the user experience.
|
||||||
|
- Optimized the timing of capturing all unmatched routes and redirecting to a full-screen `404` page.
|
||||||
|
- Explicitly configured the `Tailwind CSS` entry file path to improve the contextual recognition and prompting performance of the `Tailwind CSS IntelliSense` plugin
|
||||||
|
|
||||||
# 6.1.0 (2025-07-31)
|
# 6.1.0 (2025-07-31)
|
||||||
|
|
||||||
### ✔️ Refactor
|
### ✔️ Refactor
|
||||||
|
|||||||
20
CHANGELOG.md
20
CHANGELOG.md
@@ -1,3 +1,23 @@
|
|||||||
|
# 6.2.0 (2025-10-16)
|
||||||
|
|
||||||
|
### 🎫 Features
|
||||||
|
|
||||||
|
- Added full-screen `403`, `404`, and `500` error pages. These full-screen error pages are clear and secure, improving the user experience.
|
||||||
|
|
||||||
|
### 🐞 Bug Fixes
|
||||||
|
|
||||||
|
- Fixed an issue where the built-in homepage did not have a `name` configured, causing cache invalidation after setting the page cache.
|
||||||
|
- Fixed an issue where, in an embedded same-origin `iframe` page, when the `beforeunload` event was registered, right-clicking a tab and reloading it would cause the browser to prompt two confirmation blocks.
|
||||||
|
- Fixed an issue where pages with `keepAlive: true` set to cache invalidation when the initial load was slow.
|
||||||
|
- Fixed an issue where multiple tabs could be activated simultaneously when using the same parameters in different routes.
|
||||||
|
- Fixed an issue where the right-click menu on a tab displayed incorrectly when passing `params` parameters.
|
||||||
|
|
||||||
|
### 🍏 Perf
|
||||||
|
|
||||||
|
- Optimized the `nprogress` progress bar. It no longer displays when reloading a page or requesting an interface, improving the user experience.
|
||||||
|
- Optimized the timing of capturing all unmatched routes and redirecting to a full-screen `404` page.
|
||||||
|
- Explicitly configured the `Tailwind CSS` entry file path to improve the contextual recognition and prompting performance of the `Tailwind CSS IntelliSense` plugin
|
||||||
|
|
||||||
# 6.1.0 (2025-07-31)
|
# 6.1.0 (2025-07-31)
|
||||||
|
|
||||||
### ✔️ Refactor
|
### ✔️ Refactor
|
||||||
|
|||||||
@@ -1,3 +1,23 @@
|
|||||||
|
# 6.2.0 (2025-10-16)
|
||||||
|
|
||||||
|
### 🎫 Feat
|
||||||
|
|
||||||
|
- 添加全屏`403`、`404`、`500`页面,全屏错误页面清晰且安全,提升用户体验
|
||||||
|
|
||||||
|
### 🐞 Bug fixes
|
||||||
|
|
||||||
|
- 修复内置的首页未设置`name`导致设置页面缓存后缓存无效的问题
|
||||||
|
- 修复在内嵌同源`iframe`页面中,当其注册了`beforeunload`事件时,右键标签页点击重新加载导致浏览器弹出两次确认拦截的问题
|
||||||
|
- 修复设置了`keepAlive: true`的页面在初次加载缓慢的情况下出现的页面缓存失效的问题
|
||||||
|
- 修复不同路由使用相同参数时,多个标签页会同时被激活的问题
|
||||||
|
- 修复`params`传参模式下标签页右键菜单显示不正确的问题
|
||||||
|
|
||||||
|
### 🍏 Perf
|
||||||
|
|
||||||
|
- 优化`nprogress`进度条,页面重进或接口请求时不再显示进度条,提升用户体验
|
||||||
|
- 优化当捕获所有未匹配路由并跳转全屏`404`页面的时机
|
||||||
|
- 显式配置`Tailwind CSS`入口文件路径,优化`Tailwind CSS IntelliSense`插件的上下文识别与提示性能
|
||||||
|
|
||||||
# 6.1.0 (2025-07-31)
|
# 6.1.0 (2025-07-31)
|
||||||
|
|
||||||
### ✔️ Refactor
|
### ✔️ Refactor
|
||||||
|
|||||||
@@ -80,9 +80,9 @@ menus:
|
|||||||
pureMarkdown: Markdown
|
pureMarkdown: Markdown
|
||||||
pureEditor: Editor
|
pureEditor: Editor
|
||||||
pureAbnormal: Abnormal Page
|
pureAbnormal: Abnormal Page
|
||||||
pureFourZeroFour: "404"
|
purePageNotFound: "404"
|
||||||
pureFourZeroOne: "403"
|
pureAccessDenied: "403"
|
||||||
pureFive: "500"
|
pureServerError: "500"
|
||||||
pureComponents: Components
|
pureComponents: Components
|
||||||
pureDialog: Dialog
|
pureDialog: Dialog
|
||||||
pureDrawer: Drawer
|
pureDrawer: Drawer
|
||||||
|
|||||||
@@ -80,9 +80,9 @@ menus:
|
|||||||
pureMarkdown: Markdown
|
pureMarkdown: Markdown
|
||||||
pureEditor: 编辑器
|
pureEditor: 编辑器
|
||||||
pureAbnormal: 异常页面
|
pureAbnormal: 异常页面
|
||||||
pureFourZeroFour: "404"
|
purePageNotFound: "404"
|
||||||
pureFourZeroOne: "403"
|
pureAccessDenied: "403"
|
||||||
pureFive: "500"
|
pureServerError: "500"
|
||||||
pureComponents: 组件
|
pureComponents: 组件
|
||||||
pureDialog: 函数式弹框
|
pureDialog: 函数式弹框
|
||||||
pureDrawer: 函数式抽屉
|
pureDrawer: 函数式抽屉
|
||||||
|
|||||||
60
package.json
60
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "vue-pure-admin",
|
"name": "vue-pure-admin",
|
||||||
"version": "6.1.0",
|
"version": "6.2.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -56,7 +56,7 @@
|
|||||||
"@pureadmin/table": "^3.3.0",
|
"@pureadmin/table": "^3.3.0",
|
||||||
"@pureadmin/utils": "^2.6.2",
|
"@pureadmin/utils": "^2.6.2",
|
||||||
"@vue-flow/background": "^1.3.2",
|
"@vue-flow/background": "^1.3.2",
|
||||||
"@vue-flow/core": "^1.46.4",
|
"@vue-flow/core": "^1.47.0",
|
||||||
"@vueuse/core": "^13.9.0",
|
"@vueuse/core": "^13.9.0",
|
||||||
"@vueuse/motion": "^3.0.3",
|
"@vueuse/motion": "^3.0.3",
|
||||||
"@wangeditor/editor": "^5.1.23",
|
"@wangeditor/editor": "^5.1.23",
|
||||||
@@ -70,9 +70,9 @@
|
|||||||
"cropperjs": "^1.6.2",
|
"cropperjs": "^1.6.2",
|
||||||
"dayjs": "^1.11.18",
|
"dayjs": "^1.11.18",
|
||||||
"deep-chat": "^2.2.2",
|
"deep-chat": "^2.2.2",
|
||||||
"echarts": "^5.6.0",
|
"echarts": "^6.0.0",
|
||||||
"el-table-infinite-scroll": "^3.0.7",
|
"el-table-infinite-scroll": "^3.0.7",
|
||||||
"element-plus": "^2.11.2",
|
"element-plus": "^2.11.7",
|
||||||
"highlight.js": "^11.11.1",
|
"highlight.js": "^11.11.1",
|
||||||
"intro.js": "^7.2.0",
|
"intro.js": "^7.2.0",
|
||||||
"js-cookie": "^3.0.5",
|
"js-cookie": "^3.0.5",
|
||||||
@@ -90,13 +90,13 @@
|
|||||||
"qs": "^6.14.0",
|
"qs": "^6.14.0",
|
||||||
"responsive-storage": "^2.2.0",
|
"responsive-storage": "^2.2.0",
|
||||||
"sortablejs": "^1.15.6",
|
"sortablejs": "^1.15.6",
|
||||||
"swiper": "^11.2.10",
|
"swiper": "^12.0.2",
|
||||||
"typeit": "^8.8.7",
|
"typeit": "^8.8.7",
|
||||||
"v-contextmenu": "^3.2.0",
|
"v-contextmenu": "^3.2.0",
|
||||||
"v3-infinite-loading": "^1.3.2",
|
"v3-infinite-loading": "^1.3.2",
|
||||||
"vditor": "^3.11.2",
|
"vditor": "^3.11.2",
|
||||||
"version-rocket": "^1.7.4",
|
"version-rocket": "^1.7.4",
|
||||||
"vue": "^3.5.21",
|
"vue": "^3.5.22",
|
||||||
"vue-i18n": "^11.1.12",
|
"vue-i18n": "^11.1.12",
|
||||||
"vue-json-pretty": "^2.5.0",
|
"vue-json-pretty": "^2.5.0",
|
||||||
"vue-pdf-embed": "^2.1.3",
|
"vue-pdf-embed": "^2.1.3",
|
||||||
@@ -109,25 +109,25 @@
|
|||||||
"vue3-puzzle-vcode": "^1.1.7",
|
"vue3-puzzle-vcode": "^1.1.7",
|
||||||
"vuedraggable": "^4.1.0",
|
"vuedraggable": "^4.1.0",
|
||||||
"vxe-table": "4.6.25",
|
"vxe-table": "4.6.25",
|
||||||
"wavesurfer.js": "^7.10.1",
|
"wavesurfer.js": "^7.11.0",
|
||||||
"xgplayer": "^3.0.23",
|
"xgplayer": "^3.0.23",
|
||||||
"xlsx": "^0.18.5"
|
"xlsx": "^0.18.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@commitlint/cli": "^19.8.1",
|
"@commitlint/cli": "^20.1.0",
|
||||||
"@commitlint/config-conventional": "^19.8.1",
|
"@commitlint/config-conventional": "^20.0.0",
|
||||||
"@commitlint/types": "^19.8.1",
|
"@commitlint/types": "^20.0.0",
|
||||||
"@eslint/js": "^9.35.0",
|
"@eslint/js": "^9.37.0",
|
||||||
"@faker-js/faker": "^9.9.0",
|
"@faker-js/faker": "^10.0.0",
|
||||||
"@iconify/json": "^2.2.384",
|
"@iconify/json": "^2.2.393",
|
||||||
"@iconify/vue": "4.2.0",
|
"@iconify/vue": "4.2.0",
|
||||||
"@intlify/unplugin-vue-i18n": "^6.0.8",
|
"@intlify/unplugin-vue-i18n": "^11.0.1",
|
||||||
"@tailwindcss/vite": "^4.1.13",
|
"@tailwindcss/vite": "^4.1.14",
|
||||||
"@types/codemirror": "^5.60.16",
|
"@types/codemirror": "^5.60.16",
|
||||||
"@types/dagre": "^0.7.53",
|
"@types/dagre": "^0.7.53",
|
||||||
"@types/intro.js": "^5.1.5",
|
"@types/intro.js": "^5.1.5",
|
||||||
"@types/js-cookie": "^3.0.6",
|
"@types/js-cookie": "^3.0.6",
|
||||||
"@types/node": "^20.19.14",
|
"@types/node": "^20.19.19",
|
||||||
"@types/nprogress": "^0.2.3",
|
"@types/nprogress": "^0.2.3",
|
||||||
"@types/path-browserify": "^1.0.3",
|
"@types/path-browserify": "^1.0.3",
|
||||||
"@types/qrcode": "^1.5.5",
|
"@types/qrcode": "^1.5.5",
|
||||||
@@ -136,35 +136,35 @@
|
|||||||
"@vitejs/plugin-vue": "^6.0.1",
|
"@vitejs/plugin-vue": "^6.0.1",
|
||||||
"@vitejs/plugin-vue-jsx": "^5.1.1",
|
"@vitejs/plugin-vue-jsx": "^5.1.1",
|
||||||
"boxen": "^8.0.1",
|
"boxen": "^8.0.1",
|
||||||
"code-inspector-plugin": "^1.2.8",
|
"code-inspector-plugin": "^1.2.10",
|
||||||
"cssnano": "^7.1.1",
|
"cssnano": "^7.1.1",
|
||||||
"dagre": "^0.8.5",
|
"dagre": "^0.8.5",
|
||||||
"eslint": "^9.35.0",
|
"eslint": "^9.37.0",
|
||||||
"eslint-config-prettier": "^10.1.8",
|
"eslint-config-prettier": "^10.1.8",
|
||||||
"eslint-plugin-prettier": "^5.5.4",
|
"eslint-plugin-prettier": "^5.5.4",
|
||||||
"eslint-plugin-vue": "^10.4.0",
|
"eslint-plugin-vue": "^10.5.0",
|
||||||
"gradient-string": "^3.0.0",
|
"gradient-string": "^3.0.0",
|
||||||
"husky": "^9.1.7",
|
"husky": "^9.1.7",
|
||||||
"lint-staged": "^16.1.6",
|
"lint-staged": "^16.2.3",
|
||||||
"postcss": "^8.5.6",
|
"postcss": "^8.5.6",
|
||||||
"postcss-html": "^1.8.0",
|
"postcss-html": "^1.8.0",
|
||||||
"postcss-load-config": "^6.0.1",
|
"postcss-load-config": "^6.0.1",
|
||||||
"postcss-scss": "^4.0.9",
|
"postcss-scss": "^4.0.9",
|
||||||
"prettier": "^3.6.2",
|
"prettier": "^3.6.2",
|
||||||
"rimraf": "^6.0.1",
|
"rimraf": "^6.0.1",
|
||||||
"rollup-plugin-visualizer": "^6.0.3",
|
"rollup-plugin-visualizer": "^6.0.4",
|
||||||
"sass": "^1.92.1",
|
"sass": "^1.93.2",
|
||||||
"stylelint": "^16.24.0",
|
"stylelint": "^16.25.0",
|
||||||
"stylelint-config-recess-order": "^7.3.0",
|
"stylelint-config-recess-order": "^7.3.0",
|
||||||
"stylelint-config-recommended-vue": "^1.6.1",
|
"stylelint-config-recommended-vue": "^1.6.1",
|
||||||
"stylelint-config-standard-scss": "^14.0.0",
|
"stylelint-config-standard-scss": "^14.0.0",
|
||||||
"stylelint-prettier": "^5.0.3",
|
"stylelint-prettier": "^5.0.3",
|
||||||
"svgo": "^4.0.0",
|
"svgo": "^4.0.0",
|
||||||
"tailwindcss": "^4.1.13",
|
"tailwindcss": "^4.1.14",
|
||||||
"typescript": "^5.9.2",
|
"typescript": "^5.9.3",
|
||||||
"typescript-eslint": "^8.43.0",
|
"typescript-eslint": "^8.46.0",
|
||||||
"unplugin-icons": "^22.3.0",
|
"unplugin-icons": "^22.4.2",
|
||||||
"vite": "^7.1.5",
|
"vite": "^7.1.9",
|
||||||
"vite-plugin-cdn-import": "^1.0.1",
|
"vite-plugin-cdn-import": "^1.0.1",
|
||||||
"vite-plugin-compression": "^0.5.1",
|
"vite-plugin-compression": "^0.5.1",
|
||||||
"vite-plugin-fake-server": "^2.2.0",
|
"vite-plugin-fake-server": "^2.2.0",
|
||||||
@@ -172,10 +172,10 @@
|
|||||||
"vite-plugin-router-warn": "^1.0.0",
|
"vite-plugin-router-warn": "^1.0.0",
|
||||||
"vite-svg-loader": "^5.1.0",
|
"vite-svg-loader": "^5.1.0",
|
||||||
"vue-eslint-parser": "^10.2.0",
|
"vue-eslint-parser": "^10.2.0",
|
||||||
"vue-tsc": "^3.0.7"
|
"vue-tsc": "^3.1.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^20.19.0 || >=22.12.0",
|
"node": "^20.19.0 || >=22.13.0",
|
||||||
"pnpm": ">=9"
|
"pnpm": ">=9"
|
||||||
},
|
},
|
||||||
"pnpm": {
|
"pnpm": {
|
||||||
|
|||||||
2359
pnpm-lock.yaml
generated
2359
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"Version": "6.1.0",
|
"Version": "6.2.0",
|
||||||
"Title": "PureAdmin",
|
"Title": "PureAdmin",
|
||||||
"FixedHeader": true,
|
"FixedHeader": true,
|
||||||
"HiddenSideBar": false,
|
"HiddenSideBar": false,
|
||||||
|
|||||||
@@ -35,8 +35,20 @@ type DialogProps = {
|
|||||||
top?: string;
|
top?: string;
|
||||||
/** 是否需要遮罩层,默认 `true` */
|
/** 是否需要遮罩层,默认 `true` */
|
||||||
modal?: boolean;
|
modal?: boolean;
|
||||||
|
/** 是否允许穿透遮罩层,默认 `false`。使用时需将 `modal` 属性设置为 `false` */
|
||||||
|
modalPenetrable?: boolean;
|
||||||
|
/** 遮罩的自定义类名 */
|
||||||
|
modalClass?: string;
|
||||||
|
/** `header` 部分的自定义 `class` 名 */
|
||||||
|
headerClass?: string;
|
||||||
|
/** `body` 部分的自定义 `class` 名 */
|
||||||
|
bodyClass?: string;
|
||||||
|
/** `footer` 部分的自定义 `class` 名 */
|
||||||
|
footerClass?: string;
|
||||||
/** `Dialog` 自身是否插入至 `body` 元素上。嵌套的 `Dialog` 必须指定该属性并赋值为 `true`,默认 `false` */
|
/** `Dialog` 自身是否插入至 `body` 元素上。嵌套的 `Dialog` 必须指定该属性并赋值为 `true`,默认 `false` */
|
||||||
appendToBody?: boolean;
|
appendToBody?: boolean;
|
||||||
|
/** `Dialog` 挂载到哪个 `DOM` 元素,该属性会覆盖 `append-to-body` 属性,默认 `body` */
|
||||||
|
appendTo?: string | HTMLElement;
|
||||||
/** 是否在 `Dialog` 出现时将 `body` 滚动锁定,默认 `true` */
|
/** 是否在 `Dialog` 出现时将 `body` 滚动锁定,默认 `true` */
|
||||||
lockScroll?: boolean;
|
lockScroll?: boolean;
|
||||||
/** `Dialog` 的自定义类名 */
|
/** `Dialog` 的自定义类名 */
|
||||||
@@ -57,12 +69,22 @@ type DialogProps = {
|
|||||||
beforeClose?: (done: DoneFn) => void;
|
beforeClose?: (done: DoneFn) => void;
|
||||||
/** 为 `Dialog` 启用可拖拽功能,默认 `false` */
|
/** 为 `Dialog` 启用可拖拽功能,默认 `false` */
|
||||||
draggable?: boolean;
|
draggable?: boolean;
|
||||||
|
/** 拖动范围可以超出可视区,默认 `false` */
|
||||||
|
overflow?: boolean;
|
||||||
/** 是否让 `Dialog` 的 `header` 和 `footer` 部分居中排列,默认 `false` */
|
/** 是否让 `Dialog` 的 `header` 和 `footer` 部分居中排列,默认 `false` */
|
||||||
center?: boolean;
|
center?: boolean;
|
||||||
/** 是否水平垂直对齐对话框,默认 `false` */
|
/** 是否水平垂直对齐对话框,默认 `false` */
|
||||||
alignCenter?: boolean;
|
alignCenter?: boolean;
|
||||||
/** 当关闭 `Dialog` 时,销毁其中的元素,默认 `false` */
|
/** 当关闭 `Dialog` 时,销毁其中的元素,默认 `false` */
|
||||||
destroyOnClose?: boolean;
|
destroyOnClose?: boolean;
|
||||||
|
/** 自定义关闭图标,默认 `Close` */
|
||||||
|
closeIcon?: string | Component;
|
||||||
|
/** 和原生的 `CSS` 的 `z-index` 相同,改变 `z` 轴的顺序 */
|
||||||
|
zIndex?: number;
|
||||||
|
/** `header` 的 `aria-level` 属性 */
|
||||||
|
headerAriaLevel?: string;
|
||||||
|
/** 对话框动画的自定义过渡配置。可以是一个字符串(过渡名称),也可以是一个包含 `Vue` 过渡属性的对象,默认 `dialog-fade` */
|
||||||
|
transition?: string | object;
|
||||||
};
|
};
|
||||||
|
|
||||||
//element-plus.org/zh-CN/component/popconfirm.html#attributes
|
//element-plus.org/zh-CN/component/popconfirm.html#attributes
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ type ArgsType = {
|
|||||||
/** `cancel` 点击取消按钮、`sure` 点击确定按钮、`close` 点击右上角关闭按钮或空白页或按下了 `esc` 键 */
|
/** `cancel` 点击取消按钮、`sure` 点击确定按钮、`close` 点击右上角关闭按钮或空白页或按下了 `esc` 键 */
|
||||||
command: "cancel" | "sure" | "close";
|
command: "cancel" | "sure" | "close";
|
||||||
};
|
};
|
||||||
|
|
||||||
type ButtonType =
|
type ButtonType =
|
||||||
| "primary"
|
| "primary"
|
||||||
| "success"
|
| "success"
|
||||||
@@ -20,11 +19,11 @@ type DrawerProps = {
|
|||||||
visible?: boolean;
|
visible?: boolean;
|
||||||
/** `Drawer` 自身是否插入至 `body` 元素上。嵌套的 `Drawer` 必须指定该属性并赋值为 `true`,默认 `false` */
|
/** `Drawer` 自身是否插入至 `body` 元素上。嵌套的 `Drawer` 必须指定该属性并赋值为 `true`,默认 `false` */
|
||||||
appendToBody?: boolean;
|
appendToBody?: boolean;
|
||||||
/** 挂载到哪个 `DOM` 元素 将覆盖 `appendToBody` */
|
/** 挂载到哪个 `DOM` 元素,会覆盖 `appendToBody` 属性,默认 `body` */
|
||||||
appendTo?: string;
|
appendTo?: string;
|
||||||
/** 是否在 `Drawer` 出现时将 `body` 滚动锁定,默认 `true` */
|
/** 是否在 `Drawer` 出现时将 `body` 滚动锁定,默认 `true` */
|
||||||
lockScroll?: boolean;
|
lockScroll?: boolean;
|
||||||
/** 关闭前的回调,会暂停 `Drawer` 的关闭 回调函数内执行 `done` 参数方法的时候才是真正关闭对话框的时候 */
|
/** 关闭前的回调,会暂停 `Drawer` 的关闭,回调函数内执行 `done` 参数方法的时候才是真正关闭对话框的时候 */
|
||||||
beforeClose?: (done: DoneFn) => void;
|
beforeClose?: (done: DoneFn) => void;
|
||||||
/** 是否可以通过点击 `modal` 关闭 `Drawer` ,默认 `true` */
|
/** 是否可以通过点击 `modal` 关闭 `Drawer` ,默认 `true` */
|
||||||
closeOnClickModal?: boolean;
|
closeOnClickModal?: boolean;
|
||||||
@@ -44,9 +43,13 @@ type DrawerProps = {
|
|||||||
destroyOnClose?: boolean;
|
destroyOnClose?: boolean;
|
||||||
/** 是否需要遮罩层,默认 `true` */
|
/** 是否需要遮罩层,默认 `true` */
|
||||||
modal?: boolean;
|
modal?: boolean;
|
||||||
|
/** 是否允许穿透遮罩层,默认 `false`。使用时需将 `modal` 属性设置为 `false` */
|
||||||
|
modalPenetrable?: boolean;
|
||||||
/** `Drawer` 打开的方向,默认 `rtl` */
|
/** `Drawer` 打开的方向,默认 `rtl` */
|
||||||
direction?: "rtl" | "ltr" | "ttb" | "btt";
|
direction?: "rtl" | "ltr" | "ttb" | "btt";
|
||||||
/** `Drawer` 窗体的大小, 当使用 `number` 类型时, 以像素为单位, 当使用 `string` 类型时, 请传入 `'x%'`, 否则便会以 `number` 类型解释 */
|
/** 是否启用可调整大小的功能,默认 `false` */
|
||||||
|
resizable?: boolean;
|
||||||
|
/** `Drawer` 窗体的大小, 当使用 `number` 类型时, 以像素为单位, 当使用 `string` 类型时, 请传入 `'x%'`, 否则便会以 `number` 类型解释,默认 `30%` */
|
||||||
size?: string | number;
|
size?: string | number;
|
||||||
/** `Drawer` 的标题 */
|
/** `Drawer` 的标题 */
|
||||||
title?: string;
|
title?: string;
|
||||||
@@ -54,6 +57,12 @@ type DrawerProps = {
|
|||||||
withHeader?: boolean;
|
withHeader?: boolean;
|
||||||
/** 遮罩层的自定义类名 */
|
/** 遮罩层的自定义类名 */
|
||||||
modalClass?: string;
|
modalClass?: string;
|
||||||
|
/** `header` 部分的自定义 `class` 名 */
|
||||||
|
headerClass?: string;
|
||||||
|
/** `body` 部分的自定义 `class` 名 */
|
||||||
|
bodyClass?: string;
|
||||||
|
/** `footer` 部分的自定义 `class` 名 */
|
||||||
|
footerClass?: string;
|
||||||
/** 设置 `z-index` */
|
/** 设置 `z-index` */
|
||||||
zIndex?: number;
|
zIndex?: number;
|
||||||
/** `header` 的 `aria-level` 属性,默认 `2` */
|
/** `header` 的 `aria-level` 属性,默认 `2` */
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ export default defineComponent({
|
|||||||
"pt-[3px]",
|
"pt-[3px]",
|
||||||
"px-[11px]",
|
"px-[11px]",
|
||||||
"border-b-[1px]",
|
"border-b-[1px]",
|
||||||
"border-solid",
|
"border-b-solid",
|
||||||
"border-[#dcdfe6]",
|
"border-[#dcdfe6]",
|
||||||
"dark:border-[#303030]"
|
"dark:border-[#303030]"
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ export default defineComponent({
|
|||||||
"pt-[3px]",
|
"pt-[3px]",
|
||||||
"px-[11px]",
|
"px-[11px]",
|
||||||
"border-b-[1px]",
|
"border-b-[1px]",
|
||||||
"border-solid",
|
"border-b-solid",
|
||||||
"border-[#dcdfe6]",
|
"border-[#dcdfe6]",
|
||||||
"dark:border-[#303030]"
|
"dark:border-[#303030]"
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -356,7 +356,7 @@ function onClickDrop(key, item, selectRoute?: RouteConfigs) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
showMenuModel(route.fullPath, route.query);
|
showMenuModel(route.fullPath, route.query, route.params);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -391,15 +391,18 @@ function disabledMenus(value: boolean, fixedTag = false) {
|
|||||||
function showMenuModel(
|
function showMenuModel(
|
||||||
currentPath: string,
|
currentPath: string,
|
||||||
query: object = {},
|
query: object = {},
|
||||||
|
params: object = {},
|
||||||
refresh = false
|
refresh = false
|
||||||
) {
|
) {
|
||||||
const allRoute = multiTags.value;
|
const allRoute = multiTags.value;
|
||||||
const routeLength = multiTags.value.length;
|
const routeLength = multiTags.value.length;
|
||||||
let currentIndex = -1;
|
let currentIndex = -1;
|
||||||
if (isAllEmpty(query)) {
|
if (!isAllEmpty(params)) {
|
||||||
currentIndex = allRoute.findIndex(v => v.path === currentPath);
|
currentIndex = allRoute.findIndex(v => isEqual(v.params, params));
|
||||||
} else {
|
} else if (!isAllEmpty(query)) {
|
||||||
currentIndex = allRoute.findIndex(v => isEqual(v.query, query));
|
currentIndex = allRoute.findIndex(v => isEqual(v.query, query));
|
||||||
|
} else {
|
||||||
|
currentIndex = allRoute.findIndex(v => v.path === currentPath);
|
||||||
}
|
}
|
||||||
function fixedTagDisabled() {
|
function fixedTagDisabled() {
|
||||||
if (allRoute[currentIndex]?.meta?.fixedTag) {
|
if (allRoute[currentIndex]?.meta?.fixedTag) {
|
||||||
@@ -465,14 +468,14 @@ function openMenu(tag, e) {
|
|||||||
} else if (route.path !== tag.path && route.name !== tag.name) {
|
} else if (route.path !== tag.path && route.name !== tag.name) {
|
||||||
// 右键菜单不匹配当前路由,隐藏刷新
|
// 右键菜单不匹配当前路由,隐藏刷新
|
||||||
tagsViews[0].show = false;
|
tagsViews[0].show = false;
|
||||||
showMenuModel(tag.path, tag.query);
|
showMenuModel(tag.path, tag.query, tag.params);
|
||||||
} else if (multiTags.value.length === 2 && route.path !== tag.path) {
|
} else if (multiTags.value.length === 2 && route.path !== tag.path) {
|
||||||
showMenus(true);
|
showMenus(true);
|
||||||
// 只有两个标签时不显示关闭其他标签页
|
// 只有两个标签时不显示关闭其他标签页
|
||||||
tagsViews[4].show = false;
|
tagsViews[4].show = false;
|
||||||
} else if (route.path === tag.path) {
|
showMenuModel(tag.path, tag.query, tag.params);
|
||||||
// 右键当前激活的菜单
|
} else {
|
||||||
showMenuModel(tag.path, tag.query, true);
|
showMenuModel(tag.path, tag.query, tag.params, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
currentSelect.value = tag;
|
currentSelect.value = tag;
|
||||||
|
|||||||
@@ -19,13 +19,22 @@ const loading = ref(true);
|
|||||||
const currentRoute = useRoute();
|
const currentRoute = useRoute();
|
||||||
const frameSrc = ref<string>("");
|
const frameSrc = ref<string>("");
|
||||||
const frameRef = ref<HTMLElement | null>(null);
|
const frameRef = ref<HTMLElement | null>(null);
|
||||||
|
const fallbackTimer = ref<number | null>(null);
|
||||||
|
|
||||||
if (unref(currentRoute.meta)?.frameSrc) {
|
if (unref(currentRoute.meta)?.frameSrc) {
|
||||||
frameSrc.value = unref(currentRoute.meta)?.frameSrc as string;
|
frameSrc.value = unref(currentRoute.meta)?.frameSrc as string;
|
||||||
}
|
}
|
||||||
unref(currentRoute.meta)?.frameLoading === false && hideLoading();
|
|
||||||
|
function clearFallbackTimer() {
|
||||||
|
if (fallbackTimer.value !== null) {
|
||||||
|
clearTimeout(fallbackTimer.value);
|
||||||
|
fallbackTimer.value = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function hideLoading() {
|
function hideLoading() {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
|
clearFallbackTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
@@ -34,32 +43,42 @@ function init() {
|
|||||||
if (!iframe) return;
|
if (!iframe) return;
|
||||||
const _frame = iframe as any;
|
const _frame = iframe as any;
|
||||||
if (_frame.attachEvent) {
|
if (_frame.attachEvent) {
|
||||||
_frame.attachEvent("onload", () => {
|
_frame.attachEvent("onload", hideLoading);
|
||||||
hideLoading();
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
iframe.onload = () => {
|
iframe.onload = hideLoading;
|
||||||
hideLoading();
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let isRedirect = false;
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => currentRoute.fullPath,
|
() => currentRoute.fullPath,
|
||||||
path => {
|
path => {
|
||||||
if (
|
if (
|
||||||
currentRoute.name === "Redirect" &&
|
currentRoute.name === "Redirect" &&
|
||||||
path.includes(props.frameInfo?.fullPath)
|
props.frameInfo?.fullPath &&
|
||||||
|
path.includes(props.frameInfo.fullPath)
|
||||||
) {
|
) {
|
||||||
frameSrc.value = path; // redirect时,置换成任意值,待重定向后 重新赋值
|
isRedirect = true;
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
// 重新赋值
|
if (props.frameInfo?.fullPath === path && isRedirect) {
|
||||||
if (props.frameInfo?.fullPath === path) {
|
loading.value = true;
|
||||||
frameSrc.value = props.frameInfo?.frameSrc;
|
clearFallbackTimer();
|
||||||
|
const url = new URL(props.frameInfo.frameSrc, window.location.origin);
|
||||||
|
const joinChar = url.search ? "&" : "?";
|
||||||
|
frameSrc.value = `${props.frameInfo.frameSrc}${joinChar}t=${Date.now()}`;
|
||||||
|
fallbackTimer.value = window.setTimeout(() => {
|
||||||
|
if (loading.value) {
|
||||||
|
hideLoading();
|
||||||
|
}
|
||||||
|
}, 1500);
|
||||||
|
isRedirect = false;
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
{ immediate: true }
|
||||||
);
|
);
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|||||||
@@ -114,14 +114,21 @@ export function useTags() {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
function conditionHandle(item, previous, next) {
|
function conditionHandle(item, previous, next) {
|
||||||
|
const currentName = route.name || "";
|
||||||
|
const itemName = item.name || "";
|
||||||
|
|
||||||
if (isBoolean(route?.meta?.showLink) && route?.meta?.showLink === false) {
|
if (isBoolean(route?.meta?.showLink) && route?.meta?.showLink === false) {
|
||||||
if (Object.keys(route.query).length > 0) {
|
if (Object.keys(route.query).length > 0) {
|
||||||
return isEqual(route.query, item.query) ? previous : next;
|
return currentName === itemName && isEqual(route.query, item.query)
|
||||||
|
? previous
|
||||||
|
: next;
|
||||||
} else {
|
} else {
|
||||||
return isEqual(route.params, item.params) ? previous : next;
|
return currentName === itemName && isEqual(route.params, item.params)
|
||||||
|
? previous
|
||||||
|
: next;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return route.path === item.path ? previous : next;
|
return currentName === itemName ? previous : next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export default {
|
|||||||
name: "403",
|
name: "403",
|
||||||
component: () => import("@/views/error/403.vue"),
|
component: () => import("@/views/error/403.vue"),
|
||||||
meta: {
|
meta: {
|
||||||
title: $t("menus.pureFourZeroOne")
|
title: $t("menus.pureAccessDenied")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -24,7 +24,7 @@ export default {
|
|||||||
name: "404",
|
name: "404",
|
||||||
component: () => import("@/views/error/404.vue"),
|
component: () => import("@/views/error/404.vue"),
|
||||||
meta: {
|
meta: {
|
||||||
title: $t("menus.pureFourZeroFour")
|
title: $t("menus.purePageNotFound")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -32,7 +32,7 @@ export default {
|
|||||||
name: "500",
|
name: "500",
|
||||||
component: () => import("@/views/error/500.vue"),
|
component: () => import("@/views/error/500.vue"),
|
||||||
meta: {
|
meta: {
|
||||||
title: $t("menus.pureFive")
|
title: $t("menus.pureServerError")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -8,8 +8,27 @@ export default [
|
|||||||
component: () => import("@/views/login/index.vue"),
|
component: () => import("@/views/login/index.vue"),
|
||||||
meta: {
|
meta: {
|
||||||
title: $t("menus.pureLogin"),
|
title: $t("menus.pureLogin"),
|
||||||
showLink: false,
|
showLink: false
|
||||||
rank: 101
|
}
|
||||||
|
},
|
||||||
|
// 全屏403(无权访问)页面
|
||||||
|
{
|
||||||
|
path: "/access-denied",
|
||||||
|
name: "AccessDenied",
|
||||||
|
component: () => import("@/views/error/403.vue"),
|
||||||
|
meta: {
|
||||||
|
title: $t("menus.pureAccessDenied"),
|
||||||
|
showLink: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 全屏500(服务器出错)页面
|
||||||
|
{
|
||||||
|
path: "/server-error",
|
||||||
|
name: "ServerError",
|
||||||
|
component: () => import("@/views/error/500.vue"),
|
||||||
|
meta: {
|
||||||
|
title: $t("menus.pureServerError"),
|
||||||
|
showLink: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -17,8 +36,7 @@ export default [
|
|||||||
component: Layout,
|
component: Layout,
|
||||||
meta: {
|
meta: {
|
||||||
title: $t("status.pureLoad"),
|
title: $t("status.pureLoad"),
|
||||||
showLink: false,
|
showLink: false
|
||||||
rank: 102
|
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
@@ -28,6 +46,15 @@ export default [
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/account-settings",
|
||||||
|
name: "AccountSettings",
|
||||||
|
component: () => import("@/views/account-settings/index.vue"),
|
||||||
|
meta: {
|
||||||
|
title: $t("buttons.pureAccountSettings"),
|
||||||
|
showLink: false
|
||||||
|
}
|
||||||
|
},
|
||||||
// 下面是一个无layout菜单的例子(一个全屏空白页面),因为这种情况极少发生,所以只需要在前端配置即可(配置路径:src/router/modules/remaining.ts)
|
// 下面是一个无layout菜单的例子(一个全屏空白页面),因为这种情况极少发生,所以只需要在前端配置即可(配置路径:src/router/modules/remaining.ts)
|
||||||
{
|
{
|
||||||
path: "/empty",
|
path: "/empty",
|
||||||
@@ -35,18 +62,7 @@ export default [
|
|||||||
component: () => import("@/views/empty/index.vue"),
|
component: () => import("@/views/empty/index.vue"),
|
||||||
meta: {
|
meta: {
|
||||||
title: $t("menus.pureEmpty"),
|
title: $t("menus.pureEmpty"),
|
||||||
showLink: false,
|
showLink: false
|
||||||
rank: 103
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: "/account-settings",
|
|
||||||
name: "AccountSettings",
|
|
||||||
component: () => import("@/views/account-settings/index.vue"),
|
|
||||||
meta: {
|
|
||||||
title: $t("buttons.pureAccountSettings"),
|
|
||||||
showLink: false,
|
|
||||||
rank: 104
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
] satisfies Array<RouteConfigsTable>;
|
] satisfies Array<RouteConfigsTable>;
|
||||||
|
|||||||
@@ -139,12 +139,17 @@ function findRouteByPath(path: string, routes: RouteRecordRaw[]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 动态路由注册完成后,再添加全屏404(页面不存在)页面,避免刷新动态路由页面时误跳转到404页面 */
|
||||||
function addPathMatch() {
|
function addPathMatch() {
|
||||||
if (!router.hasRoute("pathMatch")) {
|
if (!router.hasRoute("pathMatch")) {
|
||||||
router.addRoute({
|
router.addRoute({
|
||||||
path: "/:pathMatch(.*)",
|
path: "/:pathMatch(.*)*",
|
||||||
name: "pathMatch",
|
name: "PageNotFound",
|
||||||
redirect: "/error/404"
|
component: () => import("@/views/error/404.vue"),
|
||||||
|
meta: {
|
||||||
|
title: "menus.purePageNotFound",
|
||||||
|
showLink: false
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,22 +80,15 @@ export const useMultiTagsStore = defineStore("pure-multiTags", {
|
|||||||
if (isBoolean(tagVal?.meta?.showLink) && !tagVal?.meta?.showLink)
|
if (isBoolean(tagVal?.meta?.showLink) && !tagVal?.meta?.showLink)
|
||||||
return;
|
return;
|
||||||
const tagPath = tagVal.path;
|
const tagPath = tagVal.path;
|
||||||
// 判断tag是否已存在
|
|
||||||
const tagHasExits = this.multiTags.some(tag => {
|
const tagHasExits = this.multiTags.some(tag => {
|
||||||
return tag.path === tagPath;
|
return (
|
||||||
|
tag.path === tagPath &&
|
||||||
|
isEqual(tag?.query, tagVal?.query) &&
|
||||||
|
isEqual(tag?.params, tagVal?.params)
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 判断tag中的query键值是否相等
|
if (tagHasExits) return;
|
||||||
const tagQueryHasExits = this.multiTags.some(tag => {
|
|
||||||
return isEqual(tag?.query, tagVal?.query);
|
|
||||||
});
|
|
||||||
|
|
||||||
// 判断tag中的params键值是否相等
|
|
||||||
const tagParamsHasExits = this.multiTags.some(tag => {
|
|
||||||
return isEqual(tag?.params, tagVal?.params);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (tagHasExits && tagQueryHasExits && tagParamsHasExits) return;
|
|
||||||
|
|
||||||
// 动态路由可打开的最大数量
|
// 动态路由可打开的最大数量
|
||||||
const dynamicLevel = tagVal?.meta?.dynamicLevel ?? -1;
|
const dynamicLevel = tagVal?.meta?.dynamicLevel ?? -1;
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import { defineStore } from "pinia";
|
|||||||
import {
|
import {
|
||||||
type cacheType,
|
type cacheType,
|
||||||
store,
|
store,
|
||||||
debounce,
|
|
||||||
ascending,
|
ascending,
|
||||||
getKeyList,
|
getKeyList,
|
||||||
filterTree,
|
filterTree,
|
||||||
@@ -33,33 +32,35 @@ export const usePermissionStore = defineStore("pure-permission", {
|
|||||||
this.constantMenus.concat(routes) as any
|
this.constantMenus.concat(routes) as any
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
/** 监听缓存页面是否存在于标签页,不存在则删除 */
|
||||||
|
clearCache() {
|
||||||
|
let cacheLength = this.cachePageList.length;
|
||||||
|
const nameList = getKeyList(useMultiTagsStoreHook().multiTags, "name");
|
||||||
|
while (cacheLength > 0) {
|
||||||
|
nameList.findIndex(v => v === this.cachePageList[cacheLength - 1]) ===
|
||||||
|
-1 &&
|
||||||
|
this.cachePageList.splice(
|
||||||
|
this.cachePageList.indexOf(this.cachePageList[cacheLength - 1]),
|
||||||
|
1
|
||||||
|
);
|
||||||
|
cacheLength--;
|
||||||
|
}
|
||||||
|
},
|
||||||
cacheOperate({ mode, name }: cacheType) {
|
cacheOperate({ mode, name }: cacheType) {
|
||||||
const delIndex = this.cachePageList.findIndex(v => v === name);
|
const delIndex = this.cachePageList.findIndex(v => v === name);
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case "refresh":
|
case "refresh":
|
||||||
this.cachePageList = this.cachePageList.filter(v => v !== name);
|
this.cachePageList = this.cachePageList.filter(v => v !== name);
|
||||||
|
this.clearCache();
|
||||||
break;
|
break;
|
||||||
case "add":
|
case "add":
|
||||||
this.cachePageList.push(name);
|
this.cachePageList.push(name);
|
||||||
break;
|
break;
|
||||||
case "delete":
|
case "delete":
|
||||||
delIndex !== -1 && this.cachePageList.splice(delIndex, 1);
|
delIndex !== -1 && this.cachePageList.splice(delIndex, 1);
|
||||||
|
this.clearCache();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/** 监听缓存页面是否存在于标签页,不存在则删除 */
|
|
||||||
debounce(() => {
|
|
||||||
let cacheLength = this.cachePageList.length;
|
|
||||||
const nameList = getKeyList(useMultiTagsStoreHook().multiTags, "name");
|
|
||||||
while (cacheLength > 0) {
|
|
||||||
nameList.findIndex(v => v === this.cachePageList[cacheLength - 1]) ===
|
|
||||||
-1 &&
|
|
||||||
this.cachePageList.splice(
|
|
||||||
this.cachePageList.indexOf(this.cachePageList[cacheLength - 1]),
|
|
||||||
1
|
|
||||||
);
|
|
||||||
cacheLength--;
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
},
|
},
|
||||||
/** 清空缓存页面 */
|
/** 清空缓存页面 */
|
||||||
clearAllCachePage() {
|
clearAllCachePage() {
|
||||||
|
|||||||
@@ -172,10 +172,6 @@
|
|||||||
.is-active > .el-sub-menu__title,
|
.is-active > .el-sub-menu__title,
|
||||||
.is-active.submenu-title-noDropdown {
|
.is-active.submenu-title-noDropdown {
|
||||||
color: var(--pure-theme-sub-menu-active-text) !important;
|
color: var(--pure-theme-sub-menu-active-text) !important;
|
||||||
|
|
||||||
i {
|
|
||||||
color: var(--pure-theme-sub-menu-active-text) !important;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.is-active {
|
.is-active {
|
||||||
@@ -270,10 +266,6 @@
|
|||||||
.is-active > .el-sub-menu__title,
|
.is-active > .el-sub-menu__title,
|
||||||
.is-active.submenu-title-noDropdown {
|
.is-active.submenu-title-noDropdown {
|
||||||
color: var(--pure-theme-sub-menu-active-text) !important;
|
color: var(--pure-theme-sub-menu-active-text) !important;
|
||||||
|
|
||||||
i {
|
|
||||||
color: var(--pure-theme-sub-menu-active-text) !important;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 子菜单中还有子菜单 */
|
/* 子菜单中还有子菜单 */
|
||||||
@@ -374,10 +366,6 @@
|
|||||||
.is-active > .el-sub-menu__title,
|
.is-active > .el-sub-menu__title,
|
||||||
.is-active.submenu-title-noDropdown {
|
.is-active.submenu-title-noDropdown {
|
||||||
color: var(--pure-theme-sub-menu-active-text) !important;
|
color: var(--pure-theme-sub-menu-active-text) !important;
|
||||||
|
|
||||||
i {
|
|
||||||
color: var(--pure-theme-sub-menu-active-text) !important;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.nest-menu .el-sub-menu > .el-sub-menu__title,
|
.nest-menu .el-sub-menu > .el-sub-menu__title,
|
||||||
@@ -541,10 +529,6 @@
|
|||||||
.is-active > .el-sub-menu__title,
|
.is-active > .el-sub-menu__title,
|
||||||
.is-active.submenu-title-noDropdown {
|
.is-active.submenu-title-noDropdown {
|
||||||
color: var(--pure-theme-sub-menu-active-text) !important;
|
color: var(--pure-theme-sub-menu-active-text) !important;
|
||||||
|
|
||||||
i {
|
|
||||||
color: var(--pure-theme-sub-menu-active-text) !important;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.is-active {
|
.is-active {
|
||||||
|
|||||||
@@ -463,6 +463,16 @@ function onSureBtnLoading() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 自定义动画
|
||||||
|
function onTransitionClick(title, transition) {
|
||||||
|
addDialog({
|
||||||
|
width: "30%",
|
||||||
|
title,
|
||||||
|
transition,
|
||||||
|
contentRenderer: () => <p>{JSON.stringify(transition)}</p>
|
||||||
|
});
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -551,5 +561,112 @@ function onSureBtnLoading() {
|
|||||||
点击底部确定按钮可开启按钮动画
|
点击底部确定按钮可开启按钮动画
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-space>
|
</el-space>
|
||||||
|
<el-divider />
|
||||||
|
<el-space wrap>
|
||||||
|
<el-button
|
||||||
|
@click="onTransitionClick('淡入淡出动画(默认)', 'dialog-fade')"
|
||||||
|
>
|
||||||
|
淡入淡出动画(默认)
|
||||||
|
</el-button>
|
||||||
|
<el-button @click="onTransitionClick('缩放动画', 'dialog-scale')">
|
||||||
|
缩放动画
|
||||||
|
</el-button>
|
||||||
|
<el-button @click="onTransitionClick('滑动动画', 'dialog-slide')">
|
||||||
|
滑动动画
|
||||||
|
</el-button>
|
||||||
|
<el-button @click="onTransitionClick('弹跳动画', 'dialog-bounce')">
|
||||||
|
弹跳动画
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
@click="
|
||||||
|
onTransitionClick('自定义动画事件处理器(可配置对象)', {
|
||||||
|
name: 'dialog-custom-object',
|
||||||
|
appear: true,
|
||||||
|
mode: 'out-in',
|
||||||
|
duration: 500
|
||||||
|
})
|
||||||
|
"
|
||||||
|
>
|
||||||
|
自定义动画事件处理器(可配置对象)
|
||||||
|
</el-button>
|
||||||
|
</el-space>
|
||||||
</el-card>
|
</el-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
/* Scale Animation */
|
||||||
|
.dialog-scale-enter-active,
|
||||||
|
.dialog-scale-leave-active,
|
||||||
|
.dialog-scale-enter-active .el-dialog,
|
||||||
|
.dialog-scale-leave-active .el-dialog {
|
||||||
|
transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-scale-enter-from,
|
||||||
|
.dialog-scale-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-scale-enter-from .el-dialog,
|
||||||
|
.dialog-scale-leave-to .el-dialog {
|
||||||
|
opacity: 0;
|
||||||
|
transform: scale(0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Slide Animation */
|
||||||
|
.dialog-slide-enter-active,
|
||||||
|
.dialog-slide-leave-active,
|
||||||
|
.dialog-slide-enter-active .el-dialog,
|
||||||
|
.dialog-slide-leave-active .el-dialog {
|
||||||
|
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-slide-enter-from,
|
||||||
|
.dialog-slide-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-slide-enter-from .el-dialog,
|
||||||
|
.dialog-slide-leave-to .el-dialog {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-100px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Bounce Animation */
|
||||||
|
.dialog-bounce-enter-active,
|
||||||
|
.dialog-bounce-leave-active,
|
||||||
|
.dialog-bounce-enter-active .el-dialog,
|
||||||
|
.dialog-bounce-leave-active .el-dialog {
|
||||||
|
transition: all 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-bounce-enter-from,
|
||||||
|
.dialog-bounce-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-bounce-enter-from .el-dialog,
|
||||||
|
.dialog-bounce-leave-to .el-dialog {
|
||||||
|
opacity: 0;
|
||||||
|
transform: scale(0.3) translateY(-50px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Object Configuration Animation */
|
||||||
|
.dialog-custom-object-enter-active,
|
||||||
|
.dialog-custom-object-leave-active,
|
||||||
|
.dialog-custom-object-enter-active .el-dialog,
|
||||||
|
.dialog-custom-object-leave-active .el-dialog {
|
||||||
|
transition: all 0.5s cubic-bezier(0.25, 0.8, 0.25, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-custom-object-enter-from,
|
||||||
|
.dialog-custom-object-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-custom-object-enter-from .el-dialog,
|
||||||
|
.dialog-custom-object-leave-to .el-dialog {
|
||||||
|
opacity: 0;
|
||||||
|
transform: rotate(180deg) scale(0.5);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -422,6 +422,17 @@ function onSureBtnLoading() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onResizableClick(title, content, direction) {
|
||||||
|
addDrawer({
|
||||||
|
title,
|
||||||
|
direction,
|
||||||
|
resizable: true, // 启用可调整大小的功能
|
||||||
|
contentRenderer: () => (
|
||||||
|
<p class="text-[var(--el-color-primary)]">{content}</p> // jsx 语法 (注意在.vue文件启用jsx语法,需要在script开启lang="tsx")
|
||||||
|
)
|
||||||
|
});
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -498,5 +509,28 @@ function onSureBtnLoading() {
|
|||||||
点击底部确定按钮可开启按钮动画
|
点击底部确定按钮可开启按钮动画
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-space>
|
</el-space>
|
||||||
|
<el-divider />
|
||||||
|
<el-space wrap>
|
||||||
|
<el-button
|
||||||
|
@click="onResizableClick('从左侧打开', '拖动抽屉右侧边缘', 'ltr')"
|
||||||
|
>
|
||||||
|
拖拽调整大小(从左侧打开)
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
@click="onResizableClick('从右侧打开', '拖动抽屉左侧边缘', 'rtl')"
|
||||||
|
>
|
||||||
|
拖拽调整大小(从右侧打开)
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
@click="onResizableClick('从顶部打开', '拖动抽屉底部边缘', 'ttb')"
|
||||||
|
>
|
||||||
|
拖拽调整大小(从顶部打开)
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
@click="onResizableClick('从底部打开', '拖动抽屉顶部边缘', 'btt')"
|
||||||
|
>
|
||||||
|
拖拽调整大小(从底部打开)
|
||||||
|
</el-button>
|
||||||
|
</el-space>
|
||||||
</el-card>
|
</el-card>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -10,9 +10,11 @@ const router = useRouter();
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="flex justify-center items-center h-[640px]">
|
<div
|
||||||
|
class="flex flex-col md:flex-row justify-center items-center min-h-full w-full p-4 md:p-0"
|
||||||
|
>
|
||||||
<noAccess />
|
<noAccess />
|
||||||
<div class="ml-12">
|
<div class="mt-8 md:ml-12 md:mt-0 text-center md:text-left">
|
||||||
<p
|
<p
|
||||||
v-motion
|
v-motion
|
||||||
class="font-medium text-4xl mb-4! dark:text-white"
|
class="font-medium text-4xl mb-4! dark:text-white"
|
||||||
@@ -32,7 +34,7 @@ const router = useRouter();
|
|||||||
</p>
|
</p>
|
||||||
<p
|
<p
|
||||||
v-motion
|
v-motion
|
||||||
class="mb-4! text-gray-500"
|
class="text-xl mb-4! text-gray-500"
|
||||||
:initial="{
|
:initial="{
|
||||||
opacity: 0,
|
opacity: 0,
|
||||||
y: 100
|
y: 100
|
||||||
@@ -50,6 +52,7 @@ const router = useRouter();
|
|||||||
<el-button
|
<el-button
|
||||||
v-motion
|
v-motion
|
||||||
type="primary"
|
type="primary"
|
||||||
|
class="block mx-auto md:inline-block md:mx-0"
|
||||||
:initial="{
|
:initial="{
|
||||||
opacity: 0,
|
opacity: 0,
|
||||||
y: 100
|
y: 100
|
||||||
@@ -68,3 +71,9 @@ const router = useRouter();
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.main-content {
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -10,9 +10,11 @@ const router = useRouter();
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="flex justify-center items-center h-[640px]">
|
<div
|
||||||
|
class="flex flex-col md:flex-row justify-center items-center min-h-full w-full p-4 md:p-0"
|
||||||
|
>
|
||||||
<noExist />
|
<noExist />
|
||||||
<div class="ml-12">
|
<div class="mt-8 md:ml-12 md:mt-0 text-center md:text-left">
|
||||||
<p
|
<p
|
||||||
v-motion
|
v-motion
|
||||||
class="font-medium text-4xl mb-4! dark:text-white"
|
class="font-medium text-4xl mb-4! dark:text-white"
|
||||||
@@ -32,7 +34,7 @@ const router = useRouter();
|
|||||||
</p>
|
</p>
|
||||||
<p
|
<p
|
||||||
v-motion
|
v-motion
|
||||||
class="mb-4! text-gray-500"
|
class="text-xl mb-4! text-gray-500"
|
||||||
:initial="{
|
:initial="{
|
||||||
opacity: 0,
|
opacity: 0,
|
||||||
y: 100
|
y: 100
|
||||||
@@ -50,6 +52,7 @@ const router = useRouter();
|
|||||||
<el-button
|
<el-button
|
||||||
v-motion
|
v-motion
|
||||||
type="primary"
|
type="primary"
|
||||||
|
class="block mx-auto md:inline-block md:mx-0"
|
||||||
:initial="{
|
:initial="{
|
||||||
opacity: 0,
|
opacity: 0,
|
||||||
y: 100
|
y: 100
|
||||||
@@ -68,3 +71,9 @@ const router = useRouter();
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.main-content {
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -10,9 +10,11 @@ const router = useRouter();
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="flex justify-center items-center h-[640px]">
|
<div
|
||||||
|
class="flex flex-col md:flex-row justify-center items-center min-h-full w-full p-4 md:p-0"
|
||||||
|
>
|
||||||
<noServer />
|
<noServer />
|
||||||
<div class="ml-12">
|
<div class="mt-8 md:ml-12 md:mt-0 text-center md:text-left">
|
||||||
<p
|
<p
|
||||||
v-motion
|
v-motion
|
||||||
class="font-medium text-4xl mb-4! dark:text-white"
|
class="font-medium text-4xl mb-4! dark:text-white"
|
||||||
@@ -32,7 +34,7 @@ const router = useRouter();
|
|||||||
</p>
|
</p>
|
||||||
<p
|
<p
|
||||||
v-motion
|
v-motion
|
||||||
class="mb-4! text-gray-500"
|
class="text-xl mb-4! text-gray-500"
|
||||||
:initial="{
|
:initial="{
|
||||||
opacity: 0,
|
opacity: 0,
|
||||||
y: 100
|
y: 100
|
||||||
@@ -50,6 +52,7 @@ const router = useRouter();
|
|||||||
<el-button
|
<el-button
|
||||||
v-motion
|
v-motion
|
||||||
type="primary"
|
type="primary"
|
||||||
|
class="block mx-auto md:inline-block md:mx-0"
|
||||||
:initial="{
|
:initial="{
|
||||||
opacity: 0,
|
opacity: 0,
|
||||||
y: 100
|
y: 100
|
||||||
@@ -68,3 +71,9 @@ const router = useRouter();
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.main-content {
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ onMounted(() => {
|
|||||||
<span class="font-medium">
|
<span class="font-medium">
|
||||||
流程图组件,采用开源的
|
流程图组件,采用开源的
|
||||||
<el-link
|
<el-link
|
||||||
href="https://site.logic-flow.cn/docs/#/zh/guide/start"
|
href="https://site.logic-flow.cn/tutorial/get-started"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
style="margin: 0 4px 5px; font-size: 16px"
|
style="margin: 0 4px 5px; font-size: 16px"
|
||||||
>
|
>
|
||||||
|
|||||||
Reference in New Issue
Block a user