From 642899b920c7e364bff3764e7eaedcde7b4dfca4 Mon Sep 17 00:00:00 2001 From: "cnb.aUOqoEV4wEA" Date: Wed, 12 Nov 2025 11:53:38 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=8E=BB=E9=99=A4=E6=97=A0=E7=94=A8?= =?UTF-8?q?=E5=AD=90=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/backend-mock/.env | 3 - apps/backend-mock/README.md | 15 - apps/backend-mock/api/auth/codes.ts | 16 - apps/backend-mock/api/auth/login.post.ts | 42 -- apps/backend-mock/api/auth/logout.post.ts | 17 - apps/backend-mock/api/auth/refresh.post.ts | 35 -- apps/backend-mock/api/demo/bigint.ts | 32 - apps/backend-mock/api/menu/all.ts | 15 - apps/backend-mock/api/status.ts | 8 - apps/backend-mock/api/system/dept/.post.ts | 16 - .../api/system/dept/[id].delete.ts | 16 - apps/backend-mock/api/system/dept/[id].put.ts | 16 - apps/backend-mock/api/system/dept/list.ts | 62 -- apps/backend-mock/api/system/menu/list.ts | 13 - .../api/system/menu/name-exists.ts | 29 - .../api/system/menu/path-exists.ts | 29 - apps/backend-mock/api/system/role/list.ts | 84 --- apps/backend-mock/api/table/list.ts | 117 ---- apps/backend-mock/api/test.get.ts | 3 - apps/backend-mock/api/test.post.ts | 3 - apps/backend-mock/api/timezone/getTimezone.ts | 12 - .../api/timezone/getTimezoneOptions.ts | 11 - apps/backend-mock/api/timezone/setTimezone.ts | 22 - apps/backend-mock/api/upload.ts | 14 - apps/backend-mock/api/user/info.ts | 11 - apps/backend-mock/error.ts | 7 - apps/backend-mock/middleware/1.api.ts | 20 - apps/backend-mock/nitro.config.ts | 20 - apps/backend-mock/package.json | 21 - apps/backend-mock/routes/[...].ts | 15 - apps/backend-mock/tsconfig.build.json | 4 - apps/backend-mock/tsconfig.json | 3 - apps/backend-mock/utils/cookie-utils.ts | 28 - apps/backend-mock/utils/jwt-utils.ts | 77 --- apps/backend-mock/utils/mock-data.ts | 421 ------------- apps/backend-mock/utils/response.ts | 70 --- apps/backend-mock/utils/timezone-utils.ts | 9 - apps/web-antd/.env | 8 - apps/web-antd/.env.analyze | 7 - apps/web-antd/.env.development | 16 - apps/web-antd/.env.production | 19 - apps/web-antd/index.html | 35 -- apps/web-antd/package.json | 50 -- apps/web-antd/postcss.config.mjs | 1 - apps/web-antd/public/favicon.ico | Bin 5430 -> 0 bytes apps/web-antd/src/adapter/component/index.ts | 211 ------- apps/web-antd/src/adapter/form.ts | 49 -- apps/web-antd/src/adapter/vxe-table.ts | 69 -- apps/web-antd/src/api/core/auth.ts | 51 -- apps/web-antd/src/api/core/index.ts | 3 - apps/web-antd/src/api/core/menu.ts | 10 - apps/web-antd/src/api/core/user.ts | 10 - apps/web-antd/src/api/index.ts | 1 - apps/web-antd/src/api/request.ts | 113 ---- apps/web-antd/src/app.vue | 39 -- apps/web-antd/src/bootstrap.ts | 76 --- apps/web-antd/src/layouts/auth.vue | 25 - apps/web-antd/src/layouts/basic.vue | 162 ----- apps/web-antd/src/layouts/index.ts | 6 - apps/web-antd/src/locales/README.md | 3 - apps/web-antd/src/locales/index.ts | 102 --- .../src/locales/langs/en-US/demos.json | 13 - .../src/locales/langs/en-US/page.json | 14 - .../src/locales/langs/zh-CN/demos.json | 13 - .../src/locales/langs/zh-CN/page.json | 14 - apps/web-antd/src/main.ts | 31 - apps/web-antd/src/preferences.ts | 13 - apps/web-antd/src/router/access.ts | 42 -- apps/web-antd/src/router/guard.ts | 133 ---- apps/web-antd/src/router/index.ts | 37 -- apps/web-antd/src/router/routes/core.ts | 97 --- apps/web-antd/src/router/routes/index.ts | 37 -- .../src/router/routes/modules/dashboard.ts | 38 -- .../src/router/routes/modules/demos.ts | 28 - .../src/router/routes/modules/vben.ts | 94 --- apps/web-antd/src/store/auth.ts | 118 ---- apps/web-antd/src/store/index.ts | 1 - apps/web-antd/src/views/_core/README.md | 3 - apps/web-antd/src/views/_core/about/index.vue | 9 - .../views/_core/authentication/code-login.vue | 69 -- .../_core/authentication/forget-password.vue | 43 -- .../src/views/_core/authentication/login.vue | 98 --- .../_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 - .../dashboard/analytics/analytics-trends.vue | 98 --- .../analytics/analytics-visits-data.vue | 82 --- .../analytics/analytics-visits-sales.vue | 46 -- .../analytics/analytics-visits-source.vue | 65 -- .../dashboard/analytics/analytics-visits.vue | 55 -- .../src/views/dashboard/analytics/index.vue | 90 --- .../src/views/dashboard/workspace/index.vue | 266 -------- apps/web-antd/src/views/demos/antd/index.vue | 66 -- apps/web-antd/tailwind.config.mjs | 1 - apps/web-antd/tsconfig.json | 12 - apps/web-antd/tsconfig.node.json | 10 - apps/web-antd/vite.config.mts | 20 - apps/web-ele/.env | 8 - apps/web-ele/.env.analyze | 7 - apps/web-ele/.env.development | 16 - apps/web-ele/.env.production | 19 - apps/web-ele/index.html | 35 -- apps/web-ele/package.json | 53 -- apps/web-ele/postcss.config.mjs | 1 - apps/web-ele/public/favicon.ico | Bin 5430 -> 0 bytes apps/web-ele/src/adapter/component/index.ts | 331 ---------- apps/web-ele/src/adapter/form.ts | 41 -- apps/web-ele/src/adapter/vxe-table.ts | 70 --- apps/web-ele/src/api/core/auth.ts | 51 -- apps/web-ele/src/api/core/index.ts | 3 - apps/web-ele/src/api/core/menu.ts | 10 - apps/web-ele/src/api/core/user.ts | 10 - apps/web-ele/src/api/index.ts | 1 - apps/web-ele/src/api/request.ts | 113 ---- apps/web-ele/src/app.vue | 17 - apps/web-ele/src/bootstrap.ts | 79 --- apps/web-ele/src/layouts/auth.vue | 25 - apps/web-ele/src/layouts/basic.vue | 162 ----- apps/web-ele/src/layouts/index.ts | 6 - apps/web-ele/src/locales/README.md | 3 - apps/web-ele/src/locales/index.ts | 102 --- .../src/locales/langs/en-US/demos.json | 14 - .../web-ele/src/locales/langs/en-US/page.json | 14 - .../src/locales/langs/zh-CN/demos.json | 14 - .../web-ele/src/locales/langs/zh-CN/page.json | 14 - apps/web-ele/src/main.ts | 31 - apps/web-ele/src/preferences.ts | 13 - apps/web-ele/src/router/access.ts | 42 -- apps/web-ele/src/router/guard.ts | 133 ---- apps/web-ele/src/router/index.ts | 37 -- apps/web-ele/src/router/routes/core.ts | 97 --- apps/web-ele/src/router/routes/index.ts | 37 -- .../src/router/routes/modules/dashboard.ts | 38 -- .../src/router/routes/modules/demos.ts | 36 -- .../web-ele/src/router/routes/modules/vben.ts | 94 --- apps/web-ele/src/store/auth.ts | 119 ---- apps/web-ele/src/store/index.ts | 1 - apps/web-ele/src/views/_core/README.md | 3 - apps/web-ele/src/views/_core/about/index.vue | 9 - .../views/_core/authentication/code-login.vue | 69 -- .../_core/authentication/forget-password.vue | 43 -- .../src/views/_core/authentication/login.vue | 98 --- .../_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 - .../dashboard/analytics/analytics-trends.vue | 98 --- .../analytics/analytics-visits-data.vue | 82 --- .../analytics/analytics-visits-sales.vue | 46 -- .../analytics/analytics-visits-source.vue | 65 -- .../dashboard/analytics/analytics-visits.vue | 55 -- .../src/views/dashboard/analytics/index.vue | 90 --- .../src/views/dashboard/workspace/index.vue | 266 -------- .../web-ele/src/views/demos/element/index.vue | 117 ---- apps/web-ele/src/views/demos/form/basic.vue | 191 ------ apps/web-ele/tailwind.config.mjs | 1 - apps/web-ele/tsconfig.json | 12 - apps/web-ele/tsconfig.node.json | 10 - apps/web-ele/vite.config.mts | 27 - apps/web-naive/.env | 8 - apps/web-naive/.env.analyze | 7 - apps/web-naive/.env.development | 16 - apps/web-naive/.env.production | 19 - apps/web-naive/index.html | 35 -- apps/web-naive/package.json | 49 -- apps/web-naive/postcss.config.mjs | 1 - apps/web-naive/public/favicon.ico | Bin 5430 -> 0 bytes apps/web-naive/src/adapter/component/index.ts | 231 ------- apps/web-naive/src/adapter/form.ts | 45 -- apps/web-naive/src/adapter/naive.ts | 25 - apps/web-naive/src/adapter/vxe-table.ts | 69 -- apps/web-naive/src/api/core/auth.ts | 51 -- apps/web-naive/src/api/core/index.ts | 3 - apps/web-naive/src/api/core/menu.ts | 10 - apps/web-naive/src/api/core/user.ts | 10 - apps/web-naive/src/api/index.ts | 1 - apps/web-naive/src/api/request.ts | 112 ---- apps/web-naive/src/app.vue | 56 -- apps/web-naive/src/bootstrap.ts | 76 --- apps/web-naive/src/layouts/auth.vue | 25 - apps/web-naive/src/layouts/basic.vue | 163 ----- apps/web-naive/src/layouts/index.ts | 6 - apps/web-naive/src/locales/README.md | 3 - apps/web-naive/src/locales/index.ts | 38 -- .../src/locales/langs/en-US/demos.json | 15 - .../src/locales/langs/en-US/page.json | 14 - .../src/locales/langs/zh-CN/demos.json | 15 - .../src/locales/langs/zh-CN/page.json | 14 - apps/web-naive/src/main.ts | 31 - apps/web-naive/src/preferences.ts | 13 - apps/web-naive/src/router/access.ts | 40 -- apps/web-naive/src/router/guard.ts | 132 ---- apps/web-naive/src/router/index.ts | 37 -- apps/web-naive/src/router/routes/core.ts | 97 --- apps/web-naive/src/router/routes/index.ts | 37 -- .../src/router/routes/modules/dashboard.ts | 38 -- .../src/router/routes/modules/demos.ts | 44 -- .../src/router/routes/modules/vben.ts | 94 --- apps/web-naive/src/store/auth.ts | 119 ---- apps/web-naive/src/store/index.ts | 1 - apps/web-naive/src/views/_core/README.md | 3 - .../web-naive/src/views/_core/about/index.vue | 9 - .../views/_core/authentication/code-login.vue | 69 -- .../_core/authentication/forget-password.vue | 43 -- .../src/views/_core/authentication/login.vue | 98 --- .../_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 - .../dashboard/analytics/analytics-trends.vue | 98 --- .../analytics/analytics-visits-data.vue | 82 --- .../analytics/analytics-visits-sales.vue | 46 -- .../analytics/analytics-visits-source.vue | 65 -- .../dashboard/analytics/analytics-visits.vue | 55 -- .../src/views/dashboard/analytics/index.vue | 90 --- .../src/views/dashboard/workspace/index.vue | 266 -------- apps/web-naive/src/views/demos/form/basic.vue | 169 ----- apps/web-naive/src/views/demos/form/modal.vue | 71 --- .../web-naive/src/views/demos/naive/index.vue | 69 -- .../web-naive/src/views/demos/table/index.vue | 38 -- apps/web-naive/tailwind.config.mjs | 1 - apps/web-naive/tsconfig.json | 12 - apps/web-naive/tsconfig.node.json | 10 - apps/web-naive/vite.config.mts | 20 - package.json | 8 +- 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 | 59 -- playground/playwright.config.ts | 108 ---- playground/postcss.config.mjs | 1 - playground/public/favicon.ico | Bin 5430 -> 0 bytes playground/src/adapter/component/index.ts | 207 ------ playground/src/adapter/form.ts | 47 -- playground/src/adapter/vxe-table.ts | 297 --------- 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 | 188 ------ playground/src/layouts/index.ts | 6 - playground/src/locales/README.md | 3 - playground/src/locales/index.ts | 102 --- playground/src/locales/langs/en-US/demos.json | 71 --- .../src/locales/langs/en-US/examples.json | 76 --- playground/src/locales/langs/en-US/page.json | 16 - .../src/locales/langs/en-US/system.json | 65 -- playground/src/locales/langs/zh-CN/demos.json | 72 --- .../src/locales/langs/zh-CN/examples.json | 76 --- playground/src/locales/langs/zh-CN/page.json | 16 - .../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 | 594 ------------------ .../src/router/routes/modules/examples.ts | 335 ---------- .../src/router/routes/modules/system.ts | 46 -- playground/src/router/routes/modules/vben.ts | 106 ---- playground/src/store/auth.ts | 120 ---- 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 - .../dashboard/analytics/analytics-trends.vue | 98 --- .../analytics/analytics-visits-data.vue | 82 --- .../analytics/analytics-visits-sales.vue | 46 -- .../analytics/analytics-visits-source.vue | 65 -- .../dashboard/analytics/analytics-visits.vue | 55 -- .../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 | 157 ----- playground/src/views/demos/access/index.vue | 98 --- .../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 | 117 ---- .../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 | 53 -- .../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/count-to/index.vue | 178 ------ 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 | 447 ------------- .../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 | 111 ---- .../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 | 135 ---- 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 | 505 --------------- 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 - 417 files changed, 2 insertions(+), 24992 deletions(-) delete mode 100644 apps/backend-mock/.env delete mode 100644 apps/backend-mock/README.md delete mode 100644 apps/backend-mock/api/auth/codes.ts delete mode 100644 apps/backend-mock/api/auth/login.post.ts delete mode 100644 apps/backend-mock/api/auth/logout.post.ts delete mode 100644 apps/backend-mock/api/auth/refresh.post.ts delete mode 100644 apps/backend-mock/api/demo/bigint.ts delete mode 100644 apps/backend-mock/api/menu/all.ts delete mode 100644 apps/backend-mock/api/status.ts delete mode 100644 apps/backend-mock/api/system/dept/.post.ts delete mode 100644 apps/backend-mock/api/system/dept/[id].delete.ts delete mode 100644 apps/backend-mock/api/system/dept/[id].put.ts delete mode 100644 apps/backend-mock/api/system/dept/list.ts delete mode 100644 apps/backend-mock/api/system/menu/list.ts delete mode 100644 apps/backend-mock/api/system/menu/name-exists.ts delete mode 100644 apps/backend-mock/api/system/menu/path-exists.ts delete mode 100644 apps/backend-mock/api/system/role/list.ts delete mode 100644 apps/backend-mock/api/table/list.ts delete mode 100644 apps/backend-mock/api/test.get.ts delete mode 100644 apps/backend-mock/api/test.post.ts delete mode 100644 apps/backend-mock/api/timezone/getTimezone.ts delete mode 100644 apps/backend-mock/api/timezone/getTimezoneOptions.ts delete mode 100644 apps/backend-mock/api/timezone/setTimezone.ts delete mode 100644 apps/backend-mock/api/upload.ts delete mode 100644 apps/backend-mock/api/user/info.ts delete mode 100644 apps/backend-mock/error.ts delete mode 100644 apps/backend-mock/middleware/1.api.ts delete mode 100644 apps/backend-mock/nitro.config.ts delete mode 100644 apps/backend-mock/package.json delete mode 100644 apps/backend-mock/routes/[...].ts delete mode 100644 apps/backend-mock/tsconfig.build.json delete mode 100644 apps/backend-mock/tsconfig.json delete mode 100644 apps/backend-mock/utils/cookie-utils.ts delete mode 100644 apps/backend-mock/utils/jwt-utils.ts delete mode 100644 apps/backend-mock/utils/mock-data.ts delete mode 100644 apps/backend-mock/utils/response.ts delete mode 100644 apps/backend-mock/utils/timezone-utils.ts delete mode 100644 apps/web-antd/.env delete mode 100644 apps/web-antd/.env.analyze delete mode 100644 apps/web-antd/.env.development delete mode 100644 apps/web-antd/.env.production delete mode 100644 apps/web-antd/index.html delete mode 100644 apps/web-antd/package.json delete mode 100644 apps/web-antd/postcss.config.mjs delete mode 100644 apps/web-antd/public/favicon.ico delete mode 100644 apps/web-antd/src/adapter/component/index.ts delete mode 100644 apps/web-antd/src/adapter/form.ts delete mode 100644 apps/web-antd/src/adapter/vxe-table.ts delete mode 100644 apps/web-antd/src/api/core/auth.ts delete mode 100644 apps/web-antd/src/api/core/index.ts delete mode 100644 apps/web-antd/src/api/core/menu.ts delete mode 100644 apps/web-antd/src/api/core/user.ts delete mode 100644 apps/web-antd/src/api/index.ts delete mode 100644 apps/web-antd/src/api/request.ts delete mode 100644 apps/web-antd/src/app.vue delete mode 100644 apps/web-antd/src/bootstrap.ts delete mode 100644 apps/web-antd/src/layouts/auth.vue delete mode 100644 apps/web-antd/src/layouts/basic.vue delete mode 100644 apps/web-antd/src/layouts/index.ts delete mode 100644 apps/web-antd/src/locales/README.md delete mode 100644 apps/web-antd/src/locales/index.ts delete mode 100644 apps/web-antd/src/locales/langs/en-US/demos.json delete mode 100644 apps/web-antd/src/locales/langs/en-US/page.json delete mode 100644 apps/web-antd/src/locales/langs/zh-CN/demos.json delete mode 100644 apps/web-antd/src/locales/langs/zh-CN/page.json delete mode 100644 apps/web-antd/src/main.ts delete mode 100644 apps/web-antd/src/preferences.ts delete mode 100644 apps/web-antd/src/router/access.ts delete mode 100644 apps/web-antd/src/router/guard.ts delete mode 100644 apps/web-antd/src/router/index.ts delete mode 100644 apps/web-antd/src/router/routes/core.ts delete mode 100644 apps/web-antd/src/router/routes/index.ts delete mode 100644 apps/web-antd/src/router/routes/modules/dashboard.ts delete mode 100644 apps/web-antd/src/router/routes/modules/demos.ts delete mode 100644 apps/web-antd/src/router/routes/modules/vben.ts delete mode 100644 apps/web-antd/src/store/auth.ts delete mode 100644 apps/web-antd/src/store/index.ts delete mode 100644 apps/web-antd/src/views/_core/README.md delete mode 100644 apps/web-antd/src/views/_core/about/index.vue delete mode 100644 apps/web-antd/src/views/_core/authentication/code-login.vue delete mode 100644 apps/web-antd/src/views/_core/authentication/forget-password.vue delete mode 100644 apps/web-antd/src/views/_core/authentication/login.vue delete mode 100644 apps/web-antd/src/views/_core/authentication/qrcode-login.vue delete mode 100644 apps/web-antd/src/views/_core/authentication/register.vue delete mode 100644 apps/web-antd/src/views/_core/fallback/coming-soon.vue delete mode 100644 apps/web-antd/src/views/_core/fallback/forbidden.vue delete mode 100644 apps/web-antd/src/views/_core/fallback/internal-error.vue delete mode 100644 apps/web-antd/src/views/_core/fallback/not-found.vue delete mode 100644 apps/web-antd/src/views/_core/fallback/offline.vue delete mode 100644 apps/web-antd/src/views/dashboard/analytics/analytics-trends.vue delete mode 100644 apps/web-antd/src/views/dashboard/analytics/analytics-visits-data.vue delete mode 100644 apps/web-antd/src/views/dashboard/analytics/analytics-visits-sales.vue delete mode 100644 apps/web-antd/src/views/dashboard/analytics/analytics-visits-source.vue delete mode 100644 apps/web-antd/src/views/dashboard/analytics/analytics-visits.vue delete mode 100644 apps/web-antd/src/views/dashboard/analytics/index.vue delete mode 100644 apps/web-antd/src/views/dashboard/workspace/index.vue delete mode 100644 apps/web-antd/src/views/demos/antd/index.vue delete mode 100644 apps/web-antd/tailwind.config.mjs delete mode 100644 apps/web-antd/tsconfig.json delete mode 100644 apps/web-antd/tsconfig.node.json delete mode 100644 apps/web-antd/vite.config.mts delete mode 100644 apps/web-ele/.env delete mode 100644 apps/web-ele/.env.analyze delete mode 100644 apps/web-ele/.env.development delete mode 100644 apps/web-ele/.env.production delete mode 100644 apps/web-ele/index.html delete mode 100644 apps/web-ele/package.json delete mode 100644 apps/web-ele/postcss.config.mjs delete mode 100644 apps/web-ele/public/favicon.ico delete mode 100644 apps/web-ele/src/adapter/component/index.ts delete mode 100644 apps/web-ele/src/adapter/form.ts delete mode 100644 apps/web-ele/src/adapter/vxe-table.ts delete mode 100644 apps/web-ele/src/api/core/auth.ts delete mode 100644 apps/web-ele/src/api/core/index.ts delete mode 100644 apps/web-ele/src/api/core/menu.ts delete mode 100644 apps/web-ele/src/api/core/user.ts delete mode 100644 apps/web-ele/src/api/index.ts delete mode 100644 apps/web-ele/src/api/request.ts delete mode 100644 apps/web-ele/src/app.vue delete mode 100644 apps/web-ele/src/bootstrap.ts delete mode 100644 apps/web-ele/src/layouts/auth.vue delete mode 100644 apps/web-ele/src/layouts/basic.vue delete mode 100644 apps/web-ele/src/layouts/index.ts delete mode 100644 apps/web-ele/src/locales/README.md delete mode 100644 apps/web-ele/src/locales/index.ts delete mode 100644 apps/web-ele/src/locales/langs/en-US/demos.json delete mode 100644 apps/web-ele/src/locales/langs/en-US/page.json delete mode 100644 apps/web-ele/src/locales/langs/zh-CN/demos.json delete mode 100644 apps/web-ele/src/locales/langs/zh-CN/page.json delete mode 100644 apps/web-ele/src/main.ts delete mode 100644 apps/web-ele/src/preferences.ts delete mode 100644 apps/web-ele/src/router/access.ts delete mode 100644 apps/web-ele/src/router/guard.ts delete mode 100644 apps/web-ele/src/router/index.ts delete mode 100644 apps/web-ele/src/router/routes/core.ts delete mode 100644 apps/web-ele/src/router/routes/index.ts delete mode 100644 apps/web-ele/src/router/routes/modules/dashboard.ts delete mode 100644 apps/web-ele/src/router/routes/modules/demos.ts delete mode 100644 apps/web-ele/src/router/routes/modules/vben.ts delete mode 100644 apps/web-ele/src/store/auth.ts delete mode 100644 apps/web-ele/src/store/index.ts delete mode 100644 apps/web-ele/src/views/_core/README.md delete mode 100644 apps/web-ele/src/views/_core/about/index.vue delete mode 100644 apps/web-ele/src/views/_core/authentication/code-login.vue delete mode 100644 apps/web-ele/src/views/_core/authentication/forget-password.vue delete mode 100644 apps/web-ele/src/views/_core/authentication/login.vue delete mode 100644 apps/web-ele/src/views/_core/authentication/qrcode-login.vue delete mode 100644 apps/web-ele/src/views/_core/authentication/register.vue delete mode 100644 apps/web-ele/src/views/_core/fallback/coming-soon.vue delete mode 100644 apps/web-ele/src/views/_core/fallback/forbidden.vue delete mode 100644 apps/web-ele/src/views/_core/fallback/internal-error.vue delete mode 100644 apps/web-ele/src/views/_core/fallback/not-found.vue delete mode 100644 apps/web-ele/src/views/_core/fallback/offline.vue delete mode 100644 apps/web-ele/src/views/dashboard/analytics/analytics-trends.vue delete mode 100644 apps/web-ele/src/views/dashboard/analytics/analytics-visits-data.vue delete mode 100644 apps/web-ele/src/views/dashboard/analytics/analytics-visits-sales.vue delete mode 100644 apps/web-ele/src/views/dashboard/analytics/analytics-visits-source.vue delete mode 100644 apps/web-ele/src/views/dashboard/analytics/analytics-visits.vue delete mode 100644 apps/web-ele/src/views/dashboard/analytics/index.vue delete mode 100644 apps/web-ele/src/views/dashboard/workspace/index.vue delete mode 100644 apps/web-ele/src/views/demos/element/index.vue delete mode 100644 apps/web-ele/src/views/demos/form/basic.vue delete mode 100644 apps/web-ele/tailwind.config.mjs delete mode 100644 apps/web-ele/tsconfig.json delete mode 100644 apps/web-ele/tsconfig.node.json delete mode 100644 apps/web-ele/vite.config.mts delete mode 100644 apps/web-naive/.env delete mode 100644 apps/web-naive/.env.analyze delete mode 100644 apps/web-naive/.env.development delete mode 100644 apps/web-naive/.env.production delete mode 100644 apps/web-naive/index.html delete mode 100644 apps/web-naive/package.json delete mode 100644 apps/web-naive/postcss.config.mjs delete mode 100644 apps/web-naive/public/favicon.ico delete mode 100644 apps/web-naive/src/adapter/component/index.ts delete mode 100644 apps/web-naive/src/adapter/form.ts delete mode 100644 apps/web-naive/src/adapter/naive.ts delete mode 100644 apps/web-naive/src/adapter/vxe-table.ts delete mode 100644 apps/web-naive/src/api/core/auth.ts delete mode 100644 apps/web-naive/src/api/core/index.ts delete mode 100644 apps/web-naive/src/api/core/menu.ts delete mode 100644 apps/web-naive/src/api/core/user.ts delete mode 100644 apps/web-naive/src/api/index.ts delete mode 100644 apps/web-naive/src/api/request.ts delete mode 100644 apps/web-naive/src/app.vue delete mode 100644 apps/web-naive/src/bootstrap.ts delete mode 100644 apps/web-naive/src/layouts/auth.vue delete mode 100644 apps/web-naive/src/layouts/basic.vue delete mode 100644 apps/web-naive/src/layouts/index.ts delete mode 100644 apps/web-naive/src/locales/README.md delete mode 100644 apps/web-naive/src/locales/index.ts delete mode 100644 apps/web-naive/src/locales/langs/en-US/demos.json delete mode 100644 apps/web-naive/src/locales/langs/en-US/page.json delete mode 100644 apps/web-naive/src/locales/langs/zh-CN/demos.json delete mode 100644 apps/web-naive/src/locales/langs/zh-CN/page.json delete mode 100644 apps/web-naive/src/main.ts delete mode 100644 apps/web-naive/src/preferences.ts delete mode 100644 apps/web-naive/src/router/access.ts delete mode 100644 apps/web-naive/src/router/guard.ts delete mode 100644 apps/web-naive/src/router/index.ts delete mode 100644 apps/web-naive/src/router/routes/core.ts delete mode 100644 apps/web-naive/src/router/routes/index.ts delete mode 100644 apps/web-naive/src/router/routes/modules/dashboard.ts delete mode 100644 apps/web-naive/src/router/routes/modules/demos.ts delete mode 100644 apps/web-naive/src/router/routes/modules/vben.ts delete mode 100644 apps/web-naive/src/store/auth.ts delete mode 100644 apps/web-naive/src/store/index.ts delete mode 100644 apps/web-naive/src/views/_core/README.md delete mode 100644 apps/web-naive/src/views/_core/about/index.vue delete mode 100644 apps/web-naive/src/views/_core/authentication/code-login.vue delete mode 100644 apps/web-naive/src/views/_core/authentication/forget-password.vue delete mode 100644 apps/web-naive/src/views/_core/authentication/login.vue delete mode 100644 apps/web-naive/src/views/_core/authentication/qrcode-login.vue delete mode 100644 apps/web-naive/src/views/_core/authentication/register.vue delete mode 100644 apps/web-naive/src/views/_core/fallback/coming-soon.vue delete mode 100644 apps/web-naive/src/views/_core/fallback/forbidden.vue delete mode 100644 apps/web-naive/src/views/_core/fallback/internal-error.vue delete mode 100644 apps/web-naive/src/views/_core/fallback/not-found.vue delete mode 100644 apps/web-naive/src/views/_core/fallback/offline.vue delete mode 100644 apps/web-naive/src/views/dashboard/analytics/analytics-trends.vue delete mode 100644 apps/web-naive/src/views/dashboard/analytics/analytics-visits-data.vue delete mode 100644 apps/web-naive/src/views/dashboard/analytics/analytics-visits-sales.vue delete mode 100644 apps/web-naive/src/views/dashboard/analytics/analytics-visits-source.vue delete mode 100644 apps/web-naive/src/views/dashboard/analytics/analytics-visits.vue delete mode 100644 apps/web-naive/src/views/dashboard/analytics/index.vue delete mode 100644 apps/web-naive/src/views/dashboard/workspace/index.vue delete mode 100644 apps/web-naive/src/views/demos/form/basic.vue delete mode 100644 apps/web-naive/src/views/demos/form/modal.vue delete mode 100644 apps/web-naive/src/views/demos/naive/index.vue delete mode 100644 apps/web-naive/src/views/demos/table/index.vue delete mode 100644 apps/web-naive/tailwind.config.mjs delete mode 100644 apps/web-naive/tsconfig.json delete mode 100644 apps/web-naive/tsconfig.node.json delete mode 100644 apps/web-naive/vite.config.mts 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/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/count-to/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/apps/backend-mock/.env b/apps/backend-mock/.env deleted file mode 100644 index b20c4a65..00000000 --- a/apps/backend-mock/.env +++ /dev/null @@ -1,3 +0,0 @@ -PORT=5320 -ACCESS_TOKEN_SECRET=access_token_secret -REFRESH_TOKEN_SECRET=refresh_token_secret diff --git a/apps/backend-mock/README.md b/apps/backend-mock/README.md deleted file mode 100644 index 401bda76..00000000 --- a/apps/backend-mock/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# @vben/backend-mock - -## Description - -Vben Admin 数据 mock 服务,没有对接任何的数据库,所有数据都是模拟的,用于前端开发时提供数据支持。线上环境不再提供 mock 集成,可自行部署服务或者对接真实数据,由于 `mock.js` 等工具有一些限制,比如上传文件不行、无法模拟复杂的逻辑等,所以这里使用了真实的后端服务来实现。唯一麻烦的是本地需要同时启动后端服务和前端服务,但是这样可以更好的模拟真实环境。该服务不需要手动启动,已经集成在 vite 插件内,随应用一起启用。 - -## Running the app - -```bash -# development -$ pnpm run start - -# production mode -$ pnpm run build -``` diff --git a/apps/backend-mock/api/auth/codes.ts b/apps/backend-mock/api/auth/codes.ts deleted file mode 100644 index e610b338..00000000 --- a/apps/backend-mock/api/auth/codes.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { eventHandler } from 'h3'; -import { verifyAccessToken } from '~/utils/jwt-utils'; -import { MOCK_CODES } from '~/utils/mock-data'; -import { unAuthorizedResponse, useResponseSuccess } from '~/utils/response'; - -export default eventHandler((event) => { - const userinfo = verifyAccessToken(event); - if (!userinfo) { - return unAuthorizedResponse(event); - } - - const codes = - MOCK_CODES.find((item) => item.username === userinfo.username)?.codes ?? []; - - return useResponseSuccess(codes); -}); diff --git a/apps/backend-mock/api/auth/login.post.ts b/apps/backend-mock/api/auth/login.post.ts deleted file mode 100644 index e23942c4..00000000 --- a/apps/backend-mock/api/auth/login.post.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { defineEventHandler, readBody, setResponseStatus } from 'h3'; -import { - clearRefreshTokenCookie, - setRefreshTokenCookie, -} from '~/utils/cookie-utils'; -import { generateAccessToken, generateRefreshToken } from '~/utils/jwt-utils'; -import { MOCK_USERS } from '~/utils/mock-data'; -import { - forbiddenResponse, - useResponseError, - useResponseSuccess, -} from '~/utils/response'; - -export default defineEventHandler(async (event) => { - const { password, username } = await readBody(event); - if (!password || !username) { - setResponseStatus(event, 400); - return useResponseError( - 'BadRequestException', - 'Username and password are required', - ); - } - - const findUser = MOCK_USERS.find( - (item) => item.username === username && item.password === password, - ); - - if (!findUser) { - clearRefreshTokenCookie(event); - return forbiddenResponse(event, 'Username or password is incorrect.'); - } - - const accessToken = generateAccessToken(findUser); - const refreshToken = generateRefreshToken(findUser); - - setRefreshTokenCookie(event, refreshToken); - - return useResponseSuccess({ - ...findUser, - accessToken, - }); -}); diff --git a/apps/backend-mock/api/auth/logout.post.ts b/apps/backend-mock/api/auth/logout.post.ts deleted file mode 100644 index 74c8d315..00000000 --- a/apps/backend-mock/api/auth/logout.post.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { defineEventHandler } from 'h3'; -import { - clearRefreshTokenCookie, - getRefreshTokenFromCookie, -} from '~/utils/cookie-utils'; -import { useResponseSuccess } from '~/utils/response'; - -export default defineEventHandler(async (event) => { - const refreshToken = getRefreshTokenFromCookie(event); - if (!refreshToken) { - return useResponseSuccess(''); - } - - clearRefreshTokenCookie(event); - - return useResponseSuccess(''); -}); diff --git a/apps/backend-mock/api/auth/refresh.post.ts b/apps/backend-mock/api/auth/refresh.post.ts deleted file mode 100644 index 7d8d3a51..00000000 --- a/apps/backend-mock/api/auth/refresh.post.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { defineEventHandler } from 'h3'; -import { - clearRefreshTokenCookie, - getRefreshTokenFromCookie, - setRefreshTokenCookie, -} from '~/utils/cookie-utils'; -import { generateAccessToken, verifyRefreshToken } from '~/utils/jwt-utils'; -import { MOCK_USERS } from '~/utils/mock-data'; -import { forbiddenResponse } from '~/utils/response'; - -export default defineEventHandler(async (event) => { - const refreshToken = getRefreshTokenFromCookie(event); - if (!refreshToken) { - return forbiddenResponse(event); - } - - clearRefreshTokenCookie(event); - - const userinfo = verifyRefreshToken(refreshToken); - if (!userinfo) { - return forbiddenResponse(event); - } - - const findUser = MOCK_USERS.find( - (item) => item.username === userinfo.username, - ); - if (!findUser) { - return forbiddenResponse(event); - } - const accessToken = generateAccessToken(findUser); - - setRefreshTokenCookie(event, refreshToken); - - return accessToken; -}); diff --git a/apps/backend-mock/api/demo/bigint.ts b/apps/backend-mock/api/demo/bigint.ts deleted file mode 100644 index 00d6c28c..00000000 --- a/apps/backend-mock/api/demo/bigint.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { eventHandler, setHeader } from 'h3'; -import { verifyAccessToken } from '~/utils/jwt-utils'; -import { unAuthorizedResponse } from '~/utils/response'; - -export default eventHandler(async (event) => { - const userinfo = verifyAccessToken(event); - if (!userinfo) { - return unAuthorizedResponse(event); - } - const data = ` - { - "code": 0, - "message": "success", - "data": [ - { - "id": 123456789012345678901234567890123456789012345678901234567890, - "name": "John Doe", - "age": 30, - "email": "john-doe@demo.com" - }, - { - "id": 987654321098765432109876543210987654321098765432109876543210, - "name": "Jane Smith", - "age": 25, - "email": "jane@demo.com" - } - ] - } - `; - setHeader(event, 'Content-Type', 'application/json'); - return data; -}); diff --git a/apps/backend-mock/api/menu/all.ts b/apps/backend-mock/api/menu/all.ts deleted file mode 100644 index 7923f7ca..00000000 --- a/apps/backend-mock/api/menu/all.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { eventHandler } from 'h3'; -import { verifyAccessToken } from '~/utils/jwt-utils'; -import { MOCK_MENUS } from '~/utils/mock-data'; -import { unAuthorizedResponse, useResponseSuccess } from '~/utils/response'; - -export default eventHandler(async (event) => { - const userinfo = verifyAccessToken(event); - if (!userinfo) { - return unAuthorizedResponse(event); - } - - const menus = - MOCK_MENUS.find((item) => item.username === userinfo.username)?.menus ?? []; - return useResponseSuccess(menus); -}); diff --git a/apps/backend-mock/api/status.ts b/apps/backend-mock/api/status.ts deleted file mode 100644 index 43782095..00000000 --- a/apps/backend-mock/api/status.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { eventHandler, getQuery, setResponseStatus } from 'h3'; -import { useResponseError } from '~/utils/response'; - -export default eventHandler((event) => { - const { status } = getQuery(event); - setResponseStatus(event, Number(status)); - return useResponseError(`${status}`); -}); diff --git a/apps/backend-mock/api/system/dept/.post.ts b/apps/backend-mock/api/system/dept/.post.ts deleted file mode 100644 index 9a4896af..00000000 --- a/apps/backend-mock/api/system/dept/.post.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { eventHandler } from 'h3'; -import { verifyAccessToken } from '~/utils/jwt-utils'; -import { - sleep, - unAuthorizedResponse, - useResponseSuccess, -} from '~/utils/response'; - -export default eventHandler(async (event) => { - const userinfo = verifyAccessToken(event); - if (!userinfo) { - return unAuthorizedResponse(event); - } - await sleep(600); - return useResponseSuccess(null); -}); diff --git a/apps/backend-mock/api/system/dept/[id].delete.ts b/apps/backend-mock/api/system/dept/[id].delete.ts deleted file mode 100644 index eac0f584..00000000 --- a/apps/backend-mock/api/system/dept/[id].delete.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { eventHandler } from 'h3'; -import { verifyAccessToken } from '~/utils/jwt-utils'; -import { - sleep, - unAuthorizedResponse, - useResponseSuccess, -} from '~/utils/response'; - -export default eventHandler(async (event) => { - const userinfo = verifyAccessToken(event); - if (!userinfo) { - return unAuthorizedResponse(event); - } - await sleep(1000); - return useResponseSuccess(null); -}); diff --git a/apps/backend-mock/api/system/dept/[id].put.ts b/apps/backend-mock/api/system/dept/[id].put.ts deleted file mode 100644 index 6805e139..00000000 --- a/apps/backend-mock/api/system/dept/[id].put.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { eventHandler } from 'h3'; -import { verifyAccessToken } from '~/utils/jwt-utils'; -import { - sleep, - unAuthorizedResponse, - useResponseSuccess, -} from '~/utils/response'; - -export default eventHandler(async (event) => { - const userinfo = verifyAccessToken(event); - if (!userinfo) { - return unAuthorizedResponse(event); - } - await sleep(2000); - return useResponseSuccess(null); -}); diff --git a/apps/backend-mock/api/system/dept/list.ts b/apps/backend-mock/api/system/dept/list.ts deleted file mode 100644 index a649a0d2..00000000 --- a/apps/backend-mock/api/system/dept/list.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { faker } from '@faker-js/faker'; -import { eventHandler } from 'h3'; -import { verifyAccessToken } from '~/utils/jwt-utils'; -import { unAuthorizedResponse, useResponseSuccess } from '~/utils/response'; - -const formatterCN = new Intl.DateTimeFormat('zh-CN', { - timeZone: 'Asia/Shanghai', - year: 'numeric', - month: '2-digit', - day: '2-digit', - hour: '2-digit', - minute: '2-digit', - second: '2-digit', -}); - -function generateMockDataList(count: number) { - const dataList = []; - - for (let i = 0; i < count; i++) { - const dataItem: Record = { - id: faker.string.uuid(), - pid: 0, - name: faker.commerce.department(), - status: faker.helpers.arrayElement([0, 1]), - createTime: formatterCN.format( - faker.date.between({ from: '2021-01-01', to: '2022-12-31' }), - ), - remark: faker.lorem.sentence(), - }; - if (faker.datatype.boolean()) { - dataItem.children = Array.from( - { length: faker.number.int({ min: 1, max: 5 }) }, - () => ({ - id: faker.string.uuid(), - pid: dataItem.id, - name: faker.commerce.department(), - status: faker.helpers.arrayElement([0, 1]), - createTime: formatterCN.format( - faker.date.between({ from: '2023-01-01', to: '2023-12-31' }), - ), - remark: faker.lorem.sentence(), - }), - ); - } - dataList.push(dataItem); - } - - return dataList; -} - -const mockData = generateMockDataList(10); - -export default eventHandler(async (event) => { - const userinfo = verifyAccessToken(event); - if (!userinfo) { - return unAuthorizedResponse(event); - } - - const listData = structuredClone(mockData); - - return useResponseSuccess(listData); -}); diff --git a/apps/backend-mock/api/system/menu/list.ts b/apps/backend-mock/api/system/menu/list.ts deleted file mode 100644 index ce96bb14..00000000 --- a/apps/backend-mock/api/system/menu/list.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { eventHandler } from 'h3'; -import { verifyAccessToken } from '~/utils/jwt-utils'; -import { MOCK_MENU_LIST } from '~/utils/mock-data'; -import { unAuthorizedResponse, useResponseSuccess } from '~/utils/response'; - -export default eventHandler(async (event) => { - const userinfo = verifyAccessToken(event); - if (!userinfo) { - return unAuthorizedResponse(event); - } - - return useResponseSuccess(MOCK_MENU_LIST); -}); diff --git a/apps/backend-mock/api/system/menu/name-exists.ts b/apps/backend-mock/api/system/menu/name-exists.ts deleted file mode 100644 index 7d5551b3..00000000 --- a/apps/backend-mock/api/system/menu/name-exists.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { eventHandler, getQuery } from 'h3'; -import { verifyAccessToken } from '~/utils/jwt-utils'; -import { MOCK_MENU_LIST } from '~/utils/mock-data'; -import { unAuthorizedResponse, useResponseSuccess } from '~/utils/response'; - -const namesMap: Record = {}; - -function getNames(menus: any[]) { - menus.forEach((menu) => { - namesMap[menu.name] = String(menu.id); - if (menu.children) { - getNames(menu.children); - } - }); -} -getNames(MOCK_MENU_LIST); - -export default eventHandler(async (event) => { - const userinfo = verifyAccessToken(event); - if (!userinfo) { - return unAuthorizedResponse(event); - } - const { id, name } = getQuery(event); - - return (name as string) in namesMap && - (!id || namesMap[name as string] !== String(id)) - ? useResponseSuccess(true) - : useResponseSuccess(false); -}); diff --git a/apps/backend-mock/api/system/menu/path-exists.ts b/apps/backend-mock/api/system/menu/path-exists.ts deleted file mode 100644 index f3c3be99..00000000 --- a/apps/backend-mock/api/system/menu/path-exists.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { eventHandler, getQuery } from 'h3'; -import { verifyAccessToken } from '~/utils/jwt-utils'; -import { MOCK_MENU_LIST } from '~/utils/mock-data'; -import { unAuthorizedResponse, useResponseSuccess } from '~/utils/response'; - -const pathMap: Record = { '/': 0 }; - -function getPaths(menus: any[]) { - menus.forEach((menu) => { - pathMap[menu.path] = String(menu.id); - if (menu.children) { - getPaths(menu.children); - } - }); -} -getPaths(MOCK_MENU_LIST); - -export default eventHandler(async (event) => { - const userinfo = verifyAccessToken(event); - if (!userinfo) { - return unAuthorizedResponse(event); - } - const { id, path } = getQuery(event); - - return (path as string) in pathMap && - (!id || pathMap[path as string] !== String(id)) - ? useResponseSuccess(true) - : useResponseSuccess(false); -}); diff --git a/apps/backend-mock/api/system/role/list.ts b/apps/backend-mock/api/system/role/list.ts deleted file mode 100644 index bad29a51..00000000 --- a/apps/backend-mock/api/system/role/list.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { faker } from '@faker-js/faker'; -import { eventHandler, getQuery } from 'h3'; -import { verifyAccessToken } from '~/utils/jwt-utils'; -import { getMenuIds, MOCK_MENU_LIST } from '~/utils/mock-data'; -import { unAuthorizedResponse, usePageResponseSuccess } from '~/utils/response'; - -const formatterCN = new Intl.DateTimeFormat('zh-CN', { - timeZone: 'Asia/Shanghai', - year: 'numeric', - month: '2-digit', - day: '2-digit', - hour: '2-digit', - minute: '2-digit', - second: '2-digit', -}); - -const menuIds = getMenuIds(MOCK_MENU_LIST); - -function generateMockDataList(count: number) { - const dataList = []; - - for (let i = 0; i < count; i++) { - const dataItem: Record = { - id: faker.string.uuid(), - name: faker.commerce.product(), - status: faker.helpers.arrayElement([0, 1]), - createTime: formatterCN.format( - faker.date.between({ from: '2022-01-01', to: '2025-01-01' }), - ), - permissions: faker.helpers.arrayElements(menuIds), - remark: faker.lorem.sentence(), - }; - - dataList.push(dataItem); - } - - return dataList; -} - -const mockData = generateMockDataList(100); - -export default eventHandler(async (event) => { - const userinfo = verifyAccessToken(event); - if (!userinfo) { - return unAuthorizedResponse(event); - } - - const { - page = 1, - pageSize = 20, - name, - id, - remark, - startTime, - endTime, - status, - } = getQuery(event); - let listData = structuredClone(mockData); - if (name) { - listData = listData.filter((item) => - item.name.toLowerCase().includes(String(name).toLowerCase()), - ); - } - if (id) { - listData = listData.filter((item) => - item.id.toLowerCase().includes(String(id).toLowerCase()), - ); - } - if (remark) { - listData = listData.filter((item) => - item.remark?.toLowerCase()?.includes(String(remark).toLowerCase()), - ); - } - if (startTime) { - listData = listData.filter((item) => item.createTime >= startTime); - } - if (endTime) { - listData = listData.filter((item) => item.createTime <= endTime); - } - if (['0', '1'].includes(status as string)) { - listData = listData.filter((item) => item.status === Number(status)); - } - return usePageResponseSuccess(page as string, pageSize as string, listData); -}); diff --git a/apps/backend-mock/api/table/list.ts b/apps/backend-mock/api/table/list.ts deleted file mode 100644 index 6664b583..00000000 --- a/apps/backend-mock/api/table/list.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { faker } from '@faker-js/faker'; -import { eventHandler, getQuery } from 'h3'; -import { verifyAccessToken } from '~/utils/jwt-utils'; -import { - sleep, - unAuthorizedResponse, - usePageResponseSuccess, -} from '~/utils/response'; - -function generateMockDataList(count: number) { - const dataList = []; - - for (let i = 0; i < count; i++) { - const dataItem = { - id: faker.string.uuid(), - imageUrl: faker.image.avatar(), - imageUrl2: faker.image.avatar(), - open: faker.datatype.boolean(), - status: faker.helpers.arrayElement(['success', 'error', 'warning']), - productName: faker.commerce.productName(), - price: faker.commerce.price(), - currency: faker.finance.currencyCode(), - quantity: faker.number.int({ min: 1, max: 100 }), - available: faker.datatype.boolean(), - category: faker.commerce.department(), - releaseDate: faker.date.past(), - rating: faker.number.float({ min: 1, max: 5 }), - description: faker.commerce.productDescription(), - weight: faker.number.float({ min: 0.1, max: 10 }), - color: faker.color.human(), - inProduction: faker.datatype.boolean(), - tags: Array.from({ length: 3 }, () => faker.commerce.productAdjective()), - }; - - dataList.push(dataItem); - } - - return dataList; -} - -const mockData = generateMockDataList(100); - -export default eventHandler(async (event) => { - const userinfo = verifyAccessToken(event); - if (!userinfo) { - return unAuthorizedResponse(event); - } - - await sleep(600); - - const { page, pageSize, sortBy, sortOrder } = getQuery(event); - // 规范化分页参数,处理 string[] - const pageRaw = Array.isArray(page) ? page[0] : page; - const pageSizeRaw = Array.isArray(pageSize) ? pageSize[0] : pageSize; - const pageNumber = Math.max( - 1, - Number.parseInt(String(pageRaw ?? '1'), 10) || 1, - ); - const pageSizeNumber = Math.min( - 100, - Math.max(1, Number.parseInt(String(pageSizeRaw ?? '10'), 10) || 10), - ); - const listData = structuredClone(mockData); - - // 规范化 query 入参,兼容 string[] - const sortKeyRaw = Array.isArray(sortBy) ? sortBy[0] : sortBy; - const sortOrderRaw = Array.isArray(sortOrder) ? sortOrder[0] : sortOrder; - // 检查 sortBy 是否是 listData 元素的合法属性键 - if ( - typeof sortKeyRaw === 'string' && - listData[0] && - Object.prototype.hasOwnProperty.call(listData[0], sortKeyRaw) - ) { - // 定义数组元素的类型 - type ItemType = (typeof listData)[0]; - const sortKey = sortKeyRaw as keyof ItemType; // 将 sortBy 断言为合法键 - const isDesc = sortOrderRaw === 'desc'; - listData.sort((a, b) => { - const aValue = a[sortKey] as unknown; - const bValue = b[sortKey] as unknown; - - let result = 0; - - if (typeof aValue === 'number' && typeof bValue === 'number') { - result = aValue - bValue; - } else if (aValue instanceof Date && bValue instanceof Date) { - result = aValue.getTime() - bValue.getTime(); - } else if (typeof aValue === 'boolean' && typeof bValue === 'boolean') { - if (aValue === bValue) { - result = 0; - } else { - result = aValue ? 1 : -1; - } - } else { - const aStr = String(aValue); - const bStr = String(bValue); - const aNum = Number(aStr); - const bNum = Number(bStr); - result = - Number.isFinite(aNum) && Number.isFinite(bNum) - ? aNum - bNum - : aStr.localeCompare(bStr, undefined, { - numeric: true, - sensitivity: 'base', - }); - } - - return isDesc ? -result : result; - }); - } - - return usePageResponseSuccess( - String(pageNumber), - String(pageSizeNumber), - listData, - ); -}); diff --git a/apps/backend-mock/api/test.get.ts b/apps/backend-mock/api/test.get.ts deleted file mode 100644 index dc2ceef7..00000000 --- a/apps/backend-mock/api/test.get.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { defineEventHandler } from 'h3'; - -export default defineEventHandler(() => 'Test get handler'); diff --git a/apps/backend-mock/api/test.post.ts b/apps/backend-mock/api/test.post.ts deleted file mode 100644 index 0e9e337a..00000000 --- a/apps/backend-mock/api/test.post.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { defineEventHandler } from 'h3'; - -export default defineEventHandler(() => 'Test post handler'); diff --git a/apps/backend-mock/api/timezone/getTimezone.ts b/apps/backend-mock/api/timezone/getTimezone.ts deleted file mode 100644 index 0cbcb6ec..00000000 --- a/apps/backend-mock/api/timezone/getTimezone.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { eventHandler } from 'h3'; -import { verifyAccessToken } from '~/utils/jwt-utils'; -import { unAuthorizedResponse, useResponseSuccess } from '~/utils/response'; -import { getTimezone } from '~/utils/timezone-utils'; - -export default eventHandler((event) => { - const userinfo = verifyAccessToken(event); - if (!userinfo) { - return unAuthorizedResponse(event); - } - return useResponseSuccess(getTimezone()); -}); diff --git a/apps/backend-mock/api/timezone/getTimezoneOptions.ts b/apps/backend-mock/api/timezone/getTimezoneOptions.ts deleted file mode 100644 index 6c241864..00000000 --- a/apps/backend-mock/api/timezone/getTimezoneOptions.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { eventHandler } from 'h3'; -import { TIME_ZONE_OPTIONS } from '~/utils/mock-data'; -import { useResponseSuccess } from '~/utils/response'; - -export default eventHandler(() => { - const data = TIME_ZONE_OPTIONS.map((o) => ({ - label: `${o.timezone} (GMT${o.offset >= 0 ? `+${o.offset}` : o.offset})`, - value: o.timezone, - })); - return useResponseSuccess(data); -}); diff --git a/apps/backend-mock/api/timezone/setTimezone.ts b/apps/backend-mock/api/timezone/setTimezone.ts deleted file mode 100644 index 34d8f19e..00000000 --- a/apps/backend-mock/api/timezone/setTimezone.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { eventHandler, readBody } from 'h3'; -import { verifyAccessToken } from '~/utils/jwt-utils'; -import { TIME_ZONE_OPTIONS } from '~/utils/mock-data'; -import { unAuthorizedResponse, useResponseSuccess } from '~/utils/response'; -import { setTimezone } from '~/utils/timezone-utils'; - -export default eventHandler(async (event) => { - const userinfo = verifyAccessToken(event); - if (!userinfo) { - return unAuthorizedResponse(event); - } - const body = await readBody<{ timezone?: unknown }>(event); - const timezone = - typeof body?.timezone === 'string' ? body.timezone : undefined; - const allowed = TIME_ZONE_OPTIONS.some((o) => o.timezone === timezone); - if (!timezone || !allowed) { - setResponseStatus(event, 400); - return useResponseError('Bad Request', 'Invalid timezone'); - } - setTimezone(timezone); - return useResponseSuccess({}); -}); diff --git a/apps/backend-mock/api/upload.ts b/apps/backend-mock/api/upload.ts deleted file mode 100644 index 436b63cb..00000000 --- a/apps/backend-mock/api/upload.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { eventHandler } from 'h3'; -import { verifyAccessToken } from '~/utils/jwt-utils'; -import { unAuthorizedResponse, useResponseSuccess } from '~/utils/response'; - -export default eventHandler((event) => { - const userinfo = verifyAccessToken(event); - if (!userinfo) { - return unAuthorizedResponse(event); - } - return useResponseSuccess({ - url: 'https://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1.webp', - }); - // return useResponseError("test") -}); diff --git a/apps/backend-mock/api/user/info.ts b/apps/backend-mock/api/user/info.ts deleted file mode 100644 index 138cb433..00000000 --- a/apps/backend-mock/api/user/info.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { eventHandler } from 'h3'; -import { verifyAccessToken } from '~/utils/jwt-utils'; -import { unAuthorizedResponse, useResponseSuccess } from '~/utils/response'; - -export default eventHandler((event) => { - const userinfo = verifyAccessToken(event); - if (!userinfo) { - return unAuthorizedResponse(event); - } - return useResponseSuccess(userinfo); -}); diff --git a/apps/backend-mock/error.ts b/apps/backend-mock/error.ts deleted file mode 100644 index e20beac4..00000000 --- a/apps/backend-mock/error.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { NitroErrorHandler } from 'nitropack'; - -const errorHandler: NitroErrorHandler = function (error, event) { - event.node.res.end(`[Error Handler] ${error.stack}`); -}; - -export default errorHandler; diff --git a/apps/backend-mock/middleware/1.api.ts b/apps/backend-mock/middleware/1.api.ts deleted file mode 100644 index 339cda4d..00000000 --- a/apps/backend-mock/middleware/1.api.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { defineEventHandler } from 'h3'; -import { forbiddenResponse, sleep } from '~/utils/response'; - -export default defineEventHandler(async (event) => { - event.node.res.setHeader( - 'Access-Control-Allow-Origin', - event.headers.get('Origin') ?? '*', - ); - if (event.method === 'OPTIONS') { - event.node.res.statusCode = 204; - event.node.res.statusMessage = 'No Content.'; - return 'OK'; - } else if ( - ['DELETE', 'PATCH', 'POST', 'PUT'].includes(event.method) && - event.path.startsWith('/api/system/') - ) { - await sleep(Math.floor(Math.random() * 2000)); - return forbiddenResponse(event, '演示环境,禁止修改'); - } -}); diff --git a/apps/backend-mock/nitro.config.ts b/apps/backend-mock/nitro.config.ts deleted file mode 100644 index c0fc13e2..00000000 --- a/apps/backend-mock/nitro.config.ts +++ /dev/null @@ -1,20 +0,0 @@ -import errorHandler from './error'; - -process.env.COMPATIBILITY_DATE = new Date().toISOString(); -export default defineNitroConfig({ - devErrorHandler: errorHandler, - errorHandler: '~/error', - routeRules: { - '/api/**': { - cors: true, - headers: { - 'Access-Control-Allow-Credentials': 'true', - 'Access-Control-Allow-Headers': - 'Accept, Authorization, Content-Length, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, X-CSRF-TOKEN, X-Requested-With', - 'Access-Control-Allow-Methods': 'GET,HEAD,PUT,PATCH,POST,DELETE', - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Expose-Headers': '*', - }, - }, - }, -}); diff --git a/apps/backend-mock/package.json b/apps/backend-mock/package.json deleted file mode 100644 index cc0b8d53..00000000 --- a/apps/backend-mock/package.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "@vben/backend-mock", - "version": "0.0.1", - "description": "", - "private": true, - "license": "MIT", - "author": "", - "scripts": { - "build": "nitro build", - "start": "nitro dev" - }, - "dependencies": { - "@faker-js/faker": "catalog:", - "jsonwebtoken": "catalog:", - "nitropack": "catalog:" - }, - "devDependencies": { - "@types/jsonwebtoken": "catalog:", - "h3": "catalog:" - } -} diff --git a/apps/backend-mock/routes/[...].ts b/apps/backend-mock/routes/[...].ts deleted file mode 100644 index 5a22563d..00000000 --- a/apps/backend-mock/routes/[...].ts +++ /dev/null @@ -1,15 +0,0 @@ -import { defineEventHandler } from 'h3'; - -export default defineEventHandler(() => { - return ` -

