From 1ec73473cf1134e1bb63b71e4ecbe5eadeb35318 Mon Sep 17 00:00:00 2001
From: dap <15891557205@163.com>
Date: Mon, 26 Jan 2026 18:51:57 +0800
Subject: [PATCH] =?UTF-8?q?chore:=20=E7=A7=BB=E9=99=A4=20playground=20?=
=?UTF-8?q?=E7=9B=AE=E5=BD=95=E5=8F=8A=E7=9B=B8=E5=85=B3=E9=85=8D=E7=BD=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
清理不再需要的 playground 项目,包括:
- 删除 playground 源码目录及所有相关文件
- 从 pnpm-workspace.yaml 移除 playground 工作区
- 从 .vscode 配置中移除 playground 相关路径
- 从 package.json 脚本中移除 build:play 和 dev:play 命令
- 从 vben-admin.code-workspace 移除 playground 项目引用
- 从 .vscode/launch.json 移除 playground 调试配置
---
.vscode/launch.json | 9 -
.vscode/settings.json | 1 -
package.json | 2 -
playground/.env | 8 -
playground/.env.analyze | 7 -
playground/.env.development | 20 -
playground/.env.production | 19 -
playground/__tests__/e2e/auth-login.spec.ts | 20 -
playground/__tests__/e2e/common/auth.ts | 46 --
playground/index.html | 35 --
playground/package.json | 60 --
playground/playwright.config.ts | 108 ----
playground/postcss.config.mjs | 1 -
playground/public/favicon.ico | Bin 5430 -> 0 bytes
playground/src/adapter/component/index.ts | 585 -----------------
playground/src/adapter/form.ts | 47 --
playground/src/adapter/vxe-table.ts | 298 ---------
playground/src/api/core/auth.ts | 57 --
playground/src/api/core/index.ts | 4 -
playground/src/api/core/menu.ts | 10 -
playground/src/api/core/timezone.ts | 26 -
playground/src/api/core/user.ts | 10 -
playground/src/api/examples/download.ts | 28 -
playground/src/api/examples/index.ts | 2 -
playground/src/api/examples/json-bigint.ts | 10 -
playground/src/api/examples/params.ts | 19 -
playground/src/api/examples/status.ts | 10 -
playground/src/api/examples/table.ts | 18 -
playground/src/api/examples/upload.ts | 25 -
playground/src/api/index.ts | 3 -
playground/src/api/request.ts | 133 ----
playground/src/api/system/dept.ts | 54 --
playground/src/api/system/index.ts | 3 -
playground/src/api/system/menu.ts | 158 -----
playground/src/api/system/role.ts | 55 --
playground/src/app.vue | 39 --
playground/src/bootstrap.ts | 84 ---
playground/src/layouts/auth.vue | 25 -
playground/src/layouts/basic.vue | 232 -------
playground/src/layouts/index.ts | 6 -
playground/src/locales/README.md | 3 -
playground/src/locales/index.ts | 98 ---
playground/src/locales/langs/en-US/demos.json | 71 ---
.../src/locales/langs/en-US/examples.json | 83 ---
playground/src/locales/langs/en-US/page.json | 17 -
.../src/locales/langs/en-US/system.json | 65 --
playground/src/locales/langs/zh-CN/demos.json | 72 ---
.../src/locales/langs/zh-CN/examples.json | 83 ---
playground/src/locales/langs/zh-CN/page.json | 17 -
.../src/locales/langs/zh-CN/system.json | 67 --
playground/src/main.ts | 31 -
playground/src/preferences.ts | 13 -
playground/src/router/access.ts | 42 --
playground/src/router/guard.ts | 136 ----
playground/src/router/index.ts | 37 --
playground/src/router/routes/core.ts | 97 ---
playground/src/router/routes/index.ts | 47 --
.../src/router/routes/modules/dashboard.ts | 38 --
playground/src/router/routes/modules/demos.ts | 588 ------------------
.../src/router/routes/modules/examples.ts | 353 -----------
.../src/router/routes/modules/system.ts | 46 --
playground/src/router/routes/modules/vben.ts | 116 ----
playground/src/store/auth.ts | 127 ----
playground/src/store/index.ts | 1 -
playground/src/timezone-init.ts | 20 -
playground/src/views/_core/README.md | 3 -
playground/src/views/_core/about/index.vue | 9 -
.../views/_core/authentication/code-login.vue | 109 ----
.../_core/authentication/forget-password.vue | 42 --
.../src/views/_core/authentication/login.vue | 132 ----
.../_core/authentication/qrcode-login.vue | 10 -
.../views/_core/authentication/register.vue | 96 ---
.../src/views/_core/fallback/coming-soon.vue | 7 -
.../src/views/_core/fallback/forbidden.vue | 9 -
.../views/_core/fallback/internal-error.vue | 9 -
.../src/views/_core/fallback/not-found.vue | 9 -
.../src/views/_core/fallback/offline.vue | 9 -
.../src/views/_core/profile/base-setting.vue | 65 --
playground/src/views/_core/profile/index.vue | 49 --
.../_core/profile/notification-setting.vue | 31 -
.../views/_core/profile/password-setting.vue | 63 --
.../views/_core/profile/security-setting.vue | 43 --
.../dashboard/analytics/analytics-trends.vue | 97 ---
.../analytics/analytics-visits-data.vue | 81 ---
.../analytics/analytics-visits-sales.vue | 46 --
.../analytics/analytics-visits-source.vue | 64 --
.../dashboard/analytics/analytics-visits.vue | 54 --
.../src/views/dashboard/analytics/index.vue | 90 ---
.../src/views/dashboard/workspace/index.vue | 266 --------
.../src/views/demos/access/admin-visible.vue | 11 -
.../src/views/demos/access/button-control.vue | 155 -----
playground/src/views/demos/access/index.vue | 93 ---
.../views/demos/access/menu-visible-403.vue | 11 -
.../src/views/demos/access/super-visible.vue | 11 -
.../src/views/demos/access/user-visible.vue | 11 -
.../src/views/demos/active-icon/index.vue | 11 -
playground/src/views/demos/badge/index.vue | 113 ----
.../views/demos/breadcrumb/lateral-detail.vue | 21 -
.../src/views/demos/breadcrumb/lateral.vue | 25 -
.../views/demos/breadcrumb/level-detail.vue | 11 -
.../views/demos/features/clipboard/index.vue | 25 -
.../demos/features/file-download/base64.ts | 1 -
.../demos/features/file-download/index.vue | 100 ---
.../demos/features/full-screen/index.vue | 47 --
.../features/hide-menu-children/children.vue | 23 -
.../features/hide-menu-children/parent.vue | 17 -
.../src/views/demos/features/icons/index.vue | 115 ----
.../demos/features/json-bigint/index.vue | 39 --
.../demos/features/login-expired/index.vue | 39 --
.../views/demos/features/menu-query/index.vue | 11 -
.../views/demos/features/new-window/index.vue | 11 -
.../request-params-serializer/index.vue | 61 --
.../src/views/demos/features/tabs/index.vue | 105 ----
.../views/demos/features/tabs/tab-detail.vue | 23 -
.../vue-query/concurrency-caching.vue | 61 --
.../views/demos/features/vue-query/index.vue | 40 --
.../features/vue-query/infinite-queries.vue | 58 --
.../features/vue-query/paginated-queries.vue | 52 --
.../features/vue-query/query-retries.vue | 34 -
.../views/demos/features/vue-query/typing.ts | 18 -
.../views/demos/features/watermark/index.vue | 86 ---
playground/src/views/demos/nested/menu-1.vue | 7 -
.../src/views/demos/nested/menu-2-1.vue | 7 -
.../src/views/demos/nested/menu-3-1.vue | 7 -
.../src/views/demos/nested/menu-3-2-1.vue | 7 -
.../src/views/examples/button-group/index.vue | 229 -------
.../captcha/point-selection-captcha.vue | 181 ------
.../views/examples/captcha/slider-captcha.vue | 117 ----
.../captcha/slider-rotate-captcha.vue | 28 -
.../captcha/slider-translate-captcha.vue | 27 -
.../src/views/examples/context-menu/index.vue | 59 --
.../src/views/examples/count-to/index.vue | 178 ------
.../src/views/examples/cropper/index.vue | 144 -----
playground/src/views/examples/doc-button.vue | 22 -
.../examples/drawer/auto-height-demo.vue | 47 --
.../src/views/examples/drawer/base-demo.vue | 35 --
.../views/examples/drawer/dynamic-demo.vue | 31 -
.../examples/drawer/form-drawer-demo.vue | 56 --
.../views/examples/drawer/in-content-demo.vue | 48 --
.../src/views/examples/drawer/index.vue | 195 ------
.../examples/drawer/shared-data-demo.vue | 29 -
.../src/views/examples/ellipsis/index.vue | 46 --
playground/src/views/examples/form/api.vue | 274 --------
playground/src/views/examples/form/basic.vue | 498 ---------------
.../src/views/examples/form/custom-layout.vue | 111 ----
playground/src/views/examples/form/custom.vue | 100 ---
.../src/views/examples/form/dynamic.vue | 262 --------
playground/src/views/examples/form/merge.vue | 116 ----
.../examples/form/modules/two-fields.vue | 42 --
playground/src/views/examples/form/query.vue | 276 --------
playground/src/views/examples/form/rules.vue | 245 --------
.../examples/form/scroll-to-error-test.vue | 180 ------
.../src/views/examples/json-viewer/data.ts | 66 --
.../src/views/examples/json-viewer/index.vue | 51 --
.../src/views/examples/layout/col-page.vue | 108 ----
.../src/views/examples/loading/index.vue | 101 ---
.../views/examples/modal/auto-height-demo.vue | 49 --
.../src/views/examples/modal/base-demo.vue | 34 -
.../src/views/examples/modal/blur-demo.vue | 23 -
.../src/views/examples/modal/drag-demo.vue | 19 -
.../src/views/examples/modal/dynamic-demo.vue | 41 --
.../views/examples/modal/form-modal-demo.vue | 91 ---
.../views/examples/modal/in-content-demo.vue | 30 -
playground/src/views/examples/modal/index.vue | 278 ---------
.../src/views/examples/modal/nested-demo.vue | 24 -
.../views/examples/modal/shared-data-demo.vue | 29 -
.../src/views/examples/motion/index.vue | 213 -------
.../src/views/examples/resize/basic.vue | 58 --
playground/src/views/examples/tippy/index.vue | 303 ---------
.../src/views/examples/vxe-table/basic.vue | 112 ----
.../views/examples/vxe-table/custom-cell.vue | 108 ----
.../views/examples/vxe-table/edit-cell.vue | 57 --
.../src/views/examples/vxe-table/edit-row.vue | 94 ---
.../src/views/examples/vxe-table/fixed.vue | 69 --
.../src/views/examples/vxe-table/form.vue | 127 ----
.../src/views/examples/vxe-table/remote.vue | 81 ---
.../views/examples/vxe-table/table-data.ts | 172 -----
.../src/views/examples/vxe-table/tree.vue | 62 --
.../src/views/examples/vxe-table/virtual.vue | 66 --
playground/src/views/system/dept/data.ts | 136 ----
playground/src/views/system/dept/list.vue | 143 -----
.../src/views/system/dept/modules/form.vue | 78 ---
playground/src/views/system/menu/data.ts | 109 ----
playground/src/views/system/menu/list.vue | 162 -----
.../src/views/system/menu/modules/form.vue | 504 ---------------
playground/src/views/system/role/data.ts | 127 ----
playground/src/views/system/role/list.vue | 164 -----
.../src/views/system/role/modules/form.vue | 142 -----
playground/tailwind.config.mjs | 1 -
playground/tsconfig.json | 12 -
playground/tsconfig.node.json | 10 -
playground/vite.config.mts | 20 -
pnpm-workspace.yaml | 1 -
vben-admin.code-workspace | 4 -
194 files changed, 15060 deletions(-)
delete mode 100644 playground/.env
delete mode 100644 playground/.env.analyze
delete mode 100644 playground/.env.development
delete mode 100644 playground/.env.production
delete mode 100644 playground/__tests__/e2e/auth-login.spec.ts
delete mode 100644 playground/__tests__/e2e/common/auth.ts
delete mode 100644 playground/index.html
delete mode 100644 playground/package.json
delete mode 100644 playground/playwright.config.ts
delete mode 100644 playground/postcss.config.mjs
delete mode 100644 playground/public/favicon.ico
delete mode 100644 playground/src/adapter/component/index.ts
delete mode 100644 playground/src/adapter/form.ts
delete mode 100644 playground/src/adapter/vxe-table.ts
delete mode 100644 playground/src/api/core/auth.ts
delete mode 100644 playground/src/api/core/index.ts
delete mode 100644 playground/src/api/core/menu.ts
delete mode 100644 playground/src/api/core/timezone.ts
delete mode 100644 playground/src/api/core/user.ts
delete mode 100644 playground/src/api/examples/download.ts
delete mode 100644 playground/src/api/examples/index.ts
delete mode 100644 playground/src/api/examples/json-bigint.ts
delete mode 100644 playground/src/api/examples/params.ts
delete mode 100644 playground/src/api/examples/status.ts
delete mode 100644 playground/src/api/examples/table.ts
delete mode 100644 playground/src/api/examples/upload.ts
delete mode 100644 playground/src/api/index.ts
delete mode 100644 playground/src/api/request.ts
delete mode 100644 playground/src/api/system/dept.ts
delete mode 100644 playground/src/api/system/index.ts
delete mode 100644 playground/src/api/system/menu.ts
delete mode 100644 playground/src/api/system/role.ts
delete mode 100644 playground/src/app.vue
delete mode 100644 playground/src/bootstrap.ts
delete mode 100644 playground/src/layouts/auth.vue
delete mode 100644 playground/src/layouts/basic.vue
delete mode 100644 playground/src/layouts/index.ts
delete mode 100644 playground/src/locales/README.md
delete mode 100644 playground/src/locales/index.ts
delete mode 100644 playground/src/locales/langs/en-US/demos.json
delete mode 100644 playground/src/locales/langs/en-US/examples.json
delete mode 100644 playground/src/locales/langs/en-US/page.json
delete mode 100644 playground/src/locales/langs/en-US/system.json
delete mode 100644 playground/src/locales/langs/zh-CN/demos.json
delete mode 100644 playground/src/locales/langs/zh-CN/examples.json
delete mode 100644 playground/src/locales/langs/zh-CN/page.json
delete mode 100644 playground/src/locales/langs/zh-CN/system.json
delete mode 100644 playground/src/main.ts
delete mode 100644 playground/src/preferences.ts
delete mode 100644 playground/src/router/access.ts
delete mode 100644 playground/src/router/guard.ts
delete mode 100644 playground/src/router/index.ts
delete mode 100644 playground/src/router/routes/core.ts
delete mode 100644 playground/src/router/routes/index.ts
delete mode 100644 playground/src/router/routes/modules/dashboard.ts
delete mode 100644 playground/src/router/routes/modules/demos.ts
delete mode 100644 playground/src/router/routes/modules/examples.ts
delete mode 100644 playground/src/router/routes/modules/system.ts
delete mode 100644 playground/src/router/routes/modules/vben.ts
delete mode 100644 playground/src/store/auth.ts
delete mode 100644 playground/src/store/index.ts
delete mode 100644 playground/src/timezone-init.ts
delete mode 100644 playground/src/views/_core/README.md
delete mode 100644 playground/src/views/_core/about/index.vue
delete mode 100644 playground/src/views/_core/authentication/code-login.vue
delete mode 100644 playground/src/views/_core/authentication/forget-password.vue
delete mode 100644 playground/src/views/_core/authentication/login.vue
delete mode 100644 playground/src/views/_core/authentication/qrcode-login.vue
delete mode 100644 playground/src/views/_core/authentication/register.vue
delete mode 100644 playground/src/views/_core/fallback/coming-soon.vue
delete mode 100644 playground/src/views/_core/fallback/forbidden.vue
delete mode 100644 playground/src/views/_core/fallback/internal-error.vue
delete mode 100644 playground/src/views/_core/fallback/not-found.vue
delete mode 100644 playground/src/views/_core/fallback/offline.vue
delete mode 100644 playground/src/views/_core/profile/base-setting.vue
delete mode 100644 playground/src/views/_core/profile/index.vue
delete mode 100644 playground/src/views/_core/profile/notification-setting.vue
delete mode 100644 playground/src/views/_core/profile/password-setting.vue
delete mode 100644 playground/src/views/_core/profile/security-setting.vue
delete mode 100644 playground/src/views/dashboard/analytics/analytics-trends.vue
delete mode 100644 playground/src/views/dashboard/analytics/analytics-visits-data.vue
delete mode 100644 playground/src/views/dashboard/analytics/analytics-visits-sales.vue
delete mode 100644 playground/src/views/dashboard/analytics/analytics-visits-source.vue
delete mode 100644 playground/src/views/dashboard/analytics/analytics-visits.vue
delete mode 100644 playground/src/views/dashboard/analytics/index.vue
delete mode 100644 playground/src/views/dashboard/workspace/index.vue
delete mode 100644 playground/src/views/demos/access/admin-visible.vue
delete mode 100644 playground/src/views/demos/access/button-control.vue
delete mode 100644 playground/src/views/demos/access/index.vue
delete mode 100644 playground/src/views/demos/access/menu-visible-403.vue
delete mode 100644 playground/src/views/demos/access/super-visible.vue
delete mode 100644 playground/src/views/demos/access/user-visible.vue
delete mode 100644 playground/src/views/demos/active-icon/index.vue
delete mode 100644 playground/src/views/demos/badge/index.vue
delete mode 100644 playground/src/views/demos/breadcrumb/lateral-detail.vue
delete mode 100644 playground/src/views/demos/breadcrumb/lateral.vue
delete mode 100644 playground/src/views/demos/breadcrumb/level-detail.vue
delete mode 100644 playground/src/views/demos/features/clipboard/index.vue
delete mode 100644 playground/src/views/demos/features/file-download/base64.ts
delete mode 100644 playground/src/views/demos/features/file-download/index.vue
delete mode 100644 playground/src/views/demos/features/full-screen/index.vue
delete mode 100644 playground/src/views/demos/features/hide-menu-children/children.vue
delete mode 100644 playground/src/views/demos/features/hide-menu-children/parent.vue
delete mode 100644 playground/src/views/demos/features/icons/index.vue
delete mode 100644 playground/src/views/demos/features/json-bigint/index.vue
delete mode 100644 playground/src/views/demos/features/login-expired/index.vue
delete mode 100644 playground/src/views/demos/features/menu-query/index.vue
delete mode 100644 playground/src/views/demos/features/new-window/index.vue
delete mode 100644 playground/src/views/demos/features/request-params-serializer/index.vue
delete mode 100644 playground/src/views/demos/features/tabs/index.vue
delete mode 100644 playground/src/views/demos/features/tabs/tab-detail.vue
delete mode 100644 playground/src/views/demos/features/vue-query/concurrency-caching.vue
delete mode 100644 playground/src/views/demos/features/vue-query/index.vue
delete mode 100644 playground/src/views/demos/features/vue-query/infinite-queries.vue
delete mode 100644 playground/src/views/demos/features/vue-query/paginated-queries.vue
delete mode 100644 playground/src/views/demos/features/vue-query/query-retries.vue
delete mode 100644 playground/src/views/demos/features/vue-query/typing.ts
delete mode 100644 playground/src/views/demos/features/watermark/index.vue
delete mode 100644 playground/src/views/demos/nested/menu-1.vue
delete mode 100644 playground/src/views/demos/nested/menu-2-1.vue
delete mode 100644 playground/src/views/demos/nested/menu-3-1.vue
delete mode 100644 playground/src/views/demos/nested/menu-3-2-1.vue
delete mode 100644 playground/src/views/examples/button-group/index.vue
delete mode 100644 playground/src/views/examples/captcha/point-selection-captcha.vue
delete mode 100644 playground/src/views/examples/captcha/slider-captcha.vue
delete mode 100644 playground/src/views/examples/captcha/slider-rotate-captcha.vue
delete mode 100644 playground/src/views/examples/captcha/slider-translate-captcha.vue
delete mode 100644 playground/src/views/examples/context-menu/index.vue
delete mode 100644 playground/src/views/examples/count-to/index.vue
delete mode 100644 playground/src/views/examples/cropper/index.vue
delete mode 100644 playground/src/views/examples/doc-button.vue
delete mode 100644 playground/src/views/examples/drawer/auto-height-demo.vue
delete mode 100644 playground/src/views/examples/drawer/base-demo.vue
delete mode 100644 playground/src/views/examples/drawer/dynamic-demo.vue
delete mode 100644 playground/src/views/examples/drawer/form-drawer-demo.vue
delete mode 100644 playground/src/views/examples/drawer/in-content-demo.vue
delete mode 100644 playground/src/views/examples/drawer/index.vue
delete mode 100644 playground/src/views/examples/drawer/shared-data-demo.vue
delete mode 100644 playground/src/views/examples/ellipsis/index.vue
delete mode 100644 playground/src/views/examples/form/api.vue
delete mode 100644 playground/src/views/examples/form/basic.vue
delete mode 100644 playground/src/views/examples/form/custom-layout.vue
delete mode 100644 playground/src/views/examples/form/custom.vue
delete mode 100644 playground/src/views/examples/form/dynamic.vue
delete mode 100644 playground/src/views/examples/form/merge.vue
delete mode 100644 playground/src/views/examples/form/modules/two-fields.vue
delete mode 100644 playground/src/views/examples/form/query.vue
delete mode 100644 playground/src/views/examples/form/rules.vue
delete mode 100644 playground/src/views/examples/form/scroll-to-error-test.vue
delete mode 100644 playground/src/views/examples/json-viewer/data.ts
delete mode 100644 playground/src/views/examples/json-viewer/index.vue
delete mode 100644 playground/src/views/examples/layout/col-page.vue
delete mode 100644 playground/src/views/examples/loading/index.vue
delete mode 100644 playground/src/views/examples/modal/auto-height-demo.vue
delete mode 100644 playground/src/views/examples/modal/base-demo.vue
delete mode 100644 playground/src/views/examples/modal/blur-demo.vue
delete mode 100644 playground/src/views/examples/modal/drag-demo.vue
delete mode 100644 playground/src/views/examples/modal/dynamic-demo.vue
delete mode 100644 playground/src/views/examples/modal/form-modal-demo.vue
delete mode 100644 playground/src/views/examples/modal/in-content-demo.vue
delete mode 100644 playground/src/views/examples/modal/index.vue
delete mode 100644 playground/src/views/examples/modal/nested-demo.vue
delete mode 100644 playground/src/views/examples/modal/shared-data-demo.vue
delete mode 100644 playground/src/views/examples/motion/index.vue
delete mode 100644 playground/src/views/examples/resize/basic.vue
delete mode 100644 playground/src/views/examples/tippy/index.vue
delete mode 100644 playground/src/views/examples/vxe-table/basic.vue
delete mode 100644 playground/src/views/examples/vxe-table/custom-cell.vue
delete mode 100644 playground/src/views/examples/vxe-table/edit-cell.vue
delete mode 100644 playground/src/views/examples/vxe-table/edit-row.vue
delete mode 100644 playground/src/views/examples/vxe-table/fixed.vue
delete mode 100644 playground/src/views/examples/vxe-table/form.vue
delete mode 100644 playground/src/views/examples/vxe-table/remote.vue
delete mode 100644 playground/src/views/examples/vxe-table/table-data.ts
delete mode 100644 playground/src/views/examples/vxe-table/tree.vue
delete mode 100644 playground/src/views/examples/vxe-table/virtual.vue
delete mode 100644 playground/src/views/system/dept/data.ts
delete mode 100644 playground/src/views/system/dept/list.vue
delete mode 100644 playground/src/views/system/dept/modules/form.vue
delete mode 100644 playground/src/views/system/menu/data.ts
delete mode 100644 playground/src/views/system/menu/list.vue
delete mode 100644 playground/src/views/system/menu/modules/form.vue
delete mode 100644 playground/src/views/system/role/data.ts
delete mode 100644 playground/src/views/system/role/list.vue
delete mode 100644 playground/src/views/system/role/modules/form.vue
delete mode 100644 playground/tailwind.config.mjs
delete mode 100644 playground/tsconfig.json
delete mode 100644 playground/tsconfig.node.json
delete mode 100644 playground/vite.config.mts
diff --git a/.vscode/launch.json b/.vscode/launch.json
index e9673304..0278f837 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -2,15 +2,6 @@
"$schema": "https://json.schemastore.org/launchsettings.json",
"version": "0.2.0",
"configurations": [
- {
- "type": "chrome",
- "name": "vben admin playground dev",
- "request": "launch",
- "url": "http://localhost:5555",
- "env": { "NODE_ENV": "development" },
- "sourceMaps": true,
- "webRoot": "${workspaceFolder}/playground"
- },
{
"type": "chrome",
"name": "vben admin antd dev",
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 7e5d3765..afeea814 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -199,7 +199,6 @@
"i18n-ally.localesPaths": [
"packages/locales/src/langs",
- "playground/src/locales/langs",
"apps/*/src/locales/langs"
],
"i18n-ally.pathMatcher": "{locale}/{namespace}.{ext}",
diff --git a/package.json b/package.json
index f012eb5d..5632fc35 100644
--- a/package.json
+++ b/package.json
@@ -31,7 +31,6 @@
"build:antd:test": "pnpm run build --filter=@vben/web-antd build:test",
"build:docker": "./scripts/deploy/build-local-docker-image.sh",
"build:docs": "pnpm run build --filter=@vben/docs",
- "build:play": "pnpm run build --filter=@vben/playground",
"changeset": "pnpm exec changeset",
"check": "pnpm run check:circular && pnpm run check:dep && pnpm run check:type && pnpm check:cspell",
"check:circular": "vsh check-circular",
@@ -43,7 +42,6 @@
"dev": "turbo-run dev",
"dev:antd": "pnpm -F @vben/web-antd run dev",
"dev:docs": "pnpm -F @vben/docs run dev",
- "dev:play": "pnpm -F @vben/playground run dev",
"format": "vsh lint --format",
"lint": "vsh lint",
"postinstall": "pnpm -r run stub --if-present",
diff --git a/playground/.env b/playground/.env
deleted file mode 100644
index 94ff4faf..00000000
--- a/playground/.env
+++ /dev/null
@@ -1,8 +0,0 @@
-# 应用标题
-VITE_APP_TITLE=Vben Admin
-
-# 应用命名空间,用于缓存、store等功能的前缀,确保隔离
-VITE_APP_NAMESPACE=vben-web-play
-
-# 对store进行加密的密钥,在将store持久化到localStorage时会使用该密钥进行加密
-VITE_APP_STORE_SECURE_KEY=please-replace-me-with-your-own-key
diff --git a/playground/.env.analyze b/playground/.env.analyze
deleted file mode 100644
index ffafa8dd..00000000
--- a/playground/.env.analyze
+++ /dev/null
@@ -1,7 +0,0 @@
-# public path
-VITE_BASE=/
-
-# Basic interface address SPA
-VITE_GLOB_API_URL=/api
-
-VITE_VISUALIZER=true
diff --git a/playground/.env.development b/playground/.env.development
deleted file mode 100644
index 0b1dc057..00000000
--- a/playground/.env.development
+++ /dev/null
@@ -1,20 +0,0 @@
-# 端口号
-VITE_PORT=5555
-
-VITE_BASE=/
-
-# 接口地址
-VITE_GLOB_API_URL=/api
-
-# 是否开启 Nitro Mock服务,true 为开启,false 为关闭
-VITE_NITRO_MOCK=true
-
-# 是否打开 devtools,true 为打开,false 为关闭
-VITE_DEVTOOLS=false
-
-# 是否注入全局loading
-VITE_INJECT_APP_LOADING=true
-
-# 钉钉登录配置
-VITE_GLOB_AUTH_DINGDING_CLIENT_ID=应用的clientId
-VITE_GLOB_AUTH_DINGDING_CORP_ID=应用的corpId
diff --git a/playground/.env.production b/playground/.env.production
deleted file mode 100644
index 5375847a..00000000
--- a/playground/.env.production
+++ /dev/null
@@ -1,19 +0,0 @@
-VITE_BASE=/
-
-# 接口地址
-VITE_GLOB_API_URL=https://mock-napi.vben.pro/api
-
-# 是否开启压缩,可以设置为 none, brotli, gzip
-VITE_COMPRESS=none
-
-# 是否开启 PWA
-VITE_PWA=false
-
-# vue-router 的模式
-VITE_ROUTER_HISTORY=hash
-
-# 是否注入全局loading
-VITE_INJECT_APP_LOADING=true
-
-# 打包后是否生成dist.zip
-VITE_ARCHIVER=true
diff --git a/playground/__tests__/e2e/auth-login.spec.ts b/playground/__tests__/e2e/auth-login.spec.ts
deleted file mode 100644
index bb6cd289..00000000
--- a/playground/__tests__/e2e/auth-login.spec.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import { expect, test } from '@playwright/test';
-
-import { authLogin } from './common/auth';
-
-test.beforeEach(async ({ page }) => {
- await page.goto('/');
-});
-
-test.describe('Auth Login Page Tests', () => {
- test('check title and page elements', async ({ page }) => {
- // 获取页面标题并断言标题包含 'Vben Admin'
- const title = await page.title();
- expect(title).toContain('Vben Admin');
- });
-
- // 测试用例: 成功登录
- test('should successfully login with valid credentials', async ({ page }) => {
- await authLogin(page);
- });
-});
diff --git a/playground/__tests__/e2e/common/auth.ts b/playground/__tests__/e2e/common/auth.ts
deleted file mode 100644
index 26b526fd..00000000
--- a/playground/__tests__/e2e/common/auth.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-import type { Page } from '@playwright/test';
-
-import { expect } from '@playwright/test';
-
-export async function authLogin(page: Page) {
- // 确保登录表单正常
- const usernameInput = await page.locator(`input[name='username']`);
- await expect(usernameInput).toBeVisible();
-
- const passwordInput = await page.locator(`input[name='password']`);
- await expect(passwordInput).toBeVisible();
-
- const sliderCaptcha = await page.locator(`div[name='captcha']`);
- const sliderCaptchaAction = await page.locator(`div[name='captcha-action']`);
- await expect(sliderCaptcha).toBeVisible();
- await expect(sliderCaptchaAction).toBeVisible();
-
- // 拖动验证码滑块
- // 获取拖动按钮的位置
- const sliderCaptchaBox = await sliderCaptcha.boundingBox();
- if (!sliderCaptchaBox) throw new Error('滑块未找到');
-
- const actionBoundingBox = await sliderCaptchaAction.boundingBox();
- if (!actionBoundingBox) throw new Error('要拖动的按钮未找到');
-
- // 计算起始位置和目标位置
- const startX = actionBoundingBox.x + actionBoundingBox.width / 2; // div 中心的 x 坐标
- const startY = actionBoundingBox.y + actionBoundingBox.height / 2; // div 中心的 y 坐标
-
- const targetX = startX + sliderCaptchaBox.width + actionBoundingBox.width; // 向右拖动容器的宽度
- const targetY = startY; // y 坐标保持不变
-
- // 模拟鼠标拖动
- await page.mouse.move(startX, startY); // 移动到 action 的中心
- await page.mouse.down(); // 按下鼠标
- await page.mouse.move(targetX, targetY, { steps: 20 }); // 拖动到目标位置
- await page.mouse.up(); // 松开鼠标
-
- // 在拖动后进行断言,检查action是否在预期位置,
- const newActionBoundingBox = await sliderCaptchaAction.boundingBox();
- expect(newActionBoundingBox?.x).toBeGreaterThan(actionBoundingBox.x);
-
- // 到这里已经校验成功,点击进行登录
- await page.waitForTimeout(300);
- await page.getByRole('button', { name: 'login' }).click();
-}
diff --git a/playground/index.html b/playground/index.html
deleted file mode 100644
index ca532699..00000000
--- a/playground/index.html
+++ /dev/null
@@ -1,35 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
- <%= VITE_APP_TITLE %>
-
-
-
-
-
-
-
-
diff --git a/playground/package.json b/playground/package.json
deleted file mode 100644
index a200475d..00000000
--- a/playground/package.json
+++ /dev/null
@@ -1,60 +0,0 @@
-{
- "name": "@vben/playground",
- "version": "5.5.9",
- "homepage": "https://vben.pro",
- "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
- "repository": {
- "type": "git",
- "url": "git+https://github.com/vbenjs/vue-vben-admin.git",
- "directory": "playground"
- },
- "license": "MIT",
- "author": {
- "name": "vben",
- "email": "ann.vben@gmail.com",
- "url": "https://github.com/anncwb"
- },
- "type": "module",
- "scripts": {
- "build": "pnpm vite build --mode production",
- "build:analyze": "pnpm vite build --mode analyze",
- "dev": "pnpm vite --mode development",
- "preview": "vite preview",
- "typecheck": "vue-tsc --noEmit --skipLibCheck",
- "test:e2e": "playwright test",
- "test:e2e-ui": "playwright test --ui",
- "test:e2e-codegen": "playwright codegen"
- },
- "imports": {
- "#/*": "./src/*"
- },
- "dependencies": {
- "@tanstack/vue-query": "catalog:",
- "@vben-core/menu-ui": "workspace:*",
- "@vben-core/shadcn-ui": "workspace:*",
- "@vben/access": "workspace:*",
- "@vben/common-ui": "workspace:*",
- "@vben/constants": "workspace:*",
- "@vben/hooks": "workspace:*",
- "@vben/icons": "workspace:*",
- "@vben/layouts": "workspace:*",
- "@vben/locales": "workspace:*",
- "@vben/plugins": "workspace:*",
- "@vben/preferences": "workspace:*",
- "@vben/request": "workspace:*",
- "@vben/stores": "workspace:*",
- "@vben/styles": "workspace:*",
- "@vben/types": "workspace:*",
- "@vben/utils": "workspace:*",
- "@vueuse/core": "catalog:",
- "antdv-next": "catalog:",
- "dayjs": "catalog:",
- "json-bigint": "catalog:",
- "pinia": "catalog:",
- "vue": "catalog:",
- "vue-router": "catalog:"
- },
- "devDependencies": {
- "@types/json-bigint": "catalog:"
- }
-}
diff --git a/playground/playwright.config.ts b/playground/playwright.config.ts
deleted file mode 100644
index ca0c9085..00000000
--- a/playground/playwright.config.ts
+++ /dev/null
@@ -1,108 +0,0 @@
-import type { PlaywrightTestConfig } from '@playwright/test';
-
-import { devices } from '@playwright/test';
-
-/**
- * Read environment variables from file.
- * https://github.com/motdotla/dotenv
- */
-// require('dotenv').config();
-
-/**
- * See https://playwright.dev/docs/test-configuration.
- */
-const config: PlaywrightTestConfig = {
- expect: {
- /**
- * Maximum time expect() should wait for the condition to be met.
- * For example in `await expect(locator).toHaveText();`
- */
- timeout: 5000,
- },
- /* Fail the build on CI if you accidentally left test.only in the source code. */
- forbidOnly: !!process.env.CI,
- /* Folder for test artifacts such as screenshots, videos, traces, etc. */
- outputDir: 'node_modules/.e2e/test-results/',
- /* Configure projects for major browsers */
- projects: [
- {
- name: 'chromium',
- use: {
- ...devices['Desktop Chrome'],
- },
- },
- // {
- // name: 'firefox',
- // use: {
- // ...devices['Desktop Firefox'],
- // },
- // },
- // {
- // name: 'webkit',
- // use: {
- // ...devices['Desktop Safari'],
- // },
- // },
-
- /* Test against mobile viewports. */
- // {
- // name: 'Mobile Chrome',
- // use: {
- // ...devices['Pixel 5'],
- // },
- // },
- // {
- // name: 'Mobile Safari',
- // use: {
- // ...devices['iPhone 12'],
- // },
- // },
-
- /* Test against branded browsers. */
- // {
- // name: 'Microsoft Edge',
- // use: {
- // channel: 'msedge',
- // },
- // },
- // {
- // name: 'Google Chrome',
- // use: {
- // channel: 'chrome',
- // },
- // },
- ],
- /* Reporter to use. See https://playwright.dev/docs/test-reporters */
- reporter: [
- ['list'],
- ['html', { outputFolder: 'node_modules/.e2e/test-results' }],
- ],
- /* Retry on CI only */
- retries: process.env.CI ? 2 : 0,
- testDir: './__tests__/e2e',
- /* Maximum time one test can run for. */
- timeout: 30 * 1000,
- /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
- use: {
- /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */
- actionTimeout: 0,
- /* Base URL to use in actions like `await page.goto('/')`. */
- baseURL: 'http://localhost:5555',
- /* Only on CI systems run the tests headless */
- headless: !!process.env.CI,
- /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
- trace: 'retain-on-failure',
- },
-
- /* Run your local dev server before starting the tests */
- webServer: {
- command: process.env.CI ? 'pnpm preview --port 5555' : 'pnpm dev',
- port: 5555,
- reuseExistingServer: !process.env.CI,
- },
-
- /* Opt out of parallel tests on CI. */
- workers: process.env.CI ? 1 : undefined,
-};
-
-export default config;
diff --git a/playground/postcss.config.mjs b/playground/postcss.config.mjs
deleted file mode 100644
index 3d807045..00000000
--- a/playground/postcss.config.mjs
+++ /dev/null
@@ -1 +0,0 @@
-export { default } from '@vben/tailwind-config/postcss';
diff --git a/playground/public/favicon.ico b/playground/public/favicon.ico
deleted file mode 100644
index fcf9818e2cf855039b272bdbfbb202d3ff3fa159..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 5430
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 import('antdv-next/es/auto-complete'),
-);
-const Button = defineAsyncComponent(() => import('antdv-next/es/button'));
-const Checkbox = defineAsyncComponent(() => import('antdv-next/es/checkbox'));
-const CheckboxGroup = defineAsyncComponent(() =>
- import('antdv-next/es/checkbox').then((res) => res.CheckboxGroup),
-);
-const DatePicker = defineAsyncComponent(
- () => import('antdv-next/es/date-picker'),
-);
-const Divider = defineAsyncComponent(() => import('antdv-next/es/divider'));
-const Input = defineAsyncComponent(() => import('antdv-next/es/input'));
-const InputNumber = defineAsyncComponent(
- () => import('antdv-next/es/input-number'),
-);
-const InputPassword = defineAsyncComponent(() =>
- import('antdv-next/es/input').then((res) => res.InputPassword),
-);
-const Mentions = defineAsyncComponent(() => import('antdv-next/es/mentions'));
-const Radio = defineAsyncComponent(() => import('antdv-next/es/radio'));
-const RadioGroup = defineAsyncComponent(() =>
- import('antdv-next/es/radio').then((res) => res.RadioGroup),
-);
-const RangePicker = defineAsyncComponent(() =>
- import('antdv-next/es/date-picker').then((res) => res.RangePicker),
-);
-const Rate = defineAsyncComponent(() => import('antdv-next/es/rate'));
-const Select = defineAsyncComponent(() => import('antdv-next/es/select'));
-const Space = defineAsyncComponent(() => import('antdv-next/es/space'));
-const Switch = defineAsyncComponent(() => import('antdv-next/es/switch'));
-const Textarea = defineAsyncComponent(() =>
- import('antdv-next/es/input').then((res) => res.Textarea),
-);
-const TimePicker = defineAsyncComponent(
- () => import('antdv-next/es/time-picker'),
-);
-const TreeSelect = defineAsyncComponent(
- () => import('antdv-next/es/tree-select'),
-);
-const Cascader = defineAsyncComponent(() => import('antdv-next/es/cascader'));
-const Upload = defineAsyncComponent(() => import('antdv-next/es/upload'));
-const Image = defineAsyncComponent(() => import('antdv-next/es/image'));
-const PreviewGroup = defineAsyncComponent(() =>
- import('antdv-next/es/image').then((res) => res.ImagePreviewGroup),
-);
-
-const withDefaultPlaceholder = (
- component: T,
- type: 'input' | 'select',
- componentProps: Recordable = {},
-) => {
- return defineComponent({
- name: component.name,
- inheritAttrs: false,
- setup: (props: any, { attrs, expose, slots }) => {
- const placeholder =
- props?.placeholder ||
- attrs?.placeholder ||
- $t(`ui.placeholder.${type}`);
- // 透传组件暴露的方法
- const innerRef = ref();
- expose(
- new Proxy(
- {},
- {
- get: (_target, key) => innerRef.value?.[key],
- has: (_target, key) => key in (innerRef.value || {}),
- },
- ),
- );
- return () =>
- h(
- component,
- { ...componentProps, placeholder, ...props, ...attrs, ref: innerRef },
- slots,
- );
- },
- });
-};
-
-const withPreviewUpload = () => {
- // 检查是否为图片文件的辅助函数
- const isImageFile = (file: UploadFile): boolean => {
- const imageExtensions = new Set([
- 'bmp',
- 'gif',
- 'jpeg',
- 'jpg',
- 'png',
- 'svg',
- 'webp',
- ]);
- if (file.url) {
- try {
- const pathname = new URL(file.url, 'http://localhost').pathname;
- const ext = pathname.split('.').pop()?.toLowerCase();
- return ext ? imageExtensions.has(ext) : false;
- } catch {
- const ext = file.url?.split('.').pop()?.toLowerCase();
- return ext ? imageExtensions.has(ext) : false;
- }
- }
- if (!file.type) {
- const ext = file.name?.split('.').pop()?.toLowerCase();
- return ext ? imageExtensions.has(ext) : false;
- }
- return file.type.startsWith('image/');
- };
- // 创建默认的上传按钮插槽
- const createDefaultSlotsWithUpload = (
- listType: string,
- placeholder: string,
- ) => {
- switch (listType) {
- case 'picture-card': {
- return {
- default: () => placeholder,
- };
- }
- default: {
- return {
- default: () =>
- h(
- Button,
- {
- icon: h(IconifyIcon, {
- icon: 'ant-design:upload-outlined',
- class: 'mb-1 size-4',
- }),
- },
- () => placeholder,
- ),
- };
- }
- }
- };
- // 构建预览图片组
- const previewImage = async (
- file: UploadFile,
- visible: Ref,
- fileList: Ref,
- ) => {
- // 如果当前文件不是图片,直接打开
- if (!isImageFile(file)) {
- if (file.url) {
- window.open(file.url, '_blank');
- } else if (file.preview) {
- window.open(file.preview, '_blank');
- } else {
- message.error($t('ui.formRules.previewWarning'));
- }
- return;
- }
-
- // 对于图片文件,继续使用预览组
- const [ImageComponent, PreviewGroupComponent] = await Promise.all([
- Image,
- PreviewGroup,
- ]);
-
- const getBase64 = (file: File) => {
- return new Promise((resolve, reject) => {
- const reader = new FileReader();
- reader.readAsDataURL(file);
- reader.addEventListener('load', () => resolve(reader.result));
- reader.addEventListener('error', (error) => reject(error));
- });
- };
- // 从fileList中过滤出所有图片文件
- const imageFiles = (unref(fileList) || []).filter((element) =>
- isImageFile(element),
- );
-
- // 为所有没有预览地址的图片生成预览
- for (const imgFile of imageFiles) {
- if (!imgFile.url && !imgFile.preview && imgFile.originFileObj) {
- imgFile.preview = (await getBase64(imgFile.originFileObj)) as string;
- }
- }
- const container: HTMLElement | null = document.createElement('div');
- document.body.append(container);
-
- // 用于追踪组件是否已卸载
- let isUnmounted = false;
-
- const PreviewWrapper = {
- setup() {
- return () => {
- if (isUnmounted) return null;
- return h(
- PreviewGroupComponent,
- {
- class: 'hidden',
- preview: {
- visible: visible.value,
- // 设置初始显示的图片索引
- current: imageFiles.findIndex((f) => f.uid === file.uid),
- onVisibleChange: (value: boolean) => {
- visible.value = value;
- if (!value) {
- // 延迟清理,确保动画完成
- setTimeout(() => {
- if (!isUnmounted && container) {
- isUnmounted = true;
- render(null, container);
- container.remove();
- }
- }, 300);
- }
- },
- },
- },
- () =>
- // 渲染所有图片文件
- imageFiles.map((imgFile) =>
- h(ImageComponent, {
- key: imgFile.uid,
- src: imgFile.url || imgFile.preview,
- }),
- ),
- );
- };
- },
- };
-
- render(h(PreviewWrapper), container);
- };
-
- // 图片裁剪操作
- const cropImage = (file: File, aspectRatio: string | undefined) => {
- return new Promise((resolve, reject) => {
- const container: HTMLElement | null = document.createElement('div');
- document.body.append(container);
-
- // 用于追踪组件是否已卸载
- let isUnmounted = false;
- let objectUrl: null | string = null;
-
- const open = ref(true);
- const cropperRef = ref | null>(null);
-
- const closeModal = () => {
- open.value = false;
- // 延迟清理,确保动画完成
- setTimeout(() => {
- if (!isUnmounted && container) {
- if (objectUrl) {
- URL.revokeObjectURL(objectUrl);
- }
- isUnmounted = true;
- render(null, container);
- container.remove();
- }
- }, 300);
- };
-
- const CropperWrapper = {
- setup() {
- return () => {
- if (isUnmounted) return null;
- if (!objectUrl) {
- objectUrl = URL.createObjectURL(file);
- }
- return h(
- Modal,
- {
- open: open.value,
- title: h('div', {}, [
- $t('ui.crop.title'),
- h(
- 'span',
- {
- class: `${aspectRatio ? '' : 'hidden'} ml-2 text-sm text-gray-400 font-normal`,
- },
- $t('ui.crop.titleTip', [aspectRatio]),
- ),
- ]),
- centered: true,
- width: 548,
- keyboard: false,
- maskClosable: false,
- closable: false,
- cancelText: $t('common.cancel'),
- okText: $t('ui.crop.confirm'),
- destroyOnClose: true,
- onOk: async () => {
- const cropper = cropperRef.value;
- if (!cropper) {
- reject(new Error('Cropper not found'));
- closeModal();
- return;
- }
- try {
- const dataUrl = await cropper.getCropImage();
- resolve(dataUrl);
- } catch {
- reject(new Error($t('ui.crop.errorTip')));
- } finally {
- closeModal();
- }
- },
- onCancel() {
- resolve('');
- closeModal();
- },
- },
- () =>
- h(VCropper, {
- ref: (ref: any) => (cropperRef.value = ref),
- img: objectUrl as string,
- aspectRatio,
- }),
- );
- };
- },
- };
-
- render(h(CropperWrapper), container);
- });
- };
-
- return defineComponent({
- name: Upload.name,
- emits: ['update:modelValue'],
- setup: (
- props: any,
- { attrs, slots, emit }: { attrs: any; emit: any; slots: any },
- ) => {
- const previewVisible = ref(false);
-
- const placeholder = attrs?.placeholder || $t(`ui.placeholder.upload`);
-
- const listType = attrs?.listType || attrs?.['list-type'] || 'text';
-
- const fileList = ref(
- attrs?.fileList || attrs?.['file-list'] || [],
- );
-
- const maxSize = computed(() => attrs?.maxSize ?? attrs?.['max-size']);
- const aspectRatio = computed(
- () => attrs?.aspectRatio ?? attrs?.['aspect-ratio'],
- );
-
- const handleBeforeUpload = async (
- file: UploadFile,
- originFileList: Array,
- ) => {
- if (maxSize.value && (file.size || 0) / 1024 / 1024 > maxSize.value) {
- message.error($t('ui.formRules.sizeLimit', [maxSize.value]));
- file.status = 'removed';
- return false;
- }
- // 多选或者非图片不唤起裁剪框
- if (
- attrs.crop &&
- !attrs.multiple &&
- originFileList[0] &&
- isImageFile(file)
- ) {
- file.status = 'removed';
- // antd Upload组件问题 file参数获取的是UploadFile类型对象无法取到File类型 所以通过originFileList[0]获取
- const blob = await cropImage(originFileList[0], aspectRatio.value);
- return new Promise((resolve, reject) => {
- if (!blob) {
- return reject(new Error($t('ui.crop.errorTip')));
- }
- resolve(blob);
- });
- }
-
- return attrs.beforeUpload?.(file) ?? true;
- };
-
- const handleChange = (event: UploadChangeParam) => {
- try {
- // 行内写法 handleChange: (event) => {}
- attrs.handleChange?.(event);
- // template写法 @handle-change="(event) => {}"
- attrs.onHandleChange?.(event);
- } catch (error) {
- // Avoid breaking internal v-model sync on user handler errors
- console.error(error);
- }
- fileList.value = event.fileList.filter(
- (file) => file.status !== 'removed',
- );
- emit(
- 'update:modelValue',
- event.fileList?.length ? fileList.value : undefined,
- );
- };
-
- const handlePreview = async (file: UploadFile) => {
- previewVisible.value = true;
- await previewImage(file, previewVisible, fileList);
- };
-
- const renderUploadButton = (): any => {
- const isDisabled = attrs.disabled;
-
- // 如果禁用,不渲染上传按钮
- if (isDisabled) {
- return null;
- }
-
- // 否则渲染默认上传按钮
- return isEmpty(slots)
- ? createDefaultSlotsWithUpload(listType, placeholder)
- : slots;
- };
-
- // 可以监听到表单API设置的值
- watch(
- () => attrs.modelValue,
- (res) => {
- fileList.value = res;
- },
- );
-
- return () =>
- h(
- Upload,
- {
- ...props,
- ...attrs,
- fileList: fileList.value,
- beforeUpload: handleBeforeUpload,
- onChange: handleChange,
- onPreview: handlePreview,
- },
- renderUploadButton(),
- );
- },
- });
-};
-
-// 这里需要自行根据业务组件库进行适配,需要用到的组件都需要在这里类型说明
-export type ComponentType =
- | 'ApiCascader'
- | 'ApiSelect'
- | 'ApiTreeSelect'
- | 'AutoComplete'
- | 'Cascader'
- | 'Checkbox'
- | 'CheckboxGroup'
- | 'DatePicker'
- | 'DefaultButton'
- | 'Divider'
- | 'IconPicker'
- | 'Input'
- | 'InputNumber'
- | 'InputPassword'
- | 'Mentions'
- | 'PrimaryButton'
- | 'Radio'
- | 'RadioGroup'
- | 'RangePicker'
- | 'Rate'
- | 'Select'
- | 'Space'
- | 'Switch'
- | 'Textarea'
- | 'TimePicker'
- | 'TreeSelect'
- | 'Upload'
- | BaseFormComponentType;
-
-async function initComponentAdapter() {
- const components: Partial> = {
- // 如果你的组件体积比较大,可以使用异步加载
- // Button: () =>
- // import('xxx').then((res) => res.Button),
-
- ApiCascader: withDefaultPlaceholder(ApiComponent, 'select', {
- component: Cascader,
- fieldNames: { label: 'label', value: 'value', children: 'children' },
- loadingSlot: 'suffixIcon',
- modelPropName: 'value',
- visibleEvent: 'onVisibleChange',
- }),
- ApiSelect: withDefaultPlaceholder(ApiComponent, 'select', {
- component: Select,
- loadingSlot: 'suffixIcon',
- modelPropName: 'value',
- visibleEvent: 'onVisibleChange',
- }),
- ApiTreeSelect: withDefaultPlaceholder(ApiComponent, 'select', {
- component: TreeSelect,
- fieldNames: { label: 'label', value: 'value', children: 'children' },
- loadingSlot: 'suffixIcon',
- modelPropName: 'value',
- optionsPropName: 'treeData',
- visibleEvent: 'onVisibleChange',
- }),
- AutoComplete,
- Cascader,
- Checkbox,
- CheckboxGroup,
- DatePicker,
- // 自定义默认按钮
- DefaultButton: (props, { attrs, slots }) => {
- return h(Button, { ...props, attrs, type: 'default' }, slots);
- },
- Divider,
- IconPicker: withDefaultPlaceholder(IconPicker, 'select', {
- iconSlot: 'addonAfter',
- inputComponent: Input,
- modelValueProp: 'value',
- }),
- Input: withDefaultPlaceholder(Input, 'input'),
- InputNumber: withDefaultPlaceholder(InputNumber, 'input'),
- InputPassword: withDefaultPlaceholder(InputPassword, 'input'),
- Mentions: withDefaultPlaceholder(Mentions, 'input'),
- // 自定义主要按钮
- PrimaryButton: (props, { attrs, slots }) => {
- return h(Button, { ...props, attrs, type: 'primary' }, slots);
- },
- Radio,
- RadioGroup,
- RangePicker,
- Rate,
- Select: withDefaultPlaceholder(Select, 'select'),
- Space,
- Switch,
- Textarea: withDefaultPlaceholder(Textarea, 'input'),
- TimePicker,
- TreeSelect: withDefaultPlaceholder(TreeSelect, 'select'),
- Upload: withPreviewUpload(),
- };
-
- // 将组件注册到全局共享状态中
- globalShareState.setComponents(components);
-
- // 定义全局共享状态中的消息提示
- globalShareState.defineMessage({
- // 复制成功消息提示
- copyPreferencesSuccess: (title, content) => {
- notification.success({
- description: content,
- message: title,
- placement: 'bottomRight',
- });
- },
- });
-}
-
-export { initComponentAdapter };
diff --git a/playground/src/adapter/form.ts b/playground/src/adapter/form.ts
deleted file mode 100644
index c5589aab..00000000
--- a/playground/src/adapter/form.ts
+++ /dev/null
@@ -1,47 +0,0 @@
-import type {
- VbenFormSchema as FormSchema,
- VbenFormProps,
-} from '@vben/common-ui';
-
-import type { ComponentType } from './component';
-
-import { setupVbenForm, useVbenForm as useForm, z } from '@vben/common-ui';
-import { $t } from '@vben/locales';
-
-async function initSetupVbenForm() {
- setupVbenForm({
- config: {
- // ant design vue组件库默认都是 v-model:value
- baseModelPropName: 'value',
- // 一些组件是 v-model:checked 或者 v-model:fileList
- modelPropNameMap: {
- Checkbox: 'checked',
- Radio: 'checked',
- Switch: 'checked',
- Upload: 'fileList',
- },
- },
- defineRules: {
- // 输入项目必填国际化适配
- required: (value, _params, ctx) => {
- if (value === undefined || value === null || value.length === 0) {
- return $t('ui.formRules.required', [ctx.label]);
- }
- return true;
- },
- // 选择项目必填国际化适配
- selectRequired: (value, _params, ctx) => {
- if (value === undefined || value === null) {
- return $t('ui.formRules.selectRequired', [ctx.label]);
- }
- return true;
- },
- },
- });
-}
-
-const useVbenForm = useForm;
-
-export { initSetupVbenForm, useVbenForm, z };
-export type VbenFormSchema = FormSchema;
-export type { VbenFormProps };
diff --git a/playground/src/adapter/vxe-table.ts b/playground/src/adapter/vxe-table.ts
deleted file mode 100644
index 617aa015..00000000
--- a/playground/src/adapter/vxe-table.ts
+++ /dev/null
@@ -1,298 +0,0 @@
-import type { VxeTableGridOptions } from '@vben/plugins/vxe-table';
-import type { Recordable } from '@vben/types';
-
-import type { ComponentType } from './component';
-
-import { h } from 'vue';
-
-import { IconifyIcon } from '@vben/icons';
-import { $te } from '@vben/locales';
-import {
- setupVbenVxeTable,
- useVbenVxeGrid as useGrid,
-} from '@vben/plugins/vxe-table';
-import { get, isFunction, isString } from '@vben/utils';
-
-import { objectOmit } from '@vueuse/core';
-import { Button, Image, Popconfirm, Switch, Tag } from 'antdv-next';
-
-import { $t } from '#/locales';
-
-import { useVbenForm } from './form';
-
-setupVbenVxeTable({
- configVxeTable: (vxeUI) => {
- vxeUI.setConfig({
- grid: {
- align: 'center',
- border: false,
- columnConfig: {
- resizable: true,
- },
-
- formConfig: {
- // 全局禁用vxe-table的表单配置,使用formOptions
- enabled: false,
- },
- minHeight: 180,
- proxyConfig: {
- autoLoad: true,
- response: {
- result: 'items',
- total: 'total',
- list: '',
- },
- showActiveMsg: true,
- showResponseMsg: false,
- },
- round: true,
- showOverflow: true,
- size: 'small',
- } as VxeTableGridOptions,
- });
-
- /**
- * 解决vxeTable在热更新时可能会出错的问题
- */
- vxeUI.renderer.forEach((_item, key) => {
- if (key.startsWith('Cell')) {
- vxeUI.renderer.delete(key);
- }
- });
-
- // 表格配置项可以用 cellRender: { name: 'CellImage' },
- vxeUI.renderer.add('CellImage', {
- renderTableDefault(renderOpts, params) {
- const { props } = renderOpts;
- const { column, row } = params;
- return h(Image, { src: row[column.field], ...props });
- },
- });
-
- // 表格配置项可以用 cellRender: { name: 'CellLink' },
- vxeUI.renderer.add('CellLink', {
- renderTableDefault(renderOpts) {
- const { props } = renderOpts;
- return h(
- Button,
- { size: 'small', type: 'link' },
- { default: () => props?.text },
- );
- },
- });
-
- // 单元格渲染: Tag
- vxeUI.renderer.add('CellTag', {
- renderTableDefault({ options, props }, { column, row }) {
- const value = get(row, column.field);
- const tagOptions = options ?? [
- { color: 'success', label: $t('common.enabled'), value: 1 },
- { color: 'error', label: $t('common.disabled'), value: 0 },
- ];
- const tagItem = tagOptions.find((item) => item.value === value);
- return h(
- Tag,
- {
- ...props,
- ...objectOmit(tagItem ?? {}, ['label']),
- },
- { default: () => tagItem?.label ?? value },
- );
- },
- });
-
- vxeUI.renderer.add('CellSwitch', {
- renderTableDefault({ attrs, props }, { column, row }) {
- const loadingKey = `__loading_${column.field}`;
- const finallyProps = {
- checkedChildren: $t('common.enabled'),
- checkedValue: 1,
- unCheckedChildren: $t('common.disabled'),
- unCheckedValue: 0,
- ...props,
- checked: row[column.field],
- loading: row[loadingKey] ?? false,
- 'onUpdate:checked': onChange,
- };
- async function onChange(newVal: any) {
- row[loadingKey] = true;
- try {
- const result = await attrs?.beforeChange?.(newVal, row);
- if (result !== false) {
- row[column.field] = newVal;
- }
- } finally {
- row[loadingKey] = false;
- }
- }
- return h(Switch, finallyProps);
- },
- });
-
- /**
- * 注册表格的操作按钮渲染器
- */
- vxeUI.renderer.add('CellOperation', {
- renderTableDefault({ attrs, options, props }, { column, row }) {
- const defaultProps = { size: 'small', type: 'link', ...props };
- let align = 'end';
- switch (column.align) {
- case 'center': {
- align = 'center';
- break;
- }
- case 'left': {
- align = 'start';
- break;
- }
- default: {
- align = 'end';
- break;
- }
- }
- const presets: Recordable> = {
- delete: {
- danger: true,
- text: $t('common.delete'),
- },
- edit: {
- text: $t('common.edit'),
- },
- };
- const operations: Array> = (
- options || ['edit', 'delete']
- )
- .map((opt) => {
- if (isString(opt)) {
- return presets[opt]
- ? { code: opt, ...presets[opt], ...defaultProps }
- : {
- code: opt,
- text: $te(`common.${opt}`) ? $t(`common.${opt}`) : opt,
- ...defaultProps,
- };
- } else {
- return { ...defaultProps, ...presets[opt.code], ...opt };
- }
- })
- .map((opt) => {
- const optBtn: Recordable = {};
- Object.keys(opt).forEach((key) => {
- optBtn[key] = isFunction(opt[key]) ? opt[key](row) : opt[key];
- });
- return optBtn;
- })
- .filter((opt) => opt.show !== false);
-
- function renderBtn(opt: Recordable, listen = true) {
- return h(
- Button,
- {
- ...props,
- ...opt,
- icon: undefined,
- onClick: listen
- ? () =>
- attrs?.onClick?.({
- code: opt.code,
- row,
- })
- : undefined,
- },
- {
- default: () => {
- const content = [];
- if (opt.icon) {
- content.push(
- h(IconifyIcon, { class: 'size-5', icon: opt.icon }),
- );
- }
- content.push(opt.text);
- return content;
- },
- },
- );
- }
-
- function renderConfirm(opt: Recordable) {
- let viewportWrapper: HTMLElement | null = null;
- return h(
- Popconfirm,
- {
- /**
- * 当popconfirm用在固定列中时,将固定列作为弹窗的容器时可能会因为固定列较窄而无法容纳弹窗
- * 将表格主体区域作为弹窗容器时又会因为固定列的层级较高而遮挡弹窗
- * 将body或者表格视口区域作为弹窗容器时又会导致弹窗无法跟随表格滚动。
- * 鉴于以上各种情况,一种折中的解决方案是弹出层展示时,禁止操作表格的滚动条。
- * 这样既解决了弹窗的遮挡问题,又不至于让弹窗随着表格的滚动而跑出视口区域。
- */
- getPopupContainer(el) {
- viewportWrapper = el.closest('.vxe-table--viewport-wrapper');
- return document.body;
- },
- placement: 'topLeft',
- title: $t('ui.actionTitle.delete', [attrs?.nameTitle || '']),
- ...props,
- ...opt,
- icon: undefined,
- onOpenChange: (open: boolean) => {
- // 当弹窗打开时,禁止表格的滚动
- if (open) {
- viewportWrapper?.style.setProperty('pointer-events', 'none');
- } else {
- viewportWrapper?.style.removeProperty('pointer-events');
- }
- },
- onConfirm: () => {
- attrs?.onClick?.({
- code: opt.code,
- row,
- });
- },
- },
- {
- default: () => renderBtn({ ...opt }, false),
- description: () =>
- h(
- 'div',
- { class: 'truncate' },
- $t('ui.actionMessage.deleteConfirm', [
- row[attrs?.nameField || 'name'],
- ]),
- ),
- },
- );
- }
-
- const btns = operations.map((opt) =>
- opt.code === 'delete' ? renderConfirm(opt) : renderBtn(opt),
- );
- return h(
- 'div',
- {
- class: 'flex table-operations',
- style: { justifyContent: align },
- },
- btns,
- );
- },
- });
-
- // 这里可以自行扩展 vxe-table 的全局配置,比如自定义格式化
- // vxeUI.formats.add
- },
- useVbenForm,
-});
-
-export const useVbenVxeGrid = >(
- ...rest: Parameters>
-) => useGrid(...rest);
-
-export type OnActionClickParams> = {
- code: string;
- row: T;
-};
-export type OnActionClickFn> = (
- params: OnActionClickParams,
-) => void;
-export type * from '@vben/plugins/vxe-table';
diff --git a/playground/src/api/core/auth.ts b/playground/src/api/core/auth.ts
deleted file mode 100644
index b4627cbe..00000000
--- a/playground/src/api/core/auth.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-import { baseRequestClient, requestClient } from '#/api/request';
-
-export namespace AuthApi {
- /** 登录接口参数 */
- export interface LoginParams {
- password?: string;
- username?: string;
- }
-
- /** 登录接口返回值 */
- export interface LoginResult {
- accessToken: string;
- }
-
- export interface RefreshTokenResult {
- data: string;
- status: number;
- }
-}
-
-/**
- * 登录
- */
-export async function loginApi(data: AuthApi.LoginParams) {
- return requestClient.post('/auth/login', data, {
- withCredentials: true,
- });
-}
-
-/**
- * 刷新accessToken
- */
-export async function refreshTokenApi() {
- return baseRequestClient.post(
- '/auth/refresh',
- null,
- {
- withCredentials: true,
- },
- );
-}
-
-/**
- * 退出登录
- */
-export async function logoutApi() {
- return baseRequestClient.post('/auth/logout', null, {
- withCredentials: true,
- });
-}
-
-/**
- * 获取用户权限码
- */
-export async function getAccessCodesApi() {
- return requestClient.get('/auth/codes');
-}
diff --git a/playground/src/api/core/index.ts b/playground/src/api/core/index.ts
deleted file mode 100644
index 7134366b..00000000
--- a/playground/src/api/core/index.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export * from './auth';
-export * from './menu';
-export * from './timezone';
-export * from './user';
diff --git a/playground/src/api/core/menu.ts b/playground/src/api/core/menu.ts
deleted file mode 100644
index 9ef60b11..00000000
--- a/playground/src/api/core/menu.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import type { RouteRecordStringComponent } from '@vben/types';
-
-import { requestClient } from '#/api/request';
-
-/**
- * 获取用户所有菜单
- */
-export async function getAllMenusApi() {
- return requestClient.get('/menu/all');
-}
diff --git a/playground/src/api/core/timezone.ts b/playground/src/api/core/timezone.ts
deleted file mode 100644
index 13d44d19..00000000
--- a/playground/src/api/core/timezone.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import { requestClient } from '#/api/request';
-
-/**
- * 获取系统支持的时区列表
- */
-export async function getTimezoneOptionsApi() {
- return await requestClient.get<
- {
- label: string;
- value: string;
- }[]
- >('/timezone/getTimezoneOptions');
-}
-/**
- * 获取用户时区
- */
-export async function getTimezoneApi(): Promise {
- return requestClient.get('/timezone/getTimezone');
-}
-/**
- * 设置用户时区
- * @param timezone 时区
- */
-export async function setTimezoneApi(timezone: string): Promise {
- return requestClient.post('/timezone/setTimezone', { timezone });
-}
diff --git a/playground/src/api/core/user.ts b/playground/src/api/core/user.ts
deleted file mode 100644
index 7e28ea84..00000000
--- a/playground/src/api/core/user.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import type { UserInfo } from '@vben/types';
-
-import { requestClient } from '#/api/request';
-
-/**
- * 获取用户信息
- */
-export async function getUserInfoApi() {
- return requestClient.get('/user/info');
-}
diff --git a/playground/src/api/examples/download.ts b/playground/src/api/examples/download.ts
deleted file mode 100644
index 0b4dcd36..00000000
--- a/playground/src/api/examples/download.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import type { RequestResponse } from '@vben/request';
-
-import { requestClient } from '../request';
-
-/**
- * 下载文件,获取Blob
- * @returns Blob
- */
-async function downloadFile1() {
- return requestClient.download(
- 'https://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1.webp',
- );
-}
-
-/**
- * 下载文件,获取完整的Response
- * @returns RequestResponse
- */
-async function downloadFile2() {
- return requestClient.download>(
- 'https://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1.webp',
- {
- responseReturn: 'raw',
- },
- );
-}
-
-export { downloadFile1, downloadFile2 };
diff --git a/playground/src/api/examples/index.ts b/playground/src/api/examples/index.ts
deleted file mode 100644
index c830b81f..00000000
--- a/playground/src/api/examples/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export * from './status';
-export * from './table';
diff --git a/playground/src/api/examples/json-bigint.ts b/playground/src/api/examples/json-bigint.ts
deleted file mode 100644
index 19e41e2e..00000000
--- a/playground/src/api/examples/json-bigint.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import { requestClient } from '#/api/request';
-
-/**
- * 发起请求
- */
-async function getBigIntData() {
- return requestClient.get('/demo/bigint');
-}
-
-export { getBigIntData };
diff --git a/playground/src/api/examples/params.ts b/playground/src/api/examples/params.ts
deleted file mode 100644
index 6568ec64..00000000
--- a/playground/src/api/examples/params.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import type { Recordable } from '@vben/types';
-
-import { requestClient } from '#/api/request';
-
-/**
- * 发起数组请求
- */
-async function getParamsData(
- params: Recordable,
- type: 'brackets' | 'comma' | 'indices' | 'repeat',
-) {
- return requestClient.get('/status', {
- params,
- paramsSerializer: type,
- responseReturn: 'raw',
- });
-}
-
-export { getParamsData };
diff --git a/playground/src/api/examples/status.ts b/playground/src/api/examples/status.ts
deleted file mode 100644
index 4a75fe7e..00000000
--- a/playground/src/api/examples/status.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import { requestClient } from '#/api/request';
-
-/**
- * 模拟任意状态码
- */
-async function getMockStatusApi(status: string) {
- return requestClient.get('/status', { params: { status } });
-}
-
-export { getMockStatusApi };
diff --git a/playground/src/api/examples/table.ts b/playground/src/api/examples/table.ts
deleted file mode 100644
index 4739ca98..00000000
--- a/playground/src/api/examples/table.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { requestClient } from '#/api/request';
-
-export namespace DemoTableApi {
- export interface PageFetchParams {
- [key: string]: any;
- page: number;
- pageSize: number;
- }
-}
-
-/**
- * 获取示例表格数据
- */
-async function getExampleTableApi(params: DemoTableApi.PageFetchParams) {
- return requestClient.get('/table/list', { params });
-}
-
-export { getExampleTableApi };
diff --git a/playground/src/api/examples/upload.ts b/playground/src/api/examples/upload.ts
deleted file mode 100644
index 246d4f26..00000000
--- a/playground/src/api/examples/upload.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import { requestClient } from '#/api/request';
-
-interface UploadFileParams {
- file: File;
- onError?: (error: Error) => void;
- onProgress?: (progress: { percent: number }) => void;
- onSuccess?: (data: any, file: File) => void;
-}
-export async function upload_file({
- file,
- onError,
- onProgress,
- onSuccess,
-}: UploadFileParams) {
- try {
- onProgress?.({ percent: 0 });
-
- const data = await requestClient.upload('/upload', { file });
-
- onProgress?.({ percent: 100 });
- onSuccess?.(data, file);
- } catch (error) {
- onError?.(error instanceof Error ? error : new Error(String(error)));
- }
-}
diff --git a/playground/src/api/index.ts b/playground/src/api/index.ts
deleted file mode 100644
index 3c3fa0d2..00000000
--- a/playground/src/api/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export * from './core';
-export * from './examples';
-export * from './system';
diff --git a/playground/src/api/request.ts b/playground/src/api/request.ts
deleted file mode 100644
index 3aebcce6..00000000
--- a/playground/src/api/request.ts
+++ /dev/null
@@ -1,133 +0,0 @@
-/**
- * 该文件可自行根据业务逻辑进行调整
- */
-import type { AxiosResponseHeaders, RequestClientOptions } from '@vben/request';
-
-import { useAppConfig } from '@vben/hooks';
-import { preferences } from '@vben/preferences';
-import {
- authenticateResponseInterceptor,
- defaultResponseInterceptor,
- errorMessageResponseInterceptor,
- RequestClient,
-} from '@vben/request';
-import { useAccessStore } from '@vben/stores';
-import { cloneDeep } from '@vben/utils';
-
-import { message } from 'antdv-next';
-import JSONBigInt from 'json-bigint';
-
-import { useAuthStore } from '#/store';
-
-import { refreshTokenApi } from './core';
-
-const { apiURL } = useAppConfig(import.meta.env, import.meta.env.PROD);
-
-function createRequestClient(baseURL: string, options?: RequestClientOptions) {
- const client = new RequestClient({
- ...options,
- baseURL,
- transformResponse: (data: any, header: AxiosResponseHeaders) => {
- // storeAsString指示将BigInt存储为字符串,设为false则会存储为内置的BigInt类型
- if (
- header.getContentType()?.toString().includes('application/json') &&
- typeof data === 'string'
- ) {
- return cloneDeep(
- JSONBigInt({ storeAsString: true, strict: true }).parse(data),
- );
- }
- return data;
- },
- });
-
- /**
- * 重新认证逻辑
- */
- async function doReAuthenticate() {
- console.warn('Access token or refresh token is invalid or expired. ');
- const accessStore = useAccessStore();
- const authStore = useAuthStore();
- accessStore.setAccessToken(null);
- if (
- preferences.app.loginExpiredMode === 'modal' &&
- accessStore.isAccessChecked
- ) {
- accessStore.setLoginExpired(true);
- } else {
- await authStore.logout();
- }
- }
-
- /**
- * 刷新token逻辑
- */
- async function doRefreshToken() {
- const accessStore = useAccessStore();
- const resp = await refreshTokenApi();
- const newToken = resp.data;
- accessStore.setAccessToken(newToken);
- return newToken;
- }
-
- function formatToken(token: null | string) {
- return token ? `Bearer ${token}` : null;
- }
-
- // 请求头处理
- client.addRequestInterceptor({
- fulfilled: async (config) => {
- const accessStore = useAccessStore();
-
- config.headers.Authorization = formatToken(accessStore.accessToken);
- config.headers['Accept-Language'] = preferences.app.locale;
- return config;
- },
- });
-
- // 处理返回的响应数据格式
- client.addResponseInterceptor(
- defaultResponseInterceptor({
- codeField: 'code',
- dataField: 'data',
- successCode: 0,
- }),
- );
-
- // token过期的处理
- client.addResponseInterceptor(
- authenticateResponseInterceptor({
- client,
- doReAuthenticate,
- doRefreshToken,
- enableRefreshToken: preferences.app.enableRefreshToken,
- formatToken,
- }),
- );
-
- // 通用的错误处理,如果没有进入上面的错误处理逻辑,就会进入这里
- client.addResponseInterceptor(
- errorMessageResponseInterceptor((msg: string, error) => {
- // 这里可以根据业务进行定制,你可以拿到 error 内的信息进行定制化处理,根据不同的 code 做不同的提示,而不是直接使用 message.error 提示 msg
- // 当前mock接口返回的错误字段是 error 或者 message
- const responseData = error?.response?.data ?? {};
- const errorMessage = responseData?.error ?? responseData?.message ?? '';
- // 如果没有错误信息,则会根据状态码进行提示
- message.error(errorMessage || msg);
- }),
- );
-
- return client;
-}
-
-export const requestClient = createRequestClient(apiURL, {
- responseReturn: 'data',
-});
-
-export const baseRequestClient = new RequestClient({ baseURL: apiURL });
-
-export interface PageFetchParams {
- [key: string]: any;
- pageNo?: number;
- pageSize?: number;
-}
diff --git a/playground/src/api/system/dept.ts b/playground/src/api/system/dept.ts
deleted file mode 100644
index ce2b0de8..00000000
--- a/playground/src/api/system/dept.ts
+++ /dev/null
@@ -1,54 +0,0 @@
-import { requestClient } from '#/api/request';
-
-export namespace SystemDeptApi {
- export interface SystemDept {
- [key: string]: any;
- children?: SystemDept[];
- id: string;
- name: string;
- remark?: string;
- status: 0 | 1;
- }
-}
-
-/**
- * 获取部门列表数据
- */
-async function getDeptList() {
- return requestClient.get>(
- '/system/dept/list',
- );
-}
-
-/**
- * 创建部门
- * @param data 部门数据
- */
-async function createDept(
- data: Omit,
-) {
- return requestClient.post('/system/dept', data);
-}
-
-/**
- * 更新部门
- *
- * @param id 部门 ID
- * @param data 部门数据
- */
-async function updateDept(
- id: string,
- data: Omit,
-) {
- return requestClient.put(`/system/dept/${id}`, data);
-}
-
-/**
- * 删除部门
- * @param id 部门 ID
- */
-async function deleteDept(id: string) {
- return requestClient.delete(`/system/dept/${id}`);
-}
-
-export { createDept, deleteDept, getDeptList, updateDept };
diff --git a/playground/src/api/system/index.ts b/playground/src/api/system/index.ts
deleted file mode 100644
index f2a248f1..00000000
--- a/playground/src/api/system/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export * from './dept';
-export * from './menu';
-export * from './role';
diff --git a/playground/src/api/system/menu.ts b/playground/src/api/system/menu.ts
deleted file mode 100644
index 507a5aec..00000000
--- a/playground/src/api/system/menu.ts
+++ /dev/null
@@ -1,158 +0,0 @@
-import type { Recordable } from '@vben/types';
-
-import { requestClient } from '#/api/request';
-
-export namespace SystemMenuApi {
- /** 徽标颜色集合 */
- export const BadgeVariants = [
- 'default',
- 'destructive',
- 'primary',
- 'success',
- 'warning',
- ] as const;
- /** 徽标类型集合 */
- export const BadgeTypes = ['dot', 'normal'] as const;
- /** 菜单类型集合 */
- export const MenuTypes = [
- 'catalog',
- 'menu',
- 'embedded',
- 'link',
- 'button',
- ] as const;
- /** 系统菜单 */
- export interface SystemMenu {
- [key: string]: any;
- /** 后端权限标识 */
- authCode: string;
- /** 子级 */
- children?: SystemMenu[];
- /** 组件 */
- component?: string;
- /** 菜单ID */
- id: string;
- /** 菜单元数据 */
- meta?: {
- /** 激活时显示的图标 */
- activeIcon?: string;
- /** 作为路由时,需要激活的菜单的Path */
- activePath?: string;
- /** 固定在标签栏 */
- affixTab?: boolean;
- /** 在标签栏固定的顺序 */
- affixTabOrder?: number;
- /** 徽标内容(当徽标类型为normal时有效) */
- badge?: string;
- /** 徽标类型 */
- badgeType?: (typeof BadgeTypes)[number];
- /** 徽标颜色 */
- badgeVariants?: (typeof BadgeVariants)[number];
- /** 在菜单中隐藏下级 */
- hideChildrenInMenu?: boolean;
- /** 在面包屑中隐藏 */
- hideInBreadcrumb?: boolean;
- /** 在菜单中隐藏 */
- hideInMenu?: boolean;
- /** 在标签栏中隐藏 */
- hideInTab?: boolean;
- /** 菜单图标 */
- icon?: string;
- /** 内嵌Iframe的URL */
- iframeSrc?: string;
- /** 是否缓存页面 */
- keepAlive?: boolean;
- /** 外链页面的URL */
- link?: string;
- /** 同一个路由最大打开的标签数 */
- maxNumOfOpenTab?: number;
- /** 无需基础布局 */
- noBasicLayout?: boolean;
- /** 是否在新窗口打开 */
- openInNewWindow?: boolean;
- /** 菜单排序 */
- order?: number;
- /** 额外的路由参数 */
- query?: Recordable;
- /** 菜单标题 */
- title?: string;
- };
- /** 菜单名称 */
- name: string;
- /** 路由路径 */
- path: string;
- /** 父级ID */
- pid: string;
- /** 重定向 */
- redirect?: string;
- /** 菜单类型 */
- type: (typeof MenuTypes)[number];
- }
-}
-
-/**
- * 获取菜单数据列表
- */
-async function getMenuList() {
- return requestClient.get>(
- '/system/menu/list',
- );
-}
-
-async function isMenuNameExists(
- name: string,
- id?: SystemMenuApi.SystemMenu['id'],
-) {
- return requestClient.get('/system/menu/name-exists', {
- params: { id, name },
- });
-}
-
-async function isMenuPathExists(
- path: string,
- id?: SystemMenuApi.SystemMenu['id'],
-) {
- return requestClient.get('/system/menu/path-exists', {
- params: { id, path },
- });
-}
-
-/**
- * 创建菜单
- * @param data 菜单数据
- */
-async function createMenu(
- data: Omit,
-) {
- return requestClient.post('/system/menu', data);
-}
-
-/**
- * 更新菜单
- *
- * @param id 菜单 ID
- * @param data 菜单数据
- */
-async function updateMenu(
- id: string,
- data: Omit,
-) {
- return requestClient.put(`/system/menu/${id}`, data);
-}
-
-/**
- * 删除菜单
- * @param id 菜单 ID
- */
-async function deleteMenu(id: string) {
- return requestClient.delete(`/system/menu/${id}`);
-}
-
-export {
- createMenu,
- deleteMenu,
- getMenuList,
- isMenuNameExists,
- isMenuPathExists,
- updateMenu,
-};
diff --git a/playground/src/api/system/role.ts b/playground/src/api/system/role.ts
deleted file mode 100644
index 60b465ae..00000000
--- a/playground/src/api/system/role.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-import type { Recordable } from '@vben/types';
-
-import { requestClient } from '#/api/request';
-
-export namespace SystemRoleApi {
- export interface SystemRole {
- [key: string]: any;
- id: string;
- name: string;
- permissions: string[];
- remark?: string;
- status: 0 | 1;
- }
-}
-
-/**
- * 获取角色列表数据
- */
-async function getRoleList(params: Recordable) {
- return requestClient.get>(
- '/system/role/list',
- { params },
- );
-}
-
-/**
- * 创建角色
- * @param data 角色数据
- */
-async function createRole(data: Omit) {
- return requestClient.post('/system/role', data);
-}
-
-/**
- * 更新角色
- *
- * @param id 角色 ID
- * @param data 角色数据
- */
-async function updateRole(
- id: string,
- data: Omit,
-) {
- return requestClient.put(`/system/role/${id}`, data);
-}
-
-/**
- * 删除角色
- * @param id 角色 ID
- */
-async function deleteRole(id: string) {
- return requestClient.delete(`/system/role/${id}`);
-}
-
-export { createRole, deleteRole, getRoleList, updateRole };
diff --git a/playground/src/app.vue b/playground/src/app.vue
deleted file mode 100644
index 59ca8618..00000000
--- a/playground/src/app.vue
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-
-
-
-
-
-
-
diff --git a/playground/src/bootstrap.ts b/playground/src/bootstrap.ts
deleted file mode 100644
index fed07340..00000000
--- a/playground/src/bootstrap.ts
+++ /dev/null
@@ -1,84 +0,0 @@
-import { createApp, watchEffect } from 'vue';
-
-import { registerAccessDirective } from '@vben/access';
-import { registerLoadingDirective } from '@vben/common-ui';
-import { preferences } from '@vben/preferences';
-import { initStores } from '@vben/stores';
-import '@vben/styles';
-import '@vben/styles/antd';
-
-import { useTitle } from '@vueuse/core';
-
-import { $t, setupI18n } from '#/locales';
-import { router } from '#/router';
-
-import { initComponentAdapter } from './adapter/component';
-import { initSetupVbenForm } from './adapter/form';
-import App from './app.vue';
-import { initTimezone } from './timezone-init';
-
-async function bootstrap(namespace: string) {
- // 初始化组件适配器
- await initComponentAdapter();
-
- // 初始化表单组件
- await initSetupVbenForm();
-
- // 设置弹窗的默认配置
- // setDefaultModalProps({
- // fullscreenButton: false,
- // });
- // 设置抽屉的默认配置
- // setDefaultDrawerProps({
- // zIndex: 1020,
- // });
-
- const app = createApp(App);
-
- // 注册v-loading指令
- registerLoadingDirective(app, {
- loading: 'loading', // 在这里可以自定义指令名称,也可以明确提供false表示不注册这个指令
- spinning: 'spinning',
- });
-
- // 国际化 i18n 配置
- await setupI18n(app);
-
- // 配置 pinia-tore
- await initStores(app, { namespace });
-
- // 初始化时区HANDLER
- initTimezone();
-
- // 安装权限指令
- registerAccessDirective(app);
-
- // 初始化 tippy
- const { initTippy } = await import('@vben/common-ui/es/tippy');
- initTippy(app);
-
- // 配置路由及路由守卫
- app.use(router);
-
- // 配置@tanstack/vue-query
- const { VueQueryPlugin } = await import('@tanstack/vue-query');
- app.use(VueQueryPlugin);
-
- // 配置Motion插件
- const { MotionPlugin } = await import('@vben/plugins/motion');
- app.use(MotionPlugin);
-
- // 动态更新标题
- watchEffect(() => {
- if (preferences.app.dynamicTitle) {
- const routeTitle = router.currentRoute.value.meta?.title;
- const pageTitle =
- (routeTitle ? `${$t(routeTitle)} - ` : '') + preferences.app.name;
- useTitle(pageTitle);
- }
- });
-
- app.mount('#app');
-}
-
-export { bootstrap };
diff --git a/playground/src/layouts/auth.vue b/playground/src/layouts/auth.vue
deleted file mode 100644
index c33a632a..00000000
--- a/playground/src/layouts/auth.vue
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/playground/src/layouts/basic.vue b/playground/src/layouts/basic.vue
deleted file mode 100644
index 25318499..00000000
--- a/playground/src/layouts/basic.vue
+++ /dev/null
@@ -1,232 +0,0 @@
-
-
-
-
-
-
-
-
- item.id && markRead(item.id)"
- @remove="(item) => item.id && remove(item.id)"
- @make-all="handleMakeAll"
- />
-
-
-
-
-
-
-
-
-
-
-
diff --git a/playground/src/layouts/index.ts b/playground/src/layouts/index.ts
deleted file mode 100644
index a4320780..00000000
--- a/playground/src/layouts/index.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-const BasicLayout = () => import('./basic.vue');
-const AuthPageLayout = () => import('./auth.vue');
-
-const IFrameView = () => import('@vben/layouts').then((m) => m.IFrameView);
-
-export { AuthPageLayout, BasicLayout, IFrameView };
diff --git a/playground/src/locales/README.md b/playground/src/locales/README.md
deleted file mode 100644
index 7b451032..00000000
--- a/playground/src/locales/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# locale
-
-每个app使用的国际化可能不同,这里用于扩展国际化的功能,例如扩展 dayjs、antd组件库的多语言切换,以及app本身的国际化文件。
diff --git a/playground/src/locales/index.ts b/playground/src/locales/index.ts
deleted file mode 100644
index aeef4f57..00000000
--- a/playground/src/locales/index.ts
+++ /dev/null
@@ -1,98 +0,0 @@
-import type { LocaleSetupOptions, SupportedLanguagesType } from '@vben/locales';
-import type { Locale } from 'antdv-next/es/locale';
-import type { App } from 'vue';
-
-import {
- $t,
- setupI18n as coreSetup,
- loadLocalesMapFromDir,
-} from '@vben/locales';
-import { preferences } from '@vben/preferences';
-import antdEnLocale from 'antdv-next/es/locale/en_US';
-import antdDefaultLocale from 'antdv-next/es/locale/zh_CN';
-import dayjs from 'dayjs';
-import { ref } from 'vue';
-
-const antdLocale = ref(antdDefaultLocale);
-
-const modules = import.meta.glob('./langs/**/*.json');
-
-const localesMap = loadLocalesMapFromDir(
- /\.\/langs\/([^/]+)\/(.*)\.json$/,
- modules,
-);
-/**
- * 加载应用特有的语言包
- * 这里也可以改造为从服务端获取翻译数据
- * @param lang
- */
-async function loadMessages(lang: SupportedLanguagesType) {
- const [appLocaleMessages] = await Promise.all([
- localesMap[lang]?.(),
- loadThirdPartyMessage(lang),
- ]);
- return appLocaleMessages?.default;
-}
-
-/**
- * 加载第三方组件库的语言包
- * @param lang
- */
-async function loadThirdPartyMessage(lang: SupportedLanguagesType) {
- await Promise.all([loadAntdLocale(lang), loadDayjsLocale(lang)]);
-}
-
-/**
- * 加载dayjs的语言包
- * @param lang
- */
-async function loadDayjsLocale(lang: SupportedLanguagesType) {
- let locale;
- switch (lang) {
- case 'en-US': {
- locale = await import('dayjs/locale/en');
- break;
- }
- case 'zh-CN': {
- locale = await import('dayjs/locale/zh-cn');
- break;
- }
- // 默认使用英语
- default: {
- locale = await import('dayjs/locale/en');
- }
- }
- if (locale) {
- dayjs.locale(locale);
- } else {
- console.error(`Failed to load dayjs locale for ${lang}`);
- }
-}
-
-/**
- * 加载antd的语言包
- * @param lang
- */
-async function loadAntdLocale(lang: SupportedLanguagesType) {
- switch (lang) {
- case 'en-US': {
- antdLocale.value = antdEnLocale;
- break;
- }
- case 'zh-CN': {
- antdLocale.value = antdDefaultLocale;
- break;
- }
- }
-}
-
-async function setupI18n(app: App, options: LocaleSetupOptions = {}) {
- await coreSetup(app, {
- defaultLocale: preferences.app.locale,
- loadMessages,
- missingWarn: !import.meta.env.PROD,
- ...options,
- });
-}
-
-export { $t, antdLocale, setupI18n };
diff --git a/playground/src/locales/langs/en-US/demos.json b/playground/src/locales/langs/en-US/demos.json
deleted file mode 100644
index 8697ea3c..00000000
--- a/playground/src/locales/langs/en-US/demos.json
+++ /dev/null
@@ -1,71 +0,0 @@
-{
- "title": "Demos",
- "access": {
- "frontendPermissions": "Frontend Permissions",
- "backendPermissions": "Backend Permissions",
- "pageAccess": "Page Access",
- "buttonControl": "Button Control",
- "menuVisible403": "Menu Visible(403)",
- "superVisible": "Visible to Super",
- "adminVisible": "Visible to Admin",
- "userVisible": "Visible to User"
- },
- "nested": {
- "title": "Nested Menu",
- "menu1": "Menu 1",
- "menu2": "Menu 2",
- "menu2_1": "Menu 2-1",
- "menu3": "Menu 3",
- "menu3_1": "Menu 3-1",
- "menu3_2": "Menu 3-2",
- "menu3_2_1": "Menu 3-2-1"
- },
- "outside": {
- "title": "External Pages",
- "embedded": "Embedded",
- "externalLink": "External Link"
- },
- "badge": {
- "title": "Menu Badge",
- "dot": "Dot Badge",
- "text": "Text Badge",
- "color": "Badge Color"
- },
- "activeIcon": {
- "title": "Active Menu Icon",
- "children": "Children Active Icon"
- },
- "fallback": {
- "title": "Fallback Page"
- },
- "features": {
- "title": "Features",
- "hideChildrenInMenu": "Hide Menu Children",
- "loginExpired": "Login Expired",
- "icons": "Icons",
- "watermark": "Watermark",
- "tabs": "Tabs",
- "tabDetail": "Tab Detail Page",
- "fullScreen": "FullScreen",
- "clipboard": "Clipboard",
- "menuWithQuery": "Menu With Query",
- "openInNewWindow": "Open in New Window",
- "fileDownload": "File Download"
- },
- "breadcrumb": {
- "navigation": "Breadcrumb Navigation",
- "lateral": "Lateral Mode",
- "lateralDetail": "Lateral Mode Detail",
- "level": "Level Mode",
- "levelDetail": "Level Mode Detail"
- },
- "vben": {
- "title": "Project",
- "about": "About",
- "document": "Document",
- "antdv": "Ant Design Vue Version",
- "naive-ui": "Naive UI Version",
- "element-plus": "Element Plus Version",
- "tdesign": "TDesign Vue Version"
- }
-}
diff --git a/playground/src/locales/langs/en-US/examples.json b/playground/src/locales/langs/en-US/examples.json
deleted file mode 100644
index 05035487..00000000
--- a/playground/src/locales/langs/en-US/examples.json
+++ /dev/null
@@ -1,83 +0,0 @@
-{
- "title": "Examples",
- "modal": {
- "title": "Modal"
- },
- "drawer": {
- "title": "Drawer"
- },
- "ellipsis": {
- "title": "EllipsisText"
- },
- "form": {
- "title": "Form",
- "basic": "Basic Form",
- "layout": "Custom Layout",
- "query": "Query Form",
- "rules": "Form Rules",
- "dynamic": "Dynamic Form",
- "custom": "Custom Component",
- "api": "Api",
- "merge": "Merge Form",
- "scrollToError": "Scroll to Error Field",
- "upload-error": "Partial file upload failed",
- "upload-urls": "Urls after file upload",
- "file": "file",
- "crop-image": "Crop image",
- "upload-image": "Click to upload image"
- },
- "vxeTable": {
- "title": "Vxe Table",
- "basic": "Basic Table",
- "remote": "Remote Load",
- "tree": "Tree Table",
- "fixed": "Fixed Header/Column",
- "virtual": "Virtual Scroll",
- "editCell": "Edit Cell",
- "editRow": "Edit Row",
- "custom-cell": "Custom Cell",
- "form": "Form Table"
- },
- "captcha": {
- "title": "Captcha",
- "pointSelection": "Point Selection Captcha",
- "sliderCaptcha": "Slider Captcha",
- "sliderRotateCaptcha": "Rotate Captcha",
- "sliderTranslateCaptcha": "Translate Captcha",
- "captchaCardTitle": "Please complete the security verification",
- "pageDescription": "Verify user identity by clicking on specific locations in the image.",
- "pageTitle": "Captcha Component Example",
- "basic": "Basic Usage",
- "titlePlaceholder": "Captcha Title Text",
- "captchaImageUrlPlaceholder": "Captcha Image (supports img tag src attribute value)",
- "hintImage": "Hint Image",
- "hintText": "Hint Text",
- "hintImagePlaceholder": "Hint Image (supports img tag src attribute value)",
- "hintTextPlaceholder": "Hint Text",
- "showConfirm": "Show Confirm",
- "hideConfirm": "Hide Confirm",
- "widthPlaceholder": "Captcha Image Width Default 300px",
- "heightPlaceholder": "Captcha Image Height Default 220px",
- "paddingXPlaceholder": "Horizontal Padding Default 12px",
- "paddingYPlaceholder": "Vertical Padding Default 16px",
- "index": "Index:",
- "timestamp": "Timestamp:",
- "x": "x:",
- "y": "y:"
- },
- "resize": {
- "title": "Resize"
- },
- "layout": {
- "col-page": "ColPage Layout"
- },
- "button-group": {
- "title": "Button Group"
- },
- "function": {
- "contentMenu": "Content Menu"
- },
- "cropper": {
- "title": "Cropper"
- }
-}
diff --git a/playground/src/locales/langs/en-US/page.json b/playground/src/locales/langs/en-US/page.json
deleted file mode 100644
index 32e323c2..00000000
--- a/playground/src/locales/langs/en-US/page.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "auth": {
- "login": "Login",
- "register": "Register",
- "codeLogin": "Code Login",
- "qrcodeLogin": "Qr Code Login",
- "forgetPassword": "Forget Password",
- "sendingCode": "SMS Code is sending...",
- "codeSentTo": "Code has been sent to {0}",
- "profile": "Profile"
- },
- "dashboard": {
- "title": "Dashboard",
- "analytics": "Analytics",
- "workspace": "Workspace"
- }
-}
diff --git a/playground/src/locales/langs/en-US/system.json b/playground/src/locales/langs/en-US/system.json
deleted file mode 100644
index 003dfbbe..00000000
--- a/playground/src/locales/langs/en-US/system.json
+++ /dev/null
@@ -1,65 +0,0 @@
-{
- "title": "System Management",
- "dept": {
- "name": "Department",
- "title": "Department Management",
- "deptName": "Department Name",
- "status": "Status",
- "createTime": "Create Time",
- "remark": "Remark",
- "operation": "Operation",
- "parentDept": "Parent Department"
- },
- "menu": {
- "title": "Menu Management",
- "parent": "Parent Menu",
- "menuTitle": "Title",
- "menuName": "Menu Name",
- "name": "Menu",
- "type": "Type",
- "typeCatalog": "Catalog",
- "typeMenu": "Menu",
- "typeButton": "Button",
- "typeLink": "Link",
- "typeEmbedded": "Embedded",
- "icon": "Icon",
- "activeIcon": "Active Icon",
- "activePath": "Active Path",
- "path": "Route Path",
- "component": "Component",
- "status": "Status",
- "authCode": "Auth Code",
- "badge": "Badge",
- "operation": "Operation",
- "linkSrc": "Link Address",
- "affixTab": "Affix In Tabs",
- "keepAlive": "Keep Alive",
- "hideInMenu": "Hide In Menu",
- "hideInTab": "Hide In Tabbar",
- "hideChildrenInMenu": "Hide Children In Menu",
- "hideInBreadcrumb": "Hide In Breadcrumb",
- "advancedSettings": "Other Settings",
- "activePathMustExist": "The path could not find a valid menu",
- "activePathHelp": "When jumping to the current route, \nthe menu path that needs to be activated must be specified when it does not display in the navigation menu.",
- "badgeType": {
- "title": "Badge Type",
- "dot": "Dot",
- "normal": "Text",
- "none": "None"
- },
- "badgeVariants": "Badge Style"
- },
- "role": {
- "title": "Role Management",
- "list": "Role List",
- "name": "Role",
- "roleName": "Role Name",
- "id": "Role ID",
- "status": "Status",
- "remark": "Remark",
- "createTime": "Creation Time",
- "operation": "Operation",
- "permissions": "Permissions",
- "setPermissions": "Permissions"
- }
-}
diff --git a/playground/src/locales/langs/zh-CN/demos.json b/playground/src/locales/langs/zh-CN/demos.json
deleted file mode 100644
index b7823b72..00000000
--- a/playground/src/locales/langs/zh-CN/demos.json
+++ /dev/null
@@ -1,72 +0,0 @@
-{
- "title": "演示",
- "access": {
- "frontendPermissions": "前端权限",
- "backendPermissions": "后端权限",
- "pageAccess": "页面访问",
- "buttonControl": "按钮控制",
- "menuVisible403": "菜单可见(403)",
- "superVisible": "Super 可见",
- "adminVisible": "Admin 可见",
- "userVisible": "User 可见"
- },
- "nested": {
- "title": "嵌套菜单",
- "menu1": "菜单 1",
- "menu2": "菜单 2",
- "menu2_1": "菜单 2-1",
- "menu3": "菜单 3",
- "menu3_1": "菜单 3-1",
- "menu3_2": "菜单 3-2",
- "menu3_2_1": "菜单 3-2-1"
- },
- "outside": {
- "title": "外部页面",
- "embedded": "内嵌",
- "externalLink": "外链"
- },
- "badge": {
- "title": "菜单徽标",
- "dot": "点徽标",
- "text": "文本徽标",
- "color": "徽标颜色"
- },
- "activeIcon": {
- "title": "菜单激活图标",
- "children": "子级激活图标"
- },
- "fallback": {
- "title": "缺省页"
- },
- "features": {
- "title": "功能",
- "hideChildrenInMenu": "隐藏子菜单",
- "loginExpired": "登录过期",
- "icons": "图标",
- "watermark": "水印",
- "tabs": "标签页",
- "tabDetail": "标签详情页",
- "fullScreen": "全屏",
- "clipboard": "剪贴板",
- "menuWithQuery": "带参菜单",
- "openInNewWindow": "新窗口打开",
- "fileDownload": "文件下载",
- "requestParamsSerializer": "参数序列化"
- },
- "breadcrumb": {
- "navigation": "面包屑导航",
- "lateral": "平级模式",
- "level": "层级模式",
- "levelDetail": "层级模式详情",
- "lateralDetail": "平级模式详情"
- },
- "vben": {
- "title": "项目",
- "about": "关于",
- "document": "文档",
- "antdv": "Ant Design Vue 版本",
- "naive-ui": "Naive UI 版本",
- "element-plus": "Element Plus 版本",
- "tdesign": "TDesign Vue 版本"
- }
-}
diff --git a/playground/src/locales/langs/zh-CN/examples.json b/playground/src/locales/langs/zh-CN/examples.json
deleted file mode 100644
index 3b0d934c..00000000
--- a/playground/src/locales/langs/zh-CN/examples.json
+++ /dev/null
@@ -1,83 +0,0 @@
-{
- "title": "示例",
- "modal": {
- "title": "弹窗"
- },
- "drawer": {
- "title": "抽屉"
- },
- "ellipsis": {
- "title": "文本省略"
- },
- "resize": {
- "title": "拖动调整"
- },
- "form": {
- "title": "表单",
- "basic": "基础表单",
- "layout": "自定义布局",
- "query": "查询表单",
- "rules": "表单校验",
- "dynamic": "动态表单",
- "custom": "自定义组件",
- "api": "Api",
- "merge": "合并表单",
- "scrollToError": "滚动到错误字段",
- "upload-error": "部分文件上传失败",
- "upload-urls": "文件上传后的网址",
- "file": "文件",
- "crop-image": "裁剪图片",
- "upload-image": "点击上传图片"
- },
- "vxeTable": {
- "title": "Vxe 表格",
- "basic": "基础表格",
- "remote": "远程加载",
- "tree": "树形表格",
- "fixed": "固定表头/列",
- "virtual": "虚拟滚动",
- "editCell": "单元格编辑",
- "editRow": "行编辑",
- "custom-cell": "自定义单元格",
- "form": "搜索表单"
- },
- "captcha": {
- "title": "验证码",
- "pointSelection": "点选验证",
- "sliderCaptcha": "滑块验证",
- "sliderRotateCaptcha": "旋转验证",
- "sliderTranslateCaptcha": "拼图滑块验证",
- "captchaCardTitle": "请完成安全验证",
- "pageDescription": "通过点击图片中的特定位置来验证用户身份。",
- "pageTitle": "验证码组件示例",
- "basic": "基本使用",
- "titlePlaceholder": "验证码标题文案",
- "captchaImageUrlPlaceholder": "验证码图片(支持img标签src属性值)",
- "hintImage": "提示图片",
- "hintText": "提示文本",
- "hintImagePlaceholder": "提示图片(支持img标签src属性值)",
- "hintTextPlaceholder": "提示文本",
- "showConfirm": "展示确认",
- "hideConfirm": "隐藏确认",
- "widthPlaceholder": "验证码图片宽度 默认300px",
- "heightPlaceholder": "验证码图片高度 默认220px",
- "paddingXPlaceholder": "水平内边距 默认12px",
- "paddingYPlaceholder": "垂直内边距 默认16px",
- "index": "索引:",
- "timestamp": "时间戳:",
- "x": "x:",
- "y": "y:"
- },
- "layout": {
- "col-page": "双列布局"
- },
- "button-group": {
- "title": "按钮组"
- },
- "function": {
- "contentMenu": "上下文菜单"
- },
- "cropper": {
- "title": "图片裁剪"
- }
-}
diff --git a/playground/src/locales/langs/zh-CN/page.json b/playground/src/locales/langs/zh-CN/page.json
deleted file mode 100644
index 437068c9..00000000
--- a/playground/src/locales/langs/zh-CN/page.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "auth": {
- "login": "登录",
- "register": "注册",
- "codeLogin": "验证码登录",
- "qrcodeLogin": "二维码登录",
- "forgetPassword": "忘记密码",
- "sendingCode": "正在发送验证码",
- "codeSentTo": "验证码已发送至{0}",
- "profile": "个人中心"
- },
- "dashboard": {
- "title": "概览",
- "analytics": "分析页",
- "workspace": "工作台"
- }
-}
diff --git a/playground/src/locales/langs/zh-CN/system.json b/playground/src/locales/langs/zh-CN/system.json
deleted file mode 100644
index be5a7ae3..00000000
--- a/playground/src/locales/langs/zh-CN/system.json
+++ /dev/null
@@ -1,67 +0,0 @@
-{
- "title": "系统管理",
- "dept": {
- "list": "部门列表",
- "createTime": "创建时间",
- "deptName": "部门名称",
- "name": "部门",
- "operation": "操作",
- "parentDept": "上级部门",
- "remark": "备注",
- "status": "状态",
- "title": "部门管理"
- },
- "menu": {
- "list": "菜单列表",
- "activeIcon": "激活图标",
- "activePath": "激活路径",
- "activePathHelp": "跳转到当前路由时,需要激活的菜单路径。\n当不在导航菜单中显示时,需要指定激活路径",
- "activePathMustExist": "该路径未能找到有效的菜单",
- "advancedSettings": "其它设置",
- "affixTab": "固定在标签",
- "authCode": "权限标识",
- "badge": "徽章内容",
- "badgeVariants": "徽标样式",
- "badgeType": {
- "dot": "点",
- "none": "无",
- "normal": "文字",
- "title": "徽标类型"
- },
- "component": "页面组件",
- "hideChildrenInMenu": "隐藏子菜单",
- "hideInBreadcrumb": "在面包屑中隐藏",
- "hideInMenu": "隐藏菜单",
- "hideInTab": "在标签栏中隐藏",
- "icon": "图标",
- "keepAlive": "缓存标签页",
- "linkSrc": "链接地址",
- "menuName": "菜单名称",
- "menuTitle": "标题",
- "name": "菜单",
- "operation": "操作",
- "parent": "上级菜单",
- "path": "路由地址",
- "status": "状态",
- "title": "菜单管理",
- "type": "类型",
- "typeButton": "按钮",
- "typeCatalog": "目录",
- "typeEmbedded": "内嵌",
- "typeLink": "外链",
- "typeMenu": "菜单"
- },
- "role": {
- "title": "角色管理",
- "list": "角色列表",
- "name": "角色",
- "roleName": "角色名称",
- "id": "角色ID",
- "status": "状态",
- "remark": "备注",
- "createTime": "创建时间",
- "operation": "操作",
- "permissions": "权限",
- "setPermissions": "授权"
- }
-}
diff --git a/playground/src/main.ts b/playground/src/main.ts
deleted file mode 100644
index 5d728a02..00000000
--- a/playground/src/main.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-import { initPreferences } from '@vben/preferences';
-import { unmountGlobalLoading } from '@vben/utils';
-
-import { overridesPreferences } from './preferences';
-
-/**
- * 应用初始化完成之后再进行页面加载渲染
- */
-async function initApplication() {
- // name用于指定项目唯一标识
- // 用于区分不同项目的偏好设置以及存储数据的key前缀以及其他一些需要隔离的数据
- const env = import.meta.env.PROD ? 'prod' : 'dev';
- const appVersion = import.meta.env.VITE_APP_VERSION;
- const namespace = `${import.meta.env.VITE_APP_NAMESPACE}-${appVersion}-${env}`;
-
- // app偏好设置初始化
- await initPreferences({
- namespace,
- overrides: overridesPreferences,
- });
-
- // 启动应用并挂载
- // vue应用主要逻辑及视图
- const { bootstrap } = await import('./bootstrap');
- await bootstrap(namespace);
-
- // 移除并销毁loading
- unmountGlobalLoading();
-}
-
-initApplication();
diff --git a/playground/src/preferences.ts b/playground/src/preferences.ts
deleted file mode 100644
index b2e9ace4..00000000
--- a/playground/src/preferences.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { defineOverridesPreferences } from '@vben/preferences';
-
-/**
- * @description 项目配置文件
- * 只需要覆盖项目中的一部分配置,不需要的配置不用覆盖,会自动使用默认配置
- * !!! 更改配置后请清空缓存,否则可能不生效
- */
-export const overridesPreferences = defineOverridesPreferences({
- // overrides
- app: {
- name: import.meta.env.VITE_APP_TITLE,
- },
-});
diff --git a/playground/src/router/access.ts b/playground/src/router/access.ts
deleted file mode 100644
index e9e98511..00000000
--- a/playground/src/router/access.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-import type {
- ComponentRecordType,
- GenerateMenuAndRoutesOptions,
-} from '@vben/types';
-
-import { generateAccessible } from '@vben/access';
-import { preferences } from '@vben/preferences';
-
-import { message } from 'antdv-next';
-
-import { getAllMenusApi } from '#/api';
-import { BasicLayout, IFrameView } from '#/layouts';
-import { $t } from '#/locales';
-
-const forbiddenComponent = () => import('#/views/_core/fallback/forbidden.vue');
-
-async function generateAccess(options: GenerateMenuAndRoutesOptions) {
- const pageMap: ComponentRecordType = import.meta.glob('../views/**/*.vue');
-
- const layoutMap: ComponentRecordType = {
- BasicLayout,
- IFrameView,
- };
-
- return await generateAccessible(preferences.app.accessMode, {
- ...options,
- fetchMenuListAsync: async () => {
- message.loading({
- content: `${$t('common.loadingMenu')}...`,
- duration: 1.5,
- });
- return await getAllMenusApi();
- },
- // 可以指定没有权限跳转403页面
- forbiddenComponent,
- // 如果 route.meta.menuVisibleWithForbidden = true
- layoutMap,
- pageMap,
- });
-}
-
-export { generateAccess };
diff --git a/playground/src/router/guard.ts b/playground/src/router/guard.ts
deleted file mode 100644
index 167a84d1..00000000
--- a/playground/src/router/guard.ts
+++ /dev/null
@@ -1,136 +0,0 @@
-import type { Router } from 'vue-router';
-
-import { LOGIN_PATH } from '@vben/constants';
-import { preferences } from '@vben/preferences';
-import { useAccessStore, useUserStore } from '@vben/stores';
-import { startProgress, stopProgress } from '@vben/utils';
-
-import { accessRoutes, coreRouteNames } from '#/router/routes';
-import { useAuthStore } from '#/store';
-
-import { generateAccess } from './access';
-
-/**
- * 通用守卫配置
- * @param router
- */
-function setupCommonGuard(router: Router) {
- // 记录已经加载的页面
- const loadedPaths = new Set();
-
- router.beforeEach((to) => {
- to.meta.loaded = loadedPaths.has(to.path);
-
- // 页面加载进度条
- if (!to.meta.loaded && preferences.transition.progress) {
- startProgress();
- }
- return true;
- });
-
- router.afterEach((to) => {
- // 记录页面是否加载,如果已经加载,后续的页面切换动画等效果不在重复执行
- loadedPaths.add(to.path);
-
- // 关闭页面加载进度条
- if (preferences.transition.progress) {
- stopProgress();
- }
- });
-}
-
-/**
- * 权限访问守卫配置
- * @param router
- */
-function setupAccessGuard(router: Router) {
- router.beforeEach(async (to, from) => {
- const accessStore = useAccessStore();
- const userStore = useUserStore();
- const authStore = useAuthStore();
- // 基本路由,这些路由不需要进入权限拦截
- if (coreRouteNames.includes(to.name as string)) {
- if (to.path === LOGIN_PATH && accessStore.accessToken) {
- return decodeURIComponent(
- (to.query?.redirect as string) ||
- userStore.userInfo?.homePath ||
- preferences.app.defaultHomePath,
- );
- }
- return true;
- }
-
- // accessToken 检查
- if (!accessStore.accessToken) {
- // 明确声明忽略权限访问权限,则可以访问
- if (to.meta.ignoreAccess) {
- return true;
- }
-
- // 没有访问权限,跳转登录页面
- if (to.fullPath !== LOGIN_PATH) {
- return {
- path: LOGIN_PATH,
- // 如不需要,直接删除 query
- query:
- to.fullPath === preferences.app.defaultHomePath
- ? {}
- : { redirect: encodeURIComponent(to.fullPath) },
- // 携带当前跳转的页面,登录后重新跳转该页面
- replace: true,
- };
- }
- return to;
- }
-
- // 是否已经生成过动态路由
- if (accessStore.isAccessChecked) {
- return true;
- }
-
- // 生成路由表
- // 当前登录用户拥有的角色标识列表
- const userInfo = userStore.userInfo || (await authStore.fetchUserInfo());
- const userRoles = userInfo.roles ?? [];
-
- // 生成菜单和路由
- const { accessibleMenus, accessibleRoutes } = await generateAccess({
- roles: userRoles,
- router,
- // 则会在菜单中显示,但是访问会被重定向到403
- routes: accessRoutes,
- });
-
- // 保存菜单信息和路由信息
- accessStore.setAccessMenus(accessibleMenus);
- accessStore.setAccessRoutes(accessibleRoutes);
- accessStore.setIsAccessChecked(true);
- let redirectPath: string;
- if (from.query.redirect) {
- redirectPath = from.query.redirect as string;
- } else if (to.fullPath === preferences.app.defaultHomePath) {
- redirectPath = preferences.app.defaultHomePath;
- } else if (userInfo.homePath && to.fullPath === userInfo.homePath) {
- redirectPath = userInfo.homePath;
- } else {
- redirectPath = to.fullPath;
- }
- return {
- ...router.resolve(decodeURIComponent(redirectPath)),
- replace: true,
- };
- });
-}
-
-/**
- * 项目守卫配置
- * @param router
- */
-function createRouterGuard(router: Router) {
- /** 通用 */
- setupCommonGuard(router);
- /** 权限访问 */
- setupAccessGuard(router);
-}
-
-export { createRouterGuard };
diff --git a/playground/src/router/index.ts b/playground/src/router/index.ts
deleted file mode 100644
index 48402303..00000000
--- a/playground/src/router/index.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-import {
- createRouter,
- createWebHashHistory,
- createWebHistory,
-} from 'vue-router';
-
-import { resetStaticRoutes } from '@vben/utils';
-
-import { createRouterGuard } from './guard';
-import { routes } from './routes';
-
-/**
- * @zh_CN 创建vue-router实例
- */
-const router = createRouter({
- history:
- import.meta.env.VITE_ROUTER_HISTORY === 'hash'
- ? createWebHashHistory(import.meta.env.VITE_BASE)
- : createWebHistory(import.meta.env.VITE_BASE),
- // 应该添加到路由的初始路由列表。
- routes,
- scrollBehavior: (to, _from, savedPosition) => {
- if (savedPosition) {
- return savedPosition;
- }
- return to.hash ? { behavior: 'smooth', el: to.hash } : { left: 0, top: 0 };
- },
- // 是否应该禁止尾部斜杠。
- // strict: true,
-});
-
-const resetRoutes = () => resetStaticRoutes(router, routes);
-
-// 创建路由守卫
-createRouterGuard(router);
-
-export { resetRoutes, router };
diff --git a/playground/src/router/routes/core.ts b/playground/src/router/routes/core.ts
deleted file mode 100644
index 949b0b65..00000000
--- a/playground/src/router/routes/core.ts
+++ /dev/null
@@ -1,97 +0,0 @@
-import type { RouteRecordRaw } from 'vue-router';
-
-import { LOGIN_PATH } from '@vben/constants';
-import { preferences } from '@vben/preferences';
-
-import { $t } from '#/locales';
-
-const BasicLayout = () => import('#/layouts/basic.vue');
-const AuthPageLayout = () => import('#/layouts/auth.vue');
-/** 全局404页面 */
-const fallbackNotFoundRoute: RouteRecordRaw = {
- component: () => import('#/views/_core/fallback/not-found.vue'),
- meta: {
- hideInBreadcrumb: true,
- hideInMenu: true,
- hideInTab: true,
- title: '404',
- },
- name: 'FallbackNotFound',
- path: '/:path(.*)*',
-};
-
-/** 基本路由,这些路由是必须存在的 */
-const coreRoutes: RouteRecordRaw[] = [
- /**
- * 根路由
- * 使用基础布局,作为所有页面的父级容器,子级就不必配置BasicLayout。
- * 此路由必须存在,且不应修改
- */
- {
- component: BasicLayout,
- meta: {
- hideInBreadcrumb: true,
- title: 'Root',
- },
- name: 'Root',
- path: '/',
- redirect: preferences.app.defaultHomePath,
- children: [],
- },
- {
- component: AuthPageLayout,
- meta: {
- hideInTab: true,
- title: 'Authentication',
- },
- name: 'Authentication',
- path: '/auth',
- redirect: LOGIN_PATH,
- children: [
- {
- name: 'Login',
- path: 'login',
- component: () => import('#/views/_core/authentication/login.vue'),
- meta: {
- title: $t('page.auth.login'),
- },
- },
- {
- name: 'CodeLogin',
- path: 'code-login',
- component: () => import('#/views/_core/authentication/code-login.vue'),
- meta: {
- title: $t('page.auth.codeLogin'),
- },
- },
- {
- name: 'QrCodeLogin',
- path: 'qrcode-login',
- component: () =>
- import('#/views/_core/authentication/qrcode-login.vue'),
- meta: {
- title: $t('page.auth.qrcodeLogin'),
- },
- },
- {
- name: 'ForgetPassword',
- path: 'forget-password',
- component: () =>
- import('#/views/_core/authentication/forget-password.vue'),
- meta: {
- title: $t('page.auth.forgetPassword'),
- },
- },
- {
- name: 'Register',
- path: 'register',
- component: () => import('#/views/_core/authentication/register.vue'),
- meta: {
- title: $t('page.auth.register'),
- },
- },
- ],
- },
-];
-
-export { coreRoutes, fallbackNotFoundRoute };
diff --git a/playground/src/router/routes/index.ts b/playground/src/router/routes/index.ts
deleted file mode 100644
index 275eb837..00000000
--- a/playground/src/router/routes/index.ts
+++ /dev/null
@@ -1,47 +0,0 @@
-import type { RouteRecordRaw } from 'vue-router';
-
-import { mergeRouteModules, traverseTreeValues } from '@vben/utils';
-
-import { coreRoutes, fallbackNotFoundRoute } from './core';
-
-const dynamicRouteFiles = import.meta.glob('./modules/**/*.ts', {
- eager: true,
-});
-
-// 有需要可以自行打开注释,并创建文件夹
-// const externalRouteFiles = import.meta.glob('./external/**/*.ts', { eager: true });
-// const staticRouteFiles = import.meta.glob('./static/**/*.ts', { eager: true });
-
-/** 动态路由 */
-const dynamicRoutes: RouteRecordRaw[] = mergeRouteModules(dynamicRouteFiles);
-
-/** 外部路由列表,访问这些页面可以不需要Layout,可能用于内嵌在别的系统(不会显示在菜单中) */
-// const externalRoutes: RouteRecordRaw[] = mergeRouteModules(externalRouteFiles);
-// const staticRoutes: RouteRecordRaw[] = mergeRouteModules(staticRouteFiles);
-const staticRoutes: RouteRecordRaw[] = [];
-const externalRoutes: RouteRecordRaw[] = [];
-
-/** 路由列表,由基本路由、外部路由和404兜底路由组成
- * 无需走权限验证(会一直显示在菜单中) */
-const routes: RouteRecordRaw[] = [
- ...coreRoutes,
- ...externalRoutes,
- fallbackNotFoundRoute,
-];
-
-/** 基本路由列表,这些路由不需要进入权限拦截 */
-const coreRouteNames = traverseTreeValues(coreRoutes, (route) => route.name);
-
-/** 有权限校验的路由列表,包含动态路由和静态路由 */
-const accessRoutes = [...dynamicRoutes, ...staticRoutes];
-
-const componentKeys: string[] = Object.keys(
- import.meta.glob('../../views/**/*.vue'),
-)
- .filter((item) => !item.includes('/modules/'))
- .map((v) => {
- const path = v.replace('../../views/', '/');
- return path.endsWith('.vue') ? path.slice(0, -4) : path;
- });
-
-export { accessRoutes, componentKeys, coreRouteNames, routes };
diff --git a/playground/src/router/routes/modules/dashboard.ts b/playground/src/router/routes/modules/dashboard.ts
deleted file mode 100644
index 5254dc65..00000000
--- a/playground/src/router/routes/modules/dashboard.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-import type { RouteRecordRaw } from 'vue-router';
-
-import { $t } from '#/locales';
-
-const routes: RouteRecordRaw[] = [
- {
- meta: {
- icon: 'lucide:layout-dashboard',
- order: -1,
- title: $t('page.dashboard.title'),
- },
- name: 'Dashboard',
- path: '/dashboard',
- children: [
- {
- name: 'Analytics',
- path: '/analytics',
- component: () => import('#/views/dashboard/analytics/index.vue'),
- meta: {
- affixTab: true,
- icon: 'lucide:area-chart',
- title: $t('page.dashboard.analytics'),
- },
- },
- {
- name: 'Workspace',
- path: '/workspace',
- component: () => import('#/views/dashboard/workspace/index.vue'),
- meta: {
- icon: 'carbon:workspace',
- title: $t('page.dashboard.workspace'),
- },
- },
- ],
- },
-];
-
-export default routes;
diff --git a/playground/src/router/routes/modules/demos.ts b/playground/src/router/routes/modules/demos.ts
deleted file mode 100644
index b8d27ef5..00000000
--- a/playground/src/router/routes/modules/demos.ts
+++ /dev/null
@@ -1,588 +0,0 @@
-import type { RouteRecordRaw } from 'vue-router';
-
-import { IFrameView } from '#/layouts';
-import { $t } from '#/locales';
-
-const routes: RouteRecordRaw[] = [
- {
- meta: {
- icon: 'ic:baseline-view-in-ar',
- keepAlive: true,
- order: 1000,
- title: $t('demos.title'),
- },
- name: 'Demos',
- path: '/demos',
- children: [
- // 权限控制
- {
- meta: {
- icon: 'mdi:shield-key-outline',
- title: $t('demos.access.frontendPermissions'),
- },
- name: 'AccessDemos',
- path: '/demos/access',
- children: [
- {
- name: 'AccessPageControlDemo',
- path: '/demos/access/page-control',
- component: () => import('#/views/demos/access/index.vue'),
- meta: {
- icon: 'mdi:page-previous-outline',
- title: $t('demos.access.pageAccess'),
- },
- },
- {
- name: 'AccessButtonControlDemo',
- path: '/demos/access/button-control',
- component: () => import('#/views/demos/access/button-control.vue'),
- meta: {
- icon: 'mdi:button-cursor',
- title: $t('demos.access.buttonControl'),
- },
- },
- {
- name: 'AccessMenuVisible403Demo',
- path: '/demos/access/menu-visible-403',
- component: () =>
- import('#/views/demos/access/menu-visible-403.vue'),
- meta: {
- authority: ['no-body'],
- icon: 'mdi:button-cursor',
- menuVisibleWithForbidden: true,
- title: $t('demos.access.menuVisible403'),
- },
- },
- {
- name: 'AccessSuperVisibleDemo',
- path: '/demos/access/super-visible',
- component: () => import('#/views/demos/access/super-visible.vue'),
- meta: {
- authority: ['super'],
- icon: 'mdi:button-cursor',
- title: $t('demos.access.superVisible'),
- },
- },
- {
- name: 'AccessAdminVisibleDemo',
- path: '/demos/access/admin-visible',
- component: () => import('#/views/demos/access/admin-visible.vue'),
- meta: {
- authority: ['admin'],
- icon: 'mdi:button-cursor',
- title: $t('demos.access.adminVisible'),
- },
- },
- {
- name: 'AccessUserVisibleDemo',
- path: '/demos/access/user-visible',
- component: () => import('#/views/demos/access/user-visible.vue'),
- meta: {
- authority: ['user'],
- icon: 'mdi:button-cursor',
- title: $t('demos.access.userVisible'),
- },
- },
- ],
- },
- // 功能
- {
- meta: {
- icon: 'mdi:feature-highlight',
- title: $t('demos.features.title'),
- },
- name: 'FeaturesDemos',
- path: '/demos/features',
- children: [
- {
- name: 'LoginExpiredDemo',
- path: '/demos/features/login-expired',
- component: () =>
- import('#/views/demos/features/login-expired/index.vue'),
- meta: {
- icon: 'mdi:encryption-expiration',
- title: $t('demos.features.loginExpired'),
- },
- },
- {
- name: 'IconsDemo',
- path: '/demos/features/icons',
- component: () => import('#/views/demos/features/icons/index.vue'),
- meta: {
- icon: 'lucide:annoyed',
- title: $t('demos.features.icons'),
- },
- },
- {
- name: 'WatermarkDemo',
- path: '/demos/features/watermark',
- component: () =>
- import('#/views/demos/features/watermark/index.vue'),
- meta: {
- icon: 'lucide:tags',
- title: $t('demos.features.watermark'),
- },
- },
- {
- name: 'FeatureTabsDemo',
- path: '/demos/features/tabs',
- component: () => import('#/views/demos/features/tabs/index.vue'),
- meta: {
- icon: 'lucide:app-window',
- title: $t('demos.features.tabs'),
- },
- },
- {
- name: 'FeatureTabDetailDemo',
- path: '/demos/features/tabs/detail/:id',
- component: () =>
- import('#/views/demos/features/tabs/tab-detail.vue'),
- meta: {
- activePath: '/demos/features/tabs',
- hideInMenu: true,
- maxNumOfOpenTab: 3,
- title: $t('demos.features.tabDetail'),
- },
- },
- {
- name: 'HideChildrenInMenuParentDemo',
- path: '/demos/features/hide-menu-children',
- meta: {
- hideChildrenInMenu: true,
- icon: 'ic:round-menu',
- title: $t('demos.features.hideChildrenInMenu'),
- },
- children: [
- {
- name: 'HideChildrenInMenuDemo',
- path: '',
- component: () =>
- import('#/views/demos/features/hide-menu-children/parent.vue'),
- meta: {
- // hideInMenu: true,
- title: $t('demos.features.hideChildrenInMenu'),
- },
- },
- {
- name: 'HideChildrenInMenuChildrenDemo',
- path: '/demos/features/hide-menu-children/children',
- component: () =>
- import('#/views/demos/features/hide-menu-children/children.vue'),
- meta: {
- activePath: '/demos/features/hide-menu-children',
- title: $t('demos.features.hideChildrenInMenu'),
- },
- },
- ],
- },
- {
- name: 'FullScreenDemo',
- path: '/demos/features/full-screen',
- component: () =>
- import('#/views/demos/features/full-screen/index.vue'),
- meta: {
- icon: 'lucide:fullscreen',
- title: $t('demos.features.fullScreen'),
- },
- },
- {
- name: 'FileDownloadDemo',
- path: '/demos/features/file-download',
- component: () =>
- import('#/views/demos/features/file-download/index.vue'),
- meta: {
- icon: 'lucide:hard-drive-download',
- title: $t('demos.features.fileDownload'),
- },
- },
- {
- name: 'ClipboardDemo',
- path: '/demos/features/clipboard',
- component: () =>
- import('#/views/demos/features/clipboard/index.vue'),
- meta: {
- icon: 'lucide:copy',
- title: $t('demos.features.clipboard'),
- },
- },
- {
- name: 'MenuQueryDemo',
- path: '/demos/menu-query',
- component: () =>
- import('#/views/demos/features/menu-query/index.vue'),
- meta: {
- icon: 'lucide:curly-braces',
- query: {
- id: 1,
- },
- title: $t('demos.features.menuWithQuery'),
- },
- },
- {
- name: 'NewWindowDemo',
- path: '/demos/new-window',
- component: () =>
- import('#/views/demos/features/new-window/index.vue'),
- meta: {
- icon: 'lucide:app-window',
- openInNewWindow: true,
- title: $t('demos.features.openInNewWindow'),
- },
- },
- {
- name: 'VueQueryDemo',
- path: '/demos/features/vue-query',
- component: () =>
- import('#/views/demos/features/vue-query/index.vue'),
- meta: {
- icon: 'lucide:git-pull-request-arrow',
- title: 'Tanstack Query',
- },
- },
- {
- name: 'RequestParamsSerializerDemo',
- path: '/demos/features/request-params-serializer',
- component: () =>
- import('#/views/demos/features/request-params-serializer/index.vue'),
- meta: {
- icon: 'lucide:git-pull-request-arrow',
- title: $t('demos.features.requestParamsSerializer'),
- },
- },
- {
- name: 'BigIntDemo',
- path: '/demos/features/json-bigint',
- component: () =>
- import('#/views/demos/features/json-bigint/index.vue'),
- meta: {
- icon: 'lucide:grape',
- title: 'JSON BigInt',
- },
- },
- ],
- },
- // 面包屑导航
- {
- name: 'BreadcrumbDemos',
- path: '/demos/breadcrumb',
- meta: {
- icon: 'lucide:navigation',
- title: $t('demos.breadcrumb.navigation'),
- },
- children: [
- {
- name: 'BreadcrumbLateralDemo',
- path: '/demos/breadcrumb/lateral',
- component: () => import('#/views/demos/breadcrumb/lateral.vue'),
- meta: {
- icon: 'lucide:navigation',
- title: $t('demos.breadcrumb.lateral'),
- },
- },
- {
- name: 'BreadcrumbLateralDetailDemo',
- path: '/demos/breadcrumb/lateral-detail',
- component: () =>
- import('#/views/demos/breadcrumb/lateral-detail.vue'),
- meta: {
- activePath: '/demos/breadcrumb/lateral',
- hideInMenu: true,
- title: $t('demos.breadcrumb.lateralDetail'),
- },
- },
- {
- name: 'BreadcrumbLevelDemo',
- path: '/demos/breadcrumb/level',
- meta: {
- icon: 'lucide:navigation',
- title: $t('demos.breadcrumb.level'),
- },
- children: [
- {
- name: 'BreadcrumbLevelDetailDemo',
- path: '/demos/breadcrumb/level/detail',
- component: () =>
- import('#/views/demos/breadcrumb/level-detail.vue'),
- meta: {
- title: $t('demos.breadcrumb.levelDetail'),
- },
- },
- ],
- },
- ],
- },
- // 缺省页
- {
- meta: {
- icon: 'mdi:lightbulb-error-outline',
- title: $t('demos.fallback.title'),
- },
- name: 'FallbackDemos',
- path: '/demos/fallback',
- children: [
- {
- name: 'Fallback403Demo',
- path: '/demos/fallback/403',
- component: () => import('#/views/_core/fallback/forbidden.vue'),
- meta: {
- icon: 'mdi:do-not-disturb-alt',
- title: '403',
- },
- },
- {
- name: 'Fallback404Demo',
- path: '/demos/fallback/404',
- component: () => import('#/views/_core/fallback/not-found.vue'),
- meta: {
- icon: 'mdi:table-off',
- title: '404',
- },
- },
- {
- name: 'Fallback500Demo',
- path: '/demos/fallback/500',
- component: () =>
- import('#/views/_core/fallback/internal-error.vue'),
- meta: {
- icon: 'mdi:server-network-off',
- title: '500',
- },
- },
- {
- name: 'FallbackOfflineDemo',
- path: '/demos/fallback/offline',
- component: () => import('#/views/_core/fallback/offline.vue'),
- meta: {
- icon: 'mdi:offline',
- title: $t('ui.fallback.offline'),
- },
- },
- ],
- },
- // 菜单徽标
- {
- meta: {
- badgeType: 'dot',
- badgeVariants: 'destructive',
- icon: 'lucide:circle-dot',
- title: $t('demos.badge.title'),
- },
- name: 'BadgeDemos',
- path: '/demos/badge',
- children: [
- {
- name: 'BadgeDotDemo',
- component: () => import('#/views/demos/badge/index.vue'),
- path: '/demos/badge/dot',
- meta: {
- badgeType: 'dot',
- icon: 'lucide:square-dot',
- title: $t('demos.badge.dot'),
- },
- },
- {
- name: 'BadgeTextDemo',
- component: () => import('#/views/demos/badge/index.vue'),
- path: '/demos/badge/text',
- meta: {
- badge: '10',
- icon: 'lucide:square-dot',
- title: $t('demos.badge.text'),
- },
- },
- {
- name: 'BadgeColorDemo',
- component: () => import('#/views/demos/badge/index.vue'),
- path: '/demos/badge/color',
- meta: {
- badge: 'Hot',
- badgeVariants: 'destructive',
- icon: 'lucide:square-dot',
- title: $t('demos.badge.color'),
- },
- },
- ],
- },
- // 菜单激活图标
- {
- meta: {
- activeIcon: 'fluent-emoji:radioactive',
- icon: 'bi:radioactive',
- title: $t('demos.activeIcon.title'),
- },
- name: 'ActiveIconDemos',
- path: '/demos/active-icon',
- children: [
- {
- name: 'ActiveIconDemo',
- component: () => import('#/views/demos/active-icon/index.vue'),
- path: '/demos/active-icon/children',
- meta: {
- activeIcon: 'fluent-emoji:radioactive',
- icon: 'bi:radioactive',
- title: $t('demos.activeIcon.children'),
- },
- },
- ],
- },
- // 外部链接
- {
- meta: {
- icon: 'ic:round-settings-input-composite',
- title: $t('demos.outside.title'),
- },
- name: 'OutsideDemos',
- path: '/demos/outside',
- children: [
- {
- name: 'IframeDemos',
- path: '/demos/outside/iframe',
- meta: {
- icon: 'mdi:newspaper-variant-outline',
- title: $t('demos.outside.embedded'),
- },
- children: [
- {
- name: 'VueDocumentDemo',
- path: '/demos/outside/iframe/vue-document',
- component: IFrameView,
- meta: {
- icon: 'logos:vue',
- iframeSrc: 'https://cn.vuejs.org/',
- keepAlive: true,
- title: 'Vue',
- },
- },
- {
- name: 'TailwindcssDemo',
- path: '/demos/outside/iframe/tailwindcss',
- component: IFrameView,
- meta: {
- icon: 'devicon:tailwindcss',
- iframeSrc: 'https://tailwindcss.com/',
- // keepAlive: true,
- title: 'Tailwindcss',
- },
- },
- ],
- },
- {
- name: 'ExternalLinkDemos',
- path: '/demos/outside/external-link',
- meta: {
- icon: 'mdi:newspaper-variant-multiple-outline',
- title: $t('demos.outside.externalLink'),
- },
- children: [
- {
- name: 'ViteDemo',
- path: '/demos/outside/external-link/vite',
- component: IFrameView,
- meta: {
- icon: 'logos:vitejs',
- link: 'https://vitejs.dev/',
- title: 'Vite',
- },
- },
- {
- name: 'VueUseDemo',
- path: '/demos/outside/external-link/vue-use',
- component: IFrameView,
- meta: {
- icon: 'logos:vueuse',
- link: 'https://vueuse.org',
- title: 'VueUse',
- },
- },
- ],
- },
- ],
- },
- // 嵌套菜单
- {
- meta: {
- icon: 'ic:round-menu',
- title: $t('demos.nested.title'),
- },
- name: 'NestedDemos',
- path: '/demos/nested',
- children: [
- {
- name: 'Menu1Demo',
- path: '/demos/nested/menu1',
- component: () => import('#/views/demos/nested/menu-1.vue'),
- meta: {
- icon: 'ic:round-menu',
- keepAlive: true,
- title: $t('demos.nested.menu1'),
- },
- },
- {
- name: 'Menu2Demo',
- path: '/demos/nested/menu2',
- meta: {
- icon: 'ic:round-menu',
- keepAlive: true,
- title: $t('demos.nested.menu2'),
- },
- children: [
- {
- name: 'Menu21Demo',
- path: '/demos/nested/menu2/menu2-1',
- component: () => import('#/views/demos/nested/menu-2-1.vue'),
- meta: {
- icon: 'ic:round-menu',
- keepAlive: true,
- title: $t('demos.nested.menu2_1'),
- },
- },
- ],
- },
- {
- name: 'Menu3Demo',
- path: '/demos/nested/menu3',
- meta: {
- icon: 'ic:round-menu',
- title: $t('demos.nested.menu3'),
- },
- children: [
- {
- name: 'Menu31Demo',
- path: '/demos/nested/menu3/menu3-1',
- component: () => import('#/views/demos/nested/menu-3-1.vue'),
- meta: {
- icon: 'ic:round-menu',
- keepAlive: true,
- title: $t('demos.nested.menu3_1'),
- },
- },
- {
- name: 'Menu32Demo',
- path: '/demos/nested/menu3/menu3-2',
- meta: {
- icon: 'ic:round-menu',
- title: $t('demos.nested.menu3_2'),
- },
- children: [
- {
- name: 'Menu321Demo',
- path: '/demos/nested/menu3/menu3-2/menu3-2-1',
- component: () =>
- import('#/views/demos/nested/menu-3-2-1.vue'),
- meta: {
- icon: 'ic:round-menu',
- keepAlive: true,
- title: $t('demos.nested.menu3_2_1'),
- },
- },
- ],
- },
- ],
- },
- ],
- },
- ],
- },
-];
-
-export default routes;
diff --git a/playground/src/router/routes/modules/examples.ts b/playground/src/router/routes/modules/examples.ts
deleted file mode 100644
index 017b2c22..00000000
--- a/playground/src/router/routes/modules/examples.ts
+++ /dev/null
@@ -1,353 +0,0 @@
-import type { RouteRecordRaw } from 'vue-router';
-
-import { $t } from '#/locales';
-
-const routes: RouteRecordRaw[] = [
- {
- meta: {
- icon: 'ion:layers-outline',
- keepAlive: true,
- order: 1000,
- title: $t('examples.title'),
- },
- name: 'Examples',
- path: '/examples',
- children: [
- {
- name: 'FormExample',
- path: '/examples/form',
- meta: {
- icon: 'mdi:form-select',
- title: $t('examples.form.title'),
- },
- children: [
- {
- name: 'FormBasicExample',
- path: '/examples/form/basic',
- component: () => import('#/views/examples/form/basic.vue'),
- meta: {
- title: $t('examples.form.basic'),
- },
- },
- {
- name: 'FormQueryExample',
- path: '/examples/form/query',
- component: () => import('#/views/examples/form/query.vue'),
- meta: {
- title: $t('examples.form.query'),
- },
- },
- {
- name: 'FormRulesExample',
- path: '/examples/form/rules',
- component: () => import('#/views/examples/form/rules.vue'),
- meta: {
- title: $t('examples.form.rules'),
- },
- },
- {
- name: 'FormDynamicExample',
- path: '/examples/form/dynamic',
- component: () => import('#/views/examples/form/dynamic.vue'),
- meta: {
- title: $t('examples.form.dynamic'),
- },
- },
- {
- name: 'FormLayoutExample',
- path: '/examples/form/custom-layout',
- component: () => import('#/views/examples/form/custom-layout.vue'),
- meta: {
- title: $t('examples.form.layout'),
- },
- },
- {
- name: 'FormCustomExample',
- path: '/examples/form/custom',
- component: () => import('#/views/examples/form/custom.vue'),
- meta: {
- title: $t('examples.form.custom'),
- },
- },
- {
- name: 'FormApiExample',
- path: '/examples/form/api',
- component: () => import('#/views/examples/form/api.vue'),
- meta: {
- title: $t('examples.form.api'),
- },
- },
- {
- name: 'FormMergeExample',
- path: '/examples/form/merge',
- component: () => import('#/views/examples/form/merge.vue'),
- meta: {
- title: $t('examples.form.merge'),
- },
- },
- {
- name: 'FormScrollToErrorExample',
- path: '/examples/form/scroll-to-error-test',
- component: () =>
- import('#/views/examples/form/scroll-to-error-test.vue'),
- meta: {
- title: $t('examples.form.scrollToError'),
- },
- },
- ],
- },
- {
- name: 'VxeTableExample',
- path: '/examples/vxe-table',
- meta: {
- icon: 'lucide:table',
- title: $t('examples.vxeTable.title'),
- },
- children: [
- {
- name: 'VxeTableBasicExample',
- path: '/examples/vxe-table/basic',
- component: () => import('#/views/examples/vxe-table/basic.vue'),
- meta: {
- title: $t('examples.vxeTable.basic'),
- },
- },
- {
- name: 'VxeTableRemoteExample',
- path: '/examples/vxe-table/remote',
- component: () => import('#/views/examples/vxe-table/remote.vue'),
- meta: {
- title: $t('examples.vxeTable.remote'),
- },
- },
- {
- name: 'VxeTableTreeExample',
- path: '/examples/vxe-table/tree',
- component: () => import('#/views/examples/vxe-table/tree.vue'),
- meta: {
- title: $t('examples.vxeTable.tree'),
- },
- },
- {
- name: 'VxeTableFixedExample',
- path: '/examples/vxe-table/fixed',
- component: () => import('#/views/examples/vxe-table/fixed.vue'),
- meta: {
- title: $t('examples.vxeTable.fixed'),
- },
- },
- {
- name: 'VxeTableCustomCellExample',
- path: '/examples/vxe-table/custom-cell',
- component: () =>
- import('#/views/examples/vxe-table/custom-cell.vue'),
- meta: {
- title: $t('examples.vxeTable.custom-cell'),
- },
- },
- {
- name: 'VxeTableFormExample',
- path: '/examples/vxe-table/form',
- component: () => import('#/views/examples/vxe-table/form.vue'),
- meta: {
- title: $t('examples.vxeTable.form'),
- },
- },
- {
- name: 'VxeTableEditCellExample',
- path: '/examples/vxe-table/edit-cell',
- component: () => import('#/views/examples/vxe-table/edit-cell.vue'),
- meta: {
- title: $t('examples.vxeTable.editCell'),
- },
- },
- {
- name: 'VxeTableEditRowExample',
- path: '/examples/vxe-table/edit-row',
- component: () => import('#/views/examples/vxe-table/edit-row.vue'),
- meta: {
- title: $t('examples.vxeTable.editRow'),
- },
- },
- {
- name: 'VxeTableVirtualExample',
- path: '/examples/vxe-table/virtual',
- component: () => import('#/views/examples/vxe-table/virtual.vue'),
- meta: {
- title: $t('examples.vxeTable.virtual'),
- },
- },
- ],
- },
- {
- name: 'CaptchaExample',
- path: '/examples/captcha',
- meta: {
- icon: 'logos:recaptcha',
- title: $t('examples.captcha.title'),
- },
- children: [
- {
- name: 'DragVerifyExample',
- path: '/examples/captcha/slider',
- component: () =>
- import('#/views/examples/captcha/slider-captcha.vue'),
- meta: {
- title: $t('examples.captcha.sliderCaptcha'),
- },
- },
- {
- name: 'RotateVerifyExample',
- path: '/examples/captcha/slider-rotate',
- component: () =>
- import('#/views/examples/captcha/slider-rotate-captcha.vue'),
- meta: {
- title: $t('examples.captcha.sliderRotateCaptcha'),
- },
- },
- {
- name: 'TranslateVerifyExample',
- path: '/examples/captcha/slider-translate',
- component: () =>
- import('#/views/examples/captcha/slider-translate-captcha.vue'),
- meta: {
- title: $t('examples.captcha.sliderTranslateCaptcha'),
- },
- },
- {
- name: 'CaptchaPointSelectionExample',
- path: '/examples/captcha/point-selection',
- component: () =>
- import('#/views/examples/captcha/point-selection-captcha.vue'),
- meta: {
- title: $t('examples.captcha.pointSelection'),
- },
- },
- ],
- },
- {
- name: 'ModalExample',
- path: '/examples/modal',
- component: () => import('#/views/examples/modal/index.vue'),
- meta: {
- icon: 'system-uicons:window-content',
- keepAlive: true,
- title: $t('examples.modal.title'),
- },
- },
- {
- name: 'DrawerExample',
- path: '/examples/drawer',
- component: () => import('#/views/examples/drawer/index.vue'),
- meta: {
- icon: 'iconoir:drawer',
- keepAlive: true,
- title: $t('examples.drawer.title'),
- },
- },
- {
- name: 'EllipsisExample',
- path: '/examples/ellipsis',
- component: () => import('#/views/examples/ellipsis/index.vue'),
- meta: {
- icon: 'ion:ellipsis-horizontal',
- title: $t('examples.ellipsis.title'),
- },
- },
- {
- name: 'VueResizeDemo',
- path: '/demos/resize/basic',
- component: () => import('#/views/examples/resize/basic.vue'),
- meta: {
- icon: 'material-symbols:resize',
- title: $t('examples.resize.title'),
- },
- },
- {
- name: 'ColPageDemo',
- path: '/examples/layout/col-page',
- component: () => import('#/views/examples/layout/col-page.vue'),
- meta: {
- badge: 'Alpha',
- badgeVariants: 'destructive',
- icon: 'material-symbols:horizontal-distribute',
- title: $t('examples.layout.col-page'),
- },
- },
- {
- name: 'TippyDemo',
- path: '/examples/tippy',
- component: () => import('#/views/examples/tippy/index.vue'),
- meta: {
- icon: 'mdi:message-settings-outline',
- title: 'Tippy',
- },
- },
- {
- name: 'JsonViewer',
- path: '/examples/json-viewer',
- component: () => import('#/views/examples/json-viewer/index.vue'),
- meta: {
- icon: 'tabler:json',
- title: 'JsonViewer',
- },
- },
- {
- name: 'Motion',
- path: '/examples/motion',
- component: () => import('#/views/examples/motion/index.vue'),
- meta: {
- icon: 'mdi:animation-play',
- title: 'Motion',
- },
- },
- {
- name: 'CountTo',
- path: '/examples/count-to',
- component: () => import('#/views/examples/count-to/index.vue'),
- meta: {
- icon: 'mdi:animation-play',
- title: 'CountTo',
- },
- },
- {
- name: 'Loading',
- path: '/examples/loading',
- component: () => import('#/views/examples/loading/index.vue'),
- meta: {
- icon: 'mdi:circle-double',
- title: 'Loading',
- },
- },
- {
- name: 'ButtonGroup',
- path: '/examples/button-group',
- component: () => import('#/views/examples/button-group/index.vue'),
- meta: {
- icon: 'mdi:check-circle',
- title: $t('examples.button-group.title'),
- },
- },
- {
- name: 'ContextMenu',
- path: '/examples/context-menu',
- component: () => import('#/views/examples/context-menu/index.vue'),
- meta: {
- icon: 'mdi:menu',
- title: $t('examples.function.contentMenu'),
- },
- },
- {
- name: 'CropperDemo',
- path: '/examples/cropper',
- component: () => import('#/views/examples/cropper/index.vue'),
- meta: {
- icon: 'mdi:crop',
- title: $t('examples.cropper.title'),
- },
- },
- ],
- },
-];
-
-export default routes;
diff --git a/playground/src/router/routes/modules/system.ts b/playground/src/router/routes/modules/system.ts
deleted file mode 100644
index e1bf7125..00000000
--- a/playground/src/router/routes/modules/system.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-import type { RouteRecordRaw } from 'vue-router';
-
-import { $t } from '#/locales';
-
-const routes: RouteRecordRaw[] = [
- {
- meta: {
- icon: 'ion:settings-outline',
- order: 9997,
- title: $t('system.title'),
- },
- name: 'System',
- path: '/system',
- children: [
- {
- path: '/system/role',
- name: 'SystemRole',
- meta: {
- icon: 'mdi:account-group',
- title: $t('system.role.title'),
- },
- component: () => import('#/views/system/role/list.vue'),
- },
- {
- path: '/system/menu',
- name: 'SystemMenu',
- meta: {
- icon: 'mdi:menu',
- title: $t('system.menu.title'),
- },
- component: () => import('#/views/system/menu/list.vue'),
- },
- {
- path: '/system/dept',
- name: 'SystemDept',
- meta: {
- icon: 'charm:organisation',
- title: $t('system.dept.title'),
- },
- component: () => import('#/views/system/dept/list.vue'),
- },
- ],
- },
-];
-
-export default routes;
diff --git a/playground/src/router/routes/modules/vben.ts b/playground/src/router/routes/modules/vben.ts
deleted file mode 100644
index 6b621e9e..00000000
--- a/playground/src/router/routes/modules/vben.ts
+++ /dev/null
@@ -1,116 +0,0 @@
-import type { RouteRecordRaw } from 'vue-router';
-
-import {
- VBEN_ANT_PREVIEW_URL,
- VBEN_DOC_URL,
- VBEN_ELE_PREVIEW_URL,
- VBEN_GITHUB_URL,
- VBEN_LOGO_URL,
- VBEN_NAIVE_PREVIEW_URL,
- VBEN_TD_PREVIEW_URL,
-} from '@vben/constants';
-import { SvgAntdvLogoIcon, SvgTDesignIcon } from '@vben/icons';
-
-import { IFrameView } from '#/layouts';
-import { $t } from '#/locales';
-
-const routes: RouteRecordRaw[] = [
- {
- meta: {
- badgeType: 'dot',
- icon: VBEN_LOGO_URL,
- order: 9998,
- title: $t('demos.vben.title'),
- },
- name: 'VbenProject',
- path: '/vben-admin',
- children: [
- {
- name: 'VbenDocument',
- path: '/vben-admin/document',
- component: IFrameView,
- meta: {
- icon: 'lucide:book-open-text',
- link: VBEN_DOC_URL,
- title: $t('demos.vben.document'),
- },
- },
- {
- name: 'VbenGithub',
- path: '/vben-admin/github',
- component: IFrameView,
- meta: {
- icon: 'mdi:github',
- link: VBEN_GITHUB_URL,
- title: 'Github',
- },
- },
- {
- name: 'VbenAntdv',
- path: '/vben-admin/antdv',
- component: IFrameView,
- meta: {
- badgeType: 'dot',
- icon: SvgAntdvLogoIcon,
- link: VBEN_ANT_PREVIEW_URL,
- title: $t('demos.vben.antdv'),
- },
- },
- {
- name: 'VbenNaive',
- path: '/vben-admin/naive',
- component: IFrameView,
- meta: {
- badgeType: 'dot',
- icon: 'logos:naiveui',
- link: VBEN_NAIVE_PREVIEW_URL,
- title: $t('demos.vben.naive-ui'),
- },
- },
- {
- name: 'VbenElementPlus',
- path: '/vben-admin/ele',
- component: IFrameView,
- meta: {
- badgeType: 'dot',
- icon: 'logos:element',
- link: VBEN_ELE_PREVIEW_URL,
- title: $t('demos.vben.element-plus'),
- },
- },
- {
- name: 'VbenTDesign',
- path: '/vben-admin/tdesign',
- component: IFrameView,
- meta: {
- badgeType: 'dot',
- icon: SvgTDesignIcon,
- link: VBEN_TD_PREVIEW_URL,
- title: $t('demos.vben.tdesign'),
- },
- },
- ],
- },
- {
- component: () => import('#/views/_core/about/index.vue'),
- meta: {
- icon: 'lucide:copyright',
- order: 9999,
- title: $t('demos.vben.about'),
- },
- name: 'VbenAbout',
- path: '/vben-admin/about',
- },
- {
- name: 'Profile',
- path: '/profile',
- component: () => import('#/views/_core/profile/index.vue'),
- meta: {
- icon: 'lucide:user',
- hideInMenu: true,
- title: $t('page.auth.profile'),
- },
- },
-];
-
-export default routes;
diff --git a/playground/src/store/auth.ts b/playground/src/store/auth.ts
deleted file mode 100644
index 548869f0..00000000
--- a/playground/src/store/auth.ts
+++ /dev/null
@@ -1,127 +0,0 @@
-import type { Recordable, UserInfo } from '@vben/types';
-
-import { ref } from 'vue';
-import { useRouter } from 'vue-router';
-
-import { LOGIN_PATH } from '@vben/constants';
-import { preferences } from '@vben/preferences';
-import { resetAllStores, useAccessStore, useUserStore } from '@vben/stores';
-
-import { notification } from 'antdv-next';
-import { defineStore } from 'pinia';
-
-import { getAccessCodesApi, getUserInfoApi, loginApi, logoutApi } from '#/api';
-import { $t } from '#/locales';
-
-export const useAuthStore = defineStore('auth', () => {
- const accessStore = useAccessStore();
- const userStore = useUserStore();
- const router = useRouter();
-
- const loginLoading = ref(false);
-
- /**
- * 异步处理登录操作
- * Asynchronously handle the login process
- * @param params 登录表单数据
- * @param onSuccess 成功之后的回调函数
- */
- async function authLogin(
- params: Recordable,
- onSuccess?: () => Promise | void,
- ) {
- // 异步处理用户登录操作并获取 accessToken
- let userInfo: null | UserInfo = null;
- try {
- loginLoading.value = true;
- const { accessToken } = await loginApi(params);
-
- // 如果成功获取到 accessToken
- if (accessToken) {
- accessStore.setAccessToken(accessToken);
-
- // 获取用户信息并存储到 accessStore 中
- const [fetchUserInfoResult, accessCodes] = await Promise.all([
- fetchUserInfo(),
- getAccessCodesApi(),
- ]);
-
- userInfo = fetchUserInfoResult;
-
- userStore.setUserInfo(userInfo);
- accessStore.setAccessCodes(accessCodes);
-
- if (accessStore.loginExpired) {
- accessStore.setLoginExpired(false);
- } else {
- onSuccess
- ? await onSuccess?.()
- : await router.push(
- userInfo.homePath || preferences.app.defaultHomePath,
- );
- }
-
- if (userInfo?.realName) {
- notification.success({
- description: `${$t('authentication.loginSuccessDesc')}:${userInfo?.realName}`,
- duration: 3,
- message: $t('authentication.loginSuccess'),
- });
- }
- }
- } finally {
- loginLoading.value = false;
- }
-
- return {
- userInfo,
- };
- }
-
- const isLoggingOut = ref(false); // 正在 logout 标识, 防止 /logout 死循环.
-
- async function logout(redirect: boolean = true) {
- if (isLoggingOut.value) return; // 正在登出中, 说明已进入循环, 直接返回.
- isLoggingOut.value = true; // 设置 标识
-
- try {
- await logoutApi();
- } catch {
- // 不做任何处理
- } finally {
- isLoggingOut.value = false; // 重置 标识
-
- resetAllStores();
- accessStore.setLoginExpired(false);
- }
-
- // 回登录页带上当前路由地址
- await router.replace({
- path: LOGIN_PATH,
- query: redirect
- ? {
- redirect: encodeURIComponent(router.currentRoute.value.fullPath),
- }
- : {},
- });
- }
-
- async function fetchUserInfo() {
- let userInfo: null | UserInfo = null;
- userInfo = await getUserInfoApi();
- userStore.setUserInfo(userInfo);
- return userInfo;
- }
-
- function $reset() {
- loginLoading.value = false;
- }
-
- return {
- $reset,
- authLogin,
- fetchUserInfo,
- loginLoading,
- logout,
- };
-});
diff --git a/playground/src/store/index.ts b/playground/src/store/index.ts
deleted file mode 100644
index 269586ee..00000000
--- a/playground/src/store/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from './auth';
diff --git a/playground/src/timezone-init.ts b/playground/src/timezone-init.ts
deleted file mode 100644
index 1d82bd47..00000000
--- a/playground/src/timezone-init.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import { setTimezoneHandler } from '@vben/stores';
-
-import { getTimezoneApi, getTimezoneOptionsApi, setTimezoneApi } from '#/api';
-
-/**
- * 初始化时区处理,通过API保存时区设置
- */
-export function initTimezone() {
- setTimezoneHandler({
- getTimezone() {
- return getTimezoneApi();
- },
- setTimezone(timezone: string) {
- return setTimezoneApi(timezone);
- },
- getTimezoneOptions() {
- return getTimezoneOptionsApi();
- },
- });
-}
diff --git a/playground/src/views/_core/README.md b/playground/src/views/_core/README.md
deleted file mode 100644
index 8248afe6..00000000
--- a/playground/src/views/_core/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# \_core
-
-此目录包含应用程序正常运行所需的基本视图。这些视图是应用程序布局中使用的视图。
diff --git a/playground/src/views/_core/about/index.vue b/playground/src/views/_core/about/index.vue
deleted file mode 100644
index 0ee52433..00000000
--- a/playground/src/views/_core/about/index.vue
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
diff --git a/playground/src/views/_core/authentication/code-login.vue b/playground/src/views/_core/authentication/code-login.vue
deleted file mode 100644
index 428c6061..00000000
--- a/playground/src/views/_core/authentication/code-login.vue
+++ /dev/null
@@ -1,109 +0,0 @@
-
-
-
-
-
diff --git a/playground/src/views/_core/authentication/forget-password.vue b/playground/src/views/_core/authentication/forget-password.vue
deleted file mode 100644
index 34491113..00000000
--- a/playground/src/views/_core/authentication/forget-password.vue
+++ /dev/null
@@ -1,42 +0,0 @@
-
-
-
-
-
diff --git a/playground/src/views/_core/authentication/login.vue b/playground/src/views/_core/authentication/login.vue
deleted file mode 100644
index 162398e0..00000000
--- a/playground/src/views/_core/authentication/login.vue
+++ /dev/null
@@ -1,132 +0,0 @@
-
-
-
-
-
diff --git a/playground/src/views/_core/authentication/qrcode-login.vue b/playground/src/views/_core/authentication/qrcode-login.vue
deleted file mode 100644
index 23f5f2da..00000000
--- a/playground/src/views/_core/authentication/qrcode-login.vue
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
diff --git a/playground/src/views/_core/authentication/register.vue b/playground/src/views/_core/authentication/register.vue
deleted file mode 100644
index b1a5de72..00000000
--- a/playground/src/views/_core/authentication/register.vue
+++ /dev/null
@@ -1,96 +0,0 @@
-
-
-
-
-
diff --git a/playground/src/views/_core/fallback/coming-soon.vue b/playground/src/views/_core/fallback/coming-soon.vue
deleted file mode 100644
index f394930f..00000000
--- a/playground/src/views/_core/fallback/coming-soon.vue
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
diff --git a/playground/src/views/_core/fallback/forbidden.vue b/playground/src/views/_core/fallback/forbidden.vue
deleted file mode 100644
index 8ea65fed..00000000
--- a/playground/src/views/_core/fallback/forbidden.vue
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
diff --git a/playground/src/views/_core/fallback/internal-error.vue b/playground/src/views/_core/fallback/internal-error.vue
deleted file mode 100644
index 819a47d5..00000000
--- a/playground/src/views/_core/fallback/internal-error.vue
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
diff --git a/playground/src/views/_core/fallback/not-found.vue b/playground/src/views/_core/fallback/not-found.vue
deleted file mode 100644
index 4d178e9c..00000000
--- a/playground/src/views/_core/fallback/not-found.vue
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
diff --git a/playground/src/views/_core/fallback/offline.vue b/playground/src/views/_core/fallback/offline.vue
deleted file mode 100644
index 5de4a88d..00000000
--- a/playground/src/views/_core/fallback/offline.vue
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
diff --git a/playground/src/views/_core/profile/base-setting.vue b/playground/src/views/_core/profile/base-setting.vue
deleted file mode 100644
index aa8a4c26..00000000
--- a/playground/src/views/_core/profile/base-setting.vue
+++ /dev/null
@@ -1,65 +0,0 @@
-
-
-
-
diff --git a/playground/src/views/_core/profile/index.vue b/playground/src/views/_core/profile/index.vue
deleted file mode 100644
index 8740894e..00000000
--- a/playground/src/views/_core/profile/index.vue
+++ /dev/null
@@ -1,49 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/_core/profile/notification-setting.vue b/playground/src/views/_core/profile/notification-setting.vue
deleted file mode 100644
index 324a4b39..00000000
--- a/playground/src/views/_core/profile/notification-setting.vue
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
-
diff --git a/playground/src/views/_core/profile/password-setting.vue b/playground/src/views/_core/profile/password-setting.vue
deleted file mode 100644
index adb065a2..00000000
--- a/playground/src/views/_core/profile/password-setting.vue
+++ /dev/null
@@ -1,63 +0,0 @@
-
-
-
-
diff --git a/playground/src/views/_core/profile/security-setting.vue b/playground/src/views/_core/profile/security-setting.vue
deleted file mode 100644
index be30db58..00000000
--- a/playground/src/views/_core/profile/security-setting.vue
+++ /dev/null
@@ -1,43 +0,0 @@
-
-
-
-
diff --git a/playground/src/views/dashboard/analytics/analytics-trends.vue b/playground/src/views/dashboard/analytics/analytics-trends.vue
deleted file mode 100644
index 9bd90fc8..00000000
--- a/playground/src/views/dashboard/analytics/analytics-trends.vue
+++ /dev/null
@@ -1,97 +0,0 @@
-
-
-
-
-
diff --git a/playground/src/views/dashboard/analytics/analytics-visits-data.vue b/playground/src/views/dashboard/analytics/analytics-visits-data.vue
deleted file mode 100644
index 651abbc1..00000000
--- a/playground/src/views/dashboard/analytics/analytics-visits-data.vue
+++ /dev/null
@@ -1,81 +0,0 @@
-
-
-
-
-
diff --git a/playground/src/views/dashboard/analytics/analytics-visits-sales.vue b/playground/src/views/dashboard/analytics/analytics-visits-sales.vue
deleted file mode 100644
index 6ff52086..00000000
--- a/playground/src/views/dashboard/analytics/analytics-visits-sales.vue
+++ /dev/null
@@ -1,46 +0,0 @@
-
-
-
-
-
diff --git a/playground/src/views/dashboard/analytics/analytics-visits-source.vue b/playground/src/views/dashboard/analytics/analytics-visits-source.vue
deleted file mode 100644
index d97c3c0f..00000000
--- a/playground/src/views/dashboard/analytics/analytics-visits-source.vue
+++ /dev/null
@@ -1,64 +0,0 @@
-
-
-
-
-
diff --git a/playground/src/views/dashboard/analytics/analytics-visits.vue b/playground/src/views/dashboard/analytics/analytics-visits.vue
deleted file mode 100644
index fc961c83..00000000
--- a/playground/src/views/dashboard/analytics/analytics-visits.vue
+++ /dev/null
@@ -1,54 +0,0 @@
-
-
-
-
-
diff --git a/playground/src/views/dashboard/analytics/index.vue b/playground/src/views/dashboard/analytics/index.vue
deleted file mode 100644
index 00b34df1..00000000
--- a/playground/src/views/dashboard/analytics/index.vue
+++ /dev/null
@@ -1,90 +0,0 @@
-
-
-
-
-
diff --git a/playground/src/views/dashboard/workspace/index.vue b/playground/src/views/dashboard/workspace/index.vue
deleted file mode 100644
index b95d6138..00000000
--- a/playground/src/views/dashboard/workspace/index.vue
+++ /dev/null
@@ -1,266 +0,0 @@
-
-
-
-
-
-
- 早安, {{ userStore.userInfo?.realName }}, 开始您一天的工作吧!
-
- 今日晴,20℃ - 32℃!
-
-
-
-
-
diff --git a/playground/src/views/demos/access/admin-visible.vue b/playground/src/views/demos/access/admin-visible.vue
deleted file mode 100644
index 079b9309..00000000
--- a/playground/src/views/demos/access/admin-visible.vue
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
diff --git a/playground/src/views/demos/access/button-control.vue b/playground/src/views/demos/access/button-control.vue
deleted file mode 100644
index 63557b5e..00000000
--- a/playground/src/views/demos/access/button-control.vue
+++ /dev/null
@@ -1,155 +0,0 @@
-
-
-
-
-
-
- 当前角色:
-
- {{ userStore.userRoles?.[0] }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/demos/access/index.vue b/playground/src/views/demos/access/index.vue
deleted file mode 100644
index 88649764..00000000
--- a/playground/src/views/demos/access/index.vue
+++ /dev/null
@@ -1,93 +0,0 @@
-
-
-
-
-
- 当前权限模式:
- {{
- accessMode === 'frontend' ? '前端权限控制' : '后端权限控制'
- }}
-
-
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/demos/access/menu-visible-403.vue b/playground/src/views/demos/access/menu-visible-403.vue
deleted file mode 100644
index 7e3cde88..00000000
--- a/playground/src/views/demos/access/menu-visible-403.vue
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
diff --git a/playground/src/views/demos/access/super-visible.vue b/playground/src/views/demos/access/super-visible.vue
deleted file mode 100644
index 877fcd11..00000000
--- a/playground/src/views/demos/access/super-visible.vue
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
diff --git a/playground/src/views/demos/access/user-visible.vue b/playground/src/views/demos/access/user-visible.vue
deleted file mode 100644
index a3c5f001..00000000
--- a/playground/src/views/demos/access/user-visible.vue
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
diff --git a/playground/src/views/demos/active-icon/index.vue b/playground/src/views/demos/active-icon/index.vue
deleted file mode 100644
index af9f69af..00000000
--- a/playground/src/views/demos/active-icon/index.vue
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
diff --git a/playground/src/views/demos/badge/index.vue b/playground/src/views/demos/badge/index.vue
deleted file mode 100644
index 05168215..00000000
--- a/playground/src/views/demos/badge/index.vue
+++ /dev/null
@@ -1,113 +0,0 @@
-
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/demos/breadcrumb/lateral-detail.vue b/playground/src/views/demos/breadcrumb/lateral-detail.vue
deleted file mode 100644
index 73d778d0..00000000
--- a/playground/src/views/demos/breadcrumb/lateral-detail.vue
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/demos/breadcrumb/lateral.vue b/playground/src/views/demos/breadcrumb/lateral.vue
deleted file mode 100644
index cbf64bb7..00000000
--- a/playground/src/views/demos/breadcrumb/lateral.vue
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/demos/breadcrumb/level-detail.vue b/playground/src/views/demos/breadcrumb/level-detail.vue
deleted file mode 100644
index 7aa18d4b..00000000
--- a/playground/src/views/demos/breadcrumb/level-detail.vue
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
diff --git a/playground/src/views/demos/features/clipboard/index.vue b/playground/src/views/demos/features/clipboard/index.vue
deleted file mode 100644
index 32e4e4b9..00000000
--- a/playground/src/views/demos/features/clipboard/index.vue
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
-
-
- Current copied: {{ text || 'none' }}
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/demos/features/file-download/base64.ts b/playground/src/views/demos/features/file-download/base64.ts
deleted file mode 100644
index ee6ac2bc..00000000
--- a/playground/src/views/demos/features/file-download/base64.ts
+++ /dev/null
@@ -1 +0,0 @@
-export default `data:image/png;base64,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`;
diff --git a/playground/src/views/demos/features/file-download/index.vue b/playground/src/views/demos/features/file-download/index.vue
deleted file mode 100644
index a40a2d3e..00000000
--- a/playground/src/views/demos/features/file-download/index.vue
+++ /dev/null
@@ -1,100 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ downloadResult }}
-
-
-
diff --git a/playground/src/views/demos/features/full-screen/index.vue b/playground/src/views/demos/features/full-screen/index.vue
deleted file mode 100644
index 172e57f7..00000000
--- a/playground/src/views/demos/features/full-screen/index.vue
+++ /dev/null
@@ -1,47 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
- Current State: {{ isFullscreen }}
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/demos/features/hide-menu-children/children.vue b/playground/src/views/demos/features/hide-menu-children/children.vue
deleted file mode 100644
index 1959f96d..00000000
--- a/playground/src/views/demos/features/hide-menu-children/children.vue
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
-
-
-
-
- 关闭当前标签页
-
-
-
-
diff --git a/playground/src/views/demos/features/hide-menu-children/parent.vue b/playground/src/views/demos/features/hide-menu-children/parent.vue
deleted file mode 100644
index b732c1be..00000000
--- a/playground/src/views/demos/features/hide-menu-children/parent.vue
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
- 打开子路由
-
-
-
-
diff --git a/playground/src/views/demos/features/icons/index.vue b/playground/src/views/demos/features/icons/index.vue
deleted file mode 100644
index 93975063..00000000
--- a/playground/src/views/demos/features/icons/index.vue
+++ /dev/null
@@ -1,115 +0,0 @@
-
-
-
-
-
-
- 图标可在
-
- Iconify
-
- 中查找,支持多种图标库,如 Material Design, Font Awesome, Jam Icons 等。
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 原始样式(Iconify):
-
-
-
- 原始样式(svg):
-
-
-
- 自定义Input:
-
-
-
- 显示为一个Icon:
-
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/demos/features/json-bigint/index.vue b/playground/src/views/demos/features/json-bigint/index.vue
deleted file mode 100644
index c35ae1e3..00000000
--- a/playground/src/views/demos/features/json-bigint/index.vue
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-
-
-
-
- 有些后端接口返回的ID是长整数,但javascript原生的JSON解析是不支持超过2^53-1的长整数的。
- 这种情况可以建议后端返回数据前将长整数转换为字符串类型。如果后端不接受我们的建议😡……
-
- 下面的按钮点击后会发起请求,接口返回的JSON数据中的id字段是超出整数范围的数字,已自动将其解析为字符串
-
-
-
-
-
-
-
diff --git a/playground/src/views/demos/features/login-expired/index.vue b/playground/src/views/demos/features/login-expired/index.vue
deleted file mode 100644
index 98ec5227..00000000
--- a/playground/src/views/demos/features/login-expired/index.vue
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-
-
-
-
- 接口请求遇到401状态码时,需要重新登录。有两种方式:
-
1.转到登录页,登录成功后跳转回原页面
-
- 2.弹出重新登录弹窗,登录后关闭弹窗,不进行任何页面跳转(刷新后还是会跳转登录页面)
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/demos/features/menu-query/index.vue b/playground/src/views/demos/features/menu-query/index.vue
deleted file mode 100644
index 6943a248..00000000
--- a/playground/src/views/demos/features/menu-query/index.vue
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
diff --git a/playground/src/views/demos/features/new-window/index.vue b/playground/src/views/demos/features/new-window/index.vue
deleted file mode 100644
index 68f89d0d..00000000
--- a/playground/src/views/demos/features/new-window/index.vue
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
diff --git a/playground/src/views/demos/features/request-params-serializer/index.vue b/playground/src/views/demos/features/request-params-serializer/index.vue
deleted file mode 100644
index 0acc59d2..00000000
--- a/playground/src/views/demos/features/request-params-serializer/index.vue
+++ /dev/null
@@ -1,61 +0,0 @@
-
-
-
-
-
- brackets
- comma
- indices
- repeat
-
-
-
-
需要提交的参数
-
{{ JSON.stringify(params, null, 2) }}
-
-
-
-
访问地址
-
{{ response }}
-
-
-
参数字符串
-
{{ paramsStr }}
-
-
-
参数解码
-
{{ decodeURIComponent(paramsStr) }}
-
-
-
-
-
-
diff --git a/playground/src/views/demos/features/tabs/index.vue b/playground/src/views/demos/features/tabs/index.vue
deleted file mode 100644
index 5b5bdd7d..00000000
--- a/playground/src/views/demos/features/tabs/index.vue
+++ /dev/null
@@ -1,105 +0,0 @@
-
-
-
-
-
-
- 如果标签页存在,直接跳转切换。如果标签页不存在,则打开新的标签页。
-
-
-
-
-
-
-
-
- 用于动态控制标签页的各种操作
-
-
-
-
-
-
-
-
-
-
-
-
- 该操作不会影响页面标题,仅修改Tab标题
-
-
-
-
-
-
-
-
-
-
- 限制带参数的tab打开的最大数量,由 `route.meta.maxNumOfOpenTab` 控制
-
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/demos/features/tabs/tab-detail.vue b/playground/src/views/demos/features/tabs/tab-detail.vue
deleted file mode 100644
index c03b61c8..00000000
--- a/playground/src/views/demos/features/tabs/tab-detail.vue
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
-
- {{ index }} - 详情页内容在此
-
-
diff --git a/playground/src/views/demos/features/vue-query/concurrency-caching.vue b/playground/src/views/demos/features/vue-query/concurrency-caching.vue
deleted file mode 100644
index 1e0f3280..00000000
--- a/playground/src/views/demos/features/vue-query/concurrency-caching.vue
+++ /dev/null
@@ -1,61 +0,0 @@
-
-
-
-
-
以下{{ count }}个组件共用一个数据源。
-
缓存更新时间:{{ new Date(dataUpdatedAt).toLocaleString() }}
-
-
-
-
diff --git a/playground/src/views/demos/features/vue-query/index.vue b/playground/src/views/demos/features/vue-query/index.vue
deleted file mode 100644
index cc60b1a2..00000000
--- a/playground/src/views/demos/features/vue-query/index.vue
+++ /dev/null
@@ -1,40 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/demos/features/vue-query/infinite-queries.vue b/playground/src/views/demos/features/vue-query/infinite-queries.vue
deleted file mode 100644
index f6545ebe..00000000
--- a/playground/src/views/demos/features/vue-query/infinite-queries.vue
+++ /dev/null
@@ -1,58 +0,0 @@
-
-
-
-
-
加载...
-
出错了: {{ error }}
-
-
Fetching...
-
- -
- {{ product.title }}
-
-
-
-
-
-
diff --git a/playground/src/views/demos/features/vue-query/paginated-queries.vue b/playground/src/views/demos/features/vue-query/paginated-queries.vue
deleted file mode 100644
index 5a157fb6..00000000
--- a/playground/src/views/demos/features/vue-query/paginated-queries.vue
+++ /dev/null
@@ -1,52 +0,0 @@
-
-
-
-
-
-
当前页: {{ page }}
-
-
-
-
加载中...
-
出错了: {{ error }}
-
-
-
diff --git a/playground/src/views/demos/features/vue-query/query-retries.vue b/playground/src/views/demos/features/vue-query/query-retries.vue
deleted file mode 100644
index 53ee8faa..00000000
--- a/playground/src/views/demos/features/vue-query/query-retries.vue
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
- 重试次数{{ count }}
- {{ error }}
-
diff --git a/playground/src/views/demos/features/vue-query/typing.ts b/playground/src/views/demos/features/vue-query/typing.ts
deleted file mode 100644
index 95558dd8..00000000
--- a/playground/src/views/demos/features/vue-query/typing.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-export interface IProducts {
- limit: number;
- products: {
- brand: string;
- category: string;
- description: string;
- discountPercentage: string;
- id: string;
- images: string[];
- price: string;
- rating: string;
- stock: string;
- thumbnail: string;
- title: string;
- }[];
- skip: number;
- total: number;
-}
diff --git a/playground/src/views/demos/features/watermark/index.vue b/playground/src/views/demos/features/watermark/index.vue
deleted file mode 100644
index 82f994f5..00000000
--- a/playground/src/views/demos/features/watermark/index.vue
+++ /dev/null
@@ -1,86 +0,0 @@
-
-
-
-
-
-
- 水印使用了
-
- watermark-js-plus
-
- 开源插件,详细配置可见插件配置。
-
-
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/demos/nested/menu-1.vue b/playground/src/views/demos/nested/menu-1.vue
deleted file mode 100644
index f394930f..00000000
--- a/playground/src/views/demos/nested/menu-1.vue
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
diff --git a/playground/src/views/demos/nested/menu-2-1.vue b/playground/src/views/demos/nested/menu-2-1.vue
deleted file mode 100644
index f394930f..00000000
--- a/playground/src/views/demos/nested/menu-2-1.vue
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
diff --git a/playground/src/views/demos/nested/menu-3-1.vue b/playground/src/views/demos/nested/menu-3-1.vue
deleted file mode 100644
index f394930f..00000000
--- a/playground/src/views/demos/nested/menu-3-1.vue
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
diff --git a/playground/src/views/demos/nested/menu-3-2-1.vue b/playground/src/views/demos/nested/menu-3-2-1.vue
deleted file mode 100644
index f394930f..00000000
--- a/playground/src/views/demos/nested/menu-3-2-1.vue
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
diff --git a/playground/src/views/examples/button-group/index.vue b/playground/src/views/examples/button-group/index.vue
deleted file mode 100644
index f642ce16..00000000
--- a/playground/src/views/examples/button-group/index.vue
+++ /dev/null
@@ -1,229 +0,0 @@
-
-
-
-
-
-
-
- 按钮组:
-
-
-
- {{ btn.label }}
-
-
-
-
- {{ btn.label }}
-
-
-
- 单选:{{ radioValue }}
-
-
-
- 单选插槽:{{ radioValue }}
-
-
-
-
- {{ label }}
- {{ value }}
- {{ data.num }}
-
-
-
-
- 多选{{ checkValue }}
-
-
-
- 自定义图标{{ checkValue }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/examples/captcha/point-selection-captcha.vue b/playground/src/views/examples/captcha/point-selection-captcha.vue
deleted file mode 100644
index 2663cb5e..00000000
--- a/playground/src/views/examples/captcha/point-selection-captcha.vue
+++ /dev/null
@@ -1,181 +0,0 @@
-
-
-
-
-
-
-
-
-
- px
-
-
-
-
- px
-
-
-
-
- px
-
-
-
-
- px
-
-
-
-
-
-
- {{ params.title || $t('examples.captcha.captchaCardTitle') }}
-
-
-
-
- -
- {{
- $t('examples.captcha.index') + point.i
- }}
- {{
- $t('examples.captcha.timestamp') + point.t
- }}
- {{
- $t('examples.captcha.x') + point.x
- }}
- {{
- $t('examples.captcha.y') + point.y
- }}
-
-
-
-
-
diff --git a/playground/src/views/examples/captcha/slider-captcha.vue b/playground/src/views/examples/captcha/slider-captcha.vue
deleted file mode 100644
index 174a0b66..00000000
--- a/playground/src/views/examples/captcha/slider-captcha.vue
+++ /dev/null
@@ -1,117 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 成功
-
-
- 拖动
-
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/examples/captcha/slider-rotate-captcha.vue b/playground/src/views/examples/captcha/slider-rotate-captcha.vue
deleted file mode 100644
index 9b012753..00000000
--- a/playground/src/views/examples/captcha/slider-rotate-captcha.vue
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/examples/captcha/slider-translate-captcha.vue b/playground/src/views/examples/captcha/slider-translate-captcha.vue
deleted file mode 100644
index 5e4d5a3e..00000000
--- a/playground/src/views/examples/captcha/slider-translate-captcha.vue
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/examples/context-menu/index.vue b/playground/src/views/examples/context-menu/index.vue
deleted file mode 100644
index 0bdadc2b..00000000
--- a/playground/src/views/examples/context-menu/index.vue
+++ /dev/null
@@ -1,59 +0,0 @@
-
-
-
-
-
- 一共四个菜单(刷新、关闭当前、关闭其他、关闭所有)
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/examples/count-to/index.vue b/playground/src/views/examples/count-to/index.vue
deleted file mode 100644
index bf8d3f76..00000000
--- a/playground/src/views/examples/count-to/index.vue
+++ /dev/null
@@ -1,178 +0,0 @@
-
-
-
-
-
- 使用useTransition封装的数字滚动动画组件,每次改变当前值都会产生过渡动画。
-
-
-
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/examples/cropper/index.vue b/playground/src/views/examples/cropper/index.vue
deleted file mode 100644
index 09ba10c2..00000000
--- a/playground/src/views/examples/cropper/index.vue
+++ /dev/null
@@ -1,144 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
![裁剪预览]()
-
-
-
-
-
-
diff --git a/playground/src/views/examples/doc-button.vue b/playground/src/views/examples/doc-button.vue
deleted file mode 100644
index c9746adc..00000000
--- a/playground/src/views/examples/doc-button.vue
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
-
diff --git a/playground/src/views/examples/drawer/auto-height-demo.vue b/playground/src/views/examples/drawer/auto-height-demo.vue
deleted file mode 100644
index 1197e02f..00000000
--- a/playground/src/views/examples/drawer/auto-height-demo.vue
+++ /dev/null
@@ -1,47 +0,0 @@
-
-
-
-
- {{ item }}
-
-
-
-
-
-
-
diff --git a/playground/src/views/examples/drawer/base-demo.vue b/playground/src/views/examples/drawer/base-demo.vue
deleted file mode 100644
index 2e36966d..00000000
--- a/playground/src/views/examples/drawer/base-demo.vue
+++ /dev/null
@@ -1,35 +0,0 @@
-
-
-
- extra
- base demo
-
-
-
-
-
-
diff --git a/playground/src/views/examples/drawer/dynamic-demo.vue b/playground/src/views/examples/drawer/dynamic-demo.vue
deleted file mode 100644
index 18e67631..00000000
--- a/playground/src/views/examples/drawer/dynamic-demo.vue
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/examples/drawer/form-drawer-demo.vue b/playground/src/views/examples/drawer/form-drawer-demo.vue
deleted file mode 100644
index 5af392f6..00000000
--- a/playground/src/views/examples/drawer/form-drawer-demo.vue
+++ /dev/null
@@ -1,56 +0,0 @@
-
-
-
-
-
-
diff --git a/playground/src/views/examples/drawer/in-content-demo.vue b/playground/src/views/examples/drawer/in-content-demo.vue
deleted file mode 100644
index 66c7d38d..00000000
--- a/playground/src/views/examples/drawer/in-content-demo.vue
+++ /dev/null
@@ -1,48 +0,0 @@
-
-
-
- extra
- 此弹窗指定在内容区域打开,并且在关闭之后弹窗内容不会被销毁
-
-
-
-
diff --git a/playground/src/views/examples/drawer/index.vue b/playground/src/views/examples/drawer/index.vue
deleted file mode 100644
index 0d8e9336..00000000
--- a/playground/src/views/examples/drawer/index.vue
+++ /dev/null
@@ -1,195 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 一个基础的抽屉示例
-
-
-
-
-
-
-
-
- 指定抽屉在内容区域打开,不会覆盖顶部和左侧菜单等区域
-
-
-
-
-
-
-
-
- 可根据内容自动计算滚动高度
-
-
-
-
- 通过 setState 动态调整抽屉数据
-
-
-
-
-
- 通过共享 sharedData 来进行数据交互
-
-
-
-
- 打开抽屉并设置表单schema以及数据
-
-
-
-
diff --git a/playground/src/views/examples/drawer/shared-data-demo.vue b/playground/src/views/examples/drawer/shared-data-demo.vue
deleted file mode 100644
index 1be3641c..00000000
--- a/playground/src/views/examples/drawer/shared-data-demo.vue
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
- 外部传递数据: {{ data }}
-
-
diff --git a/playground/src/views/examples/ellipsis/index.vue b/playground/src/views/examples/ellipsis/index.vue
deleted file mode 100644
index 5c1ad1ce..00000000
--- a/playground/src/views/examples/ellipsis/index.vue
+++ /dev/null
@@ -1,46 +0,0 @@
-
-
-
-
-
-
-
-
- {{ text }}
-
-
-
- {{ text }}
-
-
-
- {{ text }}
-
-
-
- 住在我心里孤独的 孤独的海怪 痛苦之王 开始厌倦 深海的光 停滞的海浪
-
-
- 《秦皇岛》
住在我心里孤独的
孤独的海怪 痛苦之王
开始厌倦
- 深海的光 停滞的海浪
-
-
-
-
-
-
diff --git a/playground/src/views/examples/form/api.vue b/playground/src/views/examples/form/api.vue
deleted file mode 100644
index a637b961..00000000
--- a/playground/src/views/examples/form/api.vue
+++ /dev/null
@@ -1,274 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/examples/form/basic.vue b/playground/src/views/examples/form/basic.vue
deleted file mode 100644
index 1d2c48dd..00000000
--- a/playground/src/views/examples/form/basic.vue
+++ /dev/null
@@ -1,498 +0,0 @@
-
-
-
-
-
-
-
- 表单组件基础示例,请注意,该页面用到的参数代码会添加一些简单注释,方便理解,请仔细查看。
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/examples/form/custom-layout.vue b/playground/src/views/examples/form/custom-layout.vue
deleted file mode 100644
index ac106e75..00000000
--- a/playground/src/views/examples/form/custom-layout.vue
+++ /dev/null
@@ -1,111 +0,0 @@
-
-
-
-
-
-
-
使用tailwind自定义表单项的布局,使用Divider分割表单。
-
-
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/examples/form/custom.vue b/playground/src/views/examples/form/custom.vue
deleted file mode 100644
index b9a9f654..00000000
--- a/playground/src/views/examples/form/custom.vue
+++ /dev/null
@@ -1,100 +0,0 @@
-
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/examples/form/dynamic.vue b/playground/src/views/examples/form/dynamic.vue
deleted file mode 100644
index b7bd770d..00000000
--- a/playground/src/views/examples/form/dynamic.vue
+++ /dev/null
@@ -1,262 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/examples/form/merge.vue b/playground/src/views/examples/form/merge.vue
deleted file mode 100644
index c4a78fa1..00000000
--- a/playground/src/views/examples/form/merge.vue
+++ /dev/null
@@ -1,116 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/examples/form/modules/two-fields.vue b/playground/src/views/examples/form/modules/two-fields.vue
deleted file mode 100644
index 05de8441..00000000
--- a/playground/src/views/examples/form/modules/two-fields.vue
+++ /dev/null
@@ -1,42 +0,0 @@
-
-
-
-
-
-
-
diff --git a/playground/src/views/examples/form/query.vue b/playground/src/views/examples/form/query.vue
deleted file mode 100644
index d3401d0b..00000000
--- a/playground/src/views/examples/form/query.vue
+++ /dev/null
@@ -1,276 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/examples/form/rules.vue b/playground/src/views/examples/form/rules.vue
deleted file mode 100644
index f5143261..00000000
--- a/playground/src/views/examples/form/rules.vue
+++ /dev/null
@@ -1,245 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/examples/form/scroll-to-error-test.vue b/playground/src/views/examples/form/scroll-to-error-test.vue
deleted file mode 100644
index a2edf94a..00000000
--- a/playground/src/views/examples/form/scroll-to-error-test.vue
+++ /dev/null
@@ -1,180 +0,0 @@
-
-
-
-
-
-
-
-
- 启用滚动到错误字段
-
-
-
-
-
-
测试说明:
-
- - 所有验证方法在验证失败时都会自动滚动到第一个错误字段
- - 可以通过右上角的开关控制是否启用自动滚动功能
-
-
-
-
-
验证方法测试:
-
-
-
-
-
-
-
• validateAndSubmitForm(): 验证表单并提交
-
• validate(): 手动验证整个表单
-
• validateField(): 验证单个字段(这里测试用户名字段)
-
-
-
-
-
数据填充测试:
-
-
-
-
-
-
• 填充部分数据后验证,会滚动到第一个错误字段
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/examples/json-viewer/data.ts b/playground/src/views/examples/json-viewer/data.ts
deleted file mode 100644
index 2767e079..00000000
--- a/playground/src/views/examples/json-viewer/data.ts
+++ /dev/null
@@ -1,66 +0,0 @@
-export const json1 = {
- additionalInfo: {
- author: 'Your Name',
- debug: true,
- version: '1.3.10',
- versionCode: 132,
- },
- additionalNotes: 'This JSON is used for demonstration purposes',
- tools: [
- {
- description: 'Description of Tool 1',
- name: 'Tool 1',
- },
- {
- description: 'Description of Tool 2',
- name: 'Tool 2',
- },
- {
- description: 'Description of Tool 3',
- name: 'Tool 3',
- },
- {
- description: 'Description of Tool 4',
- name: 'Tool 4',
- },
- ],
-};
-
-export const json2 = JSON.parse(`
- {
- "id": "chatcmpl-123",
- "object": "chat.completion",
- "created": 1677652288,
- "model": "gpt-3.5-turbo-0613",
- "system_fingerprint": "fp_44709d6fcb",
- "choices": [{
- "index": 0,
- "message": {
- "role": "assistant",
- "content": "Hello there, how may I assist you today?"
- },
- "finish_reason": "stop"
- }],
- "usage": {
- "prompt_tokens": 9,
- "completion_tokens": 12,
- "total_tokens": 21,
- "debug_mode": true
- },
- "debug": {
- "startAt": "2021-08-01T00:00:00Z",
- "logs": [
- {
- "timestamp": "2021-08-01T00:00:00Z",
- "message": "This is a debug message",
- "extra":[ "extra1", "extra2" ]
- },
- {
- "timestamp": "2021-08-01T00:00:01Z",
- "message": "This is another debug message",
- "extra":[ "extra3", "extra4" ]
- }
- ]
- }
-}
- `);
diff --git a/playground/src/views/examples/json-viewer/index.vue b/playground/src/views/examples/json-viewer/index.vue
deleted file mode 100644
index c38712f2..00000000
--- a/playground/src/views/examples/json-viewer/index.vue
+++ /dev/null
@@ -1,51 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/examples/layout/col-page.vue b/playground/src/views/examples/layout/col-page.vue
deleted file mode 100644
index 8a6f7724..00000000
--- a/playground/src/views/examples/layout/col-page.vue
+++ /dev/null
@@ -1,108 +0,0 @@
-
-
-
-
- ColPage 双列布局组件
- Alpha
-
-
-
-
-
-
-
-
-
这里是左侧内容
-
这里是左侧内容
-
这里是左侧内容
-
这里是左侧内容
-
这里是左侧内容
-
-
-
-
-
- 可拖动调整宽度
- 显示拖动分隔线
- 显示拖动手柄
- 左侧可折叠
-
-
- 左侧最小宽度百分比:
- (props.leftMinWidth = value as number)"
- />
- 左侧最大宽度百分比:
- (props.leftMaxWidth = value as number)"
- />
-
-
-
-
- 双列布局组件是一个在Page组件上扩展的相对基础的布局组件,支持左侧折叠(当拖拽导致左侧宽度比最小宽度还要小时,还可以进入折叠状态)、拖拽调整宽度等功能。
-
- 以上宽度设置的数值是百分比,最小值为1,最大值为100。
-
- 这是一个实验性的组件,用法可能会发生变动,也可能最终不会被采用。在其用法正式出现在文档中之前,不建议在生产环境中使用。
-
-
-
-
-
-
-
diff --git a/playground/src/views/examples/loading/index.vue b/playground/src/views/examples/loading/index.vue
deleted file mode 100644
index 19bb7d6b..00000000
--- a/playground/src/views/examples/loading/index.vue
+++ /dev/null
@@ -1,101 +0,0 @@
-
-
-
-
- 这是Antd 组件库自带的Spin组件演示
-
-
-
-
-
-
-
-
-
-
- Loading组件可以设置文字,并且也提供了icon插槽用于替换加载图标。
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Spinner组件是Loading组件的一个特例,只有一个固定的统一样式。
-
-
-
-
-
-
-
diff --git a/playground/src/views/examples/modal/auto-height-demo.vue b/playground/src/views/examples/modal/auto-height-demo.vue
deleted file mode 100644
index 58c67124..00000000
--- a/playground/src/views/examples/modal/auto-height-demo.vue
+++ /dev/null
@@ -1,49 +0,0 @@
-
-
-
-
-
- {{ item }}
-
-
-
-
-
-
diff --git a/playground/src/views/examples/modal/base-demo.vue b/playground/src/views/examples/modal/base-demo.vue
deleted file mode 100644
index cda4c966..00000000
--- a/playground/src/views/examples/modal/base-demo.vue
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
- base demo
-
-
-
diff --git a/playground/src/views/examples/modal/blur-demo.vue b/playground/src/views/examples/modal/blur-demo.vue
deleted file mode 100644
index 23b071b2..00000000
--- a/playground/src/views/examples/modal/blur-demo.vue
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
- 调整滑块来改变遮罩层模糊程度:{{ blur }}
-
-
-
diff --git a/playground/src/views/examples/modal/drag-demo.vue b/playground/src/views/examples/modal/drag-demo.vue
deleted file mode 100644
index 82c0e5a0..00000000
--- a/playground/src/views/examples/modal/drag-demo.vue
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
- 鼠标移动到 header 上,可拖拽弹窗
-
diff --git a/playground/src/views/examples/modal/dynamic-demo.vue b/playground/src/views/examples/modal/dynamic-demo.vue
deleted file mode 100644
index 1977b3e9..00000000
--- a/playground/src/views/examples/modal/dynamic-demo.vue
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/examples/modal/form-modal-demo.vue b/playground/src/views/examples/modal/form-modal-demo.vue
deleted file mode 100644
index 8e15bbb2..00000000
--- a/playground/src/views/examples/modal/form-modal-demo.vue
+++ /dev/null
@@ -1,91 +0,0 @@
-
-
-
-
-
-
diff --git a/playground/src/views/examples/modal/in-content-demo.vue b/playground/src/views/examples/modal/in-content-demo.vue
deleted file mode 100644
index 972424a8..00000000
--- a/playground/src/views/examples/modal/in-content-demo.vue
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
- 此弹窗指定在内容区域打开,并且在关闭之后弹窗内容不会被销毁
-
-
-
diff --git a/playground/src/views/examples/modal/index.vue b/playground/src/views/examples/modal/index.vue
deleted file mode 100644
index 90bb10fe..00000000
--- a/playground/src/views/examples/modal/index.vue
+++ /dev/null
@@ -1,278 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 一个基础的弹窗示例
-
-
-
-
-
-
- 在内容区域打开弹窗的示例
-
-
-
-
-
-
- 可根据内容并自动调整高度
-
-
-
-
-
-
- 配置 draggable 可开启拖拽功能
-
-
-
-
-
-
- 通过 setState 动态调整弹窗数据
-
-
-
-
-
-
-
-
-
- 通过共享 sharedData 来进行数据交互
-
-
-
-
-
-
- 弹窗与表单结合
-
-
-
-
-
-
- 在已经打开的弹窗中再次打开弹窗
-
-
-
-
-
-
- 遮罩层应用类似毛玻璃的模糊效果
-
-
-
-
-
-
-
-
- 通过快捷方法创建动态提示弹窗,适合一些轻量的提示和确认、输入等
-
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/examples/modal/nested-demo.vue b/playground/src/views/examples/modal/nested-demo.vue
deleted file mode 100644
index a7384d78..00000000
--- a/playground/src/views/examples/modal/nested-demo.vue
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
-
-
-
-
diff --git a/playground/src/views/examples/modal/shared-data-demo.vue b/playground/src/views/examples/modal/shared-data-demo.vue
deleted file mode 100644
index 57b14b61..00000000
--- a/playground/src/views/examples/modal/shared-data-demo.vue
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
- 外部传递数据: {{ data }}
-
-
diff --git a/playground/src/views/examples/motion/index.vue b/playground/src/views/examples/motion/index.vue
deleted file mode 100644
index a371e5f6..00000000
--- a/playground/src/views/examples/motion/index.vue
+++ /dev/null
@@ -1,213 +0,0 @@
-
-
-
-
- 一个易于使用的为其它组件赋予动画效果的组件。
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 附属组件,会作为整体处理动画
-
-
-
-
- 顺序延迟
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/examples/resize/basic.vue b/playground/src/views/examples/resize/basic.vue
deleted file mode 100644
index 6295839a..00000000
--- a/playground/src/views/examples/resize/basic.vue
+++ /dev/null
@@ -1,58 +0,0 @@
-
-
-
-
-
-
- {{
- `width: ${size.width}px, height: ${size.height}px, top: ${size.top}px, left: ${size.left}px`
- }}
-
-
-
-
- resize(sizeList[idx], rect)"
- @resizing="(rect) => resize(sizeList[idx], rect)"
- >
-
-
-
-
-
diff --git a/playground/src/views/examples/tippy/index.vue b/playground/src/views/examples/tippy/index.vue
deleted file mode 100644
index 232e8cc3..00000000
--- a/playground/src/views/examples/tippy/index.vue
+++ /dev/null
@@ -1,303 +0,0 @@
-
-
-
-
-
-
- Tippy
- 是一个轻量级的提示工具库,它可以用来创建各种交互式提示,如工具提示、引导提示等。
-
-
-
-
-
-
- 指令形式使用比较简洁,直接在需要展示tooltip的组件上用v-tippy传递配置,适用于固定内容的工具提示。
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 更多配置请
-
- ,这里只列出了一些常用的配置
-
-
-
-
-
diff --git a/playground/src/views/examples/vxe-table/basic.vue b/playground/src/views/examples/vxe-table/basic.vue
deleted file mode 100644
index 3f9630ec..00000000
--- a/playground/src/views/examples/vxe-table/basic.vue
+++ /dev/null
@@ -1,112 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/examples/vxe-table/custom-cell.vue b/playground/src/views/examples/vxe-table/custom-cell.vue
deleted file mode 100644
index 95b015a9..00000000
--- a/playground/src/views/examples/vxe-table/custom-cell.vue
+++ /dev/null
@@ -1,108 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
- {{ row.status }}
-
-
-
-
-
-
-
diff --git a/playground/src/views/examples/vxe-table/edit-cell.vue b/playground/src/views/examples/vxe-table/edit-cell.vue
deleted file mode 100644
index 9aebde86..00000000
--- a/playground/src/views/examples/vxe-table/edit-cell.vue
+++ /dev/null
@@ -1,57 +0,0 @@
-
-
-
-
-
-
-
diff --git a/playground/src/views/examples/vxe-table/edit-row.vue b/playground/src/views/examples/vxe-table/edit-row.vue
deleted file mode 100644
index 31ebadf9..00000000
--- a/playground/src/views/examples/vxe-table/edit-row.vue
+++ /dev/null
@@ -1,94 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/examples/vxe-table/fixed.vue b/playground/src/views/examples/vxe-table/fixed.vue
deleted file mode 100644
index a9791323..00000000
--- a/playground/src/views/examples/vxe-table/fixed.vue
+++ /dev/null
@@ -1,69 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/examples/vxe-table/form.vue b/playground/src/views/examples/vxe-table/form.vue
deleted file mode 100644
index ec9e4b52..00000000
--- a/playground/src/views/examples/vxe-table/form.vue
+++ /dev/null
@@ -1,127 +0,0 @@
-
-
-
-
-
-
-
diff --git a/playground/src/views/examples/vxe-table/remote.vue b/playground/src/views/examples/vxe-table/remote.vue
deleted file mode 100644
index de2faf85..00000000
--- a/playground/src/views/examples/vxe-table/remote.vue
+++ /dev/null
@@ -1,81 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/examples/vxe-table/table-data.ts b/playground/src/views/examples/vxe-table/table-data.ts
deleted file mode 100644
index b4eb5ede..00000000
--- a/playground/src/views/examples/vxe-table/table-data.ts
+++ /dev/null
@@ -1,172 +0,0 @@
-interface TableRowData {
- address: string;
- age: number;
- id: number;
- name: string;
- nickname: string;
- role: string;
-}
-
-const roles = ['User', 'Admin', 'Manager', 'Guest'];
-
-export const MOCK_TABLE_DATA: TableRowData[] = (() => {
- const data: TableRowData[] = [];
- for (let i = 0; i < 40; i++) {
- data.push({
- address: `New York${i}`,
- age: i + 1,
- id: i,
- name: `Test${i}`,
- nickname: `Test${i}`,
- role: roles[Math.floor(Math.random() * roles.length)] as string,
- });
- }
- return data;
-})();
-
-export const MOCK_TREE_TABLE_DATA = [
- {
- date: '2020-08-01',
- id: 10_000,
- name: 'Test1',
- parentId: null,
- size: 1024,
- type: 'mp3',
- },
- {
- date: '2021-04-01',
- id: 10_050,
- name: 'Test2',
- parentId: null,
- size: 0,
- type: 'mp4',
- },
- {
- date: '2020-03-01',
- id: 24_300,
- name: 'Test3',
- parentId: 10_050,
- size: 1024,
- type: 'avi',
- },
- {
- date: '2021-04-01',
- id: 20_045,
- name: 'Test4',
- parentId: 24_300,
- size: 600,
- type: 'html',
- },
- {
- date: '2021-04-01',
- id: 10_053,
- name: 'Test5',
- parentId: 24_300,
- size: 0,
- type: 'avi',
- },
- {
- date: '2021-10-01',
- id: 24_330,
- name: 'Test6',
- parentId: 10_053,
- size: 25,
- type: 'txt',
- },
- {
- date: '2020-01-01',
- id: 21_011,
- name: 'Test7',
- parentId: 10_053,
- size: 512,
- type: 'pdf',
- },
- {
- date: '2021-06-01',
- id: 22_200,
- name: 'Test8',
- parentId: 10_053,
- size: 1024,
- type: 'js',
- },
- {
- date: '2020-11-01',
- id: 23_666,
- name: 'Test9',
- parentId: null,
- size: 2048,
- type: 'xlsx',
- },
- {
- date: '2021-06-01',
- id: 23_677,
- name: 'Test10',
- parentId: 23_666,
- size: 1024,
- type: 'js',
- },
- {
- date: '2021-06-01',
- id: 23_671,
- name: 'Test11',
- parentId: 23_677,
- size: 1024,
- type: 'js',
- },
- {
- date: '2021-06-01',
- id: 23_672,
- name: 'Test12',
- parentId: 23_677,
- size: 1024,
- type: 'js',
- },
- {
- date: '2021-06-01',
- id: 23_688,
- name: 'Test13',
- parentId: 23_666,
- size: 1024,
- type: 'js',
- },
- {
- date: '2021-06-01',
- id: 23_681,
- name: 'Test14',
- parentId: 23_688,
- size: 1024,
- type: 'js',
- },
- {
- date: '2021-06-01',
- id: 23_682,
- name: 'Test15',
- parentId: 23_688,
- size: 1024,
- type: 'js',
- },
- {
- date: '2020-10-01',
- id: 24_555,
- name: 'Test16',
- parentId: null,
- size: 224,
- type: 'avi',
- },
- {
- date: '2021-06-01',
- id: 24_566,
- name: 'Test17',
- parentId: 24_555,
- size: 1024,
- type: 'js',
- },
- {
- date: '2021-06-01',
- id: 24_577,
- name: 'Test18',
- parentId: 24_555,
- size: 1024,
- type: 'js',
- },
-];
diff --git a/playground/src/views/examples/vxe-table/tree.vue b/playground/src/views/examples/vxe-table/tree.vue
deleted file mode 100644
index 1a28dee0..00000000
--- a/playground/src/views/examples/vxe-table/tree.vue
+++ /dev/null
@@ -1,62 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/examples/vxe-table/virtual.vue b/playground/src/views/examples/vxe-table/virtual.vue
deleted file mode 100644
index f35a691b..00000000
--- a/playground/src/views/examples/vxe-table/virtual.vue
+++ /dev/null
@@ -1,66 +0,0 @@
-
-
-
-
-
-
-
diff --git a/playground/src/views/system/dept/data.ts b/playground/src/views/system/dept/data.ts
deleted file mode 100644
index 64ec56be..00000000
--- a/playground/src/views/system/dept/data.ts
+++ /dev/null
@@ -1,136 +0,0 @@
-import type { VxeTableGridOptions } from '@vben/plugins/vxe-table';
-
-import type { VbenFormSchema } from '#/adapter/form';
-import type { OnActionClickFn } from '#/adapter/vxe-table';
-import type { SystemDeptApi } from '#/api/system/dept';
-
-import { z } from '#/adapter/form';
-import { getDeptList } from '#/api/system/dept';
-import { $t } from '#/locales';
-
-/**
- * 获取编辑表单的字段配置。如果没有使用多语言,可以直接export一个数组常量
- */
-export function useSchema(): VbenFormSchema[] {
- return [
- {
- component: 'Input',
- fieldName: 'name',
- label: $t('system.dept.deptName'),
- rules: z
- .string()
- .min(2, $t('ui.formRules.minLength', [$t('system.dept.deptName'), 2]))
- .max(
- 20,
- $t('ui.formRules.maxLength', [$t('system.dept.deptName'), 20]),
- ),
- },
- {
- component: 'ApiTreeSelect',
- componentProps: {
- allowClear: true,
- api: getDeptList,
- class: 'w-full',
- labelField: 'name',
- valueField: 'id',
- childrenField: 'children',
- },
- fieldName: 'pid',
- label: $t('system.dept.parentDept'),
- },
- {
- component: 'RadioGroup',
- componentProps: {
- buttonStyle: 'solid',
- options: [
- { label: $t('common.enabled'), value: 1 },
- { label: $t('common.disabled'), value: 0 },
- ],
- optionType: 'button',
- },
- defaultValue: 1,
- fieldName: 'status',
- label: $t('system.dept.status'),
- },
- {
- component: 'Textarea',
- componentProps: {
- maxLength: 50,
- rows: 3,
- showCount: true,
- },
- fieldName: 'remark',
- label: $t('system.dept.remark'),
- rules: z
- .string()
- .max(50, $t('ui.formRules.maxLength', [$t('system.dept.remark'), 50]))
- .optional(),
- },
- ];
-}
-
-/**
- * 获取表格列配置
- * @description 使用函数的形式返回列数据而不是直接export一个Array常量,是为了响应语言切换时重新翻译表头
- * @param onActionClick 表格操作按钮点击事件
- */
-export function useColumns(
- onActionClick?: OnActionClickFn,
-): VxeTableGridOptions['columns'] {
- return [
- {
- align: 'left',
- field: 'name',
- fixed: 'left',
- title: $t('system.dept.deptName'),
- treeNode: true,
- width: 150,
- },
- {
- cellRender: { name: 'CellTag' },
- field: 'status',
- title: $t('system.dept.status'),
- width: 100,
- },
- {
- field: 'createTime',
- resizable: false,
- title: $t('system.dept.createTime'),
- width: 'auto',
- },
- {
- field: 'remark',
- title: $t('system.dept.remark'),
- },
- {
- align: 'right',
- cellRender: {
- attrs: {
- nameField: 'name',
- nameTitle: $t('system.dept.name'),
- onClick: onActionClick,
- },
- name: 'CellOperation',
- options: [
- {
- code: 'append',
- text: '新增下级',
- },
- 'edit', // 默认的编辑按钮
- {
- code: 'delete', // 默认的删除按钮
- disabled: (row: SystemDeptApi.SystemDept) => {
- return !!(row.children && row.children.length > 0);
- },
- },
- ],
- },
- field: 'operation',
- fixed: 'right',
- headerAlign: 'center',
- showOverflow: false,
- title: $t('system.dept.operation'),
- width: 200,
- },
- ];
-}
diff --git a/playground/src/views/system/dept/list.vue b/playground/src/views/system/dept/list.vue
deleted file mode 100644
index f98099d5..00000000
--- a/playground/src/views/system/dept/list.vue
+++ /dev/null
@@ -1,143 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/system/dept/modules/form.vue b/playground/src/views/system/dept/modules/form.vue
deleted file mode 100644
index 1f91d999..00000000
--- a/playground/src/views/system/dept/modules/form.vue
+++ /dev/null
@@ -1,78 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/system/menu/data.ts b/playground/src/views/system/menu/data.ts
deleted file mode 100644
index 75190b4a..00000000
--- a/playground/src/views/system/menu/data.ts
+++ /dev/null
@@ -1,109 +0,0 @@
-import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table';
-import type { SystemMenuApi } from '#/api/system/menu';
-
-import { $t } from '#/locales';
-
-export function getMenuTypeOptions() {
- return [
- {
- color: 'processing',
- label: $t('system.menu.typeCatalog'),
- value: 'catalog',
- },
- { color: 'default', label: $t('system.menu.typeMenu'), value: 'menu' },
- { color: 'error', label: $t('system.menu.typeButton'), value: 'button' },
- {
- color: 'success',
- label: $t('system.menu.typeEmbedded'),
- value: 'embedded',
- },
- { color: 'warning', label: $t('system.menu.typeLink'), value: 'link' },
- ];
-}
-
-export function useColumns(
- onActionClick: OnActionClickFn,
-): VxeTableGridOptions['columns'] {
- return [
- {
- align: 'left',
- field: 'meta.title',
- fixed: 'left',
- slots: { default: 'title' },
- title: $t('system.menu.menuTitle'),
- treeNode: true,
- width: 250,
- },
- {
- align: 'center',
- cellRender: { name: 'CellTag', options: getMenuTypeOptions() },
- field: 'type',
- title: $t('system.menu.type'),
- width: 100,
- },
- {
- field: 'authCode',
- title: $t('system.menu.authCode'),
- width: 200,
- },
- {
- align: 'left',
- field: 'path',
- title: $t('system.menu.path'),
- width: 200,
- },
-
- {
- align: 'left',
- field: 'component',
- formatter: ({ row }) => {
- switch (row.type) {
- case 'catalog':
- case 'menu': {
- return row.component ?? '';
- }
- case 'embedded': {
- return row.meta?.iframeSrc ?? '';
- }
- case 'link': {
- return row.meta?.link ?? '';
- }
- }
- return '';
- },
- minWidth: 200,
- title: $t('system.menu.component'),
- },
- {
- cellRender: { name: 'CellTag' },
- field: 'status',
- title: $t('system.menu.status'),
- width: 100,
- },
-
- {
- align: 'right',
- cellRender: {
- attrs: {
- nameField: 'name',
- onClick: onActionClick,
- },
- name: 'CellOperation',
- options: [
- {
- code: 'append',
- text: '新增下级',
- },
- 'edit', // 默认的编辑按钮
- 'delete', // 默认的删除按钮
- ],
- },
- field: 'operation',
- fixed: 'right',
- headerAlign: 'center',
- showOverflow: false,
- title: $t('system.menu.operation'),
- width: 200,
- },
- ];
-}
diff --git a/playground/src/views/system/menu/list.vue b/playground/src/views/system/menu/list.vue
deleted file mode 100644
index 74f2f698..00000000
--- a/playground/src/views/system/menu/list.vue
+++ /dev/null
@@ -1,162 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
{{ $t(row.meta?.title) }}
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/system/menu/modules/form.vue b/playground/src/views/system/menu/modules/form.vue
deleted file mode 100644
index ceabfba1..00000000
--- a/playground/src/views/system/menu/modules/form.vue
+++ /dev/null
@@ -1,504 +0,0 @@
-
-
-
-
-
-
diff --git a/playground/src/views/system/role/data.ts b/playground/src/views/system/role/data.ts
deleted file mode 100644
index 255b6cc7..00000000
--- a/playground/src/views/system/role/data.ts
+++ /dev/null
@@ -1,127 +0,0 @@
-import type { VbenFormSchema } from '#/adapter/form';
-import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table';
-import type { SystemRoleApi } from '#/api';
-
-import { $t } from '#/locales';
-
-export function useFormSchema(): VbenFormSchema[] {
- return [
- {
- component: 'Input',
- fieldName: 'name',
- label: $t('system.role.roleName'),
- rules: 'required',
- },
- {
- component: 'RadioGroup',
- componentProps: {
- buttonStyle: 'solid',
- options: [
- { label: $t('common.enabled'), value: 1 },
- { label: $t('common.disabled'), value: 0 },
- ],
- optionType: 'button',
- },
- defaultValue: 1,
- fieldName: 'status',
- label: $t('system.role.status'),
- },
- {
- component: 'Textarea',
- fieldName: 'remark',
- label: $t('system.role.remark'),
- },
- {
- component: 'Input',
- fieldName: 'permissions',
- formItemClass: 'items-start',
- label: $t('system.role.setPermissions'),
- modelPropName: 'modelValue',
- },
- ];
-}
-
-export function useGridFormSchema(): VbenFormSchema[] {
- return [
- {
- component: 'Input',
- fieldName: 'name',
- label: $t('system.role.roleName'),
- },
- { component: 'Input', fieldName: 'id', label: $t('system.role.id') },
- {
- component: 'Select',
- componentProps: {
- allowClear: true,
- options: [
- { label: $t('common.enabled'), value: 1 },
- { label: $t('common.disabled'), value: 0 },
- ],
- },
- fieldName: 'status',
- label: $t('system.role.status'),
- },
- {
- component: 'Input',
- fieldName: 'remark',
- label: $t('system.role.remark'),
- },
- {
- component: 'RangePicker',
- fieldName: 'createTime',
- label: $t('system.role.createTime'),
- },
- ];
-}
-
-export function useColumns(
- onActionClick: OnActionClickFn,
- onStatusChange?: (newStatus: any, row: T) => PromiseLike,
-): VxeTableGridOptions['columns'] {
- return [
- {
- field: 'name',
- title: $t('system.role.roleName'),
- width: 200,
- },
- {
- field: 'id',
- title: $t('system.role.id'),
- width: 200,
- },
- {
- cellRender: {
- attrs: { beforeChange: onStatusChange },
- name: onStatusChange ? 'CellSwitch' : 'CellTag',
- },
- field: 'status',
- title: $t('system.role.status'),
- width: 100,
- },
- {
- field: 'remark',
- minWidth: 100,
- title: $t('system.role.remark'),
- },
- {
- field: 'createTime',
- title: $t('system.role.createTime'),
- width: 200,
- },
- {
- align: 'center',
- cellRender: {
- attrs: {
- nameField: 'name',
- nameTitle: $t('system.role.name'),
- onClick: onActionClick,
- },
- name: 'CellOperation',
- },
- field: 'operation',
- fixed: 'right',
- title: $t('system.role.operation'),
- width: 130,
- },
- ];
-}
diff --git a/playground/src/views/system/role/list.vue b/playground/src/views/system/role/list.vue
deleted file mode 100644
index 499d67e6..00000000
--- a/playground/src/views/system/role/list.vue
+++ /dev/null
@@ -1,164 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
diff --git a/playground/src/views/system/role/modules/form.vue b/playground/src/views/system/role/modules/form.vue
deleted file mode 100644
index 6b5d14f7..00000000
--- a/playground/src/views/system/role/modules/form.vue
+++ /dev/null
@@ -1,142 +0,0 @@
-
-
-
-
-
-
-
diff --git a/playground/tailwind.config.mjs b/playground/tailwind.config.mjs
deleted file mode 100644
index f17f556f..00000000
--- a/playground/tailwind.config.mjs
+++ /dev/null
@@ -1 +0,0 @@
-export { default } from '@vben/tailwind-config';
diff --git a/playground/tsconfig.json b/playground/tsconfig.json
deleted file mode 100644
index 02c287fe..00000000
--- a/playground/tsconfig.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "$schema": "https://json.schemastore.org/tsconfig",
- "extends": "@vben/tsconfig/web-app.json",
- "compilerOptions": {
- "baseUrl": ".",
- "paths": {
- "#/*": ["./src/*"]
- }
- },
- "references": [{ "path": "./tsconfig.node.json" }],
- "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"]
-}
diff --git a/playground/tsconfig.node.json b/playground/tsconfig.node.json
deleted file mode 100644
index c2f0d86c..00000000
--- a/playground/tsconfig.node.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "$schema": "https://json.schemastore.org/tsconfig",
- "extends": "@vben/tsconfig/node.json",
- "compilerOptions": {
- "composite": true,
- "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
- "noEmit": false
- },
- "include": ["vite.config.mts"]
-}
diff --git a/playground/vite.config.mts b/playground/vite.config.mts
deleted file mode 100644
index b6360f1d..00000000
--- a/playground/vite.config.mts
+++ /dev/null
@@ -1,20 +0,0 @@
-import { defineConfig } from '@vben/vite-config';
-
-export default defineConfig(async () => {
- return {
- application: {},
- vite: {
- server: {
- proxy: {
- '/api': {
- changeOrigin: true,
- rewrite: (path) => path.replace(/^\/api/, ''),
- // mock代理目标地址
- target: 'http://localhost:5320/api',
- ws: true,
- },
- },
- },
- },
- };
-});
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
index 895b96e4..4bc09821 100644
--- a/pnpm-workspace.yaml
+++ b/pnpm-workspace.yaml
@@ -11,7 +11,6 @@ packages:
- apps/*
- scripts/*
- docs
- - playground
overrides:
'@ast-grep/napi': 'catalog:'
diff --git a/vben-admin.code-workspace b/vben-admin.code-workspace
index 5ad3c40a..999641b0 100644
--- a/vben-admin.code-workspace
+++ b/vben-admin.code-workspace
@@ -148,10 +148,6 @@
"name": "@vben/utils",
"path": "packages/utils",
},
- {
- "name": "@vben/playground",
- "path": "playground",
- },
{
"name": "@vben/turbo-run",
"path": "scripts/turbo-run",