From 40dda3d4e4abde10d0c7d36ab7948b0279d2011c Mon Sep 17 00:00:00 2001 From: DaxPay Date: Tue, 2 Jul 2024 16:22:50 +0800 Subject: [PATCH] =?UTF-8?q?ref=20=E8=B7=AF=E7=94=B1=E7=94=9F=E6=88=90?= =?UTF-8?q?=E6=96=B9=E5=BC=8F=E8=B0=83=E6=95=B4=E4=B8=BA=E5=90=8E=E5=8F=B0?= =?UTF-8?q?=E7=94=9F=E6=88=90=E5=92=8C=E5=8E=BB=E9=99=A4mock?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .commitlintrc.cjs | 2 +- .env | 2 +- .env.analyze | 5 - .env.development | 18 +- .env.docker | 5 - .env.production | 6 - .env.test | 5 - .vscode/settings.json | 1 - internal/eslint-config/build.config.ts | 4 +- internal/eslint-config/src/index.ts | 2 +- internal/eslint-config/src/strict.ts | 2 +- internal/stylelint-config/build.config.ts | 4 +- internal/stylelint-config/src/index.ts | 2 +- internal/ts-config/base.json | 2 +- internal/vite-config/build.config.ts | 4 +- internal/vite-config/package.json | 1 - .../vite-config/src/config/application.ts | 56 +- internal/vite-config/src/config/common.ts | 8 +- internal/vite-config/src/config/package.ts | 28 +- internal/vite-config/src/index.ts | 4 +- internal/vite-config/src/plugins/appConfig.ts | 72 +- internal/vite-config/src/plugins/compress.ts | 18 +- internal/vite-config/src/plugins/html.ts | 8 +- internal/vite-config/src/plugins/index.ts | 61 +- internal/vite-config/src/plugins/mock.ts | 19 - internal/vite-config/src/plugins/svgSprite.ts | 10 +- .../vite-config/src/plugins/visualizer.ts | 6 +- internal/vite-config/src/utils/env.ts | 38 +- internal/vite-config/src/utils/hash.ts | 16 +- internal/vite-config/src/utils/modifyVars.ts | 28 +- mock/_createProductionServer.ts | 34 - mock/_util.ts | 52 -- mock/demo/account.ts | 71 -- mock/demo/api-cascader.ts | 325 ------- mock/demo/select-demo.ts | 28 - mock/demo/system.ts | 195 ---- mock/demo/table-demo.ts | 55 -- mock/demo/tree-demo.ts | 38 - mock/sys/menu.ts | 270 ------ mock/sys/user.ts | 120 --- package.json | 5 +- pnpm-lock.yaml | 314 ------- public/favicon.ico | Bin 894 -> 9662 bytes public/logo.png | Bin 4042 -> 14114 bytes src/api/common/BaseApi.api.ts | 21 + src/api/common/Captcha.ts | 19 + src/api/common/ChinaRegion.api.ts | 48 + src/api/common/FileUpload.ts | 103 +++ src/api/common/LoginAssist.ts | 22 + src/api/common/Parameter.ts | 13 + src/api/sys/login.ts | 47 + src/api/sys/menu.ts | 10 +- src/api/sys/model/menuModel.ts | 32 + src/api/sys/model/userModel.ts | 45 +- src/api/sys/user.ts | 65 +- src/assets/images/logo.png | Bin 28304 -> 14114 bytes src/components/Link/Link.vue | 42 + src/components/Link/index.ts | 4 + src/components/registerGlobComp.ts | 85 +- src/enums/appEnum.ts | 3 - src/enums/httpEnum.ts | 1 + src/enums/wsNoticeEnum.ts | 9 + src/hooks/setting/index.ts | 3 +- src/hooks/web/usePermission.ts | 56 +- src/logics/websocket/UserGlobalWebSocker.ts | 105 +++ src/logics/websocket/WebSockerType.ts | 9 + src/logics/websocket/WebsocketNotice.ts | 37 + src/router/guard/index.ts | 6 +- src/router/guard/paramMenuGuard.ts | 4 +- src/router/guard/permissionGuard.ts | 122 +-- src/router/guard/stateGuard.ts | 4 + src/router/helper/menuHelper.ts | 34 +- src/router/helper/routeHelper.ts | 67 +- src/router/menus/index.ts | 24 +- src/router/routes/index.ts | 3 +- src/router/routes/mainOut.ts | 22 - src/router/routes/modules/dashboard.ts | 4 +- src/router/routes/modules/demo/charts.ts | 80 -- src/router/routes/modules/demo/comp.ts | 470 ---------- src/router/routes/modules/demo/feat.ts | 279 ------ src/router/routes/modules/demo/iframe.ts | 49 - src/router/routes/modules/demo/level.ts | 68 -- src/router/routes/modules/demo/page.ts | 255 ------ src/router/routes/modules/demo/permission.ts | 92 -- src/router/routes/modules/demo/steps.ts | 31 - src/router/routes/modules/demo/system.ts | 87 -- src/router/routes/modules/hooks/request.ts | 79 -- src/router/routes/project.ts | 51 ++ src/router/types.ts | 8 +- src/settings/designSetting.ts | 14 - src/settings/projectSetting.ts | 106 +-- src/store/action/userAction.ts | 39 + src/store/modules/permission.ts | 202 ++--- src/store/modules/user.ts | 176 ++-- src/utils/env.ts | 6 +- src/utils/http/axios/index.ts | 150 ++- src/utils/is.ts | 27 + src/views/demo/charts/Line.vue | 113 --- src/views/demo/charts/Map.vue | 70 -- src/views/demo/charts/Pie.vue | 130 --- src/views/demo/charts/SaleRadar.vue | 95 -- src/views/demo/charts/china.json | 856 ------------------ src/views/demo/charts/data.ts | 189 ---- src/views/demo/charts/map/Baidu.vue | 41 - src/views/demo/charts/map/Gaode.vue | 42 - src/views/demo/charts/map/Google.vue | 47 - src/views/demo/comp/button/index.vue | 106 --- src/views/demo/comp/card-list/index.vue | 32 - src/views/demo/comp/count-to/index.vue | 34 - src/views/demo/comp/cropper/index.vue | 72 -- src/views/demo/comp/desc/index.vue | 77 -- src/views/demo/comp/drawer/Drawer1.vue | 6 - src/views/demo/comp/drawer/Drawer2.vue | 11 - src/views/demo/comp/drawer/Drawer3.vue | 28 - src/views/demo/comp/drawer/Drawer4.vue | 46 - src/views/demo/comp/drawer/Drawer5.vue | 9 - src/views/demo/comp/drawer/index.vue | 50 - src/views/demo/comp/loading/index.vue | 97 -- src/views/demo/comp/modal/Modal1.vue | 53 -- src/views/demo/comp/modal/Modal2.vue | 11 - src/views/demo/comp/modal/Modal3.vue | 8 - src/views/demo/comp/modal/Modal4.vue | 75 -- src/views/demo/comp/modal/Modal5.vue | 40 - src/views/demo/comp/modal/index.vue | 114 --- src/views/demo/comp/qrcode/index.vue | 107 --- src/views/demo/comp/scroll/Action.vue | 50 - src/views/demo/comp/scroll/VirtualScroll.vue | 79 -- src/views/demo/comp/scroll/index.vue | 26 - src/views/demo/comp/strength-meter/index.vue | 24 - src/views/demo/comp/time/index.vue | 35 - src/views/demo/comp/transition/index.vue | 73 -- src/views/demo/comp/upload/Upload1.vue | 16 - src/views/demo/comp/upload/Upload2.vue | 56 -- src/views/demo/comp/upload/Upload3.vue | 73 -- src/views/demo/comp/upload/Upload4.vue | 187 ---- src/views/demo/comp/upload/index.vue | 15 - src/views/demo/comp/verify/Rotate.vue | 18 - src/views/demo/comp/verify/index.vue | 79 -- .../demo/feat/breadcrumb/ChildrenList.vue | 8 - .../feat/breadcrumb/ChildrenListDetail.vue | 8 - src/views/demo/feat/breadcrumb/FlatList.vue | 8 - .../demo/feat/breadcrumb/FlatListDetail.vue | 3 - src/views/demo/feat/click-out-side/index.vue | 24 - src/views/demo/feat/context-menu/index.vue | 78 -- src/views/demo/feat/copy/index.vue | 29 - src/views/demo/feat/download/imgBase64.ts | 1 - src/views/demo/feat/download/index.vue | 47 - src/views/demo/feat/ellipsis/index.vue | 41 - src/views/demo/feat/full-screen/index.vue | 36 - src/views/demo/feat/icon/index.vue | 69 -- src/views/demo/feat/img-preview/index.vue | 20 - src/views/demo/feat/menu-params/index.vue | 31 - src/views/demo/feat/msg/index.vue | 68 -- src/views/demo/feat/request-demo/index.vue | 76 -- src/views/demo/feat/ripple/index.vue | 11 - src/views/demo/feat/session-timeout/index.vue | 45 - src/views/demo/feat/tab-params/index.vue | 24 - src/views/demo/feat/tabs/TabDetail.vue | 20 - src/views/demo/feat/tabs/index.vue | 53 -- src/views/demo/feat/watermark/index.vue | 32 - src/views/demo/feat/ws/index.vue | 100 -- src/views/demo/form/AdvancedForm.vue | 189 ---- src/views/demo/form/AppendForm.vue | 201 ---- src/views/demo/form/CustomerForm.vue | 225 ----- src/views/demo/form/DynamicForm.vue | 229 ----- src/views/demo/form/RefForm.vue | 172 ---- src/views/demo/form/RuleForm.vue | 245 ----- src/views/demo/form/TabsForm.vue | 118 --- src/views/demo/form/UseForm.vue | 483 ---------- src/views/demo/form/index.vue | 821 ----------------- src/views/demo/level/Menu111.vue | 10 - src/views/demo/level/Menu12.vue | 10 - src/views/demo/level/Menu2.vue | 10 - src/views/demo/main-out/index.vue | 6 - .../demo/page/account/center/Application.vue | 74 -- .../demo/page/account/center/Article.vue | 79 -- .../demo/page/account/center/Project.vue | 57 -- src/views/demo/page/account/center/data.tsx | 124 --- src/views/demo/page/account/center/index.vue | 138 --- .../demo/page/account/setting/AccountBind.vue | 46 - .../demo/page/account/setting/BaseSetting.vue | 79 -- .../demo/page/account/setting/MsgNotify.vue | 27 - .../page/account/setting/SecureSetting.vue | 29 - src/views/demo/page/account/setting/data.ts | 149 --- src/views/demo/page/account/setting/index.vue | 50 - src/views/demo/page/desc/basic/data.tsx | 196 ---- src/views/demo/page/desc/basic/index.vue | 71 -- src/views/demo/page/desc/high/data.tsx | 65 -- src/views/demo/page/desc/high/index.vue | 107 --- src/views/demo/page/form/basic/data.ts | 139 --- src/views/demo/page/form/basic/index.vue | 64 -- src/views/demo/page/form/high/PersonTable.vue | 127 --- src/views/demo/page/form/high/data.ts | 149 --- src/views/demo/page/form/high/index.vue | 65 -- src/views/demo/page/form/step/Step1.vue | 92 -- src/views/demo/page/form/step/Step2.vue | 61 -- src/views/demo/page/form/step/Step3.vue | 23 - src/views/demo/page/form/step/data.tsx | 77 -- src/views/demo/page/form/step/index.vue | 71 -- src/views/demo/page/list/basic/data.tsx | 17 - src/views/demo/page/list/basic/index.vue | 143 --- src/views/demo/page/list/card/data.tsx | 14 - src/views/demo/page/list/card/index.vue | 87 -- src/views/demo/page/list/search/data.tsx | 37 - src/views/demo/page/list/search/index.vue | 105 --- src/views/demo/page/result/fail/index.vue | 47 - src/views/demo/page/result/success/index.vue | 51 -- .../demo/permission/CurrentPermissionMode.vue | 23 - src/views/demo/permission/back/Btn.vue | 76 -- src/views/demo/permission/back/index.vue | 51 -- src/views/demo/permission/front/AuthPageA.vue | 16 - src/views/demo/permission/front/AuthPageB.vue | 16 - src/views/demo/permission/front/Btn.vue | 74 -- src/views/demo/permission/front/index.vue | 47 - src/views/demo/steps/index.vue | 38 - .../demo/system/account/AccountDetail.vue | 61 -- .../demo/system/account/AccountModal.vue | 69 -- src/views/demo/system/account/DeptTree.vue | 38 - src/views/demo/system/account/account.data.ts | 156 ---- src/views/demo/system/account/index.vue | 126 --- src/views/demo/system/dept/DeptModal.vue | 58 -- src/views/demo/system/dept/dept.data.ts | 110 --- src/views/demo/system/dept/index.vue | 88 -- src/views/demo/system/menu/MenuDrawer.vue | 58 -- src/views/demo/system/menu/index.vue | 96 -- src/views/demo/system/menu/menu.data.ts | 200 ---- src/views/demo/system/password/index.vue | 41 - src/views/demo/system/password/pwd.data.ts | 46 - src/views/demo/system/role/RoleDrawer.vue | 67 -- src/views/demo/system/role/index.vue | 85 -- src/views/demo/system/role/role.data.ts | 123 --- src/views/demo/system/vxe-account/index.vue | 86 -- .../system/vxe-account/vxeAccount.data.ts | 84 -- src/views/demo/table/AuthColumn.vue | 150 --- src/views/demo/table/Basic.vue | 65 -- src/views/demo/table/CustomerCell.vue | 97 -- src/views/demo/table/EditCellTable.vue | 260 ------ src/views/demo/table/EditRowTable.vue | 301 ------ src/views/demo/table/ExpandTable.vue | 65 -- src/views/demo/table/FetchTable.vue | 31 - src/views/demo/table/FixedColumn.vue | 85 -- src/views/demo/table/FixedHeight.vue | 37 - src/views/demo/table/FooterTable.vue | 41 - src/views/demo/table/FormTable.vue | 34 - src/views/demo/table/MergeHeader.vue | 18 - src/views/demo/table/MultipleHeader.vue | 17 - src/views/demo/table/RefTable.vue | 117 --- .../demo/table/ResizeParentHeightTable.vue | 67 -- src/views/demo/table/TreeTable.vue | 38 - src/views/demo/table/UseTable.vue | 137 --- src/views/demo/table/VxeTable.vue | 110 --- src/views/demo/table/tableData.tsx | 461 ---------- src/views/demo/tree/ActionTree.vue | 121 --- src/views/demo/tree/EditTree.vue | 112 --- src/views/demo/tree/data.ts | 119 --- src/views/demo/tree/index.vue | 115 --- src/views/hooks/request/base.tsx | 319 ------- src/views/hooks/request/cache.tsx | 311 ------- src/views/hooks/request/debounce.tsx | 60 -- src/views/hooks/request/loading-delay.tsx | 53 -- src/views/hooks/request/mock-api.ts | 25 - src/views/hooks/request/polling.tsx | 94 -- src/views/hooks/request/ready.tsx | 85 -- .../hooks/request/refresh-on-window-focus.tsx | 47 - src/views/hooks/request/refresy-deps.tsx | 163 ---- src/views/hooks/request/retry.tsx | 73 -- src/views/hooks/request/throttle.tsx | 59 -- src/views/sys/login/Login.vue | 64 +- src/views/sys/login/LoginForm.vue | 224 ++--- tsconfig.json | 1 - types/axios.d.ts | 25 +- types/config.d.ts | 12 +- types/global.d.ts | 1 - types/vue-router.d.ts | 31 +- uno.config.ts | 2 +- vite.config.ts | 14 +- 276 files changed, 1551 insertions(+), 19426 deletions(-) delete mode 100644 internal/vite-config/src/plugins/mock.ts delete mode 100644 mock/_createProductionServer.ts delete mode 100644 mock/_util.ts delete mode 100644 mock/demo/account.ts delete mode 100644 mock/demo/api-cascader.ts delete mode 100644 mock/demo/select-demo.ts delete mode 100644 mock/demo/system.ts delete mode 100644 mock/demo/table-demo.ts delete mode 100644 mock/demo/tree-demo.ts delete mode 100644 mock/sys/menu.ts delete mode 100644 mock/sys/user.ts create mode 100644 src/api/common/BaseApi.api.ts create mode 100644 src/api/common/Captcha.ts create mode 100644 src/api/common/ChinaRegion.api.ts create mode 100644 src/api/common/FileUpload.ts create mode 100644 src/api/common/LoginAssist.ts create mode 100644 src/api/common/Parameter.ts create mode 100644 src/api/sys/login.ts create mode 100644 src/components/Link/Link.vue create mode 100644 src/components/Link/index.ts create mode 100644 src/enums/wsNoticeEnum.ts create mode 100644 src/logics/websocket/UserGlobalWebSocker.ts create mode 100644 src/logics/websocket/WebSockerType.ts create mode 100644 src/logics/websocket/WebsocketNotice.ts delete mode 100644 src/router/routes/mainOut.ts delete mode 100644 src/router/routes/modules/demo/charts.ts delete mode 100644 src/router/routes/modules/demo/comp.ts delete mode 100644 src/router/routes/modules/demo/feat.ts delete mode 100644 src/router/routes/modules/demo/iframe.ts delete mode 100644 src/router/routes/modules/demo/level.ts delete mode 100644 src/router/routes/modules/demo/page.ts delete mode 100644 src/router/routes/modules/demo/permission.ts delete mode 100644 src/router/routes/modules/demo/steps.ts delete mode 100644 src/router/routes/modules/demo/system.ts delete mode 100644 src/router/routes/modules/hooks/request.ts create mode 100644 src/router/routes/project.ts create mode 100644 src/store/action/userAction.ts delete mode 100644 src/views/demo/charts/Line.vue delete mode 100644 src/views/demo/charts/Map.vue delete mode 100644 src/views/demo/charts/Pie.vue delete mode 100644 src/views/demo/charts/SaleRadar.vue delete mode 100644 src/views/demo/charts/china.json delete mode 100644 src/views/demo/charts/data.ts delete mode 100644 src/views/demo/charts/map/Baidu.vue delete mode 100644 src/views/demo/charts/map/Gaode.vue delete mode 100644 src/views/demo/charts/map/Google.vue delete mode 100644 src/views/demo/comp/button/index.vue delete mode 100644 src/views/demo/comp/card-list/index.vue delete mode 100644 src/views/demo/comp/count-to/index.vue delete mode 100644 src/views/demo/comp/cropper/index.vue delete mode 100644 src/views/demo/comp/desc/index.vue delete mode 100644 src/views/demo/comp/drawer/Drawer1.vue delete mode 100644 src/views/demo/comp/drawer/Drawer2.vue delete mode 100644 src/views/demo/comp/drawer/Drawer3.vue delete mode 100644 src/views/demo/comp/drawer/Drawer4.vue delete mode 100644 src/views/demo/comp/drawer/Drawer5.vue delete mode 100644 src/views/demo/comp/drawer/index.vue delete mode 100644 src/views/demo/comp/loading/index.vue delete mode 100644 src/views/demo/comp/modal/Modal1.vue delete mode 100644 src/views/demo/comp/modal/Modal2.vue delete mode 100644 src/views/demo/comp/modal/Modal3.vue delete mode 100644 src/views/demo/comp/modal/Modal4.vue delete mode 100644 src/views/demo/comp/modal/Modal5.vue delete mode 100644 src/views/demo/comp/modal/index.vue delete mode 100644 src/views/demo/comp/qrcode/index.vue delete mode 100644 src/views/demo/comp/scroll/Action.vue delete mode 100644 src/views/demo/comp/scroll/VirtualScroll.vue delete mode 100644 src/views/demo/comp/scroll/index.vue delete mode 100644 src/views/demo/comp/strength-meter/index.vue delete mode 100644 src/views/demo/comp/time/index.vue delete mode 100644 src/views/demo/comp/transition/index.vue delete mode 100644 src/views/demo/comp/upload/Upload1.vue delete mode 100644 src/views/demo/comp/upload/Upload2.vue delete mode 100644 src/views/demo/comp/upload/Upload3.vue delete mode 100644 src/views/demo/comp/upload/Upload4.vue delete mode 100644 src/views/demo/comp/upload/index.vue delete mode 100644 src/views/demo/comp/verify/Rotate.vue delete mode 100644 src/views/demo/comp/verify/index.vue delete mode 100644 src/views/demo/feat/breadcrumb/ChildrenList.vue delete mode 100644 src/views/demo/feat/breadcrumb/ChildrenListDetail.vue delete mode 100644 src/views/demo/feat/breadcrumb/FlatList.vue delete mode 100644 src/views/demo/feat/breadcrumb/FlatListDetail.vue delete mode 100644 src/views/demo/feat/click-out-side/index.vue delete mode 100644 src/views/demo/feat/context-menu/index.vue delete mode 100644 src/views/demo/feat/copy/index.vue delete mode 100644 src/views/demo/feat/download/imgBase64.ts delete mode 100644 src/views/demo/feat/download/index.vue delete mode 100644 src/views/demo/feat/ellipsis/index.vue delete mode 100644 src/views/demo/feat/full-screen/index.vue delete mode 100644 src/views/demo/feat/icon/index.vue delete mode 100644 src/views/demo/feat/img-preview/index.vue delete mode 100644 src/views/demo/feat/menu-params/index.vue delete mode 100644 src/views/demo/feat/msg/index.vue delete mode 100644 src/views/demo/feat/request-demo/index.vue delete mode 100644 src/views/demo/feat/ripple/index.vue delete mode 100644 src/views/demo/feat/session-timeout/index.vue delete mode 100644 src/views/demo/feat/tab-params/index.vue delete mode 100644 src/views/demo/feat/tabs/TabDetail.vue delete mode 100644 src/views/demo/feat/tabs/index.vue delete mode 100644 src/views/demo/feat/watermark/index.vue delete mode 100644 src/views/demo/feat/ws/index.vue delete mode 100644 src/views/demo/form/AdvancedForm.vue delete mode 100644 src/views/demo/form/AppendForm.vue delete mode 100644 src/views/demo/form/CustomerForm.vue delete mode 100644 src/views/demo/form/DynamicForm.vue delete mode 100644 src/views/demo/form/RefForm.vue delete mode 100644 src/views/demo/form/RuleForm.vue delete mode 100644 src/views/demo/form/TabsForm.vue delete mode 100644 src/views/demo/form/UseForm.vue delete mode 100644 src/views/demo/form/index.vue delete mode 100644 src/views/demo/level/Menu111.vue delete mode 100644 src/views/demo/level/Menu12.vue delete mode 100644 src/views/demo/level/Menu2.vue delete mode 100644 src/views/demo/main-out/index.vue delete mode 100644 src/views/demo/page/account/center/Application.vue delete mode 100644 src/views/demo/page/account/center/Article.vue delete mode 100644 src/views/demo/page/account/center/Project.vue delete mode 100644 src/views/demo/page/account/center/data.tsx delete mode 100644 src/views/demo/page/account/center/index.vue delete mode 100644 src/views/demo/page/account/setting/AccountBind.vue delete mode 100644 src/views/demo/page/account/setting/BaseSetting.vue delete mode 100644 src/views/demo/page/account/setting/MsgNotify.vue delete mode 100644 src/views/demo/page/account/setting/SecureSetting.vue delete mode 100644 src/views/demo/page/account/setting/data.ts delete mode 100644 src/views/demo/page/account/setting/index.vue delete mode 100644 src/views/demo/page/desc/basic/data.tsx delete mode 100644 src/views/demo/page/desc/basic/index.vue delete mode 100644 src/views/demo/page/desc/high/data.tsx delete mode 100644 src/views/demo/page/desc/high/index.vue delete mode 100644 src/views/demo/page/form/basic/data.ts delete mode 100644 src/views/demo/page/form/basic/index.vue delete mode 100644 src/views/demo/page/form/high/PersonTable.vue delete mode 100644 src/views/demo/page/form/high/data.ts delete mode 100644 src/views/demo/page/form/high/index.vue delete mode 100644 src/views/demo/page/form/step/Step1.vue delete mode 100644 src/views/demo/page/form/step/Step2.vue delete mode 100644 src/views/demo/page/form/step/Step3.vue delete mode 100644 src/views/demo/page/form/step/data.tsx delete mode 100644 src/views/demo/page/form/step/index.vue delete mode 100644 src/views/demo/page/list/basic/data.tsx delete mode 100644 src/views/demo/page/list/basic/index.vue delete mode 100644 src/views/demo/page/list/card/data.tsx delete mode 100644 src/views/demo/page/list/card/index.vue delete mode 100644 src/views/demo/page/list/search/data.tsx delete mode 100644 src/views/demo/page/list/search/index.vue delete mode 100644 src/views/demo/page/result/fail/index.vue delete mode 100644 src/views/demo/page/result/success/index.vue delete mode 100644 src/views/demo/permission/CurrentPermissionMode.vue delete mode 100644 src/views/demo/permission/back/Btn.vue delete mode 100644 src/views/demo/permission/back/index.vue delete mode 100644 src/views/demo/permission/front/AuthPageA.vue delete mode 100644 src/views/demo/permission/front/AuthPageB.vue delete mode 100644 src/views/demo/permission/front/Btn.vue delete mode 100644 src/views/demo/permission/front/index.vue delete mode 100644 src/views/demo/steps/index.vue delete mode 100644 src/views/demo/system/account/AccountDetail.vue delete mode 100644 src/views/demo/system/account/AccountModal.vue delete mode 100644 src/views/demo/system/account/DeptTree.vue delete mode 100644 src/views/demo/system/account/account.data.ts delete mode 100644 src/views/demo/system/account/index.vue delete mode 100644 src/views/demo/system/dept/DeptModal.vue delete mode 100644 src/views/demo/system/dept/dept.data.ts delete mode 100644 src/views/demo/system/dept/index.vue delete mode 100644 src/views/demo/system/menu/MenuDrawer.vue delete mode 100644 src/views/demo/system/menu/index.vue delete mode 100644 src/views/demo/system/menu/menu.data.ts delete mode 100644 src/views/demo/system/password/index.vue delete mode 100644 src/views/demo/system/password/pwd.data.ts delete mode 100644 src/views/demo/system/role/RoleDrawer.vue delete mode 100644 src/views/demo/system/role/index.vue delete mode 100644 src/views/demo/system/role/role.data.ts delete mode 100644 src/views/demo/system/vxe-account/index.vue delete mode 100644 src/views/demo/system/vxe-account/vxeAccount.data.ts delete mode 100644 src/views/demo/table/AuthColumn.vue delete mode 100644 src/views/demo/table/Basic.vue delete mode 100644 src/views/demo/table/CustomerCell.vue delete mode 100644 src/views/demo/table/EditCellTable.vue delete mode 100644 src/views/demo/table/EditRowTable.vue delete mode 100644 src/views/demo/table/ExpandTable.vue delete mode 100644 src/views/demo/table/FetchTable.vue delete mode 100644 src/views/demo/table/FixedColumn.vue delete mode 100644 src/views/demo/table/FixedHeight.vue delete mode 100644 src/views/demo/table/FooterTable.vue delete mode 100644 src/views/demo/table/FormTable.vue delete mode 100644 src/views/demo/table/MergeHeader.vue delete mode 100644 src/views/demo/table/MultipleHeader.vue delete mode 100644 src/views/demo/table/RefTable.vue delete mode 100644 src/views/demo/table/ResizeParentHeightTable.vue delete mode 100644 src/views/demo/table/TreeTable.vue delete mode 100644 src/views/demo/table/UseTable.vue delete mode 100644 src/views/demo/table/VxeTable.vue delete mode 100644 src/views/demo/table/tableData.tsx delete mode 100644 src/views/demo/tree/ActionTree.vue delete mode 100644 src/views/demo/tree/EditTree.vue delete mode 100644 src/views/demo/tree/data.ts delete mode 100644 src/views/demo/tree/index.vue delete mode 100644 src/views/hooks/request/base.tsx delete mode 100644 src/views/hooks/request/cache.tsx delete mode 100644 src/views/hooks/request/debounce.tsx delete mode 100644 src/views/hooks/request/loading-delay.tsx delete mode 100644 src/views/hooks/request/mock-api.ts delete mode 100644 src/views/hooks/request/polling.tsx delete mode 100644 src/views/hooks/request/ready.tsx delete mode 100644 src/views/hooks/request/refresh-on-window-focus.tsx delete mode 100644 src/views/hooks/request/refresy-deps.tsx delete mode 100644 src/views/hooks/request/retry.tsx delete mode 100644 src/views/hooks/request/throttle.tsx diff --git a/.commitlintrc.cjs b/.commitlintrc.cjs index 9bb2aef74..0221cdc3a 100644 --- a/.commitlintrc.cjs +++ b/.commitlintrc.cjs @@ -61,7 +61,7 @@ module.exports = { }, customScopesAlign: !scopeComplete ? 'top' : 'bottom', defaultScope: scopeComplete, - scopes: [...scopes, 'mock'], + scopes: [...scopes], allowEmptyIssuePrefixs: false, allowCustomIssuePrefixs: false, diff --git a/.env b/.env index 361dcb23e..5b6fcbd13 100644 --- a/.env +++ b/.env @@ -1,2 +1,2 @@ # spa-title -VITE_GLOB_APP_TITLE = Vben Admin +VITE_GLOB_APP_TITLE = DaxPay多商户管理端 diff --git a/.env.analyze b/.env.analyze index 165728f10..74cf5d3bd 100644 --- a/.env.analyze +++ b/.env.analyze @@ -1,5 +1,3 @@ -# Whether to open mock -VITE_USE_MOCK = true # public path VITE_PUBLIC_PATH = / @@ -13,9 +11,6 @@ VITE_BUILD_COMPRESS = 'none' # Basic interface address SPA VITE_GLOB_API_URL = /basic-api -# File upload address, optional -# It can be forwarded by nginx or write the actual address directly -VITE_GLOB_UPLOAD_URL = /upload # Interface prefix VITE_GLOB_API_URL_PREFIX = diff --git a/.env.development b/.env.development index 0daf23b26..2c19ccc94 100644 --- a/.env.development +++ b/.env.development @@ -1,14 +1,12 @@ -# Whether to open mock -VITE_USE_MOCK = true -# public path -VITE_PUBLIC_PATH = / +# 发布路径 +VITE_PUBLIC_PATH=/ -# Basic interface address SPA -VITE_GLOB_API_URL = /basic-api +# 接口地址 +VITE_GLOB_API_URL=/server -# File upload address, optional -VITE_GLOB_UPLOAD_URL = /upload - -# Interface prefix +# 接口前缀 VITE_GLOB_API_URL_PREFIX = + +# 终端类型 +VITE_GLOB_APP_CLIENT=dax-pay diff --git a/.env.docker b/.env.docker index f7676e705..76319d1f8 100644 --- a/.env.docker +++ b/.env.docker @@ -1,5 +1,3 @@ -# Whether to open mock -VITE_USE_MOCK = false # public path VITE_PUBLIC_PATH = / @@ -15,8 +13,5 @@ VITE_DROP_CONSOLE = true VITE_BUILD_COMPRESS = 'none' VITE_GLOB_API_URL = "__vg_base_url" -# File upload address, optional -# It can be forwarded by nginx or write the actual address directly -VITE_GLOB_UPLOAD_URL = /files/upload # Interface prefix VITE_GLOB_API_URL_PREFIX = diff --git a/.env.production b/.env.production index 03f5ec342..c252fd8c6 100644 --- a/.env.production +++ b/.env.production @@ -1,5 +1,3 @@ -# Whether to open mock -VITE_USE_MOCK = true # public path VITE_PUBLIC_PATH = / @@ -13,9 +11,5 @@ VITE_BUILD_COMPRESS = 'gzip' # Basic interface address SPA VITE_GLOB_API_URL = /basic-api -# File upload address, optional -# It can be forwarded by nginx or write the actual address directly -VITE_GLOB_UPLOAD_URL = /upload - # Interface prefix VITE_GLOB_API_URL_PREFIX = diff --git a/.env.test b/.env.test index f18e16ce9..d9c63423f 100644 --- a/.env.test +++ b/.env.test @@ -1,6 +1,4 @@ NODE_ENV = production -# Whether to open mock -VITE_USE_MOCK = true # public path VITE_PUBLIC_PATH = / @@ -13,9 +11,6 @@ VITE_BUILD_COMPRESS = 'none' # Basic interface address SPA VITE_GLOB_API_URL = /basic-api -# File upload address, optional -# It can be forwarded by nginx or write the actual address directly -VITE_GLOB_UPLOAD_URL = /upload # Interface prefix VITE_GLOB_API_URL_PREFIX = diff --git a/.vscode/settings.json b/.vscode/settings.json index 20aa576e6..aece65f5c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -115,7 +115,6 @@ "iconify", "INTLIFY", "lintstagedrc", - "mockjs", "nprogress", "pinia", "pnpm", diff --git a/internal/eslint-config/build.config.ts b/internal/eslint-config/build.config.ts index 08301e5e1..e4719045d 100644 --- a/internal/eslint-config/build.config.ts +++ b/internal/eslint-config/build.config.ts @@ -1,4 +1,4 @@ -import { defineBuildConfig } from 'unbuild'; +import { defineBuildConfig } from 'unbuild' export default defineBuildConfig({ clean: true, @@ -7,4 +7,4 @@ export default defineBuildConfig({ rollup: { emitCJS: true, }, -}); +}) diff --git a/internal/eslint-config/src/index.ts b/internal/eslint-config/src/index.ts index 1138bb376..95ff26b1f 100644 --- a/internal/eslint-config/src/index.ts +++ b/internal/eslint-config/src/index.ts @@ -88,4 +88,4 @@ export default { // ], }, globals: { defineOptions: 'readonly' }, -}; +} diff --git a/internal/eslint-config/src/strict.ts b/internal/eslint-config/src/strict.ts index 5dbf5b700..837500fcb 100644 --- a/internal/eslint-config/src/strict.ts +++ b/internal/eslint-config/src/strict.ts @@ -54,4 +54,4 @@ export default { 'vue/attributes-order': 'error', 'vue/require-default-prop': 'error', }, -}; +} diff --git a/internal/stylelint-config/build.config.ts b/internal/stylelint-config/build.config.ts index 20c8b54a1..aef3e10bd 100644 --- a/internal/stylelint-config/build.config.ts +++ b/internal/stylelint-config/build.config.ts @@ -1,4 +1,4 @@ -import { defineBuildConfig } from 'unbuild'; +import { defineBuildConfig } from 'unbuild' export default defineBuildConfig({ clean: true, @@ -7,4 +7,4 @@ export default defineBuildConfig({ rollup: { emitCJS: true, }, -}); +}) diff --git a/internal/stylelint-config/src/index.ts b/internal/stylelint-config/src/index.ts index 8b15456db..b8cb663ea 100644 --- a/internal/stylelint-config/src/index.ts +++ b/internal/stylelint-config/src/index.ts @@ -89,4 +89,4 @@ export default { ], }, ignoreFiles: ['**/*.js', '**/*.jsx', '**/*.tsx', '**/*.ts'], -}; +} diff --git a/internal/ts-config/base.json b/internal/ts-config/base.json index 8b900543d..1b343ca91 100644 --- a/internal/ts-config/base.json +++ b/internal/ts-config/base.json @@ -8,7 +8,7 @@ "strict": true, "declaration": true, "noImplicitOverride": true, - "noUnusedLocals": true, + "noUnusedLocals": false, "esModuleInterop": true, "useUnknownInCatchVariables": false, "composite": false, diff --git a/internal/vite-config/build.config.ts b/internal/vite-config/build.config.ts index 20c8b54a1..aef3e10bd 100644 --- a/internal/vite-config/build.config.ts +++ b/internal/vite-config/build.config.ts @@ -1,4 +1,4 @@ -import { defineBuildConfig } from 'unbuild'; +import { defineBuildConfig } from 'unbuild' export default defineBuildConfig({ clean: true, @@ -7,4 +7,4 @@ export default defineBuildConfig({ rollup: { emitCJS: true, }, -}); +}) diff --git a/internal/vite-config/package.json b/internal/vite-config/package.json index 86d44e2ef..6d20f8d80 100644 --- a/internal/vite-config/package.json +++ b/internal/vite-config/package.json @@ -52,7 +52,6 @@ "vite-plugin-compression": "^0.5.1", "vite-plugin-dts": "^3.9.0", "vite-plugin-html": "^3.2.2", - "vite-plugin-mock": "^2.9.6", "vite-plugin-purge-icons": "^0.10.0", "vite-plugin-svg-icons": "^2.0.1" } diff --git a/internal/vite-config/src/config/application.ts b/internal/vite-config/src/config/application.ts index 7ee5ef1dc..fe92a94b4 100644 --- a/internal/vite-config/src/config/application.ts +++ b/internal/vite-config/src/config/application.ts @@ -1,41 +1,37 @@ -import { resolve } from 'node:path'; +import { resolve } from 'node:path' -import dayjs from 'dayjs'; -import { readPackageJSON } from 'pkg-types'; -import { defineConfig, loadEnv, mergeConfig, type UserConfig } from 'vite'; +import dayjs from 'dayjs' +import { readPackageJSON } from 'pkg-types' +import { defineConfig, loadEnv, mergeConfig, type UserConfig } from 'vite' -import { createPlugins } from '../plugins'; -import { generateModifyVars } from '../utils/modifyVars'; -import { commonConfig } from './common'; +import { createPlugins } from '../plugins' +import { generateModifyVars } from '../utils/modifyVars' +import { commonConfig } from './common' interface DefineOptions { - overrides?: UserConfig; + overrides?: UserConfig options?: { // - }; + } } function defineApplicationConfig(defineOptions: DefineOptions = {}) { - const { overrides = {} } = defineOptions; + const { overrides = {} } = defineOptions return defineConfig(async ({ command, mode }) => { - const root = process.cwd(); - const isBuild = command === 'build'; - const { VITE_PUBLIC_PATH, VITE_USE_MOCK, VITE_BUILD_COMPRESS, VITE_ENABLE_ANALYZE } = loadEnv( - mode, - root, - ); + const root = process.cwd() + const isBuild = command === 'build' + const { VITE_PUBLIC_PATH, VITE_BUILD_COMPRESS, VITE_ENABLE_ANALYZE } = loadEnv(mode, root) - const defineData = await createDefineData(root); + const defineData = await createDefineData(root) const plugins = await createPlugins({ isBuild, root, enableAnalyze: VITE_ENABLE_ANALYZE === 'true', - enableMock: VITE_USE_MOCK === 'true', compress: VITE_BUILD_COMPRESS, - }); + }) - const pathResolve = (pathname: string) => resolve(root, '.', pathname); + const pathResolve = (pathname: string) => resolve(root, '.', pathname) const applicationConfig: UserConfig = { base: VITE_PUBLIC_PATH, @@ -81,29 +77,29 @@ function defineApplicationConfig(defineOptions: DefineOptions = {}) { }, }, plugins, - }; + } - const mergedConfig = mergeConfig(commonConfig(mode), applicationConfig); + const mergedConfig = mergeConfig(commonConfig(mode), applicationConfig) - return mergeConfig(mergedConfig, overrides); - }); + return mergeConfig(mergedConfig, overrides) + }) } async function createDefineData(root: string) { try { - const pkgJson = await readPackageJSON(root); - const { dependencies, devDependencies, name, version } = pkgJson; + const pkgJson = await readPackageJSON(root) + const { dependencies, devDependencies, name, version } = pkgJson const __APP_INFO__ = { pkg: { dependencies, devDependencies, name, version }, lastBuildTime: dayjs().format('YYYY-MM-DD HH:mm:ss'), - }; + } return { __APP_INFO__: JSON.stringify(__APP_INFO__), - }; + } } catch (error) { - return {}; + return {} } } -export { defineApplicationConfig }; +export { defineApplicationConfig } diff --git a/internal/vite-config/src/config/common.ts b/internal/vite-config/src/config/common.ts index 559896eb2..ff0de1dcf 100644 --- a/internal/vite-config/src/config/common.ts +++ b/internal/vite-config/src/config/common.ts @@ -1,5 +1,5 @@ -import UnoCSS from 'unocss/vite'; -import { type UserConfig } from 'vite'; +import UnoCSS from 'unocss/vite' +import { type UserConfig } from 'vite' const commonConfig: (mode: string) => UserConfig = (mode) => ({ server: { @@ -17,6 +17,6 @@ const commonConfig: (mode: string) => UserConfig = (mode) => ({ }, }, plugins: [UnoCSS()], -}); +}) -export { commonConfig }; +export { commonConfig } diff --git a/internal/vite-config/src/config/package.ts b/internal/vite-config/src/config/package.ts index ab8385271..a860b99e0 100644 --- a/internal/vite-config/src/config/package.ts +++ b/internal/vite-config/src/config/package.ts @@ -1,21 +1,21 @@ -import { readPackageJSON } from 'pkg-types'; -import { defineConfig, mergeConfig, type UserConfig } from 'vite'; -import dts from 'vite-plugin-dts'; +import { readPackageJSON } from 'pkg-types' +import { defineConfig, mergeConfig, type UserConfig } from 'vite' +import dts from 'vite-plugin-dts' -import { commonConfig } from './common'; +import { commonConfig } from './common' interface DefineOptions { - overrides?: UserConfig; + overrides?: UserConfig options?: { // - }; + } } function definePackageConfig(defineOptions: DefineOptions = {}) { - const { overrides = {} } = defineOptions; - const root = process.cwd(); + const { overrides = {} } = defineOptions + const root = process.cwd() return defineConfig(async ({ mode }) => { - const { dependencies = {}, peerDependencies = {} } = await readPackageJSON(root); + const { dependencies = {}, peerDependencies = {} } = await readPackageJSON(root) const packageConfig: UserConfig = { build: { lib: { @@ -32,11 +32,11 @@ function definePackageConfig(defineOptions: DefineOptions = {}) { logLevel: 'error', }), ], - }; - const mergedConfig = mergeConfig(commonConfig(mode), packageConfig); + } + const mergedConfig = mergeConfig(commonConfig(mode), packageConfig) - return mergeConfig(mergedConfig, overrides); - }); + return mergeConfig(mergedConfig, overrides) + }) } -export { definePackageConfig }; +export { definePackageConfig } diff --git a/internal/vite-config/src/index.ts b/internal/vite-config/src/index.ts index 9ef1e80fa..10e9af8e5 100644 --- a/internal/vite-config/src/index.ts +++ b/internal/vite-config/src/index.ts @@ -1,2 +1,2 @@ -export * from './config/application'; -export * from './config/package'; +export * from './config/application' +export * from './config/package' diff --git a/internal/vite-config/src/plugins/appConfig.ts b/internal/vite-config/src/plugins/appConfig.ts index 7d5066236..73c91e1df 100644 --- a/internal/vite-config/src/plugins/appConfig.ts +++ b/internal/vite-config/src/plugins/appConfig.ts @@ -1,43 +1,43 @@ -import colors from 'picocolors'; -import { readPackageJSON } from 'pkg-types'; -import { type PluginOption } from 'vite'; +import colors from 'picocolors' +import { readPackageJSON } from 'pkg-types' +import { type PluginOption } from 'vite' -import { getEnvConfig } from '../utils/env'; -import { createContentHash } from '../utils/hash'; +import { getEnvConfig } from '../utils/env' +import { createContentHash } from '../utils/hash' -const GLOBAL_CONFIG_FILE_NAME = '_app.config.js'; -const PLUGIN_NAME = 'app-config'; +const GLOBAL_CONFIG_FILE_NAME = '_app.config.js' +const PLUGIN_NAME = 'app-config' async function createAppConfigPlugin({ root, isBuild, }: { - root: string; - isBuild: boolean; + root: string + isBuild: boolean }): Promise { - let publicPath: string; - let source: string; + let publicPath: string + let source: string if (!isBuild) { return { name: PLUGIN_NAME, - }; + } } - const { version = '' } = await readPackageJSON(root); + const { version = '' } = await readPackageJSON(root) return { name: PLUGIN_NAME, async configResolved(_config) { - const appTitle = _config?.env?.VITE_GLOB_APP_TITLE ?? ''; + const appTitle = _config?.env?.VITE_GLOB_APP_TITLE ?? '' // appTitle = appTitle.replace(/\s/g, '_').replace(/-/g, '_'); - publicPath = _config.base; - source = await getConfigSource(appTitle); + publicPath = _config.base + source = await getConfigSource(appTitle) }, async transformIndexHtml(html) { - publicPath = publicPath.endsWith('/') ? publicPath : `${publicPath}/`; + publicPath = publicPath.endsWith('/') ? publicPath : `${publicPath}/` const appConfigSrc = `${ publicPath || '/' - }${GLOBAL_CONFIG_FILE_NAME}?v=${version}-${createContentHash(source)}`; + }${GLOBAL_CONFIG_FILE_NAME}?v=${version}-${createContentHash(source)}` return { html, @@ -49,7 +49,7 @@ async function createAppConfigPlugin({ }, }, ], - }; + } }, async generateBundle() { try { @@ -57,16 +57,16 @@ async function createAppConfigPlugin({ type: 'asset', fileName: GLOBAL_CONFIG_FILE_NAME, source, - }); + }) - console.log(colors.cyan(`✨configuration file is build successfully!`)); + console.log(colors.cyan(`✨configuration file is build successfully!`)) } catch (error) { console.log( colors.red('configuration file configuration file failed to package:\n' + error), - ); + ) } }, - }; + } } /** @@ -75,30 +75,30 @@ async function createAppConfigPlugin({ */ const getVariableName = (title: string) => { function strToHex(str: string) { - const result: string[] = []; + const result: string[] = [] for (let i = 0; i < str.length; ++i) { - const hex = str.charCodeAt(i).toString(16); - result.push(('000' + hex).slice(-4)); + const hex = str.charCodeAt(i).toString(16) + result.push(('000' + hex).slice(-4)) } - return result.join('').toUpperCase(); + return result.join('').toUpperCase() } - return `__PRODUCTION__${strToHex(title) || '__APP'}__CONF__`.toUpperCase().replace(/\s/g, ''); -}; + return `__PRODUCTION__${strToHex(title) || '__APP'}__CONF__`.toUpperCase().replace(/\s/g, '') +} async function getConfigSource(appTitle: string) { - const config = await getEnvConfig(); - const variableName = getVariableName(appTitle); - const windowVariable = `window.${variableName}`; + const config = await getEnvConfig() + const variableName = getVariableName(appTitle) + const windowVariable = `window.${variableName}` // Ensure that the variable will not be modified - let source = `${windowVariable}=${JSON.stringify(config)};`; + let source = `${windowVariable}=${JSON.stringify(config)};` source += ` Object.freeze(${windowVariable}); Object.defineProperty(window, "${variableName}", { configurable: false, writable: false, }); - `.replace(/\s/g, ''); - return source; + `.replace(/\s/g, '') + return source } -export { createAppConfigPlugin }; +export { createAppConfigPlugin } diff --git a/internal/vite-config/src/plugins/compress.ts b/internal/vite-config/src/plugins/compress.ts index 8fc139765..e695bbe14 100644 --- a/internal/vite-config/src/plugins/compress.ts +++ b/internal/vite-config/src/plugins/compress.ts @@ -2,19 +2,19 @@ * Used to package and output gzip. Note that this does not work properly in Vite, the specific reason is still being investigated * https://github.com/anncwb/vite-plugin-compression */ -import type { PluginOption } from 'vite'; -import compressPlugin from 'vite-plugin-compression'; +import type { PluginOption } from 'vite' +import compressPlugin from 'vite-plugin-compression' export function configCompressPlugin({ compress, deleteOriginFile = false, }: { - compress: string; - deleteOriginFile?: boolean; + compress: string + deleteOriginFile?: boolean }): PluginOption[] { - const compressList = compress.split(','); + const compressList = compress.split(',') - const plugins: PluginOption[] = []; + const plugins: PluginOption[] = [] if (compressList.includes('gzip')) { plugins.push( @@ -22,7 +22,7 @@ export function configCompressPlugin({ ext: '.gz', deleteOriginFile, }), - ); + ) } if (compressList.includes('brotli')) { @@ -32,7 +32,7 @@ export function configCompressPlugin({ algorithm: 'brotliCompress', deleteOriginFile, }), - ); + ) } - return plugins; + return plugins } diff --git a/internal/vite-config/src/plugins/html.ts b/internal/vite-config/src/plugins/html.ts index a01b43a03..28285d9e9 100644 --- a/internal/vite-config/src/plugins/html.ts +++ b/internal/vite-config/src/plugins/html.ts @@ -2,12 +2,12 @@ * Plugin to minimize and use ejs template syntax in index.html. * https://github.com/anncwb/vite-plugin-html */ -import type { PluginOption } from 'vite'; -import { createHtmlPlugin } from 'vite-plugin-html'; +import type { PluginOption } from 'vite' +import { createHtmlPlugin } from 'vite-plugin-html' export function configHtmlPlugin({ isBuild }: { isBuild: boolean }) { const htmlPlugin: PluginOption[] = createHtmlPlugin({ minify: isBuild, - }); - return htmlPlugin; + }) + return htmlPlugin } diff --git a/internal/vite-config/src/plugins/index.ts b/internal/vite-config/src/plugins/index.ts index 77b746685..0dea375b8 100644 --- a/internal/vite-config/src/plugins/index.ts +++ b/internal/vite-config/src/plugins/index.ts @@ -1,40 +1,40 @@ -import vue from '@vitejs/plugin-vue'; -import vueJsx from '@vitejs/plugin-vue-jsx'; -import { type PluginOption } from 'vite'; -import purgeIcons from 'vite-plugin-purge-icons'; -import DevTools from 'vite-plugin-vue-devtools'; +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' +import { type PluginOption } from 'vite' +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +import purgeIcons from 'vite-plugin-purge-icons' +import DevTools from 'vite-plugin-vue-devtools' -import { createAppConfigPlugin } from './appConfig'; -import { configCompressPlugin } from './compress'; -import { configHtmlPlugin } from './html'; -import { configMockPlugin } from './mock'; -import { configSvgIconsPlugin } from './svgSprite'; -import { configVisualizerConfig } from './visualizer'; +import { createAppConfigPlugin } from './appConfig' +import { configCompressPlugin } from './compress' +import { configHtmlPlugin } from './html' +import { configSvgIconsPlugin } from './svgSprite' +import { configVisualizerConfig } from './visualizer' interface Options { - isBuild: boolean; - root: string; - compress: string; - enableMock?: boolean; - enableAnalyze?: boolean; + isBuild: boolean + root: string + compress: string + enableAnalyze?: boolean } -async function createPlugins({ isBuild, root, enableMock, compress, enableAnalyze }: Options) { - const vitePlugins: (PluginOption | PluginOption[])[] = [vue(), vueJsx()]; +async function createPlugins({ isBuild, root, compress, enableAnalyze }: Options) { + const vitePlugins: (PluginOption | PluginOption[])[] = [vue(), vueJsx()] - const appConfigPlugin = await createAppConfigPlugin({ root, isBuild }); - vitePlugins.push(appConfigPlugin); + const appConfigPlugin = await createAppConfigPlugin({ root, isBuild }) + vitePlugins.push(appConfigPlugin) - vitePlugins.push(DevTools()); + vitePlugins.push(DevTools()) // vite-plugin-html - vitePlugins.push(configHtmlPlugin({ isBuild })); + vitePlugins.push(configHtmlPlugin({ isBuild })) // vite-plugin-svg-icons - vitePlugins.push(configSvgIconsPlugin({ isBuild })); + vitePlugins.push(configSvgIconsPlugin({ isBuild })) // vite-plugin-purge-icons - vitePlugins.push(purgeIcons()); + vitePlugins.push(purgeIcons()) // The following plugins only work in the production environment if (isBuild) { @@ -43,20 +43,15 @@ async function createPlugins({ isBuild, root, enableMock, compress, enableAnalyz configCompressPlugin({ compress, }), - ); + ) } // rollup-plugin-visualizer if (enableAnalyze) { - vitePlugins.push(configVisualizerConfig()); + vitePlugins.push(configVisualizerConfig()) } - // vite-plugin-mock - if (enableMock) { - vitePlugins.push(configMockPlugin({ isBuild })); - } - - return vitePlugins; + return vitePlugins } -export { createPlugins }; +export { createPlugins } diff --git a/internal/vite-config/src/plugins/mock.ts b/internal/vite-config/src/plugins/mock.ts deleted file mode 100644 index b47899c00..000000000 --- a/internal/vite-config/src/plugins/mock.ts +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Mock plugin for development and production. - * https://github.com/anncwb/vite-plugin-mock - */ -import { viteMockServe } from 'vite-plugin-mock'; - -export function configMockPlugin({ isBuild }: { isBuild: boolean }) { - return viteMockServe({ - ignore: /^_/, - mockPath: 'mock', - localEnabled: !isBuild, - prodEnabled: isBuild, - injectCode: ` - import { setupProdMockServer } from '../mock/_createProductionServer'; - - setupProdMockServer(); - `, - }); -} diff --git a/internal/vite-config/src/plugins/svgSprite.ts b/internal/vite-config/src/plugins/svgSprite.ts index 659e5af7f..910d7ff68 100644 --- a/internal/vite-config/src/plugins/svgSprite.ts +++ b/internal/vite-config/src/plugins/svgSprite.ts @@ -3,15 +3,15 @@ * https://github.com/anncwb/vite-plugin-svg-icons */ -import { resolve } from 'node:path'; +import { resolve } from 'node:path' -import type { PluginOption } from 'vite'; -import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'; +import type { PluginOption } from 'vite' +import { createSvgIconsPlugin } from 'vite-plugin-svg-icons' export function configSvgIconsPlugin({ isBuild }: { isBuild: boolean }) { const svgIconsPlugin = createSvgIconsPlugin({ iconDirs: [resolve(process.cwd(), 'src/assets/icons')], svgoOptions: isBuild, - }); - return svgIconsPlugin as PluginOption; + }) + return svgIconsPlugin as PluginOption } diff --git a/internal/vite-config/src/plugins/visualizer.ts b/internal/vite-config/src/plugins/visualizer.ts index 0b6ba6214..d5d11a36c 100644 --- a/internal/vite-config/src/plugins/visualizer.ts +++ b/internal/vite-config/src/plugins/visualizer.ts @@ -1,8 +1,8 @@ /** * Package file volume analysis */ -import visualizer from 'rollup-plugin-visualizer'; -import { type PluginOption } from 'vite'; +import visualizer from 'rollup-plugin-visualizer' +import { type PluginOption } from 'vite' export function configVisualizerConfig() { return visualizer({ @@ -10,5 +10,5 @@ export function configVisualizerConfig() { open: true, gzipSize: true, brotliSize: true, - }) as PluginOption; + }) as PluginOption } diff --git a/internal/vite-config/src/utils/env.ts b/internal/vite-config/src/utils/env.ts index c84ea943a..3c9d23728 100644 --- a/internal/vite-config/src/utils/env.ts +++ b/internal/vite-config/src/utils/env.ts @@ -1,20 +1,20 @@ -import { join } from 'node:path'; +import { join } from 'node:path' -import dotenv from 'dotenv'; -import { readFile } from 'fs-extra'; +import dotenv from 'dotenv' +import { readFile } from 'fs-extra' /** * 获取当前环境下生效的配置文件名 */ function getConfFiles() { - const script = process.env.npm_lifecycle_script as string; - const reg = new RegExp('--mode ([a-z_\\d]+)'); - const result = reg.exec(script); + const script = process.env.npm_lifecycle_script as string + const reg = new RegExp('--mode ([a-z_\\d]+)') + const result = reg.exec(script) if (result) { - const mode = result[1]; - return ['.env', `.env.${mode}`]; + const mode = result[1] + return ['.env', `.env.${mode}`] } - return ['.env', '.env.production']; + return ['.env', '.env.production'] } /** @@ -26,24 +26,24 @@ export async function getEnvConfig( match = 'VITE_GLOB_', confFiles = getConfFiles(), ): Promise<{ - [key: string]: string; + [key: string]: string }> { - let envConfig = {}; + let envConfig = {} for (const confFile of confFiles) { try { - const envPath = await readFile(join(process.cwd(), confFile), { encoding: 'utf8' }); - const env = dotenv.parse(envPath); - envConfig = { ...envConfig, ...env }; + const envPath = await readFile(join(process.cwd(), confFile), { encoding: 'utf8' }) + const env = dotenv.parse(envPath) + envConfig = { ...envConfig, ...env } } catch (e) { - console.error(`Error in parsing ${confFile}`, e); + console.error(`Error in parsing ${confFile}`, e) } } - const reg = new RegExp(`^(${match})`); + const reg = new RegExp(`^(${match})`) Object.keys(envConfig).forEach((key) => { if (!reg.test(key)) { - Reflect.deleteProperty(envConfig, key); + Reflect.deleteProperty(envConfig, key) } - }); - return envConfig; + }) + return envConfig } diff --git a/internal/vite-config/src/utils/hash.ts b/internal/vite-config/src/utils/hash.ts index 0b5a7c976..16a46b7c2 100644 --- a/internal/vite-config/src/utils/hash.ts +++ b/internal/vite-config/src/utils/hash.ts @@ -1,16 +1,16 @@ -import { createHash } from 'node:crypto'; +import { createHash } from 'node:crypto' function createContentHash(content: string, hashLSize = 12) { - const hash = createHash('sha256').update(content); - return hash.digest('hex').slice(0, hashLSize); + const hash = createHash('sha256').update(content) + return hash.digest('hex').slice(0, hashLSize) } function strToHex(str: string) { - const result: string[] = []; + const result: string[] = [] for (let i = 0; i < str.length; ++i) { - const hex = str.charCodeAt(i).toString(16); - result.push(('000' + hex).slice(-4)); + const hex = str.charCodeAt(i).toString(16) + result.push(('000' + hex).slice(-4)) } - return result.join('').toUpperCase(); + return result.join('').toUpperCase() } -export { createContentHash, strToHex }; +export { createContentHash, strToHex } diff --git a/internal/vite-config/src/utils/modifyVars.ts b/internal/vite-config/src/utils/modifyVars.ts index 0554343cb..47f3763d8 100644 --- a/internal/vite-config/src/utils/modifyVars.ts +++ b/internal/vite-config/src/utils/modifyVars.ts @@ -1,34 +1,34 @@ -import { resolve } from 'node:path'; +import { resolve } from 'node:path' -import { generate } from '@ant-design/colors'; +import { generate } from '@ant-design/colors' // @ts-ignore: typo /* import { getThemeVariables } from 'ant-design-vue/dist/theme'; */ -import { theme } from 'ant-design-vue/lib'; -import convertLegacyToken from 'ant-design-vue/lib/theme/convertLegacyToken'; +import { theme } from 'ant-design-vue/lib' +import convertLegacyToken from 'ant-design-vue/lib/theme/convertLegacyToken' -const { defaultAlgorithm, defaultSeed } = theme; -const primaryColor = '#0960bd'; +const { defaultAlgorithm, defaultSeed } = theme +const primaryColor = '#0960bd' function generateAntColors(color: string, theme: 'default' | 'dark' = 'default') { return generate(color, { theme, - }); + }) } /** * less global variable */ export function generateModifyVars() { - const palettes = generateAntColors(primaryColor); - const primary = palettes[5]; - const primaryColorObj: Record = {}; + const palettes = generateAntColors(primaryColor) + const primary = palettes[5] + const primaryColorObj: Record = {} for (let index = 0; index < 10; index++) { - primaryColorObj[`primary-${index + 1}`] = palettes[index]; + primaryColorObj[`primary-${index + 1}`] = palettes[index] } // const modifyVars = getThemeVariables(); - const mapToken = defaultAlgorithm(defaultSeed); - const v3Token = convertLegacyToken(mapToken); + const mapToken = defaultAlgorithm(defaultSeed) + const v3Token = convertLegacyToken(mapToken) return { ...v3Token, // reference: Avoid repeated references @@ -43,5 +43,5 @@ export function generateModifyVars() { 'font-size-base': '14px', // Main font size 'border-radius-base': '2px', // Component/float fillet 'link-color': primary, // Link color - }; + } } diff --git a/mock/_createProductionServer.ts b/mock/_createProductionServer.ts deleted file mode 100644 index 4e80843e4..000000000 --- a/mock/_createProductionServer.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { createProdMockServer } from 'vite-plugin-mock/es/createProdMockServer' - -// 问题描述 -// 1. `import.meta.globEager` 已被弃用, 需要升级vite版本,有兼容问题 -// 2. `vite-plugin-mock` 插件问题 https://github.com/vbenjs/vite-plugin-mock/issues/56 - -// const modules: Record = import.meta.glob("./**/*.ts", { -// import: "default", -// eager: true, -// }); - -// const mockModules = Object.keys(modules).reduce((pre, key) => { -// if (!key.includes("/_")) { -// pre.push(...modules[key]); -// } -// return pre; -// }, [] as any[]); - -const modules = import.meta.glob('./**/*.ts', { eager: true }) - -const mockModules: any[] = [] -Object.keys(modules).forEach((key) => { - if (key.includes('/_')) { - return - } - mockModules.push(...(modules as Recordable)[key].default) -}) - -/** - * Used in a production environment. Need to manually import all modules - */ -export function setupProdMockServer() { - createProdMockServer(mockModules) -} diff --git a/mock/_util.ts b/mock/_util.ts deleted file mode 100644 index bad847f18..000000000 --- a/mock/_util.ts +++ /dev/null @@ -1,52 +0,0 @@ -// Interface data format used to return a unified format -import { ResultEnum } from '@/enums/httpEnum' - -export function resultSuccess(result: T, { message = 'ok' } = {}) { - return { - code: ResultEnum.SUCCESS, - result, - message, - type: 'success', - } -} - -export function resultPageSuccess(page: number, pageSize: number, list: T[], { message = 'ok' } = {}) { - const pageData = pagination(page, pageSize, list) - - return { - ...resultSuccess({ - items: pageData, - total: list.length, - }), - message, - } -} - -export function resultError(message = 'Request failed', { code = ResultEnum.ERROR, result = null } = {}) { - return { - code, - result, - message, - type: 'error', - } -} - -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.length) : array.slice(offset, offset + Number(pageSize)) -} - -export interface requestParams { - method: string - body: any - headers?: { authorization?: string } - query: any -} - -/** - * @description 本函数用于从request数据中获取token,请根据项目的实际情况修改 - * - */ -export function getRequestToken({ headers }: requestParams): string | undefined { - return headers?.authorization -} diff --git a/mock/demo/account.ts b/mock/demo/account.ts deleted file mode 100644 index 74194f10c..000000000 --- a/mock/demo/account.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { MockMethod } from 'vite-plugin-mock' -import { resultSuccess, resultError } from '../_util' -import { ResultEnum } from '@/enums/httpEnum' - -const userInfo = { - name: 'Vben', - userid: '00000001', - email: 'test@gmail.com', - signature: '海纳百川,有容乃大', - introduction: '微笑着,努力着,欣赏着', - title: '交互专家', - group: '某某某事业群-某某平台部-某某技术部-UED', - tags: [ - { - key: '0', - label: '很有想法的', - }, - { - key: '1', - label: '专注设计', - }, - { - key: '2', - label: '辣~', - }, - { - key: '3', - label: '大长腿', - }, - { - key: '4', - label: '川妹子', - }, - { - key: '5', - label: '海纳百川', - }, - ], - notifyCount: 12, - unreadCount: 11, - country: 'China', - address: 'Xiamen City 77', - phone: '0592-268888888', -} - -export default [ - { - url: '/basic-api/account/getAccountInfo', - timeout: 1000, - method: 'get', - response: () => { - return resultSuccess(userInfo) - }, - }, - { - url: '/basic-api/user/sessionTimeout', - method: 'post', - statusCode: 401, - response: () => { - return resultError() - }, - }, - { - url: '/basic-api/user/tokenExpired', - method: 'post', - statusCode: 200, - response: () => { - return resultError('Token Expired!', { code: ResultEnum.TIMEOUT as number }) - }, - }, -] as MockMethod[] diff --git a/mock/demo/api-cascader.ts b/mock/demo/api-cascader.ts deleted file mode 100644 index dcaf322cd..000000000 --- a/mock/demo/api-cascader.ts +++ /dev/null @@ -1,325 +0,0 @@ -import { MockMethod } from 'vite-plugin-mock' -import { resultSuccess } from '../_util' - -const areaList: any[] = [ - { - id: '530825900854620160', - code: '430000', - parentCode: '100000', - levelType: 1, - name: '湖南省', - province: '湖南省', - city: null, - district: null, - town: null, - village: null, - parentPath: '430000', - createTime: '2020-11-30 15:47:31', - updateTime: '2020-11-30 16:33:42', - customized: false, - usable: true, - }, - { - id: '530825900883980288', - code: '430100', - parentCode: '430000', - levelType: 2, - name: '长沙市', - province: '湖南省', - city: '长沙市', - district: null, - town: null, - village: null, - parentPath: '430000,430100', - createTime: '2020-11-30 15:47:31', - updateTime: '2020-11-30 16:33:42', - customized: false, - usable: true, - }, - { - id: '530825900951089152', - code: '430102', - parentCode: '430100', - levelType: 3, - name: '芙蓉区', - province: '湖南省', - city: '长沙市', - district: '芙蓉区', - town: null, - village: null, - parentPath: '430000,430100,430102', - createTime: '2020-11-30 15:47:31', - updateTime: '2020-11-30 16:33:42', - customized: false, - usable: true, - }, - { - id: '530825901014003712', - code: '430104', - parentCode: '430100', - levelType: 3, - name: '岳麓区', - province: '湖南省', - city: '长沙市', - district: '岳麓区', - town: null, - village: null, - parentPath: '430000,430100,430104', - createTime: '2020-11-30 15:47:31', - updateTime: '2020-11-30 16:33:42', - customized: false, - usable: true, - }, - { - id: '530825900988837888', - code: '430103', - parentCode: '430100', - levelType: 3, - name: '天心区', - province: '湖南省', - city: '长沙市', - district: '天心区', - town: null, - village: null, - parentPath: '430000,430100,430103', - createTime: '2020-11-30 15:47:31', - updateTime: '2020-11-30 16:33:42', - customized: false, - usable: true, - }, - { - id: '530826672489115648', - code: '430103002', - parentCode: '430103', - levelType: 4, - name: '坡子街街道', - province: '湖南省', - city: '长沙市', - district: '天心区', - town: '坡子街街道', - village: null, - parentPath: '430000,430100,430103,430103002', - createTime: '2020-11-30 15:47:31', - updateTime: '2020-12-14 15:26:43', - customized: false, - usable: true, - }, - { - id: '530840241171607552', - code: '430103002001', - parentCode: '430103002', - levelType: 5, - name: '八角亭社区', - province: '湖南省', - city: '长沙市', - district: '天心区', - town: '坡子街街道', - village: '八角亭社区', - parentPath: '430000,430100,430103,430103002,430103002001', - createTime: '2020-11-30 15:47:31', - updateTime: '2021-01-20 14:07:23', - customized: false, - usable: true, - }, - { - id: '530840241200967680', - code: '430103002002', - parentCode: '430103002', - levelType: 5, - name: '西牌楼社区', - province: '湖南省', - city: '长沙市', - district: '天心区', - town: '坡子街街道', - village: '西牌楼社区', - parentPath: '430000,430100,430103,430103002,430103002002', - createTime: '2020-11-30 15:47:31', - updateTime: '2020-11-30 17:30:41', - customized: false, - usable: true, - }, - { - id: '530840241230327808', - code: '430103002003', - parentCode: '430103002', - levelType: 5, - name: '太平街社区', - province: '湖南省', - city: '长沙市', - district: '天心区', - town: '坡子街街道', - village: '太平街社区', - parentPath: '430000,430100,430103,430103002,430103002003', - createTime: '2020-11-30 15:47:31', - updateTime: '2020-11-30 17:30:41', - customized: false, - usable: true, - }, - { - id: '530840241259687936', - code: '430103002005', - parentCode: '430103002', - levelType: 5, - name: '坡子街社区', - province: '湖南省', - city: '长沙市', - district: '天心区', - town: '坡子街街道', - village: '坡子街社区', - parentPath: '430000,430100,430103,430103002,430103002005', - createTime: '2020-11-30 15:47:31', - updateTime: '2020-11-30 17:30:41', - customized: false, - usable: true, - }, - { - id: '530840241284853760', - code: '430103002006', - parentCode: '430103002', - levelType: 5, - name: '青山祠社区', - province: '湖南省', - city: '长沙市', - district: '天心区', - town: '坡子街街道', - village: '青山祠社区', - parentPath: '430000,430100,430103,430103002,430103002006', - createTime: '2020-11-30 15:47:31', - updateTime: '2020-11-30 17:30:41', - customized: false, - usable: true, - }, - { - id: '530840241310019584', - code: '430103002007', - parentCode: '430103002', - levelType: 5, - name: '沙河社区', - province: '湖南省', - city: '长沙市', - district: '天心区', - town: '坡子街街道', - village: '沙河社区', - parentPath: '430000,430100,430103,430103002,430103002007', - createTime: '2020-11-30 15:47:31', - updateTime: '2020-11-30 17:30:41', - customized: false, - usable: true, - }, - { - id: '530840241381322752', - code: '430103002008', - parentCode: '430103002', - levelType: 5, - name: '碧湘社区', - province: '湖南省', - city: '长沙市', - district: '天心区', - town: '坡子街街道', - village: '碧湘社区', - parentPath: '430000,430100,430103,430103002,430103002008', - createTime: '2020-11-30 15:47:31', - updateTime: '2020-11-30 17:30:41', - customized: false, - usable: true, - }, - { - id: '530840241410682880', - code: '430103002009', - parentCode: '430103002', - levelType: 5, - name: '创远社区', - province: '湖南省', - city: '长沙市', - district: '天心区', - town: '坡子街街道', - village: '创远社区', - parentPath: '430000,430100,430103,430103002,430103002009', - createTime: '2020-11-30 15:47:31', - updateTime: '2020-11-30 17:30:41', - customized: false, - usable: true, - }, - { - id: '530840241431654400', - code: '430103002010', - parentCode: '430103002', - levelType: 5, - name: '楚湘社区', - province: '湖南省', - city: '长沙市', - district: '天心区', - town: '坡子街街道', - village: '楚湘社区', - parentPath: '430000,430100,430103,430103002,430103002010', - createTime: '2020-11-30 15:47:31', - updateTime: '2020-11-30 17:30:41', - customized: false, - usable: true, - }, - { - id: '530840241465208832', - code: '430103002011', - parentCode: '430103002', - levelType: 5, - name: '西湖社区', - province: '湖南省', - city: '长沙市', - district: '天心区', - town: '坡子街街道', - village: '西湖社区', - parentPath: '430000,430100,430103,430103002,430103002011', - createTime: '2020-11-30 15:47:31', - updateTime: '2020-11-30 17:30:41', - customized: false, - usable: true, - }, - { - id: '530840241502957568', - code: '430103002012', - parentCode: '430103002', - levelType: 5, - name: '登仁桥社区', - province: '湖南省', - city: '长沙市', - district: '天心区', - town: '坡子街街道', - village: '登仁桥社区', - parentPath: '430000,430100,430103,430103002,430103002012', - createTime: '2020-11-30 15:47:31', - updateTime: '2020-11-30 17:30:41', - customized: false, - usable: true, - }, - { - id: '530840241553289216', - code: '430103002013', - parentCode: '430103002', - levelType: 5, - name: '文庙坪社区', - province: '湖南省', - city: '长沙市', - district: '天心区', - town: '坡子街街道', - village: '文庙坪社区', - parentPath: '430000,430100,430103,430103002,430103002013', - createTime: '2020-11-30 15:47:31', - updateTime: '2020-11-30 17:30:41', - customized: false, - usable: true, - }, -] -export default [ - { - url: '/basic-api/cascader/getAreaRecord', - timeout: 1000, - method: 'post', - response: ({ body }) => { - const { parentCode } = body || {} - if (!parentCode) { - return resultSuccess(areaList.filter((it) => it.code === '430000')) - } - return resultSuccess(areaList.filter((it) => it.parentCode === parentCode)) - }, - }, -] as MockMethod[] diff --git a/mock/demo/select-demo.ts b/mock/demo/select-demo.ts deleted file mode 100644 index 7e248af4d..000000000 --- a/mock/demo/select-demo.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { MockMethod } from 'vite-plugin-mock' -import { resultSuccess } from '../_util' - -const demoList = (keyword, count = 20) => { - const result = { - list: [] as any[], - } - for (let index = 0; index < count; index++) { - result.list.push({ - name: `${keyword ?? ''}选项${index}`, - id: `${index}`, - }) - } - return result -} - -export default [ - { - url: '/basic-api/select/getDemoOptions', - timeout: 1000, - method: 'get', - response: ({ query }) => { - const { keyword, count } = query - console.log(keyword) - return resultSuccess(demoList(keyword, count)) - }, - }, -] as MockMethod[] diff --git a/mock/demo/system.ts b/mock/demo/system.ts deleted file mode 100644 index aac92ac11..000000000 --- a/mock/demo/system.ts +++ /dev/null @@ -1,195 +0,0 @@ -import { MockMethod } from 'vite-plugin-mock' -import { resultError, resultPageSuccess, resultSuccess } from '../_util' - -const accountList = (() => { - const result: any[] = [] - for (let index = 0; index < 20; index++) { - result.push({ - id: `${index}`, - account: '@first', - email: '@email', - nickname: '@cname()', - role: '@first', - createTime: '@datetime', - remark: '@cword(10,20)', - 'dept|0-2': 1, - 'status|1': ['0', '1'], - }) - } - return result -})() - -const roleList = (() => { - const result: any[] = [] - for (let index = 0; index < 4; index++) { - result.push({ - id: index + 1, - orderNo: `${index + 1}`, - roleName: ['超级管理员', '管理员', '文章管理员', '普通用户'][index], - roleValue: '@first', - createTime: '@datetime', - remark: '@cword(10,20)', - menu: [['0', '1', '2'], ['0', '1'], ['0', '2'], ['2']][index], - 'status|1': ['0', '1'], - }) - } - return result -})() - -const deptList = (() => { - const result: any[] = [] - for (let index = 0; index < 3; index++) { - result.push({ - id: `${index}`, - deptName: ['华东分部', '华南分部', '西北分部'][index], - orderNo: index + 1, - createTime: '@datetime', - remark: '@cword(10,20)', - 'status|1': ['0', '0', '1'], - children: (() => { - const children: any[] = [] - for (let j = 0; j < 4; j++) { - children.push({ - id: `${index}-${j}`, - deptName: ['研发部', '市场部', '商务部', '财务部'][j], - orderNo: j + 1, - createTime: '@datetime', - remark: '@cword(10,20)', - 'status|1': ['0', '1'], - parentDept: `${index}`, - children: undefined, - }) - } - return children - })(), - }) - } - return result -})() - -const menuList = (() => { - const result: any[] = [] - for (let index = 0; index < 3; index++) { - result.push({ - id: `${index}`, - icon: ['ion:layers-outline', 'ion:git-compare-outline', 'ion:tv-outline'][index], - component: 'LAYOUT', - type: '0', - menuName: ['Dashboard', '权限管理', '功能'][index], - permission: '', - orderNo: index + 1, - createTime: '@datetime', - 'status|1': ['0', '0', '1'], - children: (() => { - const children: any[] = [] - for (let j = 0; j < 4; j++) { - children.push({ - id: `${index}-${j}`, - type: '1', - menuName: ['菜单1', '菜单2', '菜单3', '菜单4'][j], - icon: 'ion:document', - permission: ['menu1:view', 'menu2:add', 'menu3:update', 'menu4:del'][index], - component: ['/dashboard/welcome/index', '/dashboard/analysis/index', '/dashboard/workbench/index', '/dashboard/test/index'][j], - orderNo: j + 1, - createTime: '@datetime', - 'status|1': ['0', '1'], - parentMenu: `${index}`, - children: (() => { - const children: any[] = [] - for (let k = 0; k < 4; k++) { - children.push({ - id: `${index}-${j}-${k}`, - type: '2', - menuName: '按钮' + (j + 1) + '-' + (k + 1), - icon: '', - permission: ['menu1:view', 'menu2:add', 'menu3:update', 'menu4:del'][index] + ':btn' + (k + 1), - component: [ - '/dashboard/welcome/index', - '/dashboard/analysis/index', - '/dashboard/workbench/index', - '/dashboard/test/index', - ][j], - orderNo: j + 1, - createTime: '@datetime', - 'status|1': ['0', '1'], - parentMenu: `${index}-${j}`, - children: undefined, - }) - } - return children - })(), - }) - } - return children - })(), - }) - } - return result -})() - -export default [ - { - url: '/basic-api/system/getAccountList', - timeout: 100, - method: 'get', - response: ({ query }) => { - const { page = 1, pageSize = 20 } = query - return resultPageSuccess(page, pageSize, accountList) - }, - }, - { - url: '/basic-api/system/getRoleListByPage', - timeout: 100, - method: 'get', - response: ({ query }) => { - const { page = 1, pageSize = 20 } = query - return resultPageSuccess(page, pageSize, roleList) - }, - }, - { - url: '/basic-api/system/setRoleStatus', - timeout: 500, - method: 'post', - response: ({ query }) => { - const { id, status } = query - return resultSuccess({ id, status }) - }, - }, - { - url: '/basic-api/system/getAllRoleList', - timeout: 100, - method: 'get', - response: () => { - return resultSuccess(roleList) - }, - }, - { - url: '/basic-api/system/getDeptList', - timeout: 100, - method: 'get', - response: () => { - return resultSuccess(deptList) - }, - }, - { - url: '/basic-api/system/getMenuList', - timeout: 100, - method: 'get', - response: () => { - return resultSuccess(menuList) - }, - }, - { - url: '/basic-api/system/accountExist', - timeout: 500, - method: 'post', - response: ({ body }) => { - const { account } = body || {} - if (account && account.indexOf('admin') !== -1) { - return resultError('该字段不能包含admin') - } else { - return resultSuccess(`${account} can use`) - } - }, - }, -] as MockMethod[] diff --git a/mock/demo/table-demo.ts b/mock/demo/table-demo.ts deleted file mode 100644 index 8a1255de0..000000000 --- a/mock/demo/table-demo.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { MockMethod } from 'vite-plugin-mock' -import { Random } from 'mockjs' -import { resultPageSuccess } from '../_util' - -function getRandomPics(count = 10): string[] { - const arr: string[] = [] - for (let i = 0; i < count; i++) { - arr.push(Random.image('800x600', Random.color(), Random.color(), Random.title())) - } - return arr -} - -const demoList = (() => { - const result: any[] = [] - for (let index = 0; index < 200; index++) { - result.push({ - id: `${index}`, - beginTime: '@datetime', - endTime: '@datetime', - address: '@city()', - name: '@cname()', - name1: '@cname()', - name2: '@cname()', - name3: '@cname()', - name4: '@cname()', - name5: '@cname()', - name6: '@cname()', - name7: '@cname()', - name8: '@cname()', - radio1: `选项${index + 1}`, - radio2: `选项${index + 1}`, - radio3: `选项${index + 1}`, - avatar: Random.image('400x400', Random.color(), Random.color(), Random.first()), - imgArr: getRandomPics(Math.ceil(Math.random() * 3) + 1), - imgs: getRandomPics(Math.ceil(Math.random() * 3) + 1), - date: `@date('yyyy-MM-dd')`, - time: `@time('HH:mm')`, - 'no|100000-10000000': 100000, - 'status|1': ['normal', 'enable', 'disable'], - }) - } - return result -})() - -export default [ - { - url: '/basic-api/table/getDemoList', - timeout: 100, - method: 'get', - response: ({ query }) => { - const { page = 1, pageSize = 20 } = query - return resultPageSuccess(page, pageSize, demoList) - }, - }, -] as MockMethod[] diff --git a/mock/demo/tree-demo.ts b/mock/demo/tree-demo.ts deleted file mode 100644 index c31374875..000000000 --- a/mock/demo/tree-demo.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { MockMethod } from 'vite-plugin-mock' -import { resultSuccess } from '../_util' - -const demoTreeList = (keyword) => { - const result = { - list: [] as Recordable[], - } - for (let index = 0; index < 5; index++) { - const children: Recordable[] = [] - for (let j = 0; j < 3; j++) { - children.push({ - title: `${keyword ?? ''}选项${index}-${j}`, - value: `${index}-${j}`, - key: `${index}-${j}`, - }) - } - result.list.push({ - title: `${keyword ?? ''}选项${index}`, - value: `${index}`, - key: `${index}`, - children, - }) - } - return result -} - -export default [ - { - url: '/basic-api/tree/getDemoOptions', - timeout: 1000, - method: 'get', - response: ({ query }) => { - const { keyword } = query - console.log(keyword) - return resultSuccess(demoTreeList(keyword)) - }, - }, -] as MockMethod[] diff --git a/mock/sys/menu.ts b/mock/sys/menu.ts deleted file mode 100644 index 97d93dc7e..000000000 --- a/mock/sys/menu.ts +++ /dev/null @@ -1,270 +0,0 @@ -import { resultSuccess, resultError, getRequestToken, requestParams } from '../_util' -import { MockMethod } from 'vite-plugin-mock' -import { createFakeUserList } from './user' - -// single -const dashboardRoute = { - path: '/dashboard', - name: 'Dashboard', - component: 'LAYOUT', - redirect: '/dashboard/analysis', - meta: { - title: 'routes.dashboard.dashboard', - hideChildrenInMenu: true, - icon: 'bx:bx-home', - }, - children: [ - { - path: 'analysis', - name: 'Analysis', - component: '/dashboard/analysis/index', - meta: { - hideMenu: true, - hideBreadcrumb: true, - title: 'routes.dashboard.analysis', - currentActiveMenu: '/dashboard', - icon: 'bx:bx-home', - }, - }, - { - path: 'workbench', - name: 'Workbench', - component: '/dashboard/workbench/index', - meta: { - hideMenu: true, - hideBreadcrumb: true, - title: 'routes.dashboard.workbench', - currentActiveMenu: '/dashboard', - icon: 'bx:bx-home', - }, - }, - ], -} - -const backRoute = { - path: 'back', - name: 'PermissionBackDemo', - meta: { - title: 'routes.demo.permission.back', - }, - - children: [ - { - path: 'page', - name: 'BackAuthPage', - component: '/demo/permission/back/index', - meta: { - title: 'routes.demo.permission.backPage', - }, - }, - { - path: 'btn', - name: 'BackAuthBtn', - component: '/demo/permission/back/Btn', - meta: { - title: 'routes.demo.permission.backBtn', - }, - }, - ], -} - -const authRoute = { - path: '/permission', - name: 'Permission', - component: 'LAYOUT', - redirect: '/permission/front/page', - meta: { - icon: 'carbon:user-role', - title: 'routes.demo.permission.permission', - }, - children: [backRoute], -} - -const levelRoute = { - path: '/level', - name: 'Level', - component: 'LAYOUT', - redirect: '/level/menu1/menu1-1', - meta: { - icon: 'carbon:user-role', - title: 'routes.demo.level.level', - }, - - children: [ - { - path: 'menu1', - name: 'Menu1Demo', - meta: { - title: 'Menu1', - }, - children: [ - { - path: 'menu1-1', - name: 'Menu11Demo', - meta: { - title: 'Menu1-1', - }, - children: [ - { - path: 'menu1-1-1', - name: 'Menu111Demo', - component: '/demo/level/Menu111', - meta: { - title: 'Menu111', - }, - }, - ], - }, - { - path: 'menu1-2', - name: 'Menu12Demo', - component: '/demo/level/Menu12', - meta: { - title: 'Menu1-2', - }, - }, - ], - }, - { - path: 'menu2', - name: 'Menu2Demo', - component: '/demo/level/Menu2', - meta: { - title: 'Menu2', - }, - }, - ], -} - -const sysRoute = { - path: '/system', - name: 'System', - component: 'LAYOUT', - redirect: '/system/account', - meta: { - icon: 'ion:settings-outline', - title: 'routes.demo.system.moduleName', - }, - children: [ - { - path: 'account', - name: 'AccountManagement', - meta: { - title: 'routes.demo.system.account', - ignoreKeepAlive: true, - }, - component: '/demo/system/account/index', - }, - { - path: 'account_detail/:id', - name: 'AccountDetail', - meta: { - hideMenu: true, - title: 'routes.demo.system.account_detail', - ignoreKeepAlive: true, - showMenu: false, - currentActiveMenu: '/system/account', - }, - component: '/demo/system/account/AccountDetail', - }, - { - path: 'role', - name: 'RoleManagement', - meta: { - title: 'routes.demo.system.role', - ignoreKeepAlive: true, - }, - component: '/demo/system/role/index', - }, - - { - path: 'menu', - name: 'MenuManagement', - meta: { - title: 'routes.demo.system.menu', - ignoreKeepAlive: true, - }, - component: '/demo/system/menu/index', - }, - { - path: 'dept', - name: 'DeptManagement', - meta: { - title: 'routes.demo.system.dept', - ignoreKeepAlive: true, - }, - component: '/demo/system/dept/index', - }, - { - path: 'changePassword', - name: 'ChangePassword', - meta: { - title: 'routes.demo.system.password', - ignoreKeepAlive: true, - }, - component: '/demo/system/password/index', - }, - ], -} - -const linkRoute = { - path: '/link', - name: 'Link', - component: 'LAYOUT', - meta: { - icon: 'ion:tv-outline', - title: 'routes.demo.iframe.frame', - }, - children: [ - { - path: 'doc', - name: 'Doc', - meta: { - title: 'routes.demo.iframe.doc', - frameSrc: 'https://doc.vvbin.cn/', - }, - }, - { - path: 'https://doc.vvbin.cn/', - name: 'DocExternal', - component: 'LAYOUT', - meta: { - title: 'routes.demo.iframe.docExternal', - }, - }, - ], -} - -export default [ - { - url: '/basic-api/getMenuList', - timeout: 1000, - method: 'get', - response: (request: requestParams) => { - const token = getRequestToken(request) - if (!token) { - return resultError('Invalid token!') - } - const checkUser = createFakeUserList().find((item) => item.token === token) - if (!checkUser) { - return resultError('Invalid user token!') - } - const id = checkUser.userId - let menu: Object[] - switch (id) { - case '1': - dashboardRoute.redirect = dashboardRoute.path + '/' + dashboardRoute.children[0].path - menu = [dashboardRoute, authRoute, levelRoute, sysRoute, linkRoute] - break - case '2': - dashboardRoute.redirect = dashboardRoute.path + '/' + dashboardRoute.children[1].path - menu = [dashboardRoute, authRoute, levelRoute, linkRoute] - break - default: - menu = [] - } - - return resultSuccess(menu) - }, - }, -] as unknown as MockMethod[] diff --git a/mock/sys/user.ts b/mock/sys/user.ts deleted file mode 100644 index 1b08d34d4..000000000 --- a/mock/sys/user.ts +++ /dev/null @@ -1,120 +0,0 @@ -import { MockMethod } from 'vite-plugin-mock' -import { resultError, resultSuccess, getRequestToken, requestParams } from '../_util' - -export function createFakeUserList() { - return [ - { - userId: '1', - username: 'vben', - realName: 'Vben Admin', - avatar: '', - desc: 'manager', - password: '123456', - token: 'fakeToken1', - homePath: '/dashboard/analysis', - roles: [ - { - roleName: 'Super Admin', - value: 'super', - }, - ], - }, - { - userId: '2', - username: 'test', - password: '123456', - realName: 'test user', - avatar: '', - desc: 'tester', - token: 'fakeToken2', - homePath: '/dashboard/workbench', - roles: [ - { - roleName: 'Tester', - value: 'test', - }, - ], - }, - ] -} - -const fakeCodeList: any = { - '1': ['1000', '3000', '5000'], - - '2': ['2000', '4000', '6000'], -} -export default [ - // mock user login - { - url: '/basic-api/login', - timeout: 200, - method: 'post', - response: ({ body }) => { - const { username, password } = body - const checkUser = createFakeUserList().find((item) => item.username === username && password === item.password) - if (!checkUser) { - return resultError('Incorrect account or password!') - } - const { userId, username: _username, token, realName, desc, roles } = checkUser - return resultSuccess({ - roles, - userId, - username: _username, - token, - realName, - desc, - }) - }, - }, - { - url: '/basic-api/getUserInfo', - method: 'get', - response: (request: requestParams) => { - const token = getRequestToken(request) - if (!token) return resultError('Invalid token') - const checkUser = createFakeUserList().find((item) => item.token === token) - if (!checkUser) { - return resultError('The corresponding user information was not obtained!') - } - return resultSuccess(checkUser) - }, - }, - { - url: '/basic-api/getPermCode', - timeout: 200, - method: 'get', - response: (request: requestParams) => { - const token = getRequestToken(request) - if (!token) return resultError('Invalid token') - const checkUser = createFakeUserList().find((item) => item.token === token) - if (!checkUser) { - return resultError('Invalid token!') - } - const codeList = fakeCodeList[checkUser.userId] - - return resultSuccess(codeList) - }, - }, - { - url: '/basic-api/logout', - timeout: 200, - method: 'get', - response: (request: requestParams) => { - const token = getRequestToken(request) - if (!token) return resultError('Invalid token') - const checkUser = createFakeUserList().find((item) => item.token === token) - if (!checkUser) { - return resultError('Invalid token!') - } - return resultSuccess(undefined, { message: 'Token has been destroyed' }) - }, - }, - { - url: '/basic-api/testRetry', - statusCode: 405, - method: 'get', - response: () => { - return resultError('Error!') - }, - }, -] as MockMethod[] diff --git a/package.json b/package.json index ca44a742e..2907b8a1f 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "preinstall": "npx only-allow pnpm", "postinstall": "turbo run stub", "lint": "turbo run lint", - "lint:eslint": "eslint --cache --max-warnings 0 \"{src,mock}/**/*.{vue,ts,tsx}\" --fix", + "lint:eslint": "eslint --cache --max-warnings 0 \"{src}/**/*.{vue,ts,tsx}\" --fix", "lint:prettier": "prettier --write .", "lint:stylelint": "stylelint \"**/*.{vue,css,less,scss}\" --fix --cache --cache-location node_modules/.cache/stylelint/", "log": "conventional-changelog -p angular -i CHANGELOG.md -s", @@ -83,7 +83,6 @@ "dayjs": "^1.11.10", "echarts": "^5.5.0", "lodash-es": "^4.17.21", - "mockjs": "^1.1.0", "nprogress": "^0.2.0", "path-to-regexp": "^6.2.2", "pinia": "2.1.7", @@ -112,7 +111,6 @@ "@types/codemirror": "^5.60.15", "@types/crypto-js": "^4.2.2", "@types/lodash-es": "^4.17.12", - "@types/mockjs": "^1.0.10", "@types/nprogress": "^0.2.3", "@types/qrcode": "^1.5.5", "@types/qs": "^6.9.15", @@ -138,7 +136,6 @@ "typescript": "^5.4.5", "unbuild": "^2.0.0", "vite": "^5.2.10", - "vite-plugin-mock": "^2.9.6", "vite-plugin-vue-devtools": "^7.2.0", "vue-tsc": "^2.0.14" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c0dc311f1..b1903bde5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -50,9 +50,6 @@ importers: lodash-es: specifier: ^4.17.21 version: 4.17.21 - mockjs: - specifier: ^1.1.0 - version: 1.1.0 nprogress: specifier: ^0.2.0 version: 0.2.0 @@ -132,9 +129,6 @@ importers: '@types/lodash-es': specifier: ^4.17.12 version: 4.17.12 - '@types/mockjs': - specifier: ^1.0.10 - version: 1.0.10 '@types/nprogress': specifier: ^0.2.3 version: 0.2.3 @@ -210,9 +204,6 @@ importers: vite: specifier: ^5.2.10 version: 5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.30.3) - vite-plugin-mock: - specifier: ^2.9.6 - version: 2.9.8(mockjs@1.1.0)(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.30.3)) vite-plugin-vue-devtools: specifier: ^7.2.0 version: 7.2.0(rollup@3.29.4)(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.30.3))(vue@3.4.25(typescript@5.4.5)) @@ -422,9 +413,6 @@ importers: vite-plugin-html: specifier: ^3.2.2 version: 3.2.2(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.30.3)) - vite-plugin-mock: - specifier: ^2.9.6 - version: 2.9.8(mockjs@1.1.0)(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.30.3)) vite-plugin-purge-icons: specifier: ^0.10.0 version: 0.10.0(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.30.3)) @@ -905,12 +893,6 @@ packages: cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.14.54': - resolution: {integrity: sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - '@esbuild/linux-loong64@0.19.12': resolution: {integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==} engines: {node: '>=12'} @@ -1489,9 +1471,6 @@ packages: '@types/mime@1.3.5': resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} - '@types/mockjs@1.0.10': - resolution: {integrity: sha512-SXgrhajHG7boLv6oU93CcmdDm0HYRiceuz6b+7z+/2lCJPTWDv0V5YiwFHT2ejE4bQqgSXQiVPQYPWv7LGsK1g==} - '@types/node@20.12.7': resolution: {integrity: sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==} @@ -2236,10 +2215,6 @@ packages: resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} engines: {node: '>=16'} - commander@12.0.0: - resolution: {integrity: sha512-MwVNWlYjDTtOjX5PiD7o5pK0UrFU/OYgcJfjjK4RaHZETNtjJqrZa9Y9ds88+A+f+d5lv+561eZ+yCKoS3gbAA==} - engines: {node: '>=18'} - commander@2.15.1: resolution: {integrity: sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==} @@ -2290,10 +2265,6 @@ packages: resolution: {integrity: sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==} engines: {node: '>=0.8'} - connect@3.7.0: - resolution: {integrity: sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==} - engines: {node: '>= 0.10.0'} - consola@2.15.3: resolution: {integrity: sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==} @@ -2857,131 +2828,6 @@ packages: resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} engines: {node: '>= 0.4'} - esbuild-android-64@0.14.54: - resolution: {integrity: sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - - esbuild-android-arm64@0.14.54: - resolution: {integrity: sha512-F9E+/QDi9sSkLaClO8SOV6etqPd+5DgJje1F9lOWoNncDdOBL2YF59IhsWATSt0TLZbYCf3pNlTHvVV5VfHdvg==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - - esbuild-darwin-64@0.14.54: - resolution: {integrity: sha512-jtdKWV3nBviOd5v4hOpkVmpxsBy90CGzebpbO9beiqUYVMBtSc0AL9zGftFuBon7PNDcdvNCEuQqw2x0wP9yug==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - - esbuild-darwin-arm64@0.14.54: - resolution: {integrity: sha512-OPafJHD2oUPyvJMrsCvDGkRrVCar5aVyHfWGQzY1dWnzErjrDuSETxwA2HSsyg2jORLY8yBfzc1MIpUkXlctmw==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - - esbuild-freebsd-64@0.14.54: - resolution: {integrity: sha512-OKwd4gmwHqOTp4mOGZKe/XUlbDJ4Q9TjX0hMPIDBUWWu/kwhBAudJdBoxnjNf9ocIB6GN6CPowYpR/hRCbSYAg==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - - esbuild-freebsd-arm64@0.14.54: - resolution: {integrity: sha512-sFwueGr7OvIFiQT6WeG0jRLjkjdqWWSrfbVwZp8iMP+8UHEHRBvlaxL6IuKNDwAozNUmbb8nIMXa7oAOARGs1Q==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - - esbuild-linux-32@0.14.54: - resolution: {integrity: sha512-1ZuY+JDI//WmklKlBgJnglpUL1owm2OX+8E1syCD6UAxcMM/XoWd76OHSjl/0MR0LisSAXDqgjT3uJqT67O3qw==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - - esbuild-linux-64@0.14.54: - resolution: {integrity: sha512-EgjAgH5HwTbtNsTqQOXWApBaPVdDn7XcK+/PtJwZLT1UmpLoznPd8c5CxqsH2dQK3j05YsB3L17T8vE7cp4cCg==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - - esbuild-linux-arm64@0.14.54: - resolution: {integrity: sha512-WL71L+0Rwv+Gv/HTmxTEmpv0UgmxYa5ftZILVi2QmZBgX3q7+tDeOQNqGtdXSdsL8TQi1vIaVFHUPDe0O0kdig==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - - esbuild-linux-arm@0.14.54: - resolution: {integrity: sha512-qqz/SjemQhVMTnvcLGoLOdFpCYbz4v4fUo+TfsWG+1aOu70/80RV6bgNpR2JCrppV2moUQkww+6bWxXRL9YMGw==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - - esbuild-linux-mips64le@0.14.54: - resolution: {integrity: sha512-qTHGQB8D1etd0u1+sB6p0ikLKRVuCWhYQhAHRPkO+OF3I/iSlTKNNS0Lh2Oc0g0UFGguaFZZiPJdJey3AGpAlw==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - - esbuild-linux-ppc64le@0.14.54: - resolution: {integrity: sha512-j3OMlzHiqwZBDPRCDFKcx595XVfOfOnv68Ax3U4UKZ3MTYQB5Yz3X1mn5GnodEVYzhtZgxEBidLWeIs8FDSfrQ==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - - esbuild-linux-riscv64@0.14.54: - resolution: {integrity: sha512-y7Vt7Wl9dkOGZjxQZnDAqqn+XOqFD7IMWiewY5SPlNlzMX39ocPQlOaoxvT4FllA5viyV26/QzHtvTjVNOxHZg==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - - esbuild-linux-s390x@0.14.54: - resolution: {integrity: sha512-zaHpW9dziAsi7lRcyV4r8dhfG1qBidQWUXweUjnw+lliChJqQr+6XD71K41oEIC3Mx1KStovEmlzm+MkGZHnHA==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - - esbuild-netbsd-64@0.14.54: - resolution: {integrity: sha512-PR01lmIMnfJTgeU9VJTDY9ZerDWVFIUzAtJuDHwwceppW7cQWjBBqP48NdeRtoP04/AtO9a7w3viI+PIDr6d+w==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - - esbuild-openbsd-64@0.14.54: - resolution: {integrity: sha512-Qyk7ikT2o7Wu76UsvvDS5q0amJvmRzDyVlL0qf5VLsLchjCa1+IAvd8kTBgUxD7VBUUVgItLkk609ZHUc1oCaw==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - - esbuild-sunos-64@0.14.54: - resolution: {integrity: sha512-28GZ24KmMSeKi5ueWzMcco6EBHStL3B6ubM7M51RmPwXQGLe0teBGJocmWhgwccA1GeFXqxzILIxXpHbl9Q/Kw==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - - esbuild-windows-32@0.14.54: - resolution: {integrity: sha512-T+rdZW19ql9MjS7pixmZYVObd9G7kcaZo+sETqNH4RCkuuYSuv9AGHUVnPoP9hhuE1WM1ZimHz1CIBHBboLU7w==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - - esbuild-windows-64@0.14.54: - resolution: {integrity: sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - - esbuild-windows-arm64@0.14.54: - resolution: {integrity: sha512-M0kuUvXhot1zOISQGXwWn6YtS+Y/1RT9WrVIOywZnJHo3jCDyewAc79aKNQWFCQm+xNHVTq9h8dZKvygoXQQRg==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - - esbuild@0.14.54: - resolution: {integrity: sha512-Cy9llcy8DvET5uznocPyqL3BFRrFXSVqbgpMJ9Wz8oVjZlh/zUSNbPRbov0VX7VxN2JH1Oa0uNxZ7eLRb62pJA==} - engines: {node: '>=12'} - hasBin: true - esbuild@0.19.12: resolution: {integrity: sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==} engines: {node: '>=12'} @@ -3209,10 +3055,6 @@ packages: resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} engines: {node: '>=8'} - finalhandler@1.1.2: - resolution: {integrity: sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==} - engines: {node: '>= 0.8'} - find-up@4.1.0: resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} engines: {node: '>=8'} @@ -4298,10 +4140,6 @@ packages: mlly@1.6.1: resolution: {integrity: sha512-vLgaHvaeunuOXHSmEbZ9izxPx3USsk8KCQ8iC+aTlp5sKRSoZvwhHh5L9VbKSaVC6sJDqbyohIS76E2VmHIPAA==} - mockjs@1.1.0: - resolution: {integrity: sha512-eQsKcWzIaZzEZ07NuEyO4Nw65g0hdWAyurVol1IPl1gahRwY+svqzfgfey8U8dahLwG44d6/RwEzuK52rSa/JQ==} - hasBin: true - module-details-from-path@1.0.3: resolution: {integrity: sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==} @@ -4477,10 +4315,6 @@ packages: ofetch@1.3.4: resolution: {integrity: sha512-KLIET85ik3vhEfS+3fDlc/BAZiAp+43QEC/yCo5zkNoY2YaKvNkOaFr/6wCFgFH1kuYQM5pMNi0Tg8koiIemtw==} - on-finished@2.3.0: - resolution: {integrity: sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==} - engines: {node: '>= 0.8'} - on-finished@2.4.1: resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} engines: {node: '>= 0.8'} @@ -5966,10 +5800,6 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - utils-merge@1.0.1: - resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} - engines: {node: '>= 0.4.0'} - uuid@3.4.0: resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==} deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. @@ -6027,13 +5857,6 @@ packages: '@nuxt/kit': optional: true - vite-plugin-mock@2.9.8: - resolution: {integrity: sha512-YTQM5Sn7t+/DNOwTkr+W26QGTCk1PrDkhGHslTJ90lIPJhJtDTwuSkEYMAuLP9TcVQ/qExTFx/x/GE3kxJ05sw==} - engines: {node: '>=12.0.0'} - peerDependencies: - mockjs: '>=1.1.0' - vite: '>=2.0.0' - vite-plugin-purge-icons@0.10.0: resolution: {integrity: sha512-4fMJKQuBu9lAPJWjqGEytRaxty1pP9bWgQLA68dwbbaCXu6NBrOUb/3kMaUc7TP09kerEk+qTriCk05OZXpjwA==} engines: {node: '>= 12'} @@ -6815,9 +6638,6 @@ snapshots: '@esbuild/linux-ia32@0.20.2': optional: true - '@esbuild/linux-loong64@0.14.54': - optional: true - '@esbuild/linux-loong64@0.19.12': optional: true @@ -7417,8 +7237,6 @@ snapshots: '@types/mime@1.3.5': {} - '@types/mockjs@1.0.10': {} - '@types/node@20.12.7': dependencies: undici-types: 5.26.5 @@ -8445,8 +8263,6 @@ snapshots: commander@11.1.0: {} - commander@12.0.0: {} - commander@2.15.1: {} commander@2.20.3: {} @@ -8483,15 +8299,6 @@ snapshots: connect-history-api-fallback@1.6.0: {} - connect@3.7.0: - dependencies: - debug: 2.6.9 - finalhandler: 1.1.2 - parseurl: 1.3.3 - utils-merge: 1.0.1 - transitivePeerDependencies: - - supports-color - consola@2.15.3: {} consola@3.2.3: {} @@ -9092,90 +8899,6 @@ snapshots: is-date-object: 1.0.5 is-symbol: 1.0.4 - esbuild-android-64@0.14.54: - optional: true - - esbuild-android-arm64@0.14.54: - optional: true - - esbuild-darwin-64@0.14.54: - optional: true - - esbuild-darwin-arm64@0.14.54: - optional: true - - esbuild-freebsd-64@0.14.54: - optional: true - - esbuild-freebsd-arm64@0.14.54: - optional: true - - esbuild-linux-32@0.14.54: - optional: true - - esbuild-linux-64@0.14.54: - optional: true - - esbuild-linux-arm64@0.14.54: - optional: true - - esbuild-linux-arm@0.14.54: - optional: true - - esbuild-linux-mips64le@0.14.54: - optional: true - - esbuild-linux-ppc64le@0.14.54: - optional: true - - esbuild-linux-riscv64@0.14.54: - optional: true - - esbuild-linux-s390x@0.14.54: - optional: true - - esbuild-netbsd-64@0.14.54: - optional: true - - esbuild-openbsd-64@0.14.54: - optional: true - - esbuild-sunos-64@0.14.54: - optional: true - - esbuild-windows-32@0.14.54: - optional: true - - esbuild-windows-64@0.14.54: - optional: true - - esbuild-windows-arm64@0.14.54: - optional: true - - esbuild@0.14.54: - optionalDependencies: - '@esbuild/linux-loong64': 0.14.54 - esbuild-android-64: 0.14.54 - esbuild-android-arm64: 0.14.54 - esbuild-darwin-64: 0.14.54 - esbuild-darwin-arm64: 0.14.54 - esbuild-freebsd-64: 0.14.54 - esbuild-freebsd-arm64: 0.14.54 - esbuild-linux-32: 0.14.54 - esbuild-linux-64: 0.14.54 - esbuild-linux-arm: 0.14.54 - esbuild-linux-arm64: 0.14.54 - esbuild-linux-mips64le: 0.14.54 - esbuild-linux-ppc64le: 0.14.54 - esbuild-linux-riscv64: 0.14.54 - esbuild-linux-s390x: 0.14.54 - esbuild-netbsd-64: 0.14.54 - esbuild-openbsd-64: 0.14.54 - esbuild-sunos-64: 0.14.54 - esbuild-windows-32: 0.14.54 - esbuild-windows-64: 0.14.54 - esbuild-windows-arm64: 0.14.54 - esbuild@0.19.12: optionalDependencies: '@esbuild/aix-ppc64': 0.19.12 @@ -9515,18 +9238,6 @@ snapshots: dependencies: to-regex-range: 5.0.1 - finalhandler@1.1.2: - dependencies: - debug: 2.6.9 - encodeurl: 1.0.2 - escape-html: 1.0.3 - on-finished: 2.3.0 - parseurl: 1.3.3 - statuses: 1.5.0 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - find-up@4.1.0: dependencies: locate-path: 5.0.0 @@ -10635,10 +10346,6 @@ snapshots: pkg-types: 1.1.0 ufo: 1.5.3 - mockjs@1.1.0: - dependencies: - commander: 12.0.0 - module-details-from-path@1.0.3: {} mri@1.2.0: {} @@ -10826,10 +10533,6 @@ snapshots: node-fetch-native: 1.6.4 ufo: 1.5.3 - on-finished@2.3.0: - dependencies: - ee-first: 1.1.1 - on-finished@2.4.1: dependencies: ee-first: 1.1.1 @@ -12501,8 +12204,6 @@ snapshots: util-deprecate@1.0.2: {} - utils-merge@1.0.1: {} - uuid@3.4.0: {} v8-compile-cache-lib@3.0.1: {} @@ -12582,21 +12283,6 @@ snapshots: - rollup - supports-color - vite-plugin-mock@2.9.8(mockjs@1.1.0)(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.30.3)): - dependencies: - '@types/mockjs': 1.0.10 - chalk: 4.1.2 - chokidar: 3.6.0 - connect: 3.7.0 - debug: 4.3.4 - esbuild: 0.14.54 - fast-glob: 3.3.2 - mockjs: 1.1.0 - path-to-regexp: 6.2.2 - vite: 5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.30.3) - transitivePeerDependencies: - - supports-color - vite-plugin-purge-icons@0.10.0(vite@5.2.10(@types/node@20.12.7)(less@4.2.0)(sass@1.75.0)(terser@5.30.3)): dependencies: '@purge-icons/core': 0.10.0 diff --git a/public/favicon.ico b/public/favicon.ico index d92e0b8c4963f1ae81021bbed63e94c2699dea66..bcc7d2b2f9124ef73dfe83da8936476e2595f431 100644 GIT binary patch literal 9662 zcmc(k3y_s%8OOhM!A&q$5kV1MG@vvUP{u@H7Xc$KljtapNu(BqG-?=)O<}Bqc`F^f zji!!M(~T%-L~b!&Xwb6KG1M#-0ZjuF#s$$-|O={ z@AH1&yWjapk_!Hf7?JQjI9WP0N%|*A@)@8hxfEo zI2JyZb+qw2ocbTZxSQeca39QvIYDnnAA@%wuI~lPS3s-%=s0U#(~HlTx05J83&!*c zd>#5j?9Xa1+DF0<;6;e*T}OE|WXE<*paraC{Pd-~7L4O5a35O5&_R6=ecywBgY(}4 z_rm)i|XTTo#7Yu}wbKf?EXd~zs(0E@z zNV#|HZ#%D)dbEN1_ticA8B{=-g_@Dv;at=2%j4_pLa3(P{#gkBK+976d5 zxE{U&!{Jgm8QkA1U?NlmEYE>q@aa$jB6!5n-5Tj5o3>@9FKn44W-+}e8y-i6a(1~~RkNPP#tmMh_> zVE<0o0$wlr84u}r^agOu>u@5Z?ZM6`sIP;4@I#mfE5Y&Zow>g{)XmXAm=BI$0oroE z-h!vWG0m_P4uVl&K30M8#+X!nKMt;S0=S>r)c0lJm>yu;e)tG(f~*b8_kljAgucVj zwa^69;Vjq#Pr$`62mTAsf@8Jep6>?t>3xW{j-|X6wu8RE1Lr|saGp8S&k{HnZU^JP z5$rz_+)sU(gEzoy(!R(7%Feke(>6P_-Hn=qx$q1a%QkS2--IEcooe_CXy-p*E^R*) zHiGT0?L#o$N5E_CC@_DofOfU%*k$1SkznqA3FbtEqK*bDBj`)u3c zPy@!i3jPOU!M0tFmSG%2JeA6=?S)-1m2UIAnx_4l<$EDK_BLFJUIRV(9e}{0~qi3!M=L1Z&s*} zM$Mx+I5@P;Mzy;J9P3`Yer;Kw2ikI+b=$4WF|Y+*g#O@t=eQ>L8+dIv&Ncl5T-R3k z33&aRyT@Sz90&ct9Gk-v;S$iN*SdB_K?6Jo?x}6Yw-e0E3vfAj9{(6N!$feL_rp3c z*T!mFZ+H@n*Y&RkZRzt4(2nC=m-nOh&mf3bnT-{0Ow0_O(0t06T(x z_x`t#{~cJW*%&7}1$Kk)B+^`<-L{5cyC=E|n!xL*)bL~eRdaqbxCfiScXRpvk_~q< zA=vh}z((-5{pV~e=i|J9*U_Wk8r;{if2Vd92e$R;?^xeI?SM32oy{xM&)gWl>hJk2 z;2PWy_c-k@G`F0#Xb&9@?}Gb%1e9Ygo#WgLGbwv7_+EEDq`xuIvh8OlYA4|Ppt#rG z%h_Qimos*acL96^zGLxSU6-u^TQUB7DI34Ox@3=|9n^PRH-TrHXVN@KbA*=dE6zm+ zf!Dsa(|Z>!Ip>8YXeZ!1_1nNT_zrL(*cST>O>eg?JCE{QF!$@hbEw^UrFLj5gYn)9 zp3(c^AuxCOF~!=?%yIs6U|wd&_G0Z6GcMW;T7~+I;a;1wKf^@G-xHMEHEUl6ZQTRf zc@z$Vw7*>gWp+fnL5v$QigOkB~zEJ!*?@vU!{Ze+AbdJ76U&1ovq&oC{aN zZ{TfkoOz!I`LnD$;w@wopZR=+a(~owWFzhGY@1 zn3G(6Qj=eR|+CZJWhq*|@c)vFEFxotEh4K=xj$`);` zXwjxr>vGMBb+tOxTvFAd^(dbnNoCNAR+?7I{=)fK{3Yl@lpu0VXpU92XkCleN3F>< z+P|T?MOjr^Z>Y#M*xs1rw$-G%DAlHFR>0MN^(+15GZl&w=KiVL1wn6T z6kkZ}DT8x=g_XnA|4v>HSO33$3S12u1Fjy#fSC_upeciM zfBAL8wfs)p0oU^X|9`j|GzMHfvK44*kh#ACs}Nd}*5GjrTo*z;*cWhd@)!pg85kNs n7^oeNfqano0bpKwAP>a+3=AJYn4N*)2ax^&6#E0jpkM$1?7KMX diff --git a/public/logo.png b/public/logo.png index cd4c33d8b71f31d32aaed9fefe14f237b81e764f..635e948c41318cfdc8734b2b8b48274dbbb89241 100644 GIT binary patch literal 14114 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 diff --git a/src/api/common/BaseApi.api.ts b/src/api/common/BaseApi.api.ts new file mode 100644 index 000000000..2aa3aea85 --- /dev/null +++ b/src/api/common/BaseApi.api.ts @@ -0,0 +1,21 @@ +import { defHttp } from '@/utils/http/axios' + +/** + * 回声测试 + */ +export function echo(msg: string) { + return defHttp.get({ + url: '/echo', + params: { msg }, + }) +} + +/** + * 回声测试(必须要进行登录) + */ +export function authEcho(msg: string) { + return defHttp.get({ + url: '/auth/echo', + params: { msg }, + }) +} diff --git a/src/api/common/Captcha.ts b/src/api/common/Captcha.ts new file mode 100644 index 000000000..4e13ca0ae --- /dev/null +++ b/src/api/common/Captcha.ts @@ -0,0 +1,19 @@ +import { defHttp } from '@/utils/http/axios' +import { Result } from '#/axios' + +/** + * 获取文件预览地址 + */ +export const imgCaptcha = () => { + return defHttp.post>({ + url: '/captcha/imgCaptcha', + }) +} + +/** + * 验证码 + */ +export interface Captcha { + captchaKey: string + captchaData: string +} diff --git a/src/api/common/ChinaRegion.api.ts b/src/api/common/ChinaRegion.api.ts new file mode 100644 index 000000000..0a0a9c2fd --- /dev/null +++ b/src/api/common/ChinaRegion.api.ts @@ -0,0 +1,48 @@ +import { defHttp } from '@/utils/http/axios' +import { Result } from '#/axios' + +/** + * 获取一级行政区 + */ +export function findAllProvince() { + return defHttp.get>({ + url: '/china/region/findAllProvince', + }) +} + +/** + * 获取省市二级联动 + */ +export function findAllProvinceAndCity() { + return defHttp.get>({ + url: '/china/region/findAllProvinceAndCity', + }) +} +/** + * 获取省市区三级联动 + */ +export function findAllProvinceAndCityAndArea() { + return defHttp.get>({ + url: '/china/region/findAllProvinceAndCityAndArea', + }) +} +/** + * 获取省市二级联动 + */ +export function findAllRegionByParentCode(parentCode: string) { + return defHttp.get>({ + url: '/china/region/findAllRegionByParentCode', + params: { parentCode }, + }) +} + +/** + * 区域 + */ +export interface Region { + code: string + name: string + level: 1 | 2 | 3 | 4 | 5 + isLeaf?: boolean + children: Region[] +} diff --git a/src/api/common/FileUpload.ts b/src/api/common/FileUpload.ts new file mode 100644 index 000000000..dce99877e --- /dev/null +++ b/src/api/common/FileUpload.ts @@ -0,0 +1,103 @@ +import { defHttp } from '@/utils/http/axios' +import { Result, UploadFileParams } from '#/axios' +import { UploadApiResult } from '@/api/sys/model/uploadModel' +import { getAppEnvConfig } from '@/utils/env' +import { AxiosProgressEvent } from 'axios' + +const { VITE_GLOB_API_URL, VITE_GLOB_API_URL_PREFIX } = getAppEnvConfig() + +/** + * 获取文件预览地址 + */ +export const getFilePreviewUrl = (id) => { + return defHttp.get>({ + url: `/file/getFilePreviewUrl`, + params: { id }, + }) +} + +/** + * 获取文件预览地址前缀 + */ +export const getFilePreviewUrlPrefix = () => { + return defHttp.get>({ + url: `/file/getFilePreviewUrlPrefix`, + }) +} + +/** + * 获取文件下载地址 + */ +export const getFileDownloadUrl = (id) => { + return defHttp.get>({ + url: `/file/getFileDownloadUrl`, + params: { id }, + }) +} + +/** + * 上传文件 + * @param params + * @param onUploadProgress + */ +export function uploadFile(params: UploadFileParams, onUploadProgress: (progressEvent: AxiosProgressEvent) => void) { + return defHttp.uploadFile( + { + url: VITE_GLOB_API_URL + VITE_GLOB_API_URL_PREFIX + '/file/upload', + onUploadProgress, + }, + params, + ) +} + +/** + * 上传文件信息 + */ +export interface UpdateFileInfo { + // id + id?: number + // 文件访问地址 + url?: string + // 文件大小,单位字节 + size?: string + // 文件名称 + filename?: string + // 原始文件名 + originalFilename?: string + // 基础存储路径 + basePath?: string + // 存储路径 + path?: string + // 文件扩展名 + ext?: string + // MIME类型 + contentType?: string + // 存储平台 + platform?: string + // 缩略图访问路径 + thUrl?: string + // 缩略图名称 + thFilename?: string + // 缩略图大小,单位字节 + thSize?: string + // 缩略图MIME类型 + thContentType?: string + // 文件所属对象id + objectId?: string + // 文件所属对象类型,例如用户头像,评价图片 + objectType?: string + // 文件元数据 + metadata?: string + // 文件用户元数据 + userMetadata?: string + // 缩略图元数据 + thMetadata?: string + // 缩略图用户元数据 + thUserMetadata?: string + // 附加属性 + attr?: string + // 文件ACL + fileAcl?: string + // 缩略图文件ACL + thFileAcl?: string +} diff --git a/src/api/common/LoginAssist.ts b/src/api/common/LoginAssist.ts new file mode 100644 index 000000000..b75873267 --- /dev/null +++ b/src/api/common/LoginAssist.ts @@ -0,0 +1,22 @@ +import { defHttp } from '@/utils/http/axios' +import { Result } from '#/axios' + +/** + * 根据code获取登录方式 + */ +export function findLoginTypeByCode(code) { + return defHttp.get>({ + url: '/loginType/findByCode', + params: { code }, + }) +} + +/** + * 登录方式 + */ +export interface LoginType { + // 启用验证码 + captcha: boolean + // 是否可用 + enable: boolean +} diff --git a/src/api/common/Parameter.ts b/src/api/common/Parameter.ts new file mode 100644 index 000000000..c363b6c9a --- /dev/null +++ b/src/api/common/Parameter.ts @@ -0,0 +1,13 @@ +import { defHttp } from '@/utils/http/axios' +import { Result } from '#/axios' + +/** + * 根据键名获取键值 + */ +export function findByParamKey(key) { + return defHttp.get>({ + url: `/system/param/findByParamKey`, + method: 'GET', + params: { key }, + }) +} diff --git a/src/api/sys/login.ts b/src/api/sys/login.ts new file mode 100644 index 000000000..0ba57ab20 --- /dev/null +++ b/src/api/sys/login.ts @@ -0,0 +1,47 @@ +import { defHttp } from '@/utils/http/axios' +import { LoginParams } from './model/userModel' +import { Result } from '#/axios' + +/** + * 登录接口 返回token + */ +export function login(params: LoginParams) { + return defHttp.post>({ + url: '/token/login', + params, + }) +} + +/** + * 获取微信扫码登录二维码 + */ +export function applyQrCode() { + return defHttp.post>({ + url: `/token/wechat/qr/applyQrCode`, + }) +} + +/** + * 获取扫码状态 + */ +export function getQrStatus(qrCodeKey) { + return defHttp.get>({ + url: `/token/wechat/qr/getStatus`, + params: { qrCodeKey }, + }) +} + +/** + * 退出 + */ +export function doLogout() { + return defHttp.post({ url: '/token/logout' }) +} + +/** + * 登录二维码 + */ +export interface WeChatLoginQrCode { + qrCodeKey: string + qrCodeUrl: string +} diff --git a/src/api/sys/menu.ts b/src/api/sys/menu.ts index 113869847..a85852d59 100644 --- a/src/api/sys/menu.ts +++ b/src/api/sys/menu.ts @@ -1,5 +1,6 @@ import { defHttp } from '@/utils/http/axios' -import { getMenuListResultModel } from './model/menuModel' +import { getMenuListResultModel, MenuAndResource } from './model/menuModel' +import { Result } from '#/axios' enum Api { GetMenuList = '/getMenuList', @@ -12,3 +13,10 @@ enum Api { export const getMenuList = () => { return defHttp.get({ url: Api.GetMenuList }) } + +/** + * 获取菜单和权限码 + */ +export const getPermissions = (clientCode: string) => { + return defHttp.get>({ url: '/role/menu/getPermissions', params: { clientCode } }) +} diff --git a/src/api/sys/model/menuModel.ts b/src/api/sys/model/menuModel.ts index 7e79c8c49..803e3179c 100644 --- a/src/api/sys/model/menuModel.ts +++ b/src/api/sys/model/menuModel.ts @@ -15,3 +15,35 @@ export interface RouteItem { * @description: Get menu return value */ export type getMenuListResultModel = RouteItem[] + +/** + * 用户菜单及资源权限返回类 + */ +export interface MenuAndResource { + // 权限码 + resourcePerms: Array + // 菜单 + menus: Array +} + +/** + * 权限菜单 + */ +export interface PermMenu { + parentId: number | null + title: string + name: string + effect: boolean + icon: string + hidden: boolean + hideChildrenInMenu: boolean + component: string + path: string + iframeUrl: string + redirect: string + sortNo: number + keepAlive: boolean + targetOutside: boolean + hiddenHeaderContent: boolean + children: Array +} diff --git a/src/api/sys/model/userModel.ts b/src/api/sys/model/userModel.ts index 53fa00bb0..ce0e28198 100644 --- a/src/api/sys/model/userModel.ts +++ b/src/api/sys/model/userModel.ts @@ -1,38 +1,33 @@ /** - * @description: Login interface parameters + * 账密登录参数 */ export interface LoginParams { - username: string - password: string -} - -export interface RoleInfo { - roleName: string - value: string + // 账号/手机号/邮箱 + account?: string + // 密码 + password?: string + // 终端 + client: string + // 登录方式 + loginType: string + // 验证码key + captchaKey?: string + // 验证码 + captcha?: string + // 授权码登录 + authCode?: string } /** - * @description: Login interface return value - */ -export interface LoginResultModel { - userId: string | number - token: string - roles: RoleInfo[] -} - -/** - * @description: Get user information return value + * 登录后用户信息 */ export interface GetUserInfoModel { - roles: RoleInfo[] // 用户id - userId: string | number - // 用户名 + userId: number + // 名称 + name: string + // 账号 username: string - // 真实名字 - realName: string // 头像 avatar: string - // 介绍 - desc?: string } diff --git a/src/api/sys/user.ts b/src/api/sys/user.ts index 3c4b23324..cb018b8e0 100644 --- a/src/api/sys/user.ts +++ b/src/api/sys/user.ts @@ -1,55 +1,30 @@ import { defHttp } from '@/utils/http/axios' -import { LoginParams, LoginResultModel, GetUserInfoModel } from './model/userModel' - -import { ErrorMessageMode } from '#/axios' - -enum Api { - Login = '/login', - Logout = '/logout', - GetUserInfo = '/getUserInfo', - GetPermCode = '/getPermCode', - TestRetry = '/testRetry', -} +import { GetUserInfoModel } from './model/userModel' +import { Result } from '#/axios' /** - * @description: user login api - */ -export function loginApi(params: LoginParams, mode: ErrorMessageMode = 'modal') { - return defHttp.post( - { - url: Api.Login, - params, - }, - { - errorMessageMode: mode, - }, - ) -} - -/** - * @description: getUserInfo + * 登录后获取用户信息 */ export function getUserInfo() { - return defHttp.get({ url: Api.GetUserInfo }, { errorMessageMode: 'none' }) + return defHttp.get>({ url: '/user/getLoginAfterUserInfo' }) } -export function getPermCode() { - return defHttp.get({ url: Api.GetPermCode }) +/** + * 注册 + */ +export function register(obj) { + return defHttp.post({ + url: `/user/register`, + data: obj, + }) } -export function doLogout() { - return defHttp.get({ url: Api.Logout }) -} - -export function testRetry() { - return defHttp.get( - { url: Api.TestRetry }, - { - retryRequest: { - isOpenRetry: true, - count: 5, - waitTime: 1000, - }, - }, - ) +/** + * 重置密码 + */ +export function forgetPasswordByPhone(obj) { + return defHttp.post({ + url: `/user/forgetPasswordByPhone`, + data: obj, + }) } diff --git a/src/assets/images/logo.png b/src/assets/images/logo.png index 16f2e7ab7c74552c5653652547ebce7adc4901dc..635e948c41318cfdc8734b2b8b48274dbbb89241 100644 GIT binary patch literal 14114 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 diff --git a/src/components/Link/Link.vue b/src/components/Link/Link.vue new file mode 100644 index 000000000..bf8d2dcfc --- /dev/null +++ b/src/components/Link/Link.vue @@ -0,0 +1,42 @@ + + + + + diff --git a/src/components/Link/index.ts b/src/components/Link/index.ts new file mode 100644 index 000000000..4e2f930ce --- /dev/null +++ b/src/components/Link/index.ts @@ -0,0 +1,4 @@ +import { withInstall } from '@/utils' +import link from './Link.vue' + +export const Link = withInstall(link) diff --git a/src/components/registerGlobComp.ts b/src/components/registerGlobComp.ts index a4b635a84..563237cff 100644 --- a/src/components/registerGlobComp.ts +++ b/src/components/registerGlobComp.ts @@ -1,8 +1,89 @@ import type { App } from 'vue' import { Button } from './Button' -import { Input, Layout } from 'ant-design-vue' +import { Link } from './Link' +import { + Layout, + Input, + Image, + Badge, + Popover, + InputNumber, + Empty, + Popconfirm, + Select, + SelectOption, + List, + Tabs, + Alert, + Upload, + Checkbox, + Switch, + Tree, + TreeSelect, + Typography, + Card, + Form, + Row, + Col, + Modal, + Dropdown, + Timeline, + Radio, + Steps, + Spin, + Menu, + Drawer, + Tooltip, + Tag, + Divider, + DatePicker, + TimePicker, + Descriptions, + Space, +} from 'ant-design-vue' import VXETable from 'vxe-table' export function registerGlobComp(app: App) { - app.use(Input).use(Button).use(Layout).use(VXETable) + app.use(Input) + app.use(Button) + app.use(Link) + app.use(Image) + app.use(Layout) + app.use(InputNumber) + app.use(Tag) + app.use(Tabs) + app.use(Upload) + app.use(Badge) + app.use(Popover) + app.use(Checkbox) + app.use(List) + app.use(Space) + app.use(Modal) + app.use(Drawer) + app.use(Row) + app.use(Col) + app.use(Radio) + app.use(Divider) + app.use(DatePicker) + app.use(TimePicker) + app.use(Timeline) + app.use(Typography) + app.use(Empty) + app.use(Popconfirm) + app.use(Select) + app.use(SelectOption) + app.use(Switch) + app.use(Tree) + app.use(TreeSelect) + app.use(Card) + app.use(Alert) + app.use(Menu) + app.use(Tooltip) + app.use(Descriptions) + app.use(Steps) + app.use(Form) + app.use(Spin) + app.use(Dropdown) + app.use(Input) + app.use(VXETable) } diff --git a/src/enums/appEnum.ts b/src/enums/appEnum.ts index 9860e1982..d55234efa 100644 --- a/src/enums/appEnum.ts +++ b/src/enums/appEnum.ts @@ -29,13 +29,10 @@ export enum SessionTimeoutProcessingEnum { * 权限模式 */ export enum PermissionModeEnum { - // role // 角色权限 ROLE = 'ROLE', - // back // 后端 BACK = 'BACK', - // route mapping // 路由映射 ROUTE_MAPPING = 'ROUTE_MAPPING', } diff --git a/src/enums/httpEnum.ts b/src/enums/httpEnum.ts index c7548cce9..a8d74205a 100644 --- a/src/enums/httpEnum.ts +++ b/src/enums/httpEnum.ts @@ -5,6 +5,7 @@ export enum ResultEnum { SUCCESS = 0, ERROR = -1, TIMEOUT = 401, + NOT_LOGIN = 10004, TYPE = 'success', } diff --git a/src/enums/wsNoticeEnum.ts b/src/enums/wsNoticeEnum.ts new file mode 100644 index 000000000..a33a75fee --- /dev/null +++ b/src/enums/wsNoticeEnum.ts @@ -0,0 +1,9 @@ +/** + * 服务端websocket事件通知类型 + */ +export enum WsListenerEnum { + // 通知消息发生消息更新 主要是 未读数量更新 + NOTICE_MESSAGE_UPDATE = 'notice_message_update', + // ws测试事件 + EVENT_TEST_WEBSOCKET = 'event_test_websocket', +} diff --git a/src/hooks/setting/index.ts b/src/hooks/setting/index.ts index 948a484d2..6cff28291 100644 --- a/src/hooks/setting/index.ts +++ b/src/hooks/setting/index.ts @@ -3,7 +3,7 @@ import type { GlobConfig } from '#/config' import { getAppEnvConfig } from '@/utils/env' export const useGlobSetting = (): Readonly => { - const { VITE_GLOB_APP_TITLE, VITE_GLOB_API_URL, VITE_GLOB_API_URL_PREFIX, VITE_GLOB_UPLOAD_URL } = getAppEnvConfig() + const { VITE_GLOB_APP_TITLE, VITE_GLOB_API_URL, VITE_GLOB_API_URL_PREFIX } = getAppEnvConfig() // Take global configuration const glob: Readonly = { @@ -11,7 +11,6 @@ export const useGlobSetting = (): Readonly => { apiUrl: VITE_GLOB_API_URL, shortName: VITE_GLOB_APP_TITLE.replace(/\s/g, '_').replace(/-/g, '_'), urlPrefix: VITE_GLOB_API_URL_PREFIX, - uploadUrl: VITE_GLOB_UPLOAD_URL, } return glob as Readonly } diff --git a/src/hooks/web/usePermission.ts b/src/hooks/web/usePermission.ts index 81240cfaa..cc421480e 100644 --- a/src/hooks/web/usePermission.ts +++ b/src/hooks/web/usePermission.ts @@ -2,12 +2,10 @@ import type { RouteRecordRaw } from 'vue-router' import { useAppStore } from '@/store/modules/app' import { usePermissionStore } from '@/store/modules/permission' -import { useUserStore } from '@/store/modules/user' import { useTabs } from './useTabs' import { router, resetRouter } from '@/router' -// import { RootRoute } from '@/router/routes'; import projectSetting from '@/settings/projectSetting' import { PermissionModeEnum } from '@/enums/appEnum' @@ -19,7 +17,6 @@ import { useMultipleTabStore } from '@/store/modules/multipleTab' // User permissions related operations export function usePermission() { - const userStore = useUserStore() const appStore = useAppStore() const permissionStore = usePermissionStore() const { closeAll } = useTabs(router) @@ -30,7 +27,7 @@ export function usePermission() { async function togglePermissionMode() { appStore.setProjectConfig({ permissionMode: - appStore.projectConfig?.permissionMode === PermissionModeEnum.BACK ? PermissionModeEnum.ROUTE_MAPPING : PermissionModeEnum.BACK, + projectSetting.permissionMode === PermissionModeEnum.BACK ? PermissionModeEnum.ROUTE_MAPPING : PermissionModeEnum.BACK, }) location.reload() } @@ -38,18 +35,17 @@ export function usePermission() { /** * Reset and regain authority resource information * 重置和重新获得权限资源信息 + * @param id */ async function resume() { + console.log('重置和重新获得权限资源信息') const tabStore = useMultipleTabStore() tabStore.clearCacheTabs() resetRouter() - - // 动态加载路由(再次) const routes = await permissionStore.buildRoutesAction() routes.forEach((route) => { router.addRoute(route as unknown as RouteRecordRaw) }) - permissionStore.setLastBuildMenuTime() closeAll() } @@ -63,47 +59,11 @@ export function usePermission() { return def } - const permMode = appStore.getProjectConfig.permissionMode - - if ([PermissionModeEnum.ROUTE_MAPPING, PermissionModeEnum.ROLE].includes(permMode)) { - if (!isArray(value)) { - return userStore.getRoleList?.includes(value as RoleEnum) - } - return (intersection(value, userStore.getRoleList) as RoleEnum[]).length > 0 + const allCodeList = permissionStore.getPermCodeList as string[] + if (!isArray(value)) { + return allCodeList.includes(value) } - - if (PermissionModeEnum.BACK === permMode) { - const allCodeList = permissionStore.getPermCodeList as string[] - if (!isArray(value)) { - const splits = ['||', '&&'] - const splitName = splits.find((item) => value.includes(item)) - if (splitName) { - const splitCodes = value.split(splitName) - return splitName === splits[0] - ? intersection(splitCodes, allCodeList).length > 0 - : intersection(splitCodes, allCodeList).length === splitCodes.length - } - return allCodeList.includes(value) - } - return (intersection(value, allCodeList) as string[]).length > 0 - } - return true - } - - /** - * Change roles - * @param roles - */ - async function changeRole(roles: RoleEnum | RoleEnum[]): Promise { - if (projectSetting.permissionMode !== PermissionModeEnum.ROUTE_MAPPING) { - throw new Error('Please switch PermissionModeEnum to ROUTE_MAPPING mode in the configuration to operate!') - } - - if (!isArray(roles)) { - roles = [roles] - } - userStore.setRoleList(roles) - await resume() + return (intersection(value, allCodeList) as string[]).length > 0 } /** @@ -113,5 +73,5 @@ export function usePermission() { resume() } - return { changeRole, hasPermission, togglePermissionMode, refreshMenu } + return { hasPermission, togglePermissionMode, refreshMenu } } diff --git a/src/logics/websocket/UserGlobalWebSocker.ts b/src/logics/websocket/UserGlobalWebSocker.ts new file mode 100644 index 000000000..180b4fb45 --- /dev/null +++ b/src/logics/websocket/UserGlobalWebSocker.ts @@ -0,0 +1,105 @@ +/** + * 用户全局websocket连接管理 + */ +import { useWebSocket } from '@vueuse/core' +import { useUserStoreWithOut } from '@/store/modules/user' +import { EVENT_NOTICE, NOTIFICATION_ERROR, NOTIFICATION_INFO, NOTIFICATION_WARN } from '@/logics/websocket/WebSockerType' +import { publishWsEvent } from '@/logics/websocket/WebsocketNotice' +import { useMessage } from '@/hooks/web/useMessage' +import { findByParamKey } from '@/api/common/Parameter' +import { authEcho } from '@/api/common/BaseApi.api' + +const { notification } = useMessage() + +// websocket关闭 +let wsClose: WebSocket['close'] + +/** + * 初始化用户是否加载 + */ +export async function initWebSocket() { + const userStore = useUserStoreWithOut() + const token = userStore.getToken + const { data: wsUrl } = await findByParamKey('WebsocketServerUrl') + // 判断token是否有效, 无效会自动退出 + await authEcho('') + // 后端服务地址 + const serverUrl = `${wsUrl}/ws/user?AccessToken=${token}` + + // 创建websocket实例 + const { close } = useWebSocket(serverUrl, { + autoReconnect: true, //自动重新连接 + heartbeat: true, // 心跳检测 + onMessage: onMessage, + onConnected: () => { + console.log('用户全局WebSocket连接成功') + }, + onDisconnected: (ws, event) => { + console.error('用户全局WebSocket断开连接') + }, + }) + wsClose = close +} + +/** + * 事件分发 + */ +/** + * 处理接收到的消息 + */ +function onMessage(ws: WebSocket, event: MessageEvent) { + const res = JSON.parse(event.data) + if ([NOTIFICATION_INFO, NOTIFICATION_WARN, NOTIFICATION_ERROR].includes(res.type)) { + wsNotification(res) + } else if ([EVENT_NOTICE].includes(res.type)) { + wsEventNotice(res) + } +} + +/** + * 事件通知 弹框 + */ +function wsNotification(res: WsResult) { + if (res.type === NOTIFICATION_INFO) { + notification.info({ + message: '消息通知', + description: res.data, + }) + } else if (res.type === NOTIFICATION_WARN) { + notification.warn({ + message: '警告', + description: res.data, + }) + } else if (res.type === NOTIFICATION_ERROR) { + notification.info({ + message: '警告', + description: res.data, + }) + } +} + +/** + * 事件通知 发送到消息总线 + */ +function wsEventNotice(res: WsResult) { + // 发布事件到消息总线 + publishWsEvent(res.eventCode, res.data) +} +/** + * 关闭 + */ +export function closeWebSocket() { + wsClose && wsClose() +} + +/** + * websocket响应消息类 + */ +export interface WsResult { + // 类型编码 + type: number + // 数据体 + data: T + // 事件编码 + eventCode: number +} diff --git a/src/logics/websocket/WebSockerType.ts b/src/logics/websocket/WebSockerType.ts new file mode 100644 index 000000000..5eaa0aa68 --- /dev/null +++ b/src/logics/websocket/WebSockerType.ts @@ -0,0 +1,9 @@ +// 普通通知 +export const NOTIFICATION_INFO = 1001 +// 警告通知 +export const NOTIFICATION_WARN = 1002 +// 错误通知 +export const NOTIFICATION_ERROR = 1003 + +// 事件通知跳转 +export const EVENT_NOTICE = 9001 diff --git a/src/logics/websocket/WebsocketNotice.ts b/src/logics/websocket/WebsocketNotice.ts new file mode 100644 index 000000000..f421a9582 --- /dev/null +++ b/src/logics/websocket/WebsocketNotice.ts @@ -0,0 +1,37 @@ +import { EventHandlerList, Handler, mitt } from '@/utils/mitt' +import { WsListenerEnum } from '@/enums/wsNoticeEnum' + +/** + * 服务端WebSocket消息推送通知 + */ + +const emitter = mitt() + +/** + * 发布事件 + */ +export function publishWsEvent(key, data) { + emitter.emit(key, data) +} + +/** + * 事件监听 + */ +export function listenerEvent(key: WsListenerEnum, callback: Handler) { + emitter.on(key.toString(), callback) +} +/** + * 清除指定key所关联的事件监听 + */ +export function clearEventsByKey(key: WsListenerEnum) { + // 一个key可能对应多个事件回调, 清除该key所关联的所有会话 + const eventHandlerList = emitter.all.get(key.toString()) as EventHandlerList + eventHandlerList.forEach((value) => emitter.off(key.toString(), value)) +} + +/** + * 清除指定事件的监听 + */ +export function clearEvent(key: WsListenerEnum, callback: Handler) { + emitter.off(key.toString(), callback) +} diff --git a/src/router/guard/index.ts b/src/router/guard/index.ts index 440955e29..9be8bcac2 100644 --- a/src/router/guard/index.ts +++ b/src/router/guard/index.ts @@ -14,7 +14,7 @@ import nProgress from 'nprogress' import projectSetting from '@/settings/projectSetting' import { createParamMenuGuard } from './paramMenuGuard' -// Don't change the order of creation +// 不要更改创建顺序 export function setupRouterGuard(router: Router) { createPageGuard(router) createPageLoadingGuard(router) @@ -47,7 +47,7 @@ function createPageGuard(router: Router) { }) } -// Used to handle page loading status +// 用于处理页面加载状态 function createPageLoadingGuard(router: Router) { const userStore = useUserStoreWithOut() const appStore = useAppStoreWithOut() @@ -111,7 +111,7 @@ function createScrollGuard(router: Router) { } /** - * Used to close the message instance when the route is switched + * 用于在切换路由时关闭消息实例 * @param router */ export function createMessageGuard(router: Router) { diff --git a/src/router/guard/paramMenuGuard.ts b/src/router/guard/paramMenuGuard.ts index 4bdfec19e..c458d6a5e 100644 --- a/src/router/guard/paramMenuGuard.ts +++ b/src/router/guard/paramMenuGuard.ts @@ -37,11 +37,11 @@ const getPermissionMode = () => { const appStore = useAppStoreWithOut() return appStore.getProjectConfig.permissionMode } - +// 后端模式 const isBackMode = () => { return getPermissionMode() === PermissionModeEnum.BACK } - +// 路由映射 const isRouteMappingMode = () => { return getPermissionMode() === PermissionModeEnum.ROUTE_MAPPING } diff --git a/src/router/guard/permissionGuard.ts b/src/router/guard/permissionGuard.ts index 4fc52a7e3..6452be81f 100644 --- a/src/router/guard/permissionGuard.ts +++ b/src/router/guard/permissionGuard.ts @@ -7,124 +7,90 @@ import { useUserStoreWithOut } from '@/store/modules/user' import { PAGE_NOT_FOUND_ROUTE } from '@/router/routes/basic' -import { RootRoute } from '@/router/routes' - const LOGIN_PATH = PageEnum.BASE_LOGIN -const ROOT_PATH = RootRoute.path - const whitePathList: PageEnum[] = [LOGIN_PATH] +/** + * 路由守卫: 处理下列情况 + * 1. 载入菜单 + * 2. 处理登录后用户提示 + * @param router + */ export function createPermissionGuard(router: Router) { const userStore = useUserStoreWithOut() const permissionStore = usePermissionStoreWithOut() router.beforeEach(async (to, from, next) => { - if ( - from.path === ROOT_PATH && - to.path === PageEnum.BASE_HOME && - userStore.getUserInfo.homePath && - userStore.getUserInfo.homePath !== PageEnum.BASE_HOME - ) { - next(userStore.getUserInfo.homePath) - return - } - const token = userStore.getToken - - // Whitelist can be directly entered + // 可以访问输入白名单中的页面 if (whitePathList.includes(to.path as PageEnum)) { + // 如果在登录状态下访问登录页, 自动跳转到后续页面 if (to.path === LOGIN_PATH && token) { - const isSessionTimeout = userStore.getSessionTimeout try { - await userStore.afterLoginAction() - if (!isSessionTimeout) { - next(decodeURIComponent((to.query?.redirect as string) || '/')) - return - } + // 如果参数未携带重定向路径则自动跳转到首页 + next((to.query?.redirect as string) || '/') + return } catch { - // + /* empty */ } } next() return } - // token or user does not exist + + // token 不存在 if (!token) { - // You can access without permission. You need to set the routing meta.ignoreAuth to true + // 您可以在未经许可的情况下访问。您需要将路由meta中的 忽略身份验证设置为 true if (to.meta.ignoreAuth) { next() return } - - // redirect login page + //重定向登录页面 const redirectData: { path: string; replace: boolean; query?: Recordable } = { path: LOGIN_PATH, replace: true, } - if (to.fullPath) { + if (to.path) { redirectData.query = { ...redirectData.query, - redirect: to.fullPath, + redirect: to.path, } } next(redirectData) return } - // get userinfo while last fetch time is empty - if (userStore.getLastUpdateTime === 0) { - try { - await userStore.getUserInfoAction() - } catch (err) { - next() - return - } - } - - // 动态路由加载(首次) - if (!permissionStore.getIsDynamicAddedRoute) { - const routes = await permissionStore.buildRoutesAction() - ;[...routes, PAGE_NOT_FOUND_ROUTE].forEach((route) => { - router.addRoute(route as unknown as RouteRecordRaw) - }) - // 记录动态路由加载完成 - permissionStore.setDynamicAddedRoute(true) - - // 现在的to动态路由加载之前的,可能为PAGE_NOT_FOUND_ROUTE(例如,登陆后,刷新的时候) - // 此处应当重定向到fullPath,否则会加载404页面内容 - next({ path: to.fullPath, replace: true, query: to.query }) + // 路由是否初始化完毕, 完毕后直接直接跳转, 不再向下执行初始化操作 + if (permissionStore.getIsDynamicAddedRoute) { + next() return } + // 用户初始化等操作. + // userLoginInitAction() + + // 重载菜单, 进行路由菜单的组装并进行跳转 + console.log('重载菜单') + const routes = await permissionStore.buildRoutesAction() + routes.forEach((route) => { + try { + router.addRoute(route as RouteRecordRaw) + } catch (e) { + console.error(e) + } + }) + + // 40x 系列路由 + router.addRoute(PAGE_NOT_FOUND_ROUTE as unknown as RouteRecordRaw) + permissionStore.setDynamicAddedRoute(true) if (to.name === PAGE_NOT_FOUND_ROUTE.name) { - // 遇到不存在页面,后续逻辑不再处理redirect(阻止下面else逻辑) - from.query.redirect = '' - - if (from.path === LOGIN_PATH && to.fullPath !== (userStore.getUserInfo.homePath || PageEnum.BASE_HOME)) { - // 登陆重定向不存在路由,转去“首页” - next({ path: userStore.getUserInfo.homePath || PageEnum.BASE_HOME, replace: true }) - } else { - // 正常前往“404”页面 - next() - } - } else if (from.query.redirect) { - // 存在redirect - const redirect = decodeURIComponent((from.query.redirect as string) || '') - - // 只处理一次 from.query.redirect - // 也避免某场景(指向路由定义了 redirect)下的死循环 - from.query.redirect = '' - - if (redirect === to.fullPath) { - // 已经被redirect - next() - } else { - // 指向redirect - next({ path: redirect, replace: true }) - } + // 动态添加路由后,此处应当重定向到fullPath,否则会加载404页面内容 + next({ path: to.fullPath, replace: true, query: to.query }) } else { - // 正常访问 - next() + const redirectPath = (from.query.redirect || to.path) as string + const redirect = decodeURIComponent(redirectPath) + const nextData = to.path === redirect ? { ...to, replace: true } : { path: redirect } + next(nextData) } }) } diff --git a/src/router/guard/stateGuard.ts b/src/router/guard/stateGuard.ts index 01c30c2ac..5c4213e95 100644 --- a/src/router/guard/stateGuard.ts +++ b/src/router/guard/stateGuard.ts @@ -6,6 +6,10 @@ import { usePermissionStore } from '@/store/modules/permission' import { PageEnum } from '@/enums/pageEnum' import { removeTabChangeListener } from '@/logics/mitt/routeChange' +/** + * 创建路由守卫 + * @param router + */ export function createStateGuard(router: Router) { router.afterEach((to) => { // Just enter the login page and clear the authentication information diff --git a/src/router/helper/menuHelper.ts b/src/router/helper/menuHelper.ts index eb68ab18e..341f6f540 100644 --- a/src/router/helper/menuHelper.ts +++ b/src/router/helper/menuHelper.ts @@ -2,7 +2,7 @@ import { AppRouteModule } from '@/router/types' import type { MenuModule, Menu, AppRouteRecordRaw } from '@/router/types' import { findPath, treeMap } from '@/utils/helper/treeHelper' import { cloneDeep } from 'lodash-es' -import { isHttpUrl } from '@/utils/is' +import { isOutsideUrl } from '@/utils/is' import { RouteParams } from 'vue-router' import { toRaw } from 'vue' @@ -11,18 +11,16 @@ export function getAllParentPath(treeData: T[], path: string) { return (menuList || []).map((item) => item.path) } -// 路径处理 +/** + * 路径处理 + */ function joinParentPath(menus: Menu[], parentPath = '') { for (let index = 0; index < menus.length; index++) { const menu = menus[index] - // https://next.router.vuejs.org/guide/essentials/nested-routes.html - // Note that nested paths that start with / will be treated as a root path. - // 请注意,以 / 开头的嵌套路径将被视为根路径。 - // This allows you to leverage the component nesting without having to use a nested URL. - // 这允许你利用组件嵌套,而无需使用嵌套 URL。 - if (!(menu.path.startsWith('/') || isHttpUrl(menu.path))) { + // 请注意,以 / 开头的嵌套路径将被视为根路径。这允许你利用组件嵌套,而无需使用嵌套 URL。 + if (!(menu.path.startsWith('/') || isOutsideUrl(menu.path))) { // path doesn't start with /, nor is it a url, join parent path - // 路径不以 / 开头,也不是 url,加入父路径 + // 路径不以 / 开头,也不是外部打开的路径,加入父路径 menu.path = `${parentPath}/${menu.path}` } if (menu?.children?.length) { @@ -31,15 +29,21 @@ function joinParentPath(menus: Menu[], parentPath = '') { } } -// Parsing the menu module +/** + * 解析菜单模块 + */ export function transformMenuModule(menuModule: MenuModule): Menu { - const menuList = [menuModule] + // const { menu } = menuModule + const { menu } = menuModule + const menuList = [menu] joinParentPath(menuList) return menuList[0] } -// 将路由转换成菜单 +/** + * 将路由转换成菜单 + */ export function transformRouteToMenu(routeModList: AppRouteModule[], routerMapping = false) { // 借助 lodash 深拷贝 const cloneRouteModList = cloneDeep(routeModList) @@ -61,12 +65,12 @@ export function transformRouteToMenu(routeModList: AppRouteModule[], routerMappi // 提取树指定结构 const list = treeMap(routeList, { conversion: (node: AppRouteRecordRaw) => { - const { meta: { hideMenu = false } = {}, name } = node + const { meta: { title, hideMenu = false } = {} } = node return { ...(node.meta || {}), meta: node.meta, - name, + name: title, hideMenu, path: node.path, ...(node.redirect ? { redirect: node.redirect } : {}), @@ -81,7 +85,7 @@ export function transformRouteToMenu(routeModList: AppRouteModule[], routerMappi /** * config menu with given params */ -const menuParamRegex = /(?::)([\s\S]+?)((?=\/)|$)/g +const menuParamRegex = /:([\s\S]+?)((?=\/)|$)/g export function configureDynamicParamsMenu(menu: Menu, params: RouteParams) { const { path, paramPath } = toRaw(menu) diff --git a/src/router/helper/routeHelper.ts b/src/router/helper/routeHelper.ts index b78c56cdc..0df81164e 100644 --- a/src/router/helper/routeHelper.ts +++ b/src/router/helper/routeHelper.ts @@ -4,10 +4,10 @@ import type { Router, RouteRecordNormalized } from 'vue-router' import { getParentLayout, LAYOUT, EXCEPTION_COMPONENT } from '@/router/constant' import { cloneDeep, omit } from 'lodash-es' import { warn } from '@/utils/log' -import { createRouter, createWebHashHistory } from 'vue-router' +import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router' +import XEUtils from 'xe-utils' -export type LayoutMapKey = 'LAYOUT' -const IFRAME = () => import('@/views/sys/iframe/FrameBlank.vue') +const IFRAME = () => import('/@/views/sys/iframe/FrameBlank.vue') const LayoutMap = new Map Promise>() @@ -16,32 +16,50 @@ LayoutMap.set('IFRAME', IFRAME) let dynamicViewsModules: Record Promise> -// Dynamic introduction +/** + * 动态导入路由 + */ function asyncImportRoute(routes: AppRouteRecordRaw[] | undefined) { dynamicViewsModules = dynamicViewsModules || import.meta.glob('../../views/**/*.{vue,tsx}') + // 路由是否为空 if (!routes) return routes.forEach((item) => { - if (!item.component && item.meta?.frameSrc) { - item.component = 'IFRAME' - } const { component, name } = item + // 名称为空就随机生成 + if (!item.name) { + item.name = String(XEUtils.random(1, 999999)) + } + // 内部打开, 是否是 Iframe 方式, redirect配置作为内部打开的地址 + if ((item.component as string).toUpperCase() === 'IFRAME') { + item.meta.frameSrc = item.redirect + item.redirect = undefined + } const { children } = item + // 组件替换 if (component) { - const layoutFound = LayoutMap.get(component.toUpperCase()) - if (layoutFound) { - item.component = layoutFound + const componentName = component.toUpperCase() + if (['LAYOUT', 'IFRAME'].includes(componentName)) { + item.component = LayoutMap.get(componentName) } else { item.component = dynamicImport(dynamicViewsModules, component as string) } } else if (name) { item.component = getParentLayout() } + // 有自己菜单进行递归 children && asyncImportRoute(children) }) } +/** + * 动态引入组件 可以识别 src/views/ 下创建的组件 + * @param dynamicViewsModules + * @param component + */ function dynamicImport(dynamicViewsModules: Record Promise>, component: string) { + // 路径集合 const keys = Object.keys(dynamicViewsModules) + // 查询配置路径对应的组件 const matchKeys = keys.filter((key) => { const k = key.replace('../../views', '') const startFlag = component.startsWith('/') @@ -54,20 +72,19 @@ function dynamicImport(dynamicViewsModules: Record Promise 1) { - warn( - 'Please do not create `.vue` and `.TSX` files with the same file name in the same hierarchical directory under the views folder. This will cause dynamic introduction failure', - ) + warn('请不要在views文件夹下的同一层次目录中创建具有相同文件名的 .vue 和 .TSX 文件。这将导致动态引入失败') return } else { - warn('在src/views/下找不到`' + component + '.vue` 或 `' + component + '.tsx`, 请自行创建!') + warn('在src/views/下找不到`' + component + '.vue` 或 `' + component + '.tsx`, 请检查路径是否正确!') return EXCEPTION_COMPONENT } } -// Turn background objects into routing objects -// 将背景对象变成路由对象 -export function transformObjToRoute(routeList: AppRouteModule[]): T[] { - routeList.forEach((route) => { +/** + * 将后端对象变成路由对象 + */ +export function transformObjToRoute(routeList: AppRouteRecordRaw[]): T[] { + routeList?.forEach((route) => { const component = route.component as string if (component) { if (component.toUpperCase() === 'LAYOUT') { @@ -75,14 +92,7 @@ export function transformObjToRoute(routeList: AppRouteModul } else { route.children = [cloneDeep(route)] route.component = LAYOUT - - //某些情况下如果name如果没有值, 多个一级路由菜单会导致页面404 - if (!route.name) { - warn('找不到菜单对应的name, 请检查数据!' + JSON.stringify(route)) - } route.name = `${route.name}Parent` - // 重定向到当前路由,以防空白页面 - route.redirect = route.path route.path = '' const meta = route.meta || {} meta.single = true @@ -120,11 +130,10 @@ export function flatMultiLevelRoutes(routeModules: AppRouteModule[]) { // Routing level upgrade // 路由等级提升 function promoteRouteLevel(routeModule: AppRouteModule) { - // Use vue-router to splice menus // 使用vue-router拼接菜单 // createRouter 创建一个可以被 Vue 应用程序使用的路由实例 let router: Router | null = createRouter({ - routes: [routeModule as unknown as RouteRecordNormalized], + routes: [routeModule as RouteRecordRaw], history: createWebHashHistory(), }) // getRoutes: 获取所有 路由记录的完整列表。 @@ -138,7 +147,7 @@ function promoteRouteLevel(routeModule: AppRouteModule) { } // Add all sub-routes to the secondary route -// 将所有子路由添加到二级路由 +// 将所有子路由添加到二级路由 弃用 function addToChildren(routes: RouteRecordNormalized[], children: AppRouteRecordRaw[], routeModule: AppRouteModule) { for (let index = 0; index < children.length; index++) { const child = children[index] @@ -157,7 +166,7 @@ function addToChildren(routes: RouteRecordNormalized[], children: AppRouteRecord } // Determine whether the level exceeds 2 levels -// 判断级别是否超过2级 +// 判断级别是否超过2级 弃用 function isMultipleRoute(routeModule: AppRouteModule) { // Reflect.has 与 in 操作符 相同, 用于检查一个对象(包括它原型链上)是否拥有某个属性 if (!routeModule || !Reflect.has(routeModule, 'children') || !routeModule.children?.length) { diff --git a/src/router/menus/index.ts b/src/router/menus/index.ts index 4cd188c68..de4f4b861 100644 --- a/src/router/menus/index.ts +++ b/src/router/menus/index.ts @@ -10,7 +10,7 @@ import { router } from '@/router' import { PermissionModeEnum } from '@/enums/appEnum' import { pathToRegexp } from 'path-to-regexp' -const modules = import.meta.glob('../routes/modules/**/*.ts', { eager: true }) +const modules = import.meta.glob('./modules/**/*.ts', { eager: true }) const menuModules: MenuModule[] = [] @@ -45,31 +45,17 @@ const staticMenus: Menu[] = [] menuModules.sort((a, b) => { return (a.orderNo || 0) - (b.orderNo || 0) }) - for (const menu of menuModules) { staticMenus.push(transformMenuModule(menu)) } })() +/** + * 获取菜单 + */ async function getAsyncMenus() { const permissionStore = usePermissionStore() - //递归过滤所有隐藏的菜单 - const menuFilter = (items) => { - return items.filter((item) => { - const show = !item.meta?.hideMenu && !item.hideMenu - if (show && item.children) { - item.children = menuFilter(item.children) - } - return show - }) - } - if (isBackMode()) { - return menuFilter(permissionStore.getBackMenuList) - } - if (isRouteMappingMode()) { - return menuFilter(permissionStore.getFrontMenuList) - } - return staticMenus + return permissionStore.getBackMenuList.filter((item) => !item.meta?.hideMenu && !item.hideMenu) } export const getMenus = async (): Promise => { diff --git a/src/router/routes/index.ts b/src/router/routes/index.ts index b7c3d7cca..98b57237e 100644 --- a/src/router/routes/index.ts +++ b/src/router/routes/index.ts @@ -2,7 +2,6 @@ import type { AppRouteRecordRaw, AppRouteModule } from '@/router/types' import { PAGE_NOT_FOUND_ROUTE, REDIRECT_ROUTE } from '@/router/routes/basic' -import { mainOutRoutes } from './mainOut' import { PageEnum } from '@/enums/pageEnum' import { t } from '@/hooks/web/useI18n' @@ -40,4 +39,4 @@ export const LoginRoute: AppRouteRecordRaw = { // Basic routing without permission // 未经许可的基本路由 -export const basicRoutes = [LoginRoute, RootRoute, ...mainOutRoutes, REDIRECT_ROUTE, PAGE_NOT_FOUND_ROUTE] +export const basicRoutes = [LoginRoute, RootRoute, REDIRECT_ROUTE, PAGE_NOT_FOUND_ROUTE] diff --git a/src/router/routes/mainOut.ts b/src/router/routes/mainOut.ts deleted file mode 100644 index 37ba50879..000000000 --- a/src/router/routes/mainOut.ts +++ /dev/null @@ -1,22 +0,0 @@ -/** -The routing of this file will not show the layout. -It is an independent new page. -the contents of the file still need to log in to access - */ -import type { AppRouteModule } from '@/router/types' - -// test -// http:ip:port/main-out -export const mainOutRoutes: AppRouteModule[] = [ - { - path: '/main-out', - name: 'MainOut', - component: () => import('@/views/demo/main-out/index.vue'), - meta: { - title: 'MainOut', - ignoreAuth: true, - }, - }, -] - -export const mainOutRouteNames = mainOutRoutes.map((item) => item.name) diff --git a/src/router/routes/modules/dashboard.ts b/src/router/routes/modules/dashboard.ts index ff2c07c4d..909c420c7 100644 --- a/src/router/routes/modules/dashboard.ts +++ b/src/router/routes/modules/dashboard.ts @@ -3,7 +3,7 @@ import type { AppRouteModule } from '@/router/types' import { LAYOUT } from '@/router/constant' import { t } from '@/hooks/web/useI18n' -const dashboard: AppRouteModule = { +const Dashboard: AppRouteModule = { path: '/dashboard', name: 'Dashboard', component: LAYOUT, @@ -34,4 +34,4 @@ const dashboard: AppRouteModule = { ], } -export default dashboard +export default Dashboard diff --git a/src/router/routes/modules/demo/charts.ts b/src/router/routes/modules/demo/charts.ts deleted file mode 100644 index 8a040d94b..000000000 --- a/src/router/routes/modules/demo/charts.ts +++ /dev/null @@ -1,80 +0,0 @@ -import type { AppRouteModule } from '@/router/types' - -import { getParentLayout, LAYOUT } from '@/router/constant' -import { t } from '@/hooks/web/useI18n' - -const charts: AppRouteModule = { - path: '/charts', - name: 'Charts', - component: LAYOUT, - redirect: '/charts/echarts/map', - meta: { - orderNo: 500, - icon: 'ion:bar-chart-outline', - title: t('routes.demo.charts.charts'), - }, - children: [ - { - path: 'baiduMap', - name: 'BaiduMap', - meta: { - title: t('routes.demo.charts.baiduMap'), - }, - component: () => import('@/views/demo/charts/map/Baidu.vue'), - }, - { - path: 'aMap', - name: 'AMap', - meta: { - title: t('routes.demo.charts.aMap'), - }, - component: () => import('@/views/demo/charts/map/Gaode.vue'), - }, - { - path: 'googleMap', - name: 'GoogleMap', - meta: { - title: t('routes.demo.charts.googleMap'), - }, - component: () => import('@/views/demo/charts/map/Google.vue'), - }, - - { - path: 'echarts', - name: 'Echarts', - component: getParentLayout('Echarts'), - meta: { - title: 'Echarts', - }, - redirect: '/charts/echarts/map', - children: [ - { - path: 'map', - name: 'Map', - component: () => import('@/views/demo/charts/Map.vue'), - meta: { - title: t('routes.demo.charts.map'), - }, - }, - { - path: 'line', - name: 'Line', - component: () => import('@/views/demo/charts/Line.vue'), - meta: { - title: t('routes.demo.charts.line'), - }, - }, - { - path: 'pie', - name: 'Pie', - component: () => import('@/views/demo/charts/Pie.vue'), - meta: { - title: t('routes.demo.charts.pie'), - }, - }, - ], - }, - ], -} - -export default charts diff --git a/src/router/routes/modules/demo/comp.ts b/src/router/routes/modules/demo/comp.ts deleted file mode 100644 index d0306bbc2..000000000 --- a/src/router/routes/modules/demo/comp.ts +++ /dev/null @@ -1,470 +0,0 @@ -import type { AppRouteModule } from '@/router/types' - -import { getParentLayout, LAYOUT } from '@/router/constant' -import { t } from '@/hooks/web/useI18n' - -const comp: AppRouteModule = { - path: '/comp', - name: 'Comp', - component: LAYOUT, - redirect: '/comp/basic', - meta: { - orderNo: 30, - icon: 'ion:layers-outline', - title: t('routes.demo.comp.comp'), - }, - - children: [ - { - path: 'basic', - name: 'BasicDemo', - component: () => import('@/views/demo/comp/button/index.vue'), - meta: { - title: t('routes.demo.comp.basic'), - }, - }, - - { - path: 'form', - name: 'FormDemo', - redirect: '/comp/form/basic', - component: getParentLayout('FormDemo'), - meta: { - // icon: 'mdi:form-select', - title: t('routes.demo.form.form'), - }, - children: [ - { - path: 'basic', - name: 'FormBasicDemo', - component: () => import('@/views/demo/form/index.vue'), - meta: { - title: t('routes.demo.form.basic'), - }, - }, - { - path: 'useForm', - name: 'UseFormDemo', - component: () => import('@/views/demo/form/UseForm.vue'), - meta: { - title: t('routes.demo.form.useForm'), - }, - }, - { - path: 'refForm', - name: 'RefFormDemo', - component: () => import('@/views/demo/form/RefForm.vue'), - meta: { - title: t('routes.demo.form.refForm'), - }, - }, - { - path: 'advancedForm', - name: 'AdvancedFormDemo', - component: () => import('@/views/demo/form/AdvancedForm.vue'), - meta: { - title: t('routes.demo.form.advancedForm'), - }, - }, - { - path: 'ruleForm', - name: 'RuleFormDemo', - component: () => import('@/views/demo/form/RuleForm.vue'), - meta: { - title: t('routes.demo.form.ruleForm'), - }, - }, - { - path: 'dynamicForm', - name: 'DynamicFormDemo', - component: () => import('@/views/demo/form/DynamicForm.vue'), - meta: { - title: t('routes.demo.form.dynamicForm'), - }, - }, - { - path: 'customerForm', - name: 'CustomerFormDemo', - component: () => import('@/views/demo/form/CustomerForm.vue'), - meta: { - title: t('routes.demo.form.customerForm'), - }, - }, - { - path: 'appendForm', - name: 'appendFormDemo', - component: () => import('@/views/demo/form/AppendForm.vue'), - meta: { - title: t('routes.demo.form.appendForm'), - }, - }, - { - path: 'tabsForm', - name: 'tabsFormDemo', - component: () => import('@/views/demo/form/TabsForm.vue'), - meta: { - title: t('routes.demo.form.tabsForm'), - }, - }, - ], - }, - { - path: 'table', - name: 'TableDemo', - redirect: '/comp/table/basic', - component: getParentLayout('TableDemo'), - meta: { - // icon: 'carbon:table-split', - title: t('routes.demo.table.table'), - }, - - children: [ - { - path: 'basic', - name: 'TableBasicDemo', - component: () => import('@/views/demo/table/Basic.vue'), - meta: { - title: t('routes.demo.table.basic'), - }, - }, - { - path: 'treeTable', - name: 'TreeTableDemo', - component: () => import('@/views/demo/table/TreeTable.vue'), - meta: { - title: t('routes.demo.table.treeTable'), - }, - }, - { - path: 'fetchTable', - name: 'FetchTableDemo', - component: () => import('@/views/demo/table/FetchTable.vue'), - meta: { - title: t('routes.demo.table.fetchTable'), - }, - }, - { - path: 'fixedColumn', - name: 'FixedColumnDemo', - component: () => import('@/views/demo/table/FixedColumn.vue'), - meta: { - title: t('routes.demo.table.fixedColumn'), - }, - }, - { - path: 'customerCell', - name: 'CustomerCellDemo', - component: () => import('@/views/demo/table/CustomerCell.vue'), - meta: { - title: t('routes.demo.table.customerCell'), - }, - }, - { - path: 'formTable', - name: 'FormTableDemo', - component: () => import('@/views/demo/table/FormTable.vue'), - meta: { - title: t('routes.demo.table.formTable'), - }, - }, - { - path: 'useTable', - name: 'UseTableDemo', - component: () => import('@/views/demo/table/UseTable.vue'), - meta: { - title: t('routes.demo.table.useTable'), - }, - }, - { - path: 'refTable', - name: 'RefTableDemo', - component: () => import('@/views/demo/table/RefTable.vue'), - meta: { - title: t('routes.demo.table.refTable'), - }, - }, - { - path: 'multipleHeader', - name: 'MultipleHeaderDemo', - component: () => import('@/views/demo/table/MultipleHeader.vue'), - meta: { - title: t('routes.demo.table.multipleHeader'), - }, - }, - { - path: 'mergeHeader', - name: 'MergeHeaderDemo', - component: () => import('@/views/demo/table/MergeHeader.vue'), - meta: { - title: t('routes.demo.table.mergeHeader'), - }, - }, - { - path: 'expandTable', - name: 'ExpandTableDemo', - component: () => import('@/views/demo/table/ExpandTable.vue'), - meta: { - title: t('routes.demo.table.expandTable'), - }, - }, - { - path: 'fixedHeight', - name: 'FixedHeightDemo', - component: () => import('@/views/demo/table/FixedHeight.vue'), - meta: { - title: t('routes.demo.table.fixedHeight'), - }, - }, - { - path: 'footerTable', - name: 'FooterTableDemo', - component: () => import('@/views/demo/table/FooterTable.vue'), - meta: { - title: t('routes.demo.table.footerTable'), - }, - }, - { - path: 'editCellTable', - name: 'EditCellTableDemo', - component: () => import('@/views/demo/table/EditCellTable.vue'), - meta: { - title: t('routes.demo.table.editCellTable'), - }, - }, - { - path: 'editRowTable', - name: 'EditRowTableDemo', - component: () => import('@/views/demo/table/EditRowTable.vue'), - meta: { - title: t('routes.demo.table.editRowTable'), - }, - }, - { - path: 'authColumn', - name: 'AuthColumnDemo', - component: () => import('@/views/demo/table/AuthColumn.vue'), - meta: { - title: t('routes.demo.table.authColumn'), - }, - }, - { - path: 'resizeParentHeightTable', - name: 'ResizeParentHeightTable', - component: () => import('@/views/demo/table/ResizeParentHeightTable.vue'), - meta: { - title: t('routes.demo.table.resizeParentHeightTable'), - }, - }, - { - path: 'vxeTable', - name: 'VxeTableDemo', - component: () => import('@/views/demo/table/VxeTable.vue'), - meta: { - title: t('routes.demo.table.vxeTable'), - }, - }, - ], - }, - { - path: 'transition', - name: 'transitionDemo', - component: () => import('@/views/demo/comp/transition/index.vue'), - meta: { - title: t('routes.demo.comp.transition'), - }, - }, - { - path: 'cropper', - name: 'CropperDemo', - component: () => import('@/views/demo/comp/cropper/index.vue'), - meta: { - title: t('routes.demo.comp.cropperImage'), - }, - }, - - { - path: 'timestamp', - name: 'TimeDemo', - component: () => import('@/views/demo/comp/time/index.vue'), - meta: { - title: t('routes.demo.comp.time'), - }, - }, - { - path: 'countTo', - name: 'CountTo', - component: () => import('@/views/demo/comp/count-to/index.vue'), - meta: { - title: t('routes.demo.comp.countTo'), - }, - }, - { - path: 'tree', - name: 'TreeDemo', - redirect: '/comp/tree/basic', - component: getParentLayout('TreeDemo'), - meta: { - // icon: 'clarity:tree-view-line', - title: t('routes.demo.comp.tree'), - }, - children: [ - { - path: 'basic', - name: 'BasicTreeDemo', - component: () => import('@/views/demo/tree/index.vue'), - meta: { - title: t('routes.demo.comp.treeBasic'), - }, - }, - { - path: 'editTree', - name: 'EditTreeDemo', - component: () => import('@/views/demo/tree/EditTree.vue'), - meta: { - title: t('routes.demo.comp.editTree'), - }, - }, - { - path: 'actionTree', - name: 'ActionTreeDemo', - component: () => import('@/views/demo/tree/ActionTree.vue'), - meta: { - title: t('routes.demo.comp.actionTree'), - }, - }, - ], - }, - { - path: 'scroll', - name: 'ScrollDemo', - redirect: '/comp/scroll/basic', - component: getParentLayout('ScrollDemo'), - meta: { - title: t('routes.demo.comp.scroll'), - }, - children: [ - { - path: 'basic', - name: 'BasicScrollDemo', - component: () => import('@/views/demo/comp/scroll/index.vue'), - meta: { - title: t('routes.demo.comp.scrollBasic'), - }, - }, - { - path: 'action', - name: 'ActionScrollDemo', - component: () => import('@/views/demo/comp/scroll/Action.vue'), - meta: { - title: t('routes.demo.comp.scrollAction'), - }, - }, - { - path: 'virtualScroll', - name: 'VirtualScrollDemo', - component: () => import('@/views/demo/comp/scroll/VirtualScroll.vue'), - meta: { - title: t('routes.demo.comp.virtualScroll'), - }, - }, - ], - }, - - { - path: 'modal', - name: 'ModalDemo', - component: () => import('@/views/demo/comp/modal/index.vue'), - meta: { - title: t('routes.demo.comp.modal'), - }, - }, - { - path: 'drawer', - name: 'DrawerDemo', - component: () => import('@/views/demo/comp/drawer/index.vue'), - meta: { - title: t('routes.demo.comp.drawer'), - }, - }, - { - path: 'desc', - name: 'DescDemo', - component: () => import('@/views/demo/comp/desc/index.vue'), - meta: { - title: t('routes.demo.comp.desc'), - }, - }, - - { - path: 'verify', - name: 'VerifyDemo', - component: getParentLayout('VerifyDemo'), - redirect: '/comp/verify/drag', - meta: { - title: t('routes.demo.comp.verify'), - }, - children: [ - { - path: 'drag', - name: 'VerifyDragDemo', - component: () => import('@/views/demo/comp/verify/index.vue'), - meta: { - title: t('routes.demo.comp.verifyDrag'), - }, - }, - { - path: 'rotate', - name: 'VerifyRotateDemo', - component: () => import('@/views/demo/comp/verify/Rotate.vue'), - meta: { - title: t('routes.demo.comp.verifyRotate'), - }, - }, - ], - }, - // - - { - path: 'qrcode', - name: 'QrCodeDemo', - component: () => import('@/views/demo/comp/qrcode/index.vue'), - meta: { - title: t('routes.demo.comp.qrcode'), - }, - }, - { - path: 'strength-meter', - name: 'StrengthMeterDemo', - component: () => import('@/views/demo/comp/strength-meter/index.vue'), - meta: { - title: t('routes.demo.comp.strength'), - }, - }, - { - path: 'upload', - name: 'UploadDemo', - component: () => import('@/views/demo/comp/upload/index.vue'), - meta: { - title: t('routes.demo.comp.upload'), - }, - }, - { - path: 'loading', - name: 'LoadingDemo', - component: () => import('@/views/demo/comp/loading/index.vue'), - meta: { - title: t('routes.demo.comp.loading'), - }, - }, - { - path: 'cardList', - name: 'CardListDemo', - component: () => import('@/views/demo/comp/card-list/index.vue'), - meta: { - title: t('routes.demo.comp.cardList'), - }, - }, - ], -} - -export default comp diff --git a/src/router/routes/modules/demo/feat.ts b/src/router/routes/modules/demo/feat.ts deleted file mode 100644 index 70b9641a5..000000000 --- a/src/router/routes/modules/demo/feat.ts +++ /dev/null @@ -1,279 +0,0 @@ -import type { AppRouteModule } from '@/router/types' - -import { getParentLayout, LAYOUT } from '@/router/constant' -import { t } from '@/hooks/web/useI18n' - -const feat: AppRouteModule = { - path: '/feat', - name: 'FeatDemo', - component: LAYOUT, - redirect: '/feat/icon', - meta: { - orderNo: 19, - icon: 'ion:git-compare-outline', - title: t('routes.demo.feat.feat'), - }, - - children: [ - { - path: 'icon', - name: 'IconDemo', - component: () => import('@/views/demo/feat/icon/index.vue'), - meta: { - title: t('routes.demo.feat.icon'), - }, - }, - { - path: 'ws', - name: 'WebSocket', - component: () => import('@/views/demo/feat/ws/index.vue'), - meta: { - title: t('routes.demo.feat.ws'), - }, - }, - { - path: 'request', - name: 'RequestDemo', - // @ts-ignore - component: () => import('@/views/demo/feat/request-demo/index.vue'), - meta: { - title: t('routes.demo.feat.requestDemo'), - }, - }, - { - path: 'session-timeout', - name: 'SessionTimeout', - component: () => import('@/views/demo/feat/session-timeout/index.vue'), - meta: { - title: t('routes.demo.feat.sessionTimeout'), - }, - }, - { - path: 'tabs', - name: 'TabsDemo', - component: () => import('@/views/demo/feat/tabs/index.vue'), - meta: { - title: t('routes.demo.feat.tabs'), - hideChildrenInMenu: true, - }, - children: [ - { - path: 'detail/:id', - name: 'TabDetail', - component: () => import('@/views/demo/feat/tabs/TabDetail.vue'), - meta: { - currentActiveMenu: '/feat/tabs', - title: t('routes.demo.feat.tabDetail'), - hideMenu: true, - dynamicLevel: 3, - realPath: '/feat/tabs/detail', - }, - }, - ], - }, - { - path: 'breadcrumb', - name: 'BreadcrumbDemo', - redirect: '/feat/breadcrumb/flat', - component: getParentLayout('BreadcrumbDemo'), - meta: { - title: t('routes.demo.feat.breadcrumb'), - }, - - children: [ - { - path: 'flat', - name: 'BreadcrumbFlatDemo', - component: () => import('@/views/demo/feat/breadcrumb/FlatList.vue'), - meta: { - title: t('routes.demo.feat.breadcrumbFlat'), - }, - }, - { - path: 'flatDetail', - name: 'BreadcrumbFlatDetailDemo', - component: () => import('@/views/demo/feat/breadcrumb/FlatListDetail.vue'), - meta: { - title: t('routes.demo.feat.breadcrumbFlatDetail'), - hideMenu: true, - hideTab: true, - currentActiveMenu: '/feat/breadcrumb/flat', - }, - }, - { - path: 'children', - name: 'BreadcrumbChildrenDemo', - component: () => import('@/views/demo/feat/breadcrumb/ChildrenList.vue'), - meta: { - title: t('routes.demo.feat.breadcrumbChildren'), - }, - children: [ - { - path: 'childrenDetail', - name: 'BreadcrumbChildrenDetailDemo', - component: () => import('@/views/demo/feat/breadcrumb/ChildrenListDetail.vue'), - meta: { - currentActiveMenu: '/feat/breadcrumb/children', - title: t('routes.demo.feat.breadcrumbChildrenDetail'), - //hideTab: true, - // hideMenu: true, - }, - }, - ], - }, - ], - }, - - { - path: 'context-menu', - name: 'ContextMenuDemo', - component: () => import('@/views/demo/feat/context-menu/index.vue'), - meta: { - title: t('routes.demo.feat.contextMenu'), - }, - }, - { - path: 'download', - name: 'DownLoadDemo', - component: () => import('@/views/demo/feat/download/index.vue'), - meta: { - title: t('routes.demo.feat.download'), - }, - }, - { - path: 'click-out-side', - name: 'ClickOutSideDemo', - component: () => import('@/views/demo/feat/click-out-side/index.vue'), - meta: { - title: t('routes.demo.feat.clickOutSide'), - }, - }, - { - path: 'img-preview', - name: 'ImgPreview', - component: () => import('@/views/demo/feat/img-preview/index.vue'), - meta: { - title: t('routes.demo.feat.imgPreview'), - }, - }, - { - path: 'copy', - name: 'CopyDemo', - component: () => import('@/views/demo/feat/copy/index.vue'), - meta: { - title: t('routes.demo.feat.copy'), - }, - }, - { - path: 'ellipsis', - name: 'EllipsisDemo', - component: () => import('@/views/demo/feat/ellipsis/index.vue'), - meta: { - title: t('routes.demo.feat.ellipsis'), - }, - }, - { - path: 'msg', - name: 'MsgDemo', - component: () => import('@/views/demo/feat/msg/index.vue'), - meta: { - title: t('routes.demo.feat.msg'), - }, - }, - { - path: 'watermark', - name: 'WatermarkDemo', - component: () => import('@/views/demo/feat/watermark/index.vue'), - meta: { - title: t('routes.demo.feat.watermark'), - }, - }, - { - path: 'ripple', - name: 'RippleDemo', - component: () => import('@/views/demo/feat/ripple/index.vue'), - meta: { - title: t('routes.demo.feat.ripple'), - }, - }, - { - path: 'full-screen', - name: 'FullScreenDemo', - component: () => import('@/views/demo/feat/full-screen/index.vue'), - meta: { - title: t('routes.demo.feat.fullScreen'), - }, - }, - { - path: '/error-log', - name: 'ErrorLog', - component: () => import('@/views/sys/error-log/index.vue'), - meta: { - title: t('routes.demo.feat.errorLog'), - }, - }, - { - path: 'testTab/:id', - name: 'TestTab', - component: () => import('@/views/demo/feat/tab-params/index.vue'), - meta: { - title: t('routes.demo.feat.tab'), - carryParam: true, - hidePathForChildren: true, - }, - children: [ - { - path: 'testTab/id1', - name: 'TestTab1', - component: () => import('@/views/demo/feat/tab-params/index.vue'), - meta: { - title: t('routes.demo.feat.tab1'), - carryParam: true, - ignoreRoute: true, - }, - }, - { - path: 'testTab/id2', - name: 'TestTab2', - component: () => import('@/views/demo/feat/tab-params/index.vue'), - meta: { - title: t('routes.demo.feat.tab2'), - carryParam: true, - ignoreRoute: true, - }, - }, - ], - }, - { - path: 'testParam/:id', - name: 'TestParam', - component: getParentLayout('TestParam'), - meta: { - title: t('routes.demo.feat.menu'), - ignoreKeepAlive: true, - }, - children: [ - { - path: 'sub1', - name: 'TestParam_1', - component: () => import('@/views/demo/feat/menu-params/index.vue'), - meta: { - title: t('routes.demo.feat.menu1'), - ignoreKeepAlive: true, - }, - }, - { - path: 'sub2', - name: 'TestParam_2', - component: () => import('@/views/demo/feat/menu-params/index.vue'), - meta: { - title: t('routes.demo.feat.menu2'), - ignoreKeepAlive: true, - }, - }, - ], - }, - ], -} - -export default feat diff --git a/src/router/routes/modules/demo/iframe.ts b/src/router/routes/modules/demo/iframe.ts deleted file mode 100644 index 7b10f3978..000000000 --- a/src/router/routes/modules/demo/iframe.ts +++ /dev/null @@ -1,49 +0,0 @@ -import type { AppRouteModule } from '@/router/types' - -import { LAYOUT } from '@/router/constant' -import { t } from '@/hooks/web/useI18n' - -const IFrame = () => import('@/views/sys/iframe/FrameBlank.vue') - -const iframe: AppRouteModule = { - path: '/frame', - name: 'Frame', - component: LAYOUT, - redirect: '/frame/doc', - meta: { - orderNo: 1000, - icon: 'ion:tv-outline', - title: t('routes.demo.iframe.frame'), - }, - - children: [ - { - path: 'doc', - name: 'Doc', - component: IFrame, - meta: { - frameSrc: 'https://doc.vvbin.cn/', - title: t('routes.demo.iframe.doc'), - }, - }, - { - path: 'antv', - name: 'Antv', - component: IFrame, - meta: { - frameSrc: 'https://www.antdv.com/docs/vue/introduce-cn/', - title: t('routes.demo.iframe.antv'), - }, - }, - { - path: 'https://doc.vvbin.cn/', - name: 'DocExternal', - component: IFrame, - meta: { - title: t('routes.demo.iframe.docExternal'), - }, - }, - ], -} - -export default iframe diff --git a/src/router/routes/modules/demo/level.ts b/src/router/routes/modules/demo/level.ts deleted file mode 100644 index a92b07da5..000000000 --- a/src/router/routes/modules/demo/level.ts +++ /dev/null @@ -1,68 +0,0 @@ -import type { AppRouteModule } from '@/router/types' - -import { getParentLayout, LAYOUT } from '@/router/constant' -import { t } from '@/hooks/web/useI18n' - -const level: AppRouteModule = { - path: '/level', - name: 'Level', - component: LAYOUT, - redirect: '/level/menu1/menu1-1/menu1-1-1', - meta: { - orderNo: 2000, - icon: 'ion:menu-outline', - title: t('routes.demo.level.level'), - }, - - children: [ - { - path: 'menu1', - name: 'Menu1Demo', - component: getParentLayout('Menu1Demo'), - meta: { - title: 'Menu1', - }, - redirect: '/level/menu1/menu1-1/menu1-1-1', - children: [ - { - path: 'menu1-1', - name: 'Menu11Demo', - component: getParentLayout('Menu11Demo'), - meta: { - title: 'Menu1-1', - }, - redirect: '/level/menu1/menu1-1/menu1-1-1', - children: [ - { - path: 'menu1-1-1', - name: 'Menu111Demo', - component: () => import('@/views/demo/level/Menu111.vue'), - meta: { - title: 'Menu111', - }, - }, - ], - }, - { - path: 'menu1-2', - name: 'Menu12Demo', - component: () => import('@/views/demo/level/Menu12.vue'), - meta: { - title: 'Menu1-2', - }, - }, - ], - }, - { - path: 'menu2', - name: 'Menu2Demo', - component: () => import('@/views/demo/level/Menu2.vue'), - meta: { - title: 'Menu2', - // ignoreKeepAlive: true, - }, - }, - ], -} - -export default level diff --git a/src/router/routes/modules/demo/page.ts b/src/router/routes/modules/demo/page.ts deleted file mode 100644 index 602772c8c..000000000 --- a/src/router/routes/modules/demo/page.ts +++ /dev/null @@ -1,255 +0,0 @@ -import type { AppRouteModule } from '@/router/types' - -import { getParentLayout, LAYOUT } from '@/router/constant' -import { ExceptionEnum } from '@/enums/exceptionEnum' -import { t } from '@/hooks/web/useI18n' - -const ExceptionPage = () => import('@/views/sys/exception/Exception.vue') - -const page: AppRouteModule = { - path: '/page-demo', - name: 'PageDemo', - component: LAYOUT, - redirect: '/page-demo/form/basic', - meta: { - orderNo: 20, - icon: 'ion:aperture-outline', - title: t('routes.demo.page.page'), - }, - children: [ - // =============================form start============================= - { - path: 'form', - name: 'FormPage', - redirect: '/page-demo/form/basic', - component: getParentLayout('FormPage'), - meta: { - title: t('routes.demo.page.form'), - }, - children: [ - { - path: 'basic', - name: 'FormBasicPage', - component: () => import('@/views/demo/page/form/basic/index.vue'), - meta: { - title: t('routes.demo.page.formBasic'), - }, - }, - { - path: 'step', - name: 'FormStepPage', - component: () => import('@/views/demo/page/form/step/index.vue'), - meta: { - title: t('routes.demo.page.formStep'), - }, - }, - { - path: 'high', - name: 'FormHightPage', - component: () => import('@/views/demo/page/form/high/index.vue'), - meta: { - title: t('routes.demo.page.formHigh'), - }, - }, - ], - }, - // =============================form end============================= - // =============================desc start============================= - { - path: 'desc', - name: 'DescPage', - component: getParentLayout('DescPage'), - redirect: '/page-demo/desc/basic', - meta: { - title: t('routes.demo.page.desc'), - }, - children: [ - { - path: 'basic', - name: 'DescBasicPage', - component: () => import('@/views/demo/page/desc/basic/index.vue'), - meta: { - title: t('routes.demo.page.descBasic'), - }, - }, - { - path: 'high', - name: 'DescHighPage', - component: () => import('@/views/demo/page/desc/high/index.vue'), - meta: { - title: t('routes.demo.page.descHigh'), - }, - }, - ], - }, - // =============================desc end============================= - - // =============================result start============================= - { - path: 'result', - name: 'ResultPage', - redirect: '/page-demo/result/success', - component: getParentLayout('ResultPage'), - - meta: { - title: t('routes.demo.page.result'), - }, - children: [ - { - path: 'success', - name: 'ResultSuccessPage', - component: () => import('@/views/demo/page/result/success/index.vue'), - meta: { - title: t('routes.demo.page.resultSuccess'), - }, - }, - { - path: 'fail', - name: 'ResultFailPage', - component: () => import('@/views/demo/page/result/fail/index.vue'), - meta: { - title: t('routes.demo.page.resultFail'), - }, - }, - ], - }, - // =============================result end============================= - - // =============================account start============================= - { - path: 'account', - name: 'AccountPage', - component: getParentLayout('AccountPage'), - redirect: '/page-demo/account/setting', - meta: { - title: t('routes.demo.page.account'), - }, - children: [ - { - path: 'center', - name: 'AccountCenterPage', - component: () => import('@/views/demo/page/account/center/index.vue'), - meta: { - title: t('routes.demo.page.accountCenter'), - }, - }, - { - path: 'setting', - name: 'AccountSettingPage', - component: () => import('@/views/demo/page/account/setting/index.vue'), - meta: { - title: t('routes.demo.page.accountSetting'), - }, - }, - ], - }, - // =============================account end============================= - // =============================exception start============================= - { - path: 'exception', - name: 'ExceptionPage', - component: getParentLayout('ExceptionPage'), - redirect: '/page-demo/exception/404', - meta: { - title: t('routes.demo.page.exception'), - }, - children: [ - { - path: '403', - name: 'PageNotAccess', - component: ExceptionPage, - props: { - status: ExceptionEnum.PAGE_NOT_ACCESS, - }, - meta: { - title: '403', - }, - }, - { - path: '404', - name: 'PageNotFound', - component: ExceptionPage, - props: { - status: ExceptionEnum.PAGE_NOT_FOUND, - }, - meta: { - title: '404', - }, - }, - { - path: '500', - name: 'ServiceError', - component: ExceptionPage, - props: { - status: ExceptionEnum.ERROR, - }, - meta: { - title: '500', - }, - }, - { - path: 'net-work-error', - name: 'NetWorkError', - component: ExceptionPage, - props: { - status: ExceptionEnum.NET_WORK_ERROR, - }, - meta: { - title: t('routes.demo.page.netWorkError'), - }, - }, - { - path: 'not-data', - name: 'NotData', - component: ExceptionPage, - props: { - status: ExceptionEnum.PAGE_NOT_DATA, - }, - meta: { - title: t('routes.demo.page.notData'), - }, - }, - ], - }, - // =============================exception end============================= - // =============================list start============================= - { - path: 'list', - name: 'ListPage', - component: getParentLayout('ListPage'), - redirect: '/page-demo/list/card', - meta: { - title: t('routes.demo.page.list'), - }, - children: [ - { - path: 'basic', - name: 'ListBasicPage', - component: () => import('@/views/demo/page/list/basic/index.vue'), - meta: { - title: t('routes.demo.page.listBasic'), - }, - }, - { - path: 'card', - name: 'ListCardPage', - component: () => import('@/views/demo/page/list/card/index.vue'), - meta: { - title: t('routes.demo.page.listCard'), - }, - }, - { - path: 'search', - name: 'ListSearchPage', - component: () => import('@/views/demo/page/list/search/index.vue'), - meta: { - title: t('routes.demo.page.listSearch'), - }, - }, - ], - }, - // =============================list end============================= - ], -} - -export default page diff --git a/src/router/routes/modules/demo/permission.ts b/src/router/routes/modules/demo/permission.ts deleted file mode 100644 index 605b14503..000000000 --- a/src/router/routes/modules/demo/permission.ts +++ /dev/null @@ -1,92 +0,0 @@ -import type { AppRouteModule } from '@/router/types' - -import { getParentLayout, LAYOUT } from '@/router/constant' -import { RoleEnum } from '@/enums/roleEnum' -import { t } from '@/hooks/web/useI18n' - -const permission: AppRouteModule = { - path: '/permission', - name: 'Permission', - component: LAYOUT, - redirect: '/permission/front/page', - meta: { - orderNo: 15, - icon: 'ion:key-outline', - title: t('routes.demo.permission.permission'), - }, - - children: [ - { - path: 'front', - name: 'PermissionFrontDemo', - component: getParentLayout('PermissionFrontDemo'), - meta: { - title: t('routes.demo.permission.front'), - }, - children: [ - { - path: 'page', - name: 'FrontPageAuth', - component: () => import('@/views/demo/permission/front/index.vue'), - meta: { - title: t('routes.demo.permission.frontPage'), - }, - }, - { - path: 'btn', - name: 'FrontBtnAuth', - component: () => import('@/views/demo/permission/front/Btn.vue'), - meta: { - title: t('routes.demo.permission.frontBtn'), - }, - }, - { - path: 'auth-pageA', - name: 'FrontAuthPageA', - component: () => import('@/views/demo/permission/front/AuthPageA.vue'), - meta: { - title: t('routes.demo.permission.frontTestA'), - roles: [RoleEnum.SUPER], - }, - }, - { - path: 'auth-pageB', - name: 'FrontAuthPageB', - component: () => import('@/views/demo/permission/front/AuthPageB.vue'), - meta: { - title: t('routes.demo.permission.frontTestB'), - roles: [RoleEnum.TEST], - }, - }, - ], - }, - { - path: 'back', - name: 'PermissionBackDemo', - component: getParentLayout('PermissionBackDemo'), - meta: { - title: t('routes.demo.permission.back'), - }, - children: [ - { - path: 'page', - name: 'BackAuthPage', - component: () => import('@/views/demo/permission/back/index.vue'), - meta: { - title: t('routes.demo.permission.backPage'), - }, - }, - { - path: 'btn', - name: 'BackAuthBtn', - component: () => import('@/views/demo/permission/back/Btn.vue'), - meta: { - title: t('routes.demo.permission.backBtn'), - }, - }, - ], - }, - ], -} - -export default permission diff --git a/src/router/routes/modules/demo/steps.ts b/src/router/routes/modules/demo/steps.ts deleted file mode 100644 index 3f46f5737..000000000 --- a/src/router/routes/modules/demo/steps.ts +++ /dev/null @@ -1,31 +0,0 @@ -import type { AppRouteModule } from '@/router/types' - -import { LAYOUT } from '@/router/constant' -import { t } from '@/hooks/web/useI18n' - -const steps: AppRouteModule = { - path: '/steps', - name: 'StepsDemo', - component: LAYOUT, - redirect: '/steps/index', - meta: { - orderNo: 90000, - hideChildrenInMenu: true, - icon: 'whh:paintroll', - title: t('routes.demo.steps.page'), - }, - children: [ - { - path: 'index', - name: 'StepsDemoPage', - component: () => import('@/views/demo/steps/index.vue'), - meta: { - title: t('routes.demo.steps.page'), - icon: 'whh:paintroll', - hideMenu: true, - }, - }, - ], -} - -export default steps diff --git a/src/router/routes/modules/demo/system.ts b/src/router/routes/modules/demo/system.ts deleted file mode 100644 index e70555021..000000000 --- a/src/router/routes/modules/demo/system.ts +++ /dev/null @@ -1,87 +0,0 @@ -import type { AppRouteModule } from '@/router/types' - -import { LAYOUT } from '@/router/constant' -import { t } from '@/hooks/web/useI18n' - -const system: AppRouteModule = { - path: '/system', - name: 'System', - component: LAYOUT, - redirect: '/system/account', - meta: { - orderNo: 2000, - icon: 'ion:settings-outline', - title: t('routes.demo.system.moduleName'), - }, - children: [ - { - path: 'account', - name: 'AccountManagement', - meta: { - title: t('routes.demo.system.account'), - ignoreKeepAlive: false, - }, - component: () => import('@/views/demo/system/account/index.vue'), - }, - { - path: 'vxeTableAccount', - name: 'VxeTableAccountManagement', - meta: { - title: t('routes.demo.system.vxeTableAccount'), - ignoreKeepAlive: false, - }, - component: () => import('@/views/demo/system/vxe-account/index.vue'), - }, - { - path: 'account_detail/:id', - name: 'AccountDetail', - meta: { - hideMenu: true, - title: t('routes.demo.system.account_detail'), - ignoreKeepAlive: true, - showMenu: false, - currentActiveMenu: '/system/account', - }, - component: () => import('@/views/demo/system/account/AccountDetail.vue'), - }, - { - path: 'role', - name: 'RoleManagement', - meta: { - title: t('routes.demo.system.role'), - ignoreKeepAlive: true, - }, - component: () => import('@/views/demo/system/role/index.vue'), - }, - - { - path: 'menu', - name: 'MenuManagement', - meta: { - title: t('routes.demo.system.menu'), - ignoreKeepAlive: true, - }, - component: () => import('@/views/demo/system/menu/index.vue'), - }, - { - path: 'dept', - name: 'DeptManagement', - meta: { - title: t('routes.demo.system.dept'), - ignoreKeepAlive: true, - }, - component: () => import('@/views/demo/system/dept/index.vue'), - }, - { - path: 'changePassword', - name: 'ChangePassword', - meta: { - title: t('routes.demo.system.password'), - ignoreKeepAlive: true, - }, - component: () => import('@/views/demo/system/password/index.vue'), - }, - ], -} - -export default system diff --git a/src/router/routes/modules/hooks/request.ts b/src/router/routes/modules/hooks/request.ts deleted file mode 100644 index 077b52c64..000000000 --- a/src/router/routes/modules/hooks/request.ts +++ /dev/null @@ -1,79 +0,0 @@ -import type { AppRouteModule } from '@/router/types' - -import { LAYOUT } from '@/router/constant' - -const charts: AppRouteModule = { - path: '/useRequest', - name: 'useRequest', - component: LAYOUT, - redirect: '/useRequest/base', - meta: { - orderNo: 900, - icon: 'ant-design:api-outlined', - title: 'useRequest', - }, - children: [ - { - path: 'base', - name: 'useRequest-base', - meta: { title: '基础用法' }, - component: () => import('@/views/hooks/request/base'), - }, - { - path: 'loading-delay', - name: 'useRequest-loading-delay', - meta: { title: 'Loading Delay' }, - component: () => import('@/views/hooks/request/loading-delay'), - }, - { - path: 'polling', - name: 'useRequest-polling', - meta: { title: '轮询' }, - component: () => import('@/views/hooks/request/polling'), - }, - { - path: 'ready', - name: 'useRequest-ready', - meta: { title: 'Ready' }, - component: () => import('@/views/hooks/request/ready'), - }, - { - path: 'refresy-deps', - name: 'useRequest-refresy-deps', - meta: { title: '依赖刷新' }, - component: () => import('@/views/hooks/request/refresy-deps'), - }, - { - path: 'refresh-on-window-focus', - name: 'useRequest-refresh-on-window-focus', - meta: { title: '屏幕聚焦重新请求' }, - component: () => import('@/views/hooks/request/refresh-on-window-focus'), - }, - { - path: 'debounce', - name: 'useRequest-debounce', - meta: { title: '防抖' }, - component: () => import('@/views/hooks/request/debounce'), - }, - { - path: 'throttle', - name: 'useRequest-throttle', - meta: { title: '节流' }, - component: () => import('@/views/hooks/request/throttle'), - }, - { - path: 'cache', - name: 'useRequest-cache', - meta: { title: '缓存&SWR' }, - component: () => import('@/views/hooks/request/cache'), - }, - { - path: 'retry', - name: 'useRequest-retry', - meta: { title: '错误重试' }, - component: () => import('@/views/hooks/request/retry'), - }, - ], -} - -export default charts diff --git a/src/router/routes/project.ts b/src/router/routes/project.ts new file mode 100644 index 000000000..3291f8b16 --- /dev/null +++ b/src/router/routes/project.ts @@ -0,0 +1,51 @@ +import { AppRouteModule } from '@/router/types' +import { LAYOUT } from '@/router/constant' + +/** + * 位于主框架内的页面, 通常需要登录 + */ +export const INTERNAL: AppRouteModule = { + path: '/base/internal', + name: 'PROJECT_INTERNAL', + component: LAYOUT, + redirect: '', + meta: { + title: '项目基础路由', + }, + children: [ + // { + // path: '/account/setting', + // name: 'AccountSettingPage', + // component: () => import('/@/views/account/setting/index.vue'), + // meta: { title: '个人设置' }, + // }, + // { + // path: '/about/index', + // name: 'AboutPage', + // component: () => import('/@/views/sys/about/index.vue'), + // meta: { title: '关于' }, + // }, + ], +} + +/** + * 位于主框架外的页面 + */ +export const OUTSIDE: AppRouteModule = { + path: '/outside', + name: 'PROJECT_OUTSIDE', + meta: { title: '' }, + children: [ + // { + // path: '/cashier', + // name: 'cashier', + // component: () => import('/@/views/demo/cashier/Cashier.vue'), + // meta: { title: '收银台演示', ignoreAuth: true }, + // }, + ], +} + +/** + * 项目基础路由 + */ +export const PROJECT_BASE = [INTERNAL, OUTSIDE] diff --git a/src/router/types.ts b/src/router/types.ts index 18e32cb37..786999e3d 100644 --- a/src/router/types.ts +++ b/src/router/types.ts @@ -8,6 +8,9 @@ export type Component = ReturnType | (() => Pro export interface AppRouteRecordRaw extends Omit { name: string meta: RouteMeta + targetOutside?: boolean + redirect?: string + iframeUrl?: string component?: Component | string components?: Component children?: AppRouteRecordRaw[] @@ -48,7 +51,10 @@ export interface Menu { hideMenu?: boolean } -export type MenuModule = Menu +export type MenuModule = { + orderNo?: number + menu: Menu +} // export type AppRouteModule = RouteModule | AppRouteRecordRaw; export type AppRouteModule = AppRouteRecordRaw diff --git a/src/settings/designSetting.ts b/src/settings/designSetting.ts index f9b01b0f5..a285f4184 100644 --- a/src/settings/designSetting.ts +++ b/src/settings/designSetting.ts @@ -26,20 +26,6 @@ export const APP_PRESET_COLOR_LIST: string[] = [ '#ff9800', ] -// header preset color -export const HEADER_PRESET_BG_COLOR_LIST: string[] = [ - '#ffffff', - '#151515', - '#009688', - '#5172DC', - '#018ffb', - '#409eff', - '#e74c3c', - '#24292e', - '#394664', - '#001529', - '#383f45', -] // sider preset color export const SIDE_BAR_BG_COLOR_LIST: string[] = [ diff --git a/src/settings/projectSetting.ts b/src/settings/projectSetting.ts index d7369600b..013e3b155 100644 --- a/src/settings/projectSetting.ts +++ b/src/settings/projectSetting.ts @@ -9,98 +9,98 @@ import { SettingButtonPositionEnum, SessionTimeoutProcessingEnum, } from '@/enums/appEnum' -import { SIDE_BAR_BG_COLOR_LIST, HEADER_PRESET_BG_COLOR_LIST, APP_PRESET_COLOR_LIST } from './designSetting' +import { APP_PRESET_COLOR_LIST } from './designSetting' // ! You need to clear the browser cache after the change const setting: ProjectConfig = { - // Whether to show the configuration button + // 是否显示配置按钮 showSettingButton: true, - // Whether to show the theme switch button + // 是否显示主题切换按钮 showDarkModeToggle: true, - // `Settings` button position + // `Settings` 按钮位置 settingButtonPosition: SettingButtonPositionEnum.AUTO, - // Permission mode - permissionMode: PermissionModeEnum.ROUTE_MAPPING, + // 权限模式 + permissionMode: PermissionModeEnum.BACK, - // Permission-related cache is stored in sessionStorage or localStorage + // 权限相关缓存存储在sessionStorage或localStorage中 permissionCacheType: CacheTypeEnum.LOCAL, - // Session timeout processing + // 会话超时处理 sessionTimeoutProcessing: SessionTimeoutProcessingEnum.ROUTE_JUMP, - // color + // 颜色 themeColor: APP_PRESET_COLOR_LIST[0], - // Website gray mode, open for possible mourning dates + // 灰度迷失 grayMode: false, - // Color Weakness Mode + // 色弱模式 colorWeak: false, - // Whether to cancel the menu, the top, the multi-tab page display, for possible embedded in other systems + // 是否取消菜单,顶部,多选项卡页面显示,对于可能嵌入其他系统 fullContent: false, - // content mode + // 内容模式 contentMode: ContentEnum.FULL, - // Whether to display the logo + // 是否显示Logo showLogo: true, - // Whether to show footer + // 是否显示页脚 showFooter: false, - // Header configuration + // 页头设置 headerSetting: { - // header bg color - bgColor: HEADER_PRESET_BG_COLOR_LIST[0], - // Fixed at the top + // 背景颜色 + bgColor: '#ffffff', + // 固定在顶部 fixed: true, - // Whether to show top + // 是否显示 show: true, - // theme + // 主题 theme: ThemeEnum.LIGHT, - // Whether to enable the lock screen function + // 是否启用锁屏功能 useLockPage: true, - // Whether to show the full screen button + // 是否显示全屏按钮 showFullScreen: true, - // Whether to show the document button - showDoc: true, - // Whether to show the notification button - showNotice: true, - // Whether to display the menu search + // 是否显示文档按钮 + showDoc: false, + // 是否显示通知按钮 + showNotice: false, + // 是否显示搜索按钮 showSearch: true, - showApi: true, + // 显示API切换 + showApi: false, }, - // Menu configuration + // 菜单配置 menuSetting: { - // sidebar menu bg color - bgColor: SIDE_BAR_BG_COLOR_LIST[0], - // Whether to fix the left menu + // 背景颜色 + bgColor: '#28333E', + // 是否固定 fixed: true, // Menu collapse collapsed: false, - // When sider hide because of the responsive layout + // 当sider因为响应式布局而隐藏时 siderHidden: false, - // Whether to display the menu name when folding the menu + // 折叠菜单时是否显示菜单名称 collapsedShowTitle: false, - // Whether it can be dragged - // Only limited to the opening of the left menu, the mouse has a drag bar on the right side of the menu + // 是否可以拖动仅限于左侧菜单的打开,鼠标在菜单的右侧有一个拖动条 canDrag: false, - // Whether to show no dom + // Whether to show no dom 是否不显示dom show: true, - // Whether to show dom + // Whether to show dom 是否隐藏 hidden: false, - // Menu width + // Menu width 宽度 menuWidth: 210, - // Menu mode + // Menu mode 模式 mode: MenuModeEnum.INLINE, - // Menu type + // Menu 类型 type: MenuTypeEnum.SIDEBAR, - // Menu theme + // Menu 主题 theme: ThemeEnum.DARK, // Split menu split: false, @@ -118,12 +118,13 @@ const setting: ProjectConfig = { mixSideFixed: false, }, - // Multi-label + // 多标签配置 multiTabsSetting: { + // 缓存 自动还原原来已打开的标签 cache: false, // Turn on show: true, - // Is it possible to drag and drop sorting tabs + // 是否可以拖放排序标签 canDrag: true, // Turn on quick actions showQuick: true, @@ -131,7 +132,7 @@ const setting: ProjectConfig = { showRedo: true, // Whether to show the collapse button showFold: true, - // Auto collapsed + // 自动折叠 autoCollapse: false, }, @@ -165,19 +166,18 @@ const setting: ProjectConfig = { showBreadCrumbIcon: false, // Use error-handler-plugin - useErrorHandle: true, + useErrorHandle: false, - // Whether to open back to top + // 是否打开返回顶部 useOpenBackTop: true, - // Is it possible to embed iframe pages + // 是否可以嵌入 iframe 页面 canEmbedIFramePage: true, - // Whether to delete unclosed messages and notify when switching the interface - closeMessageOnSwitch: true, + // 切换接口时是否删除未关闭的消息并通知 + closeMessageOnSwitch: false, - // Whether to cancel the http request that has been sent but not responded when switching the interface. - // If it is enabled, I want to overwrite a single interface. Can be set in a separate interface + // 如果启用,我想覆盖单个接口。可以在单独的界面中设置 removeAllHttpPending: false, } diff --git a/src/store/action/userAction.ts b/src/store/action/userAction.ts new file mode 100644 index 000000000..adb332ed3 --- /dev/null +++ b/src/store/action/userAction.ts @@ -0,0 +1,39 @@ +import { closeWebSocket, initWebSocket } from '@/logics/websocket/UserGlobalWebSocker' +import { useUserStoreWithOut } from '@/store/modules/user' +// import { userPassWordCheck } from '@/views/security/remind/UserRemind' + +/** + * 用户登录后初始化等操作, 主要用在下列两种场景上 + * 1. 用户登陆后的操作 + * 2. 刷新页面时路由重新加载 + */ +export async function userLoginInitAction() { + const userStore = useUserStoreWithOut() + + // 刷新登陆后用户信息 + userStore.refreshUserInfoAction().then() + // 初始化 websocket连接. + initWebSocket().then() + // 检查密码情况 + // const check = await userPassWordCheck() + // if (!check) { + // return + // } + // 检查消息提醒 +} + +/** + * 用户后的操作 + */ +export function userLogoutAction() { + const userStore = useUserStoreWithOut() + // 关闭websocket + closeWebSocket() + + // 重置 Token和用户信息 需要放最后 + userStore.resetState() +} + +/** + * 监听后端推送的退出事件 + */ diff --git a/src/store/modules/permission.ts b/src/store/modules/permission.ts index e82819964..901a8d282 100644 --- a/src/store/modules/permission.ts +++ b/src/store/modules/permission.ts @@ -2,27 +2,21 @@ import type { AppRouteRecordRaw, Menu } from '@/router/types' import { defineStore } from 'pinia' import { store } from '@/store' -import { useI18n } from '@/hooks/web/useI18n' -import { useUserStore } from './user' -import { useAppStoreWithOut } from './app' -import { toRaw } from 'vue' import { transformObjToRoute, flatMultiLevelRoutes } from '@/router/helper/routeHelper' import { transformRouteToMenu } from '@/router/helper/menuHelper' -import projectSetting from '@/settings/projectSetting' - -import { PermissionModeEnum } from '@/enums/appEnum' - -import { asyncRoutes } from '@/router/routes' import { ERROR_LOG_ROUTE, PAGE_NOT_FOUND_ROUTE } from '@/router/routes/basic' import { filter } from '@/utils/helper/treeHelper' -import { getMenuList } from '@/api/sys/menu' -import { getPermCode } from '@/api/sys/user' +import { getPermissions } from '@/api/sys/menu' import { useMessage } from '@/hooks/web/useMessage' import { PageEnum } from '@/enums/pageEnum' +import Dashboard from '@/router/routes/modules/dashboard' +import { PROJECT_BASE } from '@/router/routes/project' +import { PermMenu } from '@/api/sys/model/menuModel' +import { getAppEnvConfig } from '@/utils/env' interface PermissionState { // Permission code list @@ -60,20 +54,20 @@ export const usePermissionStore = defineStore({ frontMenuList: [], }), getters: { - getPermCodeList(state): string[] | number[] { - return state.permCodeList + getPermCodeList(): string[] | number[] { + return this.permCodeList }, - getBackMenuList(state): Menu[] { - return state.backMenuList + getBackMenuList(): Menu[] { + return this.backMenuList }, - getFrontMenuList(state): Menu[] { - return state.frontMenuList + getFrontMenuList(): Menu[] { + return this.frontMenuList }, - getLastBuildMenuTime(state): number { - return state.lastBuildMenuTime + getLastBuildMenuTime(): number { + return this.lastBuildMenuTime }, - getIsDynamicAddedRoute(state): boolean { - return state.isDynamicAddedRoute + getIsDynamicAddedRoute(): boolean { + return this.isDynamicAddedRoute }, }, actions: { @@ -103,31 +97,51 @@ export const usePermissionStore = defineStore({ this.backMenuList = [] this.lastBuildMenuTime = 0 }, - async changePermissionCode() { - const codeList = await getPermCode() - this.setPermCodeList(codeList) + /** + * 权限码和菜单更新, 更新权限码并返回菜单信息 + */ + async changeMenuAndPermCode(): Promise { + const { VITE_GLOB_APP_CLIENT } = getAppEnvConfig() + const { + data: { menus, resourcePerms }, + } = await getPermissions(VITE_GLOB_APP_CLIENT as string) + this.setPermCodeList(resourcePerms) + return menus }, - // 构建路由 + /** + * 转换路由为系统中的菜单 + */ + convertMenus(permMenus: PermMenu[]): AppRouteRecordRaw[] { + return ( + permMenus?.map((o) => { + return { + name: o.name, + path: o.path, + component: o.component, + targetOutside: o.targetOutside, + iframeUrl: o.iframeUrl, + redirect: o.redirect, + meta: { + orderNo: o.sortNo, + title: o.title, + icon: o.icon, + hideMenu: o.hidden, + hideChildrenInMenu: o.hideChildrenInMenu, + ignoreKeepAlive: !o.keepAlive, + }, + children: this.convertMenus(o.children), + } as AppRouteRecordRaw + }) || [] + ) + }, + + /** + * 构建路由 后端控制 + */ async buildRoutesAction(): Promise { - const { t } = useI18n() - const userStore = useUserStore() - const appStore = useAppStoreWithOut() - + // 路由 let routes: AppRouteRecordRaw[] = [] - const roleList = toRaw(userStore.getRoleList) || [] - const { permissionMode = projectSetting.permissionMode } = appStore.getProjectConfig - - // 路由过滤器 在 函数filter 作为回调传入遍历使用 - const routeFilter = (route: AppRouteRecordRaw) => { - const { meta } = route - // 抽出角色 - const { roles } = meta || {} - if (!roles) return true - // 进行角色权限判断 - return roleList.some((role) => roles.includes(role)) - } - const routeRemoveIgnoreFilter = (route: AppRouteRecordRaw) => { const { meta } = route // ignoreRoute 为true 则路由仅用于菜单生成,不会在实际的路由表中出现 @@ -141,7 +155,8 @@ export const usePermissionStore = defineStore({ * */ const patchHomeAffix = (routes: AppRouteRecordRaw[]) => { if (!routes || routes.length === 0) return - let homePath: string = userStore.getUserInfo.homePath || PageEnum.BASE_HOME + // 主页路径 + let homePath: string = PageEnum.BASE_HOME function patcher(routes: AppRouteRecordRaw[], parentPath = '') { if (parentPath) parentPath = parentPath + '/' @@ -168,85 +183,42 @@ export const usePermissionStore = defineStore({ return } - switch (permissionMode) { - // 角色权限 - case PermissionModeEnum.ROLE: - // 对非一级路由进行过滤 - routes = filter(asyncRoutes, routeFilter) - // 对一级路由根据角色权限过滤 - routes = routes.filter(routeFilter) - // Convert multi-level routing to level 2 routing - // 将多级路由转换为 2 级路由 - routes = flatMultiLevelRoutes(routes) - break + const { createMessage } = useMessage() - // 路由映射, 默认进入该case - case PermissionModeEnum.ROUTE_MAPPING: - // 对非一级路由进行过滤 - routes = filter(asyncRoutes, routeFilter) - // 对一级路由再次根据角色权限过滤 - routes = routes.filter(routeFilter) - // 将路由转换成菜单 - const menuList = transformRouteToMenu(routes, true) - // 移除掉 ignoreRoute: true 的路由 非一级路由 - routes = filter(routes, routeRemoveIgnoreFilter) - // 移除掉 ignoreRoute: true 的路由 一级路由; - routes = routes.filter(routeRemoveIgnoreFilter) - // 对菜单进行排序 - menuList.sort((a, b) => { - return (a.meta?.orderNo || 0) - (b.meta?.orderNo || 0) - }) + createMessage.loading({ + content: '菜单加载中...', + duration: 1, + }) - // 设置菜单列表 - this.setFrontMenuList(menuList) + let routeList: AppRouteRecordRaw[] = [] - // Convert multi-level routing to level 2 routing - // 将多级路由转换为 2 级路由 - routes = flatMultiLevelRoutes(routes) - break + // 获取后台的菜单和更新权限码 + try { + const permMenus = await this.changeMenuAndPermCode() + // 将 后端获取的菜单转换为系统中的菜单格式 + routeList = this.convertMenus(permMenus) + } catch (error) { + console.error(error) + } + // 后端获取的菜单如果为空, 不进行处理 + if (routeList) { + routeList = transformObjToRoute(routeList) + // 后台路由到菜单结构 + const backMenuList = transformRouteToMenu(routeList) + this.setBackMenuList(backMenuList) + // 删除 meta.ignoreRoute 项 + routeList = filter(routeList, routeRemoveIgnoreFilter) + routeList = routeList.filter(routeRemoveIgnoreFilter) - // If you are sure that you do not need to do background dynamic permissions, please comment the entire judgment below - // 如果确定不需要做后台动态权限,请在下方注释整个判断 - case PermissionModeEnum.BACK: - const { createMessage } = useMessage() - - createMessage.loading({ - content: t('sys.app.menuLoading'), - duration: 1, - }) - - // !Simulate to obtain permission codes from the background, - // 模拟从后台获取权限码, - // this function may only need to be executed once, and the actual project can be put at the right time by itself - // 这个功能可能只需要执行一次,实际项目可以自己放在合适的时间 - let routeList: AppRouteRecordRaw[] = [] - try { - await this.changePermissionCode() - routeList = (await getMenuList()) as AppRouteRecordRaw[] - } catch (error) { - console.error(error) - } - - // Dynamically introduce components - // 动态引入组件 - routeList = transformObjToRoute(routeList) - - // Background routing to menu structure - // 后台路由到菜单结构 - const backMenuList = transformRouteToMenu(routeList) - this.setBackMenuList(backMenuList) - - // remove meta.ignoreRoute item - // 删除 meta.ignoreRoute 项 - routeList = filter(routeList, routeRemoveIgnoreFilter) - routeList = routeList.filter(routeRemoveIgnoreFilter) - - routeList = flatMultiLevelRoutes(routeList) - routes = [PAGE_NOT_FOUND_ROUTE, ...routeList] - break + routeList = flatMultiLevelRoutes(routeList) } + routes = [PAGE_NOT_FOUND_ROUTE, ...routeList] + + // 添加更多配置的路由菜单 routes.push(ERROR_LOG_ROUTE) + routes.push(Dashboard) + routes.push(...PROJECT_BASE) patchHomeAffix(routes) return routes }, diff --git a/src/store/modules/user.ts b/src/store/modules/user.ts index e877dc399..38276b489 100644 --- a/src/store/modules/user.ts +++ b/src/store/modules/user.ts @@ -1,184 +1,118 @@ import type { UserInfo } from '#/store' -import type { ErrorMessageMode } from '#/axios' import { defineStore } from 'pinia' import { store } from '@/store' -import { RoleEnum } from '@/enums/roleEnum' +import { clearAuthCache, getAuthCache, setAuthCache } from '@/utils/auth' import { PageEnum } from '@/enums/pageEnum' -import { ROLES_KEY, TOKEN_KEY, USER_INFO_KEY } from '@/enums/cacheEnum' -import { getAuthCache, setAuthCache } from '@/utils/auth' -import { GetUserInfoModel, LoginParams } from '@/api/sys/model/userModel' -import { doLogout, getUserInfo, loginApi } from '@/api/sys/user' -import { useI18n } from '@/hooks/web/useI18n' +import { LoginParams } from '@/api/sys/model/userModel' +import { doLogout, login } from '@/api/sys/login' import { useMessage } from '@/hooks/web/useMessage' import { router } from '@/router' -import { usePermissionStore } from '@/store/modules/permission' -import { RouteRecordRaw } from 'vue-router' -import { PAGE_NOT_FOUND_ROUTE } from '@/router/routes/basic' -import { isArray } from '@/utils/is' import { h } from 'vue' +import { getFilePreviewUrlPrefix } from '@/api/common/FileUpload' +import { getUserInfo } from '@/api/sys/user' +import { userLogoutAction } from '@/store/action/userAction' +import { TOKEN_KEY, USER_INFO_KEY } from '@/enums/cacheEnum' interface UserState { userInfo: Nullable token?: string - roleList: RoleEnum[] - sessionTimeout?: boolean - lastUpdateTime: number } export const useUserStore = defineStore({ id: 'app-user', state: (): UserState => ({ - // user info + // 用户信息 userInfo: null, // token token: undefined, - // roleList - roleList: [], - // Whether the login expired - sessionTimeout: false, - // Last fetch time - lastUpdateTime: 0, }), getters: { - getUserInfo(state): UserInfo { - return state.userInfo || getAuthCache(USER_INFO_KEY) || {} + getUserInfo(): UserInfo { + return this.userInfo || getAuthCache(USER_INFO_KEY) || {} }, - getToken(state): string { - return state.token || getAuthCache(TOKEN_KEY) - }, - getRoleList(state): RoleEnum[] { - return state.roleList.length > 0 ? state.roleList : getAuthCache(ROLES_KEY) - }, - getSessionTimeout(state): boolean { - return !!state.sessionTimeout - }, - getLastUpdateTime(state): number { - return state.lastUpdateTime + getToken(): string { + return this.token || getAuthCache(TOKEN_KEY) }, }, actions: { + /** + * 设置token + */ setToken(info: string | undefined) { - this.token = info ? info : '' // for null or undefined value + this.token = info ? info : '' setAuthCache(TOKEN_KEY, info) }, - setRoleList(roleList: RoleEnum[]) { - this.roleList = roleList - setAuthCache(ROLES_KEY, roleList) - }, + /** + * 保存用户信息, 不要直接使用 + * 使用 UserStoreUtil 中的包装方法来处理 + */ setUserInfo(info: UserInfo | null) { this.userInfo = info - this.lastUpdateTime = new Date().getTime() setAuthCache(USER_INFO_KEY, info) }, - setSessionTimeout(flag: boolean) { - this.sessionTimeout = flag - }, + /** + * 重置 Token和用户状态 + */ resetState() { this.userInfo = null this.token = '' - this.roleList = [] - this.sessionTimeout = false + clearAuthCache() }, /** - * @description: login + * 登录方法 */ - async login( - params: LoginParams & { - goHome?: boolean - mode?: ErrorMessageMode - }, - ): Promise { + async login(params: LoginParams) { try { - const { goHome = true, mode, ...loginParams } = params - const data = await loginApi(loginParams, mode) - const { token } = data - - // save token + const to = router.currentRoute.value + const { data: token } = await login(params) + // 保存token this.setToken(token) - return this.afterLoginAction(goHome) + // 跳转路由 + await router.replace((to.query?.redirect as string) || '/') + return token } catch (error) { - return Promise.reject(error) + console.error(error) } }, - async afterLoginAction(goHome?: boolean): Promise { - if (!this.getToken) return null - // get user info - const userInfo = await this.getUserInfoAction() - - const sessionTimeout = this.sessionTimeout - if (sessionTimeout) { - this.setSessionTimeout(false) - } else { - const permissionStore = usePermissionStore() - - // 动态路由加载(首次) - if (!permissionStore.isDynamicAddedRoute) { - const routes = await permissionStore.buildRoutesAction() - ;[...routes, PAGE_NOT_FOUND_ROUTE].forEach((route) => { - router.addRoute(route as unknown as RouteRecordRaw) - }) - // 记录动态路由加载完成 - permissionStore.setDynamicAddedRoute(true) - } - - goHome && (await router.replace(userInfo?.homePath || PageEnum.BASE_HOME)) - } - return userInfo - }, - async getUserInfoAction(): Promise { - if (!this.getToken) return null - const userInfo = await getUserInfo() - const { roles = [] } = userInfo - if (isArray(roles)) { - const roleList = roles.map((item) => item.value) as RoleEnum[] - this.setRoleList(roleList) - } else { - userInfo.roles = [] - this.setRoleList([]) - } - this.setUserInfo(userInfo) - return userInfo - }, /** - * @description: logout + * 刷新登陆后用户信息 + */ + async refreshUserInfoAction() { + if (!this.getToken) return null + const { data: userInfo } = await getUserInfo() + // 设置头像 + const { data: urlPrefix } = await getFilePreviewUrlPrefix() + userInfo.avatar = userInfo.avatar ? urlPrefix + userInfo.avatar : '' + this.setUserInfo(userInfo as any) + }, + /** + * 退出操作 */ async logout(goLogin = false) { if (this.getToken) { try { + // 服务端退出 await doLogout() } catch { - console.log('注销Token失败') + console.warn('注销Token失败') } } - this.setToken(undefined) - this.setSessionTimeout(false) - this.setUserInfo(null) - if (goLogin) { - // 直接回登陆页 - router.replace(PageEnum.BASE_LOGIN) - } else { - // 回登陆页带上当前路由地址 - router.replace({ - path: PageEnum.BASE_LOGIN, - query: { - redirect: encodeURIComponent(router.currentRoute.value.fullPath), - }, - }) - } + // 重置状态 + userLogoutAction() + // 跳转到登录页 + goLogin && (await router.push(PageEnum.BASE_LOGIN)) }, /** - * @description: Confirm before logging out + * 是否进行退出弹窗 */ confirmLoginOut() { const { createConfirm } = useMessage() - const { t } = useI18n() createConfirm({ iconType: 'warning', - title: () => h('span', t('sys.app.logoutTip')), - content: () => h('span', t('sys.app.logoutMessage')), + title: () => h('span', '温馨提醒'), + content: () => h('span', '是否确认退出系统?'), onOk: async () => { - // 主动登出,不带redirect地址 await this.logout(true) }, }) @@ -186,7 +120,7 @@ export const useUserStore = defineStore({ }, }) -// Need to be used outside the setup +// setup 之外使用 export function useUserStoreWithOut() { return useUserStore(store) } diff --git a/src/utils/env.ts b/src/utils/env.ts index 0dcf345b5..15abb3330 100644 --- a/src/utils/env.ts +++ b/src/utils/env.ts @@ -30,7 +30,8 @@ export function getAppEnvConfig() { ? // Get the global configuration (the configuration will be extracted independently when packaging) (import.meta.env as unknown as GlobEnvConfig) : (window[ENV_NAME] as unknown as GlobEnvConfig) - const { VITE_GLOB_APP_TITLE, VITE_GLOB_API_URL_PREFIX, VITE_GLOB_UPLOAD_URL } = ENV + + const { VITE_GLOB_APP_TITLE, VITE_GLOB_API_URL_PREFIX, VITE_GLOB_APP_CLIENT, VITE_GLOB_API_TIMEOUT } = ENV let { VITE_GLOB_API_URL } = ENV if (localStorage.getItem(API_ADDRESS)) { const address = JSON.parse(localStorage.getItem(API_ADDRESS) || '{}') @@ -40,7 +41,8 @@ export function getAppEnvConfig() { VITE_GLOB_APP_TITLE, VITE_GLOB_API_URL, VITE_GLOB_API_URL_PREFIX, - VITE_GLOB_UPLOAD_URL, + VITE_GLOB_API_TIMEOUT, + VITE_GLOB_APP_CLIENT, } } diff --git a/src/utils/http/axios/index.ts b/src/utils/http/axios/index.ts index 6fa58e434..e9e29af6b 100644 --- a/src/utils/http/axios/index.ts +++ b/src/utils/http/axios/index.ts @@ -10,97 +10,88 @@ import { checkStatus } from './checkStatus' import { useGlobSetting } from '@/hooks/setting' import { useMessage } from '@/hooks/web/useMessage' import { RequestEnum, ResultEnum, ContentTypeEnum } from '@/enums/httpEnum' -import { isString, isUndefined, isNull, isEmpty } from '@/utils/is' -import { getToken } from '@/utils/auth' +import { isString } from '@/utils/is' import { setObjToUrlParams, deepMerge } from '@/utils' import { useErrorLogStoreWithOut } from '@/store/modules/errorLog' -import { useI18n } from '@/hooks/web/useI18n' import { joinTimestamp, formatRequestDate } from './helper' import { useUserStoreWithOut } from '@/store/modules/user' import { AxiosRetry } from '@/utils/http/axios/axiosRetry' -import axios from 'axios' +import { getAppEnvConfig } from '@/utils/env' + +/** + * axios配置 可自行根据项目进行更改,只需更改该文件即可,其他文件可以不动 + */ const globSetting = useGlobSetting() const urlPrefix = globSetting.urlPrefix -const { createMessage, createErrorModal, createSuccessModal } = useMessage() +const { createMessage, createErrorModal } = useMessage() /** - * @description: 数据处理,方便区分多种处理方式 + * 数据处理,方便区分多种处理方式 */ const transform: AxiosTransform = { /** - * @description: 处理响应数据。如果数据不是预期格式,可直接抛出错误 + * 处理响应数据。如果数据不是预期格式,可直接抛出错误 */ transformResponseHook: (res: AxiosResponse, options: RequestOptions) => { - const { t } = useI18n() - const { isTransformResponse, isReturnNativeResponse } = options - // 是否返回原生响应头 比如:需要获取响应头时使用该属性 - if (isReturnNativeResponse) { + // 错误的时候返回 + const contentType = res.headers['content-type'] + const rawData = res.data + // 获取请求头的数据 + if (!rawData) { + throw new Error('请求出错,请稍候重试') + } + // 下载流处理, 直接原样返回 + if (contentType === 'application/octet-stream') { return res } - // 不进行任何处理,直接返回 - // 用于页面代码可能需要直接获取code,data,message这些信息时开启 - if (!isTransformResponse) { - return res.data - } - // 错误的时候返回 - const { data } = res - if (!data) { - // return '[HTTP] Request has no return value'; - throw new Error(t('sys.api.apiRequestFailed')) + // 接收的通常是json的数据,这里 code,data,message为 后台统一的字段,需要在 types.ts内修改为项目自己的接口返回格式 + const { code, msg, traceId } = rawData + + // 如果返回值中连code都没有, 说明返回的不是结构体, 不继续向下进行处理 + if (code === undefined) { + return } - // 这里 code,result,message为 后台统一的字段,需要在 types.ts内修改为项目自己的接口返回格式 - const { code, result, message } = data // 这里逻辑可以根据项目进行修改 - const hasSuccess = data && Reflect.has(data, 'code') && code === ResultEnum.SUCCESS + const hasSuccess = rawData && Reflect.has(rawData, 'code') && code === ResultEnum.SUCCESS if (hasSuccess) { - let successMsg = message - - if (isNull(successMsg) || isUndefined(successMsg) || isEmpty(successMsg)) { - successMsg = t(`sys.api.operationSuccess`) - } - - if (options.successMessageMode === 'modal') { - createSuccessModal({ title: t('sys.api.successTip'), content: successMsg }) - } else if (options.successMessageMode === 'message') { - createMessage.success(successMsg) - } - return result + return rawData } - // 在此处根据自己项目的实际情况对不同的code执行不同的操作 - // 如果不希望中断当前请求,请return数据,否则直接抛出异常即可 + // 在此处根据自己项目的实际情况对不同的code执行不同的操作, 如果不希望中断当前请求,请return数据,否则直接抛出异常即可 let timeoutMsg = '' + const userStore = useUserStoreWithOut() switch (code) { case ResultEnum.TIMEOUT: - timeoutMsg = t('sys.api.timeoutMessage') - const userStore = useUserStoreWithOut() - // 被动登出,带redirect地址 - userStore.logout(false) + case ResultEnum.NOT_LOGIN: + timeoutMsg = '登录超时,请重新登录!' + userStore.setToken(undefined) + userStore.logout(true).then() break default: - if (message) { - timeoutMsg = message + if (msg) { + timeoutMsg = msg } } - // errorMessageMode='modal'的时候会显示modal错误弹窗,而不是消息提示,用于一些比较重要的错误 + // errorMessageMode=‘modal’的时候会显示modal错误弹窗,而不是消息提示,用于一些比较重要的错误 // errorMessageMode='none' 一般是调用时明确表示不希望自动弹出错误提示 if (options.errorMessageMode === 'modal') { - createErrorModal({ title: t('sys.api.errorTip'), content: timeoutMsg }) + createErrorModal({ title: '错误提示', content: timeoutMsg || '请求出错,请稍候重试' }) } else if (options.errorMessageMode === 'message') { - createMessage.error(timeoutMsg) + createMessage.error(timeoutMsg || '请求出错,请稍候重试') } - - throw new Error(timeoutMsg || t('sys.api.apiRequestFailed')) + console.error('TraceId:', traceId) + throw new Error(timeoutMsg || '请求出错,请稍候重试') }, - // 请求之前处理config + /** + * 请求之前处理config + */ beforeRequestHook: (config, options) => { const { apiUrl, joinPrefix, joinParamsToUrl, formatDate, joinTime = true, urlPrefix } = options - if (joinPrefix) { config.url = `${urlPrefix}${config.url}` } @@ -108,6 +99,7 @@ const transform: AxiosTransform = { if (apiUrl && isString(apiUrl)) { config.url = `${apiUrl}${config.url}` } + // 请求参数和请求体转换 const params = config.params || {} const data = config.data || false formatDate && data && !isString(data) && formatRequestDate(data) @@ -126,10 +118,6 @@ const transform: AxiosTransform = { if (Reflect.has(config, 'data') && config.data && (Object.keys(config.data).length > 0 || config.data instanceof FormData)) { config.data = data config.params = params - } else { - // 非GET请求如果没有提供data,则将params视为data - config.data = params - config.params = undefined } if (joinParamsToUrl) { config.url = setObjToUrlParams(config.url as string, Object.assign({}, config.params, config.data)) @@ -144,30 +132,30 @@ const transform: AxiosTransform = { }, /** - * @description: 请求拦截器处理 + * 请求拦截器处理 */ requestInterceptors: (config, options) => { // 请求之前处理config - const token = getToken() + const userStore = useUserStoreWithOut() + const token = userStore.getToken if (token && (config as Recordable)?.requestOptions?.withToken !== false) { - // jwt token - ;(config as Recordable).headers.Authorization = options.authenticationScheme ? `${options.authenticationScheme} ${token}` : token + // 添加 token 到请求头 + ;(config as Recordable).headers.AccessToken = token } return config }, /** - * @description: 响应拦截器处理 + * 响应拦截器处理 */ responseInterceptors: (res: AxiosResponse) => { return res }, /** - * @description: 响应错误处理 + * 响应错误处理 */ responseInterceptorsCatch: (axiosInstance: AxiosInstance, error: any) => { - const { t } = useI18n() const errorLogStore = useErrorLogStoreWithOut() errorLogStore.addAjaxErrorInfo(error) const { response, code, message, config } = error || {} @@ -176,21 +164,17 @@ const transform: AxiosTransform = { const err: string = error?.toString?.() ?? '' let errMessage = '' - if (axios.isCancel(error)) { - return Promise.reject(error) - } - try { if (code === 'ECONNABORTED' && message.indexOf('timeout') !== -1) { - errMessage = t('sys.api.apiTimeoutMessage') + errMessage = '接口请求超时,请刷新页面重试!' } if (err?.includes('Network Error')) { - errMessage = t('sys.api.networkExceptionMsg') + errMessage = '网络异常,请检查您的网络连接是否正常!' } if (errMessage) { if (errorMessageMode === 'modal') { - createErrorModal({ title: t('sys.api.errorTip'), content: errMessage }) + createErrorModal({ title: '错误提示', content: errMessage }) } else if (errorMessageMode === 'message') { createMessage.error(errMessage) } @@ -205,16 +189,16 @@ const transform: AxiosTransform = { // 添加自动重试机制 保险起见 只针对GET请求 const retryRequest = new AxiosRetry() const { isOpenRetry } = config.requestOptions.retryRequest - config.method?.toUpperCase() === RequestEnum.GET && - isOpenRetry && - error?.response?.status !== 401 && - // @ts-ignore - retryRequest.retry(axiosInstance, error) - return Promise.reject(error) + config.method?.toUpperCase() === RequestEnum.GET && isOpenRetry && retryRequest.retry(axiosInstance, error) }, } +/** + * 创建请求用 Axios 对象 + * @param opt + */ function createAxios(opt?: Partial) { + const { VITE_GLOB_API_TIMEOUT } = getAppEnvConfig() return new VAxios( // 深度合并 deepMerge( @@ -223,7 +207,7 @@ function createAxios(opt?: Partial) { // authentication schemes,e.g: Bearer // authenticationScheme: 'Bearer', authenticationScheme: '', - timeout: 10 * 1000, + timeout: VITE_GLOB_API_TIMEOUT, // 基础接口地址 // baseURL: globSetting.apiUrl, @@ -236,10 +220,6 @@ function createAxios(opt?: Partial) { requestOptions: { // 默认将prefix 添加到url joinPrefix: true, - // 是否返回原生响应头 比如:需要获取响应头时使用该属性 - isReturnNativeResponse: false, - // 需要对返回数据进行处理 - isTransformResponse: true, // post请求的时候添加参数到url joinParamsToUrl: false, // 格式化提交参数时间 @@ -257,7 +237,7 @@ function createAxios(opt?: Partial) { // 是否携带token withToken: true, retryRequest: { - isOpenRetry: true, + isOpenRetry: false, count: 5, waitTime: 100, }, @@ -268,11 +248,3 @@ function createAxios(opt?: Partial) { ) } export const defHttp = createAxios() - -// other api url -// export const otherHttp = createAxios({ -// requestOptions: { -// apiUrl: 'xxx', -// urlPrefix: 'xxx', -// }, -// }); diff --git a/src/utils/is.ts b/src/utils/is.ts index cab21548b..24843bc04 100644 --- a/src/utils/is.ts +++ b/src/utils/is.ts @@ -1,3 +1,5 @@ +import { router } from '@/router' + export { isArguments, isArrayBuffer, @@ -70,3 +72,28 @@ export function isPascalCase(str: string): boolean { const regex = /^[A-Z][A-Za-z]*$/ return regex.test(str) } + +/** + * 是否是网址 + * @param path + */ +export function isUrl(path: string): boolean { + return isHttpUrl(path) +} + +/** + * 是否从外部打开的链接 + * @return 打开的地址, 为空字符则说明无法打开 + */ +export function isOutsideUrl(path: string): string { + if (isUrl(path)) { + return path + } + if (path.startsWith('outside://')) { + // 转换成项目内路由地址 + const routerPath = path.substring(10) + const to = router.resolve(routerPath) + return to.href + } + return '' +} diff --git a/src/views/demo/charts/Line.vue b/src/views/demo/charts/Line.vue deleted file mode 100644 index 4a88c2a24..000000000 --- a/src/views/demo/charts/Line.vue +++ /dev/null @@ -1,113 +0,0 @@ - - diff --git a/src/views/demo/charts/Map.vue b/src/views/demo/charts/Map.vue deleted file mode 100644 index d19e2c7c2..000000000 --- a/src/views/demo/charts/Map.vue +++ /dev/null @@ -1,70 +0,0 @@ - - diff --git a/src/views/demo/charts/Pie.vue b/src/views/demo/charts/Pie.vue deleted file mode 100644 index 9a5ddd85d..000000000 --- a/src/views/demo/charts/Pie.vue +++ /dev/null @@ -1,130 +0,0 @@ - - diff --git a/src/views/demo/charts/SaleRadar.vue b/src/views/demo/charts/SaleRadar.vue deleted file mode 100644 index 74afae671..000000000 --- a/src/views/demo/charts/SaleRadar.vue +++ /dev/null @@ -1,95 +0,0 @@ - - diff --git a/src/views/demo/charts/china.json b/src/views/demo/charts/china.json deleted file mode 100644 index bbc0a8322..000000000 --- a/src/views/demo/charts/china.json +++ /dev/null @@ -1,856 +0,0 @@ -{ - "type": "FeatureCollection", - "features": [ - { - "type": "Feature", - "id": "710000", - "properties": { - "id": "710000", - "cp": [121.509062, 24.044332], - "name": "台湾", - "childNum": 6 - }, - "geometry": { - "type": "MultiPolygon", - "coordinates": [ - ["@@°Ü¯Û"], - [ - "@@ƛĴÕƊÉɼģºðʀ\\ƎsÆNŌÔĚäœnÜƤɊĂǀĆĴžĤNJŨxĚĮǂƺòƌ‚–âÔ®ĮXŦţƸZûЋƕƑGđ¨ĭMó·ęcëƝɉlÝƯֹÅŃ^Ó·śŃNjƏďíåɛGɉ™¿@ăƑŽ¥ĘWǬÏĶŁâ" - ], - ["@@\\p|WoYG¿¥I†j@¢"], - ["@@…¡‰@ˆV^RqˆBbAŒnTXeRz¤Lž«³I"], - ["@@ÆEE—„kWqë @œ"], - ["@@fced"], - ["@@„¯ɜÄèaì¯ØǓIġĽ"], - ["@@çûĖ롖hòř "] - ], - "encodeOffsets": [ - [[122886, 24033]], - [[123335, 22980]], - [[122375, 24193]], - [[122518, 24117]], - [[124427, 22618]], - [[124862, 26043]], - [[126259, 26318]], - [[127671, 26683]] - ] - } - }, - { - "type": "Feature", - "id": "130000", - "properties": { - "id": "130000", - "cp": [114.502461, 38.045474], - "name": "河北", - "childNum": 3 - }, - "geometry": { - "type": "MultiPolygon", - "coordinates": [ - ["@@o~†Z]‚ªr‰ºc_ħ²G¼s`jΟnüsœłNX_“M`ǽÓnUK…Ĝēs¤­©yrý§uģŒc†JŠ›e"], - ["@@U`Ts¿m‚"], - [ - "@@oºƋÄd–eVŽDJj£€J|Ådz•Ft~žKŨ¸IÆv|”‡¢r}膎onb˜}`RÎÄn°ÒdÞ²„^®’lnÐèĄlðӜ×]ªÆ}LiĂ±Ö`^°Ç¶p®đDcœŋ`–ZÔ’¶êqvFƚ†N®ĆTH®¦O’¾ŠIbÐã´BĐɢŴÆíȦp–ĐÞXR€·nndOž¤’OÀĈƒ­Qg˜µFo|gȒęSWb©osx|hYh•gŃfmÖĩnº€T̒Sp›¢dYĤ¶UĈjl’ǐpäìë|³kÛfw²Xjz~ÂqbTŠÑ„ěŨ@|oM‡’zv¢ZrÃVw¬ŧˏfŒ°ÐT€ªqŽs{Sž¯r æÝlNd®²Ğ džiGʂJ™¼lr}~K¨ŸƐÌWö€™ÆŠzRš¤lêmĞL΄’@¡|q]SvK€ÑcwpÏρ†ĿćènĪWlĄkT}ˆJ”¤~ƒÈT„d„™pddʾĬŠ”ŽBVt„EÀ¢ôPĎƗè@~‚k–ü\\rÊĔÖæW_§¼F˜†´©òDòj’ˆYÈrbĞāøŀG{ƀ|¦ðrb|ÀH`pʞkv‚GpuARhÞÆǶgƊTǼƹS£¨¡ù³ŘÍ]¿Ây™ôEP xX¶¹܇O¡“gÚ¡IwÃ鑦ÅB‡Ï|ǰ…N«úmH¯‹âŸDùŽyŜžŲIÄuШDž•¸dɂ‡‚FŸƒ•›Oh‡đ©OŸ›iÃ`ww^ƒÌkŸ‘ÑH«ƇǤŗĺtFu…{Z}Ö@U‡´…ʚLg®¯Oı°ÃwŸ ^˜—€VbÉs‡ˆmA…ê]]w„§›RRl£‡ȭµu¯b{ÍDěïÿȧŽuT£ġƒěŗƃĝ“Q¨fV†Ƌ•ƅn­a@‘³@šď„yýIĹÊKšŭfċŰóŒxV@tˆƯŒJ”]eƒR¾fe|rHA˜|h~Ėƍl§ÏŠlTíb ØoˆÅbbx³^zÃ͚¶Sj®A”yÂhðk`š«P€”ˈµEF†Û¬Y¨Ļrõqi¼‰Wi°§’б´°^[ˆÀ|ĠO@ÆxO\\tŽa\\tĕtû{ġŒȧXýĪÓjùÎRb›š^ΛfK[ݏděYfíÙTyŽuUSyŌŏů@Oi½’éŅ­aVcř§ax¹XŻác‡žWU£ôãºQ¨÷Ñws¥qEH‰Ù|‰›šYQoŕÇyáĂ£MðoťÊ‰P¡mšWO¡€v†{ôvîēÜISpÌhp¨ ‘j†deŔQÖj˜X³à™Ĉ[n`Yp@Už–cM`’RKhŒEbœ”pŞlNut®Etq‚nsÁŠgA‹iú‹oH‡qCX‡”hfgu“~ϋWP½¢G^}¯ÅīGCŸÑ^ãziMáļMTÃƘrMc|O_ž¯Ŏ´|‡morDkO\\mĆJfl@c̬¢aĦtRıҙ¾ùƀ^juųœK­ƒUFy™—Ɲ…›īÛ÷ąV×qƥV¿aȉd³B›qPBm›aËđŻģm“Å®Vйd^K‡KoŸnYg“¯Xhqa”Ldu¥•ÍpDž¡KąÅƒkĝęěhq‡}HyÓ]¹ǧ£…Í÷¿qáµ§š™g‘¤o^á¾ZE‡¤i`ij{n•ƒOl»ŸWÝĔįhg›F[¿¡—ßkOüš_‰€ū‹i„DZàUtėGylƒ}ŒÓM}€jpEC~¡FtoQi‘šHkk{Ãmï‚" - ] - ], - "encodeOffsets": [[[119712, 40641]], [[121616, 39981]], [[116462, 37237]]] - } - }, - { - "type": "Feature", - "id": "140000", - "properties": { - "id": "140000", - "cp": [111.849248, 36.857014], - "name": "山西", - "childNum": 1 - }, - "geometry": { - "type": "Polygon", - "coordinates": [ - "@@Þĩ҃S‰ra}Á€yWix±Üe´lè“ßÓǏok‘ćiµVZģ¡coœ‘TS˹ĪmnÕńe–hZg{gtwªpXaĚThȑp{¶Eh—®RćƑP¿£‘Pmc¸mQÝW•ďȥoÅîɡųAďä³aωJ‘½¥PG­ąSM­™…EÅruµé€‘Yӎ•Ō_d›ĒCo­Èµ]¯_²ÕjāŽK~©ÅØ^ԛkïçămϑk]­±ƒcݯÑÃmQÍ~_a—pm…~ç¡q“ˆu{JÅŧ·Ls}–EyÁÆcI{¤IiCfUc•ƌÃp§]웫vD@¡SÀ‘µM‚ÅwuŽYY‡¡DbÑc¡hƒ×]nkoQdaMç~eD•ÛtT‰©±@¥ù@É¡‰ZcW|WqOJmĩl«ħşvOÓ«IqăV—¥ŸD[mI~Ó¢cehiÍ]Ɠ~ĥqXŠ·eƷœn±“}v•[ěďŽŕ]_‘œ•`‰¹ƒ§ÕōI™o©b­s^}Ét±ū«³p£ÿ·Wµ|¡¥ăFÏs׌¥ŅxŸÊdÒ{ºvĴÎêÌɊ²¶€ü¨|ÞƸµȲ‘LLúÉƎ¤ϊęĔV`„_bª‹S^|ŸdŠzY|dz¥p†ZbÆ£¶ÒK}tĦÔņƠ‚PYzn€ÍvX¶Ěn ĠÔ„zý¦ª˜÷žÑĸَUȌ¸‚dòÜJð´’ìúNM¬ŒXZ´‘¤ŊǸ_tldIš{¦ƀðĠȤ¥NehXnYG‚‡R° ƬDj¬¸|CĞ„Kq‚ºfƐiĺ©ª~ĆOQª ¤@ìǦɌ²æBŒÊ”TœŸ˜ʂōĖ’šĴŞ–ȀœÆÿȄlŤĒö„t”νî¼ĨXhŒ‘˜|ªM¤Ðz" - ], - "encodeOffsets": [[116874, 41716]] - } - }, - { - "type": "Feature", - "id": "150000", - "properties": { - "id": "150000", - "cp": [111.670801, 41.818311], - "name": "内蒙古", - "childNum": 2 - }, - "geometry": { - "type": "MultiPolygon", - "coordinates": [ - [ - "@@¯PqƒFB…‰|S•³C|kñ•H‹d‘iÄ¥sˆʼnő…PóÑÑE^‘ÅPpy_YtS™hQ·aHwsOnʼnÚs©iqj›‰€USiº]ïWš‰«gW¡A–Rë¥_ŽsgÁnUI«m‰…„‹]j‡vV¼euhwqA„aW˜ƒ_µj…»çjioQR¹ēÃßt@r³[ÛlćË^ÍÉáG“›OUۗOB±•XŸkŇ¹£k|e]ol™ŸkVͼÕqtaÏõjgÁ£§U^Œ”RLˆËnX°Ç’Bz†^~wfvˆypV ¯„ƫĉ˭ȫƗŷɿÿĿƑ˃ĝÿÃǃßËőó©ǐȍŒĖM×ÍEyx‹þp]Évïè‘vƀnÂĴÖ@‚‰†V~Ĉv¦wĖt—ējyÄDXÄxGQuv_›i¦aBçw‘˛wD™©{ŸtāmQ€{EJ§KPśƘƿ¥@‰sCT•É}ɃwˆƇy±ŸgÑ“}T[÷kÐ禫…SÒ¥¸ëBX½‰HáŵÀğtSÝÂa[ƣ°¯¦P]£ġ“–“Òk®G²„èQ°óMq}EŠóƐÇ\\ƒ‡@áügQ͋u¥Fƒ“T՛¿Jû‡]|mvāÎYua^WoÀa·­ząÒot×¶CLƗi¯¤mƎHNJ¤îìɾŊìTdåwsRÖgĒųúÍġäÕ}Q¶—ˆ¿A•†‹[¡Œ{d×uQAƒ›M•xV‹vMOmăl«ct[wº_šÇʊŽŸjb£ĦS_é“QZ“_lwgOiýe`YYLq§IÁˆdz£ÙË[ÕªuƏ³ÍT—s·bÁĽäė[›b[ˆŗfãcn¥îC¿÷µ[ŏÀQ­ōšĉm¿Á^£mJVm‡—L[{Ï_£›F¥Ö{ŹA}…×Wu©ÅaųijƳhB{·TQqÙIķˑZđ©Yc|M¡…L•eVUóK_QWk’_ĥ‘¿ãZ•»X\\ĴuUƒè‡lG®ěłTĠğDєOrÍd‚ÆÍz]‹±…ŭ©ŸÅ’]ŒÅÐ}UË¥©Tċ™ïxgckfWgi\\ÏĒ¥HkµE˜ë{»ÏetcG±ahUiñiWsɁˆ·c–C‚Õk]wȑ|ća}w…VaĚ᠞ŒG°ùnM¬¯†{ÈˆÐÆA’¥ÄêJxÙ¢”hP¢Ûˆº€µwWOŸóFŽšÁz^ÀŗÎú´§¢T¤ǻƺSė‰ǵhÝÅQgvBHouʝl_o¿Ga{ïq{¥|ſĿHĂ÷aĝÇq‡Z‘ñiñC³ª—…»E`¨åXēÕqÉû[l•}ç@čƘóO¿¡ƒFUsA‰“ʽīccšocƒ‚ƒÇS}„“£‡IS~ălkĩXçmĈ…ŀЂoÐdxÒuL^T{r@¢‘žÍƒĝKén£kQ™‰yšÅõËXŷƏL§~}kqš»IHėDžjĝŸ»ÑÞoŸå°qTt|r©ÏS‹¯·eŨĕx«È[eMˆ¿yuˆ‘pN~¹ÏyN£{©’—g‹ħWí»Í¾s“əšDž_ÃĀɗ±ą™ijĉʍŌŷ—S›É“A‹±åǥɋ@럣R©ąP©}ĹªƏj¹erƒLDĝ·{i«ƫC£µsKCš…GS|úþX”gp›{ÁX¿Ÿć{ƱȏñZáĔyoÁhA™}ŅĆfdʼn„_¹„Y°ėǩÑ¡H¯¶oMQqð¡Ë™|‘Ñ`ƭŁX½·óۓxğįÅcQ‡ˆ“ƒs«tȋDžF“Ÿù^i‘t«Č¯[›hAi©á¥ÇĚ×l|¹y¯YȵƓ‹ñǙµï‚ċ™Ļ|Dœ™üȭ¶¡˜›oŽäÕG\\ďT¿Òõr¯œŸLguÏYęRƩšɷŌO\\İТæ^Ŋ IJȶȆbÜGŽĝ¬¿ĚVĎgª^íu½jÿĕęjık@Ľƒ]ėl¥Ë‡ĭûÁ„ƒėéV©±ćn©­ȇžÍq¯½•YÃÔʼn“ÉNѝÅÝy¹NqáʅDǡËñ­ƁYÅy̱os§ȋµʽǘǏƬɱà‘ưN¢ƔÊuľýľώȪƺɂļžxœZĈ}ÌʼnŪ˜ĺœŽĭFЛĽ̅ȣͽÒŵìƩÇϋÿȮǡŏçƑůĕ~Ǎ›¼ȳÐUf†dIxÿ\\G ˆzâɏÙOº·pqy£†@ŒŠqþ@Ǟ˽IBäƣzsÂZ†ÁàĻdñ°ŕzéØűzșCìDȐĴĺf®ŽÀľưø@ɜÖÞKĊŇƄ§‚͑těï͡VAġÑÑ»d³öǍÝXĉĕÖ{þĉu¸ËʅğU̎éhɹƆ̗̮ȘNJ֥ड़ࡰţાíϲäʮW¬®ҌeרūȠkɬɻ̼ãüfƠSצɩςåȈHϚÎKdzͲOðÏȆƘ¼CϚǚ࢚˼ФԂ¤ƌžĞ̪Qʤ´¼mȠJˀŸƲÀɠmǐnǔĎȆÞǠN~€ʢĜ‚¶ƌĆĘźʆȬ˪ĚǏĞGȖƴƀj`ĢçĶāàŃºē̃ĖćšYŒÀŎüôQÐÂŎŞdžŞêƖš˜oˆDĤÕºÑǘÛˤ³̀gńƘĔÀ^žªƂ`ªt¾äƚêĦĀ¼Ð€Ĕǎ¨Ȕ»͠^ˮÊȦƤøxRrŜH¤¸ÂxDĝŒ|ø˂˜ƮÐ¬ɚwɲFjĔ²Äw°dždÀɞ_ĸdîàŎjʜêTĞªŌ‡ŜWÈ|tqĢUB~´°ÎFC•ŽU¼pĀēƄN¦¾O¶ŠłKĊOj“Ě”j´ĜYp˜{¦„ˆSĚÍ\\Tš×ªV–÷Ší¨ÅDK°ßtŇĔKš¨ǵÂcḷ̌ĚǣȄĽF‡lġUĵœŇ‹ȣFʉɁƒMğįʏƶɷØŭOǽ«ƽū¹Ʊő̝Ȩ§ȞʘĖiɜɶʦ}¨֪ࠜ̀ƇǬ¹ǨE˦ĥªÔêFŽxúQ„Er´W„rh¤Ɛ \\talĈDJ˜Ü|[Pll̚¸ƎGú´Pž¬W¦†^¦–H]prR“n|or¾wLVnÇIujkmon£cX^Bh`¥V”„¦U¤¸}€xRj–[^xN[~ªŠxQ„‚[`ªHÆÂExx^wšN¶Ê˜|¨ì†˜€MrœdYp‚oRzNy˜ÀDs~€bcfÌ`L–¾n‹|¾T‚°c¨È¢a‚r¤–`[|òDŞĔöxElÖdH„ÀI`„Ď\\Àì~ƎR¼tf•¦^¢ķ¶e”ÐÚMŒptgj–„ɡČÅyġLû™ŇV®ŠÄÈƀ†Ď°P|ªVV†ªj–¬ĚÒêp¬–E|ŬÂc|ÀtƐK fˆ{ĘFǜƌXƲąo½Ę‘\\¥–o}›Ûu£ç­kX‘{uĩ«āíÓUŅßŢq€Ť¥lyň[€oi{¦‹L‡ń‡ðFȪȖ”ĒL„¿Ì‹ˆfŒ£K£ʺ™oqNŸƒwğc`ue—tOj×°KJ±qƒÆġm‰Ěŗos¬…qehqsuœƒH{¸kH¡Š…ÊRǪÇƌbȆ¢´ä܍¢NìÉʖ¦â©Ġu¦öČ^â£Ăh–šĖMÈÄw‚\\fŦ°W ¢¾luŸD„wŠ\\̀ʉÌÛM…Ā[bӞEn}¶Vc…ê“sƒ" - ] - ], - "encodeOffsets": [[[129102, 52189]]] - } - }, - { - "type": "Feature", - "id": "210000", - "properties": { - "id": "210000", - "cp": [123.429096, 41.796767], - "name": "辽宁", - "childNum": 16 - }, - "geometry": { - "type": "MultiPolygon", - "coordinates": [ - ["@@L–Ž@@s™a"], - ["@@MnNm"], - ["@@d‚c"], - ["@@eÀ‚C@b‚“‰"], - ["@@f‡…Xwkbr–Ä`qg"], - ["@@^jtW‘Q"], - ["@@~ Y]c"], - ["@@G`ĔN^_¿Z‚ÃM"], - ["@@iX¶B‹Y"], - ["@@„YƒZ"], - ["@@L_{Epf"], - ["@@^WqCT\\"], - ["@@\\[“‹§t|”¤_"], - ["@@m`n_"], - ["@@Ïxnj{q_×^Giip"], - [ - "@@@œé^B†‡ntˆaÊU—˜Ÿ]x ¯ÄPIJ­°h€ʙK³†VˆÕ@Y~†|EvĹsDŽ¦­L^p²ŸÒG ’Ël]„xxÄ_˜fT¤Ď¤cŽœP„–C¨¸TVjbgH²sdÎdHt`Bˆ—²¬GJję¶[ÐhjeXdlwhšðSȦªVÊπ‹Æ‘Z˜ÆŶ®²†^ŒÎyÅÎcPqń“ĚDMħĜŁH­ˆk„çvV[ij¼W–‚YÀäĦ’‘`XlžR`žôLUVžfK–¢†{NZdĒª’YĸÌÚJRr¸SA|ƴgŴĴÆbvªØX~†źBŽ|¦ÕœEž¤Ð`\\|Kˆ˜UnnI]¤ÀÂĊnŎ™R®Ő¿¶\\ÀøíDm¦ÎbŨab‰œaĘ\\ľã‚¸a˜tÎSƐ´©v\\ÖÚÌǴ¤Â‡¨JKr€Z_Z€fjþhPkx€`Y”’RIŒjJcVf~sCN¤ ˆE‚œhæm‰–sHy¨SðÑÌ\\\\ŸĐRZk°IS§fqŒßýáЍÙÉÖ[^¯ǤŲ„ê´\\¦¬ĆPM¯£Ÿˆ»uïpùzEx€žanµyoluqe¦W^£ÊL}ñrkqWňûP™‰UP¡ôJŠoo·ŒU}£Œ„[·¨@XŒĸŸ“‹‹DXm­Ûݏº‡›GU‹CÁª½{íĂ^cj‡k“¶Ã[q¤“LÉö³cux«zZfƒ²BWÇ®Yß½ve±ÃC•ý£W{Ú^’q^sÑ·¨‹ÍOt“¹·C¥‡GD›rí@wÕKţ݋˜Ÿ«V·i}xËÍ÷‘i©ĝ‡ɝǡ]ƒˆ{c™±OW‹³Ya±Ÿ‰_穂Hžĕoƫ€Ňqƒr³‰Lys[„ñ³¯OS–ďOMisZ†±ÅFC¥Pq{‚Ã[Pg}\\—¿ghćO…•k^ģÁFıĉĥM­oEqqZûěʼn³F‘¦oĵ—hŸÕP{¯~TÍlª‰N‰ßY“Ð{Ps{ÃVU™™eĎwk±ʼnVÓ½ŽJãÇÇ»Jm°dhcÀff‘dF~ˆ€ĀeĖ€d`sx² šƒ®EżĀdQ‹Âd^~ăÔHˆ¦\\›LKpĄVez¤NP ǹӗR™ÆąJSh­a[¦´Âghwm€BÐ¨źhI|žVVŽ—Ž|p] Â¼èNä¶ÜBÖ¼“L`‚¼bØæŒKV”ŸpoœúNZÞÒKxpw|ÊEMnzEQšŽIZ”ŽZ‡NBˆčÚFÜçmĩ‚WĪñt‘ÞĵÇñZ«uD‚±|Əlij¥ãn·±PmÍa‰–da‡ CL‡Ǒkùó¡³Ï«QaċϑOÃ¥ÕđQȥċƭy‹³ÃA" - ] - ], - "encodeOffsets": [ - [[123686, 41445]], - [[126019, 40435]], - [[124393, 40128]], - [[126117, 39963]], - [[125322, 40140]], - [[126686, 40700]], - [[126041, 40374]], - [[125584, 40168]], - [[125453, 40165]], - [[125362, 40214]], - [[125280, 40291]], - [[125774, 39997]], - [[125976, 40496]], - [[125822, 39993]], - [[125509, 40217]], - [[122731, 40949]] - ] - } - }, - { - "type": "Feature", - "id": "220000", - "properties": { "id": "220000", "cp": [125.3245, 43.886841], "name": "吉林", "childNum": 1 }, - "geometry": { - "type": "Polygon", - "coordinates": [ - "@@‘p䔳PClƒFbbÍzš€wBG’ĭ€Z„Åi“»ƒlY­ċ²SgŽkÇ£—^S‰“qd¯•‹R…©éŽ£¯S†\\cZ¹iűƏCuƍÓX‡oR}“M^o•£…R}oªU­F…uuXHlEŕ‡€Ï©¤ÛmTŽþ¤D–²ÄufàÀ­XXȱAe„yYw¬dvõ´KÊ£”\\rµÄl”iˆdā]|DÂVŒœH¹ˆÞ®ÜWnŒC”Œķ W‹§@\\¸‹ƒ~¤‹Vp¸‰póIO¢ŠVOšŇürXql~òÉK]¤¥Xrfkvzpm¶bwyFoúvð‡¼¤ N°ąO¥«³[ƒéǡű_°Õ\\ÚÊĝŽþâőàerR¨­JYlďQ[ ÏYëЧTGz•tnŠß¡gFkMŸāGÁ¤ia É‰™È¹`\\xs€¬dĆkNnuNUŠ–užP@‚vRY¾•–\\¢…ŒGªóĄ~RãÖÎĢù‚đŴÕhQŽxtcæëSɽʼníëlj£ƍG£nj°KƘµDsØÑpyƸ®¿bXp‚]vbÍZuĂ{nˆ^IüœÀSք”¦EŒvRÎûh@℈[‚Əȉô~FNr¯ôçR±ƒ­HÑl•’Ģ–^¤¢‚OðŸŒævxsŒ]ÞÁTĠs¶¿âƊGW¾ìA¦·TѬ†è¥€ÏÐJ¨¼ÒÖ¼ƒƦɄxÊ~S–tD@ŠĂ¼Ŵ¡jlºWžvЉˆzƦZЎ²CH— „Axiukd‹ŒGgetqmcžÛ£Ozy¥cE}|…¾cZ…k‚‰¿uŐã[oxGikfeäT@…šSUwpiÚFM©’£è^ڟ‚`@v¶eň†f h˜eP¶žt“äOlÔUgƒÞzŸU`lœ}ÔÆUvØ_Ō¬Öi^ĉi§²ÃŠB~¡Ĉ™ÚEgc|DC_Ȧm²rBx¼MÔ¦ŮdĨÃâYx‘ƘDVÇĺĿg¿cwÅ\\¹˜¥Yĭlœ¤žOv†šLjM_a W`zļMž·\\swqÝSA‡š—q‰Śij¯Š‘°kŠRē°wx^Đkǂғ„œž“œŽ„‹\\]˜nrĂ}²ĊŲÒøãh·M{yMzysěnĒġV·°“G³¼XÀ““™¤¹i´o¤ŃšŸÈ`̃DzÄUĞd\\i֚ŒˆmÈBĤÜɲDEh LG¾ƀľ{WaŒYÍȏĢĘÔRîĐj‹}Ǟ“ccj‡oUb½š{“h§Ǿ{K‹ƖµÎ÷žGĀÖŠåưÎs­l›•yiē«‹`姝H¥Ae^§„GK}iã\\c]v©ģZ“mÃ|“[M}ģTɟĵ‘Â`À–çm‰‘FK¥ÚíÁbXš³ÌQґHof{‰]e€pt·GŋĜYünĎųVY^’˜ydõkÅZW„«WUa~U·Sb•wGçǑ‚“iW^q‹F‚“›uNĝ—·Ew„‹UtW·Ýďæ©PuqEzwAV•—XR‰ãQ`­©GŒM‡ehc›c”ďϝd‡©ÑW_ϗYƅŒ»…é\\ƒɹ~ǙG³mØ©BšuT§Ĥ½¢Ã_ý‘L¡‘ýŸqT^rme™\\Pp•ZZbƒyŸ’uybQ—efµ]UhĿDCmûvašÙNSkCwn‰cćfv~…Y‹„ÇG" - ], - "encodeOffsets": [[130196, 42528]] - } - }, - { - "type": "Feature", - "id": "230000", - "properties": { - "id": "230000", - "cp": [128.642464, 46.756967], - "name": "黑龙江", - "childNum": 2 - }, - "geometry": { - "type": "MultiPolygon", - "coordinates": [ - [ - "@@UƒµNÿ¥īè灋•HÍøƕ¶LŒǽ|g¨|”™Ža¾pViˆdd”~ÈiŒíďÓQġėǐZ΋ŽXb½|ſÃH½ŸKFgɱCģÛÇA‡n™‹jÕc[VĝDZÃ˄Ç_™ £ń³pŽj£º”š¿”»WH´¯”U¸đĢmžtĜyzzNN|g¸÷äűѱĉā~mq^—Œ[ƒ”››”ƒǁÑďlw]¯xQĔ‰¯l‰’€°řĴrŠ™˜BˆÞTxr[tޏĻN_yŸX`biN™Ku…P›£k‚ZĮ—¦[ºxÆÀdhŽĹŀUÈƗCw’áZħÄŭcÓ¥»NAw±qȥnD`{ChdÙFćš}¢‰A±Äj¨]ĊÕjŋ«×`VuÓś~_kŷVÝyh„“VkÄãPs”Oµ—fŸge‚Ň…µf@u_Ù ÙcŸªNªÙEojVx™T@†ãSefjlwH\\pŏäÀvŠŽlY†½d{†F~¦dyz¤PÜndsrhf‹HcŒvlwjFœ£G˜±DύƥY‡yϊu¹XikĿ¦ÏqƗǀOŜ¨LI|FRĂn sª|Cš˜zxAè¥bœfudTrFWÁ¹Am|˜ĔĕsķÆF‡´Nš‰}ć…UŠÕ@Áijſmužç’uð^ÊýowŒFzØÎĕNőžǏȎôªÌŒDŽàĀÄ˄ĞŀƒʀĀƘŸˮȬƬĊ°ƒUŸzou‡xe]}Ž…AyȑW¯ÌmK‡“Q]‹Īºif¸ÄX|sZt|½ÚUΠlkš^p{f¤lˆºlÆW –€A²˜PVܜPH”Êâ]ÎĈÌÜk´\\@qàsĔÄQºpRij¼èi†`¶—„bXƒrBgxfv»ŽuUiˆŒ^v~”J¬mVp´£Œ´VWrnP½ì¢BX‚¬h™ŠðX¹^TjVœŠriªj™tŊÄm€tPGx¸bgRšŽsT`ZozÆO]’ÒFô҆Oƒ‡ŊŒvŞ”p’cGŒêŠsx´DR–Œ{A†„EOr°Œ•žx|íœbˆ³Wm~DVjºéNN†Ëܲɶ­GƒxŷCStŸ}]ûō•SmtuÇÃĕN•™āg»šíT«u}ç½BĵÞʣ¥ëÊ¡Mێ³ãȅ¡ƋaǩÈÉQ‰†G¢·lG|›„tvgrrf«†ptęŘnŠÅĢr„I²¯LiØsPf˜_vĠd„xM prʹšL¤‹¤‡eˌƒÀđK“žïÙVY§]I‡óáĥ]ķ†Kˆ¥Œj|pŇ\\kzţ¦šnņäÔVĂîά|vW’®l¤èØr‚˜•xm¶ă~lÄƯĄ̈́öȄEÔ¤ØQĄ–Ą»ƢjȦOǺ¨ìSŖÆƬy”Qœv`–cwƒZSÌ®ü±DŽ]ŀç¬B¬©ńzƺŷɄeeOĨS’Œfm Ċ‚ƀP̎ēz©Ċ‚ÄÕÊmgŸÇsJ¥ƔˆŊśæ’΁Ñqv¿íUOµª‰ÂnĦÁ_½ä@ê텣P}Ġ[@gġ}g“ɊדûÏWXá¢užƻÌsNͽƎÁ§č՛AēeL³àydl›¦ĘVçŁpśdžĽĺſʃQíÜçÛġԏsĕ¬—Ǹ¯YßċġHµ ¡eå`ļƒrĉŘóƢFì“ĎWøxÊk†”ƈdƬv|–I|·©NqńRŀƒ¤é”eŊœŀ›ˆàŀU²ŕƀB‚Q£Ď}L¹Îk@©ĈuǰųǨ”Ú§ƈnTËÇéƟÊcfčŤ^Xm‡—HĊĕË«W·ċëx³ǔķÐċJā‚wİ_ĸ˜Ȁ^ôWr­°oú¬Ħ…ŨK~”ȰCĐ´Ƕ£’fNÎèâw¢XnŮeÂÆĶŽ¾¾xäLĴĘlļO¤ÒĨA¢Êɚ¨®‚ØCÔ ŬGƠ”ƦYĜ‡ĘÜƬDJ—g_ͥœ@čŅĻA“¶¯@wÎqC½Ĉ»NŸăëK™ďÍQ“Ùƫ[«Ãí•gßÔÇOÝáW‘ñuZ“¯ĥ€Ÿŕā¡ÑķJu¤E Ÿå¯°WKɱ_d_}}vyŸõu¬ï¹ÓU±½@gÏ¿rýD‰†g…Cd‰µ—°MFYxw¿CG£‹Rƛ½Õ{]L§{qqąš¿BÇƻğëšܭNJË|c²}Fµ}›ÙRsÓpg±ŠQNqǫŋRwŕnéÑÉKŸ†«SeYR…ŋ‹@{¤SJ}šD Ûǖ֍Ÿ]gr¡µŷjqWÛham³~S«“„›Þ]" - ] - ], - "encodeOffsets": [[[134456, 44547]]] - } - }, - { - "type": "Feature", - "id": "320000", - "properties": { - "id": "320000", - "cp": [119.767413, 33.041544], - "name": "江苏", - "childNum": 1 - }, - "geometry": { - "type": "Polygon", - "coordinates": [ - "@@cþÅPiŠ`ZŸRu¥É\\]~°ŽY`µ†Óƒ^phÁbnÀşúŽòa–ĬºTÖŒb‚˜e¦¦€{¸ZâćNpŒ©žHr|^ˆmjhŠSEb\\afv`sz^lkŽlj‹Ätg‹¤D˜­¾Xš¿À’|ДiZ„ȀåB·î}GL¢õcßjaŸyBFµÏC^ĭ•cÙt¿sğH]j{s©HM¢ƒQnDÀ©DaÜތ·jgàiDbPufjDk`dPOîƒhw¡ĥ‡¥šG˜ŸP²ĐobºrY†„î¶aHŢ´ ]´‚rılw³r_{£DB_Ûdåuk|ˆŨ¯F Cºyr{XFy™e³Þċ‡¿Â™kĭB¿„MvÛpm`rÚã”@ƹhågËÖƿxnlč¶Åì½Ot¾dJlŠVJʜǀœŞqvnOŠ^ŸJ”Z‘ż·Q}ê͎ÅmµÒ]Žƍ¦Dq}¬R^èĂ´ŀĻĊIԒtžIJyQŐĠMNtœR®òLh‰›Ěs©»œ}OӌGZz¶A\\jĨFˆäOĤ˜HYš†JvÞHNiÜaϚɖnFQlšNM¤ˆB´ĄNöɂtp–Ŭdf先‹qm¿QûŠùއÚb¤uŃJŴu»¹Ą•lȖħŴw̌ŵ²ǹǠ͛hĭłƕrçü±Y™xci‡tğ®jű¢KOķ•Coy`å®VTa­_Ā]ŐÝɞï²ʯÊ^]afYǸÃĆēĪȣJđ͍ôƋĝÄ͎ī‰çÛɈǥ£­ÛmY`ó£Z«§°Ó³QafusNıDž_k}¢m[ÝóDµ—¡RLčiXy‡ÅNïă¡¸iĔϑNÌŕoēdōîåŤûHcs}~Ûwbù¹£¦ÓCt‹OPrƒE^ÒoŠg™ĉIµžÛÅʹK…¤½phMŠü`o怆ŀ" - ], - "encodeOffsets": [[121740, 32276]] - } - }, - { - "type": "Feature", - "id": "330000", - "properties": { - "id": "330000", - "cp": [120.153576, 29.287459], - "name": "浙江", - "childNum": 45 - }, - "geometry": { - "type": "MultiPolygon", - "coordinates": [ - ["@@E^dQ]K"], - ["@@jX^j‡"], - ["@@sfŠbU‡"], - ["@@qP\\xz[ck"], - ["@@‘Rƒ¢‚FX}°[s_"], - ["@@Cbœ\\—}"], - ["@@e|v\\la{u"], - ["@@v~u}"], - ["@@QxÂF¯}"], - ["@@¹nŒvÞs¯o"], - ["@@rSkUEj"], - ["@@bi­ZŒP"], - ["@@p[}INf"], - ["@@À¿€"], - ["@@¹dnbŒ…"], - ["@@rSŸBnR"], - ["@@g~h}"], - ["@@FlEk"], - ["@@OdPc"], - ["@@v[u\\"], - ["@@FjâL~wyoo~›sµL–\\"], - ["@@¬e¹aNˆ"], - ["@@\\nÔ¡q]L³ë\\ÿ®ŒQ֎"], - ["@@ÊA­©[¬"], - ["@@KxŒv­"], - ["@@@hlIk]"], - ["@@pW{o||j"], - ["@@Md|_mC"], - ["@@¢…X£ÏylD¼XˆtH"], - ["@@hlÜ[LykAvyfw^Ež›¤"], - ["@@fp¤Mus“R"], - ["@@®_ma~•LÁ¬šZ"], - ["@@iM„xZ"], - ["@@ZcYd"], - ["@@Z~dOSo|A¿qZv"], - ["@@@`”EN¡v"], - ["@@|–TY{"], - ["@@@n@m"], - ["@@XWkCT\\"], - ["@@ºwšZRkĕWO¢"], - ["@@™X®±Grƪ\\ÔáXq{‹"], - ["@@ůTG°ĄLHm°UC‹"], - [ - "@@¤Ž€aÜx~}dtüGæţŎíĔcŖpMËВj碷ðĄÆMzˆjWKĎ¢Q¶˜À_꒔_Bı€i«pZ€gf€¤Nrq]§ĂN®«H±‡yƳí¾×ŸīàLłčŴǝĂíÀBŖÕªˆŠÁŖHŗʼnåqûõi¨hÜ·ƒñt»¹ýv_[«¸m‰YL¯‰Qª…mĉÅdMˆ•gÇjcº«•ęœ¬­K­´ƒB«Âącoċ\\xKd¡gěŧ«®á’[~ıxu·Å”KsËɏc¢Ù\\ĭƛëbf¹­ģSƒĜkáƉÔ­ĈZB{ŠaM‘µ‰fzʼnfåÂŧįƋǝÊĕġć£g³ne­ą»@­¦S®‚\\ßðCšh™iqªĭiAu‡A­µ”_W¥ƣO\\lċĢttC¨£t`ˆ™PZäuXßBs‡Ļyek€OđġĵHuXBšµ]׌‡­­\\›°®¬F¢¾pµ¼kŘó¬Wät’¸|@ž•L¨¸µr“ºù³Ù~§WI‹ŸZWŽ®’±Ð¨ÒÉx€`‰²pĜ•rOògtÁZ}þÙ]„’¡ŒŸFK‚wsPlU[}¦Rvn`hq¬\\”nQ´ĘRWb”‚_ rtČFI֊kŠŠĦPJ¶ÖÀÖJĈĄTĚòžC ²@Pú…Øzœ©PœCÈÚœĒ±„hŖ‡l¬â~nm¨f©–iļ«m‡nt–u†ÖZÜÄj“ŠLŽ®E̜Fª²iÊxبžIÈhhst" - ], - ["@@o\\V’zRZ}y"], - ["@@†@°¡mۛGĕ¨§Ianá[ýƤjfæ‡ØL–•äGr™"] - ], - "encodeOffsets": [ - [[125592, 31553]], - [[125785, 31436]], - [[125729, 31431]], - [[125513, 31380]], - [[125223, 30438]], - [[125115, 30114]], - [[124815, 29155]], - [[124419, 28746]], - [[124095, 28635]], - [[124005, 28609]], - [[125000, 30713]], - [[125111, 30698]], - [[125078, 30682]], - [[125150, 30684]], - [[124014, 28103]], - [[125008, 31331]], - [[125411, 31468]], - [[125329, 31479]], - [[125626, 30916]], - [[125417, 30956]], - [[125254, 30976]], - [[125199, 30997]], - [[125095, 31058]], - [[125083, 30915]], - [[124885, 31015]], - [[125218, 30798]], - [[124867, 30838]], - [[124755, 30788]], - [[124802, 30809]], - [[125267, 30657]], - [[125218, 30578]], - [[125200, 30562]], - [[124968, 30474]], - [[125167, 30396]], - [[124955, 29879]], - [[124714, 29781]], - [[124762, 29462]], - [[124325, 28754]], - [[123990, 28459]], - [[125366, 31477]], - [[125115, 30363]], - [[125369, 31139]], - [[122495, 31878]], - [[125329, 30690]], - [[125192, 30787]] - ] - } - }, - { - "type": "Feature", - "id": "340000", - "properties": { "id": "340000", "cp": [117.283042, 31.26119], "name": "安徽", "childNum": 3 }, - "geometry": { - "type": "MultiPolygon", - "coordinates": [ - ["@@^iuLX^"], - ["@@‚e©Ehl"], - [ - "@@°ZÆëϵmkǀwÌÕæhºgBĝâqÙĊz›ÖgņtÀÁÊÆá’hEz|WzqD¹€Ÿ°E‡ŧl{ævÜcA`¤C`|´qžxIJkq^³³ŸGšµbƒíZ…¹qpa±ď OH—¦™Ħˆx¢„gPícOl_iCveaOjCh߸i݋bÛªCC¿€m„RV§¢A|t^iĠGÀtÚs–d]ĮÐDE¶zAb àiödK¡~H¸íæAžǿYƒ“j{ď¿‘™À½W—®£ChŒÃsiŒkkly]_teu[bFa‰Tig‡n{]Gqªo‹ĈMYá|·¥f¥—őaSÕė™NµñĞ«ImŒ_m¿Âa]uĜp …Z_§{Cƒäg¤°r[_Yj‰ÆOdý“[ŽI[á·¥“Q_n‡ùgL¾mv™ˊBÜÆ¶ĊJhšp“c¹˜O]iŠ]œ¥ jtsggJǧw×jÉ©±›EFˍ­‰Ki”ÛÃÕYv…s•ˆm¬njĻª•§emná}k«ŕˆƒgđ²Ù›DǤ›í¡ªOy›†×Où±@DŸñSęćăÕIÕ¿IµĥO‰‰jNÕËT¡¿tNæŇàåyķrĕq§ÄĩsWÆßŽF¶žX®¿‰mŒ™w…RIޓfßoG‘³¾©uyH‘į{Ɓħ¯AFnuP…ÍÔzšŒV—dàôº^Ðæd´€‡oG¤{S‰¬ćxã}›ŧ×Kǥĩ«žÕOEзÖdÖsƘѨ[’Û^Xr¢¼˜§xvěƵ`K”§ tÒ´Cvlo¸fzŨð¾NY´ı~ÉĔē…ßúLÃϖ_ÈÏ|]ÂÏFl”g`bšežž€n¾¢pU‚h~ƴ˶_‚r sĄ~cž”ƈ]|r c~`¼{À{ȒiJjz`îÀT¥Û³…]’u}›f…ïQl{skl“oNdŸjŸäËzDvčoQŠďHI¦rb“tHĔ~BmlRš—V_„ħTLnñH±’DžœL‘¼L˜ªl§Ťa¸ŒĚlK²€\\RòvDcÎJbt[¤€D@®hh~kt°ǾzÖ@¾ªdb„YhüóZ ň¶vHrľ\\ʗJuxAT|dmÀO„‹[ÃԋG·ĚąĐlŪÚpSJ¨ĸˆLvÞcPæķŨŽ®mАˆálŸwKhïgA¢ųƩޖ¤OȜm’°ŒK´" - ] - ], - "encodeOffsets": [[[121722, 32278]], [[119475, 30423]], [[119168, 35472]]] - } - }, - { - "type": "Feature", - "id": "350000", - "properties": { - "id": "350000", - "cp": [118.306239, 26.075302], - "name": "福建", - "childNum": 18 - }, - "geometry": { - "type": "MultiPolygon", - "coordinates": [ - ["@@“zht´‡]"], - ["@@aj^~ĆG—©O"], - ["@@ed¨„C}}i"], - ["@@@vˆPGsQ"], - ["@@‰sBz‚ddW]Q"], - ["@@SލQ“{"], - ["@@NŽVucW"], - ["@@qptBAq"], - ["@@‰’¸[mu"], - ["@@Q\\pD]_"], - ["@@jSwUadpF"], - ["@@eXª~ƒ•"], - ["@@AjvFso"], - ["@@fT–›_Çí\\Ÿ™—v|ba¦jZÆy€°"], - ["@@IjJi"], - ["@@wJI€ˆxš«¼AoNe{M­"], - ["@@K‰±¡Óˆ”ČäeZ"], - [ - "@@k¡¹Eh~c®wBk‹UplÀ¡I•~Māe£bN¨gZý¡a±Öcp©PhžI”Ÿ¢Qq…ÇGj‹|¥U™ g[Ky¬ŏ–v@OpˆtÉEŸF„\\@ åA¬ˆV{Xģ‰ĐBy…cpě…¼³Ăp·¤ƒ¥o“hqqÚ¡ŅLsƒ^ᗞ§qlŸÀhH¨MCe»åÇGD¥zPO£čÙkJA¼ß–ėu›ĕeûҍiÁŧSW¥˜QŠûŗ½ùěcݧSùĩąSWó«íęACµ›eR—åǃRCÒÇZÍ¢‹ź±^dlsŒtjD¸•‚ZpužÔâÒH¾oLUêÃÔjjēò´ĄW‚ƛ…^Ñ¥‹ĦŸ@Çò–ŠmŒƒOw¡õyJ†yD}¢ďÑÈġfŠZd–a©º²z£šN–ƒjD°Ötj¶¬ZSÎ~¾c°¶Ðm˜x‚O¸¢Pl´žSL|¥žA†ȪĖM’ņIJg®áIJČĒü` ŽQF‡¬h|ÓJ@zµ |ê³È ¸UÖŬŬÀEttĸr‚]€˜ðŽM¤ĶIJHtÏ A’†žĬkvsq‡^aÎbvŒd–™fÊòSD€´Z^’xPsÞrv‹ƞŀ˜jJd×ŘÉ ®A–ΦĤd€xĆqAŒ†ZR”ÀMźŒnĊ»ŒİÐZ— YX–æJŠyĊ²ˆ·¶q§·–K@·{s‘Xãô«lŗ¶»o½E¡­«¢±¨Yˆ®Ø‹¶^A™vWĶGĒĢžPlzfˆļŽtàAvWYãšO_‡¤sD§ssČġ[kƤPX¦Ž`¶“ž®ˆBBvĪjv©šjx[L¥àï[F…¼ÍË»ğV`«•Ip™}ccÅĥZE‹ãoP…´B@ŠD—¸m±“z«Ƴ—¿å³BRضˆœWlâþäą`“]Z£Tc— ĹGµ¶H™m@_©—kŒ‰¾xĨ‡ôȉðX«½đCIbćqK³Á‹Äš¬OAwã»aLʼn‡ËĥW[“ÂGI—ÂNxij¤D¢ŽîĎÎB§°_JœGsƒ¥E@…¤uć…P‘å†cuMuw¢BI¿‡]zG¹guĮck\\_" - ] - ], - "encodeOffsets": [ - [[123250, 27563]], - [[122541, 27268]], - [[123020, 27189]], - [[122916, 27125]], - [[122887, 26845]], - [[122808, 26762]], - [[122568, 25912]], - [[122778, 26197]], - [[122515, 26757]], - [[122816, 26587]], - [[123388, 27005]], - [[122450, 26243]], - [[122578, 25962]], - [[121255, 25103]], - [[120987, 24903]], - [[122339, 25802]], - [[121042, 25093]], - [[122439, 26024]] - ] - } - }, - { - "type": "Feature", - "id": "360000", - "properties": { - "id": "360000", - "cp": [115.592151, 27.676493], - "name": "江西", - "childNum": 1 - }, - "geometry": { - "type": "Polygon", - "coordinates": [ - "@@ĢĨƐgÂMD~ņªe^\\^§„ý©j׍cZ†Ø¨zdÒa¶ˆlҍJŒìõ`oz÷@¤u޸´†ôęöY¼‰HČƶajlÞƩ¥éZ[”|h}^U Œ ¥p„ĄžƦO lt¸Æ €Q\\€ŠaÆ|CnÂOjt­ĚĤd’ÈŒF`’¶„@Ð딠¦ōҞ¨Sêv†HĢûXD®…QgėWiØPÞìºr¤dž€NĠ¢l–•ĄtZoœCƞÔºCxrpĠV®Ê{f_Y`_ƒeq’’®Aot`@o‚DXfkp¨|Šs¬\\D‘ÄSfè©Hn¬…^DhÆyøJh“ØxĢĀLʈ„ƠPżċĄwȠ̦G®ǒĤäTŠÆ~ĦwŠ«|TF¡Šn€c³Ïå¹]ĉđxe{ÎӐ†vOEm°BƂĨİ|G’vz½ª´€H’àp”eJ݆Qšxn‹ÀŠW­žEµàXÅĪt¨ÃĖrÄwÀFÎ|ňÓMå¼ibµ¯»åDT±m[“r«_gŽmQu~¥V\\OkxtL E¢‹ƒ‘Ú^~ýê‹Pó–qo슱_Êw§ÑªåƗ⼋mĉŹ‹¿NQ“…YB‹ąrwģcÍ¥B•Ÿ­ŗÊcØiI—žƝĿuŒqtāwO]‘³YCñTeɕš‹caub͈]trlu€ī…B‘ПGsĵıN£ï—^ķqss¿FūūV՟·´Ç{éĈý‰ÿ›OEˆR_ŸđûIċâJh­ŅıN‘ȩĕB…¦K{Tk³¡OP·wn—µÏd¯}½TÍ«YiµÕsC¯„iM•¤™­•¦¯P|ÿUHv“he¥oFTu‰õ\\ŽOSs‹MòđƇiaºćXŸĊĵà·çhƃ÷ǜ{‘ígu^›đg’m[×zkKN‘¶Õ»lčÓ{XSƉv©_ÈëJbVk„ĔVÀ¤P¾ºÈMÖxlò~ªÚàGĂ¢B„±’ÌŒK˜y’áV‡¼Ã~­…`g›ŸsÙfI›Ƌlę¹e|–~udjˆuTlXµf`¿JdŠ[\\˜„L‚‘²" - ], - "encodeOffsets": [[116689, 26234]] - } - }, - { - "type": "Feature", - "id": "370000", - "properties": { - "id": "370000", - "cp": [118.000923, 36.275807], - "name": "山东", - "childNum": 13 - }, - "geometry": { - "type": "MultiPolygon", - "coordinates": [ - ["@@Xjd]{K"], - ["@@itbFHy"], - ["@@HlGk"], - ["@@T‚ŒGŸy"], - ["@@K¬˜•‹U"], - ["@@WdXc"], - ["@@PtOs"], - ["@@•LnXhc"], - ["@@ppVƒu]Or"], - ["@@cdzAUa"], - ["@@udRhnCI‡"], - ["@@ˆoIƒpR„"], - [ - "@@Ľč{fzƤî’Kš–ÎMĮ]†—ZFˆ½Y]â£ph’™š¶¨râøÀ†ÎǨ¤^ºÄ”Gzˆ~grĚĜlĞÆ„LĆdž¢Îo¦–cv“Kb€gr°Wh”mZp ˆL]LºcU‰Æ­n”żĤÌǜbAnrOAœ´žȊcÀbƦUØrĆUÜøœĬƞ†š˜Ez„VL®öØBkŖÝĐ˹ŧ̄±ÀbÎɜnb²ĦhņBĖ›žįĦåXćì@L¯´ywƕCéõė ƿ¸‘lµ¾Z|†ZWyFYŸ¨Mf~C¿`€à_RÇzwƌfQnny´INoƬˆèôº|sT„JUš›‚L„îVj„ǎ¾Ē؍‚Dz²XPn±ŴPè¸ŔLƔÜƺ_T‘üÃĤBBċȉöA´fa„˜M¨{«M`‡¶d¡ô‰Ö°šmȰBÔjjŒ´PM|”c^d¤u•ƒ¤Û´Œä«ƢfPk¶Môlˆ]Lb„}su^ke{lC‘…M•rDŠÇ­]NÑFsmoõľH‰yGă{{çrnÓE‰‹ƕZGª¹Fj¢ïW…uøCǷ돡ąuhÛ¡^Kx•C`C\\bÅxì²ĝÝ¿_N‰īCȽĿåB¥¢·IŖÕy\\‡¹kx‡Ã£Č×GDyÕ¤ÁçFQ¡„KtŵƋ]CgÏAùSed‡cÚź—ŠuYfƒyMmhUWpSyGwMPqŀ—›Á¼zK›¶†G•­Y§Ëƒ@–´śÇµƕBmœ@Io‚g——Z¯u‹TMx}C‘‰VK‚ï{éƵP—™_K«™pÛÙqċtkkù]gŽ‹Tğwo•ɁsMõ³ă‡AN£™MRkmEʕč™ÛbMjÝGu…IZ™—GPģ‡ãħE[iµBEuŸDPԛ~ª¼ętŠœ]ŒûG§€¡QMsğNPŏįzs£Ug{đJĿļā³]ç«Qr~¥CƎÑ^n¶ÆéÎR~ݏY’I“] P‰umŝrƿ›‰›Iā‹[x‰edz‹L‘¯v¯s¬ÁY…~}…ťuٌg›ƋpÝĄ_ņī¶ÏSR´ÁP~ž¿Cyžċßdwk´Ss•X|t‰`Ä Èð€AªìÎT°¦Dd–€a^lĎDĶÚY°Ž`ĪŴǒˆ”àŠv\\ebŒZH„ŖR¬ŢƱùęO•ÑM­³FۃWp[ƒ" - ] - ], - "encodeOffsets": [ - [[123806, 39303]], - [[123821, 39266]], - [[123742, 39256]], - [[123702, 39203]], - [[123649, 39066]], - [[123847, 38933]], - [[123580, 38839]], - [[123894, 37288]], - [[123043, 36624]], - [[123344, 38676]], - [[123522, 38857]], - [[123628, 38858]], - [[118260, 36742]] - ] - } - }, - { - "type": "Feature", - "id": "410000", - "properties": { - "id": "410000", - "cp": [113.665412, 33.757975], - "name": "河南", - "childNum": 1 - }, - "geometry": { - "type": "Polygon", - "coordinates": [ - "@@•ýL™ùµP³swIÓxcŢĞð†´E®žÚPt†ĴXØx¶˜@«ŕŕQGƒ‹Yfa[şu“ßǩ™đš_X³ijÕčC]kbc•¥CS¯ëÍB©÷‹–³­Siˆ_}m˜YTtž³xlàcȂzÀD}ÂOQ³ÐTĨ¯†ƗòËŖ[hœł‹Ŧv~††}ÂZž«¤lPǕ£ªÝŴÅR§ØnhcŒtâk‡nύ­ľŹUÓÝdKuķ‡I§oTũÙďkęĆH¸ÓŒ\\ăŒ¿PcnS{wBIvɘĽ[GqµuŸŇôYgûƒZcaŽ©@½Õǽys¯}lgg@­C\\£as€IdÍuCQñ[L±ęk·‹ţb¨©kK—’»›KC²‘òGKmĨS`ƒ˜UQ™nk}AGē”sqaJ¥ĐGR‰ĎpCuÌy ã iMc”plk|tRk†ðœev~^‘´†¦ÜŽSí¿_iyjI|ȑ|¿_»d}qŸ^{“Ƈdă}Ÿtqµ`Ƴĕg}V¡om½fa™Ço³TTj¥„tĠ—Ry”K{ùÓjuµ{t}uËR‘iŸvGŠçJFjµŠÍyqΘàQÂFewixGw½Yŷpµú³XU›½ġy™łå‰kÚwZXˆ·l„¢Á¢K”zO„Λ΀jc¼htoDHr…|­J“½}JZ_¯iPq{tę½ĕ¦Zpĵø«kQ…Ťƒ]MÛfaQpě±ǽ¾]u­Fu‹÷nƒ™čįADp}AjmcEǒaª³o³ÆÍSƇĈÙDIzˑ赟^ˆKLœ—i—Þñ€[œƒaA²zz‰Ì÷Dœ|[šíijgf‚ÕÞd®|`ƒĆ~„oĠƑô³Ŋ‘D×°¯CsŠøÀ«ì‰UMhTº¨¸ǡîS–Ô„DruÂÇZ•ÖEŽ’vPZ„žW”~؋ÐtĄE¢¦Ðy¸bŠô´oŬ¬Ž²Ês~€€]®tªašpŎJ¨Öº„_ŠŔ–`’Ŗ^Ѝ\\Ĝu–”~m²Ƹ›¸fW‰ĦrƔ}Î^gjdfÔ¡J}\\n C˜¦þWxªJRÔŠu¬ĨĨmF†dM{\\d\\ŠYÊ¢ú@@¦ª²SŠÜsC–}fNècbpRmlØ^g„d¢aÒ¢CZˆZxvÆ¶N¿’¢T@€uCœ¬^ĊðÄn|žlGl’™Rjsp¢ED}€Fio~ÔNŽ‹„~zkĘHVsDzßjƒŬŒŠŢ`Pûàl¢˜\\ÀœEhŽİgÞē X¼Pk–„|m" - ], - "encodeOffsets": [[118256, 37017]] - } - }, - { - "type": "Feature", - "id": "420000", - "properties": { - "id": "420000", - "cp": [113.298572, 30.684355], - "name": "湖北", - "childNum": 3 - }, - "geometry": { - "type": "MultiPolygon", - "coordinates": [ - ["@@AB‚"], - ["@@lskt"], - [ - "@@¾«}{ra®pîÃ\\™›{øCŠËyyB±„b\\›ò˜Ý˜jK›‡L ]ĎĽÌ’JyÚCƈćÎT´Å´pb©È‘dFin~BCo°BĎĚømvŒ®E^vǾ½Ĝ²Ro‚bÜeNŽ„^ĺ£R†¬lĶ÷YoĖ¥Ě¾|sOr°jY`~I”¾®I†{GqpCgyl{‡£œÍƒÍyPL“¡ƒ¡¸kW‡xYlÙæŠšŁĢzœ¾žV´W¶ùŸo¾ZHxjwfx„GNÁ•³Xéæl¶‰EièIH‰ u’jÌQ~v|sv¶Ôi|ú¢Fh˜Qsğ¦ƒSiŠBg™ÐE^ÁÐ{–čnOÂȞUÎóĔ†ÊēIJ}Z³½Mŧïeyp·uk³DsѨŸL“¶_œÅuèw»—€¡WqÜ]\\‘Ò§tƗcÕ¸ÕFÏǝĉăxŻČƟO‡ƒKÉġÿ×wg”÷IÅzCg†]m«ªGeçÃTC’«[‰t§{loWeC@ps_Bp‘­r‘„f_``Z|ei¡—oċMqow€¹DƝӛDYpûs•–‹Ykıǃ}s¥ç³[§ŸcYЧHK„«Qy‰]¢“wwö€¸ïx¼ņ¾Xv®ÇÀµRĠЋžHMž±cÏd„ƒǍũȅȷ±DSyúĝ£ŤĀàtÖÿï[îb\\}pĭÉI±Ñy…¿³x¯N‰o‰|¹H™ÏÛm‹júË~Tš•u˜ęjCöAwě¬R’đl¯ Ñb­‰ŇT†Ŀ_[Œ‘IčĄʿnM¦ğ\\É[T·™k¹œ©oĕ@A¾w•ya¥Y\\¥Âaz¯ãÁ¡k¥ne£Ûw†E©Êō¶˓uoj_Uƒ¡cF¹­[Wv“P©w—huÕyBF“ƒ`R‹qJUw\\i¡{jŸŸEPïÿ½fć…QÑÀQ{ž‚°‡fLԁ~wXg—ītêݾ–ĺ‘Hdˆ³fJd]‹HJ²…E€ƒoU¥†HhwQsƐ»Xmg±çve›]Dm͂PˆoCc¾‹_h”–høYrŊU¶eD°Č_N~øĹĚ·`z’]Äþp¼…äÌQŒv\\rCŒé¾TnkžŐڀÜa‡“¼ÝƆ̶Ûo…d…ĔňТJq’Pb ¾|JŒ¾fXŠƐîĨ_Z¯À}úƲ‹N_ĒĊ^„‘ĈaŐyp»CÇĕKŠšñL³ŠġMŒ²wrIÒŭxjb[œžn«øœ˜—æˆàƒ ^²­h¯Ú€ŐªÞ¸€Y²ĒVø}Ā^İ™´‚LŠÚm„¥ÀJÞ{JVŒųÞŃx×sxxƈē ģMř–ÚðòIf–Ċ“Œ\\Ʈ±ŒdʧĘD†vČ_Àæ~DŒċ´A®µ†¨ØLV¦êHÒ¤" - ] - ], - "encodeOffsets": [[[113712, 34000]], [[115612, 30507]], [[113649, 34054]]] - } - }, - { - "type": "Feature", - "id": "430000", - "properties": { "id": "430000", "cp": [111.782279, 28.09409], "name": "湖南", "childNum": 3 }, - "geometry": { - "type": "MultiPolygon", - "coordinates": [ - ["@@—n„FTs"], - ["@@ßÅÆá‰½ÔXr—†CO™“…ËR‘ïÿĩ­TooQyšÓ[‹ŅBE¬–ÎÓXa„į§Ã¸G °ITxp‰úxÚij¥Ïš–̾ŠedžÄ©ĸG…œàGh‚€M¤–Â_U}Ċ}¢pczfŠþg¤€”ÇòAV‘‹M"], - [ - "@@©K—ƒA·³CQ±Á«³BUŠƑ¹AŠtćOw™D]ŒJiØSm¯b£‘ylƒ›X…HËѱH•«–‘C^õľA–Å§¤É¥„ïyuǙuA¢^{ÌC´­¦ŷJ£^[†“ª¿‡ĕ~•Ƈ…•N… skóā‡¹¿€ï]ă~÷O§­@—Vm¡‹Qđ¦¢Ĥ{ºjԏŽŒª¥nf´•~ÕoŸž×Ûą‹MąıuZœmZcÒ IJβSÊDŽŶ¨ƚƒ’CÖŎªQؼrŭŽ­«}NÏürʬŒmjr€@ĘrTW ­SsdHzƓ^ÇÂyUi¯DÅYlŹu{hTœ}mĉ–¹¥ě‰Dÿë©ıÓ[Oº£ž“¥ót€ł¹MՄžƪƒ`Pš…Di–ÛUоÅ‌ìˆU’ñB“È£ýhe‰dy¡oċ€`pfmjP~‚kZa…ZsÐd°wj§ƒ@€Ĵ®w~^‚kÀÅKvNmX\\¨a“”сqvíó¿F„¤¡@ũÑVw}S@j}¾«pĂr–ªg àÀ²NJ¶¶Dô…K‚|^ª†Ž°LX¾ŴäPᜣEXd›”^¶›IJÞܓ~‘u¸ǔ˜Ž›MRhsR…e†`ÄofIÔ\\Ø  i”ćymnú¨cj ¢»–GČìƊÿШXeĈ¾Oð Fi ¢|[jVxrIQŒ„_E”zAN¦zLU`œcªx”OTu RLÄ¢dV„i`p˔vŎµªÉžF~ƒØ€d¢ºgİàw¸Áb[¦Zb¦–z½xBĖ@ªpº›šlS¸Ö\\Ĕ[N¥ˀmĎă’J\\‹ŀ`€…ňSڊĖÁĐiO“Ĝ«BxDõĚiv—ž–S™Ì}iùŒžÜnšÐºGŠ{Šp°M´w†ÀÒzJ²ò¨ oTçüöoÛÿñŽőФ‚ùTz²CȆȸǎۃƑÐc°dPÎŸğ˶[Ƚu¯½WM¡­Éž“’B·rížnZŸÒ `‡¨GA¾\\pē˜XhÆRC­üWGġu…T靧Ŏѝ©ò³I±³}_‘‹EÃħg®ęisÁPDmÅ{‰b[Rşs·€kPŸŽƥƒóRo”O‹ŸVŸ~]{g\\“êYƪ¦kÝbiċƵŠGZ»Ěõ…ó·³vŝž£ø@pyö_‹ëŽIkѵ‡bcѧy…×dY؎ªiþž¨ƒ[]f]Ņ©C}ÁN‡»hĻħƏ’ĩ" - ] - ], - "encodeOffsets": [[[115640, 30489]], [[112543, 27312]], [[116690, 26230]]] - } - }, - { - "type": "Feature", - "id": "440000", - "properties": { - "id": "440000", - "cp": [113.280637, 23.125178], - "name": "广东", - "childNum": 24 - }, - "geometry": { - "type": "MultiPolygon", - "coordinates": [ - ["@@QdˆAua"], - ["@@ƒlxDLo"], - ["@@sbhNLo"], - ["@@Ă āŸ"], - ["@@WltO[["], - ["@@Krœ]S"], - ["@@e„„I]y"], - ["@@I|„Mym"], - ["@@ƒÛ³LSŒž¼Y"], - ["@@nvºB–ëui©`¾"], - ["@@zdšÛ›Jw®"], - ["@@†°…¯"], - ["@@a yAª¸ËJIx،@€ĀHAmßV¡o•fu•o"], - ["@@šs‰ŗÃÔėAƁ›ZšÄ ~°ČP‚‹äh"], - ["@@‹¶Ý’Ì‚vmĞh­ı‡Q"], - ["@@HœŠdSjĒ¢D}war…“u«ZqadYM"], - ["@@elŒ\\LqqU"], - ["@@~rMo\\"], - ["@@f„^ƒC"], - ["@@øPªoj÷ÍÝħXČx”°Q¨ıXNv"], - ["@@gÇƳˆŽˆ”oˆŠˆ[~tly"], - ["@@E–ÆC¿‘"], - ["@@OŽP"], - [ - "@@w‹†đóg‰™ĝ—[³‹¡VÙæÅöM̳¹pÁaËýý©D©Ü“JŹƕģGą¤{Ùū…ǘO²«BƱéA—Ò‰ĥ‡¡«BhlmtÃPµyU¯uc“d·w_bŝcīímGOŽ|KP’ȏ‡ŹãŝIŕŭŕ@Óoo¿ē‹±ß}Ž…ŭ‚ŸIJWÈCőâUâǙI›ğʼn©I›ijEׅÁ”³Aó›wXJþ±ÌŒÜӔĨ£L]ĈÙƺZǾĆĖMĸĤfŒÎĵl•ŨnȈ‘ĐtF”Š–FĤ–‚êk¶œ^k°f¶gŠŽœ}®Fa˜f`vXŲxl˜„¦–ÔÁ²¬ÐŸ¦pqÊ̲ˆi€XŸØRDÎ}†Ä@ZĠ’s„x®AR~®ETtĄZ†–ƈfŠŠHâÒÐA†µ\\S¸„^wĖkRzŠalŽŜ|E¨ÈNĀňZTŒ’pBh£\\ŒĎƀuXĖtKL–¶G|Ž»ĺEļĞ~ÜĢÛĊrˆO˜Ùîvd]nˆ¬VœÊĜ°R֟pM††–‚ƂªFbwžEÀˆ˜©Œž\\…¤]ŸI®¥D³|ˎ]CöAŤ¦…æ’´¥¸Lv¼€•¢ĽBaô–F~—š®²GÌҐEY„„œzk¤’°ahlV՞I^‹šCxĈPŽsB‰ƒºV‰¸@¾ªR²ĨN]´_eavSi‡vc•}p}Đ¼ƌkJœÚe thœ†_¸ ºx±ò_xN›Ë‹²‘@ƒă¡ßH©Ùñ}wkNÕ¹ÇO½¿£ĕ]ly_WìIžÇª`ŠuTÅxYĒÖ¼k֞’µ‚MžjJÚwn\\h‘œĒv]îh|’È›Ƅøègž¸Ķß ĉĈWb¹ƀdéƌNTtP[ŠöSvrCZžžaGuœbo´ŖÒÇА~¡zCI…özx¢„Pn‹•‰Èñ @ŒĥÒ¦†]ƞŠV}³ăĔñiiÄÓVépKG½Ä‘ÓávYo–C·sit‹iaÀy„ŧΡÈYDÑům}‰ý|m[węõĉZÅxUO}÷N¹³ĉo_qtă“qwµŁYلǝŕ¹tïÛUïmRCº…ˆĭ|µ›ÕÊK™½R‘ē ó]‘–GªęAx–»HO£|ām‡¡diď×YïYWªʼnOeÚtĐ«zđ¹T…ā‡úE™á²\\‹ķÍ}jYàÙÆſ¿Çdğ·ùTßÇţʄ¡XgWÀLJğ·¿ÃˆOj YÇ÷Qě‹i" - ] - ], - "encodeOffsets": [ - [[117381, 22988]], - [[116552, 22934]], - [[116790, 22617]], - [[116973, 22545]], - [[116444, 22536]], - [[116931, 22515]], - [[116496, 22490]], - [[116453, 22449]], - [[113301, 21439]], - [[118726, 21604]], - [[118709, 21486]], - [[113210, 20816]], - [[115482, 22082]], - [[113171, 21585]], - [[113199, 21590]], - [[115232, 22102]], - [[115739, 22373]], - [[115134, 22184]], - [[113056, 21175]], - [[119573, 21271]], - [[119957, 24020]], - [[115859, 22356]], - [[116561, 22649]], - [[116285, 22746]] - ] - } - }, - { - "type": "Feature", - "id": "450000", - "properties": { "id": "450000", "cp": [108.320004, 22.82402], "name": "广西", "childNum": 2 }, - "geometry": { - "type": "MultiPolygon", - "coordinates": [ - ["@@H– TQ§•A"], - [ - "@@ĨʪƒLƒƊDÎĹĐCǦė¸zÚGn£¾›rªŀÜt¬@֛ڈSx~øOŒ˜ŶÐÂæȠ\\„ÈÜObĖw^oބLf¬°bI lTØB̈F£Ć¹gñĤaY“t¿¤VSñœK¸¤nM†¼‚JE±„½¸šŠño‹ÜCƆæĪ^ŠĚQÖ¦^‡ˆˆf´Q†üÜʝz¯šlzUĺš@쇀p¶n]sxtx¶@„~ÒĂJb©gk‚{°‚~c°`ԙ¬rV\\“la¼¤ôá`¯¹LC†ÆbŒxEræO‚v[H­˜„[~|aB£ÖsºdAĐzNÂðsŽÞƔ…Ĥªbƒ–ab`ho¡³F«èVloޤ™ÔRzpp®SŽĪº¨ÖƒºN…ij„d`’a”¦¤F³ºDÎńĀìŠCžĜº¦Ċ•~nS›|gźvZkCÆj°zVÈÁƔ]LÊFZg…čP­kini«‹qǀcz͔Y®¬Ů»qR×ō©DՄ‘§ƙǃŵTÉĩ±ŸıdÑnYY›IJvNĆÌØÜ Öp–}e³¦m‹©iÓ|¹Ÿħņ›|ª¦QF¢Â¬ʖovg¿em‡^ucà÷gՎuŒíÙćĝ}FϼĹ{µHK•sLSđƃr‹č¤[Ag‘oS‹ŇYMÿ§Ç{Fśbky‰lQxĕƒ]T·¶[B…ÑÏGáşşƇe€…•ăYSs­FQ}­Bƒw‘tYğÃ@~…C̀Q ×W‡j˱rÉ¥oÏ ±«ÓÂ¥•ƒ€k—ŽwWűŒmcih³K›~‰µh¯e]lµ›él•E쉕E“ďs‡’mǖŧē`ãògK_ÛsUʝ“ćğ¶hŒöŒO¤Ǜn³Žc‘`¡y‹¦C‘ez€YŠwa™–‘[ďĵűMę§]X˜Î_‚훘Û]é’ÛUćİÕBƣ±…dƒy¹T^džûÅÑŦ·‡PĻþÙ`K€¦˜…¢ÍeœĥR¿Œ³£[~Œäu¼dl‰t‚†W¸oRM¢ď\\zœ}Æzdvň–{ÎXF¶°Â_„ÒÂÏL©Ö•TmuŸ¼ãl‰›īkiqéfA„·Êµ\\őDc¥ÝF“y›Ôć˜c€űH_hL܋êĺШc}rn`½„Ì@¸¶ªVLŒŠhŒ‹\\•Ţĺk~ŽĠið°|gŒtTĭĸ^x‘vK˜VGréAé‘bUu›MJ‰VÃO¡…qĂXËS‰ģãlýàŸ_ju‡YÛÒB†œG^˜é֊¶§ŽƒEG”ÅzěƒƯ¤Ek‡N[kdåucé¬dnYpAyČ{`]þ¯T’bÜÈk‚¡Ġ•vŒàh„ÂƄ¢Jî¶²" - ] - ], - "encodeOffsets": [[[111707, 21520]], [[107619, 25527]]] - } - }, - { - "type": "Feature", - "id": "460000", - "properties": { "id": "460000", "cp": [109.83119, 19.031971], "name": "海南", "childNum": 1 }, - "geometry": { - "type": "Polygon", - "coordinates": [ - "@@š¦Ŝil¢”XƦ‘ƞò–ïè§ŞCêɕrŧůÇąĻõ™·ĉ³œ̅kÇm@ċȧƒŧĥ‰Ľʉ­ƅſ“ȓÒ˦ŝE}ºƑ[ÍĜȋ gÎfǐÏĤ¨êƺ\\Ɔ¸ĠĎvʄȀœÐ¾jNðĀÒRŒšZdž™zÐŘΰH¨Ƣb²_Ġ " - ], - "encodeOffsets": [[112750, 20508]] - } - }, - { - "type": "Feature", - "id": "510000", - "properties": { - "id": "510000", - "cp": [104.065735, 30.659462], - "name": "四川", - "childNum": 2 - }, - "geometry": { - "type": "MultiPolygon", - "coordinates": [ - ["@@LqKr"], - [ - "@@Š[ĻéV£ž_ţġñpG •réÏ·~ąSfy×͂·ºſƽiÍıƣıĻmHH}siaX@iǰÁÃ×t«ƒ­Tƒ¤J–JJŒyJ•ÈŠ`Ohߦ¡uËhIyCjmÿw…ZG……Ti‹SˆsO‰žB²ŸfNmsPaˆ{M{ŠõE‘^Hj}gYpaeuž¯‘oáwHjÁ½M¡pM“–uå‡mni{fk”\\oƒÎqCw†EZ¼K›ĝŠƒAy{m÷L‡wO×SimRI¯rK™õBS«sFe‡]fµ¢óY_ÆPRcue°Cbo׌bd£ŌIHgtrnyPt¦foaXďx›lBowz‹_{ÊéWiêE„GhܸºuFĈIxf®Ž•Y½ĀǙ]¤EyŸF²ċ’w¸¿@g¢§RGv»–áŸW`ÃĵJwi]t¥wO­½a[׈]`Ãi­üL€¦LabbTÀå’c}Íh™Æhˆ‹®BH€î|Ék­¤S†y£„ia©taį·Ɖ`ō¥Uh“O…ƒĝLk}©Fos‰´›Jm„µlŁu—…ø–nÑJWΪ–YÀïAetTžŅ‚ӍG™Ë«bo‰{ıwodƟ½ƒžOġܑµxàNÖ¾P²§HKv¾–]|•B‡ÆåoZ`¡Ø`ÀmºĠ~ÌЧnDž¿¤]wğ@sƒ‰rğu‰~‘Io”[é±¹ ¿žſđӉ@q‹gˆ¹zƱřaí°KtǤV»Ã[ĩǭƑ^ÇÓ@ỗs›Zϕ‹œÅĭ€Ƌ•ěpwDóÖሯneQˌq·•GCœýS]xŸ·ý‹q³•O՜Œ¶Qzßti{ř‰áÍÇWŝŭñzÇW‹pç¿JŒ™‚Xœĩè½cŒF–ÂLiVjx}\\N†ŇĖ¥Ge–“JA¼ÄHfÈu~¸Æ«dE³ÉMA|b˜Ò…˜ćhG¬CM‚õŠ„ƤąAvƒüV€éŀ‰_V̳ĐwQj´·ZeÈÁ¨X´Æ¡Qu·»Ÿ“˜ÕZ³ġqDo‰y`L¬gdp°şŠp¦ėìÅĮZްIä”h‚‘ˆzŠĵœf²å ›ĚрKp‹IN|‹„Ñz]ń……·FU×é»R³™MƒÉ»GM«€ki€™ér™}Ã`¹ăÞmȝnÁîRǀ³ĜoİzŔwǶVÚ£À]ɜ»ĆlƂ²Ġ…þTº·àUȞÏʦ¶†I’«dĽĢdĬ¿–»Ĕ׊h\\c¬†ä²GêëĤł¥ÀǿżÃÆMº}BÕĢyFVvw–ˆxBèĻĒ©Ĉ“tCĢɽŠȣ¦āæ·HĽî“ôNԓ~^¤Ɗœu„œ^s¼{TA¼ø°¢İªDè¾Ň¶ÝJ‘®Z´ğ~Sn|ªWÚ©òzPOȸ‚bð¢|‹øĞŠŒœŒQìÛÐ@Ğ™ǎRS¤Á§d…i“´ezÝúØã]Hq„kIŸþËQǦÃsǤ[E¬ÉŪÍxXƒ·ÖƁİlƞ¹ª¹|XÊwn‘ÆƄmÀêErĒtD®ċæcQƒ”E®³^ĭ¥©l}äQto˜ŖÜqƎkµ–„ªÔĻĴ¡@Ċ°B²Èw^^RsºT£ڿœQP‘JvÄz„^Đ¹Æ¯fLà´GC²‘dt˜­ĀRt¼¤ĦOðğfÔðDŨŁĞƘïžPȆ®âbMüÀXZ ¸£@Ś›»»QÉ­™]d“sÖ×_͖_ÌêŮPrĔĐÕGĂeZÜîĘqBhtO ¤tE[h|Y‹Ô‚ZśÎs´xº±UŒ’ñˆt|O’ĩĠºNbgþŠJy^dÂY Į„]Řz¦gC‚³€R`Šz’¢AjŒ¸CL„¤RÆ»@­Ŏk\\Ç´£YW}z@Z}‰Ã¶“oû¶]´^N‡Ò}èN‚ª–P˜Íy¹`S°´†ATe€VamdUĐwʄvĮÕ\\ƒu‹Æŗ¨Yp¹àZÂm™Wh{á„}WØǍ•Éüw™ga§áCNęÎ[ĀÕĪgÖɪX˜øx¬½Ů¦¦[€—„NΆL€ÜUÖ´òrÙŠxR^–†J˜k„ijnDX{Uƒ~ET{ļº¦PZc”jF²Ė@Žp˜g€ˆ¨“B{ƒu¨ŦyhoÚD®¯¢˜ WòàFΤ¨GDäz¦kŮPœġq˚¥À]€Ÿ˜eŽâÚ´ªKxī„Pˆ—Ö|æ[xäJÞĥ‚s’NÖ½ž€I†¬nĨY´®Ð—ƐŠ€mD™ŝuäđđEb…e’e_™v¡}ìęNJē}q”É埁T¯µRs¡M@}ůa†a­¯wvƉåZwž\\Z{åû^›" - ] - ], - "encodeOffsets": [[[108815, 30935]], [[110617, 31811]]] - } - }, - { - "type": "Feature", - "id": "520000", - "properties": { - "id": "520000", - "cp": [106.713478, 26.578343], - "name": "贵州", - "childNum": 3 - }, - "geometry": { - "type": "MultiPolygon", - "coordinates": [ - ["@@†G\\†lY£‘in"], - ["@@q‚|ˆ‚mc¯tχVSÎ"], - [ - "@@hÑ£Is‡NgßH†›HªķÃh_¹ƒ¡ĝħń¦uيùŽgS¯JHŸ|sÝÅtÁïyMDč»eÕtA¤{b\\}—ƒG®u\\åPFq‹wÅaD…žK°ºâ_£ùbµ”mÁ‹ÛœĹM[q|hlaªāI}тƒµ@swtwm^oµˆD鼊yV™ky°ÉžûÛR…³‚‡eˆ‡¥]RՋěħ[ƅåÛDpŒ”J„iV™™‰ÂF²I…»mN·£›LbÒYb—WsÀbŽ™pki™TZĄă¶HŒq`……ĥ_JŸ¯ae«ƒKpÝx]aĕÛPƒÇȟ[ÁåŵÏő—÷Pw}‡TœÙ@Õs«ĿÛq©½œm¤ÙH·yǥĘĉBµĨÕnđ]K„©„œá‹ŸG纍§Õßg‡ǗĦTèƤƺ{¶ÉHÎd¾ŚÊ·OÐjXWrãLyzÉAL¾ę¢bĶėy_qMĔąro¼hĊžw¶øV¤w”²Ĉ]ʚKx|`ź¦ÂÈdr„cȁbe¸›`I¼čTF´¼Óýȃr¹ÍJ©k_șl³´_pН`oÒh޶pa‚^ÓĔ}D»^Xyœ`d˜[Kv…JPhèhCrĂĚÂ^Êƌ wˆZL­Ġ£šÁbrzOIl’MM”ĪŐžËr×ÎeŦŽtw|Œ¢mKjSǘňĂStÎŦEtqFT†¾†E쬬ôxÌO¢Ÿ KгŀºäY†„”PVgŎ¦Ŋm޼VZwVlŒ„z¤…ž£Tl®ctĽÚó{G­A‡ŒÇgeš~Αd¿æaSba¥KKûj®_ć^\\ؾbP®¦x^sxjĶI_Ä X‚⼕Hu¨Qh¡À@Ëô}ޱžGNìĎlT¸ˆ…`V~R°tbÕĊ`¸úÛtπFDu€[ƒMfqGH·¥yA‰ztMFe|R‚_Gk†ChZeÚ°to˜v`x‹b„ŒDnÐ{E}šZ˜è€x—†NEފREn˜[Pv@{~rĆAB§‚EO¿|UZ~ì„Uf¨J²ĂÝÆ€‚sª–B`„s¶œfvö¦ŠÕ~dÔq¨¸º»uù[[§´sb¤¢zþFœ¢Æ…Àhˆ™ÂˆW\\ıŽËI݊o±ĭŠ£þˆÊs}¡R]ŒěƒD‚g´VG¢‚j±®è†ºÃmpU[Á›‘Œëº°r›ÜbNu¸}Žº¼‡`ni”ºÔXĄ¤¼Ôdaµ€Á_À…†ftQQgœR—‘·Ǔ’v”}Ýלĵ]µœ“Wc¤F²›OĩųãW½¯K‚©…]€{†LóµCIµ±Mß¿hŸ•©āq¬o‚½ž~@i~TUxŪÒ¢@ƒ£ÀEîôruń‚”“‚b[§nWuMÆLl¿]x}ij­€½" - ] - ], - "encodeOffsets": [[[112158, 27383]], [[112105, 27474]], [[112095, 27476]]] - } - }, - { - "type": "Feature", - "id": "530000", - "properties": { - "id": "530000", - "cp": [101.512251, 24.740609], - "name": "云南", - "childNum": 1 - }, - "geometry": { - "type": "Polygon", - "coordinates": [ - "@@[„ùx½}ÑRH‘YīĺûsÍn‘iEoã½Ya²ė{c¬ĝg•ĂsA•ØÅwď‚õzFjw}—«Dx¿}UũlŸê™@•HÅ­F‰¨ÇoJ´Ónũuą¡Ã¢pÒŌ“Ø TF²‚xa²ËX€‚cʋlHîAßËŁkŻƑŷÉ©h™W­æßU‡“Ës¡¦}•teèÆ¶StǀÇ}Fd£j‹ĈZĆÆ‹¤T‚č\\Dƒ}O÷š£Uˆ§~ŃG™‚åŃDĝ¸œTsd¶¶Bªš¤u¢ŌĎo~t¾ÍŶÒtD¦Ú„iôö‰€z›ØX²ghįh½Û±¯€ÿm·zR¦Ɵ`ªŊÃh¢rOԍ´£Ym¼èêf¯ŪĽn„†cÚbŒw\\zlvWžªâˆ ¦g–mĿBş£¢ƹřbĥkǫßeeZkÙIKueT»sVesb‘aĕ  ¶®dNœĄÄpªyސ¼—„³BE˜®l‡ŽGœŭCœǶwêżĔÂe„pÍÀQƞpC„–¼ŲÈ­AÎô¶R„ä’Q^Øu¬°š_Èôc´¹ò¨P΢hlϦ´Ħ“Æ´sâDŽŲPnÊD^¯°’Upv†}®BP̪–jǬx–Söwlfòªv€qĸ|`H€­viļ€ndĜ­Ćhň•‚em·FyށqóžSᝑ³X_ĞçêtryvL¤§z„¦c¦¥jnŞk˜ˆlD¤øz½ĜàžĂŧMÅ|áƆàÊcðÂF܎‚áŢ¥\\\\º™İøÒÐJĴ‡„îD¦zK²ǏÎEh~’CD­hMn^ÌöÄ©ČZÀžaü„fɭyœpį´ěFűk]Ôě¢qlÅĆÙa¶~Äqššê€ljN¬¼H„ÊšNQ´ê¼VظE††^ŃÒyŒƒM{ŒJLoÒœęæŸe±Ķ›y‰’‡gã“¯JYÆĭĘëo¥Š‰o¯hcK«z_pŠrC´ĢÖY”—¼ v¸¢RŽÅW³Â§fǸYi³xR´ďUˊ`êĿU„û€uĆBƒƣö‰N€DH«Ĉg†——Ñ‚aB{ÊNF´¬c·Åv}eÇÃGB»”If•¦HňĕM…~[iwjUÁKE•Ž‹¾dĪçW›šI‹èÀŒoÈXòyŞŮÈXâÎŚŠj|àsRy‹µÖ›–Pr´þŒ ¸^wþTDŔ–Hr¸‹žRÌmf‡żÕâCôox–ĜƌÆĮŒ›Ð–œY˜tâŦÔ@]ÈǮƒ\\μģUsȯLbîƲŚºyh‡rŒŠ@ĒԝƀŸÀ²º\\êp“’JŠ}ĠvŠqt„Ġ@^xÀ£È†¨mËÏğ}n¹_¿¢×Y_æpˆÅ–A^{½•Lu¨GO±Õ½ßM¶w’ÁĢۂP‚›Ƣ¼pcIJxŠ|ap̬HšÐŒŊSfsðBZ¿©“XÏÒK•k†÷Eû¿‰S…rEFsÕūk”óVǥʼniTL‚¡n{‹uxţÏh™ôŝ¬ğōN“‘NJkyPaq™Âğ¤K®‡YŸxÉƋÁ]āęDqçgOg†ILu—\\_gz—]W¼ž~CÔē]bµogpў_oď`´³Țkl`IªºÎȄqÔþž»E³ĎSJ»œ_f·‚adÇqƒÇc¥Á_Źw{™L^ɱćx“U£µ÷xgĉp»ĆqNē`rĘzaĵĚ¡K½ÊBzyäKXqiWPÏɸ½řÍcÊG|µƕƣG˛÷Ÿk°_^ý|_zċBZocmø¯hhcæ\\lˆMFlư£Ĝ„ÆyH“„F¨‰µêÕ]—›HA…àӄ^it `þßäkŠĤÎT~Wlÿ¨„ÔPzUC–NVv [jâôDôď[}ž‰z¿–msSh‹¯{jïğl}šĹ[–őŒ‰gK‹©U·µË@¾ƒm_~q¡f¹…ÅË^»‘f³ø}Q•„¡Ö˳gͱ^ǁ…\\ëÃA_—¿bW›Ï[¶ƛ鏝£F{īZgm@|kHǭƁć¦UĔťƒ×ë}ǝƒeďºȡȘÏíBə£āĘPªij¶“ʼnÿ‡y©n‰ď£G¹¡I›Š±LÉĺÑdĉ܇W¥˜‰}g˜Á†{aqÃ¥aŠıęÏZ—ï`" - ], - "encodeOffsets": [[104636, 22969]] - } - }, - { - "type": "Feature", - "id": "540000", - "properties": { "id": "540000", "cp": [89.132212, 30.860361], "name": "西藏", "childNum": 1 }, - "geometry": { - "type": "Polygon", - "coordinates": [ - "@@hžľxŽŖ‰xƒÒVކºÅâAĪÝȆµę¯Ňa±r_w~uSÕň‘qOj]ɄQ…£Z……UDûoY’»©M[‹L¼qãË{V͕çWViŽ]ë©Ä÷àyƛh›ÚU°ŒŒa”d„cQƒ~Mx¥™cc¡ÙaSyF—ցk­ŒuRýq¿Ôµ•QĽ³aG{¿FµëªéĜÿª@¬·–K‰·àariĕĀ«V»Ŷ™Ĵū˜gèLǴŇƶaf‹tŒèBŚ£^Šâ†ǐÝ®–šM¦ÁǞÿ¬LhŸŽJ¾óƾƺcxw‹f]Y…´ƒ¦|œQLn°aœdĊ…œ\\¨o’œǀÍŎœ´ĩĀd`tÊQŞŕ|‚¨C^©œĈ¦„¦ÎJĊ{ŽëĎjª²rЉšl`¼Ą[t|¦St辉PŒÜK¸€d˜Ƅı]s¤—î_v¹ÎVòŦj˜£Əsc—¬_Ğ´|٘¦Avަw`ăaÝaa­¢e¤ı²©ªSªšÈMĄwžÉØŔì@T‘¤—Ę™\\õª@”þo´­xA s”ÂtŎKzó´ÇĊµ¢rž^nĊ­Æ¬×üGž¢‚³ {âĊ]š™G‚~bÀgVjzlhǶf€žOšfdЉªB]pj„•TO–tĊ‚n¤}®¦ƒČ¥d¢¼»ddš”Y¼Žt—¢eȤJ¤}Ǿ¡°§¤AГlc@ĝ”sªćļđAç‡wx•UuzEÖġ~AN¹ÄÅȀݦ¿ģŁéì±H…ãd«g[؉¼ēÀ•cīľġ¬cJ‘µ…ÐʥVȝ¸ßS¹†ý±ğkƁ¼ą^ɛ¤Ûÿ‰b[}¬ōõÃ]ËNm®g@•Bg}ÍF±ǐyL¥íCˆƒIij€Ï÷њį[¹¦[⚍EÛïÁÉdƅß{âNÆāŨߝ¾ě÷yC£‡k­´ÓH@¹†TZ¥¢įƒ·ÌAЧ®—Zc…v½ŸZ­¹|ŕWZqgW“|ieZÅYVӁqdq•bc²R@†c‡¥Rã»Ge†ŸeƃīQ•}J[ғK…¬Ə|o’ėjġĠÑN¡ð¯EBčnwôɍėªƒ²•CλŹġǝʅįĭạ̃ūȹ]ΓͧgšsgȽóϧµǛ†ęgſ¶ҍć`ĘąŌJޚä¤rÅň¥ÖÁUětęuůÞiĊÄÀ\\Æs¦ÓRb|Â^řÌkÄŷ¶½÷‡f±iMݑ›‰@ĥ°G¬ÃM¥n£Øą‚ğ¯ß”§aëbéüÑOčœk£{\\‘eµª×M‘šÉfm«Ƒ{Å׃Gŏǩãy³©WÑăû‚··‘Q—òı}¯ã‰I•éÕÂZ¨īès¶ZÈsŽæĔTŘvŽgÌsN@îá¾ó@‰˜ÙwU±ÉT廣TđŸWxq¹Zo‘b‹s[׌¯cĩv‡Œėŧ³BM|¹k‰ªħ—¥TzNYnݍßpęrñĠĉRS~½ŠěVVе‚õ‡«ŒM££µB•ĉ¥áºae~³AuĐh`Ü³ç@BۘïĿa©|z²Ý¼D”£à貋ŸƒIƒû›I ā€óK¥}rÝ_Á´éMaň¨€~ªSĈ½Ž½KÙóĿeƃÆBŽ·¬ën×W|Uº}LJrƳ˜lŒµ`bÔ`QˆˆÐÓ@s¬ñIŒÍ@ûws¡åQÑßÁ`ŋĴ{Ī“T•ÚÅTSij‚‹Yo|Ç[ǾµMW¢ĭiÕØ¿@˜šMh…pÕ]j†éò¿OƇĆƇp€êĉâlØw–ěsˆǩ‚ĵ¸c…bU¹ř¨WavquSMzeo_^gsÏ·¥Ó@~¯¿RiīB™Š\\”qTGªÇĜçPoŠÿfñòą¦óQīÈáP•œābß{ƒZŗĸIæÅ„hnszÁCËìñšÏ·ąĚÝUm®ó­L·ăU›Èíoù´Êj°ŁŤ_uµ^‘°Œìǖ@tĶĒ¡Æ‡M³Ģ«˜İĨÅ®ğ†RŽāð“ggheÆ¢z‚Ê©Ô\\°ÝĎz~ź¤Pn–MĪÖB£Ÿk™n鄧żćŠ˜ĆK„ǰ¼L¶è‰âz¨u¦¥LDĘz¬ýÎmĘd¾ß”Fz“hg²™Fy¦ĝ¤ċņbΛ@y‚Ąæm°NĮZRÖíŽJ²öLĸÒ¨Y®ƌÐV‰à˜tt_ڀÂyĠzž]Ţh€zĎ{†ĢX”ˆc|šÐqŽšfO¢¤ög‚ÌHNŽ„PKŖœŽ˜Uú´xx[xˆvĐCûŠìÖT¬¸^}Ìsòd´_އKgžLĴ…ÀBon|H@–Êx˜—¦BpŰˆŌ¿fµƌA¾zLjRxжF”œkĄźRzŀˆ~¶[”´Hnª–VƞuĒ­È¨ƎcƽÌm¸ÁÈM¦x͊ëÀxdžB’šú^´W†£–d„kɾĬpœw‚˂ØɦļĬIŚœÊ•n›Ŕa¸™~J°î”lɌxĤÊÈðhÌ®‚g˜T´øŽàCˆŽÀ^ªerrƘdž¢İP|Ė ŸWœªĦ^¶´ÂL„aT±üWƜ˜ǀRšŶUńšĖ[QhlLüA†‹Ü\\†qR›Ą©" - ], - "encodeOffsets": [[90849, 37210]] - } - }, - { - "type": "Feature", - "id": "610000", - "properties": { - "id": "610000", - "cp": [108.948024, 34.263161], - "name": "陕西", - "childNum": 1 - }, - "geometry": { - "type": "Polygon", - "coordinates": [ - "@@˜p¢—ȮµšûG™Ħ}Ħšðǚ¶òƄ€jɂz°{ºØkÈęâ¦jª‚Bg‚\\œċ°s¬Ž’]jžú ‚E”Ȍdž¬s„t‡”RˆÆdĠݎwܔ¸ôW¾ƮłÒ_{’Ìšû¼„jº¹¢GǪÒ¯ĘƒZ`ºŊƒecņąš~BÂgzpâēòYǠȰÌTΨÂWœ|fcŸă§uF—Œ@NŸ¢XLƒŠRMº[ğȣſï|¥J™kc`sʼnǷ’Y¹‹W@µ÷K…ãï³ÛIcñ·VȋڍÒķø©—þ¥ƒy‚ÓŸğęmWµÎumZyOŅƟĥÓ~sÑL¤µaŅY¦ocyZ{‰y c]{ŒTa©ƒ`U_Ěē£ωÊƍKù’K¶ȱÝƷ§{û»ÅÁȹÍéuij|¹cÑd‘ŠìUYƒŽO‘uF–ÕÈYvÁCqӃT•Ǣí§·S¹NgŠV¬ë÷Át‡°Dد’C´ʼnƒópģ}„ċcE˅FŸŸéGU¥×K…§­¶³B‹Č}C¿åċ`wġB·¤őcƭ²ő[Å^axwQO…ÿEËߌ•ĤNĔŸwƇˆÄŠńwĪ­Šo[„_KÓª³“ÙnK‰Çƒěœÿ]ď€ă_d©·©Ýŏ°Ù®g]±„Ÿ‡ß˜å›—¬÷m\\›iaǑkěX{¢|ZKlçhLt€Ňîŵ€œè[€É@ƉĄEœ‡tƇÏ˜³­ħZ«mJ…›×¾‘MtÝĦ£IwÄå\\Õ{‡˜ƒOwĬ©LÙ³ÙgBƕŀr̛ĢŭO¥lãyC§HÍ£ßEñŸX¡—­°ÙCgpťz‘ˆb`wI„vA|§”‡—hoĕ@E±“iYd¥OϹS|}F@¾oAO²{tfžÜ—¢Fǂ҈W²°BĤh^Wx{@„¬‚­F¸¡„ķn£P|ŸªĴ@^ĠĈæb–Ôc¶l˜Yi…–^Mi˜cϰÂ[ä€vï¶gv@À“Ĭ·lJ¸sn|¼u~a]’ÆÈtŌºJp’ƒþ£KKf~ЦUbyäIšĺãn‡Ô¿^­žŵMT–hĠܤko¼Ŏìąǜh`[tŒRd²IJ_œXPrɲ‰l‘‚XžiL§àƒ–¹ŽH˜°Ȧqº®QC—bA†„ŌJ¸ĕÚ³ĺ§ `d¨YjžiZvRĺ±öVKkjGȊĐePОZmļKÀ€‚[ŠŽ`ösìh†ïÎoĬdtKÞ{¬èÒÒBŒÔpIJÇĬJŊ¦±J«ˆY§‹@·pH€µàåVKe›pW†ftsAÅqC·¬ko«pHÆuK@oŸHĆۄķhx“e‘n›S³àǍrqƶRbzy€¸ËАl›¼EºpĤ¼Œx¼½~Ğ’”à@†ÚüdK^ˆmÌSj" - ], - "encodeOffsets": [[110234, 38774]] - } - }, - { - "type": "Feature", - "id": "620000", - "properties": { - "id": "620000", - "cp": [103.823557, 36.058039], - "name": "甘肃", - "childNum": 2 - }, - "geometry": { - "type": "MultiPolygon", - "coordinates": [ - ["@@VuUv"], - [ - "@@ũ‹EĠtt~nkh`Q‰¦ÅÄÜdw˜Ab×ĠąJˆ¤DüègĺqBqœj°lI¡ĨÒ¤úSHbš‡ŠjΑBаaZˆ¢KJŽ’O[|A£žDx}Nì•HUnrk„ kp€¼Y kMJn[aG‚áÚÏ[½rc†}aQxOgsPMnUs‡nc‹Z…ž–sKúvA›t„Þġ’£®ĀYKdnFwš¢JE°”Latf`¼h¬we|€Æ‡šbj}GA€·~WŽ”—`†¢MC¤tL©IJ°qdf”O‚“bÞĬ¹ttu`^ZúE`Œ[@„Æsîz®¡’C„ƳƜG²“R‘¢R’m”fŽwĸg܃‚ą G@pzJM½mŠhVy¸uÈÔO±¨{LfæU¶ßGĂq\\ª¬‡²I‚¥IʼnÈīoı‹ÓÑAçÑ|«LÝcspīðÍg…të_õ‰\\ĉñLYnĝg’ŸRǡÁiHLlõUĹ²uQjYi§Z_c¨Ÿ´ĹĖÙ·ŋI…ƒaBD˜­R¹ȥr—¯G•ºß„K¨jWk’ɱŠOq›Wij\\a­‹Q\\sg_ĆǛōëp»£lğۀgS•ŶN®À]ˆÓäm™ĹãJaz¥V}‰Le¤L„ýo‘¹IsŋÅÇ^‘Žbz…³tmEÁ´aйcčecÇN•ĊãÁ\\蝗dNj•]j†—ZµkÓda•ćå]ğij@ ©O{¤ĸm¢ƒE·®ƒ«|@Xwg]A챝‡XǁÑdzªc›wQÚŝñsÕ³ÛV_ýƒ˜¥\\ů¥©¾÷w—Ž©WÕÊĩhÿÖÁRo¸V¬âDb¨šhûx–Ê×nj~Zâƒg|šXÁnßYoº§ZÅŘvŒ[„ĭÖʃuďxcVbnUSf…B¯³_Tzº—ΕO©çMÑ~Mˆ³]µ^püµ”ŠÄY~y@X~¤Z³€[Èōl@®Å¼£QKƒ·Di‹¡By‘ÿ‰Q_´D¥hŗyƒ^ŸĭÁZ]cIzý‰ah¹MĪğP‘s{ò‡‹‘²Vw¹t³Ŝˁ[ŽÑ}X\\gsFŸ£sPAgěp×ëfYHāďÖqēŭOÏë“dLü•\\iŒ”t^c®šRʺ¶—¢H°mˆ‘rYŸ£BŸ¹čIoľu¶uI]vģSQ{ƒUŻ”Å}QÂ|̋°ƅ¤ĩŪU ęĄžÌZҞ\\v˜²PĔ»ƢNHƒĂyAmƂwVmž`”]ȏb•”H`‰Ì¢²ILvĜ—H®¤Dlt_„¢JJÄämèÔDëþgºƫ™”aʎÌrêYi~ ÎݤNpÀA¾Ĕ¼b…ð÷’Žˆ‡®‚”üs”zMzÖĖQdȨý†v§Tè|ªH’þa¸|šÐ ƒwKĢx¦ivr^ÿ ¸l öæfƟĴ·PJv}n\\h¹¶v†·À|\\ƁĚN´Ĝ€çèÁz]ġ¤²¨QÒŨTIl‡ªťØ}¼˗ƦvÄùØE‹’«Fï˛Iq”ōŒTvāÜŏ‚íÛߜÛV—j³âwGăÂíNOŠˆŠPìyV³ʼnĖýZso§HіiYw[߆\\X¦¥c]ÔƩÜ·«j‡ÐqvÁ¦m^ċ±R™¦΋ƈťĚgÀ»IïĨʗƮްƝ˜ĻþÍAƉſ±tÍEÕÞāNU͗¡\\ſčåÒʻĘm ƭÌŹöʥ’ëQ¤µ­ÇcƕªoIýˆ‰Iɐ_mkl³ă‰Ɠ¦j—¡Yz•Ňi–}Msßõ–īʋ —}ƒÁVmŸ_[n}eı­Uĥ¼‘ª•I{ΧDӜƻėoj‘qYhĹT©oūĶ£]ďxĩ‹ǑMĝ‰q`B´ƃ˺Ч—ç~™²ņj@”¥@đ´ί}ĥtPńǾV¬ufӃÉC‹tÓ̻‰…¹£G³€]ƖƾŎĪŪĘ̖¨ʈĢƂlɘ۪üºňUðǜȢƢż̌ȦǼ‚ĤŊɲĖ­Kq´ï¦—ºĒDzņɾªǀÞĈĂD†½ĄĎÌŗĞrôñnŽœN¼â¾ʄľԆ|DŽŽ֦ज़ȗlj̘̭ɺƅêgV̍ʆĠ·ÌĊv|ýĖÕWĊǎÞ´õ¼cÒÒBĢ͢UĜð͒s¨ňƃLĉÕÝ@ɛƯ÷¿Ľ­ĹeȏijëCȚDŲyê×Ŗyò¯ļcÂßY…tÁƤyAã˾J@ǝrý‹‰@¤…rz¸oP¹ɐÚyᐇHŸĀ[Jw…cVeȴϜ»ÈŽĖ}ƒŰŐèȭǢόĀƪÈŶë;Ñ̆ȤМľĮEŔ—ĹŊũ~ËUă{ŸĻƹɁύȩþĽvĽƓÉ@ē„ĽɲßǐƫʾǗĒpäWÐxnsÀ^ƆwW©¦cÅ¡Ji§vúF¶Ž¨c~c¼īŒeXǚ‹\\đ¾JŽwÀďksãA‹fÕ¦L}wa‚o”Z’‹D½†Ml«]eÒÅaɲáo½FõÛ]ĻÒ¡wYR£¢rvÓ®y®LF‹LzĈ„ôe]gx}•|KK}xklL]c¦£fRtív¦†PĤoH{tK" - ] - ], - "encodeOffsets": [[[108619, 36299]], [[108589, 36341]]] - } - }, - { - "type": "Feature", - "id": "630000", - "properties": { "id": "630000", "cp": [96.778916, 35.623178], "name": "青海", "childNum": 2 }, - "geometry": { - "type": "MultiPolygon", - "coordinates": [ - ["@@InJm"], - [ - "@@CƒÆ½OŃĦsΰ~dz¦@@“Ņiš±è}ؘƄ˹A³r_ĞŠǒNΌĐw¤^ŬĵªpĺSZg’rpiƼĘԛ¨C|͖J’©Ħ»®VIJ~f\\m `Un„˜~ʌŸ•ĬàöNt•~ňjy–¢Zi˜Ɣ¥ĄŠk´nl`JʇŠJþ©pdƖ®È£¶ìRʦ‘źõƮËnŸʼėæÑƀĎ[‚˜¢VÎĂMÖÝÎF²sƊƀÎBļýƞ—¯ʘƭðħ¼Jh¿ŦęΌƇš¥²Q]Č¥nuÂÏriˆ¸¬ƪÛ^Ó¦d€¥[Wà…x\\ZŽjҕ¨GtpþYŊĕ´€zUO뇉P‰îMĄÁxH´á˜iÜUà›îÜՁĂÛSuŎ‹r“œJð̬EŒ‘FÁú×uÃÎkr“Ē{V}İ«O_ÌËĬ©ŽÓŧSRѱ§Ģ£^ÂyèçěM³Ƃę{[¸¿u…ºµ[gt£¸OƤĿéYŸõ·kŸq]juw¥Dĩƍ€õÇPéĽG‘ž©ã‡¤G…uȧþRcÕĕNy“yût“ˆ­‡ø‘†ï»a½ē¿BMoᣟÍj}éZËqbʍš“Ƭh¹ìÿÓAçãnIáI`ƒks£CG­ě˜Uy×Cy•…’Ÿ@¶ʡÊBnāzG„ơMē¼±O÷õJËĚăVŸĪũƆ£Œ¯{ËL½Ìzż“„VR|ĠTbuvJvµhĻĖH”Aëáa…­OÇðñęNw‡…œľ·L›mI±íĠĩPÉ×®ÿs—’cB³±JKßĊ«`…ađ»·QAmO’‘Vţéÿ¤¹SQt]]Çx€±¯A@ĉij¢Ó祖•ƒl¶ÅÛr—ŕspãRk~¦ª]Į­´“FR„åd­ČsCqđéFn¿Åƃm’Éx{W©ºƝºįkÕƂƑ¸wWūЩÈFž£\\tÈ¥ÄRÈýÌJ ƒlGr^×äùyÞ³fj”c†€¨£ÂZ|ǓMĝšÏ@ëÜőR‹›ĝ‰Œ÷¡{aïȷPu°ËXÙ{©TmĠ}Y³’­ÞIňµç½©C¡į÷¯B»|St»›]vƒųƒs»”}MÓ ÿʪƟǭA¡fs˜»PY¼c¡»¦c„ċ­¥£~msĉP•–Siƒ^o©A‰Šec‚™PeǵŽkg‚yUi¿h}aH™šĉ^|ᴟ¡HØûÅ«ĉ®]m€¡qĉ¶³ÈyôōLÁst“BŸ®wn±ă¥HSò뚣˜S’ë@לÊăxÇN©™©T±ª£IJ¡fb®ÞbŽb_Ą¥xu¥B—ž{łĝ³«`d˜Ɛt—¤ťiñžÍUuºí`£˜^tƃIJc—·ÛLO‹½Šsç¥Ts{ă\\_»™kϊ±q©čiìĉ|ÍIƒ¥ć¥›€]ª§D{ŝŖÉR_sÿc³Īō›ƿΑ›§p›[ĉ†›c¯bKm›R¥{³„Z†e^ŽŒwx¹dƽŽôIg §Mĕ ƹĴ¿—ǣÜ̓]‹Ý–]snåA{‹eŒƭ`ǻŊĿ\\ijŬű”YÂÿ¬jĖqŽßbЏ•L«¸©@ěĀ©ê¶ìÀEH|´bRľž–Ó¶rÀQþ‹vl®Õ‚E˜TzÜdb ˜hw¤{LR„ƒd“c‹b¯‹ÙVgœ‚ƜßzÃô쮍^jUèXΖ|UäÌ»rKŽ\\ŒªN‘¼pZCü†VY††¤ɃRi^rPҒTÖ}|br°qňb̰ªiƶGQ¾²„x¦PœmlŜ‘[Ĥ¡ΞsĦŸÔÏâ\\ªÚŒU\\f…¢N²§x|¤§„xĔsZPòʛ²SÐqF`ª„VƒÞŜĶƨVZŒÌL`ˆ¢dŐIqr\\oäõ–F礻Ŷ×h¹]Clـ\\¦ďÌį¬řtTӺƙgQÇÓHţĒ”´ÃbEÄlbʔC”|CˆŮˆk„Ʈ[ʼ¬ňœ´KŮÈΰÌζƶlð”ļA†TUvdTŠG†º̼ŠÔ€ŒsÊDԄveOg" - ] - ], - "encodeOffsets": [[[105308, 37219]], [[95370, 40081]]] - } - }, - { - "type": "Feature", - "id": "640000", - "properties": { "id": "640000", "cp": [106.278179, 37.26637], "name": "宁夏", "childNum": 2 }, - "geometry": { - "type": "MultiPolygon", - "coordinates": [ - [ - "@@KëÀęĞ«OęȿȕŸı]ʼn¡åįÕÔ«Ǵõƪ™ĚQÐZhv K°›öqÀѐS[ÃÖHƖčË‡nL]ûc…Ùß@‚“ĝ‘¾}w»»‹oģF¹œ»kÌÏ·{zPƒ§B­¢íyÅt@ƒ@áš]Yv_ssģ¼i߁”ĻL¾ġsKD£¡N_…“˜X¸}B~Haiˆ™Åf{«x»ge_bs“KF¯¡Ix™mELcÿZ¤­Ģ‘ƒÝœsuBLù•t†ŒYdˆmVtNmtOPhRw~bd…¾qÐ\\âÙH\\bImlNZŸ»loƒŸqlVm–Gā§~QCw¤™{A\\‘PKŸNY‡¯bF‡kC¥’sk‹Šs_Ã\\ă«¢ħkJi¯r›rAhĹûç£CU‡ĕĊ_ԗBixÅُĄnªÑaM~ħpOu¥sîeQ¥¤^dkKwlL~{L~–hw^‚ófćƒKyEŒ­K­zuÔ¡qQ¤xZÑ¢^ļöܾEpž±âbÊÑÆ^fk¬…NC¾‘Œ“YpxbK~¥Že֎ŒäBlt¿Đx½I[ĒǙŒWž‹f»Ĭ}d§dµùEuj¨‚IÆ¢¥dXªƅx¿]mtÏwßR͌X¢͎vÆzƂZò®ǢÌʆCrâºMÞzžÆMҔÊÓŊZľ–r°Î®Ȉmª²ĈUªĚøºˆĮ¦ÌĘk„^FłĬhĚiĀ˾iİbjÕ" - ], - ["@@mfwěwMrŢªv@G‰"] - ], - "encodeOffsets": [[[109366, 40242]], [[108600, 36303]]] - } - }, - { - "type": "Feature", - "id": "650000", - "properties": { "id": "650000", "cp": [85.617733, 40.792818], "name": "新疆", "childNum": 1 }, - "geometry": { - "type": "Polygon", - "coordinates": [ - "@@QØĔ²X¨”~ǘBºjʐߨvK”ƔX¨vĊOžÃƒ·¢i@~c—‡ĝe_«”Eš“}QxgɪëÏÃ@sÅyXoŖ{ô«ŸuX…ê•Îf`œC‚¹ÂÿÐGĮÕĞXŪōŸMźÈƺQèĽôe|¿ƸJR¤ĘEjcUóº¯Ĩ_ŘÁMª÷Ð¥Oéȇ¿ÖğǤǷÂF҇zÉx[]­Ĥĝ‰œ¦EP}ûƥé¿İƷTėƫœŕƅ™ƱB»Đ±’ēO…¦E–•}‘`cȺrĦáŖuҞª«IJ‡πdƺÏØZƴwʄ¤ĖGЙǂZ̓èH¶}ÚZצʥĪï|ÇĦMŔ»İĝLj‹ì¥Βœba­¯¥ǕǚkĆŵĦɑĺƯxūД̵nơʃĽá½M»›òmqóŘĝč˾ăC…ćāƿÝɽ©DZŅ¹đ¥˜³ðLrÁ®ɱĕģʼnǻ̋ȥơŻǛȡVï¹Ň۩ûkɗġƁ§ʇė̕ĩũƽō^ƕŠUv£ƁQï“Ƶkŏ½ΉÃŭdzLқʻ«ƭ\\lƒ‡ŭD‡“{ʓDkaFÃÄa“³ŤđÔGRÈƚhSӹŚsİ«ĐË[¥ÚDkº^Øg¼ŵ¸£EÍö•€ůʼnT¡c_‡ËKY‹ƧUśĵ„݃U_©rETÏʜ±OñtYw獃{£¨uM³x½şL©Ùá[ÓÐĥ Νtģ¢\\‚ś’nkO›w¥±ƒT»ƷFɯàĩÞáB¹Æ…ÑUw„੍žĽw[“mG½Èå~‡Æ÷QyŠěCFmĭZī—ŵVÁ™ƿQƛ—ûXS²‰b½KϽĉS›©ŷXĕŸ{ŽĕK·¥Ɨcqq©f¿]‡ßDõU³h—­gËÇïģÉɋw“k¯í}I·šœbmœÉ–ř›īJɥĻˁ×xo›ɹī‡l•c…¤³Xù]‘™DžA¿w͉ì¥wÇN·ÂËnƾƍdǧđ®Ɲv•Um©³G\\“}µĿ‡QyŹl㓛µEw‰LJQ½yƋBe¶ŋÀů‡ož¥A—˜Éw@•{Gpm¿Aij†ŽKLhˆ³`ñcËtW‚±»ÕS‰ëüÿďD‡u\\wwwù³—V›LŕƒOMËGh£õP¡™er™Ïd{“‡ġWÁ…č|yšg^ğyÁzÙs`—s|ÉåªÇ}m¢Ń¨`x¥’ù^•}ƒÌ¥H«‰Yªƅ”Aйn~Ꝛf¤áÀz„gŠÇDIԝ´AňĀ҄¶ûEYospõD[{ù°]u›Jq•U•|Soċxţ[õÔĥkŋÞŭZ˺óYËüċrw €ÞkrťË¿XGÉbřaDü·Ē÷Aê[Ää€I®BÕИÞ_¢āĠpŠÛÄȉĖġDKwbm‡ÄNô‡ŠfœƫVÉvi†dz—H‘‹QµâFšù­Âœ³¦{YGžƒd¢ĚÜO „€{Ö¦ÞÍÀPŒ^b–ƾŠlŽ[„vt×ĈÍE˨¡Đ~´î¸ùÎh€uè`¸ŸHÕŔVºwĠââWò‡@{œÙNÝ´ə²ȕn{¿¥{l—÷eé^e’ďˆXj©î\\ªÑò˜Üìc\\üqˆÕ[Č¡xoÂċªbØ­Œø|€¶ȴZdÆÂšońéŒGš\\”¼C°ÌƁn´nxšÊOĨ’ہƴĸ¢¸òTxÊǪMīИÖŲÃɎOvˆʦƢ~FއRěò—¿ġ~åŊœú‰Nšžš¸qŽ’Ę[Ĕ¶ÂćnÒPĒÜvúĀÊbÖ{Äî¸~Ŕünp¤ÂH¾œĄYÒ©ÊfºmԈĘcDoĬMŬ’˜S¤„s²‚”ʘچžȂVŦ –ŽèW°ªB|IJXŔþÈJĦÆæFĚêŠYĂªĂ]øªŖNÞüA€’fɨJ€˜¯ÎrDDšĤ€`€mz\\„§~D¬{vJÂ˜«lµĂb–¤p€ŌŰNĄ¨ĊXW|ų ¿¾ɄĦƐMT”‡òP˜÷fØĶK¢ȝ˔Sô¹òEð­”`Ɩ½ǒÂň×äı–§ĤƝ§C~¡‚hlå‚ǺŦŞkâ’~}ŽFøàIJaĞ‚fƠ¥Ž„Ŕdž˜®U¸ˆźXœv¢aƆúŪtŠųƠjd•ƺŠƺÅìnrh\\ĺ¯äɝĦ]èpĄ¦´LƞĬŠ´ƤǬ˼Ēɸ¤rºǼ²¨zÌPðŀbþ¹ļD¢¹œ\\ĜÑŚŸ¶ZƄ³àjĨoâŠȴLʉȮŒĐ­ĚăŽÀêZǚŐ¤qȂ\\L¢ŌİfÆs|zºeªÙæ§΢{Ā´ƐÚ¬¨Ĵà²łhʺKÞºÖTŠiƢ¾ªì°`öøu®Ê¾ãØ" - ], - "encodeOffsets": [[88824, 50096]] - } - }, - { - "type": "Feature", - "id": "110000", - "properties": { - "id": "110000", - "cp": [116.405285, 39.904989], - "name": "北京", - "childNum": 1 - }, - "geometry": { - "type": "Polygon", - "coordinates": [ - "@@ĽOÁ›ûtŷmiÍt_H»Ĩ±d`й­{bw…Yr“³S]§§o¹€qGtm_Sŧ€“oa›‹FLg‘QN_•dV€@Zom_ć\\ߚc±x¯oœRcfe…£’o§ËgToÛJíĔóu…|wP¤™XnO¢ÉˆŦ¯rNÄā¤zâŖÈRpŢZŠœÚ{GŠrFt¦Òx§ø¹RóäV¤XdˆżâºWbwڍUd®bêņ¾‘jnŎGŃŶŠnzÚSeîĜZczî¾i]͜™QaúÍÔiþĩȨWĢ‹ü|Ėu[qb[swP@ÅğP¿{\\‡¥A¨Ï‘Ѩj¯ŠX\\¯œMK‘pA³[H…īu}}" - ], - "encodeOffsets": [[120023, 41045]] - } - }, - { - "type": "Feature", - "id": "120000", - "properties": { - "id": "120000", - "cp": [117.190182, 39.125596], - "name": "天津", - "childNum": 1 - }, - "geometry": { - "type": "Polygon", - "coordinates": [ - "@@ŬgX§Ü«E…¶Ḟ“¬O_™ïlÁg“z±AXe™µÄĵ{¶]gitgšIj·›¥îakS€‰¨ÐƎk}ĕ{gB—qGf{¿a†U^fI“ư‹³õ{YƒıëNĿžk©ïËZŏ‘R§òoY×Ógc…ĥs¡bġ«@dekąI[nlPqCnp{ˆō³°`{PNdƗqSÄĻNNâyj]äžÒD ĬH°Æ]~¡HO¾ŒX}ÐxŒgp“gWˆrDGˆŒpù‚Š^L‚ˆrzWxˆZ^¨´T\\|~@I‰zƒ–bĤ‹œjeĊªz£®Ĕvě€L†mV¾Ô_ȔNW~zbĬvG†²ZmDM~”~" - ], - "encodeOffsets": [[120237, 41215]] - } - }, - { - "type": "Feature", - "id": "310000", - "properties": { - "id": "310000", - "cp": [121.472644, 31.231706], - "name": "上海", - "childNum": 6 - }, - "geometry": { - "type": "MultiPolygon", - "coordinates": [ - ["@@ɧư¬EpƸÁxc‡"], - ["@@©„ªƒ"], - ["@@”MA‹‘š"], - ["@@Qp݁E§ÉC¾"], - ["@@bŝՕÕEȣÚƥêImɇǦèÜĠŒÚžÃƌÃ͎ó"], - ["@@ǜûȬɋŠŭ™×^‰sYŒɍDŋ‘ŽąñCG²«ªč@h–_p¯A{‡oloY€¬j@IJ`•gQڛhr|ǀ^MIJvtbe´R¯Ô¬¨YŽô¤r]ì†Ƭį"] - ], - "encodeOffsets": [ - [[124702, 32062]], - [[124547, 32200]], - [[124808, 31991]], - [[124726, 32110]], - [[124903, 32376]], - [[124438, 32149]] - ] - } - }, - { - "type": "Feature", - "id": "500000", - "properties": { - "id": "500000", - "cp": [107.304962, 29.533155], - "name": "重庆", - "childNum": 2 - }, - "geometry": { - "type": "MultiPolygon", - "coordinates": [ - [ - "@@vjG~nGŘŬĶȂƀƾ¹¸ØÎezĆT¸}êЖqHŸðqĖ䒊¥^CƒIj–²p…\\_ æüY|[YxƊæuž°xb®…Űb@~¢NQt°¶‚S栓Ê~rljĔëĚ¢~šuf`‘‚†fa‚ĔJåĊ„nÖ]„jƎćÊ@Š£¾a®£Ű{ŶĕF‹ègLk{Y|¡ĜWƔtƬJÑxq‹±ĢN´‰òK‰™–LÈüD|s`ŋ’ć]ƒÃ‰`đŒMûƱ½~Y°ħ`ƏíW‰½eI‹½{aŸ‘OIrÏ¡ĕŇa†p†µÜƅġ‘œ^ÖÛbÙŽŏml½S‹êqDu[R‹ãË»†ÿw`»y‘¸_ĺę}÷`M¯ċfCVµqʼn÷Z•gg“Œ`d½pDO‡ÎCnœ^uf²ènh¼WtƏxRGg¦…pV„†FI±ŽG^ŒIc´ec‡’G•ĹÞ½sëĬ„h˜xW‚}Kӈe­Xsbk”F¦›L‘ØgTkïƵNï¶}Gy“w\\oñ¡nmĈzjŸ•@™Óc£»Wă¹Ój“_m»ˆ¹·~MvÛaqœ»­‰êœ’\\ÂoVnŽÓØÍ™²«‹bq¿efE „€‹Ĝ^Qž~ Évý‡ş¤²Į‰pEİ}zcĺƒL‹½‡š¿gņ›¡ýE¡ya£³t\\¨\\vú»¼§·Ñr_oÒý¥u‚•_n»_ƒ•At©Þűā§IVeëƒY}{VPÀFA¨ąB}q@|Ou—\\Fm‰QF݅Mw˜å}]•€|FmϋCaƒwŒu_p—¯sfÙgY…DHl`{QEfNysBЦzG¸rHe‚„N\\CvEsÐùÜ_·ÖĉsaQ¯€}_U‡†xÃđŠq›NH¬•Äd^ÝŰR¬ã°wećJEž·vÝ·Hgƒ‚éFXjÉê`|yŒpxkAwœWĐpb¥eOsmzwqChóUQl¥F^laf‹anòsr›EvfQdÁUVf—ÎvÜ^efˆtET¬ôA\\œ¢sJŽnQTjP؈xøK|nBz‰„œĞ»LY‚…FDxӄvr“[ehľš•vN”¢o¾NiÂxGp⬐z›bfZo~hGi’]öF|‰|Nb‡tOMn eA±ŠtPT‡LjpYQ|†SH††YĀxinzDJ€Ìg¢và¥Pg‰_–ÇzII‹€II•„£®S¬„Øs쐣ŒN" - ], - ["@@ifjN@s"] - ], - "encodeOffsets": [[[109628, 30765]], [[111725, 31320]]] - } - }, - { - "type": "Feature", - "id": "810000", - "properties": { - "id": "810000", - "cp": [114.173355, 22.320048], - "name": "香港", - "childNum": 5 - }, - "geometry": { - "type": "MultiPolygon", - "coordinates": [ - ["@@AlBk"], - ["@@mŽn"], - ["@@EpFo"], - ["@@ea¢pl¸Eõ¹‡hj[ƒ]ÔCΖ@lj˜¡uBXŸ…•´‹AI¹…[‹yDUˆ]W`çwZkmc–…M›žp€Åv›}I‹oJlcaƒfёKްä¬XJmРđhI®æÔtSHn€Eˆ„ÒrÈc"], - ["@@rMUw‡AS®€e"] - ], - "encodeOffsets": [ - [[117111, 23002]], - [[117072, 22876]], - [[117045, 22887]], - [[116975, 23082]], - [[116882, 22747]] - ] - } - }, - { - "type": "Feature", - "id": "820000", - "properties": { "id": "820000", "cp": [113.54909, 22.198951], "name": "澳门", "childNum": 1 }, - "geometry": { - "type": "Polygon", - "coordinates": ["@@kÊd°å§s"], - "encodeOffsets": [[116279, 22639]] - } - } - ], - "UTF8Encoding": true -} diff --git a/src/views/demo/charts/data.ts b/src/views/demo/charts/data.ts deleted file mode 100644 index 3cf0f4a60..000000000 --- a/src/views/demo/charts/data.ts +++ /dev/null @@ -1,189 +0,0 @@ -export const mapData: any = [ - { - name: '北京', - value: Math.round(Math.random() * 1000), - tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)], - }, - { - name: '天津', - value: Math.round(Math.random() * 1000), - tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)], - }, - { - name: '上海', - value: Math.round(Math.random() * 1000), - tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)], - }, - { - name: '重庆', - value: Math.round(Math.random() * 1000), - tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)], - }, - { - name: '河北', - value: Math.round(Math.random() * 1000), - tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)], - }, - { - name: '河南', - value: Math.round(Math.random() * 1000), - tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)], - }, - { - name: '云南', - value: Math.round(Math.random() * 1000), - tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)], - }, - { - name: '辽宁', - value: Math.round(Math.random() * 1000), - tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)], - }, - { - name: '黑龙江', - value: Math.round(Math.random() * 1000), - tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)], - }, - { - name: '湖南', - value: Math.round(Math.random() * 1000), - tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)], - }, - { - name: '安徽', - value: Math.round(Math.random() * 1000), - tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)], - }, - { - name: '山东', - value: Math.round(Math.random() * 1000), - tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)], - }, - { - name: '新疆', - value: Math.round(Math.random() * 1000), - tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)], - }, - { - name: '江苏', - value: Math.round(Math.random() * 1000), - tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)], - }, - { - name: '浙江', - value: Math.round(Math.random() * 1000), - tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)], - }, - { - name: '江西', - value: Math.round(Math.random() * 1000), - tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)], - }, - { - name: '湖北', - value: Math.round(Math.random() * 1000), - tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)], - }, - { - name: '广西', - value: Math.round(Math.random() * 1000), - tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)], - }, - { - name: '甘肃', - value: Math.round(Math.random() * 1000), - tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)], - }, - { - name: '山西', - value: Math.round(Math.random() * 1000), - tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)], - }, - { - name: '内蒙古', - value: Math.round(Math.random() * 1000), - tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)], - }, - { - name: '陕西', - value: Math.round(Math.random() * 1000), - tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)], - }, - { - name: '吉林', - value: Math.round(Math.random() * 1000), - tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)], - }, - { - name: '福建', - value: Math.round(Math.random() * 1000), - tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)], - }, - { - name: '贵州', - value: Math.round(Math.random() * 1000), - tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)], - }, - { - name: '广东', - value: Math.round(Math.random() * 1000), - tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)], - }, - { - name: '青海', - value: Math.round(Math.random() * 1000), - tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)], - }, - { - name: '西藏', - value: Math.round(Math.random() * 1000), - tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)], - }, - { - name: '四川', - value: Math.round(Math.random() * 1000), - tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)], - }, - { - name: '宁夏', - value: Math.round(Math.random() * 1000), - tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)], - }, - { - name: '海南', - value: Math.round(Math.random() * 1000), - tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)], - }, - { - name: '台湾', - value: Math.round(Math.random() * 1000), - tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)], - }, - { - name: '香港', - value: Math.round(Math.random() * 1000), - tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)], - }, - { - name: '澳门', - value: Math.round(Math.random() * 1000), - tipData: [Math.round(Math.random() * 1000), Math.round(Math.random() * 1000)], - }, -] - -export const getLineData = (() => { - const category: any[] = [] - let dottedBase = +new Date() - const lineData: any[] = [] - const barData: any[] = [] - - for (let i = 0; i < 20; i++) { - const date = new Date((dottedBase += 1000 * 3600 * 24)) - category.push([date.getFullYear(), date.getMonth() + 1, date.getDate()].join('-')) - const b = Math.random() * 200 - const d = Math.random() * 200 - barData.push(b) - lineData.push(d + b) - } - return { barData, category, lineData } -})() diff --git a/src/views/demo/charts/map/Baidu.vue b/src/views/demo/charts/map/Baidu.vue deleted file mode 100644 index 3f6697367..000000000 --- a/src/views/demo/charts/map/Baidu.vue +++ /dev/null @@ -1,41 +0,0 @@ - - diff --git a/src/views/demo/charts/map/Gaode.vue b/src/views/demo/charts/map/Gaode.vue deleted file mode 100644 index 9c722ccd8..000000000 --- a/src/views/demo/charts/map/Gaode.vue +++ /dev/null @@ -1,42 +0,0 @@ - - diff --git a/src/views/demo/charts/map/Google.vue b/src/views/demo/charts/map/Google.vue deleted file mode 100644 index cdc80c0f5..000000000 --- a/src/views/demo/charts/map/Google.vue +++ /dev/null @@ -1,47 +0,0 @@ - - diff --git a/src/views/demo/comp/button/index.vue b/src/views/demo/comp/button/index.vue deleted file mode 100644 index 3f32942af..000000000 --- a/src/views/demo/comp/button/index.vue +++ /dev/null @@ -1,106 +0,0 @@ - - diff --git a/src/views/demo/comp/card-list/index.vue b/src/views/demo/comp/card-list/index.vue deleted file mode 100644 index 2a8cdb5c1..000000000 --- a/src/views/demo/comp/card-list/index.vue +++ /dev/null @@ -1,32 +0,0 @@ - - diff --git a/src/views/demo/comp/count-to/index.vue b/src/views/demo/comp/count-to/index.vue deleted file mode 100644 index d2d57e31b..000000000 --- a/src/views/demo/comp/count-to/index.vue +++ /dev/null @@ -1,34 +0,0 @@ - - - diff --git a/src/views/demo/comp/cropper/index.vue b/src/views/demo/comp/cropper/index.vue deleted file mode 100644 index 1d3bb866d..000000000 --- a/src/views/demo/comp/cropper/index.vue +++ /dev/null @@ -1,72 +0,0 @@ - - - - diff --git a/src/views/demo/comp/desc/index.vue b/src/views/demo/comp/desc/index.vue deleted file mode 100644 index 7c07381cd..000000000 --- a/src/views/demo/comp/desc/index.vue +++ /dev/null @@ -1,77 +0,0 @@ - - diff --git a/src/views/demo/comp/drawer/Drawer1.vue b/src/views/demo/comp/drawer/Drawer1.vue deleted file mode 100644 index 436829c6f..000000000 --- a/src/views/demo/comp/drawer/Drawer1.vue +++ /dev/null @@ -1,6 +0,0 @@ - - diff --git a/src/views/demo/comp/drawer/Drawer2.vue b/src/views/demo/comp/drawer/Drawer2.vue deleted file mode 100644 index 3518b3769..000000000 --- a/src/views/demo/comp/drawer/Drawer2.vue +++ /dev/null @@ -1,11 +0,0 @@ - - diff --git a/src/views/demo/comp/drawer/Drawer3.vue b/src/views/demo/comp/drawer/Drawer3.vue deleted file mode 100644 index c325f1b95..000000000 --- a/src/views/demo/comp/drawer/Drawer3.vue +++ /dev/null @@ -1,28 +0,0 @@ - - diff --git a/src/views/demo/comp/drawer/Drawer4.vue b/src/views/demo/comp/drawer/Drawer4.vue deleted file mode 100644 index 1e5000f2a..000000000 --- a/src/views/demo/comp/drawer/Drawer4.vue +++ /dev/null @@ -1,46 +0,0 @@ - - diff --git a/src/views/demo/comp/drawer/Drawer5.vue b/src/views/demo/comp/drawer/Drawer5.vue deleted file mode 100644 index 0a5e815e6..000000000 --- a/src/views/demo/comp/drawer/Drawer5.vue +++ /dev/null @@ -1,9 +0,0 @@ - - diff --git a/src/views/demo/comp/drawer/index.vue b/src/views/demo/comp/drawer/index.vue deleted file mode 100644 index 38957e591..000000000 --- a/src/views/demo/comp/drawer/index.vue +++ /dev/null @@ -1,50 +0,0 @@ - - diff --git a/src/views/demo/comp/loading/index.vue b/src/views/demo/comp/loading/index.vue deleted file mode 100644 index 51339ea6f..000000000 --- a/src/views/demo/comp/loading/index.vue +++ /dev/null @@ -1,97 +0,0 @@ - - diff --git a/src/views/demo/comp/modal/Modal1.vue b/src/views/demo/comp/modal/Modal1.vue deleted file mode 100644 index fb77028c7..000000000 --- a/src/views/demo/comp/modal/Modal1.vue +++ /dev/null @@ -1,53 +0,0 @@ - - diff --git a/src/views/demo/comp/modal/Modal2.vue b/src/views/demo/comp/modal/Modal2.vue deleted file mode 100644 index c2025fea6..000000000 --- a/src/views/demo/comp/modal/Modal2.vue +++ /dev/null @@ -1,11 +0,0 @@ - - diff --git a/src/views/demo/comp/modal/Modal3.vue b/src/views/demo/comp/modal/Modal3.vue deleted file mode 100644 index 6a5afd1cc..000000000 --- a/src/views/demo/comp/modal/Modal3.vue +++ /dev/null @@ -1,8 +0,0 @@ - - diff --git a/src/views/demo/comp/modal/Modal4.vue b/src/views/demo/comp/modal/Modal4.vue deleted file mode 100644 index e1c8ffc3c..000000000 --- a/src/views/demo/comp/modal/Modal4.vue +++ /dev/null @@ -1,75 +0,0 @@ - - diff --git a/src/views/demo/comp/modal/Modal5.vue b/src/views/demo/comp/modal/Modal5.vue deleted file mode 100644 index 64c49419a..000000000 --- a/src/views/demo/comp/modal/Modal5.vue +++ /dev/null @@ -1,40 +0,0 @@ - - diff --git a/src/views/demo/comp/modal/index.vue b/src/views/demo/comp/modal/index.vue deleted file mode 100644 index f7dcc09f7..000000000 --- a/src/views/demo/comp/modal/index.vue +++ /dev/null @@ -1,114 +0,0 @@ - - diff --git a/src/views/demo/comp/qrcode/index.vue b/src/views/demo/comp/qrcode/index.vue deleted file mode 100644 index c1b14c99c..000000000 --- a/src/views/demo/comp/qrcode/index.vue +++ /dev/null @@ -1,107 +0,0 @@ - - diff --git a/src/views/demo/comp/scroll/Action.vue b/src/views/demo/comp/scroll/Action.vue deleted file mode 100644 index b6f4035cb..000000000 --- a/src/views/demo/comp/scroll/Action.vue +++ /dev/null @@ -1,50 +0,0 @@ - - - diff --git a/src/views/demo/comp/scroll/VirtualScroll.vue b/src/views/demo/comp/scroll/VirtualScroll.vue deleted file mode 100644 index 029217d2a..000000000 --- a/src/views/demo/comp/scroll/VirtualScroll.vue +++ /dev/null @@ -1,79 +0,0 @@ - - - diff --git a/src/views/demo/comp/scroll/index.vue b/src/views/demo/comp/scroll/index.vue deleted file mode 100644 index 433084b29..000000000 --- a/src/views/demo/comp/scroll/index.vue +++ /dev/null @@ -1,26 +0,0 @@ - - - diff --git a/src/views/demo/comp/strength-meter/index.vue b/src/views/demo/comp/strength-meter/index.vue deleted file mode 100644 index fdeb1999e..000000000 --- a/src/views/demo/comp/strength-meter/index.vue +++ /dev/null @@ -1,24 +0,0 @@ - - - - diff --git a/src/views/demo/comp/time/index.vue b/src/views/demo/comp/time/index.vue deleted file mode 100644 index b39c35a0d..000000000 --- a/src/views/demo/comp/time/index.vue +++ /dev/null @@ -1,35 +0,0 @@ - - diff --git a/src/views/demo/comp/transition/index.vue b/src/views/demo/comp/transition/index.vue deleted file mode 100644 index f54a3a04e..000000000 --- a/src/views/demo/comp/transition/index.vue +++ /dev/null @@ -1,73 +0,0 @@ - - - diff --git a/src/views/demo/comp/upload/Upload1.vue b/src/views/demo/comp/upload/Upload1.vue deleted file mode 100644 index 0aa47f6e7..000000000 --- a/src/views/demo/comp/upload/Upload1.vue +++ /dev/null @@ -1,16 +0,0 @@ - - - diff --git a/src/views/demo/comp/upload/Upload2.vue b/src/views/demo/comp/upload/Upload2.vue deleted file mode 100644 index 78ba63f58..000000000 --- a/src/views/demo/comp/upload/Upload2.vue +++ /dev/null @@ -1,56 +0,0 @@ - - - diff --git a/src/views/demo/comp/upload/Upload3.vue b/src/views/demo/comp/upload/Upload3.vue deleted file mode 100644 index f093345f6..000000000 --- a/src/views/demo/comp/upload/Upload3.vue +++ /dev/null @@ -1,73 +0,0 @@ - - - diff --git a/src/views/demo/comp/upload/Upload4.vue b/src/views/demo/comp/upload/Upload4.vue deleted file mode 100644 index 9e47fc880..000000000 --- a/src/views/demo/comp/upload/Upload4.vue +++ /dev/null @@ -1,187 +0,0 @@ - - - diff --git a/src/views/demo/comp/upload/index.vue b/src/views/demo/comp/upload/index.vue deleted file mode 100644 index ff28dd59e..000000000 --- a/src/views/demo/comp/upload/index.vue +++ /dev/null @@ -1,15 +0,0 @@ - - diff --git a/src/views/demo/comp/verify/Rotate.vue b/src/views/demo/comp/verify/Rotate.vue deleted file mode 100644 index 42d7eb67b..000000000 --- a/src/views/demo/comp/verify/Rotate.vue +++ /dev/null @@ -1,18 +0,0 @@ - - diff --git a/src/views/demo/comp/verify/index.vue b/src/views/demo/comp/verify/index.vue deleted file mode 100644 index 972f581f8..000000000 --- a/src/views/demo/comp/verify/index.vue +++ /dev/null @@ -1,79 +0,0 @@ - - diff --git a/src/views/demo/feat/breadcrumb/ChildrenList.vue b/src/views/demo/feat/breadcrumb/ChildrenList.vue deleted file mode 100644 index 38179b5a5..000000000 --- a/src/views/demo/feat/breadcrumb/ChildrenList.vue +++ /dev/null @@ -1,8 +0,0 @@ - - diff --git a/src/views/demo/feat/breadcrumb/ChildrenListDetail.vue b/src/views/demo/feat/breadcrumb/ChildrenListDetail.vue deleted file mode 100644 index 4d9533965..000000000 --- a/src/views/demo/feat/breadcrumb/ChildrenListDetail.vue +++ /dev/null @@ -1,8 +0,0 @@ - - diff --git a/src/views/demo/feat/breadcrumb/FlatList.vue b/src/views/demo/feat/breadcrumb/FlatList.vue deleted file mode 100644 index 616a7aa06..000000000 --- a/src/views/demo/feat/breadcrumb/FlatList.vue +++ /dev/null @@ -1,8 +0,0 @@ - - diff --git a/src/views/demo/feat/breadcrumb/FlatListDetail.vue b/src/views/demo/feat/breadcrumb/FlatListDetail.vue deleted file mode 100644 index f427e0b66..000000000 --- a/src/views/demo/feat/breadcrumb/FlatListDetail.vue +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/src/views/demo/feat/click-out-side/index.vue b/src/views/demo/feat/click-out-side/index.vue deleted file mode 100644 index b505b8d27..000000000 --- a/src/views/demo/feat/click-out-side/index.vue +++ /dev/null @@ -1,24 +0,0 @@ - - diff --git a/src/views/demo/feat/context-menu/index.vue b/src/views/demo/feat/context-menu/index.vue deleted file mode 100644 index 33d112710..000000000 --- a/src/views/demo/feat/context-menu/index.vue +++ /dev/null @@ -1,78 +0,0 @@ - - diff --git a/src/views/demo/feat/copy/index.vue b/src/views/demo/feat/copy/index.vue deleted file mode 100644 index 7e0125923..000000000 --- a/src/views/demo/feat/copy/index.vue +++ /dev/null @@ -1,29 +0,0 @@ - - diff --git a/src/views/demo/feat/download/imgBase64.ts b/src/views/demo/feat/download/imgBase64.ts deleted file mode 100644 index 04be79a47..000000000 --- a/src/views/demo/feat/download/imgBase64.ts +++ /dev/null @@ -1 +0,0 @@ -export default `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMAAAADACAYAAABS3GwHAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QA/wAAAAAzJ3zzAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAB3RJTUUH5AodAjIGrlVB/QAAABBjYU52AAAAygAAAMAAAAAFAAAAAASpeQ4AAC6ASURBVHja7b133G1Vdaj9jDnXWruXt7+ncDhIEVCKaCiidATsgIjRm1gTu1FjTbl++ZmYqMmNRPOZm5tc400+Y65iwUQFEUSRIkixgNI5cA6nvX33veYc3x97v2IBpZzzzvdw1sNvc/5gH/ZYY80xy5ijQEZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkbG7kZCC7CaeevLu3QSyPXBKBL3RSIHKOE050EtULdqakaXvr/E+EiR9kbLRz6Wvc5HSxRagNVMIw+bnhyz/m6HbTtNvGjsAQENMNZk+FGB1EOjBfu9okLvbvj6N0Nra88kmzIegte+yDEapbRKMPp/EuZe3rcqOm37sjFKqQOKMDSFFUXxRFicVO1mqZi7/QMLS70DahS2QO9guOB92St9NGQrwEPgUBZFKHZVtr28p3ko5PucWko5MZfKmD5oACuKAM5jU6WP5S7N8+W0XLm6NYomHuZMaM3teWQG8BAkKoypknThoAM3c9ed6548lcrrJvpyTFElBUQDyCUKqUK3iMYJaTevhdufZG470LEzl0dSpyHE2qPJ1stf4vfO6eOdYTTpykc+V9BXn+02rvP+NQf25C1jTkaWvxfEADy4BJJJGB+D+aLcdGXefPCGIpf859tpvPUjsF8v5Ue5iP/9nuzVPhKyFeCXaKSGMsIb0qa+71yopsnhY44Xl5SKCpqysk6gn/+ttsHZEm6yhh2PiaI+B6y1+tI7nNz8nI/RqKXIxVWrLlsHHjHZrnHI61/S4/Uv7ZFDeJZxfK1TN7f7/NSY46RJJ4fESuQGXxV50CGz2z8CMjxxCHl8voKvxBgDWvFa3q+vJ2zo6bPmYgovWPSMpDDi4R1/mVnBIyEzgCG5rrJUEwq5vlxUUX5U0uJG6b90BP+CopcIFdUAW0ZhsAqkIloti5muSZxYJPVIrDCd6uRBHf3dExf1hOtKhn+/aompLqzph9bonkFmAMAdP/XMN6HaFSYMVNqKWibXpJw27uQAA6oS5rwkCl7QbpFOroIbSTSyg+MATtCSYg/qc+z+PZ711QrF9adWGffIXAR/8iHlbR/LVoJfR2YAQLEIb7kgIul6+br36lLqlT7PH03NYWUnKGEOvTC48PIWLdehUhq+sKEwDsQAk47ilOPkw1uc8pp5H310Ek0FZhPo5kJrd3WTGQCQ7oC/f5Njcga+9zlHtctR421eVVT2UyHI1gcGP9q3eM3jp8ok4wkJyi9cQHjAojrZ12MP6uorjTf7vmIzTPSQdV1lrB1au6ubvd4AvvLvjn4VvvWdlD/+RsynPpVbW0NOnOyZA4pecKEEU8CD5PDxiPQLOSVGf+X+wQ8/U07tfqkeVVROcnVG3nMe2lKRpoW3fzTbBj0ce70BnPYyKBeRe7SAyL9ptSPPGlF5YcmRN0DIg29LcKaAn6pi8xGSPvzds+SAMafTa1N96VifA//gIjhiUbHAfDmUdlc/e60BvOF8x++90DNzr3DZxxwX/YGamdYr1ud2csaY40hjNHYSaO8ztLo0jy+U0fFY45xg/MN/nZ6gBU9h354+c21fT7m3Rm1tpHLMnZ5SCu/6s2wVeCj22ouwnKRcMJ6w9m+cbF4b6fQDfuTWd7tzp3bIs+siSIR6DTP+vYJa0XodGauptYLob4g8ciAxMOG1tK7NuYd57v2vgrnw+3V6hy8if310sHP8qmavNYA2lnXXwuw+0L3Hs7kvk/v25XkGDogi1AWa/I1Cx+B6eXrrStjRhFiV33gWWQ6TThQ29DiyqZx6TY5vrumxfawPR18PZ/6ZosAHP5CFSSyzV26B3vrbbSIVzjsk5e++bjUp6/iagp6xIWcOq0UiyzkvIXADt44UalAuKMnQ1fmI/u7wz3HVaK3j2HWOM+uqxU9UVU/30JS99IX/GvZKfex3f0JsUk7ZIfLBs1uMOPesMe9fVVKdMhrG7SkMLr16gto8ur6quXpC7PxgS/RI8QOD0RGvh+6X6msnvDzlBT1ho1MZ8craYG6t1cleZQB/9D7HO/5bj1LJUBDkhb+1qD+tMz7iOGayL4cmTsSF2h0Mb9t8gZ6tS7eUg/gxhF0rkAIjXuVJTp9ad3pyLmXqdTs62jHCJgt/+sHsOLDMXmUAqXpmY88t9Y7cU3T6h/cW4jUNe1alL88pOyLDYAZdabmEwfalLfhCCZmsYhID/jGm3OjwQDzqtTLtOXfa8YwPTeb54LVLxEB7xVN5Vi97jQH80XsdiRdG+obygvDZf/oP+mI2TLTlnHpfjgLESxi3z3Ca17SAq5Qx0wm5+Ne4PR8JPUGtEq93+oy1Ts/YHsn0l44smcOcp+DhT/9S+dM/z1aCvcYA2nenfOPGNgbkK2+J9V3v+92xInLmSCqHVYf7nlDDwQ/jGcoj4ksVQUQfd8aZBzGKjnk1E16fs1b1JTcUTeXzIwZyyP0VKHYDPfAqYq8xABk1PP/wMhNtOO0rjmKffcdTObfsZR8TsNDJstuzk9P+aFFlJFHj9NEdfB/yeQEVxCo67fSgjY6zxDC5TwtGVZlogJ4Z4olXF3uFAbz9vC65kkH3gbKK6IiZKC7oaeN9jsoriZNAs7+CejAJ5Gui1Ty2AGZXWeJynFDdI2t7evhYX5+vjrGvedFKpFI8Hj6wZe/eBu0VBjCRxnQ3p3Lx3U3uKXqJ73Sn5nb680upVKxIuHgfgZ6IzxdF14xIVEwwzu9aY/SDrDKtqq5f1+Y1ky2OO/tvPS+51NP8O/jRxEo/+eriCW0Af/CylLe/LKWRE/JdWLNTmO27ymiLZ4515PDIY0IUuAKWR7l2inSlQq+WqI1BdoebPgVKCvumesC4cuJt/2w2HPy1lOQLcPB2+MB3995V4AltAHnnmE0MHdfjmprq+n5UGk/NC6qYE6sqkQx2IEFwHvpAuYKMVjAJu08YD2KBuiee9PrcdX1OfSs5ueZyiArI/DMDKWEV8IQ1gHed5zjurp2M9ZWSE9m/bTBi9htL7e+UHYcLoIGC3YyCM2iaJx0rEU/nyBkZpDnuDoTBKiComXZ66IYl/7zKPPs/8zo1T/lXpdKC9/+x8icf2vtWgiesASjwzSdPoqry8f1RiUytqHL8VN8cXHWCH+T5BsErSILPjZAWSuqjXeD2fCS/iYG6USbu02Mn/1V/e8f1Mv3pUdHkfyNLFZiIw+gjJE/YaFAnUOjDvj3Pq+5T8s4fOdKTV5Q8kxboBywK1ha8yalfVxFbSTDpLj74PhQ/c4sKOrbEuo0NnteM+cZxli0HtT3NimG2GEoj4XjCGcA7X+oxCqjy5Jl76FYOkK7vjU/1/emjqT0mUpJUwvj9ZRjvo3l8riI6kiMqgFmpCibLcUIVA+usHrQt5nl35GTLeTXu3bTFs5B7wm4IHpYn3BP3XYcj5n+Egnxr7QFsikkqXk4vOfOcqpPYarh4Hw/0EV8qi47XRWKLPNZ4n8fK0OWrZdX6Oqe/8yT09Fcfa+Rd/8MwbldaK+F5whmAtxGfnSqS81Dpe3qG8njfnF53cmSkA997qHgfD76V125SVDeWDDK9QkQnpwKxh7WODdOeJ31rEcOVUA7kFAjJE8oA3nxel09cGnNwdyMfeqGqVa3lvD9rxMlxFSfx8s1oCJwHNUi5hqmXMXnBmEBOF8NgImgLSx1YrMVAZeCW3dt4whjAxW9OOeqS7fzes3tUUy9v/KrDqj+4lvpXl7w/wGqYCg8wrO8jqMvhJmsSjRUkVh5/vM9jxSjSNvTvzfGdTTn53ifm8Hrkq1mM9r684SeMAYwlcMqrxpksiXxgCp2LbbHiePpUj8OKTqyXQC93GO+jOVIzIp1CXjU3LDQaQiAD2gNmI3lgZ1k+/aM1fLdxi+dtf/spFgpBNBSUJ4wB9EX5xBbh6S/YobV9YyZa7sRaKudXnNRCzf7L9X3aoFEe1taIStGuj/d5pBggAlkUadwfyXfnErl+dInuTwuG28vQyg7Bex63vc9z27s8zS7cP6dyzsvW8qYf9iZrPZ470ud4A7ELNPvL0OpcDpevwESiuYJgAqblageYtdy21crnupbtf/dGaAj6uxen1HvhBAvFHn8P8JrrPd+50NL9oOGz38grf05hBE4SJ0ePOLFGBiVOQmz+vYKz+GKNtFoTMaKDW+AAslgGq84OI90dVq7sK9/acS+NT/4p0i6jL/98DJ8PIFhg9vgVoBgr3Aqttsq17/GkjolJJ+eVHUfYYaJLiAFnBhUefCvRXrWETOQ1EkFCHHwVsApOJJ2xcvkDVr783G5//t6N0IjRhT1+FDx29uhHf+fLPO8/0PCfn0r55Lcts11GL93sTs935Zi6Ss5JOLenejAR5OtCpYQtgl0+E6w0BrQrsN3QmjdyyQMR1x7RhDNngc6gmNbeyh577PmD8/psfa5l583Q3NaVzlp0c1OOaSz4t1S7cmgJsT5AU4vl3kZdwZuS+MkJMaNFjPFhOkvCoLzKkpH+3bFcsT2Wz6jRu7ZHIg2ErTF88I/3uvuvn7FHrgBvO29wZXP/n30N1/O8++tet47GSaEnT6/1zDMSL0lQt6dCL0ffV7RbTVQKDCo8BOksyaCx35Llztmc/NNckRv+n39rs6lg1NZgbC8vkbJHmv47XtJjcylmfdvJA7Hoho7mvPFn7NMz71rX5dmRH0SDrjTC4OCbKmpHceNT4qbymiSChOjcaIYybRe6dyfmwvsK8t6W5f6RPrLZoh95PwTq/LRq2ONWgA+/wfHDO3qs73gS5ymkjqbxIyM9zq729TgT6IIJBm5PBe0WSEtlmM6Ti02Ywb9MH2jGcnMjz5dqkc41q5CL0dfNe/7mL8LJtVrY4wwA4APvKIF6/urd29R6SYoqx46l9ohaKhGgPmCii7doUqNfrJDaZYsIIIsFnMKckXa/IF9fv1a++vr/2W4eN6dy0hh8qW541168919mjzOAnnhmroNS28kb/3qMqnMH1nv66qLXg4cn+mDxPh3QXqxuskQ8kScGgvn9I4W+0N1i5aodkXz70zfRPFJzRCVRm4f3vj8b/LCHGcCH3+iInfAPNzZ45mhCdSSulVROGE85vuC14AYN7YJgBvV9fFLD1wrYooTzsMnQ7TlnZWnW8qUlw02f2ejkhBdbWg5u2hlKstXHHmUA57/CEMeGr3/3B5z16Vs03+PpZS8vqjkp5zRcfR8UOuCjAn58REw+gdQRxBqFwfX+kpH+1kiubxr51pYWM/8yZ3lz3OO4Frz07dnsv8weEwrx7vM77FsC11R55f95ph6zlUJ6kzup1OfZsZKE2vcP9/jazkmvWkbHE03ygkkDbX0E1KtI08iPdsbyqbboHX85plwwY/TWiYReGkhPq5Q9YgV49/kdDgL+7IKUH06lut83++UdP07PyLX19JqTohCunakfdHKXchUzVsPmLUbCDX4UZKdRv81yc8Py7WYsnX/cIRJbuOy2QEpaxewRK0CnkvJDZyg3kNp9qs1Uxkd65vykJ0fGDKodhAov7gnay9GfKiMTeSIhnNvTMEh3nInl+q2Jfq0iMjsXQdPBnIGPf1z4eBjRVi2rfgV4x3ldnoKQaxv+4tKcakRcUI6c6JunVZ3J+zBbbWAQ7+MjvKnRKxTV50RlOfl9pTGgTmFWZHEuks9vrpv/fP3tvr9P22OKovW9Md/xEbDqDaBr4c6FiKmuyBvP7FJsm6NKqXlNWdkYq6KPoY3QrkCAjqLEsKZKMpIn8j6g2xOkZejfb7l5ZyTfm5jT1hfHlW5sWMzOvA/LqjWAt5/teNfZPQookRNeviWmK1Kq9OXZo105MXHkQsX7yNDqfB5na6SjeeKiwQa88NW2B5/I1skx+ewBY9z6zv8uFNcZPaqqFDvw9j/NrOChWLVngA5QBCQV/nJjn/GOkdE+R1e9nDyamlIEOAlT3NADKWhcwo2MiI+tqneB6owyMMYdIp68XH/CPvJfVy3o9p/8PXLG0aI8A04IkhGxZ7BqV4BTeoZRJxScl9+/Dx7I92vjfc6uOk62qNn91TQfGjPw+mgz0X6hiKzJaRIbTKiD77DekMxbbn4gki9TYNszXyBM1EWxIFNh5NpTWJUG8LazlWuTPnPW88Fvpxq7QiXy5qR6KidUnRQ0dKILQqkmVKtIQbChAvDMMO5p1oifM3LVXMSlpL73hj9Wdrbh3h/Cpr8JpKg9hFVpALMemlFMUY38/kklYmVt1cv5ZSf7J4ORHyzepye4Xo7+WFVktIBd7ucVKM9XUiHdHssNC5F842LH5nNefI9/xgbB5mDjK4UNv5Ntf34dq84A3nOuUgFihX17cE0spuw5ciI1x5eUsg8Y74OHNMH7Gr1KXikN9RdIHnUKLTGzjUj+v5kyV+wowZkffpJctsOT7OWJLo+UVXcI/knU5cmaY7YOjW7EaT3/7Ir6V1Q805EX0kBpjqrQU8jlseMjxJUEE6q9jDCwvCWBbYbbO3DVPovMv21J5WtHbtdrTt7Ki3oxR1z5490vi4Iay32ThtkDxoE68dLd9Kv7h1HOo2RVGcBLL2hw5DU5miDtFnpzmfz+bU4ec5ycUwlW23YY1k8vT69aQSfymhQMkg7jL1ZaIBnYo6TYu2Zj/cyPpxt3/OA9ZUb/eQs/nJ6TSs/iVuCUZHTQZaSXeNpFUVgCGugelGm+agzg5rtT/uKiDjt3wpsnvP53cWa8HT1tIpVjxlJTtqh6CVPiZLmbQKGCq9ZEE1HEhdk/Dp1fsiSmO5PTb85X0/9YKvVmL1n4Fw6/+niFBF0hLYkqNhVKM4LrCOsnLKU4TztKMbqVS2Q6gIYeHavGAHqp8rT9DZft05QjOqlOOzN5kk9e1hF77KwFL4pnZWfb5S4aTsW7mP5oVSQtk2yBQY+lAPIYBa/idsb+zhunG3dc/NSttXbO5Q+/6pgCpD5aqZvx4aroBWmVTTo7aeZ+WosXpLWdSlpkKdkz2tCvGgN4xgER/3xll298qQuxY+msZOONvnfcjsjURQdLfogBJ6r4yPT9SPxAeVQqhTxjzj/YYmalDsCD31KMmo6J3c7u2Lx/YP3MGc2kc5R4ceLFDgtSrJSKVME4QTpFu3WpwmWjre636ozMO9cUuEcv1xYny+ruu7QqDOCYP0yBLt++QeUzX6xqPmHynf/SOvm2NF2/uSDByogDoNqVUjTv18R9VzSDRNtQojiLxL6bjC9tqazZOZ0UWk+13iAefABflHHgLbSqZq5bZd99Ef2pn76ECu2/YZyTKLCP3sN9sjGYzn7jM4QWAODog4SrfmK55eN36stP/H+5d7s72qDniDJlFKyqWFVW7MPwTw82tvNSiuZMZCatMmIZlBm0rNBHf+5PxSX5brs8sTOOi+0ENYhf7jy2oiz/XifNm83NehRRNKcr7rcvN+2Nr2UH/8iCABzL6q65HnQFOOiNHVDBo/zeJxfgzKfK77/wkH0uur57snP6lFIsEg0CPlf27KsPfrQQ4WtJhJE8Ts0vfGel8ACC5PpbctXGjkKuM21UR7w3g/8QAOOhVzTdual4sV21OYHKdtxxf8LsCRNED/yUDfPPZgvrsBT0LtrypBBi/kaCGsD6OMdOB1++2ks1HtOD1pFceFXnNCQ9vRBLPo4CNbMebPCd5sxOLUddzZkxwIbai6kKqPik1G4nY/Me4+vem1wQYZb1o8z38jK/NGrr/ZiSBRbxU1fROhfMbXkal3fpYshzGDluDibsryfYFmif189ze39+cGqLOsz0UyT264s5PSsXc5gIEi7TRUGkTyWa0aJNUa2iGmyyEFFnk3R7UmuYuNRcL9bHBOryvRwK3s/LbLNmG/0cNUUKgBrIWeT4BE7LY0dOo0ANkZuZ4UzdynXaCaXChyXcGcArxkIjXZI4cVrIt8d7rvU8I+5pkSzXWgiFpMTSphTVJGfGGBwLgqDOgNFuMrqwKa4vdhAdU5UwPd0H6W4KtBpjcX5hKprwVnLDtAwZFgYuAqc2cc+5FC3MoVqnJoeRo78KW5AFMYDD3t8gzg3udNPU0e+kONyTU9JzvOoGXXkX+4N4IDENrSVbtGBzKloLXD6zZyK3GNeXSlGxMxj8gWZ/FNTQ65bM5kbdpN2cjKsMyr7//Lc8engKL4qRtaDM0+UWety2CvtQBjGANRtytFse8YYFr6qxmRQvp4jKEUCY2W2AgvY1b9u+FhuNJCJUWWcGe3+TuMW43twaFdsTiK4JNvgBk+I0ktbiuE3bFRPJw5bXlwL4Y2vIadeyT0U5SGdIZQnPvnpPMPkf8plC/Gja7GJFiIp9pkfVaE9PUMcLVLU6/EqYgy+giZ3Vgu0SyQZEaiH0MxBEFC8uKrdahemdXZvvGnWBvdZCo1cw843RaLqTM1PLvRB++VuDLZFuEPT862g/Tfgm13Ab51PmeFbXxdiKavTkD3c49eM97t8M/Y6XO/5uJ6LJOlU9BdXDV1qeX2C5b2klams97mPIDdwvIWQRAG8Stzkqt5dsobMv1lcf7//2sSI6dHuWTH9xMu50iybh1zRXGeyUxDbxT/tnFk85l6eugZ6ewBYET1HvCvUov8KKDrjL3/ttJqZjDjg0L2/56Ki+8otPLoroc1Q5USFHyIOvSE9js11LkZA3dQyhWmwsGwBJrbGUjCx4xI/jJQmmm8HRd7ZTNs3FUVvzlug3eAXEIHTQyo10nnchSyfCgXYTnn+nKeXVcf8KrKABHPK6BX734tPpO+W+29r8+5832XZv+iSf6ouBg4dTbaCDr4KVPpVkh+ZthNdxNFxxW0WdSdxcPLIYR+XmCCjqwwyaYWSd7xXNzmbddvsJEx7JP6K/C9YiR8XIWWVY36JDGWE7Hc5YJW7RFdNqzwg/urjJj77blJFiXuOEybtv6ZzWbesR1krI+RbAayyp1qIyOVNCw0mjXjCxW4xHlu6MSi0jolME7OUmHvVGegsTcWFxNBrxhuiRKkcGa5kBju3iXwDR6CJe15GXkymQrgK36IoZQN5DY6djy1KXOzctsjSbHtZYTM9NnU4PAx3CHHwVSOwM1Xir5k0FQ2XF5fh5vDgTu35udD5v852qOhOvWID/Q4ljafaK9r5m3dhuwgg8qhc1TKbT/VI42yAHQpPNzDCD41jyXK6tUI8GrJABPOkNi6gqncRRz+Wo2miCmJNNJE8XISbk3l9xWrBtrSUpljw+VD6TDNyeuXQ2rjVmo2JrrURuNJheAJvi3MDt2e8WJZFB6MxjMcZY0SNzcOZfsXHqt9moH2VOAF7LjpCPuDIGUCzm6EYixVyBHJK0RU9LRU8HzQXd+4MnlnmKNtKc2YBIIdzWB0VxcbU5l5ucXZA4zauTcLFag6vIhW7ZdBbHzD69REaXm+49SkRAwY8Kes52eid8hlGjPEm/RJNnBY4W3a0K3v/NKT5t0uum9L2Suj7WyLT3cqZXjpCQtzqDg6/TWjyj1SgGnUbDuScEUon8zrjcJiq2N4hoIdzBd5B93a6Y5uJE1OrnzRSPY7JUBrWUUvSQr9E67R623fwF5u8oEvvzKVPSu/AQJGJ0t2vY2Bz9vpPEODXeV7zT01COFTRcNOOAHrGZpxxFmrclQkTVD1FvwKom9caOqNowIn6NasBIXZVUYGezZtOlkajmDfI4B4qYQQ+H+Fa6J3+BpedCXHAIn6YhFuFwwgyH3WYA+78lBf0JzvVJ05ROx+FVD/bOvwT1+y0rJshTeyAybS3HM5qzdZRJJOQlHKlJ0qVkfM7ElUZOFQ0Z7amGtFsyO1o1a/sJU7Br7iBkcEF2YIQ8rwAHdZmhgtDAESFB3KK77aW7Xg/kENCejKzdpkmpPA56AvijlIAHXx38SwvWaT02GpsIH6658MDtmc7F5cYmW2jXET8VNA7Woy6WdG46LjTrtgSYXekTHp4jDkvhHGF0QwN0X2K5kjVB3KK7zQBsUgCUl757VH/wrxegytGq8mKFZc9GoCkOT2K3aSma05wZxfCILnV2CyrgBVvopcnEPDbpl9WbZMUz4H6mGlDLfLdgtjRrptiLqMqunRqW3aITDn2hok9L2Y+7uUbfy1wQt+guN4B9Xtdg3WuXQDyu15V/+It75IDn//2UOn8aym8x2NuGmeOGM72WbINK1MdQRTVgiIGqSdzOqNpsxZXmtESuEHDro8bhennbWhyPer2c5GWwUu8OgQzoQQY965XsPBA28BFuF4CT+faKPvcuN4Buv89E1eJ7HfL5go4kU8V+t3ma9/1nK+SQFa9u8jNE8BLLEsWooAU7CRKF3Pogksb1xgO50YUFMa6uKiEdA4phvl0zLI5H+6SxKe+m7cGwmozmQc9skz5XObagHK2fZlGUM1b0oXe5p2H7nKdcUJx30mg31RpZo/gXq+phBE10UTQybarx/VqKqkCdkG5YlVSMW0qqzUJUbo4BOQL1eh1OSdoqm7mlUUsaMz3IcNx9Pzl80n2vo3Pqi9h69Tb6N1xLO/0v2pT1bgAast/j+IlHxi59yJvvTuEOIYm8bPpMXrs9al79SQi/BYH8XA/SJzZtrcaR5kwBr4YQCfcMZn+JXDepL22OKo2cGL+GUKHgAuLpKcwujVjTrJqyyO4XRhAVhHvoP+MiGudcS38sIeZCmiLAaSv0+LvsOTt9z+EbLaeeG5N6B0c36afuiNS5l6C6XCQyULyPQmwalOyS5swaDOMrLscvyCTO5nuN/ORsLyq2rXoJFnwnHtTQ7ZbMzlYtKvdjmdKVCb4TBm7RNRHy3AI87VAKxtNDgCtWSCG7zABy0WBs33i3k0++oaSvPy83gvBs9XIMoWP9FbRo2zqatIkkWHmT5fhIE/mdcbk7awud9Rg3PtiJhdn+GK/0C8bPrY2TdsUkK119e+gW3ejh7FvpPKVAXtqktFZIjF260n36sh6z/1bX0w6LYq/6LEHPUtX68D+H2m+nxGa7FqKez9lxNRIHM0U/yPONK61ufny2J3FaHbg9A6HgRXZ0i7KjWbf11EpphU1x2S1acugZDn12Hxk3lHErJMAuOwRf+N0+Lzsh4d7/aNuLv58eum3Ov9Aanm4G2gxz+PUKRlTL8TzlKAEdxz/eW/3HjgpOrFuMq0tpVF0cRdSETHQRj+tUpLk0FvX6ESXCFCRYtrkNoKcL/n6le9EwTmy3T1W7zAA+/KWuXPDVvnZ7Pv7K99KnzDf9ofmYvAgapLrbACW2XapRnqItoBqswZJ6gzG+n9SWNkXVZk7R9UK4+j7i1amRhaXRKLcwFo14S2LC7VKHvU/0ADCHgrtopXbMu8wAbt2WaqcnFCKcWt1ajmQxEUFDKdUrxHaBSrRFC3ZEhXqw1pIAHjWJ7yUjS/mo3KyikoTKuRcP3kjarthtrbotphHTITrv/LxIDCzgTsHfqitYeH6Xrb9rppTIwYYy6dS0/2Ec6ZXesyXI+B8U1PXkTE+rsWpkCnjdXbeaj0CeYZpjrbklrjSrErkxAjoFjKOrkSwsTti4VbLFcEfwgXaGn83ApcDV8aCA1oroZ9dtQFPL+vWGbV8tKt7M5ZLo63FkLkMkXS65sxIP9DNis6DFqKd5sw5DJWSFB/WitthdSiZmliTXi9UFjPdR8JZWp2zmm7VovB/LRMDZXxkoomkwlxjMlYLOpOQxe5oX6IP3VnnKVIX15yt3/uud6bFPLf+gXIovE8PWFXU7Dpr2ei3bWa1Fi2oooIHSHIcVFYzVWVvqpFGpvUGsq4UubNup2HRuOpZeQeKwtQh+Nv1vjpAvV8n/qI/3EUJhhdIhdpkBvHPdTpo9pZizTJ25UW66pdXPJfZqQS5RkSVWqqOQSF+smacYWc3bMSRgYdvBQJe4tjSXG5tvi01H8YEOvgOcwgPtklls1OyoN5KErjXn0RkHl3q4sUUvjYjxeGorFKS7y56/ms+zo9kl7Xqq5bz+8IIi5UJ8J8oXBe5ckafxihhxWopmtBDlEKYI2gNBUoncfDyy6OPaYl5EJeTBF8V3KnaxWbfeWWoasA7rsJ8ZJeKb11D6wjTF7U2uY5qSGgw7WZmw6F02OH7y18NqIn+UckhHWf/aBfGqfWvkJhH5jsC+io6wO+8EFNVYer4eowVjf1buMATeINa140rz/qjYroGuUSTMVmwQ75O6RBqLk1GlMWZLGGxIt+cw5W12lPwVz2f6ujx0v8Vz5ARq+rEVPB7t8hXwOGB8tEQUGT2gUgXDNhHzBRW5YTjud9fgh1hmfSnapgVTx1ALub1VDzZONTcxZ6JSu4CXYPV9xIOPpdWu2M3NqpHUUFvBbpK/ohoGv50ClyWYr/89LP0P1rIPZf3bFRZmlxvA1R+K2DHbJooM97aaYiVKxZjrgMuBneyOOXk54K1gu9SSFCtlfMCkewWTuLm41toRVVojEqflgI5GNY5umkhrYSpKugWTD+z2XGYz6FfLRDcD7MP1fJnncTormxe8W85AP/lEiW4vRQwqvRbdfrNpjHzLGK4Q6O36X1RPxKIWI6FoJwgY7zPo52U0KrfnkvH5OROlZZwJVvxGFPGWxU7Vtho1u64fyUhgn78AS4K5TDHX3sSObsSdch+38Sy+wKWysqrabU4AI5a4INh8HvGRJAXzfRvJV0TY+XPKePwM4n1SrcSbtRI1VKiiGuxwJ4oXo4241I7iSmOtGF8MdvBVRRRt12xvfiJK0+SR1/XcrXIhd1rs5xNyt++HIyZWqFMIkBKx235x0/+qECXgOoYksfi+64jwPYUrURrsulXYYU2bSpyjaKug4WZ/bxCjaVJb2hzXF3pi3IQSrrkeKj01bGnVbK9ZNWMq2NCFyRVmgCsM5vuC9rdQlD6GA5jkGys8+8NuTvzpNpTI9okKsR58fhWTjzdF+fhzEpnbHtTH40ABa9qUop3ko5qKTIbK8hrK44jSZjI2l0aVZqyKDZbm6EGN+FY1WmjWrHURoxCw1OJQrAjzvYT4yxaZq1AmJtIyOTbRDSLQbjWAuz9ZhYKlNF3kpxd1JRkpNAuTpSttbK9Vpf24B6uqat50dCRuaSLgQuX4DsqbSOSbUaUzY4vdSbF+3cDrE+zWN01jac9NRbVm1dT5WeuiIKhH8egMRJeNMnZ1k9/pLdJkP9bRoU0vUCPt3b4i3vGJKrkqJMVY1x8DlWl2iuGrgn4PHkd8pqJYmaEQLfmcmVIj5ZVU3C/KoqgKUbHTz0/NtG2xk6iXx1pJ+XEjCi6W+U7Fbm5XTC41VHZxfZ/HIlLbwzdT5Iot3NuBvxKIeQFCV/YNJtiKbAkbW1Jc23PLZ2dIKjhBrxK4BFgYfuXRvZyB2QiluKWVqI+VUcIm3XuJ/FxUbi3GlUZNojQJWd/HOrq9vHQWJm2S5iRvHkw6CYGmKKOYzc+n/OU3Ufux41ucw/76JhL+gW2BxBqwIgZw64di4iTCRjF3fmVG+jt7s8B3EK5HSHm0L0fwRNLUSiSUo8qggXOoRJdBnm9Ubu2I64stET+Jl5CtENVFzLZrxjdqZkNqKYd3e2pzgug7f87oNYdA67mcLRcywRgRszL9uH/k8bBiTgGHY/auHUSVCCmCWLlJjHxeRLb8nLJ+M6pgpaOl6F4tWK/COAFbCKGiYrWX1Bu5pLpUQzQOleZovKLgGyO2tTge91wUNPBuiADmBynmc0eQ2/QmapxCUQG+szuuhB4lK/ambv1QxNHP2x9A1VhRkSURvo3KdSAdHuEqIJ5BXf9qbDVviniNQ9b3MZFrx7Xmpri6ZCRyEyup018VSDpYtjZGItuqmFFWoL7PI2AW5Irt+GtHuD9NuEvexfu5gg4Xy0Ro2VZWP7f9eB4Z/mPEgMr9IBcJ8tPhV379KqBAJEsUo3nydhwjI4H0NsCLSpJ2cuOz7ajYjtSbXOB4n16rFs23K6bojIwScmXkZ76xqy1y8SJufp4ODhSewUkBfP4PxYoawKZ/GkFV8baqznmZ6dsGxl6iwnfhN5wFBpGdqsVoQUfiOY0lRgNdMimggkTaiIrtVlRurZM4HQ9ZaVGUtJuXdHZNVG2XTUGCXogwaHGAzgjyX3ny1/4W9/lRYhyGs3huOMl+iRVfIe/9xzqWFCTS6kiJpXpxm8BlwA0wSAZ9aMRhWNC8xRfsNDZcPy+GxSWiSmsxPzk3Z5J+IWSiy9Dtub1TNltbZVN1QilwsJsADYUrBK529No3sFYc8EymgtYm+GWCzKDqu1TiiF67QTrbo1wqXdV36Vd6Lj3QqY7IL+cMDOJ9oBzPaSUyGJkIOsEJTsQ34nKzF9caFTHeBqvv41Gj9Fp121uYiCMXST7w1l8VlYjonjyF/xsR3THD0dS5Wg2W77M9qN//lwmiKK/CLZt3MFkq0+sL9811HohILuv0uKWfqv+VXbTisNL2tdhpObLDm6cwGvMGBB9X2jviStOIuPWDUt9hEMG5WGYaIyZp1uwGbyQfOs1R0VZMfM0k01dVqDWmuEmexhQm8KXXQxFEV/f9rxLVeomeh4lynqPW1cjH9qe5yHzRGu7Vny8MMzj4NrUYbdGcKSFMEDK4XkEi55LRBaLqUqwQBZz98Vb6jVE736zbvjfkw0d7KgLfE+SLFdjxcmKKlDQFdq5QZuyjIdhkcVC9inrHu8+JVJNFWTdiZv/w7NzXDloT3djto84P+suKV4iNaj32JFLAay7Y9mcw+JfiSmtLVG0UTJLWh9X1g2A8TWeYWRy1xXbR1AyhAq+XtQMgcyCXAVd/FPof5jaZYY57aLOBw8NJ9zAEiw68/oKIf7nU86oXtbjyuhLHH4JCcteNd6eX3HSve6qIHhQZgcgsUYoaWopGiSQfrLKzDsKd42KnnRubW7K5Xh1nisHKmiukiXRadbvYrth1zkgtWPmLoUhAH+Rqgcs7tOZO5UYS6lqlyn1Bm988PEG3i1ffqjDuOf4Qo3LKgohs6ni4BJFLRekO6gZH230tmcdQDrnXBlQs7ajU0bjSmDZxvxwu0QWMV9ctGz+3Ni71ChIHTHCH4ewvyAOCXCjIDSkpeUakx+2E35Y9PEEN4H++1XL1xRVSL5x1SqRwE59+a/Eer3KFwE/ESEuLtqRFO46QC+Q/Ux3G9MfVxvbc+Py8SdK66q7pnfuYBALvrDzQrpiFdsmMeSQfPt6HJnAV6NUgrYhEQDTPoSwwE06630Dwm/LjDrb8eJPja5/pc/jbT5XohUsaW3OdzUWf10p8OyU7imGKUCVFBkVFkMj3kvqijapLNRUSQhSbk2EoiBHXGIv80qgteqFM2PcoAAa5xWI/Z7CbInJYrAI4eizKuoDi/XpCZwgBcOR+ESd9oMNd21VlC9TXR/e5WC/zFbuP5mwBqCH44etfiQpzy78hgBFDx0R+0SQpYtOSYlIUGXa83N08KIsgopp6kVarajutapRTQc2DprFSZZWXFxwF4kGDSXNtQnKtQLNHX8qUdZFF+rL/Cojz2FkVBgBw8x1dqsUcx312kRveN5JOTLvvgbkJiPFIuGh2BUQHQc8IXgLKAsMAN1UZiMIw+Cho/ykApJfiO5OsZ5ZtupPtIE8JJtUjZdUYQKlkKJcs37kQ6rUGUa6S9mKTYuTBdI4Qb3n5Vk4UMQpmOcQ9kKKGxe58BB4h8OGX5RcjQJEKs2zF4yhSXqHiho+PVWMAkYlodlL2u7yO32BJ+w76RvAKNnBkiw7q/SwfhoOPOcD2Fat+0FcltDAMMlR7NNUQ4ehjwh8vMzIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjJWHf8/ftAmPsVSYvIAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjAtMTAtMjlUMDI6NTA6MDYrMDA6MDASZ++eAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIwLTEwLTI5VDAyOjUwOjA2KzAwOjAwYzpXIgAAAABJRU5ErkJggg==` diff --git a/src/views/demo/feat/download/index.vue b/src/views/demo/feat/download/index.vue deleted file mode 100644 index 2074e7733..000000000 --- a/src/views/demo/feat/download/index.vue +++ /dev/null @@ -1,47 +0,0 @@ - - diff --git a/src/views/demo/feat/ellipsis/index.vue b/src/views/demo/feat/ellipsis/index.vue deleted file mode 100644 index dc99531f3..000000000 --- a/src/views/demo/feat/ellipsis/index.vue +++ /dev/null @@ -1,41 +0,0 @@ - - diff --git a/src/views/demo/feat/full-screen/index.vue b/src/views/demo/feat/full-screen/index.vue deleted file mode 100644 index 62ffd815a..000000000 --- a/src/views/demo/feat/full-screen/index.vue +++ /dev/null @@ -1,36 +0,0 @@ - - diff --git a/src/views/demo/feat/icon/index.vue b/src/views/demo/feat/icon/index.vue deleted file mode 100644 index 9382745fc..000000000 --- a/src/views/demo/feat/icon/index.vue +++ /dev/null @@ -1,69 +0,0 @@ - - diff --git a/src/views/demo/feat/img-preview/index.vue b/src/views/demo/feat/img-preview/index.vue deleted file mode 100644 index f0b4136f4..000000000 --- a/src/views/demo/feat/img-preview/index.vue +++ /dev/null @@ -1,20 +0,0 @@ - - diff --git a/src/views/demo/feat/menu-params/index.vue b/src/views/demo/feat/menu-params/index.vue deleted file mode 100644 index 37b163770..000000000 --- a/src/views/demo/feat/menu-params/index.vue +++ /dev/null @@ -1,31 +0,0 @@ - - diff --git a/src/views/demo/feat/msg/index.vue b/src/views/demo/feat/msg/index.vue deleted file mode 100644 index 240449753..000000000 --- a/src/views/demo/feat/msg/index.vue +++ /dev/null @@ -1,68 +0,0 @@ - - diff --git a/src/views/demo/feat/request-demo/index.vue b/src/views/demo/feat/request-demo/index.vue deleted file mode 100644 index 759667dd2..000000000 --- a/src/views/demo/feat/request-demo/index.vue +++ /dev/null @@ -1,76 +0,0 @@ - - - diff --git a/src/views/demo/feat/ripple/index.vue b/src/views/demo/feat/ripple/index.vue deleted file mode 100644 index 13a15372a..000000000 --- a/src/views/demo/feat/ripple/index.vue +++ /dev/null @@ -1,11 +0,0 @@ - - diff --git a/src/views/demo/feat/session-timeout/index.vue b/src/views/demo/feat/session-timeout/index.vue deleted file mode 100644 index abd74821f..000000000 --- a/src/views/demo/feat/session-timeout/index.vue +++ /dev/null @@ -1,45 +0,0 @@ - - diff --git a/src/views/demo/feat/tab-params/index.vue b/src/views/demo/feat/tab-params/index.vue deleted file mode 100644 index 35a9ff3c7..000000000 --- a/src/views/demo/feat/tab-params/index.vue +++ /dev/null @@ -1,24 +0,0 @@ - - - diff --git a/src/views/demo/feat/tabs/TabDetail.vue b/src/views/demo/feat/tabs/TabDetail.vue deleted file mode 100644 index 49d8efa29..000000000 --- a/src/views/demo/feat/tabs/TabDetail.vue +++ /dev/null @@ -1,20 +0,0 @@ - - - diff --git a/src/views/demo/feat/tabs/index.vue b/src/views/demo/feat/tabs/index.vue deleted file mode 100644 index 2671c7478..000000000 --- a/src/views/demo/feat/tabs/index.vue +++ /dev/null @@ -1,53 +0,0 @@ - - diff --git a/src/views/demo/feat/watermark/index.vue b/src/views/demo/feat/watermark/index.vue deleted file mode 100644 index b16c60a6d..000000000 --- a/src/views/demo/feat/watermark/index.vue +++ /dev/null @@ -1,32 +0,0 @@ - - diff --git a/src/views/demo/feat/ws/index.vue b/src/views/demo/feat/ws/index.vue deleted file mode 100644 index 1db4ee114..000000000 --- a/src/views/demo/feat/ws/index.vue +++ /dev/null @@ -1,100 +0,0 @@ - - diff --git a/src/views/demo/form/AdvancedForm.vue b/src/views/demo/form/AdvancedForm.vue deleted file mode 100644 index fafca22fb..000000000 --- a/src/views/demo/form/AdvancedForm.vue +++ /dev/null @@ -1,189 +0,0 @@ - - diff --git a/src/views/demo/form/AppendForm.vue b/src/views/demo/form/AppendForm.vue deleted file mode 100644 index 143cf1fbe..000000000 --- a/src/views/demo/form/AppendForm.vue +++ /dev/null @@ -1,201 +0,0 @@ - - diff --git a/src/views/demo/form/CustomerForm.vue b/src/views/demo/form/CustomerForm.vue deleted file mode 100644 index a88fea266..000000000 --- a/src/views/demo/form/CustomerForm.vue +++ /dev/null @@ -1,225 +0,0 @@ - - - - diff --git a/src/views/demo/form/DynamicForm.vue b/src/views/demo/form/DynamicForm.vue deleted file mode 100644 index 054bbe76d..000000000 --- a/src/views/demo/form/DynamicForm.vue +++ /dev/null @@ -1,229 +0,0 @@ - - diff --git a/src/views/demo/form/RefForm.vue b/src/views/demo/form/RefForm.vue deleted file mode 100644 index c2b7f2ee4..000000000 --- a/src/views/demo/form/RefForm.vue +++ /dev/null @@ -1,172 +0,0 @@ - - diff --git a/src/views/demo/form/RuleForm.vue b/src/views/demo/form/RuleForm.vue deleted file mode 100644 index 077478230..000000000 --- a/src/views/demo/form/RuleForm.vue +++ /dev/null @@ -1,245 +0,0 @@ - - diff --git a/src/views/demo/form/TabsForm.vue b/src/views/demo/form/TabsForm.vue deleted file mode 100644 index 02bc3ff0b..000000000 --- a/src/views/demo/form/TabsForm.vue +++ /dev/null @@ -1,118 +0,0 @@ - - - diff --git a/src/views/demo/form/UseForm.vue b/src/views/demo/form/UseForm.vue deleted file mode 100644 index 9ce652408..000000000 --- a/src/views/demo/form/UseForm.vue +++ /dev/null @@ -1,483 +0,0 @@ - - - diff --git a/src/views/demo/form/index.vue b/src/views/demo/form/index.vue deleted file mode 100644 index eeb5e1a81..000000000 --- a/src/views/demo/form/index.vue +++ /dev/null @@ -1,821 +0,0 @@ - - diff --git a/src/views/demo/level/Menu111.vue b/src/views/demo/level/Menu111.vue deleted file mode 100644 index 3ca97ac1a..000000000 --- a/src/views/demo/level/Menu111.vue +++ /dev/null @@ -1,10 +0,0 @@ - - diff --git a/src/views/demo/level/Menu12.vue b/src/views/demo/level/Menu12.vue deleted file mode 100644 index 9448a28d1..000000000 --- a/src/views/demo/level/Menu12.vue +++ /dev/null @@ -1,10 +0,0 @@ - - diff --git a/src/views/demo/level/Menu2.vue b/src/views/demo/level/Menu2.vue deleted file mode 100644 index a7cb0016b..000000000 --- a/src/views/demo/level/Menu2.vue +++ /dev/null @@ -1,10 +0,0 @@ - - diff --git a/src/views/demo/main-out/index.vue b/src/views/demo/main-out/index.vue deleted file mode 100644 index 2406632fd..000000000 --- a/src/views/demo/main-out/index.vue +++ /dev/null @@ -1,6 +0,0 @@ - diff --git a/src/views/demo/page/account/center/Application.vue b/src/views/demo/page/account/center/Application.vue deleted file mode 100644 index 59f71ad48..000000000 --- a/src/views/demo/page/account/center/Application.vue +++ /dev/null @@ -1,74 +0,0 @@ - - - diff --git a/src/views/demo/page/account/center/Article.vue b/src/views/demo/page/account/center/Article.vue deleted file mode 100644 index 16c811261..000000000 --- a/src/views/demo/page/account/center/Article.vue +++ /dev/null @@ -1,79 +0,0 @@ - - - diff --git a/src/views/demo/page/account/center/Project.vue b/src/views/demo/page/account/center/Project.vue deleted file mode 100644 index a9d37460e..000000000 --- a/src/views/demo/page/account/center/Project.vue +++ /dev/null @@ -1,57 +0,0 @@ - - - diff --git a/src/views/demo/page/account/center/data.tsx b/src/views/demo/page/account/center/data.tsx deleted file mode 100644 index 47a507476..000000000 --- a/src/views/demo/page/account/center/data.tsx +++ /dev/null @@ -1,124 +0,0 @@ -export interface ListItem { - title: string - icon: string - color?: string -} - -export interface TabItem { - key: string - name: string - component: string -} - -export const tags: string[] = ['很有想法的', '专注设计', '川妹子', '大长腿', '海纳百川', '前端开发', 'vue3'] - -export const teams: ListItem[] = [ - { - icon: 'ri:alipay-fill', - title: '科学搬砖组', - color: '#ff4000', - }, - { - icon: 'emojione-monotone:letter-a', - title: '中二少年团', - color: '#7c51b8', - }, - { - icon: 'ri:alipay-fill', - title: '高逼格设计', - color: '#00adf7', - }, - { - icon: 'jam:codepen-circle', - title: '程序员日常', - color: '#00adf7', - }, - { - icon: 'fa:behance-square', - title: '科学搬砖组', - color: '#7c51b8', - }, - { - icon: 'jam:codepen-circle', - title: '程序员日常', - color: '#ff4000', - }, -] - -export const details: ListItem[] = [ - { - icon: 'ic:outline-contacts', - title: '交互专家', - }, - { - icon: 'grommet-icons:cluster', - title: '某某某事业群', - }, - { - icon: 'bx:bx-home-circle', - title: '福建省厦门市', - }, -] - -export const achieveList: TabItem[] = [ - { - key: '1', - name: '文章', - component: 'Article', - }, - { - key: '2', - name: '应用', - component: 'Application', - }, - { - key: '3', - name: '项目', - component: 'Project', - }, -] - -export const actions: any[] = [ - { icon: 'clarity:star-line', text: '156', color: '#018ffb' }, - { icon: 'bx:bxs-like', text: '156', color: '#459ae8' }, - { icon: 'bx:bxs-message-dots', text: '2', color: '#42d27d' }, -] - -export const articleList = (() => { - const result: any[] = [] - for (let i = 0; i < 4; i++) { - result.push({ - title: 'Vben Admin', - description: ['Vben', '设计语言', 'Typescript'], - content: '基于Vue Next, TypeScript, Ant Design实现的一套完整的企业级后台管理系统。', - time: '2020-11-14 11:20', - }) - } - return result -})() - -export const applicationList = (() => { - const result: any[] = [] - for (let i = 0; i < 8; i++) { - result.push({ - title: 'Vben Admin', - icon: 'emojione-monotone:letter-a', - color: '#1890ff', - active: '100', - new: '1,799', - download: 'bx:bx-download', - }) - } - return result -})() - -export const projectList = (() => { - const result: any[] = [] - for (let i = 0; i < 8; i++) { - result.push({ - title: 'Vben Admin', - content: '基于Vue Next, TypeScript, Ant Design实现的一套完整的企业级后台管理系统。', - }) - } - return result -})() diff --git a/src/views/demo/page/account/center/index.vue b/src/views/demo/page/account/center/index.vue deleted file mode 100644 index 7deebe986..000000000 --- a/src/views/demo/page/account/center/index.vue +++ /dev/null @@ -1,138 +0,0 @@ - - - - diff --git a/src/views/demo/page/account/setting/AccountBind.vue b/src/views/demo/page/account/setting/AccountBind.vue deleted file mode 100644 index 898395cfb..000000000 --- a/src/views/demo/page/account/setting/AccountBind.vue +++ /dev/null @@ -1,46 +0,0 @@ - - - diff --git a/src/views/demo/page/account/setting/BaseSetting.vue b/src/views/demo/page/account/setting/BaseSetting.vue deleted file mode 100644 index 921fb4127..000000000 --- a/src/views/demo/page/account/setting/BaseSetting.vue +++ /dev/null @@ -1,79 +0,0 @@ - - - - diff --git a/src/views/demo/page/account/setting/MsgNotify.vue b/src/views/demo/page/account/setting/MsgNotify.vue deleted file mode 100644 index de946915d..000000000 --- a/src/views/demo/page/account/setting/MsgNotify.vue +++ /dev/null @@ -1,27 +0,0 @@ - - diff --git a/src/views/demo/page/account/setting/SecureSetting.vue b/src/views/demo/page/account/setting/SecureSetting.vue deleted file mode 100644 index b7b58f409..000000000 --- a/src/views/demo/page/account/setting/SecureSetting.vue +++ /dev/null @@ -1,29 +0,0 @@ - - diff --git a/src/views/demo/page/account/setting/data.ts b/src/views/demo/page/account/setting/data.ts deleted file mode 100644 index c664fa190..000000000 --- a/src/views/demo/page/account/setting/data.ts +++ /dev/null @@ -1,149 +0,0 @@ -import { FormSchema } from '@/components/Form' - -export interface ListItem { - key: string - title: string - description: string - extra?: string - avatar?: string - color?: string -} - -// tab的list -export const settingList = [ - { - key: '1', - name: '基本设置', - component: 'BaseSetting', - }, - { - key: '2', - name: '安全设置', - component: 'SecureSetting', - }, - { - key: '3', - name: '账号绑定', - component: 'AccountBind', - }, - { - key: '4', - name: '新消息通知', - component: 'MsgNotify', - }, -] - -// 基础设置 form -export const baseSetschemas: FormSchema[] = [ - { - field: 'email', - component: 'Input', - label: '邮箱', - colProps: { span: 18 }, - }, - { - field: 'name', - component: 'Input', - label: '昵称', - colProps: { span: 18 }, - }, - { - field: 'introduction', - component: 'InputTextArea', - label: '个人简介', - colProps: { span: 18 }, - }, - { - field: 'phone', - component: 'Input', - label: '联系电话', - colProps: { span: 18 }, - }, - { - field: 'address', - component: 'Input', - label: '所在地区', - colProps: { span: 18 }, - }, -] - -// 安全设置 list -export const secureSettingList: ListItem[] = [ - { - key: '1', - title: '账户密码', - description: '当前密码强度::强', - extra: '修改', - }, - { - key: '2', - title: '密保手机', - description: '已绑定手机::138****8293', - extra: '修改', - }, - { - key: '3', - title: '密保问题', - description: '未设置密保问题,密保问题可有效保护账户安全', - extra: '修改', - }, - { - key: '4', - title: '备用邮箱', - description: '已绑定邮箱::ant***sign.com', - extra: '修改', - }, - { - key: '5', - title: 'MFA 设备', - description: '未绑定 MFA 设备,绑定后,可以进行二次确认', - extra: '修改', - }, -] - -// 账号绑定 list -export const accountBindList: ListItem[] = [ - { - key: '1', - title: '绑定淘宝', - description: '当前未绑定淘宝账号', - extra: '绑定', - avatar: 'ri:taobao-fill', - color: '#ff4000', - }, - { - key: '2', - title: '绑定支付宝', - description: '当前未绑定支付宝账号', - extra: '绑定', - avatar: 'fa-brands:alipay', - color: '#2eabff', - }, - { - key: '3', - title: '绑定钉钉', - description: '当前未绑定钉钉账号', - extra: '绑定', - avatar: 'ri:dingding-fill', - color: '#2eabff', - }, -] - -// 新消息通知 list -export const msgNotifyList: ListItem[] = [ - { - key: '1', - title: '账户密码', - description: '其他用户的消息将以站内信的形式通知', - }, - { - key: '2', - title: '系统消息', - description: '系统消息将以站内信的形式通知', - }, - { - key: '3', - title: '待办任务', - description: '待办任务将以站内信的形式通知', - }, -] diff --git a/src/views/demo/page/account/setting/index.vue b/src/views/demo/page/account/setting/index.vue deleted file mode 100644 index 9e09e6ce0..000000000 --- a/src/views/demo/page/account/setting/index.vue +++ /dev/null @@ -1,50 +0,0 @@ - - - - diff --git a/src/views/demo/page/desc/basic/data.tsx b/src/views/demo/page/desc/basic/data.tsx deleted file mode 100644 index 3a75d3d68..000000000 --- a/src/views/demo/page/desc/basic/data.tsx +++ /dev/null @@ -1,196 +0,0 @@ -import { DescItem } from '@/components/Description' -import { BasicColumn } from '@/components/Table/src/types/table' -import { Button } from '@/components/Button' - -import { Badge } from 'ant-design-vue' - -export const refundData = { - a1: '1000000000', - a2: '已取货', - a3: '1234123421', - a4: '3214321432', -} - -export const personData = { - b1: '付小小', - b2: '18100000000', - b3: '菜鸟仓储', - b4: '浙江省杭州市西湖区万塘路18号', - b5: '无', -} -export const refundSchema: DescItem[] = [ - { - field: 'a1', - label: '取货单号', - }, - { - field: 'a2', - label: '状态', - }, - { - field: 'a3', - label: '销售单号', - }, - { - field: 'a4', - label: '子订单', - }, -] -export const personSchema: DescItem[] = [ - { - field: 'b1', - label: '用户姓名', - }, - { - field: 'b2', - label: '联系电话', - }, - { - field: 'b3', - label: '常用快递', - }, - { - field: 'b4', - label: '取货地址', - }, - { - field: 'b5', - label: '备注', - }, -] - -export const refundTableSchema: BasicColumn[] = [ - { - title: '商品编号', - width: 150, - dataIndex: 't1', - customRender: ({ record }) => { - return ( - - ) - }, - }, - { - title: '商品名称', - width: 150, - dataIndex: 't2', - }, - { - title: '商品条码', - width: 150, - dataIndex: 't3', - }, - { - title: '单价 ', - width: 150, - dataIndex: 't4', - }, - { - title: '数量(件) ', - width: 150, - dataIndex: 't5', - }, - { - title: '金额', - width: 150, - dataIndex: 't6', - }, -] -export const refundTimeTableSchema: BasicColumn[] = [ - { - title: '时间', - width: 150, - dataIndex: 't1', - }, - { - title: '当前进度', - width: 150, - dataIndex: 't2', - }, - { - title: '状态', - width: 150, - dataIndex: 't3', - customRender: ({ record }) => { - return - }, - }, - { - title: '操作员ID ', - width: 150, - dataIndex: 't4', - }, - { - title: '耗时', - width: 150, - dataIndex: 't5', - }, -] - -export const refundTableData: any[] = [ - { - t1: 1234561, - t2: '矿泉水 550ml', - t3: '12421432143214321', - t4: '2.00', - t5: 1, - t6: 2.0, - }, - { - t1: 1234562, - t2: '矿泉水 550ml', - t3: '12421432143214321', - t4: '2.00', - t5: 2, - t6: 2.0, - }, - { - t1: 1234562, - t2: '矿泉水 550ml', - t3: '12421432143214321', - t4: '2.00', - t5: 2, - t6: 2.0, - }, - { - t1: 1234562, - t2: '矿泉水 550ml', - t3: '12421432143214321', - t4: '2.00', - t5: 2, - t6: 2.0, - }, -] - -export const refundTimeTableData: any[] = [ - { - t1: '2017-10-01 14:10', - t2: '联系客户', - t3: '进行中', - t4: '取货员 ID1234', - t5: '5mins', - }, - { - t1: '2017-10-01 14:10', - t2: '取货员出发', - t3: '成功', - t4: '取货员 ID1234', - t5: '5mins', - }, - { - t1: '2017-10-01 14:10', - t2: '取货员接单', - t3: '成功', - t4: '系统', - t5: '5mins', - }, - { - t1: '2017-10-01 14:10', - t2: '申请审批通过', - t3: '成功', - t4: '用户', - t5: '1h', - }, -] diff --git a/src/views/demo/page/desc/basic/index.vue b/src/views/demo/page/desc/basic/index.vue deleted file mode 100644 index 52f01d47d..000000000 --- a/src/views/demo/page/desc/basic/index.vue +++ /dev/null @@ -1,71 +0,0 @@ - - - diff --git a/src/views/demo/page/desc/high/data.tsx b/src/views/demo/page/desc/high/data.tsx deleted file mode 100644 index 36118c277..000000000 --- a/src/views/demo/page/desc/high/data.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import { BasicColumn } from '@/components/Table/src/types/table' - -import { Badge } from 'ant-design-vue' - -export const refundTimeTableSchema: BasicColumn[] = [ - { - title: '时间', - width: 150, - dataIndex: 't1', - }, - { - title: '当前进度', - width: 150, - dataIndex: 't2', - }, - { - title: '状态', - width: 150, - dataIndex: 't3', - customRender: ({ record }) => { - return - }, - }, - { - title: '操作员ID ', - width: 150, - dataIndex: 't4', - }, - { - title: '耗时', - width: 150, - dataIndex: 't5', - }, -] - -export const refundTimeTableData: any[] = [ - { - t1: '2017-10-01 14:10', - t2: '联系客户', - t3: '进行中', - t4: '取货员 ID1234', - t5: '5mins', - }, - { - t1: '2017-10-01 14:10', - t2: '取货员出发', - t3: '成功', - t4: '取货员 ID1234', - t5: '5mins', - }, - { - t1: '2017-10-01 14:10', - t2: '取货员接单', - t3: '成功', - t4: '系统', - t5: '5mins', - }, - { - t1: '2017-10-01 14:10', - t2: '申请审批通过', - t3: '成功', - t4: '用户', - t5: '1h', - }, -] diff --git a/src/views/demo/page/desc/high/index.vue b/src/views/demo/page/desc/high/index.vue deleted file mode 100644 index 33dc8b084..000000000 --- a/src/views/demo/page/desc/high/index.vue +++ /dev/null @@ -1,107 +0,0 @@ - - diff --git a/src/views/demo/page/form/basic/data.ts b/src/views/demo/page/form/basic/data.ts deleted file mode 100644 index 90f6a3e57..000000000 --- a/src/views/demo/page/form/basic/data.ts +++ /dev/null @@ -1,139 +0,0 @@ -import { FormSchema } from '@/components/Form' - -const colProps = { - span: 8, -} - -export const schemas: FormSchema[] = [ - { - field: 'title', - component: 'Input', - label: '标题', - colProps, - componentProps: { - placeholder: '给目标起个名字', - }, - required: true, - }, - { - field: 'time', - component: 'RangePicker', - label: '起止日期', - colProps, - required: true, - }, - { - field: 'client', - component: 'Input', - colProps, - label: '客户', - helpMessage: '目标的服务对象', - subLabel: '( 选填 )', - componentProps: { - placeholder: '请描述你服务的客户,内部客户直接 @姓名/工号', - }, - }, - { - field: 'weights', - component: 'InputNumber', - label: '权重', - colProps, - subLabel: '( 选填 )', - componentProps: { - formatter: (value: string | number) => (value ? `${value}%` : ''), - parser: (value: string) => Number(value.replace('%', '')), - placeholder: '请输入', - }, - }, - { - field: 'target', - component: 'InputTextArea', - label: '目标描述', - colProps, - componentProps: { - placeholder: '请输入你的阶段性工作目标', - rows: 4, - }, - required: true, - }, - { - field: 'metrics', - component: 'InputTextArea', - label: '衡量标准', - colProps, - componentProps: { - placeholder: '请输入衡量标准', - rows: 4, - }, - required: true, - }, - - { - field: 'inviteer', - component: 'Input', - label: '邀评人', - colProps: { - span: 8, - }, - subLabel: '( 选填 )', - componentProps: { - placeholder: '请直接 @姓名/工号,最多可邀请 5 人', - }, - }, - { - field: 'disclosure', - component: 'RadioGroup', - label: '目标公开', - colProps: { - span: 16, - }, - itemProps: { - extra: '客户、邀评人默认被分享', - }, - componentProps: { - options: [ - { - label: '公开', - value: '1', - }, - { - label: '部分公开', - value: '2', - }, - { - label: '不公开', - value: '3', - }, - ], - }, - }, - { - field: 'disclosure', - component: 'Select', - label: ' ', - colProps: { - span: 8, - }, - show: ({ model }) => { - return model.disclosure === '2' - }, - componentProps: { - placeholder: '公开给', - mode: 'multiple', - options: [ - { - label: '同事1', - value: '1', - }, - { - label: '同事2', - value: '2', - }, - { - label: '同事3', - value: '3', - }, - ], - }, - }, -] diff --git a/src/views/demo/page/form/basic/index.vue b/src/views/demo/page/form/basic/index.vue deleted file mode 100644 index 7dab220dd..000000000 --- a/src/views/demo/page/form/basic/index.vue +++ /dev/null @@ -1,64 +0,0 @@ - - - diff --git a/src/views/demo/page/form/high/PersonTable.vue b/src/views/demo/page/form/high/PersonTable.vue deleted file mode 100644 index 2dcd352ae..000000000 --- a/src/views/demo/page/form/high/PersonTable.vue +++ /dev/null @@ -1,127 +0,0 @@ - - diff --git a/src/views/demo/page/form/high/data.ts b/src/views/demo/page/form/high/data.ts deleted file mode 100644 index ee05e2381..000000000 --- a/src/views/demo/page/form/high/data.ts +++ /dev/null @@ -1,149 +0,0 @@ -import { FormSchema } from '@/components/Form' - -const basicOptions: LabelValueOptions = [ - { - label: '付晓晓', - value: '1', - }, - { - label: '周毛毛', - value: '2', - }, -] - -const storeTypeOptions: LabelValueOptions = [ - { - label: '私密', - value: '1', - }, - { - label: '公开', - value: '2', - }, -] - -export const schemas: FormSchema[] = [ - { - field: 'f1', - component: 'Input', - label: '仓库名', - required: true, - }, - { - field: 'f2', - component: 'Input', - label: '仓库域名', - required: true, - componentProps: { - addonBefore: 'http://', - addonAfter: 'com', - }, - colProps: { - offset: 2, - }, - }, - { - field: 'f3', - component: 'Select', - label: '仓库管理员', - componentProps: { - options: basicOptions, - }, - required: true, - colProps: { - offset: 2, - }, - }, - { - field: 'f4', - component: 'Select', - label: '审批人', - componentProps: { - options: basicOptions, - }, - required: true, - }, - { - field: 'f5', - component: 'RangePicker', - label: '生效日期', - required: true, - colProps: { - offset: 2, - }, - }, - { - field: 'f6', - component: 'Select', - label: '仓库类型', - componentProps: { - options: storeTypeOptions, - }, - required: true, - colProps: { - offset: 2, - }, - }, -] -export const taskSchemas: FormSchema[] = [ - { - field: 't1', - component: 'Input', - label: '任务名', - required: true, - }, - { - field: 't2', - component: 'Input', - label: '任务描述', - required: true, - colProps: { - offset: 2, - }, - }, - { - field: 't3', - component: 'Select', - label: '执行人', - componentProps: { - options: basicOptions, - }, - required: true, - colProps: { - offset: 2, - }, - }, - { - field: 't4', - component: 'Select', - label: '责任人', - componentProps: { - options: basicOptions, - }, - required: true, - }, - { - field: 't5', - component: 'TimePicker', - label: '生效日期', - required: true, - componentProps: { - style: { width: '100%' }, - }, - colProps: { - offset: 2, - }, - }, - { - field: 't6', - component: 'Select', - label: '任务类型', - componentProps: { - options: storeTypeOptions, - }, - required: true, - colProps: { - offset: 2, - }, - }, -] diff --git a/src/views/demo/page/form/high/index.vue b/src/views/demo/page/form/high/index.vue deleted file mode 100644 index 0db5a445e..000000000 --- a/src/views/demo/page/form/high/index.vue +++ /dev/null @@ -1,65 +0,0 @@ - - - diff --git a/src/views/demo/page/form/step/Step1.vue b/src/views/demo/page/form/step/Step1.vue deleted file mode 100644 index 98af98250..000000000 --- a/src/views/demo/page/form/step/Step1.vue +++ /dev/null @@ -1,92 +0,0 @@ - - - diff --git a/src/views/demo/page/form/step/Step2.vue b/src/views/demo/page/form/step/Step2.vue deleted file mode 100644 index 8e6f408ec..000000000 --- a/src/views/demo/page/form/step/Step2.vue +++ /dev/null @@ -1,61 +0,0 @@ - - diff --git a/src/views/demo/page/form/step/Step3.vue b/src/views/demo/page/form/step/Step3.vue deleted file mode 100644 index 474d9164a..000000000 --- a/src/views/demo/page/form/step/Step3.vue +++ /dev/null @@ -1,23 +0,0 @@ - - diff --git a/src/views/demo/page/form/step/data.tsx b/src/views/demo/page/form/step/data.tsx deleted file mode 100644 index c70ee7d94..000000000 --- a/src/views/demo/page/form/step/data.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import { FormSchema } from '@/components/Form' - -export const step1Schemas: FormSchema[] = [ - { - field: 'account', - component: 'Select', - label: '付款账户', - required: true, - defaultValue: '1', - componentProps: { - options: [ - { - label: 'anncwb@126.com', - value: '1', - }, - ], - }, - colProps: { - span: 24, - }, - }, - { - field: 'fac', - label: '收款账户', - required: true, - defaultValue: 'test@example.com', - slot: 'fac', - colProps: { - span: 24, - }, - }, - { - field: 'pay', - component: 'Input', - label: '', - defaultValue: 'zfb', - show: false, - }, - { - field: 'payeeName', - component: 'Input', - label: '收款人姓名', - defaultValue: 'Vben', - required: true, - colProps: { - span: 24, - }, - }, - { - field: 'money', - component: 'Input', - label: '转账金额', - defaultValue: '500', - required: true, - renderComponentContent: () => { - return { - prefix: () => '¥', - } - }, - colProps: { - span: 24, - }, - }, -] - -export const step2Schemas: FormSchema[] = [ - { - field: 'pwd', - component: 'InputPassword', - label: '支付密码', - required: true, - defaultValue: '123456', - colProps: { - span: 24, - }, - }, -] diff --git a/src/views/demo/page/form/step/index.vue b/src/views/demo/page/form/step/index.vue deleted file mode 100644 index 6ccef5178..000000000 --- a/src/views/demo/page/form/step/index.vue +++ /dev/null @@ -1,71 +0,0 @@ - - - diff --git a/src/views/demo/page/list/basic/data.tsx b/src/views/demo/page/list/basic/data.tsx deleted file mode 100644 index 2598df36a..000000000 --- a/src/views/demo/page/list/basic/data.tsx +++ /dev/null @@ -1,17 +0,0 @@ -export const cardList = (() => { - const result: any[] = [] - for (let i = 0; i < 6; i++) { - result.push({ - id: i, - title: 'Vben Admin', - description: '基于Vue Next, TypeScript, Ant Design Vue实现的一套完整的企业级后台管理系统', - datetime: '2020-11-26 17:39', - extra: '编辑', - icon: 'logos:vue', - color: '#1890ff', - author: 'Vben', - percent: 20 * (i + 1), - }) - } - return result -})() diff --git a/src/views/demo/page/list/basic/index.vue b/src/views/demo/page/list/basic/index.vue deleted file mode 100644 index 5579afe1a..000000000 --- a/src/views/demo/page/list/basic/index.vue +++ /dev/null @@ -1,143 +0,0 @@ - - - diff --git a/src/views/demo/page/list/card/data.tsx b/src/views/demo/page/list/card/data.tsx deleted file mode 100644 index 995b706a8..000000000 --- a/src/views/demo/page/list/card/data.tsx +++ /dev/null @@ -1,14 +0,0 @@ -export const cardList = (() => { - const result: any[] = [] - for (let i = 0; i < 12; i++) { - result.push({ - title: 'Vben Admin', - icon: 'logos:vue', - color: '#1890ff', - active: '100', - new: '1,799', - download: 'bx:bx-download', - }) - } - return result -})() diff --git a/src/views/demo/page/list/card/index.vue b/src/views/demo/page/list/card/index.vue deleted file mode 100644 index 1e431ae06..000000000 --- a/src/views/demo/page/list/card/index.vue +++ /dev/null @@ -1,87 +0,0 @@ - - - diff --git a/src/views/demo/page/list/search/data.tsx b/src/views/demo/page/list/search/data.tsx deleted file mode 100644 index fa3d22071..000000000 --- a/src/views/demo/page/list/search/data.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import { FormSchema } from '@/components/Form' - -export const searchList = (() => { - const result: any[] = [] - for (let i = 0; i < 6; i++) { - result.push({ - id: i, - title: 'Vben Admin', - description: ['Vben', '设计语言', 'Typescript'], - content: '基于Vue Next, TypeScript, Ant Design实现的一套完整的企业级后台管理系统。', - time: '2020-11-14 11:20', - }) - } - return result -})() - -export const actions: any[] = [ - { icon: 'clarity:star-line', text: '156', color: '#018ffb' }, - { icon: 'bx:bxs-like', text: '156', color: '#459ae8' }, - { icon: 'bx:bxs-message-dots', text: '2', color: '#42d27d' }, -] - -export const schemas: FormSchema[] = [ - { - field: 'field1', - component: 'InputSearch', - label: '项目名', - colProps: { - span: 8, - }, - componentProps: { - onChange: (e: any) => { - console.log(e) - }, - }, - }, -] diff --git a/src/views/demo/page/list/search/index.vue b/src/views/demo/page/list/search/index.vue deleted file mode 100644 index 2e48826f9..000000000 --- a/src/views/demo/page/list/search/index.vue +++ /dev/null @@ -1,105 +0,0 @@ - - - diff --git a/src/views/demo/page/result/fail/index.vue b/src/views/demo/page/result/fail/index.vue deleted file mode 100644 index 925715366..000000000 --- a/src/views/demo/page/result/fail/index.vue +++ /dev/null @@ -1,47 +0,0 @@ - - - diff --git a/src/views/demo/page/result/success/index.vue b/src/views/demo/page/result/success/index.vue deleted file mode 100644 index 390bb13bb..000000000 --- a/src/views/demo/page/result/success/index.vue +++ /dev/null @@ -1,51 +0,0 @@ - - - diff --git a/src/views/demo/permission/CurrentPermissionMode.vue b/src/views/demo/permission/CurrentPermissionMode.vue deleted file mode 100644 index e52804420..000000000 --- a/src/views/demo/permission/CurrentPermissionMode.vue +++ /dev/null @@ -1,23 +0,0 @@ - - diff --git a/src/views/demo/permission/back/Btn.vue b/src/views/demo/permission/back/Btn.vue deleted file mode 100644 index 53a6c76a1..000000000 --- a/src/views/demo/permission/back/Btn.vue +++ /dev/null @@ -1,76 +0,0 @@ - - - diff --git a/src/views/demo/permission/back/index.vue b/src/views/demo/permission/back/index.vue deleted file mode 100644 index b97f98720..000000000 --- a/src/views/demo/permission/back/index.vue +++ /dev/null @@ -1,51 +0,0 @@ - - - diff --git a/src/views/demo/permission/front/AuthPageA.vue b/src/views/demo/permission/front/AuthPageA.vue deleted file mode 100644 index cdc08a529..000000000 --- a/src/views/demo/permission/front/AuthPageA.vue +++ /dev/null @@ -1,16 +0,0 @@ - - - diff --git a/src/views/demo/permission/front/AuthPageB.vue b/src/views/demo/permission/front/AuthPageB.vue deleted file mode 100644 index f6c5ddaeb..000000000 --- a/src/views/demo/permission/front/AuthPageB.vue +++ /dev/null @@ -1,16 +0,0 @@ - - - diff --git a/src/views/demo/permission/front/Btn.vue b/src/views/demo/permission/front/Btn.vue deleted file mode 100644 index 2ac5a8fdf..000000000 --- a/src/views/demo/permission/front/Btn.vue +++ /dev/null @@ -1,74 +0,0 @@ - - - diff --git a/src/views/demo/permission/front/index.vue b/src/views/demo/permission/front/index.vue deleted file mode 100644 index 2549b2c2b..000000000 --- a/src/views/demo/permission/front/index.vue +++ /dev/null @@ -1,47 +0,0 @@ - - - diff --git a/src/views/demo/steps/index.vue b/src/views/demo/steps/index.vue deleted file mode 100644 index 9ddad38a3..000000000 --- a/src/views/demo/steps/index.vue +++ /dev/null @@ -1,38 +0,0 @@ - - diff --git a/src/views/demo/system/account/AccountDetail.vue b/src/views/demo/system/account/AccountDetail.vue deleted file mode 100644 index f0af48270..000000000 --- a/src/views/demo/system/account/AccountDetail.vue +++ /dev/null @@ -1,61 +0,0 @@ - - - - - diff --git a/src/views/demo/system/account/AccountModal.vue b/src/views/demo/system/account/AccountModal.vue deleted file mode 100644 index ffaa6b644..000000000 --- a/src/views/demo/system/account/AccountModal.vue +++ /dev/null @@ -1,69 +0,0 @@ - - diff --git a/src/views/demo/system/account/DeptTree.vue b/src/views/demo/system/account/DeptTree.vue deleted file mode 100644 index d7bc6b821..000000000 --- a/src/views/demo/system/account/DeptTree.vue +++ /dev/null @@ -1,38 +0,0 @@ - - diff --git a/src/views/demo/system/account/account.data.ts b/src/views/demo/system/account/account.data.ts deleted file mode 100644 index f8990caa2..000000000 --- a/src/views/demo/system/account/account.data.ts +++ /dev/null @@ -1,156 +0,0 @@ -import { getAllRoleList, isAccountExist } from '@/api/demo/system' -import { BasicColumn, FormSchema } from '@/components/Table' - -/** - * transform mock data - * { - * 0: '华东分部', - * '0-0': '华东分部-研发部' - * '0-1': '华东分部-市场部', - * ... - * } - */ -export const deptMap = (() => { - const pDept = ['华东分部', '华南分部', '西北分部'] - const cDept = ['研发部', '市场部', '商务部', '财务部'] - - return pDept.reduce((map, p, pIdx) => { - map[pIdx] = p - - cDept.forEach((c, cIndex) => (map[`${pIdx}-${cIndex}`] = `${p}-${c}`)) - - return map - }, {}) -})() - -export const columns: BasicColumn[] = [ - { - title: '用户名', - dataIndex: 'account', - width: 120, - }, - { - title: '昵称', - dataIndex: 'nickname', - width: 120, - }, - { - title: '邮箱', - dataIndex: 'email', - width: 120, - }, - { - title: '创建时间', - dataIndex: 'createTime', - width: 180, - }, - { - title: '角色', - dataIndex: 'role', - width: 200, - }, - { - title: '所属部门', - dataIndex: 'dept', - customRender: ({ value }) => { - return deptMap[value] - }, - }, - { - title: '备注', - dataIndex: 'remark', - }, -] - -export const searchFormSchema: FormSchema[] = [ - { - field: 'account', - label: '用户名', - component: 'Input', - colProps: { span: 8 }, - }, - { - field: 'nickname', - label: '昵称', - component: 'Input', - colProps: { span: 8 }, - }, -] - -export const accountFormSchema: FormSchema[] = [ - { - field: 'account', - label: '用户名', - component: 'Input', - helpMessage: ['本字段演示异步验证', '不能输入带有admin的用户名'], - rules: [ - { - required: true, - message: '请输入用户名', - }, - { - trigger: 'blur', - validator(_, value) { - return new Promise((resolve, reject) => { - if (!value) return resolve() - isAccountExist(value) - .then(resolve) - .catch((err) => { - reject(err.message || '验证失败') - }) - }) - }, - }, - ], - }, - { - field: 'pwd', - label: '密码', - component: 'InputPassword', - required: true, - ifShow: false, - }, - { - label: '角色', - field: 'role', - component: 'ApiSelect', - componentProps: { - api: getAllRoleList, - labelField: 'roleName', - valueField: 'roleValue', - }, - required: true, - }, - { - field: 'dept', - label: '所属部门', - component: 'TreeSelect', - componentProps: { - fieldNames: { - label: 'deptName', - value: 'id', - }, - getPopupContainer: () => document.body, - }, - required: true, - }, - { - field: 'nickname', - label: '昵称', - component: 'Input', - required: true, - }, - - { - label: '邮箱', - field: 'email', - component: 'Input', - required: true, - }, - - { - label: '备注', - field: 'remark', - component: 'InputTextArea', - }, -] diff --git a/src/views/demo/system/account/index.vue b/src/views/demo/system/account/index.vue deleted file mode 100644 index 58d0d3f8d..000000000 --- a/src/views/demo/system/account/index.vue +++ /dev/null @@ -1,126 +0,0 @@ - - diff --git a/src/views/demo/system/dept/DeptModal.vue b/src/views/demo/system/dept/DeptModal.vue deleted file mode 100644 index f7bd7b407..000000000 --- a/src/views/demo/system/dept/DeptModal.vue +++ /dev/null @@ -1,58 +0,0 @@ - - diff --git a/src/views/demo/system/dept/dept.data.ts b/src/views/demo/system/dept/dept.data.ts deleted file mode 100644 index 92b99376c..000000000 --- a/src/views/demo/system/dept/dept.data.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { BasicColumn, FormSchema } from '@/components/Table' -import { h } from 'vue' -import { Tag } from 'ant-design-vue' - -export const columns: BasicColumn[] = [ - { - title: '部门名称', - dataIndex: 'deptName', - width: 160, - align: 'left', - }, - { - title: '排序', - dataIndex: 'orderNo', - width: 50, - }, - { - title: '状态', - dataIndex: 'status', - width: 80, - customRender: ({ record }) => { - const status = record.status - const enable = ~~status === 0 - const color = enable ? 'green' : 'red' - const text = enable ? '启用' : '停用' - return h(Tag, { color: color }, () => text) - }, - }, - { - title: '创建时间', - dataIndex: 'createTime', - width: 180, - }, - { - title: '备注', - dataIndex: 'remark', - }, -] - -export const searchFormSchema: FormSchema[] = [ - { - field: 'deptName', - label: '部门名称', - component: 'Input', - colProps: { span: 8 }, - }, - { - field: 'status', - label: '状态', - component: 'Select', - componentProps: { - options: [ - { label: '启用', value: '0' }, - { label: '停用', value: '1' }, - ], - }, - colProps: { span: 8 }, - }, -] - -export const formSchema: FormSchema[] = [ - { - field: 'deptName', - label: '部门名称', - component: 'Input', - required: true, - }, - { - field: 'parentDept', - label: '上级部门', - component: 'TreeSelect', - ifShow({ values }) { - const { deptName, parentDept } = values - // Hide without a parentDept when editing - return parentDept || (!deptName && !parentDept) - }, - componentProps: { - fieldNames: { - label: 'deptName', - value: 'id', - }, - getPopupContainer: () => document.body, - }, - required: true, - }, - { - field: 'orderNo', - label: '排序', - component: 'InputNumber', - required: true, - }, - { - field: 'status', - label: '状态', - component: 'RadioButtonGroup', - defaultValue: '0', - componentProps: { - options: [ - { label: '启用', value: '0' }, - { label: '停用', value: '1' }, - ], - }, - required: true, - }, - { - label: '备注', - field: 'remark', - component: 'InputTextArea', - }, -] diff --git a/src/views/demo/system/dept/index.vue b/src/views/demo/system/dept/index.vue deleted file mode 100644 index 49575b716..000000000 --- a/src/views/demo/system/dept/index.vue +++ /dev/null @@ -1,88 +0,0 @@ - - diff --git a/src/views/demo/system/menu/MenuDrawer.vue b/src/views/demo/system/menu/MenuDrawer.vue deleted file mode 100644 index 1760c017c..000000000 --- a/src/views/demo/system/menu/MenuDrawer.vue +++ /dev/null @@ -1,58 +0,0 @@ - - diff --git a/src/views/demo/system/menu/index.vue b/src/views/demo/system/menu/index.vue deleted file mode 100644 index fd875a923..000000000 --- a/src/views/demo/system/menu/index.vue +++ /dev/null @@ -1,96 +0,0 @@ - - diff --git a/src/views/demo/system/menu/menu.data.ts b/src/views/demo/system/menu/menu.data.ts deleted file mode 100644 index 97c1a9ce6..000000000 --- a/src/views/demo/system/menu/menu.data.ts +++ /dev/null @@ -1,200 +0,0 @@ -import { BasicColumn, FormSchema } from '@/components/Table' -import { h } from 'vue' -import { Tag } from 'ant-design-vue' -import Icon from '@/components/Icon/Icon.vue' - -export const columns: BasicColumn[] = [ - { - title: '菜单名称', - dataIndex: 'menuName', - width: 200, - align: 'left', - }, - { - title: '图标', - dataIndex: 'icon', - width: 50, - customRender: ({ record }) => { - return h(Icon, { icon: record.icon }) - }, - }, - { - title: '权限标识', - dataIndex: 'permission', - width: 180, - }, - { - title: '组件', - dataIndex: 'component', - }, - { - title: '排序', - dataIndex: 'orderNo', - width: 50, - }, - { - title: '状态', - dataIndex: 'status', - width: 80, - customRender: ({ record }) => { - const status = record.status - const enable = ~~status === 0 - const color = enable ? 'green' : 'red' - const text = enable ? '启用' : '停用' - return h(Tag, { color: color }, () => text) - }, - }, - { - title: '创建时间', - dataIndex: 'createTime', - width: 180, - }, -] - -const isDir = (type: string) => type === '0' -const isMenu = (type: string) => type === '1' -const isButton = (type: string) => type === '2' - -export const searchFormSchema: FormSchema[] = [ - { - field: 'menuName', - label: '菜单名称', - component: 'Input', - colProps: { span: 8 }, - }, - { - field: 'status', - label: '状态', - component: 'Select', - componentProps: { - options: [ - { label: '启用', value: '0' }, - { label: '停用', value: '1' }, - ], - }, - colProps: { span: 8 }, - }, -] - -export const formSchema: FormSchema[] = [ - { - field: 'type', - label: '菜单类型', - component: 'RadioButtonGroup', - defaultValue: '0', - componentProps: { - options: [ - { label: '目录', value: '0' }, - { label: '菜单', value: '1' }, - { label: '按钮', value: '2' }, - ], - }, - colProps: { lg: 24, md: 24 }, - }, - { - field: 'menuName', - label: '菜单名称', - component: 'Input', - required: true, - }, - - { - field: 'parentMenu', - label: '上级菜单', - component: 'TreeSelect', - componentProps: { - fieldNames: { - label: 'menuName', - value: 'id', - }, - getPopupContainer: () => document.body, - }, - }, - - { - field: 'orderNo', - label: '排序', - component: 'InputNumber', - required: true, - }, - { - field: 'icon', - label: '图标', - component: 'IconPicker', - required: true, - ifShow: ({ values }) => !isButton(values.type), - }, - - { - field: 'routePath', - label: '路由地址', - component: 'Input', - required: true, - ifShow: ({ values }) => !isButton(values.type), - }, - { - field: 'component', - label: '组件路径', - component: 'Input', - ifShow: ({ values }) => isMenu(values.type), - }, - { - field: 'permission', - label: '权限标识', - component: 'Input', - ifShow: ({ values }) => !isDir(values.type), - }, - { - field: 'status', - label: '状态', - component: 'RadioButtonGroup', - defaultValue: '0', - componentProps: { - options: [ - { label: '启用', value: '0' }, - { label: '禁用', value: '1' }, - ], - }, - }, - { - field: 'isExt', - label: '是否外链', - component: 'RadioButtonGroup', - defaultValue: '0', - componentProps: { - options: [ - { label: '否', value: '0' }, - { label: '是', value: '1' }, - ], - }, - ifShow: ({ values }) => !isButton(values.type), - }, - - { - field: 'keepalive', - label: '是否缓存', - component: 'RadioButtonGroup', - defaultValue: '0', - componentProps: { - options: [ - { label: '否', value: '0' }, - { label: '是', value: '1' }, - ], - }, - ifShow: ({ values }) => isMenu(values.type), - }, - - { - field: 'show', - label: '是否显示', - component: 'RadioButtonGroup', - defaultValue: '0', - componentProps: { - options: [ - { label: '是', value: '0' }, - { label: '否', value: '1' }, - ], - }, - ifShow: ({ values }) => !isButton(values.type), - }, -] diff --git a/src/views/demo/system/password/index.vue b/src/views/demo/system/password/index.vue deleted file mode 100644 index 2c0ae31e3..000000000 --- a/src/views/demo/system/password/index.vue +++ /dev/null @@ -1,41 +0,0 @@ - - diff --git a/src/views/demo/system/password/pwd.data.ts b/src/views/demo/system/password/pwd.data.ts deleted file mode 100644 index f53f54926..000000000 --- a/src/views/demo/system/password/pwd.data.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { FormSchema } from '@/components/Form' - -export const formSchema: FormSchema[] = [ - { - field: 'passwordOld', - label: '当前密码', - component: 'InputPassword', - required: true, - }, - { - field: 'passwordNew', - label: '新密码', - component: 'StrengthMeter', - componentProps: { - placeholder: '新密码', - }, - rules: [ - { - required: true, - message: '请输入新密码', - }, - ], - }, - { - field: 'confirmPassword', - label: '确认密码', - component: 'InputPassword', - - dynamicRules: ({ values }) => { - return [ - { - required: true, - validator: (_, value) => { - if (!value) { - return Promise.reject('密码不能为空') - } - if (value !== values.passwordNew) { - return Promise.reject('两次输入的密码不一致!') - } - return Promise.resolve() - }, - }, - ] - }, - }, -] diff --git a/src/views/demo/system/role/RoleDrawer.vue b/src/views/demo/system/role/RoleDrawer.vue deleted file mode 100644 index 66cda6ed2..000000000 --- a/src/views/demo/system/role/RoleDrawer.vue +++ /dev/null @@ -1,67 +0,0 @@ - - diff --git a/src/views/demo/system/role/index.vue b/src/views/demo/system/role/index.vue deleted file mode 100644 index 1be8ba1c3..000000000 --- a/src/views/demo/system/role/index.vue +++ /dev/null @@ -1,85 +0,0 @@ - - diff --git a/src/views/demo/system/role/role.data.ts b/src/views/demo/system/role/role.data.ts deleted file mode 100644 index 90794601f..000000000 --- a/src/views/demo/system/role/role.data.ts +++ /dev/null @@ -1,123 +0,0 @@ -import { BasicColumn, FormSchema } from '@/components/Table' -import { h } from 'vue' -import { Switch } from 'ant-design-vue' -import { setRoleStatus } from '@/api/demo/system' -import { useMessage } from '@/hooks/web/useMessage' - -type CheckedType = boolean | string | number -export const columns: BasicColumn[] = [ - { - title: '角色名称', - dataIndex: 'roleName', - width: 200, - }, - { - title: '角色值', - dataIndex: 'roleValue', - width: 180, - }, - { - title: '排序', - dataIndex: 'orderNo', - width: 50, - }, - { - title: '状态', - dataIndex: 'status', - width: 120, - customRender: ({ record }) => { - if (!Reflect.has(record, 'pendingStatus')) { - record.pendingStatus = false - } - return h(Switch, { - checked: record.status === '1', - checkedChildren: '停用', - unCheckedChildren: '启用', - loading: record.pendingStatus, - onChange(checked: CheckedType) { - record.pendingStatus = true - const newStatus = checked ? '1' : '0' - const { createMessage } = useMessage() - setRoleStatus(record.id, newStatus) - .then(() => { - record.status = newStatus - createMessage.success(`已成功修改角色状态`) - }) - .catch(() => { - createMessage.error('修改角色状态失败') - }) - .finally(() => { - record.pendingStatus = false - }) - }, - }) - }, - }, - { - title: '创建时间', - dataIndex: 'createTime', - width: 180, - }, - { - title: '备注', - dataIndex: 'remark', - }, -] - -export const searchFormSchema: FormSchema[] = [ - { - field: 'roleNme', - label: '角色名称', - component: 'Input', - colProps: { span: 8 }, - }, - { - field: 'status', - label: '状态', - component: 'Select', - componentProps: { - options: [ - { label: '启用', value: '1' }, - { label: '停用', value: '0' }, - ], - }, - colProps: { span: 8 }, - }, -] - -export const formSchema: FormSchema[] = [ - { - field: 'roleName', - label: '角色名称', - required: true, - component: 'Input', - }, - { - field: 'roleValue', - label: '角色值', - required: true, - component: 'Input', - }, - { - field: 'status', - label: '状态', - component: 'RadioButtonGroup', - defaultValue: '0', - componentProps: { - options: [ - { label: '启用', value: '1' }, - { label: '停用', value: '0' }, - ], - }, - }, - { - label: '备注', - field: 'remark', - component: 'InputTextArea', - }, - { - label: ' ', - field: 'menu', - slot: 'menu', - }, -] diff --git a/src/views/demo/system/vxe-account/index.vue b/src/views/demo/system/vxe-account/index.vue deleted file mode 100644 index 3db591397..000000000 --- a/src/views/demo/system/vxe-account/index.vue +++ /dev/null @@ -1,86 +0,0 @@ - - - diff --git a/src/views/demo/system/vxe-account/vxeAccount.data.ts b/src/views/demo/system/vxe-account/vxeAccount.data.ts deleted file mode 100644 index e078ecac6..000000000 --- a/src/views/demo/system/vxe-account/vxeAccount.data.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { VxeFormItemProps, VxeGridPropTypes } from '@/components/VxeTable' -import { deptMap } from '../account/account.data' - -export const columns: VxeGridPropTypes.Columns = [ - { - title: '用户名', - field: 'account', - width: 120, - }, - { - title: '昵称', - field: 'nickname', - width: 120, - }, - { - title: '邮箱', - field: 'email', - width: 120, - }, - { - title: '创建时间', - field: 'createTime', - width: 180, - }, - { - title: '角色', - field: 'role', - width: 200, - }, - { - title: '所属部门', - field: 'dept', - slots: { - default: ({ row }) => { - return deptMap[row.dept] - }, - }, - }, - { - title: '备注', - field: 'remark', - }, - { - width: 160, - title: '操作', - align: 'center', - slots: { default: 'action' }, - fixed: 'right', - }, -] - -export const searchFormSchema: VxeFormItemProps[] = [ - { - field: 'account', - title: '用户名', - itemRender: { - name: 'AInput', - }, - span: 6, - }, - { - field: 'nickname', - title: '昵称', - itemRender: { - name: 'AInput', - }, - span: 6, - }, - { - span: 12, - align: 'right', - className: '!pr-0', - itemRender: { - name: 'AButtonGroup', - children: [ - { - props: { type: 'primary', content: '查询', htmlType: 'submit' }, - attrs: { class: 'mr-2' }, - }, - { props: { type: 'default', htmlType: 'reset', content: '重置' } }, - ], - }, - }, -] diff --git a/src/views/demo/table/AuthColumn.vue b/src/views/demo/table/AuthColumn.vue deleted file mode 100644 index f49a0c8e1..000000000 --- a/src/views/demo/table/AuthColumn.vue +++ /dev/null @@ -1,150 +0,0 @@ - - diff --git a/src/views/demo/table/Basic.vue b/src/views/demo/table/Basic.vue deleted file mode 100644 index d7a99a86b..000000000 --- a/src/views/demo/table/Basic.vue +++ /dev/null @@ -1,65 +0,0 @@ - - diff --git a/src/views/demo/table/CustomerCell.vue b/src/views/demo/table/CustomerCell.vue deleted file mode 100644 index dfdfac4e7..000000000 --- a/src/views/demo/table/CustomerCell.vue +++ /dev/null @@ -1,97 +0,0 @@ - - diff --git a/src/views/demo/table/EditCellTable.vue b/src/views/demo/table/EditCellTable.vue deleted file mode 100644 index be96ea8c7..000000000 --- a/src/views/demo/table/EditCellTable.vue +++ /dev/null @@ -1,260 +0,0 @@ - - diff --git a/src/views/demo/table/EditRowTable.vue b/src/views/demo/table/EditRowTable.vue deleted file mode 100644 index a72016426..000000000 --- a/src/views/demo/table/EditRowTable.vue +++ /dev/null @@ -1,301 +0,0 @@ - - diff --git a/src/views/demo/table/ExpandTable.vue b/src/views/demo/table/ExpandTable.vue deleted file mode 100644 index 1f5783ad7..000000000 --- a/src/views/demo/table/ExpandTable.vue +++ /dev/null @@ -1,65 +0,0 @@ - - diff --git a/src/views/demo/table/FetchTable.vue b/src/views/demo/table/FetchTable.vue deleted file mode 100644 index 464d6f318..000000000 --- a/src/views/demo/table/FetchTable.vue +++ /dev/null @@ -1,31 +0,0 @@ - - diff --git a/src/views/demo/table/FixedColumn.vue b/src/views/demo/table/FixedColumn.vue deleted file mode 100644 index 73f2f3179..000000000 --- a/src/views/demo/table/FixedColumn.vue +++ /dev/null @@ -1,85 +0,0 @@ - - diff --git a/src/views/demo/table/FixedHeight.vue b/src/views/demo/table/FixedHeight.vue deleted file mode 100644 index dbb7bb96c..000000000 --- a/src/views/demo/table/FixedHeight.vue +++ /dev/null @@ -1,37 +0,0 @@ - - diff --git a/src/views/demo/table/FooterTable.vue b/src/views/demo/table/FooterTable.vue deleted file mode 100644 index f42153436..000000000 --- a/src/views/demo/table/FooterTable.vue +++ /dev/null @@ -1,41 +0,0 @@ - - diff --git a/src/views/demo/table/FormTable.vue b/src/views/demo/table/FormTable.vue deleted file mode 100644 index b0a7187f1..000000000 --- a/src/views/demo/table/FormTable.vue +++ /dev/null @@ -1,34 +0,0 @@ - - diff --git a/src/views/demo/table/MergeHeader.vue b/src/views/demo/table/MergeHeader.vue deleted file mode 100644 index 32f38384a..000000000 --- a/src/views/demo/table/MergeHeader.vue +++ /dev/null @@ -1,18 +0,0 @@ - - diff --git a/src/views/demo/table/MultipleHeader.vue b/src/views/demo/table/MultipleHeader.vue deleted file mode 100644 index 9634d4a48..000000000 --- a/src/views/demo/table/MultipleHeader.vue +++ /dev/null @@ -1,17 +0,0 @@ - - diff --git a/src/views/demo/table/RefTable.vue b/src/views/demo/table/RefTable.vue deleted file mode 100644 index 814a272ea..000000000 --- a/src/views/demo/table/RefTable.vue +++ /dev/null @@ -1,117 +0,0 @@ - - diff --git a/src/views/demo/table/ResizeParentHeightTable.vue b/src/views/demo/table/ResizeParentHeightTable.vue deleted file mode 100644 index b29042117..000000000 --- a/src/views/demo/table/ResizeParentHeightTable.vue +++ /dev/null @@ -1,67 +0,0 @@ - - diff --git a/src/views/demo/table/TreeTable.vue b/src/views/demo/table/TreeTable.vue deleted file mode 100644 index 3045ab8e2..000000000 --- a/src/views/demo/table/TreeTable.vue +++ /dev/null @@ -1,38 +0,0 @@ - - diff --git a/src/views/demo/table/UseTable.vue b/src/views/demo/table/UseTable.vue deleted file mode 100644 index 2230241e0..000000000 --- a/src/views/demo/table/UseTable.vue +++ /dev/null @@ -1,137 +0,0 @@ - - diff --git a/src/views/demo/table/VxeTable.vue b/src/views/demo/table/VxeTable.vue deleted file mode 100644 index f597045ed..000000000 --- a/src/views/demo/table/VxeTable.vue +++ /dev/null @@ -1,110 +0,0 @@ - - diff --git a/src/views/demo/table/tableData.tsx b/src/views/demo/table/tableData.tsx deleted file mode 100644 index 58a4e9e71..000000000 --- a/src/views/demo/table/tableData.tsx +++ /dev/null @@ -1,461 +0,0 @@ -import { optionsListApi } from '@/api/demo/select' -import { FormProps, FormSchema, BasicColumn } from '@/components/Table' -import { VxeFormItemProps, VxeGridPropTypes } from '@/components/VxeTable' -import { ref } from 'vue' -import { Input } from 'ant-design-vue' - -export function getBasicColumns(): BasicColumn[] { - return [ - { - title: 'ID', - dataIndex: 'id', - fixed: 'left', - width: 200, - }, - { - title: '姓名', - dataIndex: 'name', - width: 150, - filters: [ - { text: 'Male', value: 'male' }, - { text: 'Female', value: 'female' }, - ], - }, - { - title: '地址', - dataIndex: 'address', - }, - { - title: '编号', - dataIndex: 'no', - width: 150, - sorter: true, - defaultHidden: true, - }, - { - title: '开始时间', - width: 150, - sorter: true, - dataIndex: 'beginTime', - }, - { - title: '结束时间', - width: 150, - sorter: true, - dataIndex: 'endTime', - }, - ] -} - -export function getBasicShortColumns(): BasicColumn[] { - return [ - { - title: 'ID', - width: 150, - dataIndex: 'id', - sorter: true, - sortOrder: 'ascend', - }, - { - title: '姓名', - dataIndex: 'name', - width: 120, - }, - { - title: '地址', - dataIndex: 'address', - }, - { - title: '编号', - dataIndex: 'no', - width: 80, - }, - ] -} - -export function getMultipleHeaderColumns(): BasicColumn[] { - const testRef = ref('姓名:') - return [ - { - title: 'ID', - dataIndex: 'id', - width: 200, - }, - { - title: '姓名', - customHeaderRender() { - return - }, - dataIndex: 'name', - width: 120, - }, - { - title: '地址', - dataIndex: 'address', - sorter: true, - children: [ - { - title: '编号', - customHeaderRender(column) { - // 【自定义渲染的】 - return ( -
- _ {testRef.value} _{column.customTitle} -
- ) - }, - dataIndex: 'no', - width: 120, - filters: [ - { text: 'Male', value: 'male', children: [] }, - { text: 'Female', value: 'female', children: [] }, - ], - }, - - { - title: '开始时间', - dataIndex: 'beginTime', - width: 120, - }, - { - title: '结束时间', - dataIndex: 'endTime', - width: 120, - }, - ], - }, - ] -} - -export function getCustomHeaderColumns(): BasicColumn[] { - return [ - { - title: 'ID', - dataIndex: 'id', - helpMessage: 'headerHelpMessage方式1', - width: 200, - }, - { - // title: '姓名', - dataIndex: 'name', - width: 120, - }, - { - // title: '地址', - dataIndex: 'address', - width: 120, - sorter: true, - }, - - { - title: '编号', - dataIndex: 'no', - width: 120, - filters: [ - { text: 'Male', value: 'male', children: [] }, - { text: 'Female', value: 'female', children: [] }, - ], - }, - { - title: '开始时间', - dataIndex: 'beginTime', - width: 120, - }, - { - title: '结束时间', - dataIndex: 'endTime', - width: 120, - }, - ] -} - -const cellContent = (_, index) => ({ - colSpan: index === 9 ? 0 : 1, -}) - -export function getMergeHeaderColumns(): BasicColumn[] { - return [ - { - title: 'ID', - dataIndex: 'id', - width: 300, - customCell: (_, index) => ({ - colSpan: index === 9 ? 6 : 1, - }), - }, - { - title: '姓名', - dataIndex: 'name', - width: 300, - customCell: cellContent, - }, - { - title: '地址', - dataIndex: 'address', - colSpan: 2, - width: 120, - sorter: true, - customCell: (_, index) => ({ - rowSpan: index === 2 ? 2 : 1, - colSpan: index === 3 || index === 9 ? 0 : 1, - }), - }, - { - title: '编号', - dataIndex: 'no', - colSpan: 0, - filters: [ - { text: 'Male', value: 'male', children: [] }, - { text: 'Female', value: 'female', children: [] }, - ], - customCell: cellContent, - }, - { - title: '开始时间', - dataIndex: 'beginTime', - width: 200, - customCell: cellContent, - }, - { - title: '结束时间', - dataIndex: 'endTime', - width: 200, - customCell: cellContent, - }, - ] -} -export const getAdvanceSchema = (itemNumber = 6): FormSchema[] => { - const arr: FormSchema[] = [] - for (let index = 0; index < itemNumber; index++) { - arr.push({ - field: `field${index}`, - label: `字段${index}`, - component: 'Input', - colProps: { - xl: 12, - xxl: 8, - }, - }) - } - return arr -} -export function getFormConfig(): Partial { - return { - labelWidth: 100, - schemas: [ - ...getAdvanceSchema(5), - { - field: `field11`, - label: `Slot示例`, - slot: 'custom', - colProps: { - xl: 12, - xxl: 8, - }, - }, - ], - } -} -export function getBasicData() { - return (() => { - const arr: any = [] - for (let index = 0; index < 40; index++) { - arr.push({ - id: `${index}`, - name: 'John Brown', - age: `1${index}`, - no: `${index + 10}`, - address: 'New York No. 1 Lake ParkNew York No. 1 Lake Park', - beginTime: new Date().toLocaleString(), - endTime: new Date().toLocaleString(), - }) - } - return arr - })() -} - -export function getTreeTableData() { - return (() => { - const arr: any = [] - for (let index = 0; index < 40; index++) { - arr.push({ - id: `${index}`, - name: 'John Brown', - age: `1${index}`, - no: `${index + 10}`, - address: 'New York No. 1 Lake ParkNew York No. 1 Lake Park', - beginTime: new Date().toLocaleString(), - endTime: new Date().toLocaleString(), - children: [ - { - id: `l2-${index}-1`, - name: 'John Brown', - age: `1`, - no: `${index + 10}`, - address: 'New York No. 1 Lake ParkNew York No. 1 Lake Park', - beginTime: new Date().toLocaleString(), - endTime: new Date().toLocaleString(), - children: [ - { - id: `l3-${index}-1-1`, - name: 'John Brown', - age: `11`, - no: `11`, - address: 'New York No. 1 Lake ParkNew York No. 1 Lake Park', - beginTime: new Date().toLocaleString(), - endTime: new Date().toLocaleString(), - }, - { - id: `l3-${index}-1-2`, - name: 'John Brown', - age: `12`, - no: `12`, - address: 'New York No. 1 Lake ParkNew York No. 1 Lake Park', - beginTime: new Date().toLocaleString(), - endTime: new Date().toLocaleString(), - }, - ], - }, - { - id: `l2-${index}-2`, - name: 'John Brown', - age: `2`, - no: `${index + 10}`, - address: 'New York No. 1 Lake ParkNew York No. 1 Lake Park', - beginTime: new Date().toLocaleString(), - endTime: new Date().toLocaleString(), - children: [ - { - id: `l3-${index}-2-1`, - name: 'John Brown', - age: `21`, - no: `21`, - address: 'New York No. 1 Lake ParkNew York No. 1 Lake Park', - beginTime: new Date().toLocaleString(), - endTime: new Date().toLocaleString(), - }, - { - id: `l3-${index}-2-2`, - name: 'John Brown', - age: `22`, - no: `22`, - address: 'New York No. 1 Lake ParkNew York No. 1 Lake Park', - beginTime: new Date().toLocaleString(), - endTime: new Date().toLocaleString(), - }, - ], - }, - ], - }) - } - return arr - })() -} - -export const vxeTableColumns: VxeGridPropTypes.Columns = [ - { - title: '序号', - type: 'seq', - fixed: 'left', - width: '50', - align: 'center', - }, - { - title: '固定列', - field: 'name', - width: 150, - showOverflow: 'tooltip', - fixed: 'left', - }, - { - title: '自适应列', - field: 'address', - }, - { - title: '自定义列(自定义导出)', - field: 'no', - width: 200, - showOverflow: 'tooltip', - align: 'center', - slots: { - default: ({ row }) => { - const text = `自定义${row.no}` - return [
{text}
] - }, - }, - exportMethod: ({ row }) => { - return `自定义${row.no}导出` - }, - }, - { - title: '自定义编辑', - width: 150, - field: 'name1', - align: 'center', - editRender: { - name: 'AInput', - placeholder: '请点击输入', - }, - }, - { - title: '开始时间', - width: 150, - field: 'beginTime', - showOverflow: 'tooltip', - align: 'center', - }, - { - title: '结束时间', - width: 150, - field: 'endTime', - showOverflow: 'tooltip', - align: 'center', - }, - { - width: 160, - title: '操作', - align: 'center', - slots: { default: 'action' }, - fixed: 'right', - }, -] - -export const vxeTableFormSchema: VxeFormItemProps[] = [ - { - field: 'field0', - title: 'field0', - itemRender: { - name: 'AInput', - }, - span: 6, - }, - { - field: 'field1', - title: 'field1', - itemRender: { - name: 'AApiSelect', - props: { - api: optionsListApi, - resultField: 'list', - labelField: 'name', - valueField: 'id', - }, - }, - span: 6, - }, - { - span: 12, - align: 'right', - className: '!pr-0', - itemRender: { - name: 'AButtonGroup', - children: [ - { - props: { type: 'primary', content: '查询', htmlType: 'submit' }, - attrs: { class: 'mr-2' }, - }, - { props: { type: 'default', htmlType: 'reset', content: '重置' } }, - ], - }, - }, -] diff --git a/src/views/demo/tree/ActionTree.vue b/src/views/demo/tree/ActionTree.vue deleted file mode 100644 index 2bd84c88f..000000000 --- a/src/views/demo/tree/ActionTree.vue +++ /dev/null @@ -1,121 +0,0 @@ - - diff --git a/src/views/demo/tree/EditTree.vue b/src/views/demo/tree/EditTree.vue deleted file mode 100644 index ee7b42744..000000000 --- a/src/views/demo/tree/EditTree.vue +++ /dev/null @@ -1,112 +0,0 @@ - - diff --git a/src/views/demo/tree/data.ts b/src/views/demo/tree/data.ts deleted file mode 100644 index 3c3aef08f..000000000 --- a/src/views/demo/tree/data.ts +++ /dev/null @@ -1,119 +0,0 @@ -import { TreeItem } from '@/components/Tree' - -export const treeData: TreeItem[] = [ - { - title: 'parent ', - key: '0-0', - icon: 'ion:settings-outline', - children: [ - { title: 'leaf', key: '0-0-0' }, - { - title: 'leaf', - key: '0-0-1', - children: [ - { title: 'leaf', key: '0-0-0-0', children: [{ title: 'leaf', key: '0-0-0-0-1' }] }, - { title: 'leaf', key: '0-0-0-1' }, - ], - }, - ], - }, - { - title: 'parent 2', - key: '1-1', - children: [ - { title: 'leaf', key: '1-1-0' }, - { title: 'leaf', key: '1-1-1' }, - ], - }, - { - title: 'parent 3', - key: '2-2', - children: [ - { title: 'leaf', key: '2-2-0' }, - { title: 'leaf', key: '2-2-1' }, - ], - }, -] - -export const treeData2: any[] = [ - { - name: 'parent ', - id: '0-0', - - children: [ - { name: 'leaf', id: '0-0-0' }, - { - name: 'leaf', - id: '0-0-1', - - children: [ - { - name: 'leaf', - - id: '0-0-0-0', - children: [{ name: 'leaf', id: '0-0-0-0-1' }], - }, - { name: 'leaf', id: '0-0-0-1' }, - ], - }, - ], - }, - { - name: 'parent 2', - id: '1-1', - - children: [ - { name: 'leaf', id: '1-1-0' }, - { name: 'leaf', id: '1-1-1' }, - ], - }, - { - name: 'parent 3', - id: '2-2', - - children: [ - { name: 'leaf', id: '2-2-0' }, - { name: 'leaf', id: '2-2-1' }, - ], - }, -] - -export const treeData3: any[] = [ - { - name: 'parent ', - key: '0-0', - children: [ - { name: 'leaf', key: '0-0-0' }, - { - name: 'leaf', - key: '0-0-1', - children: [ - { - name: 'leaf', - key: '0-0-0-0', - children: [{ name: 'leaf', key: '0-0-0-0-1' }], - }, - { name: 'leaf', key: '0-0-0-1' }, - ], - }, - ], - }, - { - name: 'parent 2', - key: '1-1', - - children: [ - { name: 'leaf', key: '1-1-0' }, - { name: 'leaf', key: '1-1-1' }, - ], - }, - { - name: 'parent 3', - key: '2-2', - - children: [ - { name: 'leaf', key: '2-2-0' }, - { name: 'leaf', key: '2-2-1' }, - ], - }, -] diff --git a/src/views/demo/tree/index.vue b/src/views/demo/tree/index.vue deleted file mode 100644 index cf347bf13..000000000 --- a/src/views/demo/tree/index.vue +++ /dev/null @@ -1,115 +0,0 @@ - - diff --git a/src/views/hooks/request/base.tsx b/src/views/hooks/request/base.tsx deleted file mode 100644 index c750c69bb..000000000 --- a/src/views/hooks/request/base.tsx +++ /dev/null @@ -1,319 +0,0 @@ -import { defineComponent, onMounted, ref, unref } from 'vue' -import { Card, Spin, Typography, message, Input, Button, Space } from 'ant-design-vue' -import { imitateApi } from './mock-api' -import { useRequest } from '@vben/hooks' -import { PageWrapper } from '@/components/Page' - -const Demo1 = defineComponent({ - setup() { - const { data, error, loading } = useRequest(imitateApi) - - return () => ( - - - - useRequest - 的第一个参数是一个异步函数,在组件初次加载时,会自动触发该函数执行。同时自动管理该异步函数的 - loading - data - error - 等状态。 - - {`const { data, error, loading } = useRequest(imitateApi);`} - - - {/* 基础案例 */} - -
{error.value ? 'failed to load' : `Username: ${data.value}`}
-
-
- ) - }, -}) - -const Demo2 = defineComponent({ - setup() { - const search = ref('') - const setSearch = (value: string) => { - search.value = value - } - - const { loading, run } = useRequest(imitateApi, { - manual: true, - onSuccess: (result, params) => { - if (result) { - setSearch('') - message.success(`The username was changed to "${params[0]}" !`) - } - }, - }) - - return () => ( - - - - 如果设置了 - options.manual = true - ,则 useRequest 不会默认执行,需要通过 - run 来触发执行。 - - {`const { loading, run } = useRequest(imitateApi, { manual: true });`} - - - {/* 手动触发 */} - - - - - - ) - }, -}) - -const Demo3 = defineComponent({ - setup() { - const search = ref('') - const setSearch = (value: string) => { - search.value = value - } - - const { loading, run } = useRequest(imitateApi, { - manual: true, - onBefore: (params) => { - message.info(`Start Request: ${params[0]}`) - }, - onSuccess: (result, params) => { - if (result) { - setSearch('') - message.success(`The username was changed to "${params[0]}" !`) - } - }, - onError: (error) => { - message.error(error.message) - }, - onFinally: () => { - message.info(`Request finish`) - }, - }) - - return () => ( - - - - useRequest - 提供了以下几个生命周期配置项,供你在异步函数的不同阶段做一些处理。 - - - - onBefore - 请求之前触发 - - - - onSuccess - 请求成功触发 - - - - onError - 请求失败触发 - - - - onFinally - 请求完成触发 - - - - {/* 生命周期 */} - - - - - - - ) - }, -}) - -const Demo4 = defineComponent({ - setup() { - const { data, loading, run, refresh } = useRequest(imitateApi, { - manual: true, - }) - - onMounted(() => run('lutz')) - - const changeData = () => { - data.value = `${Date.now()}` - } - - return () => ( - - - - useRequest - 提供了 - refresh refreshAsync - 方法,使我们可以使用上一次的参数,重新发起请求。 - - - - - -
Username: {data.value}
- - -
-
-
- ) - }, -}) - -const Demo5 = defineComponent({ - setup() { - const search = ref('') - const setSearch = (value: string) => { - search.value = value - } - - const { loading, run, cancel } = useRequest(imitateApi, { - manual: true, - onSuccess: (result, params) => { - if (result) { - setSearch('') - message.success(`The username was changed to "${params[0]}" !`) - } - }, - }) - - return () => ( - - - - useRequest 提供了 - cancel 函数,用于忽略当前 promise 返回的数据和错误 - - - - {/* 取消响应 */} - - - - - - - ) - }, -}) - -const Demo6 = defineComponent({ - setup() { - const search = ref('') - - const { - data: username, - loading, - run, - params, - } = useRequest(imitateApi, { - defaultParams: ['lutz'], - }) - - const onChange = () => { - run(search.value) - } - - return () => ( - - - - useRequest 返回的 - params 会记录当次调用 - service 的参数数组。比如你触发了 - run(1, 2, 3),则 - params 等于 - [1, 2, 3] - - - 如果我们设置了 - options.manual = false ,则首次调用 - service - 的参数可以通过 options.defaultParams - 来设置。 - - - - {/* 管理参数 */} - - - - -
-
UserId: {unref(params)?.[0]}
-
Username: {unref(username)}
-
-
- ) - }, -}) - -export default defineComponent({ - setup() { - return () => ( - ( - - - ahooks{' '} - - useRequest 的 vue 版本,是一个强大的异步数据管理的 Hooks。 - -
    - {[ - '自动请求/手动请求', - '轮询', - '防抖', - '节流', - '屏幕聚焦重新请求', - '错误重试', - 'loading delay', - 'SWR(stale-while-revalidate)', - '缓存', - ].map((item) => ( -
  • - {item} -
  • - ))} -
-
-
- ), - }} - > - - - - - - -
- ) - }, -}) diff --git a/src/views/hooks/request/cache.tsx b/src/views/hooks/request/cache.tsx deleted file mode 100644 index b59c38d31..000000000 --- a/src/views/hooks/request/cache.tsx +++ /dev/null @@ -1,311 +0,0 @@ -import { defineComponent, ref, unref } from 'vue' -import { Card, Typography, Button, Input, Space, message } from 'ant-design-vue' -import { getArticle } from './mock-api' -import { useRequest, clearCache } from '@vben/hooks' -import { PageWrapper } from '@/components/Page' - -const Article1 = defineComponent({ - props: { - cacheKey: { - type: String, - default: 'cacheKey-demo', - }, - }, - setup(props) { - const { loading, data } = useRequest(getArticle, { - cacheKey: props.cacheKey, - }) - - return () => ( - <> -

Background loading: {loading.value ? 'true' : 'false'}

-

Latest request time: {unref(data)?.time}

-

{unref(data)?.data}

- - ) - }, -}) - -const Demo1 = defineComponent({ - setup() { - const state = ref(false) - const toggle = (bool?: boolean) => { - state.value = bool ?? !state.value - } - - return () => ( - - - - 下面的示例,我们设置了 - cacheKey - ,在组件第二次加载时,会优先返回缓存的内容,然后在背后重新发起请求。你可以通过点击按钮来体验效果。 - - - - {/* SWR */} -
- - {state.value && } -
-
- ) - }, -}) - -const Article2 = defineComponent({ - setup() { - const { loading, data } = useRequest(getArticle, { - cacheKey: 'staleTime-demo', - staleTime: 5000, - }) - - return () => ( - <> -

Background loading: {loading.value ? 'true' : 'false'}

-

Latest request time: {unref(data)?.time}

-

{unref(data)?.data}

- - ) - }, -}) - -const Demo2 = defineComponent({ - setup() { - const state = ref(false) - const toggle = (bool?: boolean) => { - state.value = bool ?? !state.value - } - - return () => ( - - - - 通过设置 - staleTime - ,我们可以指定数据新鲜时间,在这个时间内,不会重新发起请求。下面的示例设置了 5s 的新鲜时间,你可以通过点击按钮来体验效果 - - - - {/* 数据保持新鲜 */} -
- - {state.value && } -
-
- ) - }, -}) - -const Article3 = defineComponent({ - setup() { - const { loading, data, refresh } = useRequest(getArticle, { - cacheKey: 'cacheKey-share', - }) - - return () => ( - <> -

Background loading: {loading.value ? 'true' : 'false'}

- -

Latest request time: {unref(data)?.time}

-

{unref(data)?.data}

- - ) - }, -}) - -const Demo3 = defineComponent({ - setup() { - return () => ( - - - - 同一个 cacheKey - 的内容,在全局是共享的,这会带来以下几个特性 - - - -
    -
  • - 请求 Promise 共享,相同的 cacheKey - 同时只会有一个在发起请求,后发起的会共用同一个请求 Promise -
  • -
  • - 数据同步,任何时候,当我们改变其中某个 cacheKey 的内容时,其它相同 - cacheKey - 的内容均会同步 -
  • -
-
-
- - {/* 数据共享 */} -
-

Article 1

- -

Article 2

- -
-
- ) - }, -}) - -const Article4 = defineComponent({ - setup() { - const { loading, data, params, run } = useRequest(getArticle, { - cacheKey: 'cacheKey-share4', - }) - - const keyword = ref(params.value?.[0] || '') - - return () => ( - <> - - - - -

Background loading: {loading.value ? 'true' : 'false'}

-

Latest request time: {unref(data)?.time}

-

Latest request data: {unref(data)?.data}

-

keyword: {keyword.value}

- - ) - }, -}) - -const Demo4 = defineComponent({ - setup() { - const state = ref(false) - const toggle = (bool?: boolean) => { - state.value = bool ?? !state.value - } - - return () => ( - - - - 缓存的数据包括 data 和 params,通过 params 缓存机制,我们可以记忆上一次请求的条件,并在下次初始化 - - - - {/* 参数缓存 */} -
- -
{state.value && }
-
-
- ) - }, -}) - -const Demo5 = defineComponent({ - setup() { - const state = ref(false) - const toggle = (bool?: boolean) => { - state.value = bool ?? !state.value - } - - const clear = (cacheKey?: string | string[]) => { - clearCache(cacheKey) - const tips = Array.isArray(cacheKey) ? cacheKey.join('、') : cacheKey - message.success(`Clear ${tips ?? 'All'} finished`) - } - - return () => ( - - - useRequest 提供了一个 clearCache 方法,可以清除指定 cacheKey 的缓存数据。 - - - {/* 删除缓存 */} -
- - - - - - - -

Article 1

- {state.value && } -

Article 2

- {state.value && } -

Article 3

- {state.value && } -
-
- ) - }, -}) - -const Article6 = defineComponent({ - setup() { - const cacheKey = 'setCache-demo6' - const { loading, data } = useRequest(getArticle, { - cacheKey, - setCache: (data) => localStorage.setItem(cacheKey, JSON.stringify(data)), - getCache: () => JSON.parse(localStorage.getItem(cacheKey) || '{}'), - }) - - return () => ( - <> -

Background loading: {loading.value ? 'true' : 'false'}

-

Latest request time: {unref(data)?.time}

-

{unref(data)?.data}

- - ) - }, -}) - -const Demo6 = defineComponent({ - setup() { - const state = ref(false) - const toggle = (bool?: boolean) => { - state.value = bool ?? !state.value - } - - return () => ( - - - - 通过配置 setCache 和 getCache,可以自定义数据缓存,比如可以将数据存储到 localStorage、IndexDB 等。 - - - - {/* 自定义缓存 */} -
- -
{state.value && }
-
-
- ) - }, -}) - -export default defineComponent({ - setup() { - return () => ( - - - - - - - - - ) - }, -}) diff --git a/src/views/hooks/request/debounce.tsx b/src/views/hooks/request/debounce.tsx deleted file mode 100644 index 59dc6a268..000000000 --- a/src/views/hooks/request/debounce.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import { defineComponent, ref } from 'vue' -import { Card, Typography, Input, Spin, Space } from 'ant-design-vue' -import { imitateApi } from './mock-api' -import { useRequest } from '@vben/hooks' -import { PageWrapper } from '@/components/Page' - -const Demo1 = defineComponent({ - setup() { - const search = ref('') - - const { data, loading } = useRequest(imitateApi, { - debounceWait: 1000, - refreshDeps: [search], - }) - - return () => ( - - - - 通过设置 options.debounceWait - ,进入防抖模式,此时如果频繁触发 - run - 或者 - runAsync - 则会以防抖策略进行请求。 - - - - {`const { data, run } = useRequest(imitateApi, { debounceWait: 300, manual: true });`} - - - - 如上示例代码,频繁触发 - run , 300ms 执行一次。 - - - 你可以在下面 input 框中快速输入文本,体验效果 - - - {/* 防抖 */} - - - -
Username: {data.value}
-
-
-
- ) - }, -}) - -export default defineComponent({ - setup() { - return () => ( - - - - ) - }, -}) diff --git a/src/views/hooks/request/loading-delay.tsx b/src/views/hooks/request/loading-delay.tsx deleted file mode 100644 index 418f66888..000000000 --- a/src/views/hooks/request/loading-delay.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { defineComponent, unref } from 'vue' -import { Card, Typography, Button, Space } from 'ant-design-vue' -import { useRequest } from '@vben/hooks' -import { PageWrapper } from '@/components/Page' -import { imitateApi } from './mock-api' - -export default defineComponent({ - setup() { - const action = useRequest(imitateApi) - - const withLoadingDelayAction = useRequest(imitateApi, { - loadingDelay: 300, - }) - - const trigger = () => { - action.run('lutz') - withLoadingDelayAction.run('lutz') - } - - return () => ( - - - - - 通过设置 - options.loadingDelay - 可以延迟 loading 变成 - true - 的时间,有效防止闪烁。 - - - - {`const { loading, data } = useRequest(imitateApi, { loadingDelay: 300 });`} - - - - 例如上面的场景,假如 imitateApi 在 300ms 内返回,则 loading 不会变成{' '} - true Loading... 的情况。 - - - - - - -
Username: {unref(action.loading) ? 'Loading...' : unref(action.data)}
- -
Username: {unref(withLoadingDelayAction.loading) ? 'Loading...' : unref(withLoadingDelayAction.data)}
-
-
-
- ) - }, -}) diff --git a/src/views/hooks/request/mock-api.ts b/src/views/hooks/request/mock-api.ts deleted file mode 100644 index 4833f53ab..000000000 --- a/src/views/hooks/request/mock-api.ts +++ /dev/null @@ -1,25 +0,0 @@ -import Mock from 'mockjs' - -export async function imitateApi(username?: string, pass: boolean = true): Promise { - return new Promise((resolve, reject) => { - setTimeout(() => { - if (pass) { - resolve(username ?? Mock.mock('@name')) - } else { - reject(new Error(`Failed to modify username: ${username}`)) - } - }, 1250) - }) -} - -export async function getArticle(keyword?: string): Promise<{ data: string; time: number; keyword?: string }> { - return new Promise((resolve) => { - setTimeout(() => { - resolve({ - data: Mock.mock('@paragraph'), - time: new Date().getTime(), - keyword, - }) - }, 1000) - }) -} diff --git a/src/views/hooks/request/polling.tsx b/src/views/hooks/request/polling.tsx deleted file mode 100644 index 3348ca15a..000000000 --- a/src/views/hooks/request/polling.tsx +++ /dev/null @@ -1,94 +0,0 @@ -import { defineComponent } from 'vue' -import { Card, Typography, Button, Space, message } from 'ant-design-vue' -import { imitateApi } from './mock-api' -import { useRequest } from '@vben/hooks' -import { PageWrapper } from '@/components/Page' - -const Demo1 = defineComponent({ - setup() { - const { data, loading, run, cancel } = useRequest(imitateApi, { - pollingInterval: 1000, - pollingWhenHidden: false, - // onSuccess() { - // console.log('不可见是否运行呢'); // 测试不可见时,是否还在执行 - // }, - }) - - return () => ( - - - - 通过设置 - options.pollingInterval - ,进入轮询模式,useRequest 会定时触发 service 执行。 - - - {`const { data, run, cancel } = useRequest(imitateApi, { pollingInterval: 3000 });`} - - - -
-
Username: {loading.value ? 'Loading' : data.value}
- - - - -
-
- ) - }, -}) - -const Demo2 = defineComponent({ - setup() { - const { data, loading, run, cancel } = useRequest(imitateApi, { - manual: true, - pollingInterval: 3000, - pollingErrorRetryCount: 3, - pollingWhenHidden: false, - onError: (error) => { - message.error(error.message) - }, - }) - - return () => ( - - - - 通过 - options.pollingErrorRetryCount - 轮询错误重试次数。 - - - - {`const { data, run, cancel } = useRequest(imitateApi, { pollingInterval: 3000, pollingErrorRetryCount: 3 });`} - - - - -
-
Username: {loading.value ? 'Loading' : data.value}
- - - - -
-
- ) - }, -}) - -export default defineComponent({ - setup() { - return () => ( - - - - - ) - }, -}) diff --git a/src/views/hooks/request/ready.tsx b/src/views/hooks/request/ready.tsx deleted file mode 100644 index 9983ccf7f..000000000 --- a/src/views/hooks/request/ready.tsx +++ /dev/null @@ -1,85 +0,0 @@ -import { defineComponent, ref, unref } from 'vue' -import { Card, Typography, Button, Space } from 'ant-design-vue' -import { imitateApi } from './mock-api' -import { useRequest } from '@vben/hooks' -import { PageWrapper } from '@/components/Page' - -const Demo1 = defineComponent({ - setup() { - const ready = ref(false) - const toggle = (bool?: boolean) => { - ready.value = bool ?? !ready.value - } - const { data, loading } = useRequest(imitateApi, { ready }) - - return () => ( - - - - 以下示例演示了自动模式下 - ready 的行为。每次 - ready 从 false 变为 true 时,都会重新发起请求。 - - - -
- -
Ready: {JSON.stringify(unref(ready))}
- -
-
Username: {loading.value ? 'Loading' : unref(data)}
-
-
- ) - }, -}) - -const Demo2 = defineComponent({ - setup() { - const ready = ref(false) - const toggle = (bool?: boolean) => { - ready.value = bool ?? !ready.value - } - const { data, loading, run } = useRequest(imitateApi, { manual: true, ready }) - - return () => ( - - - - 以下示例演示了手动模式下 - ready - 的行为。只有当 - ready - 等于 true 时,run 才会执行。 - - - -
- -
Ready: {JSON.stringify(unref(ready))}
- -
-
- -
Username: {loading.value ? 'Loading' : unref(data)}
- -
-
-
-
- ) - }, -}) - -export default defineComponent({ - setup() { - return () => ( - - - - - ) - }, -}) diff --git a/src/views/hooks/request/refresh-on-window-focus.tsx b/src/views/hooks/request/refresh-on-window-focus.tsx deleted file mode 100644 index bebabe948..000000000 --- a/src/views/hooks/request/refresh-on-window-focus.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import { defineComponent } from 'vue' -import { Card, Typography, Spin } from 'ant-design-vue' -import { imitateApi } from './mock-api' -import { useRequest } from '@vben/hooks' -import { PageWrapper } from '@/components/Page' - -const Demo1 = defineComponent({ - setup() { - const { data, loading } = useRequest(imitateApi, { - refreshOnWindowFocus: true, - }) - - return () => ( - - - - 通过设置 options.refreshOnWindowFocus - ,在浏览器窗口 refocus 和 revisible 时, 会重新发起请求。 - - - - {`const { data, run } = useRequest(imitateApi, { refreshOnWindowFocus: true });`} - - - - 你可以点击浏览器外部,再点击当前页面来体验效果(或者隐藏当前页面,重新展示),如果和上一次请求间隔大于 5000ms, 则会重新请求一次。 - - - - {/* 屏幕聚焦重新请求 */} - -
Username: {data.value}
-
-
- ) - }, -}) - -export default defineComponent({ - setup() { - return () => ( - - - - ) - }, -}) diff --git a/src/views/hooks/request/refresy-deps.tsx b/src/views/hooks/request/refresy-deps.tsx deleted file mode 100644 index 5872bdc42..000000000 --- a/src/views/hooks/request/refresy-deps.tsx +++ /dev/null @@ -1,163 +0,0 @@ -import { computed, defineComponent, reactive, ref, unref } from 'vue' -import { Button, Card, Typography, Select } from 'ant-design-vue' -import { imitateApi } from './mock-api' -import { useRequest } from '@vben/hooks' -import { PageWrapper } from '@/components/Page' - -const options = [ - { label: 'Jack', value: 'Jack' }, - { label: 'Lucy', value: 'Lucy' }, - { label: 'Lutz', value: 'Lutz' }, -] - -const Demo1 = defineComponent({ - setup() { - const select = ref('Lutz') - const { data, loading } = useRequest(() => imitateApi(select.value), { refreshDeps: [select] }) - - return () => ( - - - - useRequest 提供了一个 - options.refreshDeps - 参数,当它的值变化后,会重新触发请求。 - - - -
-                {`const select = ref('Lutz');
-const { data, loading } = useRequest(() => imitateApi(select.value), {
-  refreshDeps: [select]
-});`}
-              
-
-
-
- - - - -
- ) - }, -}) - -export default defineComponent({ - setup() { - return () => ( - ( - - - 通过设置 - options.retryCount - ,指定错误重试次数,则 useRequest 在失败后会进行重试。 - - - -
-                    {`// useRequestOption
-retryCount?: number; // -1, 无限次重试
-retryInterval?: number; // 重试时间间隔,单位为毫秒。如果不设置,默认采用简易的指数退避算法`}
-                  
-
-
-
- ), - }} - > - -
- ) - }, -}) diff --git a/src/views/hooks/request/throttle.tsx b/src/views/hooks/request/throttle.tsx deleted file mode 100644 index d329c76e4..000000000 --- a/src/views/hooks/request/throttle.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { defineComponent, ref } from 'vue' -import { Card, Typography, Input, Spin, Space } from 'ant-design-vue' -import { imitateApi } from './mock-api' -import { useRequest } from '@vben/hooks' -import { PageWrapper } from '@/components/Page' - -const Demo1 = defineComponent({ - setup() { - const search = ref('') - - const { data, loading } = useRequest(imitateApi, { - throttleWait: 1000, - refreshDeps: [search], - }) - - return () => ( - - - - 通过设置 - options.throttleWait - ,进入节流模式,此时如果频繁触发 - run 或者 - runAsync , 则会以节流策略进行请求。 - - - - {`const { data, run } = useRequest(imitateApi, { throttleWait: 300, manual: true });`} - - - - 如上示例代码,频繁触发 - run , 300ms 执行一次。 - - - 你可以在下面 input 框中快速输入文本,体验效果 - - - {/* 节流 */} - - - -
Username: {data.value}
-
-
-
- ) - }, -}) - -export default defineComponent({ - setup() { - return () => ( - - - - ) - }, -}) diff --git a/src/views/sys/login/Login.vue b/src/views/sys/login/Login.vue index 10bba3944..0273728b8 100644 --- a/src/views/sys/login/Login.vue +++ b/src/views/sys/login/Login.vue @@ -2,7 +2,7 @@
- +
@@ -14,13 +14,11 @@
@@ -28,11 +26,12 @@ :class="`${prefixCls}-form`" class="relative w-full px-5 py-8 mx-auto my-auto rounded-md shadow-md xl:ml-16 xl:bg-transparent sm:px-8 xl:p-4 xl:shadow-none sm:w-3/4 lg:w-2/4 xl:w-auto enter-x" > + + + - -
@@ -40,16 +39,12 @@ diff --git a/src/views/sys/login/LoginForm.vue b/src/views/sys/login/LoginForm.vue index 084c3556d..52b651c31 100644 --- a/src/views/sys/login/LoginForm.vue +++ b/src/views/sys/login/LoginForm.vue @@ -1,134 +1,156 @@