Hello Vben Admin

-

Mock service is starting

- -`; -}); diff --git a/apps/backend-mock/tsconfig.build.json b/apps/backend-mock/tsconfig.build.json deleted file mode 100644 index 64f86c6b..00000000 --- a/apps/backend-mock/tsconfig.build.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "extends": "./tsconfig.json", - "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] -} diff --git a/apps/backend-mock/tsconfig.json b/apps/backend-mock/tsconfig.json deleted file mode 100644 index 43008af1..00000000 --- a/apps/backend-mock/tsconfig.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "./.nitro/types/tsconfig.json" -} diff --git a/apps/backend-mock/utils/cookie-utils.ts b/apps/backend-mock/utils/cookie-utils.ts deleted file mode 100644 index 187ce2f0..00000000 --- a/apps/backend-mock/utils/cookie-utils.ts +++ /dev/null @@ -1,28 +0,0 @@ -import type { EventHandlerRequest, H3Event } from 'h3'; - -import { deleteCookie, getCookie, setCookie } from 'h3'; - -export function clearRefreshTokenCookie(event: H3Event) { - deleteCookie(event, 'jwt', { - httpOnly: true, - sameSite: 'none', - secure: true, - }); -} - -export function setRefreshTokenCookie( - event: H3Event, - refreshToken: string, -) { - setCookie(event, 'jwt', refreshToken, { - httpOnly: true, - maxAge: 24 * 60 * 60, // unit: seconds - sameSite: 'none', - secure: true, - }); -} - -export function getRefreshTokenFromCookie(event: H3Event) { - const refreshToken = getCookie(event, 'jwt'); - return refreshToken; -} diff --git a/apps/backend-mock/utils/jwt-utils.ts b/apps/backend-mock/utils/jwt-utils.ts deleted file mode 100644 index 71858307..00000000 --- a/apps/backend-mock/utils/jwt-utils.ts +++ /dev/null @@ -1,77 +0,0 @@ -import type { EventHandlerRequest, H3Event } from 'h3'; - -import type { UserInfo } from './mock-data'; - -import { getHeader } from 'h3'; -import jwt from 'jsonwebtoken'; - -import { MOCK_USERS } from './mock-data'; - -// TODO: Replace with your own secret key -const ACCESS_TOKEN_SECRET = 'access_token_secret'; -const REFRESH_TOKEN_SECRET = 'refresh_token_secret'; - -export interface UserPayload extends UserInfo { - iat: number; - exp: number; -} - -export function generateAccessToken(user: UserInfo) { - return jwt.sign(user, ACCESS_TOKEN_SECRET, { expiresIn: '7d' }); -} - -export function generateRefreshToken(user: UserInfo) { - return jwt.sign(user, REFRESH_TOKEN_SECRET, { - expiresIn: '30d', - }); -} - -export function verifyAccessToken( - event: H3Event, -): null | Omit { - const authHeader = getHeader(event, 'Authorization'); - if (!authHeader?.startsWith('Bearer')) { - return null; - } - - const tokenParts = authHeader.split(' '); - if (tokenParts.length !== 2) { - return null; - } - const token = tokenParts[1] as string; - try { - const decoded = jwt.verify( - token, - ACCESS_TOKEN_SECRET, - ) as unknown as UserPayload; - - const username = decoded.username; - const user = MOCK_USERS.find((item) => item.username === username); - if (!user) { - return null; - } - const { password: _pwd, ...userinfo } = user; - return userinfo; - } catch { - return null; - } -} - -export function verifyRefreshToken( - token: string, -): null | Omit { - try { - const decoded = jwt.verify(token, REFRESH_TOKEN_SECRET) as UserPayload; - const username = decoded.username; - const user = MOCK_USERS.find( - (item) => item.username === username, - ) as UserInfo; - if (!user) { - return null; - } - const { password: _pwd, ...userinfo } = user; - return userinfo; - } catch { - return null; - } -} diff --git a/apps/backend-mock/utils/mock-data.ts b/apps/backend-mock/utils/mock-data.ts deleted file mode 100644 index ee38e8ef..00000000 --- a/apps/backend-mock/utils/mock-data.ts +++ /dev/null @@ -1,421 +0,0 @@ -export interface UserInfo { - id: number; - password: string; - realName: string; - roles: string[]; - username: string; - homePath?: string; -} - -export interface TimezoneOption { - offset: number; - timezone: string; -} - -export const MOCK_USERS: UserInfo[] = [ - { - id: 0, - password: '123456', - realName: 'Vben', - roles: ['super'], - username: 'vben', - }, - { - id: 1, - password: '123456', - realName: 'Admin', - roles: ['admin'], - username: 'admin', - homePath: '/workspace', - }, - { - id: 2, - password: '123456', - realName: 'Jack', - roles: ['user'], - username: 'jack', - homePath: '/analytics', - }, -]; - -export const MOCK_CODES = [ - // super - { - codes: ['AC_100100', 'AC_100110', 'AC_100120', 'AC_100010'], - username: 'vben', - }, - { - // admin - codes: ['AC_100010', 'AC_100020', 'AC_100030'], - username: 'admin', - }, - { - // user - codes: ['AC_1000001', 'AC_1000002'], - username: 'jack', - }, -]; - -const dashboardMenus = [ - { - meta: { - order: -1, - title: 'page.dashboard.title', - }, - name: 'Dashboard', - path: '/dashboard', - redirect: '/analytics', - children: [ - { - name: 'Analytics', - path: '/analytics', - component: '/dashboard/analytics/index', - meta: { - affixTab: true, - title: 'page.dashboard.analytics', - }, - }, - { - name: 'Workspace', - path: '/workspace', - component: '/dashboard/workspace/index', - meta: { - title: 'page.dashboard.workspace', - }, - }, - ], - }, -]; - -const createDemosMenus = (role: 'admin' | 'super' | 'user') => { - const roleWithMenus = { - admin: { - component: '/demos/access/admin-visible', - meta: { - icon: 'mdi:button-cursor', - title: 'demos.access.adminVisible', - }, - name: 'AccessAdminVisibleDemo', - path: '/demos/access/admin-visible', - }, - super: { - component: '/demos/access/super-visible', - meta: { - icon: 'mdi:button-cursor', - title: 'demos.access.superVisible', - }, - name: 'AccessSuperVisibleDemo', - path: '/demos/access/super-visible', - }, - user: { - component: '/demos/access/user-visible', - meta: { - icon: 'mdi:button-cursor', - title: 'demos.access.userVisible', - }, - name: 'AccessUserVisibleDemo', - path: '/demos/access/user-visible', - }, - }; - - return [ - { - meta: { - icon: 'ic:baseline-view-in-ar', - keepAlive: true, - order: 1000, - title: 'demos.title', - }, - name: 'Demos', - path: '/demos', - redirect: '/demos/access', - children: [ - { - name: 'AccessDemos', - path: '/demosaccess', - meta: { - icon: 'mdi:cloud-key-outline', - title: 'demos.access.backendPermissions', - }, - redirect: '/demos/access/page-control', - children: [ - { - name: 'AccessPageControlDemo', - path: '/demos/access/page-control', - component: '/demos/access/index', - meta: { - icon: 'mdi:page-previous-outline', - title: 'demos.access.pageAccess', - }, - }, - { - name: 'AccessButtonControlDemo', - path: '/demos/access/button-control', - component: '/demos/access/button-control', - meta: { - icon: 'mdi:button-cursor', - title: 'demos.access.buttonControl', - }, - }, - { - name: 'AccessMenuVisible403Demo', - path: '/demos/access/menu-visible-403', - component: '/demos/access/menu-visible-403', - meta: { - authority: ['no-body'], - icon: 'mdi:button-cursor', - menuVisibleWithForbidden: true, - title: 'demos.access.menuVisible403', - }, - }, - roleWithMenus[role], - ], - }, - ], - }, - ]; -}; - -export const MOCK_MENUS = [ - { - menus: [...dashboardMenus, ...createDemosMenus('super')], - username: 'vben', - }, - { - menus: [...dashboardMenus, ...createDemosMenus('admin')], - username: 'admin', - }, - { - menus: [...dashboardMenus, ...createDemosMenus('user')], - username: 'jack', - }, -]; - -export const MOCK_MENU_LIST = [ - { - id: 1, - name: 'Workspace', - status: 1, - type: 'menu', - icon: 'mdi:dashboard', - path: '/workspace', - component: '/dashboard/workspace/index', - meta: { - icon: 'carbon:workspace', - title: 'page.dashboard.workspace', - affixTab: true, - order: 0, - }, - }, - { - id: 2, - meta: { - icon: 'carbon:settings', - order: 9997, - title: 'system.title', - badge: 'new', - badgeType: 'normal', - badgeVariants: 'primary', - }, - status: 1, - type: 'catalog', - name: 'System', - path: '/system', - children: [ - { - id: 201, - pid: 2, - path: '/system/menu', - name: 'SystemMenu', - authCode: 'System:Menu:List', - status: 1, - type: 'menu', - meta: { - icon: 'carbon:menu', - title: 'system.menu.title', - }, - component: '/system/menu/list', - children: [ - { - id: 20_101, - pid: 201, - name: 'SystemMenuCreate', - status: 1, - type: 'button', - authCode: 'System:Menu:Create', - meta: { title: 'common.create' }, - }, - { - id: 20_102, - pid: 201, - name: 'SystemMenuEdit', - status: 1, - type: 'button', - authCode: 'System:Menu:Edit', - meta: { title: 'common.edit' }, - }, - { - id: 20_103, - pid: 201, - name: 'SystemMenuDelete', - status: 1, - type: 'button', - authCode: 'System:Menu:Delete', - meta: { title: 'common.delete' }, - }, - ], - }, - { - id: 202, - pid: 2, - path: '/system/dept', - name: 'SystemDept', - status: 1, - type: 'menu', - authCode: 'System:Dept:List', - meta: { - icon: 'carbon:container-services', - title: 'system.dept.title', - }, - component: '/system/dept/list', - children: [ - { - id: 20_401, - pid: 202, - name: 'SystemDeptCreate', - status: 1, - type: 'button', - authCode: 'System:Dept:Create', - meta: { title: 'common.create' }, - }, - { - id: 20_402, - pid: 202, - name: 'SystemDeptEdit', - status: 1, - type: 'button', - authCode: 'System:Dept:Edit', - meta: { title: 'common.edit' }, - }, - { - id: 20_403, - pid: 202, - name: 'SystemDeptDelete', - status: 1, - type: 'button', - authCode: 'System:Dept:Delete', - meta: { title: 'common.delete' }, - }, - ], - }, - ], - }, - { - id: 9, - meta: { - badgeType: 'dot', - order: 9998, - title: 'demos.vben.title', - icon: 'carbon:data-center', - }, - name: 'Project', - path: '/vben-admin', - type: 'catalog', - status: 1, - children: [ - { - id: 901, - pid: 9, - name: 'VbenDocument', - path: '/vben-admin/document', - component: 'IFrameView', - type: 'embedded', - status: 1, - meta: { - icon: 'carbon:book', - iframeSrc: 'https://doc.vben.pro', - title: 'demos.vben.document', - }, - }, - { - id: 902, - pid: 9, - name: 'VbenGithub', - path: '/vben-admin/github', - component: 'IFrameView', - type: 'link', - status: 1, - meta: { - icon: 'carbon:logo-github', - link: 'https://github.com/vbenjs/vue-vben-admin', - title: 'Github', - }, - }, - { - id: 903, - pid: 9, - name: 'VbenAntdv', - path: '/vben-admin/antdv', - component: 'IFrameView', - type: 'link', - status: 0, - meta: { - icon: 'carbon:hexagon-vertical-solid', - badgeType: 'dot', - link: 'https://ant.vben.pro', - title: 'demos.vben.antdv', - }, - }, - ], - }, - { - id: 10, - component: '_core/about/index', - type: 'menu', - status: 1, - meta: { - icon: 'lucide:copyright', - order: 9999, - title: 'demos.vben.about', - }, - name: 'About', - path: '/about', - }, -]; - -export function getMenuIds(menus: any[]) { - const ids: number[] = []; - menus.forEach((item) => { - ids.push(item.id); - if (item.children && item.children.length > 0) { - ids.push(...getMenuIds(item.children)); - } - }); - return ids; -} - -/** - * 时区选项 - */ -export const TIME_ZONE_OPTIONS: TimezoneOption[] = [ - { - offset: -5, - timezone: 'America/New_York', - }, - { - offset: 0, - timezone: 'Europe/London', - }, - { - offset: 8, - timezone: 'Asia/Shanghai', - }, - { - offset: 9, - timezone: 'Asia/Tokyo', - }, - { - offset: 9, - timezone: 'Asia/Seoul', - }, -]; diff --git a/apps/backend-mock/utils/response.ts b/apps/backend-mock/utils/response.ts deleted file mode 100644 index 2d4242e9..00000000 --- a/apps/backend-mock/utils/response.ts +++ /dev/null @@ -1,70 +0,0 @@ -import type { EventHandlerRequest, H3Event } from 'h3'; - -import { setResponseStatus } from 'h3'; - -export function useResponseSuccess(data: T) { - return { - code: 0, - data, - error: null, - message: 'ok', - }; -} - -export function usePageResponseSuccess( - page: number | string, - pageSize: number | string, - list: T[], - { message = 'ok' } = {}, -) { - const pageData = pagination( - Number.parseInt(`${page}`), - Number.parseInt(`${pageSize}`), - list, - ); - - return { - ...useResponseSuccess({ - items: pageData, - total: list.length, - }), - message, - }; -} - -export function useResponseError(message: string, error: any = null) { - return { - code: -1, - data: null, - error, - message, - }; -} - -export function forbiddenResponse( - event: H3Event, - message = 'Forbidden Exception', -) { - setResponseStatus(event, 403); - return useResponseError(message, message); -} - -export function unAuthorizedResponse(event: H3Event) { - setResponseStatus(event, 401); - return useResponseError('Unauthorized Exception', 'Unauthorized Exception'); -} - -export function sleep(ms: number) { - return new Promise((resolve) => setTimeout(resolve, ms)); -} - -export function pagination( - pageNo: number, - pageSize: number, - array: T[], -): T[] { - const offset = (pageNo - 1) * Number(pageSize); - return offset + Number(pageSize) >= array.length - ? array.slice(offset) - : array.slice(offset, offset + Number(pageSize)); -} diff --git a/apps/backend-mock/utils/timezone-utils.ts b/apps/backend-mock/utils/timezone-utils.ts deleted file mode 100644 index da35f920..00000000 --- a/apps/backend-mock/utils/timezone-utils.ts +++ /dev/null @@ -1,9 +0,0 @@ -let mockTimeZone: null | string = null; - -export const setTimezone = (timeZone: string) => { - mockTimeZone = timeZone; -}; - -export const getTimezone = () => { - return mockTimeZone; -}; diff --git a/apps/web-antd/.env b/apps/web-antd/.env deleted file mode 100644 index 19735f36..00000000 --- a/apps/web-antd/.env +++ /dev/null @@ -1,8 +0,0 @@ -# 应用标题 -VITE_APP_TITLE=Vben Admin Antd - -# 应用命名空间,用于缓存、store等功能的前缀,确保隔离 -VITE_APP_NAMESPACE=vben-web-antd - -# 对store进行加密的密钥,在将store持久化到localStorage时会使用该密钥进行加密 -VITE_APP_STORE_SECURE_KEY=please-replace-me-with-your-own-key diff --git a/apps/web-antd/.env.analyze b/apps/web-antd/.env.analyze deleted file mode 100644 index ffafa8dd..00000000 --- a/apps/web-antd/.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/apps/web-antd/.env.development b/apps/web-antd/.env.development deleted file mode 100644 index c138f482..00000000 --- a/apps/web-antd/.env.development +++ /dev/null @@ -1,16 +0,0 @@ -# 端口号 -VITE_PORT=5666 - -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 diff --git a/apps/web-antd/.env.production b/apps/web-antd/.env.production deleted file mode 100644 index 5375847a..00000000 --- a/apps/web-antd/.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/apps/web-antd/index.html b/apps/web-antd/index.html deleted file mode 100644 index 480eb84d..00000000 --- a/apps/web-antd/index.html +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - <%= VITE_APP_TITLE %> - - - - -
- - - diff --git a/apps/web-antd/package.json b/apps/web-antd/package.json deleted file mode 100644 index db7d0070..00000000 --- a/apps/web-antd/package.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "name": "@vben/web-antd", - "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": "apps/web-antd" - }, - "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" - }, - "imports": { - "#/*": "./src/*" - }, - "dependencies": { - "@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:", - "ant-design-vue": "catalog:", - "dayjs": "catalog:", - "pinia": "catalog:", - "vue": "catalog:", - "vue-router": "catalog:" - } -} diff --git a/apps/web-antd/postcss.config.mjs b/apps/web-antd/postcss.config.mjs deleted file mode 100644 index 3d807045..00000000 --- a/apps/web-antd/postcss.config.mjs +++ /dev/null @@ -1 +0,0 @@ -export { default } from '@vben/tailwind-config/postcss'; diff --git a/apps/web-antd/public/favicon.ico b/apps/web-antd/public/favicon.ico deleted file mode 100644 index fcf9818e2cf855039b272bdbfbb202d3ff3fa159..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5430 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 import('ant-design-vue/es/auto-complete'), -); -const Button = defineAsyncComponent(() => import('ant-design-vue/es/button')); -const Checkbox = defineAsyncComponent( - () => import('ant-design-vue/es/checkbox'), -); -const CheckboxGroup = defineAsyncComponent(() => - import('ant-design-vue/es/checkbox').then((res) => res.CheckboxGroup), -); -const DatePicker = defineAsyncComponent( - () => import('ant-design-vue/es/date-picker'), -); -const Divider = defineAsyncComponent(() => import('ant-design-vue/es/divider')); -const Input = defineAsyncComponent(() => import('ant-design-vue/es/input')); -const InputNumber = defineAsyncComponent( - () => import('ant-design-vue/es/input-number'), -); -const InputPassword = defineAsyncComponent(() => - import('ant-design-vue/es/input').then((res) => res.InputPassword), -); -const Mentions = defineAsyncComponent( - () => import('ant-design-vue/es/mentions'), -); -const Radio = defineAsyncComponent(() => import('ant-design-vue/es/radio')); -const RadioGroup = defineAsyncComponent(() => - import('ant-design-vue/es/radio').then((res) => res.RadioGroup), -); -const RangePicker = defineAsyncComponent(() => - import('ant-design-vue/es/date-picker').then((res) => res.RangePicker), -); -const Rate = defineAsyncComponent(() => import('ant-design-vue/es/rate')); -const Select = defineAsyncComponent(() => import('ant-design-vue/es/select')); -const Space = defineAsyncComponent(() => import('ant-design-vue/es/space')); -const Switch = defineAsyncComponent(() => import('ant-design-vue/es/switch')); -const Textarea = defineAsyncComponent(() => - import('ant-design-vue/es/input').then((res) => res.Textarea), -); -const TimePicker = defineAsyncComponent( - () => import('ant-design-vue/es/time-picker'), -); -const TreeSelect = defineAsyncComponent( - () => import('ant-design-vue/es/tree-select'), -); -const Upload = defineAsyncComponent(() => import('ant-design-vue/es/upload')); - -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, - ); - }, - }); -}; - -// 这里需要自行根据业务组件库进行适配,需要用到的组件都需要在这里类型说明 -export type ComponentType = - | 'ApiSelect' - | 'ApiTreeSelect' - | 'AutoComplete' - | '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), - ApiSelect: withDefaultPlaceholder( - { - ...ApiComponent, - name: 'ApiSelect', - }, - 'select', - { - component: Select, - loadingSlot: 'suffixIcon', - visibleEvent: 'onDropdownVisibleChange', - modelPropName: 'value', - }, - ), - ApiTreeSelect: withDefaultPlaceholder( - { - ...ApiComponent, - name: 'ApiTreeSelect', - }, - 'select', - { - component: TreeSelect, - fieldNames: { label: 'label', value: 'value', children: 'children' }, - loadingSlot: 'suffixIcon', - modelPropName: 'value', - optionsPropName: 'treeData', - visibleEvent: 'onVisibleChange', - }, - ), - AutoComplete, - 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, - }; - - // 将组件注册到全局共享状态中 - globalShareState.setComponents(components); - - // 定义全局共享状态中的消息提示 - globalShareState.defineMessage({ - // 复制成功消息提示 - copyPreferencesSuccess: (title, content) => { - notification.success({ - description: content, - message: title, - placement: 'bottomRight', - }); - }, - }); -} - -export { initComponentAdapter }; diff --git a/apps/web-antd/src/adapter/form.ts b/apps/web-antd/src/adapter/form.ts deleted file mode 100644 index 983a7f51..00000000 --- a/apps/web-antd/src/adapter/form.ts +++ /dev/null @@ -1,49 +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/apps/web-antd/src/adapter/vxe-table.ts b/apps/web-antd/src/adapter/vxe-table.ts deleted file mode 100644 index 7de2859d..00000000 --- a/apps/web-antd/src/adapter/vxe-table.ts +++ /dev/null @@ -1,69 +0,0 @@ -import type { VxeTableGridOptions } from '@vben/plugins/vxe-table'; - -import { h } from 'vue'; - -import { setupVbenVxeTable, useVbenVxeGrid } from '@vben/plugins/vxe-table'; - -import { Button, Image } from 'ant-design-vue'; - -import { useVbenForm } from './form'; - -setupVbenVxeTable({ - configVxeTable: (vxeUI) => { - vxeUI.setConfig({ - grid: { - align: 'center', - border: false, - columnConfig: { - resizable: true, - }, - minHeight: 180, - formConfig: { - // 全局禁用vxe-table的表单配置,使用formOptions - enabled: false, - }, - proxyConfig: { - autoLoad: true, - response: { - result: 'items', - total: 'total', - list: 'items', - }, - showActiveMsg: true, - showResponseMsg: false, - }, - round: true, - showOverflow: true, - size: 'small', - } as VxeTableGridOptions, - }); - - // 表格配置项可以用 cellRender: { name: 'CellImage' }, - vxeUI.renderer.add('CellImage', { - renderTableDefault(_renderOpts, params) { - const { column, row } = params; - return h(Image, { src: row[column.field] }); - }, - }); - - // 表格配置项可以用 cellRender: { name: 'CellLink' }, - vxeUI.renderer.add('CellLink', { - renderTableDefault(renderOpts) { - const { props } = renderOpts; - return h( - Button, - { size: 'small', type: 'link' }, - { default: () => props?.text }, - ); - }, - }); - - // 这里可以自行扩展 vxe-table 的全局配置,比如自定义格式化 - // vxeUI.formats.add - }, - useVbenForm, -}); - -export { useVbenVxeGrid }; - -export type * from '@vben/plugins/vxe-table'; diff --git a/apps/web-antd/src/api/core/auth.ts b/apps/web-antd/src/api/core/auth.ts deleted file mode 100644 index 71d9f994..00000000 --- a/apps/web-antd/src/api/core/auth.ts +++ /dev/null @@ -1,51 +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); -} - -/** - * 刷新accessToken - */ -export async function refreshTokenApi() { - return baseRequestClient.post('/auth/refresh', { - withCredentials: true, - }); -} - -/** - * 退出登录 - */ -export async function logoutApi() { - return baseRequestClient.post('/auth/logout', { - withCredentials: true, - }); -} - -/** - * 获取用户权限码 - */ -export async function getAccessCodesApi() { - return requestClient.get('/auth/codes'); -} diff --git a/apps/web-antd/src/api/core/index.ts b/apps/web-antd/src/api/core/index.ts deleted file mode 100644 index 28a5aef4..00000000 --- a/apps/web-antd/src/api/core/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './auth'; -export * from './menu'; -export * from './user'; diff --git a/apps/web-antd/src/api/core/menu.ts b/apps/web-antd/src/api/core/menu.ts deleted file mode 100644 index 9ef60b11..00000000 --- a/apps/web-antd/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/apps/web-antd/src/api/core/user.ts b/apps/web-antd/src/api/core/user.ts deleted file mode 100644 index 7e28ea84..00000000 --- a/apps/web-antd/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/apps/web-antd/src/api/index.ts b/apps/web-antd/src/api/index.ts deleted file mode 100644 index 4b0e0413..00000000 --- a/apps/web-antd/src/api/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './core'; diff --git a/apps/web-antd/src/api/request.ts b/apps/web-antd/src/api/request.ts deleted file mode 100644 index 288dddd0..00000000 --- a/apps/web-antd/src/api/request.ts +++ /dev/null @@ -1,113 +0,0 @@ -/** - * 该文件可自行根据业务逻辑进行调整 - */ -import type { 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 { message } from 'ant-design-vue'; - -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, - }); - - /** - * 重新认证逻辑 - */ - 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 }); diff --git a/apps/web-antd/src/app.vue b/apps/web-antd/src/app.vue deleted file mode 100644 index bbaccce1..00000000 --- a/apps/web-antd/src/app.vue +++ /dev/null @@ -1,39 +0,0 @@ - - - diff --git a/apps/web-antd/src/bootstrap.ts b/apps/web-antd/src/bootstrap.ts deleted file mode 100644 index ec721125..00000000 --- a/apps/web-antd/src/bootstrap.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { createApp, watchEffect } from 'vue'; - -import { registerAccessDirective } from '@vben/access'; -import { registerLoadingDirective } from '@vben/common-ui/es/loading'; -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 { initComponentAdapter } from './adapter/component'; -import { initSetupVbenForm } from './adapter/form'; -import App from './app.vue'; -import { router } from './router'; - -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 }); - - // 安装权限指令 - registerAccessDirective(app); - - // 初始化 tippy - const { initTippy } = await import('@vben/common-ui/es/tippy'); - initTippy(app); - - // 配置路由及路由守卫 - app.use(router); - - // 配置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/apps/web-antd/src/layouts/auth.vue b/apps/web-antd/src/layouts/auth.vue deleted file mode 100644 index 8ba66e85..00000000 --- a/apps/web-antd/src/layouts/auth.vue +++ /dev/null @@ -1,25 +0,0 @@ - - - diff --git a/apps/web-antd/src/layouts/basic.vue b/apps/web-antd/src/layouts/basic.vue deleted file mode 100644 index 805b8a73..00000000 --- a/apps/web-antd/src/layouts/basic.vue +++ /dev/null @@ -1,162 +0,0 @@ - - - diff --git a/apps/web-antd/src/layouts/index.ts b/apps/web-antd/src/layouts/index.ts deleted file mode 100644 index a4320780..00000000 --- a/apps/web-antd/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/apps/web-antd/src/locales/README.md b/apps/web-antd/src/locales/README.md deleted file mode 100644 index 7b451032..00000000 --- a/apps/web-antd/src/locales/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# locale - -每个app使用的国际化可能不同,这里用于扩展国际化的功能,例如扩展 dayjs、antd组件库的多语言切换,以及app本身的国际化文件。 diff --git a/apps/web-antd/src/locales/index.ts b/apps/web-antd/src/locales/index.ts deleted file mode 100644 index 7f32bd18..00000000 --- a/apps/web-antd/src/locales/index.ts +++ /dev/null @@ -1,102 +0,0 @@ -import type { Locale } from 'ant-design-vue/es/locale'; - -import type { App } from 'vue'; - -import type { LocaleSetupOptions, SupportedLanguagesType } from '@vben/locales'; - -import { ref } from 'vue'; - -import { - $t, - setupI18n as coreSetup, - loadLocalesMapFromDir, -} from '@vben/locales'; -import { preferences } from '@vben/preferences'; - -import antdEnLocale from 'ant-design-vue/es/locale/en_US'; -import antdDefaultLocale from 'ant-design-vue/es/locale/zh_CN'; -import dayjs from 'dayjs'; - -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/apps/web-antd/src/locales/langs/en-US/demos.json b/apps/web-antd/src/locales/langs/en-US/demos.json deleted file mode 100644 index 12a3b718..00000000 --- a/apps/web-antd/src/locales/langs/en-US/demos.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "title": "Demos", - "antd": "Ant Design Vue", - "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/apps/web-antd/src/locales/langs/en-US/page.json b/apps/web-antd/src/locales/langs/en-US/page.json deleted file mode 100644 index 618a258c..00000000 --- a/apps/web-antd/src/locales/langs/en-US/page.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "auth": { - "login": "Login", - "register": "Register", - "codeLogin": "Code Login", - "qrcodeLogin": "Qr Code Login", - "forgetPassword": "Forget Password" - }, - "dashboard": { - "title": "Dashboard", - "analytics": "Analytics", - "workspace": "Workspace" - } -} diff --git a/apps/web-antd/src/locales/langs/zh-CN/demos.json b/apps/web-antd/src/locales/langs/zh-CN/demos.json deleted file mode 100644 index b5007ea7..00000000 --- a/apps/web-antd/src/locales/langs/zh-CN/demos.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "title": "演示", - "antd": "Ant Design Vue", - "vben": { - "title": "项目", - "about": "关于", - "document": "文档", - "antdv": "Ant Design Vue 版本", - "naive-ui": "Naive UI 版本", - "element-plus": "Element Plus 版本", - "tdesign": "TDesign Vue 版本" - } -} diff --git a/apps/web-antd/src/locales/langs/zh-CN/page.json b/apps/web-antd/src/locales/langs/zh-CN/page.json deleted file mode 100644 index 4cb67081..00000000 --- a/apps/web-antd/src/locales/langs/zh-CN/page.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "auth": { - "login": "登录", - "register": "注册", - "codeLogin": "验证码登录", - "qrcodeLogin": "二维码登录", - "forgetPassword": "忘记密码" - }, - "dashboard": { - "title": "概览", - "analytics": "分析页", - "workspace": "工作台" - } -} diff --git a/apps/web-antd/src/main.ts b/apps/web-antd/src/main.ts deleted file mode 100644 index 5d728a02..00000000 --- a/apps/web-antd/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/apps/web-antd/src/preferences.ts b/apps/web-antd/src/preferences.ts deleted file mode 100644 index b2e9ace4..00000000 --- a/apps/web-antd/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/apps/web-antd/src/router/access.ts b/apps/web-antd/src/router/access.ts deleted file mode 100644 index 3a48be23..00000000 --- a/apps/web-antd/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 'ant-design-vue'; - -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/apps/web-antd/src/router/guard.ts b/apps/web-antd/src/router/guard.ts deleted file mode 100644 index a1ad6d88..00000000 --- a/apps/web-antd/src/router/guard.ts +++ /dev/null @@ -1,133 +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); - const redirectPath = (from.query.redirect ?? - (to.path === preferences.app.defaultHomePath - ? userInfo.homePath || preferences.app.defaultHomePath - : to.fullPath)) as string; - - return { - ...router.resolve(decodeURIComponent(redirectPath)), - replace: true, - }; - }); -} - -/** - * 项目守卫配置 - * @param router - */ -function createRouterGuard(router: Router) { - /** 通用 */ - setupCommonGuard(router); - /** 权限访问 */ - setupAccessGuard(router); -} - -export { createRouterGuard }; diff --git a/apps/web-antd/src/router/index.ts b/apps/web-antd/src/router/index.ts deleted file mode 100644 index 48402303..00000000 --- a/apps/web-antd/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/apps/web-antd/src/router/routes/core.ts b/apps/web-antd/src/router/routes/core.ts deleted file mode 100644 index 949b0b65..00000000 --- a/apps/web-antd/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/apps/web-antd/src/router/routes/index.ts b/apps/web-antd/src/router/routes/index.ts deleted file mode 100644 index e6fb1440..00000000 --- a/apps/web-antd/src/router/routes/index.ts +++ /dev/null @@ -1,37 +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]; -export { accessRoutes, coreRouteNames, routes }; diff --git a/apps/web-antd/src/router/routes/modules/dashboard.ts b/apps/web-antd/src/router/routes/modules/dashboard.ts deleted file mode 100644 index 5254dc65..00000000 --- a/apps/web-antd/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/apps/web-antd/src/router/routes/modules/demos.ts b/apps/web-antd/src/router/routes/modules/demos.ts deleted file mode 100644 index 55ade09c..00000000 --- a/apps/web-antd/src/router/routes/modules/demos.ts +++ /dev/null @@ -1,28 +0,0 @@ -import type { RouteRecordRaw } from 'vue-router'; - -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: { - title: $t('demos.antd'), - }, - name: 'AntDesignDemos', - path: '/demos/ant-design', - component: () => import('#/views/demos/antd/index.vue'), - }, - ], - }, -]; - -export default routes; diff --git a/apps/web-antd/src/router/routes/modules/vben.ts b/apps/web-antd/src/router/routes/modules/vben.ts deleted file mode 100644 index 4a8cdb0a..00000000 --- a/apps/web-antd/src/router/routes/modules/vben.ts +++ /dev/null @@ -1,94 +0,0 @@ -import type { RouteRecordRaw } from 'vue-router'; - -import { - 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 { 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: '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: 'VbenTDesign', - path: '/vben-admin/tdesign', - component: IFrameView, - meta: { - badgeType: 'dot', - icon: SvgTDesignIcon, - link: VBEN_TD_PREVIEW_URL, - title: $t('demos.vben.tdesign'), - }, - }, - { - 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: 'VbenAbout', - path: '/vben-admin/about', - component: () => import('#/views/_core/about/index.vue'), - meta: { - icon: 'lucide:copyright', - title: $t('demos.vben.about'), - order: 9999, - }, - }, -]; - -export default routes; diff --git a/apps/web-antd/src/store/auth.ts b/apps/web-antd/src/store/auth.ts deleted file mode 100644 index bd496d1e..00000000 --- a/apps/web-antd/src/store/auth.ts +++ /dev/null @@ -1,118 +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 'ant-design-vue'; -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 登录表单数据 - */ - 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, - }; - } - - async function logout(redirect: boolean = true) { - try { - await logoutApi(); - } catch { - // 不做任何处理 - } - 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/apps/web-antd/src/store/index.ts b/apps/web-antd/src/store/index.ts deleted file mode 100644 index 269586ee..00000000 --- a/apps/web-antd/src/store/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './auth'; diff --git a/apps/web-antd/src/views/_core/README.md b/apps/web-antd/src/views/_core/README.md deleted file mode 100644 index 8248afe6..00000000 --- a/apps/web-antd/src/views/_core/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# \_core - -此目录包含应用程序正常运行所需的基本视图。这些视图是应用程序布局中使用的视图。 diff --git a/apps/web-antd/src/views/_core/about/index.vue b/apps/web-antd/src/views/_core/about/index.vue deleted file mode 100644 index 0ee52433..00000000 --- a/apps/web-antd/src/views/_core/about/index.vue +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/apps/web-antd/src/views/_core/authentication/code-login.vue b/apps/web-antd/src/views/_core/authentication/code-login.vue deleted file mode 100644 index acfd1fd7..00000000 --- a/apps/web-antd/src/views/_core/authentication/code-login.vue +++ /dev/null @@ -1,69 +0,0 @@ - - - diff --git a/apps/web-antd/src/views/_core/authentication/forget-password.vue b/apps/web-antd/src/views/_core/authentication/forget-password.vue deleted file mode 100644 index fef0d427..00000000 --- a/apps/web-antd/src/views/_core/authentication/forget-password.vue +++ /dev/null @@ -1,43 +0,0 @@ - - - diff --git a/apps/web-antd/src/views/_core/authentication/login.vue b/apps/web-antd/src/views/_core/authentication/login.vue deleted file mode 100644 index 099e4c8c..00000000 --- a/apps/web-antd/src/views/_core/authentication/login.vue +++ /dev/null @@ -1,98 +0,0 @@ - - - diff --git a/apps/web-antd/src/views/_core/authentication/qrcode-login.vue b/apps/web-antd/src/views/_core/authentication/qrcode-login.vue deleted file mode 100644 index 23f5f2da..00000000 --- a/apps/web-antd/src/views/_core/authentication/qrcode-login.vue +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/apps/web-antd/src/views/_core/authentication/register.vue b/apps/web-antd/src/views/_core/authentication/register.vue deleted file mode 100644 index b1a5de72..00000000 --- a/apps/web-antd/src/views/_core/authentication/register.vue +++ /dev/null @@ -1,96 +0,0 @@ - - - diff --git a/apps/web-antd/src/views/_core/fallback/coming-soon.vue b/apps/web-antd/src/views/_core/fallback/coming-soon.vue deleted file mode 100644 index f394930f..00000000 --- a/apps/web-antd/src/views/_core/fallback/coming-soon.vue +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/apps/web-antd/src/views/_core/fallback/forbidden.vue b/apps/web-antd/src/views/_core/fallback/forbidden.vue deleted file mode 100644 index 8ea65fed..00000000 --- a/apps/web-antd/src/views/_core/fallback/forbidden.vue +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/apps/web-antd/src/views/_core/fallback/internal-error.vue b/apps/web-antd/src/views/_core/fallback/internal-error.vue deleted file mode 100644 index 819a47d5..00000000 --- a/apps/web-antd/src/views/_core/fallback/internal-error.vue +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/apps/web-antd/src/views/_core/fallback/not-found.vue b/apps/web-antd/src/views/_core/fallback/not-found.vue deleted file mode 100644 index 4d178e9c..00000000 --- a/apps/web-antd/src/views/_core/fallback/not-found.vue +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/apps/web-antd/src/views/_core/fallback/offline.vue b/apps/web-antd/src/views/_core/fallback/offline.vue deleted file mode 100644 index 5de4a88d..00000000 --- a/apps/web-antd/src/views/_core/fallback/offline.vue +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/apps/web-antd/src/views/dashboard/analytics/analytics-trends.vue b/apps/web-antd/src/views/dashboard/analytics/analytics-trends.vue deleted file mode 100644 index f1f0b232..00000000 --- a/apps/web-antd/src/views/dashboard/analytics/analytics-trends.vue +++ /dev/null @@ -1,98 +0,0 @@ - - - diff --git a/apps/web-antd/src/views/dashboard/analytics/analytics-visits-data.vue b/apps/web-antd/src/views/dashboard/analytics/analytics-visits-data.vue deleted file mode 100644 index 190fb41f..00000000 --- a/apps/web-antd/src/views/dashboard/analytics/analytics-visits-data.vue +++ /dev/null @@ -1,82 +0,0 @@ - - - diff --git a/apps/web-antd/src/views/dashboard/analytics/analytics-visits-sales.vue b/apps/web-antd/src/views/dashboard/analytics/analytics-visits-sales.vue deleted file mode 100644 index 02f50912..00000000 --- a/apps/web-antd/src/views/dashboard/analytics/analytics-visits-sales.vue +++ /dev/null @@ -1,46 +0,0 @@ - - - diff --git a/apps/web-antd/src/views/dashboard/analytics/analytics-visits-source.vue b/apps/web-antd/src/views/dashboard/analytics/analytics-visits-source.vue deleted file mode 100644 index 0915c7af..00000000 --- a/apps/web-antd/src/views/dashboard/analytics/analytics-visits-source.vue +++ /dev/null @@ -1,65 +0,0 @@ - - - diff --git a/apps/web-antd/src/views/dashboard/analytics/analytics-visits.vue b/apps/web-antd/src/views/dashboard/analytics/analytics-visits.vue deleted file mode 100644 index 7e0f1013..00000000 --- a/apps/web-antd/src/views/dashboard/analytics/analytics-visits.vue +++ /dev/null @@ -1,55 +0,0 @@ - - - diff --git a/apps/web-antd/src/views/dashboard/analytics/index.vue b/apps/web-antd/src/views/dashboard/analytics/index.vue deleted file mode 100644 index 5e3d6d28..00000000 --- a/apps/web-antd/src/views/dashboard/analytics/index.vue +++ /dev/null @@ -1,90 +0,0 @@ - - - diff --git a/apps/web-antd/src/views/dashboard/workspace/index.vue b/apps/web-antd/src/views/dashboard/workspace/index.vue deleted file mode 100644 index b95d6138..00000000 --- a/apps/web-antd/src/views/dashboard/workspace/index.vue +++ /dev/null @@ -1,266 +0,0 @@ - - - diff --git a/apps/web-antd/src/views/demos/antd/index.vue b/apps/web-antd/src/views/demos/antd/index.vue deleted file mode 100644 index b3b05cc1..00000000 --- a/apps/web-antd/src/views/demos/antd/index.vue +++ /dev/null @@ -1,66 +0,0 @@ - - - diff --git a/apps/web-antd/tailwind.config.mjs b/apps/web-antd/tailwind.config.mjs deleted file mode 100644 index f17f556f..00000000 --- a/apps/web-antd/tailwind.config.mjs +++ /dev/null @@ -1 +0,0 @@ -export { default } from '@vben/tailwind-config'; diff --git a/apps/web-antd/tsconfig.json b/apps/web-antd/tsconfig.json deleted file mode 100644 index 02c287fe..00000000 --- a/apps/web-antd/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/apps/web-antd/tsconfig.node.json b/apps/web-antd/tsconfig.node.json deleted file mode 100644 index c2f0d86c..00000000 --- a/apps/web-antd/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/apps/web-antd/vite.config.mts b/apps/web-antd/vite.config.mts deleted file mode 100644 index b6360f1d..00000000 --- a/apps/web-antd/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/apps/web-ele/.env b/apps/web-ele/.env deleted file mode 100644 index bb57c865..00000000 --- a/apps/web-ele/.env +++ /dev/null @@ -1,8 +0,0 @@ -# 应用标题 -VITE_APP_TITLE=Vben Admin Ele - -# 应用命名空间,用于缓存、store等功能的前缀,确保隔离 -VITE_APP_NAMESPACE=vben-web-ele - -# 对store进行加密的密钥,在将store持久化到localStorage时会使用该密钥进行加密 -VITE_APP_STORE_SECURE_KEY=please-replace-me-with-your-own-key diff --git a/apps/web-ele/.env.analyze b/apps/web-ele/.env.analyze deleted file mode 100644 index ffafa8dd..00000000 --- a/apps/web-ele/.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/apps/web-ele/.env.development b/apps/web-ele/.env.development deleted file mode 100644 index 8bcb432e..00000000 --- a/apps/web-ele/.env.development +++ /dev/null @@ -1,16 +0,0 @@ -# 端口号 -VITE_PORT=5777 - -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 diff --git a/apps/web-ele/.env.production b/apps/web-ele/.env.production deleted file mode 100644 index 5375847a..00000000 --- a/apps/web-ele/.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/apps/web-ele/index.html b/apps/web-ele/index.html deleted file mode 100644 index 2b59b8d7..00000000 --- a/apps/web-ele/index.html +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - <%= VITE_APP_TITLE %> - - - - -
- - - diff --git a/apps/web-ele/package.json b/apps/web-ele/package.json deleted file mode 100644 index abbedb63..00000000 --- a/apps/web-ele/package.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "name": "@vben/web-ele", - "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": "apps/web-ele" - }, - "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" - }, - "imports": { - "#/*": "./src/*" - }, - "dependencies": { - "@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:", - "dayjs": "catalog:", - "element-plus": "catalog:", - "pinia": "catalog:", - "vue": "catalog:", - "vue-router": "catalog:" - }, - "devDependencies": { - "unplugin-element-plus": "catalog:" - } -} diff --git a/apps/web-ele/postcss.config.mjs b/apps/web-ele/postcss.config.mjs deleted file mode 100644 index 3d807045..00000000 --- a/apps/web-ele/postcss.config.mjs +++ /dev/null @@ -1 +0,0 @@ -export { default } from '@vben/tailwind-config/postcss'; diff --git a/apps/web-ele/public/favicon.ico b/apps/web-ele/public/favicon.ico deleted file mode 100644 index fcf9818e2cf855039b272bdbfbb202d3ff3fa159..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5430 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 - Promise.all([ - import('element-plus/es/components/button/index'), - import('element-plus/es/components/button/style/css'), - ]).then(([res]) => res.ElButton), -); -const ElCheckbox = defineAsyncComponent(() => - Promise.all([ - import('element-plus/es/components/checkbox/index'), - import('element-plus/es/components/checkbox/style/css'), - ]).then(([res]) => res.ElCheckbox), -); -const ElCheckboxButton = defineAsyncComponent(() => - Promise.all([ - import('element-plus/es/components/checkbox/index'), - import('element-plus/es/components/checkbox-button/style/css'), - ]).then(([res]) => res.ElCheckboxButton), -); -const ElCheckboxGroup = defineAsyncComponent(() => - Promise.all([ - import('element-plus/es/components/checkbox/index'), - import('element-plus/es/components/checkbox-group/style/css'), - ]).then(([res]) => res.ElCheckboxGroup), -); -const ElDatePicker = defineAsyncComponent(() => - Promise.all([ - import('element-plus/es/components/date-picker/index'), - import('element-plus/es/components/date-picker/style/css'), - ]).then(([res]) => res.ElDatePicker), -); -const ElDivider = defineAsyncComponent(() => - Promise.all([ - import('element-plus/es/components/divider/index'), - import('element-plus/es/components/divider/style/css'), - ]).then(([res]) => res.ElDivider), -); -const ElInput = defineAsyncComponent(() => - Promise.all([ - import('element-plus/es/components/input/index'), - import('element-plus/es/components/input/style/css'), - ]).then(([res]) => res.ElInput), -); -const ElInputNumber = defineAsyncComponent(() => - Promise.all([ - import('element-plus/es/components/input-number/index'), - import('element-plus/es/components/input-number/style/css'), - ]).then(([res]) => res.ElInputNumber), -); -const ElRadio = defineAsyncComponent(() => - Promise.all([ - import('element-plus/es/components/radio/index'), - import('element-plus/es/components/radio/style/css'), - ]).then(([res]) => res.ElRadio), -); -const ElRadioButton = defineAsyncComponent(() => - Promise.all([ - import('element-plus/es/components/radio/index'), - import('element-plus/es/components/radio-button/style/css'), - ]).then(([res]) => res.ElRadioButton), -); -const ElRadioGroup = defineAsyncComponent(() => - Promise.all([ - import('element-plus/es/components/radio/index'), - import('element-plus/es/components/radio-group/style/css'), - ]).then(([res]) => res.ElRadioGroup), -); -const ElSelectV2 = defineAsyncComponent(() => - Promise.all([ - import('element-plus/es/components/select-v2/index'), - import('element-plus/es/components/select-v2/style/css'), - ]).then(([res]) => res.ElSelectV2), -); -const ElSpace = defineAsyncComponent(() => - Promise.all([ - import('element-plus/es/components/space/index'), - import('element-plus/es/components/space/style/css'), - ]).then(([res]) => res.ElSpace), -); -const ElSwitch = defineAsyncComponent(() => - Promise.all([ - import('element-plus/es/components/switch/index'), - import('element-plus/es/components/switch/style/css'), - ]).then(([res]) => res.ElSwitch), -); -const ElTimePicker = defineAsyncComponent(() => - Promise.all([ - import('element-plus/es/components/time-picker/index'), - import('element-plus/es/components/time-picker/style/css'), - ]).then(([res]) => res.ElTimePicker), -); -const ElTreeSelect = defineAsyncComponent(() => - Promise.all([ - import('element-plus/es/components/tree-select/index'), - import('element-plus/es/components/tree-select/style/css'), - ]).then(([res]) => res.ElTreeSelect), -); -const ElUpload = defineAsyncComponent(() => - Promise.all([ - import('element-plus/es/components/upload/index'), - import('element-plus/es/components/upload/style/css'), - ]).then(([res]) => res.ElUpload), -); - -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, - ); - }, - }); -}; - -// 这里需要自行根据业务组件库进行适配,需要用到的组件都需要在这里类型说明 -export type ComponentType = - | 'ApiSelect' - | 'ApiTreeSelect' - | 'Checkbox' - | 'CheckboxGroup' - | 'DatePicker' - | 'Divider' - | 'IconPicker' - | 'Input' - | 'InputNumber' - | 'RadioGroup' - | 'Select' - | 'Space' - | 'Switch' - | 'TimePicker' - | 'TreeSelect' - | 'Upload' - | BaseFormComponentType; - -async function initComponentAdapter() { - const components: Partial> = { - // 如果你的组件体积比较大,可以使用异步加载 - // Button: () => - // import('xxx').then((res) => res.Button), - ApiSelect: withDefaultPlaceholder( - { - ...ApiComponent, - name: 'ApiSelect', - }, - 'select', - { - component: ElSelectV2, - loadingSlot: 'loading', - visibleEvent: 'onVisibleChange', - }, - ), - ApiTreeSelect: withDefaultPlaceholder( - { - ...ApiComponent, - name: 'ApiTreeSelect', - }, - 'select', - { - component: ElTreeSelect, - props: { label: 'label', children: 'children' }, - nodeKey: 'value', - loadingSlot: 'loading', - optionsPropName: 'data', - visibleEvent: 'onVisibleChange', - }, - ), - Checkbox: ElCheckbox, - CheckboxGroup: (props, { attrs, slots }) => { - let defaultSlot; - if (Reflect.has(slots, 'default')) { - defaultSlot = slots.default; - } else { - const { options, isButton } = attrs; - if (Array.isArray(options)) { - defaultSlot = () => - options.map((option) => - h(isButton ? ElCheckboxButton : ElCheckbox, option), - ); - } - } - return h( - ElCheckboxGroup, - { ...props, ...attrs }, - { ...slots, default: defaultSlot }, - ); - }, - // 自定义默认按钮 - DefaultButton: (props, { attrs, slots }) => { - return h(ElButton, { ...props, attrs, type: 'info' }, slots); - }, - // 自定义主要按钮 - PrimaryButton: (props, { attrs, slots }) => { - return h(ElButton, { ...props, attrs, type: 'primary' }, slots); - }, - Divider: ElDivider, - IconPicker: withDefaultPlaceholder(IconPicker, 'select', { - iconSlot: 'append', - modelValueProp: 'model-value', - inputComponent: ElInput, - }), - Input: withDefaultPlaceholder(ElInput, 'input'), - InputNumber: withDefaultPlaceholder(ElInputNumber, 'input'), - RadioGroup: (props, { attrs, slots }) => { - let defaultSlot; - if (Reflect.has(slots, 'default')) { - defaultSlot = slots.default; - } else { - const { options } = attrs; - if (Array.isArray(options)) { - defaultSlot = () => - options.map((option) => - h(attrs.isButton ? ElRadioButton : ElRadio, option), - ); - } - } - return h( - ElRadioGroup, - { ...props, ...attrs }, - { ...slots, default: defaultSlot }, - ); - }, - Select: (props, { attrs, slots }) => { - return h(ElSelectV2, { ...props, attrs }, slots); - }, - Space: ElSpace, - Switch: ElSwitch, - TimePicker: (props, { attrs, slots }) => { - const { name, id, isRange } = props; - const extraProps: Recordable = {}; - if (isRange) { - if (name && !Array.isArray(name)) { - extraProps.name = [name, `${name}_end`]; - } - if (id && !Array.isArray(id)) { - extraProps.id = [id, `${id}_end`]; - } - } - return h( - ElTimePicker, - { - ...props, - ...attrs, - ...extraProps, - }, - slots, - ); - }, - DatePicker: (props, { attrs, slots }) => { - const { name, id, type } = props; - const extraProps: Recordable = {}; - if (type && type.includes('range')) { - if (name && !Array.isArray(name)) { - extraProps.name = [name, `${name}_end`]; - } - if (id && !Array.isArray(id)) { - extraProps.id = [id, `${id}_end`]; - } - } - return h( - ElDatePicker, - { - ...props, - ...attrs, - ...extraProps, - }, - slots, - ); - }, - TreeSelect: withDefaultPlaceholder(ElTreeSelect, 'select'), - Upload: ElUpload, - }; - - // 将组件注册到全局共享状态中 - globalShareState.setComponents(components); - - // 定义全局共享状态中的消息提示 - globalShareState.defineMessage({ - // 复制成功消息提示 - copyPreferencesSuccess: (title, content) => { - ElNotification({ - title, - message: content, - position: 'bottom-right', - duration: 0, - type: 'success', - }); - }, - }); -} - -export { initComponentAdapter }; diff --git a/apps/web-ele/src/adapter/form.ts b/apps/web-ele/src/adapter/form.ts deleted file mode 100644 index 936c3fe4..00000000 --- a/apps/web-ele/src/adapter/form.ts +++ /dev/null @@ -1,41 +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: { - modelPropNameMap: { - Upload: 'fileList', - CheckboxGroup: 'model-value', - }, - }, - 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/apps/web-ele/src/adapter/vxe-table.ts b/apps/web-ele/src/adapter/vxe-table.ts deleted file mode 100644 index 40b8179d..00000000 --- a/apps/web-ele/src/adapter/vxe-table.ts +++ /dev/null @@ -1,70 +0,0 @@ -import type { VxeTableGridOptions } from '@vben/plugins/vxe-table'; - -import { h } from 'vue'; - -import { setupVbenVxeTable, useVbenVxeGrid } from '@vben/plugins/vxe-table'; - -import { ElButton, ElImage } from 'element-plus'; - -import { useVbenForm } from './form'; - -setupVbenVxeTable({ - configVxeTable: (vxeUI) => { - vxeUI.setConfig({ - grid: { - align: 'center', - border: false, - columnConfig: { - resizable: true, - }, - minHeight: 180, - formConfig: { - // 全局禁用vxe-table的表单配置,使用formOptions - enabled: false, - }, - proxyConfig: { - autoLoad: true, - response: { - result: 'items', - total: 'total', - list: 'items', - }, - showActiveMsg: true, - showResponseMsg: false, - }, - round: true, - showOverflow: true, - size: 'small', - } as VxeTableGridOptions, - }); - - // 表格配置项可以用 cellRender: { name: 'CellImage' }, - vxeUI.renderer.add('CellImage', { - renderTableDefault(_renderOpts, params) { - const { column, row } = params; - const src = row[column.field]; - return h(ElImage, { src, previewSrcList: [src] }); - }, - }); - - // 表格配置项可以用 cellRender: { name: 'CellLink' }, - vxeUI.renderer.add('CellLink', { - renderTableDefault(renderOpts) { - const { props } = renderOpts; - return h( - ElButton, - { size: 'small', link: true }, - { default: () => props?.text }, - ); - }, - }); - - // 这里可以自行扩展 vxe-table 的全局配置,比如自定义格式化 - // vxeUI.formats.add - }, - useVbenForm, -}); - -export { useVbenVxeGrid }; - -export type * from '@vben/plugins/vxe-table'; diff --git a/apps/web-ele/src/api/core/auth.ts b/apps/web-ele/src/api/core/auth.ts deleted file mode 100644 index 71d9f994..00000000 --- a/apps/web-ele/src/api/core/auth.ts +++ /dev/null @@ -1,51 +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); -} - -/** - * 刷新accessToken - */ -export async function refreshTokenApi() { - return baseRequestClient.post('/auth/refresh', { - withCredentials: true, - }); -} - -/** - * 退出登录 - */ -export async function logoutApi() { - return baseRequestClient.post('/auth/logout', { - withCredentials: true, - }); -} - -/** - * 获取用户权限码 - */ -export async function getAccessCodesApi() { - return requestClient.get('/auth/codes'); -} diff --git a/apps/web-ele/src/api/core/index.ts b/apps/web-ele/src/api/core/index.ts deleted file mode 100644 index 28a5aef4..00000000 --- a/apps/web-ele/src/api/core/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './auth'; -export * from './menu'; -export * from './user'; diff --git a/apps/web-ele/src/api/core/menu.ts b/apps/web-ele/src/api/core/menu.ts deleted file mode 100644 index 9ef60b11..00000000 --- a/apps/web-ele/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/apps/web-ele/src/api/core/user.ts b/apps/web-ele/src/api/core/user.ts deleted file mode 100644 index 7e28ea84..00000000 --- a/apps/web-ele/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/apps/web-ele/src/api/index.ts b/apps/web-ele/src/api/index.ts deleted file mode 100644 index 4b0e0413..00000000 --- a/apps/web-ele/src/api/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './core'; diff --git a/apps/web-ele/src/api/request.ts b/apps/web-ele/src/api/request.ts deleted file mode 100644 index 203b35bf..00000000 --- a/apps/web-ele/src/api/request.ts +++ /dev/null @@ -1,113 +0,0 @@ -/** - * 该文件可自行根据业务逻辑进行调整 - */ -import type { 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 { ElMessage } from 'element-plus'; - -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, - }); - - /** - * 重新认证逻辑 - */ - 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 ?? ''; - // 如果没有错误信息,则会根据状态码进行提示 - ElMessage.error(errorMessage || msg); - }), - ); - - return client; -} - -export const requestClient = createRequestClient(apiURL, { - responseReturn: 'data', -}); - -export const baseRequestClient = new RequestClient({ baseURL: apiURL }); diff --git a/apps/web-ele/src/app.vue b/apps/web-ele/src/app.vue deleted file mode 100644 index 1217658d..00000000 --- a/apps/web-ele/src/app.vue +++ /dev/null @@ -1,17 +0,0 @@ - - - diff --git a/apps/web-ele/src/bootstrap.ts b/apps/web-ele/src/bootstrap.ts deleted file mode 100644 index e5befb5a..00000000 --- a/apps/web-ele/src/bootstrap.ts +++ /dev/null @@ -1,79 +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/ele'; - -import { useTitle } from '@vueuse/core'; -import { ElLoading } from 'element-plus'; - -import { $t, setupI18n } from '#/locales'; - -import { initComponentAdapter } from './adapter/component'; -import { initSetupVbenForm } from './adapter/form'; -import App from './app.vue'; -import { router } from './router'; - -async function bootstrap(namespace: string) { - // 初始化组件适配器 - await initComponentAdapter(); - - // 初始化表单组件 - await initSetupVbenForm(); - - // // 设置弹窗的默认配置 - // setDefaultModalProps({ - // fullscreenButton: false, - // }); - // // 设置抽屉的默认配置 - // setDefaultDrawerProps({ - // zIndex: 2000, - // }); - const app = createApp(App); - - // 注册Element Plus提供的v-loading指令 - app.directive('loading', ElLoading.directive); - - // 注册Vben提供的v-loading和v-spinning指令 - registerLoadingDirective(app, { - loading: false, // Vben提供的v-loading指令和Element Plus提供的v-loading指令二选一即可,此处false表示不注册Vben提供的v-loading指令 - spinning: 'spinning', - }); - - // 国际化 i18n 配置 - await setupI18n(app); - - // 配置 pinia-tore - await initStores(app, { namespace }); - - // 安装权限指令 - registerAccessDirective(app); - - // 初始化 tippy - const { initTippy } = await import('@vben/common-ui/es/tippy'); - initTippy(app); - - // 配置路由及路由守卫 - app.use(router); - - // 配置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/apps/web-ele/src/layouts/auth.vue b/apps/web-ele/src/layouts/auth.vue deleted file mode 100644 index 8ba66e85..00000000 --- a/apps/web-ele/src/layouts/auth.vue +++ /dev/null @@ -1,25 +0,0 @@ - - - diff --git a/apps/web-ele/src/layouts/basic.vue b/apps/web-ele/src/layouts/basic.vue deleted file mode 100644 index 805b8a73..00000000 --- a/apps/web-ele/src/layouts/basic.vue +++ /dev/null @@ -1,162 +0,0 @@ - - - diff --git a/apps/web-ele/src/layouts/index.ts b/apps/web-ele/src/layouts/index.ts deleted file mode 100644 index a4320780..00000000 --- a/apps/web-ele/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/apps/web-ele/src/locales/README.md b/apps/web-ele/src/locales/README.md deleted file mode 100644 index 7b451032..00000000 --- a/apps/web-ele/src/locales/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# locale - -每个app使用的国际化可能不同,这里用于扩展国际化的功能,例如扩展 dayjs、antd组件库的多语言切换,以及app本身的国际化文件。 diff --git a/apps/web-ele/src/locales/index.ts b/apps/web-ele/src/locales/index.ts deleted file mode 100644 index 57b87dfd..00000000 --- a/apps/web-ele/src/locales/index.ts +++ /dev/null @@ -1,102 +0,0 @@ -import type { Language } from 'element-plus/es/locale'; - -import type { App } from 'vue'; - -import type { LocaleSetupOptions, SupportedLanguagesType } from '@vben/locales'; - -import { ref } from 'vue'; - -import { - $t, - setupI18n as coreSetup, - loadLocalesMapFromDir, -} from '@vben/locales'; -import { preferences } from '@vben/preferences'; - -import dayjs from 'dayjs'; -import enLocale from 'element-plus/es/locale/lang/en'; -import defaultLocale from 'element-plus/es/locale/lang/zh-cn'; - -const elementLocale = ref(defaultLocale); - -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([loadElementLocale(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}`); - } -} - -/** - * 加载element-plus的语言包 - * @param lang - */ -async function loadElementLocale(lang: SupportedLanguagesType) { - switch (lang) { - case 'en-US': { - elementLocale.value = enLocale; - break; - } - case 'zh-CN': { - elementLocale.value = defaultLocale; - break; - } - } -} - -async function setupI18n(app: App, options: LocaleSetupOptions = {}) { - await coreSetup(app, { - defaultLocale: preferences.app.locale, - loadMessages, - missingWarn: !import.meta.env.PROD, - ...options, - }); -} - -export { $t, elementLocale, setupI18n }; diff --git a/apps/web-ele/src/locales/langs/en-US/demos.json b/apps/web-ele/src/locales/langs/en-US/demos.json deleted file mode 100644 index cc404511..00000000 --- a/apps/web-ele/src/locales/langs/en-US/demos.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "title": "Demos", - "elementPlus": "Element Plus", - "form": "Form", - "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/apps/web-ele/src/locales/langs/en-US/page.json b/apps/web-ele/src/locales/langs/en-US/page.json deleted file mode 100644 index 618a258c..00000000 --- a/apps/web-ele/src/locales/langs/en-US/page.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "auth": { - "login": "Login", - "register": "Register", - "codeLogin": "Code Login", - "qrcodeLogin": "Qr Code Login", - "forgetPassword": "Forget Password" - }, - "dashboard": { - "title": "Dashboard", - "analytics": "Analytics", - "workspace": "Workspace" - } -} diff --git a/apps/web-ele/src/locales/langs/zh-CN/demos.json b/apps/web-ele/src/locales/langs/zh-CN/demos.json deleted file mode 100644 index f8379c36..00000000 --- a/apps/web-ele/src/locales/langs/zh-CN/demos.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "title": "演示", - "elementPlus": "Element Plus", - "form": "表单演示", - "vben": { - "title": "项目", - "about": "关于", - "document": "文档", - "antdv": "Ant Design Vue 版本", - "naive-ui": "Naive UI 版本", - "element-plus": "Element Plus 版本", - "tdesign": "TDesign Vue 版本" - } -} diff --git a/apps/web-ele/src/locales/langs/zh-CN/page.json b/apps/web-ele/src/locales/langs/zh-CN/page.json deleted file mode 100644 index 4cb67081..00000000 --- a/apps/web-ele/src/locales/langs/zh-CN/page.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "auth": { - "login": "登录", - "register": "注册", - "codeLogin": "验证码登录", - "qrcodeLogin": "二维码登录", - "forgetPassword": "忘记密码" - }, - "dashboard": { - "title": "概览", - "analytics": "分析页", - "workspace": "工作台" - } -} diff --git a/apps/web-ele/src/main.ts b/apps/web-ele/src/main.ts deleted file mode 100644 index 5d728a02..00000000 --- a/apps/web-ele/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/apps/web-ele/src/preferences.ts b/apps/web-ele/src/preferences.ts deleted file mode 100644 index b2e9ace4..00000000 --- a/apps/web-ele/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/apps/web-ele/src/router/access.ts b/apps/web-ele/src/router/access.ts deleted file mode 100644 index 2d07c892..00000000 --- a/apps/web-ele/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 { ElMessage } from 'element-plus'; - -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 () => { - ElMessage({ - duration: 1500, - message: `${$t('common.loadingMenu')}...`, - }); - return await getAllMenusApi(); - }, - // 可以指定没有权限跳转403页面 - forbiddenComponent, - // 如果 route.meta.menuVisibleWithForbidden = true - layoutMap, - pageMap, - }); -} - -export { generateAccess }; diff --git a/apps/web-ele/src/router/guard.ts b/apps/web-ele/src/router/guard.ts deleted file mode 100644 index a1ad6d88..00000000 --- a/apps/web-ele/src/router/guard.ts +++ /dev/null @@ -1,133 +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); - const redirectPath = (from.query.redirect ?? - (to.path === preferences.app.defaultHomePath - ? userInfo.homePath || preferences.app.defaultHomePath - : to.fullPath)) as string; - - return { - ...router.resolve(decodeURIComponent(redirectPath)), - replace: true, - }; - }); -} - -/** - * 项目守卫配置 - * @param router - */ -function createRouterGuard(router: Router) { - /** 通用 */ - setupCommonGuard(router); - /** 权限访问 */ - setupAccessGuard(router); -} - -export { createRouterGuard }; diff --git a/apps/web-ele/src/router/index.ts b/apps/web-ele/src/router/index.ts deleted file mode 100644 index 48402303..00000000 --- a/apps/web-ele/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/apps/web-ele/src/router/routes/core.ts b/apps/web-ele/src/router/routes/core.ts deleted file mode 100644 index 949b0b65..00000000 --- a/apps/web-ele/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/apps/web-ele/src/router/routes/index.ts b/apps/web-ele/src/router/routes/index.ts deleted file mode 100644 index e6fb1440..00000000 --- a/apps/web-ele/src/router/routes/index.ts +++ /dev/null @@ -1,37 +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]; -export { accessRoutes, coreRouteNames, routes }; diff --git a/apps/web-ele/src/router/routes/modules/dashboard.ts b/apps/web-ele/src/router/routes/modules/dashboard.ts deleted file mode 100644 index 5254dc65..00000000 --- a/apps/web-ele/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/apps/web-ele/src/router/routes/modules/demos.ts b/apps/web-ele/src/router/routes/modules/demos.ts deleted file mode 100644 index 907ea3f4..00000000 --- a/apps/web-ele/src/router/routes/modules/demos.ts +++ /dev/null @@ -1,36 +0,0 @@ -import type { RouteRecordRaw } from 'vue-router'; - -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: { - title: $t('demos.elementPlus'), - }, - name: 'NaiveDemos', - path: '/demos/element', - component: () => import('#/views/demos/element/index.vue'), - }, - { - meta: { - title: $t('demos.form'), - }, - name: 'BasicForm', - path: '/demos/form', - component: () => import('#/views/demos/form/basic.vue'), - }, - ], - }, -]; - -export default routes; diff --git a/apps/web-ele/src/router/routes/modules/vben.ts b/apps/web-ele/src/router/routes/modules/vben.ts deleted file mode 100644 index 98bdaf32..00000000 --- a/apps/web-ele/src/router/routes/modules/vben.ts +++ /dev/null @@ -1,94 +0,0 @@ -import type { RouteRecordRaw } from 'vue-router'; - -import { - VBEN_ANT_PREVIEW_URL, - VBEN_DOC_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: '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: 'VbenAntd', - path: '/vben-admin/antd', - component: IFrameView, - meta: { - badgeType: 'dot', - icon: SvgAntdvLogoIcon, - link: VBEN_ANT_PREVIEW_URL, - title: $t('demos.vben.antdv'), - }, - }, - { - name: 'VbenTDesign', - path: '/vben-admin/tdesign', - component: IFrameView, - meta: { - badgeType: 'dot', - icon: SvgTDesignIcon, - link: VBEN_TD_PREVIEW_URL, - title: $t('demos.vben.tdesign'), - }, - }, - ], - }, - { - name: 'VbenAbout', - path: '/vben-admin/about', - component: () => import('#/views/_core/about/index.vue'), - meta: { - icon: 'lucide:copyright', - title: $t('demos.vben.about'), - order: 9999, - }, - }, -]; - -export default routes; diff --git a/apps/web-ele/src/store/auth.ts b/apps/web-ele/src/store/auth.ts deleted file mode 100644 index 74fadfe2..00000000 --- a/apps/web-ele/src/store/auth.ts +++ /dev/null @@ -1,119 +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 { ElNotification } from 'element-plus'; -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 登录表单数据 - */ - 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) { - // 将 accessToken 存储到 accessStore 中 - 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) { - ElNotification({ - message: `${$t('authentication.loginSuccessDesc')}:${userInfo?.realName}`, - title: $t('authentication.loginSuccess'), - type: 'success', - }); - } - } - } finally { - loginLoading.value = false; - } - - return { - userInfo, - }; - } - - async function logout(redirect: boolean = true) { - try { - await logoutApi(); - } catch { - // 不做任何处理 - } - 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/apps/web-ele/src/store/index.ts b/apps/web-ele/src/store/index.ts deleted file mode 100644 index 269586ee..00000000 --- a/apps/web-ele/src/store/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './auth'; diff --git a/apps/web-ele/src/views/_core/README.md b/apps/web-ele/src/views/_core/README.md deleted file mode 100644 index 8248afe6..00000000 --- a/apps/web-ele/src/views/_core/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# \_core - -此目录包含应用程序正常运行所需的基本视图。这些视图是应用程序布局中使用的视图。 diff --git a/apps/web-ele/src/views/_core/about/index.vue b/apps/web-ele/src/views/_core/about/index.vue deleted file mode 100644 index 0ee52433..00000000 --- a/apps/web-ele/src/views/_core/about/index.vue +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/apps/web-ele/src/views/_core/authentication/code-login.vue b/apps/web-ele/src/views/_core/authentication/code-login.vue deleted file mode 100644 index acfd1fd7..00000000 --- a/apps/web-ele/src/views/_core/authentication/code-login.vue +++ /dev/null @@ -1,69 +0,0 @@ - - - diff --git a/apps/web-ele/src/views/_core/authentication/forget-password.vue b/apps/web-ele/src/views/_core/authentication/forget-password.vue deleted file mode 100644 index fef0d427..00000000 --- a/apps/web-ele/src/views/_core/authentication/forget-password.vue +++ /dev/null @@ -1,43 +0,0 @@ - - - diff --git a/apps/web-ele/src/views/_core/authentication/login.vue b/apps/web-ele/src/views/_core/authentication/login.vue deleted file mode 100644 index 099e4c8c..00000000 --- a/apps/web-ele/src/views/_core/authentication/login.vue +++ /dev/null @@ -1,98 +0,0 @@ - - - diff --git a/apps/web-ele/src/views/_core/authentication/qrcode-login.vue b/apps/web-ele/src/views/_core/authentication/qrcode-login.vue deleted file mode 100644 index 23f5f2da..00000000 --- a/apps/web-ele/src/views/_core/authentication/qrcode-login.vue +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/apps/web-ele/src/views/_core/authentication/register.vue b/apps/web-ele/src/views/_core/authentication/register.vue deleted file mode 100644 index b1a5de72..00000000 --- a/apps/web-ele/src/views/_core/authentication/register.vue +++ /dev/null @@ -1,96 +0,0 @@ - - - diff --git a/apps/web-ele/src/views/_core/fallback/coming-soon.vue b/apps/web-ele/src/views/_core/fallback/coming-soon.vue deleted file mode 100644 index f394930f..00000000 --- a/apps/web-ele/src/views/_core/fallback/coming-soon.vue +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/apps/web-ele/src/views/_core/fallback/forbidden.vue b/apps/web-ele/src/views/_core/fallback/forbidden.vue deleted file mode 100644 index 8ea65fed..00000000 --- a/apps/web-ele/src/views/_core/fallback/forbidden.vue +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/apps/web-ele/src/views/_core/fallback/internal-error.vue b/apps/web-ele/src/views/_core/fallback/internal-error.vue deleted file mode 100644 index 819a47d5..00000000 --- a/apps/web-ele/src/views/_core/fallback/internal-error.vue +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/apps/web-ele/src/views/_core/fallback/not-found.vue b/apps/web-ele/src/views/_core/fallback/not-found.vue deleted file mode 100644 index 4d178e9c..00000000 --- a/apps/web-ele/src/views/_core/fallback/not-found.vue +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/apps/web-ele/src/views/_core/fallback/offline.vue b/apps/web-ele/src/views/_core/fallback/offline.vue deleted file mode 100644 index 5de4a88d..00000000 --- a/apps/web-ele/src/views/_core/fallback/offline.vue +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/apps/web-ele/src/views/dashboard/analytics/analytics-trends.vue b/apps/web-ele/src/views/dashboard/analytics/analytics-trends.vue deleted file mode 100644 index f1f0b232..00000000 --- a/apps/web-ele/src/views/dashboard/analytics/analytics-trends.vue +++ /dev/null @@ -1,98 +0,0 @@ - - - diff --git a/apps/web-ele/src/views/dashboard/analytics/analytics-visits-data.vue b/apps/web-ele/src/views/dashboard/analytics/analytics-visits-data.vue deleted file mode 100644 index 190fb41f..00000000 --- a/apps/web-ele/src/views/dashboard/analytics/analytics-visits-data.vue +++ /dev/null @@ -1,82 +0,0 @@ - - - diff --git a/apps/web-ele/src/views/dashboard/analytics/analytics-visits-sales.vue b/apps/web-ele/src/views/dashboard/analytics/analytics-visits-sales.vue deleted file mode 100644 index 02f50912..00000000 --- a/apps/web-ele/src/views/dashboard/analytics/analytics-visits-sales.vue +++ /dev/null @@ -1,46 +0,0 @@ - - - diff --git a/apps/web-ele/src/views/dashboard/analytics/analytics-visits-source.vue b/apps/web-ele/src/views/dashboard/analytics/analytics-visits-source.vue deleted file mode 100644 index 0915c7af..00000000 --- a/apps/web-ele/src/views/dashboard/analytics/analytics-visits-source.vue +++ /dev/null @@ -1,65 +0,0 @@ - - - diff --git a/apps/web-ele/src/views/dashboard/analytics/analytics-visits.vue b/apps/web-ele/src/views/dashboard/analytics/analytics-visits.vue deleted file mode 100644 index 7e0f1013..00000000 --- a/apps/web-ele/src/views/dashboard/analytics/analytics-visits.vue +++ /dev/null @@ -1,55 +0,0 @@ - - - diff --git a/apps/web-ele/src/views/dashboard/analytics/index.vue b/apps/web-ele/src/views/dashboard/analytics/index.vue deleted file mode 100644 index 5e3d6d28..00000000 --- a/apps/web-ele/src/views/dashboard/analytics/index.vue +++ /dev/null @@ -1,90 +0,0 @@ - - - diff --git a/apps/web-ele/src/views/dashboard/workspace/index.vue b/apps/web-ele/src/views/dashboard/workspace/index.vue deleted file mode 100644 index b95d6138..00000000 --- a/apps/web-ele/src/views/dashboard/workspace/index.vue +++ /dev/null @@ -1,266 +0,0 @@ - - - diff --git a/apps/web-ele/src/views/demos/element/index.vue b/apps/web-ele/src/views/demos/element/index.vue deleted file mode 100644 index 0a7012d6..00000000 --- a/apps/web-ele/src/views/demos/element/index.vue +++ /dev/null @@ -1,117 +0,0 @@ - - - diff --git a/apps/web-ele/src/views/demos/form/basic.vue b/apps/web-ele/src/views/demos/form/basic.vue deleted file mode 100644 index 0ecab586..00000000 --- a/apps/web-ele/src/views/demos/form/basic.vue +++ /dev/null @@ -1,191 +0,0 @@ - - diff --git a/apps/web-ele/tailwind.config.mjs b/apps/web-ele/tailwind.config.mjs deleted file mode 100644 index f17f556f..00000000 --- a/apps/web-ele/tailwind.config.mjs +++ /dev/null @@ -1 +0,0 @@ -export { default } from '@vben/tailwind-config'; diff --git a/apps/web-ele/tsconfig.json b/apps/web-ele/tsconfig.json deleted file mode 100644 index 02c287fe..00000000 --- a/apps/web-ele/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/apps/web-ele/tsconfig.node.json b/apps/web-ele/tsconfig.node.json deleted file mode 100644 index c2f0d86c..00000000 --- a/apps/web-ele/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/apps/web-ele/vite.config.mts b/apps/web-ele/vite.config.mts deleted file mode 100644 index 9f1e7235..00000000 --- a/apps/web-ele/vite.config.mts +++ /dev/null @@ -1,27 +0,0 @@ -import { defineConfig } from '@vben/vite-config'; - -import ElementPlus from 'unplugin-element-plus/vite'; - -export default defineConfig(async () => { - return { - application: {}, - vite: { - plugins: [ - ElementPlus({ - format: 'esm', - }), - ], - server: { - proxy: { - '/api': { - changeOrigin: true, - rewrite: (path) => path.replace(/^\/api/, ''), - // mock代理目标地址 - target: 'http://localhost:5320/api', - ws: true, - }, - }, - }, - }, - }; -}); diff --git a/apps/web-naive/.env b/apps/web-naive/.env deleted file mode 100644 index 213b52ce..00000000 --- a/apps/web-naive/.env +++ /dev/null @@ -1,8 +0,0 @@ -# 应用标题 -VITE_APP_TITLE=Vben Admin Naive - -# 应用命名空间,用于缓存、store等功能的前缀,确保隔离 -VITE_APP_NAMESPACE=vben-web-naive - -# 对store进行加密的密钥,在将store持久化到localStorage时会使用该密钥进行加密 -VITE_APP_STORE_SECURE_KEY=please-replace-me-with-your-own-key diff --git a/apps/web-naive/.env.analyze b/apps/web-naive/.env.analyze deleted file mode 100644 index ffafa8dd..00000000 --- a/apps/web-naive/.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/apps/web-naive/.env.development b/apps/web-naive/.env.development deleted file mode 100644 index 11c5254a..00000000 --- a/apps/web-naive/.env.development +++ /dev/null @@ -1,16 +0,0 @@ -# 端口号 -VITE_PORT=5888 - -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 diff --git a/apps/web-naive/.env.production b/apps/web-naive/.env.production deleted file mode 100644 index 5375847a..00000000 --- a/apps/web-naive/.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/apps/web-naive/index.html b/apps/web-naive/index.html deleted file mode 100644 index 7ea63841..00000000 --- a/apps/web-naive/index.html +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - <%= VITE_APP_TITLE %> - - - - -
- - - diff --git a/apps/web-naive/package.json b/apps/web-naive/package.json deleted file mode 100644 index ff69374f..00000000 --- a/apps/web-naive/package.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "name": "@vben/web-naive", - "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": "apps/web-naive" - }, - "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" - }, - "imports": { - "#/*": "./src/*" - }, - "dependencies": { - "@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:", - "naive-ui": "catalog:", - "pinia": "catalog:", - "vue": "catalog:", - "vue-router": "catalog:" - } -} diff --git a/apps/web-naive/postcss.config.mjs b/apps/web-naive/postcss.config.mjs deleted file mode 100644 index 3d807045..00000000 --- a/apps/web-naive/postcss.config.mjs +++ /dev/null @@ -1 +0,0 @@ -export { default } from '@vben/tailwind-config/postcss'; diff --git a/apps/web-naive/public/favicon.ico b/apps/web-naive/public/favicon.ico deleted file mode 100644 index fcf9818e2cf855039b272bdbfbb202d3ff3fa159..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5430 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 - import('naive-ui/es/button').then((res) => res.NButton), -); -const NCheckbox = defineAsyncComponent(() => - import('naive-ui/es/checkbox').then((res) => res.NCheckbox), -); -const NCheckboxGroup = defineAsyncComponent(() => - import('naive-ui/es/checkbox').then((res) => res.NCheckboxGroup), -); -const NDatePicker = defineAsyncComponent(() => - import('naive-ui/es/date-picker').then((res) => res.NDatePicker), -); -const NDivider = defineAsyncComponent(() => - import('naive-ui/es/divider').then((res) => res.NDivider), -); -const NInput = defineAsyncComponent(() => - import('naive-ui/es/input').then((res) => res.NInput), -); -const NInputNumber = defineAsyncComponent(() => - import('naive-ui/es/input-number').then((res) => res.NInputNumber), -); -const NRadio = defineAsyncComponent(() => - import('naive-ui/es/radio').then((res) => res.NRadio), -); -const NRadioButton = defineAsyncComponent(() => - import('naive-ui/es/radio').then((res) => res.NRadioButton), -); -const NRadioGroup = defineAsyncComponent(() => - import('naive-ui/es/radio').then((res) => res.NRadioGroup), -); -const NSelect = defineAsyncComponent(() => - import('naive-ui/es/select').then((res) => res.NSelect), -); -const NSpace = defineAsyncComponent(() => - import('naive-ui/es/space').then((res) => res.NSpace), -); -const NSwitch = defineAsyncComponent(() => - import('naive-ui/es/switch').then((res) => res.NSwitch), -); -const NTimePicker = defineAsyncComponent(() => - import('naive-ui/es/time-picker').then((res) => res.NTimePicker), -); -const NTreeSelect = defineAsyncComponent(() => - import('naive-ui/es/tree-select').then((res) => res.NTreeSelect), -); -const NUpload = defineAsyncComponent(() => - import('naive-ui/es/upload').then((res) => res.NUpload), -); - -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, - ); - }, - }); -}; - -// 这里需要自行根据业务组件库进行适配,需要用到的组件都需要在这里类型说明 -export type ComponentType = - | 'ApiSelect' - | 'ApiTreeSelect' - | 'Checkbox' - | 'CheckboxGroup' - | 'DatePicker' - | 'Divider' - | 'IconPicker' - | 'Input' - | 'InputNumber' - | 'RadioGroup' - | 'Select' - | 'Space' - | 'Switch' - | 'TimePicker' - | 'TreeSelect' - | 'Upload' - | BaseFormComponentType; - -async function initComponentAdapter() { - const components: Partial> = { - // 如果你的组件体积比较大,可以使用异步加载 - // Button: () => - // import('xxx').then((res) => res.Button), - - ApiSelect: withDefaultPlaceholder( - { - ...ApiComponent, - name: 'ApiSelect', - }, - 'select', - { - component: NSelect, - modelPropName: 'value', - }, - ), - ApiTreeSelect: withDefaultPlaceholder( - { - ...ApiComponent, - name: 'ApiTreeSelect', - }, - 'select', - { - component: NTreeSelect, - nodeKey: 'value', - loadingSlot: 'arrow', - keyField: 'value', - modelPropName: 'value', - optionsPropName: 'options', - visibleEvent: 'onVisibleChange', - }, - ), - Checkbox: NCheckbox, - CheckboxGroup: (props, { attrs, slots }) => { - let defaultSlot; - if (Reflect.has(slots, 'default')) { - defaultSlot = slots.default; - } else { - const { options } = attrs; - if (Array.isArray(options)) { - defaultSlot = () => options.map((option) => h(NCheckbox, option)); - } - } - return h( - NCheckboxGroup, - { ...props, ...attrs }, - { default: defaultSlot }, - ); - }, - DatePicker: NDatePicker, - // 自定义默认按钮 - DefaultButton: (props, { attrs, slots }) => { - return h(NButton, { ...props, attrs, type: 'default' }, slots); - }, - // 自定义主要按钮 - PrimaryButton: (props, { attrs, slots }) => { - return h(NButton, { ...props, attrs, type: 'primary' }, slots); - }, - Divider: NDivider, - IconPicker: withDefaultPlaceholder(IconPicker, 'select', { - iconSlot: 'suffix', - inputComponent: NInput, - }), - Input: withDefaultPlaceholder(NInput, 'input'), - InputNumber: withDefaultPlaceholder(NInputNumber, 'input'), - RadioGroup: (props, { attrs, slots }) => { - let defaultSlot; - if (Reflect.has(slots, 'default')) { - defaultSlot = slots.default; - } else { - const { options } = attrs; - if (Array.isArray(options)) { - defaultSlot = () => - options.map((option) => - h(attrs.isButton ? NRadioButton : NRadio, option), - ); - } - } - const groupRender = h( - NRadioGroup, - { ...props, ...attrs }, - { default: defaultSlot }, - ); - return attrs.isButton - ? h(NSpace, { vertical: true }, () => groupRender) - : groupRender; - }, - Select: withDefaultPlaceholder(NSelect, 'select'), - Space: NSpace, - Switch: NSwitch, - TimePicker: NTimePicker, - TreeSelect: withDefaultPlaceholder(NTreeSelect, 'select'), - Upload: NUpload, - }; - - // 将组件注册到全局共享状态中 - globalShareState.setComponents(components); - - // 定义全局共享状态中的消息提示 - globalShareState.defineMessage({ - // 复制成功消息提示 - copyPreferencesSuccess: (title, content) => { - message.success(content || title, { - duration: 0, - }); - }, - }); -} - -export { initComponentAdapter }; diff --git a/apps/web-naive/src/adapter/form.ts b/apps/web-naive/src/adapter/form.ts deleted file mode 100644 index 9de44a01..00000000 --- a/apps/web-naive/src/adapter/form.ts +++ /dev/null @@ -1,45 +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: { - // naive-ui组件的空值为null,不能是undefined,否则重置表单时不生效 - emptyStateValue: null, - baseModelPropName: 'value', - modelPropNameMap: { - Checkbox: 'checked', - Radio: '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/apps/web-naive/src/adapter/naive.ts b/apps/web-naive/src/adapter/naive.ts deleted file mode 100644 index 1eb7b7b6..00000000 --- a/apps/web-naive/src/adapter/naive.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { computed } from 'vue'; - -import { preferences } from '@vben/preferences'; -import '@vben/styles'; - -import { createDiscreteApi, darkTheme, lightTheme } from 'naive-ui'; - -const themeOverridesProviderProps = computed(() => ({ - themeOverrides: preferences.theme.mode === 'light' ? lightTheme : darkTheme, -})); - -const themeProviderProps = computed(() => ({ - theme: preferences.theme.mode === 'light' ? lightTheme : darkTheme, -})); - -export const { dialog, loadingBar, message, modal, notification } = - createDiscreteApi( - ['message', 'dialog', 'notification', 'loadingBar', 'modal'], - { - configProviderProps: themeProviderProps, - loadingBarProviderProps: themeOverridesProviderProps, - messageProviderProps: themeOverridesProviderProps, - notificationProviderProps: themeOverridesProviderProps, - }, - ); diff --git a/apps/web-naive/src/adapter/vxe-table.ts b/apps/web-naive/src/adapter/vxe-table.ts deleted file mode 100644 index 3bad067c..00000000 --- a/apps/web-naive/src/adapter/vxe-table.ts +++ /dev/null @@ -1,69 +0,0 @@ -import type { VxeTableGridOptions } from '@vben/plugins/vxe-table'; - -import { h } from 'vue'; - -import { setupVbenVxeTable, useVbenVxeGrid } from '@vben/plugins/vxe-table'; - -import { NButton, NImage } from 'naive-ui'; - -import { useVbenForm } from './form'; - -setupVbenVxeTable({ - configVxeTable: (vxeUI) => { - vxeUI.setConfig({ - grid: { - align: 'center', - border: false, - columnConfig: { - resizable: true, - }, - minHeight: 180, - formConfig: { - // 全局禁用vxe-table的表单配置,使用formOptions - enabled: false, - }, - proxyConfig: { - autoLoad: true, - response: { - result: 'items', - total: 'total', - list: 'items', - }, - showActiveMsg: true, - showResponseMsg: false, - }, - round: true, - showOverflow: true, - size: 'small', - } as VxeTableGridOptions, - }); - - // 表格配置项可以用 cellRender: { name: 'CellImage' }, - vxeUI.renderer.add('CellImage', { - renderTableDefault(_renderOpts, params) { - const { column, row } = params; - return h(NImage, { src: row[column.field] }); - }, - }); - - // 表格配置项可以用 cellRender: { name: 'CellLink' }, - vxeUI.renderer.add('CellLink', { - renderTableDefault(renderOpts) { - const { props } = renderOpts; - return h( - NButton, - { size: 'small', type: 'primary', quaternary: true }, - { default: () => props?.text }, - ); - }, - }); - - // 这里可以自行扩展 vxe-table 的全局配置,比如自定义格式化 - // vxeUI.formats.add - }, - useVbenForm, -}); - -export { useVbenVxeGrid }; - -export type * from '@vben/plugins/vxe-table'; diff --git a/apps/web-naive/src/api/core/auth.ts b/apps/web-naive/src/api/core/auth.ts deleted file mode 100644 index 71d9f994..00000000 --- a/apps/web-naive/src/api/core/auth.ts +++ /dev/null @@ -1,51 +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); -} - -/** - * 刷新accessToken - */ -export async function refreshTokenApi() { - return baseRequestClient.post('/auth/refresh', { - withCredentials: true, - }); -} - -/** - * 退出登录 - */ -export async function logoutApi() { - return baseRequestClient.post('/auth/logout', { - withCredentials: true, - }); -} - -/** - * 获取用户权限码 - */ -export async function getAccessCodesApi() { - return requestClient.get('/auth/codes'); -} diff --git a/apps/web-naive/src/api/core/index.ts b/apps/web-naive/src/api/core/index.ts deleted file mode 100644 index 28a5aef4..00000000 --- a/apps/web-naive/src/api/core/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './auth'; -export * from './menu'; -export * from './user'; diff --git a/apps/web-naive/src/api/core/menu.ts b/apps/web-naive/src/api/core/menu.ts deleted file mode 100644 index 9ef60b11..00000000 --- a/apps/web-naive/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/apps/web-naive/src/api/core/user.ts b/apps/web-naive/src/api/core/user.ts deleted file mode 100644 index 7e28ea84..00000000 --- a/apps/web-naive/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/apps/web-naive/src/api/index.ts b/apps/web-naive/src/api/index.ts deleted file mode 100644 index 4b0e0413..00000000 --- a/apps/web-naive/src/api/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './core'; diff --git a/apps/web-naive/src/api/request.ts b/apps/web-naive/src/api/request.ts deleted file mode 100644 index f8fbacc0..00000000 --- a/apps/web-naive/src/api/request.ts +++ /dev/null @@ -1,112 +0,0 @@ -/** - * 该文件可自行根据业务逻辑进行调整 - */ -import type { 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 { message } from '#/adapter/naive'; -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, - }); - - /** - * 重新认证逻辑 - */ - 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 }); diff --git a/apps/web-naive/src/app.vue b/apps/web-naive/src/app.vue deleted file mode 100644 index 23983c55..00000000 --- a/apps/web-naive/src/app.vue +++ /dev/null @@ -1,56 +0,0 @@ - - - diff --git a/apps/web-naive/src/bootstrap.ts b/apps/web-naive/src/bootstrap.ts deleted file mode 100644 index df0b2cbb..00000000 --- a/apps/web-naive/src/bootstrap.ts +++ /dev/null @@ -1,76 +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/naive'; - -import { useTitle } from '@vueuse/core'; - -import { $t, setupI18n } from '#/locales'; - -import { initComponentAdapter } from './adapter/component'; -import { initSetupVbenForm } from './adapter/form'; -import App from './app.vue'; -import { router } from './router'; - -async function bootstrap(namespace: string) { - // 初始化组件适配器 - await initComponentAdapter(); - - // 初始化表单组件 - await initSetupVbenForm(); - - // // 设置弹窗的默认配置 - // setDefaultModalProps({ - // fullscreenButton: false, - // }); - // // 设置抽屉的默认配置 - // setDefaultDrawerProps({ - // // zIndex: 2000, - // }); - - const app = createApp(App); - - // 注册v-loading指令 - registerLoadingDirective(app, { - loading: 'loading', // 在这里可以自定义指令名称,也可以明确提供false表示不注册这个指令 - spinning: 'spinning', - }); - - // 国际化 i18n 配置 - await setupI18n(app); - - // 配置 pinia-tore - await initStores(app, { namespace }); - - // 安装权限指令 - registerAccessDirective(app); - - // 初始化 tippy - const { initTippy } = await import('@vben/common-ui/es/tippy'); - initTippy(app); - - // 配置路由及路由守卫 - app.use(router); - - // 配置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/apps/web-naive/src/layouts/auth.vue b/apps/web-naive/src/layouts/auth.vue deleted file mode 100644 index 8ba66e85..00000000 --- a/apps/web-naive/src/layouts/auth.vue +++ /dev/null @@ -1,25 +0,0 @@ - - - diff --git a/apps/web-naive/src/layouts/basic.vue b/apps/web-naive/src/layouts/basic.vue deleted file mode 100644 index 0e9747be..00000000 --- a/apps/web-naive/src/layouts/basic.vue +++ /dev/null @@ -1,163 +0,0 @@ - - - diff --git a/apps/web-naive/src/layouts/index.ts b/apps/web-naive/src/layouts/index.ts deleted file mode 100644 index a4320780..00000000 --- a/apps/web-naive/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/apps/web-naive/src/locales/README.md b/apps/web-naive/src/locales/README.md deleted file mode 100644 index 7b451032..00000000 --- a/apps/web-naive/src/locales/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# locale - -每个app使用的国际化可能不同,这里用于扩展国际化的功能,例如扩展 dayjs、antd组件库的多语言切换,以及app本身的国际化文件。 diff --git a/apps/web-naive/src/locales/index.ts b/apps/web-naive/src/locales/index.ts deleted file mode 100644 index 58f63c10..00000000 --- a/apps/web-naive/src/locales/index.ts +++ /dev/null @@ -1,38 +0,0 @@ -import type { App } from 'vue'; - -import type { LocaleSetupOptions, SupportedLanguagesType } from '@vben/locales'; - -import { - $t, - setupI18n as coreSetup, - loadLocalesMapFromDir, -} from '@vben/locales'; -import { preferences } from '@vben/preferences'; - -const modules = import.meta.glob('./langs/**/*.json'); - -const localesMap = loadLocalesMapFromDir( - /\.\/langs\/([^/]+)\/(.*)\.json$/, - modules, -); - -/** - * 加载应用特有的语言包 - * 这里也可以改造为从服务端获取翻译数据 - * @param lang - */ -async function loadMessages(lang: SupportedLanguagesType) { - const appLocaleMessages = await localesMap[lang]?.(); - return appLocaleMessages?.default; -} - -async function setupI18n(app: App, options: LocaleSetupOptions = {}) { - await coreSetup(app, { - defaultLocale: preferences.app.locale, - loadMessages, - missingWarn: !import.meta.env.PROD, - ...options, - }); -} - -export { $t, setupI18n }; diff --git a/apps/web-naive/src/locales/langs/en-US/demos.json b/apps/web-naive/src/locales/langs/en-US/demos.json deleted file mode 100644 index 3128b0be..00000000 --- a/apps/web-naive/src/locales/langs/en-US/demos.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "title": "Demos", - "naive": "Naive UI", - "table": "Table", - "form": "Form", - "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/apps/web-naive/src/locales/langs/en-US/page.json b/apps/web-naive/src/locales/langs/en-US/page.json deleted file mode 100644 index 618a258c..00000000 --- a/apps/web-naive/src/locales/langs/en-US/page.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "auth": { - "login": "Login", - "register": "Register", - "codeLogin": "Code Login", - "qrcodeLogin": "Qr Code Login", - "forgetPassword": "Forget Password" - }, - "dashboard": { - "title": "Dashboard", - "analytics": "Analytics", - "workspace": "Workspace" - } -} diff --git a/apps/web-naive/src/locales/langs/zh-CN/demos.json b/apps/web-naive/src/locales/langs/zh-CN/demos.json deleted file mode 100644 index 3c3957a9..00000000 --- a/apps/web-naive/src/locales/langs/zh-CN/demos.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "title": "演示", - "naive": "Naive UI", - "table": "Table", - "form": "表单", - "vben": { - "title": "项目", - "about": "关于", - "document": "文档", - "antdv": "Ant Design Vue 版本", - "naive-ui": "Naive UI 版本", - "element-plus": "Element Plus 版本", - "tdesign": "TDesign Vue 版本" - } -} diff --git a/apps/web-naive/src/locales/langs/zh-CN/page.json b/apps/web-naive/src/locales/langs/zh-CN/page.json deleted file mode 100644 index 4cb67081..00000000 --- a/apps/web-naive/src/locales/langs/zh-CN/page.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "auth": { - "login": "登录", - "register": "注册", - "codeLogin": "验证码登录", - "qrcodeLogin": "二维码登录", - "forgetPassword": "忘记密码" - }, - "dashboard": { - "title": "概览", - "analytics": "分析页", - "workspace": "工作台" - } -} diff --git a/apps/web-naive/src/main.ts b/apps/web-naive/src/main.ts deleted file mode 100644 index 5d728a02..00000000 --- a/apps/web-naive/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/apps/web-naive/src/preferences.ts b/apps/web-naive/src/preferences.ts deleted file mode 100644 index b2e9ace4..00000000 --- a/apps/web-naive/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/apps/web-naive/src/router/access.ts b/apps/web-naive/src/router/access.ts deleted file mode 100644 index 7a80bac0..00000000 --- a/apps/web-naive/src/router/access.ts +++ /dev/null @@ -1,40 +0,0 @@ -import type { - ComponentRecordType, - GenerateMenuAndRoutesOptions, -} from '@vben/types'; - -import { generateAccessible } from '@vben/access'; -import { preferences } from '@vben/preferences'; - -import { message } from '#/adapter/naive'; -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(`${$t('common.loadingMenu')}...`, { - duration: 1.5, - }); - return await getAllMenusApi(); - }, - // 可以指定没有权限跳转403页面 - forbiddenComponent, - // 如果 route.meta.menuVisibleWithForbidden = true - layoutMap, - pageMap, - }); -} - -export { generateAccess }; diff --git a/apps/web-naive/src/router/guard.ts b/apps/web-naive/src/router/guard.ts deleted file mode 100644 index 28d1cea7..00000000 --- a/apps/web-naive/src/router/guard.ts +++ /dev/null @@ -1,132 +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); - const redirectPath = (from.query.redirect ?? - (to.path === preferences.app.defaultHomePath - ? userInfo.homePath || preferences.app.defaultHomePath - : to.fullPath)) as string; - - return { - ...router.resolve(decodeURIComponent(redirectPath)), - replace: true, - }; - }); -} - -/** - * 项目守卫配置 - * @param router - */ -function createRouterGuard(router: Router) { - /** 通用 */ - setupCommonGuard(router); - /** 权限访问 */ - setupAccessGuard(router); -} - -export { createRouterGuard }; diff --git a/apps/web-naive/src/router/index.ts b/apps/web-naive/src/router/index.ts deleted file mode 100644 index 48402303..00000000 --- a/apps/web-naive/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/apps/web-naive/src/router/routes/core.ts b/apps/web-naive/src/router/routes/core.ts deleted file mode 100644 index 949b0b65..00000000 --- a/apps/web-naive/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/apps/web-naive/src/router/routes/index.ts b/apps/web-naive/src/router/routes/index.ts deleted file mode 100644 index e6fb1440..00000000 --- a/apps/web-naive/src/router/routes/index.ts +++ /dev/null @@ -1,37 +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]; -export { accessRoutes, coreRouteNames, routes }; diff --git a/apps/web-naive/src/router/routes/modules/dashboard.ts b/apps/web-naive/src/router/routes/modules/dashboard.ts deleted file mode 100644 index 5254dc65..00000000 --- a/apps/web-naive/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/apps/web-naive/src/router/routes/modules/demos.ts b/apps/web-naive/src/router/routes/modules/demos.ts deleted file mode 100644 index 5e49ffa0..00000000 --- a/apps/web-naive/src/router/routes/modules/demos.ts +++ /dev/null @@ -1,44 +0,0 @@ -import type { RouteRecordRaw } from 'vue-router'; - -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: { - title: $t('demos.naive'), - }, - name: 'NaiveDemos', - path: '/demos/naive', - component: () => import('#/views/demos/naive/index.vue'), - }, - { - meta: { - title: $t('demos.table'), - }, - name: 'Table', - path: '/demos/table', - component: () => import('#/views/demos/table/index.vue'), - }, - { - meta: { - title: $t('demos.form'), - }, - name: 'Form', - path: '/demos/form', - component: () => import('#/views/demos/form/basic.vue'), - }, - ], - }, -]; - -export default routes; diff --git a/apps/web-naive/src/router/routes/modules/vben.ts b/apps/web-naive/src/router/routes/modules/vben.ts deleted file mode 100644 index 8f8803b3..00000000 --- a/apps/web-naive/src/router/routes/modules/vben.ts +++ /dev/null @@ -1,94 +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_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: 'VbenAntd', - path: '/vben-admin/antd', - component: IFrameView, - meta: { - badgeType: 'dot', - icon: SvgAntdvLogoIcon, - link: VBEN_ANT_PREVIEW_URL, - title: $t('demos.vben.antdv'), - }, - }, - { - name: 'VbenTDesign', - path: '/vben-admin/tdesign', - component: IFrameView, - meta: { - badgeType: 'dot', - icon: SvgTDesignIcon, - link: VBEN_TD_PREVIEW_URL, - title: $t('demos.vben.tdesign'), - }, - }, - { - 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: 'VbenAbout', - path: '/vben-admin/about', - component: () => import('#/views/_core/about/index.vue'), - meta: { - icon: 'lucide:copyright', - title: $t('demos.vben.about'), - order: 9999, - }, - }, -]; - -export default routes; diff --git a/apps/web-naive/src/store/auth.ts b/apps/web-naive/src/store/auth.ts deleted file mode 100644 index 0ff050b3..00000000 --- a/apps/web-naive/src/store/auth.ts +++ /dev/null @@ -1,119 +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 { defineStore } from 'pinia'; - -import { notification } from '#/adapter/naive'; -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 登录表单数据 - */ - 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) { - // 将 accessToken 存储到 accessStore 中 - 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({ - content: $t('authentication.loginSuccess'), - description: `${$t('authentication.loginSuccessDesc')}:${userInfo?.realName}`, - duration: 3000, - }); - } - } - } finally { - loginLoading.value = false; - } - - return { - userInfo, - }; - } - - async function logout(redirect: boolean = true) { - try { - await logoutApi(); - } catch { - // 不做任何处理 - } - 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/apps/web-naive/src/store/index.ts b/apps/web-naive/src/store/index.ts deleted file mode 100644 index 269586ee..00000000 --- a/apps/web-naive/src/store/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './auth'; diff --git a/apps/web-naive/src/views/_core/README.md b/apps/web-naive/src/views/_core/README.md deleted file mode 100644 index 8248afe6..00000000 --- a/apps/web-naive/src/views/_core/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# \_core - -此目录包含应用程序正常运行所需的基本视图。这些视图是应用程序布局中使用的视图。 diff --git a/apps/web-naive/src/views/_core/about/index.vue b/apps/web-naive/src/views/_core/about/index.vue deleted file mode 100644 index 0ee52433..00000000 --- a/apps/web-naive/src/views/_core/about/index.vue +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/apps/web-naive/src/views/_core/authentication/code-login.vue b/apps/web-naive/src/views/_core/authentication/code-login.vue deleted file mode 100644 index acfd1fd7..00000000 --- a/apps/web-naive/src/views/_core/authentication/code-login.vue +++ /dev/null @@ -1,69 +0,0 @@ - - - diff --git a/apps/web-naive/src/views/_core/authentication/forget-password.vue b/apps/web-naive/src/views/_core/authentication/forget-password.vue deleted file mode 100644 index fef0d427..00000000 --- a/apps/web-naive/src/views/_core/authentication/forget-password.vue +++ /dev/null @@ -1,43 +0,0 @@ - - - diff --git a/apps/web-naive/src/views/_core/authentication/login.vue b/apps/web-naive/src/views/_core/authentication/login.vue deleted file mode 100644 index 099e4c8c..00000000 --- a/apps/web-naive/src/views/_core/authentication/login.vue +++ /dev/null @@ -1,98 +0,0 @@ - - - diff --git a/apps/web-naive/src/views/_core/authentication/qrcode-login.vue b/apps/web-naive/src/views/_core/authentication/qrcode-login.vue deleted file mode 100644 index 23f5f2da..00000000 --- a/apps/web-naive/src/views/_core/authentication/qrcode-login.vue +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/apps/web-naive/src/views/_core/authentication/register.vue b/apps/web-naive/src/views/_core/authentication/register.vue deleted file mode 100644 index daf89c44..00000000 --- a/apps/web-naive/src/views/_core/authentication/register.vue +++ /dev/null @@ -1,96 +0,0 @@ - - - diff --git a/apps/web-naive/src/views/_core/fallback/coming-soon.vue b/apps/web-naive/src/views/_core/fallback/coming-soon.vue deleted file mode 100644 index f394930f..00000000 --- a/apps/web-naive/src/views/_core/fallback/coming-soon.vue +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/apps/web-naive/src/views/_core/fallback/forbidden.vue b/apps/web-naive/src/views/_core/fallback/forbidden.vue deleted file mode 100644 index 8ea65fed..00000000 --- a/apps/web-naive/src/views/_core/fallback/forbidden.vue +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/apps/web-naive/src/views/_core/fallback/internal-error.vue b/apps/web-naive/src/views/_core/fallback/internal-error.vue deleted file mode 100644 index 819a47d5..00000000 --- a/apps/web-naive/src/views/_core/fallback/internal-error.vue +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/apps/web-naive/src/views/_core/fallback/not-found.vue b/apps/web-naive/src/views/_core/fallback/not-found.vue deleted file mode 100644 index 4d178e9c..00000000 --- a/apps/web-naive/src/views/_core/fallback/not-found.vue +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/apps/web-naive/src/views/_core/fallback/offline.vue b/apps/web-naive/src/views/_core/fallback/offline.vue deleted file mode 100644 index 5de4a88d..00000000 --- a/apps/web-naive/src/views/_core/fallback/offline.vue +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/apps/web-naive/src/views/dashboard/analytics/analytics-trends.vue b/apps/web-naive/src/views/dashboard/analytics/analytics-trends.vue deleted file mode 100644 index f1f0b232..00000000 --- a/apps/web-naive/src/views/dashboard/analytics/analytics-trends.vue +++ /dev/null @@ -1,98 +0,0 @@ - - - diff --git a/apps/web-naive/src/views/dashboard/analytics/analytics-visits-data.vue b/apps/web-naive/src/views/dashboard/analytics/analytics-visits-data.vue deleted file mode 100644 index 190fb41f..00000000 --- a/apps/web-naive/src/views/dashboard/analytics/analytics-visits-data.vue +++ /dev/null @@ -1,82 +0,0 @@ - - - diff --git a/apps/web-naive/src/views/dashboard/analytics/analytics-visits-sales.vue b/apps/web-naive/src/views/dashboard/analytics/analytics-visits-sales.vue deleted file mode 100644 index 02f50912..00000000 --- a/apps/web-naive/src/views/dashboard/analytics/analytics-visits-sales.vue +++ /dev/null @@ -1,46 +0,0 @@ - - - diff --git a/apps/web-naive/src/views/dashboard/analytics/analytics-visits-source.vue b/apps/web-naive/src/views/dashboard/analytics/analytics-visits-source.vue deleted file mode 100644 index 0915c7af..00000000 --- a/apps/web-naive/src/views/dashboard/analytics/analytics-visits-source.vue +++ /dev/null @@ -1,65 +0,0 @@ - - - diff --git a/apps/web-naive/src/views/dashboard/analytics/analytics-visits.vue b/apps/web-naive/src/views/dashboard/analytics/analytics-visits.vue deleted file mode 100644 index 7e0f1013..00000000 --- a/apps/web-naive/src/views/dashboard/analytics/analytics-visits.vue +++ /dev/null @@ -1,55 +0,0 @@ - - - diff --git a/apps/web-naive/src/views/dashboard/analytics/index.vue b/apps/web-naive/src/views/dashboard/analytics/index.vue deleted file mode 100644 index 5e3d6d28..00000000 --- a/apps/web-naive/src/views/dashboard/analytics/index.vue +++ /dev/null @@ -1,90 +0,0 @@ - - - diff --git a/apps/web-naive/src/views/dashboard/workspace/index.vue b/apps/web-naive/src/views/dashboard/workspace/index.vue deleted file mode 100644 index b95d6138..00000000 --- a/apps/web-naive/src/views/dashboard/workspace/index.vue +++ /dev/null @@ -1,266 +0,0 @@ - - - diff --git a/apps/web-naive/src/views/demos/form/basic.vue b/apps/web-naive/src/views/demos/form/basic.vue deleted file mode 100644 index 60702a11..00000000 --- a/apps/web-naive/src/views/demos/form/basic.vue +++ /dev/null @@ -1,169 +0,0 @@ - - diff --git a/apps/web-naive/src/views/demos/form/modal.vue b/apps/web-naive/src/views/demos/form/modal.vue deleted file mode 100644 index 52e23542..00000000 --- a/apps/web-naive/src/views/demos/form/modal.vue +++ /dev/null @@ -1,71 +0,0 @@ - - diff --git a/apps/web-naive/src/views/demos/naive/index.vue b/apps/web-naive/src/views/demos/naive/index.vue deleted file mode 100644 index f72cdb20..00000000 --- a/apps/web-naive/src/views/demos/naive/index.vue +++ /dev/null @@ -1,69 +0,0 @@ - - - diff --git a/apps/web-naive/src/views/demos/table/index.vue b/apps/web-naive/src/views/demos/table/index.vue deleted file mode 100644 index ddc958bc..00000000 --- a/apps/web-naive/src/views/demos/table/index.vue +++ /dev/null @@ -1,38 +0,0 @@ - - - - - diff --git a/apps/web-naive/tailwind.config.mjs b/apps/web-naive/tailwind.config.mjs deleted file mode 100644 index f17f556f..00000000 --- a/apps/web-naive/tailwind.config.mjs +++ /dev/null @@ -1 +0,0 @@ -export { default } from '@vben/tailwind-config'; diff --git a/apps/web-naive/tsconfig.json b/apps/web-naive/tsconfig.json deleted file mode 100644 index 02c287fe..00000000 --- a/apps/web-naive/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/apps/web-naive/tsconfig.node.json b/apps/web-naive/tsconfig.node.json deleted file mode 100644 index c2f0d86c..00000000 --- a/apps/web-naive/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/apps/web-naive/vite.config.mts b/apps/web-naive/vite.config.mts deleted file mode 100644 index b6360f1d..00000000 --- a/apps/web-naive/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/package.json b/package.json index 06e70694..f9f18837 100644 --- a/package.json +++ b/package.json @@ -27,13 +27,9 @@ "scripts": { "build": "cross-env NODE_OPTIONS=--max-old-space-size=8192 turbo build", "build:analyze": "turbo build:analyze", - "build:antd": "pnpm run build --filter=@vben/web-antd", - "build:docker": "./scripts/deploy/build-local-docker-image.sh", - "build:docs": "pnpm run build --filter=@vben/docs", - "build:ele": "pnpm run build --filter=@vben/web-ele", - "build:naive": "pnpm run build --filter=@vben/web-naive", "build:tdesign": "pnpm run build --filter=@vben/web-tdesign", - "build:play": "pnpm run build --filter=@vben/playground", + "build:tdesign:pre": "pnpm run build:pre --filter=@vben/web-tdesign", + "build:tdesign:prod": "pnpm run build:prod --filter=@vben/web-tdesign", "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", 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 c8651563..00000000 --- a/playground/package.json +++ /dev/null @@ -1,59 +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/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:", - "ant-design-vue": "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('ant-design-vue/es/auto-complete'), -); -const Button = defineAsyncComponent(() => import('ant-design-vue/es/button')); -const Checkbox = defineAsyncComponent( - () => import('ant-design-vue/es/checkbox'), -); -const CheckboxGroup = defineAsyncComponent(() => - import('ant-design-vue/es/checkbox').then((res) => res.CheckboxGroup), -); -const DatePicker = defineAsyncComponent( - () => import('ant-design-vue/es/date-picker'), -); -const Divider = defineAsyncComponent(() => import('ant-design-vue/es/divider')); -const Input = defineAsyncComponent(() => import('ant-design-vue/es/input')); -const InputNumber = defineAsyncComponent( - () => import('ant-design-vue/es/input-number'), -); -const InputPassword = defineAsyncComponent(() => - import('ant-design-vue/es/input').then((res) => res.InputPassword), -); -const Mentions = defineAsyncComponent( - () => import('ant-design-vue/es/mentions'), -); -const Radio = defineAsyncComponent(() => import('ant-design-vue/es/radio')); -const RadioGroup = defineAsyncComponent(() => - import('ant-design-vue/es/radio').then((res) => res.RadioGroup), -); -const RangePicker = defineAsyncComponent(() => - import('ant-design-vue/es/date-picker').then((res) => res.RangePicker), -); -const Rate = defineAsyncComponent(() => import('ant-design-vue/es/rate')); -const Select = defineAsyncComponent(() => import('ant-design-vue/es/select')); -const Space = defineAsyncComponent(() => import('ant-design-vue/es/space')); -const Switch = defineAsyncComponent(() => import('ant-design-vue/es/switch')); -const Textarea = defineAsyncComponent(() => - import('ant-design-vue/es/input').then((res) => res.Textarea), -); -const TimePicker = defineAsyncComponent( - () => import('ant-design-vue/es/time-picker'), -); -const TreeSelect = defineAsyncComponent( - () => import('ant-design-vue/es/tree-select'), -); -const Upload = defineAsyncComponent(() => import('ant-design-vue/es/upload')); - -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(); - // const publicApi: Recordable = {}; - expose( - new Proxy( - {}, - { - get: (_target, key) => innerRef.value?.[key], - has: (_target, key) => key in (innerRef.value || {}), - }, - ), - ); - // const instance = getCurrentInstance(); - // instance?.proxy?.$nextTick(() => { - // for (const key in innerRef.value) { - // if (typeof innerRef.value[key] === 'function') { - // publicApi[key] = innerRef.value[key]; - // } - // } - // }); - return () => - h( - component, - { ...componentProps, placeholder, ...props, ...attrs, ref: innerRef }, - slots, - ); - }, - }); -}; - -// 这里需要自行根据业务组件库进行适配,需要用到的组件都需要在这里类型说明 -export type ComponentType = - | 'ApiSelect' - | 'ApiTreeSelect' - | 'AutoComplete' - | '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), - - 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, - 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, - }; - - // 将组件注册到全局共享状态中 - 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 24dfd4cd..00000000 --- a/playground/src/adapter/vxe-table.ts +++ /dev/null @@ -1,297 +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 'ant-design-vue'; - -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 { column, row } = params; - return h(Image, { src: row[column.field] }); - }, - }); - - // 表格配置项可以用 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 a8855361..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 'ant-design-vue'; -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 bbaccce1..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 05787651..00000000 --- a/playground/src/layouts/basic.vue +++ /dev/null @@ -1,188 +0,0 @@ - - - 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 7f32bd18..00000000 --- a/playground/src/locales/index.ts +++ /dev/null @@ -1,102 +0,0 @@ -import type { Locale } from 'ant-design-vue/es/locale'; - -import type { App } from 'vue'; - -import type { LocaleSetupOptions, SupportedLanguagesType } from '@vben/locales'; - -import { ref } from 'vue'; - -import { - $t, - setupI18n as coreSetup, - loadLocalesMapFromDir, -} from '@vben/locales'; -import { preferences } from '@vben/preferences'; - -import antdEnLocale from 'ant-design-vue/es/locale/en_US'; -import antdDefaultLocale from 'ant-design-vue/es/locale/zh_CN'; -import dayjs from 'dayjs'; - -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 2b9c23db..00000000 --- a/playground/src/locales/langs/en-US/examples.json +++ /dev/null @@ -1,76 +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", - "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" - } -} 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 50f19dc4..00000000 --- a/playground/src/locales/langs/en-US/page.json +++ /dev/null @@ -1,16 +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}" - }, - "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 aa0b00f9..00000000 --- a/playground/src/locales/langs/zh-CN/examples.json +++ /dev/null @@ -1,76 +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": "文件", - "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": "按钮组" - } -} 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 666db5b7..00000000 --- a/playground/src/locales/langs/zh-CN/page.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "auth": { - "login": "登录", - "register": "注册", - "codeLogin": "验证码登录", - "qrcodeLogin": "二维码登录", - "forgetPassword": "忘记密码", - "sendingCode": "正在发送验证码", - "codeSentTo": "验证码已发送至{0}" - }, - "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 3a48be23..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 'ant-design-vue'; - -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 514bd2eb..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.path === preferences.app.defaultHomePath) { - redirectPath = preferences.app.defaultHomePath; - } else if (userInfo.homePath && to.path === 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 3df4f0ad..00000000 --- a/playground/src/router/routes/modules/demos.ts +++ /dev/null @@ -1,594 +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 2ca6b80d..00000000 --- a/playground/src/router/routes/modules/examples.ts +++ /dev/null @@ -1,335 +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'), - }, - }, - ], - }, -]; - -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 1c177798..00000000 --- a/playground/src/router/routes/modules/vben.ts +++ /dev/null @@ -1,106 +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', - }, -]; - -export default routes; diff --git a/playground/src/store/auth.ts b/playground/src/store/auth.ts deleted file mode 100644 index 4adeb76e..00000000 --- a/playground/src/store/auth.ts +++ /dev/null @@ -1,120 +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 'ant-design-vue'; -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, - }; - } - - async function logout(redirect: boolean = true) { - try { - await logoutApi(); - } catch { - // 不做任何处理 - } - - 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 3b50c626..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/dashboard/analytics/analytics-trends.vue b/playground/src/views/dashboard/analytics/analytics-trends.vue deleted file mode 100644 index f1f0b232..00000000 --- a/playground/src/views/dashboard/analytics/analytics-trends.vue +++ /dev/null @@ -1,98 +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 190fb41f..00000000 --- a/playground/src/views/dashboard/analytics/analytics-visits-data.vue +++ /dev/null @@ -1,82 +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 02f50912..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 0915c7af..00000000 --- a/playground/src/views/dashboard/analytics/analytics-visits-source.vue +++ /dev/null @@ -1,65 +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 7e0f1013..00000000 --- a/playground/src/views/dashboard/analytics/analytics-visits.vue +++ /dev/null @@ -1,55 +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 5e3d6d28..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 @@ - - - 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 0966a7be..00000000 --- a/playground/src/views/demos/access/button-control.vue +++ /dev/null @@ -1,157 +0,0 @@ - - - diff --git a/playground/src/views/demos/access/index.vue b/playground/src/views/demos/access/index.vue deleted file mode 100644 index abd55254..00000000 --- a/playground/src/views/demos/access/index.vue +++ /dev/null @@ -1,98 +0,0 @@ - - - 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 fbe22b2e..00000000 --- a/playground/src/views/demos/badge/index.vue +++ /dev/null @@ -1,117 +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 8a4de64e..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 2c24abff..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 792315ff..00000000 --- a/playground/src/views/demos/features/clipboard/index.vue +++ /dev/null @@ -1,25 +0,0 @@ - - - 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 5342141d..00000000 --- a/playground/src/views/demos/features/file-download/index.vue +++ /dev/null @@ -1,100 +0,0 @@ - - - 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 485b2e43..00000000 --- a/playground/src/views/demos/features/full-screen/index.vue +++ /dev/null @@ -1,47 +0,0 @@ - - - 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 994c9955..00000000 --- a/playground/src/views/demos/features/icons/index.vue +++ /dev/null @@ -1,115 +0,0 @@ - - - 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 d1f58145..00000000 --- a/playground/src/views/demos/features/json-bigint/index.vue +++ /dev/null @@ -1,39 +0,0 @@ - - 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 532839af..00000000 --- a/playground/src/views/demos/features/login-expired/index.vue +++ /dev/null @@ -1,39 +0,0 @@ - - - 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 4ed4d08e..00000000 --- a/playground/src/views/demos/features/request-params-serializer/index.vue +++ /dev/null @@ -1,61 +0,0 @@ - - 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 5e7bfa2e..00000000 --- a/playground/src/views/demos/features/tabs/index.vue +++ /dev/null @@ -1,105 +0,0 @@ - - - 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 @@ - - - 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 @@ - - 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 00dd6e4f..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 2add4c15..00000000 --- a/playground/src/views/demos/features/vue-query/infinite-queries.vue +++ /dev/null @@ -1,58 +0,0 @@ - - - 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 a29e4b97..00000000 --- a/playground/src/views/demos/features/vue-query/paginated-queries.vue +++ /dev/null @@ -1,53 +0,0 @@ - - - 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 0080386f..00000000 --- a/playground/src/views/demos/features/vue-query/query-retries.vue +++ /dev/null @@ -1,34 +0,0 @@ - - - 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 27875fcc..00000000 --- a/playground/src/views/demos/features/watermark/index.vue +++ /dev/null @@ -1,86 +0,0 @@ - - - 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 23861da4..00000000 --- a/playground/src/views/examples/button-group/index.vue +++ /dev/null @@ -1,229 +0,0 @@ - - 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 498a9773..00000000 --- a/playground/src/views/examples/captcha/point-selection-captcha.vue +++ /dev/null @@ -1,181 +0,0 @@ - - - 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 0a397655..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 23775774..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 78fbd86c..00000000 --- a/playground/src/views/examples/captcha/slider-translate-captcha.vue +++ /dev/null @@ -1,27 +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 1309351d..00000000 --- a/playground/src/views/examples/count-to/index.vue +++ /dev/null @@ -1,178 +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 4dad2a8d..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 0c327340..00000000 --- a/playground/src/views/examples/drawer/auto-height-demo.vue +++ /dev/null @@ -1,47 +0,0 @@ - - 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 08bc68fc..00000000 --- a/playground/src/views/examples/drawer/base-demo.vue +++ /dev/null @@ -1,35 +0,0 @@ - - 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 ce5560fa..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 f67b9785..00000000 --- a/playground/src/views/examples/drawer/in-content-demo.vue +++ /dev/null @@ -1,48 +0,0 @@ - - diff --git a/playground/src/views/examples/drawer/index.vue b/playground/src/views/examples/drawer/index.vue deleted file mode 100644 index 9804b19f..00000000 --- a/playground/src/views/examples/drawer/index.vue +++ /dev/null @@ -1,195 +0,0 @@ - - - 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 d5422739..00000000 --- a/playground/src/views/examples/drawer/shared-data-demo.vue +++ /dev/null @@ -1,29 +0,0 @@ - - diff --git a/playground/src/views/examples/ellipsis/index.vue b/playground/src/views/examples/ellipsis/index.vue deleted file mode 100644 index b88c8190..00000000 --- a/playground/src/views/examples/ellipsis/index.vue +++ /dev/null @@ -1,46 +0,0 @@ - - - diff --git a/playground/src/views/examples/form/api.vue b/playground/src/views/examples/form/api.vue deleted file mode 100644 index a7e15a08..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 d0e91d33..00000000 --- a/playground/src/views/examples/form/basic.vue +++ /dev/null @@ -1,447 +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 cd7146b2..00000000 --- a/playground/src/views/examples/form/custom-layout.vue +++ /dev/null @@ -1,111 +0,0 @@ - - - diff --git a/playground/src/views/examples/form/custom.vue b/playground/src/views/examples/form/custom.vue deleted file mode 100644 index 7fab17a6..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 c11a3c1a..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 95a37c67..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 da79a102..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 5efae67b..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 7ec95493..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 89aaf50b..00000000 --- a/playground/src/views/examples/form/scroll-to-error-test.vue +++ /dev/null @@ -1,180 +0,0 @@ - - - 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 a91e042d..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 45d8651a..00000000 --- a/playground/src/views/examples/layout/col-page.vue +++ /dev/null @@ -1,108 +0,0 @@ - - diff --git a/playground/src/views/examples/loading/index.vue b/playground/src/views/examples/loading/index.vue deleted file mode 100644 index c31f7844..00000000 --- a/playground/src/views/examples/loading/index.vue +++ /dev/null @@ -1,101 +0,0 @@ - - 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 5e8f7ad0..00000000 --- a/playground/src/views/examples/modal/auto-height-demo.vue +++ /dev/null @@ -1,49 +0,0 @@ - - - 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 7b2f6391..00000000 --- a/playground/src/views/examples/modal/base-demo.vue +++ /dev/null @@ -1,34 +0,0 @@ - - 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 432ce0da..00000000 --- a/playground/src/views/examples/modal/blur-demo.vue +++ /dev/null @@ -1,23 +0,0 @@ - - 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 45203036..00000000 --- a/playground/src/views/examples/modal/drag-demo.vue +++ /dev/null @@ -1,19 +0,0 @@ - - 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 33d1c4ee..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 6d58aa15..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 7ffe7b77..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 3ed6cdea..00000000 --- a/playground/src/views/examples/modal/index.vue +++ /dev/null @@ -1,278 +0,0 @@ - - - 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 6251fd05..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 8ba6e7e9..00000000 --- a/playground/src/views/examples/modal/shared-data-demo.vue +++ /dev/null @@ -1,29 +0,0 @@ - - diff --git a/playground/src/views/examples/motion/index.vue b/playground/src/views/examples/motion/index.vue deleted file mode 100644 index 1faaa23b..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 @@ - - - diff --git a/playground/src/views/examples/tippy/index.vue b/playground/src/views/examples/tippy/index.vue deleted file mode 100644 index 628fa380..00000000 --- a/playground/src/views/examples/tippy/index.vue +++ /dev/null @@ -1,303 +0,0 @@ - - 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 d2047246..00000000 --- a/playground/src/views/examples/vxe-table/basic.vue +++ /dev/null @@ -1,111 +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 26258804..00000000 --- a/playground/src/views/examples/vxe-table/custom-cell.vue +++ /dev/null @@ -1,108 +0,0 @@ - - - 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 f9d25cac..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 399d3521..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 95de7045..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 7042019f..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 c8a1df46..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 48773625..00000000 --- a/playground/src/views/system/dept/data.ts +++ /dev/null @@ -1,135 +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', - title: $t('system.dept.createTime'), - width: 180, - }, - { - 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 13d45a6e..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 18a13966..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 759dccf6..00000000 --- a/playground/src/views/system/menu/list.vue +++ /dev/null @@ -1,162 +0,0 @@ - - - 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 3cf40e35..00000000 --- a/playground/src/views/system/menu/modules/form.vue +++ /dev/null @@ -1,505 +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 4775c028..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 511fb04b..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, - }, - }, - }, - }, - }; -});