From c6fd17e45e3e685990a3acaa201656e4cda7ef37 Mon Sep 17 00:00:00 2001 From: Bunny <1319900154@qq.com> Date: Thu, 27 Feb 2025 22:37:19 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BF=AE=E6=94=B9=E5=9F=BA=E6=9C=AC?= =?UTF-8?q?=E9=85=8D=E7=BD=AE;=E5=8A=A0=E5=85=A5mock?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env | 13 +- .env.development | 13 +- .env.production | 17 ++- build/css.ts | 41 +++--- build/plugins.ts | 18 ++- mock/user.ts | 19 +++ package.json | 3 + pnpm-lock.yaml | 131 +++++++++++++++++++ src/{utils => api/server}/request.ts | 40 +++--- src/api/server/requestMock.ts | 68 ++++++++++ src/api/test.ts | 6 + src/assets/styles/animations/animations.scss | 1 + src/assets/styles/animations/src/rotate.scss | 19 +++ src/assets/styles/common/common.scss | 3 + src/assets/styles/common/src/element.scss | 10 ++ src/assets/styles/global.scss | 2 + src/enums/CacheEnum.ts | 4 + src/enums/ResultEnum.ts | 9 ++ src/layout/index.vue | 17 ++- src/plugins/autofit.ts | 15 +++ src/plugins/index.ts | 5 +- src/store/modules/user.ts | 21 +++ src/types/global.d.ts | 3 + src/types/request/index.d.ts | 6 + uno.config.ts | 15 ++- 25 files changed, 444 insertions(+), 55 deletions(-) create mode 100644 mock/user.ts rename src/{utils => api/server}/request.ts (62%) create mode 100644 src/api/server/requestMock.ts create mode 100644 src/api/test.ts create mode 100644 src/assets/styles/animations/animations.scss create mode 100644 src/assets/styles/animations/src/rotate.scss create mode 100644 src/assets/styles/common/common.scss create mode 100644 src/assets/styles/common/src/element.scss create mode 100644 src/assets/styles/global.scss create mode 100644 src/enums/CacheEnum.ts create mode 100644 src/enums/ResultEnum.ts create mode 100644 src/plugins/autofit.ts create mode 100644 src/store/modules/user.ts create mode 100644 src/types/request/index.d.ts diff --git a/.env b/.env index 4045c4a..c7028d7 100644 --- a/.env +++ b/.env @@ -13,11 +13,20 @@ VITE_APP_URL=http://localhost:8801 # 如果端口被占用会直接退出,而不是尝试下一个端口 VITE_STRICT_PORT=false -# 是否启用屏幕转vw适配 -VITE_POST_CSS_PX_TO_VIEWPORT8_PLUGIN=false +# 是否启用屏幕转vw适配,可以选择 postcss-px-to-viewport-8-plugin || autofit +VITE_POST_CSS_PX_TO_VIEWPORT8_PLUGIN="autofit" # 是否在打包时使用cdn替换本地库 替换 true 不替换 false VITE_CDN=false +# 是否使用Mock +VITE_MOCK_DEV_SERVER=true + +# mock地址 +VITE_MOCK_BASE_API=/mock + +# 基础请求路径 +VITE_APP_BASE_API=/api + # 是否启用gzip压缩 VITE_COMPRESSION=gzip \ No newline at end of file diff --git a/.env.development b/.env.development index 160e4e2..2d6d599 100644 --- a/.env.development +++ b/.env.development @@ -7,11 +7,20 @@ VITE_PUBLIC_PATH=/ # 跨域代理地址 VITE_APP_URL=http://localhost:8801 +# 基础请求路径 +VITE_APP_BASE_API=/api + +# mock地址 +VITE_MOCK_BASE_API=/mock + +# 是否使用Mock +VITE_MOCK_DEV_SERVER=true + # 如果端口被占用会直接退出,而不是尝试下一个端口 VITE_STRICT_PORT=false -# 是否启用屏幕转vw适配 -VITE_POST_CSS_PX_TO_VIEWPORT8_PLUGIN=false +# 是否启用屏幕转vw适配,可以选择 postcss-px-to-viewport-8-plugin || autofit +VITE_POST_CSS_PX_TO_VIEWPORT8_PLUGIN="autofit" # 是否在打包时使用cdn替换本地库 替换 true 不替换 false VITE_CDN=false diff --git a/.env.production b/.env.production index a694b76..229e046 100644 --- a/.env.production +++ b/.env.production @@ -1,17 +1,26 @@ # 平台本地运行端口号 -VITE_PORT=8800 +VITE_PORT=7000 # 开发环境读取配置文件路径 VITE_PUBLIC_PATH=/ # 跨域代理地址 -VITE_APP_URL=http://localhost:8000 +VITE_APP_URL=http://localhost:8801 + +# 基础请求路径 +VITE_APP_BASE_API=/api + +# 是否使用Mock +VITE_MOCK_DEV_SERVER=true + +# mock地址 +VITE_MOCK_BASE_API=/mock # 如果端口被占用会直接退出,而不是尝试下一个端口 VITE_STRICT_PORT=false -# 是否启用屏幕转vw适配 -VITE_POST_CSS_PX_TO_VIEWPORT8_PLUGIN=false +# 是否启用屏幕转vw适配,可以选择 postcss-px-to-viewport-8-plugin || autofit +VITE_POST_CSS_PX_TO_VIEWPORT8_PLUGIN="autofit" # 是否在打包时使用cdn替换本地库 替换 true 不替换 false VITE_CDN=false diff --git a/build/css.ts b/build/css.ts index b7bb5a4..818e645 100644 --- a/build/css.ts +++ b/build/css.ts @@ -17,23 +17,26 @@ export const css = (mode): CSSOptions => { const usePostCssPxToViewport8plugin = (mode): Plugin => { const { VITE_POST_CSS_PX_TO_VIEWPORT8_PLUGIN } = wrapperEnv(mode, 'VITE'); - return VITE_POST_CSS_PX_TO_VIEWPORT8_PLUGIN - ? postCssPxToViewport8plugin({ - unitToConvert: 'px', - viewportWidth: 1920, // 设计稿的宽度 - unitPrecision: 5, // 单位转换后保留的精度 - propList: ['*'], // 能转化为vw的属性列表 - viewportUnit: 'vw', // 希望使用的视口单位 - fontViewportUnit: 'vw', // 字体使用的视口单位 - selectorBlackList: [], // 需要忽略的CSS选择器,不会转为视口单位,使用原有的px等单位。 - minPixelValue: 1, // 设置最小的转换数值,如果为1的话,只有大于1的值会被转换 - mediaQuery: true, // 媒体查询里的单位是否需要转换单位 - replace: true, // 是否直接更换属性值,而不添加备用属性 - exclude: [/node_modules/], // 忽略某些文件夹下的文件或特定文件,例如 'node_modules' 下的文件 - include: [], // 如果设置了include,那将只有匹配到的文件才会被转换 - landscape: false, // 是否添加根据 landscapeWidth 生成的媒体查询条件 @media (orientation: landscape) - landscapeUnit: 'vw', // 横屏时使用的单位 - landscapeWidth: 1024, // 横屏时使用的视口宽度 - }) - : null; + const cssPxToVw = postCssPxToViewport8plugin({ + unitToConvert: 'px', + viewportWidth: 1920, // 设计稿的宽度 + unitPrecision: 5, // 单位转换后保留的精度 + propList: ['*'], // 能转化为vw的属性列表 + viewportUnit: 'vw', // 希望使用的视口单位 + fontViewportUnit: 'vw', // 字体使用的视口单位 + selectorBlackList: [], // 需要忽略的CSS选择器,不会转为视口单位,使用原有的px等单位。 + minPixelValue: 1, // 设置最小的转换数值,如果为1的话,只有大于1的值会被转换 + mediaQuery: true, // 媒体查询里的单位是否需要转换单位 + replace: true, // 是否直接更换属性值,而不添加备用属性 + exclude: [/node_modules/], // 忽略某些文件夹下的文件或特定文件,例如 'node_modules' 下的文件 + include: [], // 如果设置了include,那将只有匹配到的文件才会被转换 + landscape: false, // 是否添加根据 landscapeWidth 生成的媒体查询条件 @media (orientation: landscape) + landscapeUnit: 'vw', // 横屏时使用的单位 + landscapeWidth: 1024, // 横屏时使用的视口宽度 + }); + + switch (VITE_POST_CSS_PX_TO_VIEWPORT8_PLUGIN) { + case 'postcss-px-to-viewport-8-plugin': + return cssPxToVw; + } }; diff --git a/build/plugins.ts b/build/plugins.ts index a1aa8df..bc6b743 100644 --- a/build/plugins.ts +++ b/build/plugins.ts @@ -4,12 +4,13 @@ import vueJsx from '@vitejs/plugin-vue-jsx'; import { presetIcons, presetUno } from 'unocss'; import UnoCSS from 'unocss/vite'; import type { PluginOption } from 'vite'; +import { vitePluginFakeServer } from 'vite-plugin-fake-server'; import removeConsole from 'vite-plugin-remove-console'; import Inspector from 'vite-plugin-vue-inspector'; import { useCDN } from './cdn'; import { viteConsoleLog } from './info'; -import { compressPack, report } from './utils'; +import { compressPack, report, wrapperEnv } from './utils'; export const plugins = (mode): PluginOption[] => { return [ @@ -40,5 +41,20 @@ export const plugins = (mode): PluginOption[] => { ], }), compressPack(mode), + useMock(mode), ]; }; + +/** MOCK 服务 */ +const useMock = (mode) => { + const { VITE_MOCK_DEV_SERVER } = wrapperEnv(mode); + + return VITE_MOCK_DEV_SERVER + ? vitePluginFakeServer({ + logger: true, + include: 'mock', + infixName: false, + enableProd: true, // 线上支持mock + }) + : null; +}; diff --git a/mock/user.ts b/mock/user.ts new file mode 100644 index 0000000..5f444f4 --- /dev/null +++ b/mock/user.ts @@ -0,0 +1,19 @@ +import { defineFakeRoute } from 'vite-plugin-fake-server/client'; + +export default defineFakeRoute([ + { + url: '/mock/users', + methods: 'get', + response: () => ({ + code: 200, + data: { + userId: 2, + nickname: '系统管理员', + username: 'admin', + avatar: + 'https://foruda.gitee.com/images/1723603502796844527/03cdca2a_716974.gif?imageView2/1/w/80/h/80', + }, + message: '操作成功', + }), + }, +]); diff --git a/package.json b/package.json index 55fcfab..f7f7571 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "@unocss/reset": "^66.0.0", "@vitejs/plugin-vue-jsx": "^4.1.1", "animate.css": "^4.1.1", + "autofit.js": "^3.2.4", "axios": "^1.7.9", "boxen": "^8.0.1", "dayjs": "^1.11.13", @@ -36,6 +37,7 @@ "pinia-plugin-persistedstate": "^3.2.3", "postcss-px-to-viewport-8-plugin": "^1.2.5", "prettier": "^3.3.3", + "qs": "^6.14.0", "rimraf": "^5.0.10", "rollup-plugin-visualizer": "^5.14.0", "sass": "^1.77.8", @@ -47,6 +49,7 @@ "terser": "^5.39.0", "unocss": "^66.0.0", "vite-plugin-cdn-import": "^1.0.1", + "vite-plugin-fake-server": "^2.2.0", "vite-plugin-remove-console": "^2.2.0", "vite-plugin-vue-inspector": "^5.3.1", "vue": "^3.5.13", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a83294a..ee482b4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -29,6 +29,9 @@ importers: animate.css: specifier: ^4.1.1 version: 4.1.1 + autofit.js: + specifier: ^3.2.4 + version: 3.2.4 axios: specifier: ^1.7.9 version: 1.7.9 @@ -80,6 +83,9 @@ importers: prettier: specifier: ^3.3.3 version: 3.5.2 + qs: + specifier: ^6.14.0 + version: 6.14.0 rimraf: specifier: ^5.0.10 version: 5.0.10 @@ -113,6 +119,9 @@ importers: vite-plugin-cdn-import: specifier: ^1.0.1 version: 1.0.1(rollup@4.34.8)(vite@6.1.1(jiti@2.4.2)(sass@1.85.0)(terser@5.39.0)) + vite-plugin-fake-server: + specifier: ^2.2.0 + version: 2.2.0 vite-plugin-remove-console: specifier: ^2.2.0 version: 2.2.0 @@ -1088,6 +1097,9 @@ packages: asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + autofit.js@3.2.4: + resolution: {integrity: sha512-THNaA9w55nVNzhsajMgQjtg01VZmHG0jq+HtzDOK7SXCtCiuzDu6tzbGPmt0EbuIM+7oSlKUnfRnXKKGYv8/PA==} + axios@1.7.9: resolution: {integrity: sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==} @@ -1132,6 +1144,9 @@ packages: buffer@6.0.3: resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + bundle-import@0.0.2: + resolution: {integrity: sha512-XB3T6xlgqJHThyr2luo3pNAVhfN/Y2qFEsblrzUO5QZLpJtesget8jmGDImSairScy80ZKBDVcRdFzTzWv3v8A==} + cac@6.7.14: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} @@ -1143,6 +1158,10 @@ packages: resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} engines: {node: '>= 0.4'} + call-bound@1.0.3: + resolution: {integrity: sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==} + engines: {node: '>= 0.4'} + callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} @@ -1561,6 +1580,9 @@ packages: resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} engines: {node: '>= 0.4'} + get-tsconfig@4.10.0: + resolution: {integrity: sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==} + glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -1670,6 +1692,12 @@ packages: resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} engines: {node: '>=6'} + import-from-string@0.0.5: + resolution: {integrity: sha512-z59WIHImWhnGVswc0JoyI10Qn4A8xQw7OKrCFRQHvzGZhhEixX13OtXP9ud3Xjpn16CUoYfh5mTu3tnNODiSAw==} + + import-meta-resolve@4.1.0: + resolution: {integrity: sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==} + imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} @@ -1911,6 +1939,10 @@ packages: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} + ofetch@1.4.1: resolution: {integrity: sha512-QZj2DfGplQAr2oj9KzceK9Hwz6Whxazmn85yYeVuS3u9XTMOGMRx0kO95MQ+vLsj/S/NwBDMMLU5hpxvI6Tklw==} @@ -1959,6 +1991,10 @@ packages: resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} engines: {node: '>=16 || 14 >=14.18'} + path-to-regexp@8.2.0: + resolution: {integrity: sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==} + engines: {node: '>=16'} + path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} @@ -2071,6 +2107,10 @@ packages: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} + qs@6.14.0: + resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} + engines: {node: '>=0.6'} + queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -2098,6 +2138,9 @@ packages: resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} engines: {node: '>=8'} + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} @@ -2154,6 +2197,22 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} + side-channel-list@1.0.0: + resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.0: + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + engines: {node: '>= 0.4'} + signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} @@ -2413,6 +2472,9 @@ packages: peerDependencies: vite: '>=2.0.0' + vite-plugin-fake-server@2.2.0: + resolution: {integrity: sha512-RP691997Q207nenNMhg7cvYyBXZyjqXwApTBa+a9kHmILgcAU2w4TMRDiAhIU0HPLAAR5MHlWTEpxA9Tbf+v8g==} + vite-plugin-remove-console@2.2.0: resolution: {integrity: sha512-qgjh5pz75MdE9Kzs8J0kBwaCfifHV0ezRbB9rpGsIOxam+ilcGV7WOk91vFJXquzRmiKrFh3Hxlh0JJWAmXTbQ==} @@ -3538,6 +3600,8 @@ snapshots: asynckit@0.4.0: {} + autofit.js@3.2.4: {} + axios@1.7.9: dependencies: follow-redirects: 1.15.9 @@ -3594,6 +3658,11 @@ snapshots: base64-js: 1.5.1 ieee754: 1.2.1 + bundle-import@0.0.2: + dependencies: + get-tsconfig: 4.10.0 + import-from-string: 0.0.5 + cac@6.7.14: {} cacheable@1.8.8: @@ -3606,6 +3675,11 @@ snapshots: es-errors: 1.3.0 function-bind: 1.1.2 + call-bound@1.0.3: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + callsites@3.1.0: {} camelcase@8.0.0: {} @@ -4041,6 +4115,10 @@ snapshots: dunder-proto: 1.0.1 es-object-atoms: 1.1.1 + get-tsconfig@4.10.0: + dependencies: + resolve-pkg-maps: 1.0.0 + glob-parent@5.1.2: dependencies: is-glob: 4.0.3 @@ -4142,6 +4220,13 @@ snapshots: parent-module: 1.0.1 resolve-from: 4.0.0 + import-from-string@0.0.5: + dependencies: + esbuild: 0.24.2 + import-meta-resolve: 4.1.0 + + import-meta-resolve@4.1.0: {} + imurmurhash@0.1.4: {} ini@1.3.8: {} @@ -4333,6 +4418,8 @@ snapshots: object-assign@4.1.1: {} + object-inspect@1.13.4: {} + ofetch@1.4.1: dependencies: destr: 2.0.3 @@ -4388,6 +4475,8 @@ snapshots: lru-cache: 10.4.3 minipass: 7.1.2 + path-to-regexp@8.2.0: {} + path-type@4.0.0: {} pathe@1.1.2: {} @@ -4483,6 +4572,10 @@ snapshots: punycode@2.3.1: {} + qs@6.14.0: + dependencies: + side-channel: 1.1.0 + queue-microtask@1.2.3: {} readdirp@3.6.0: @@ -4499,6 +4592,8 @@ snapshots: resolve-from@5.0.0: {} + resolve-pkg-maps@1.0.0: {} + reusify@1.0.4: {} rimraf@5.0.10: @@ -4569,6 +4664,34 @@ snapshots: shebang-regex@3.0.0: {} + side-channel-list@1.0.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.3 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.3 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.0 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + signal-exit@4.1.0: {} sirv@3.0.1: @@ -4886,6 +5009,14 @@ snapshots: magic-string: 0.25.9 vite: 6.1.1(jiti@2.4.2)(sass@1.85.0)(terser@5.39.0) + vite-plugin-fake-server@2.2.0: + dependencies: + bundle-import: 0.0.2 + chokidar: 4.0.3 + path-to-regexp: 8.2.0 + picocolors: 1.1.1 + tinyglobby: 0.2.12 + vite-plugin-remove-console@2.2.0: {} vite-plugin-vue-inspector@5.3.1(vite@6.1.1(jiti@2.4.2)(sass@1.85.0)(terser@5.39.0)): diff --git a/src/utils/request.ts b/src/api/server/request.ts similarity index 62% rename from src/utils/request.ts rename to src/api/server/request.ts index 79ad1bf..72dae80 100644 --- a/src/utils/request.ts +++ b/src/api/server/request.ts @@ -2,8 +2,6 @@ import axios, { type AxiosResponse, type InternalAxiosRequestConfig } from 'axio import qs from 'qs'; import { TOKEN_KEY } from '@/enums/CacheEnum'; -import { ResultEnum } from '@/enums/ResultEnum'; -import { useUserStoreHook } from '@/store/modules/user'; // 创建 axios 实例 const service = axios.create({ @@ -36,33 +34,31 @@ service.interceptors.response.use( if (response.config.responseType === 'blob' || response.config.responseType === 'arraybuffer') { return response; } + // const { code, data, msg } = response.data; + // if (code === ResultEnum.SUCCESS) { + // return data; + // } - const { code, data, msg } = response.data; - if (code === ResultEnum.SUCCESS) { - return data; + if (response.status === 200) { + return response.data; } - ElMessage.error(msg || '系统出错'); - return Promise.reject(new Error(msg || 'Error')); + // ElMessage.error(msg || '系统出错'); + return Promise.reject(msg || 'Error'); }, (error: any) => { // 异常处理 if (error.response.data) { - const { code, msg } = error.response.data; - if (code === ResultEnum.TOKEN_INVALID) { - ElNotification({ - title: '提示', - message: '您的会话已过期,请重新登录', - type: 'info', - }); - useUserStoreHook() - .resetToken() - .then(() => { - location.reload(); - }); - } else { - ElMessage.error(msg || '系统出错'); - } + // const { code, msg } = error.response.data; + // if (code === ResultEnum.TOKEN_INVALID) { + // ElNotification({ + // title: '提示', + // message: '您的会话已过期,请重新登录', + // type: 'info', + // }); + // } else { + // ElMessage.error(msg || '系统出错'); + // } } return Promise.reject(error.message); } diff --git a/src/api/server/requestMock.ts b/src/api/server/requestMock.ts new file mode 100644 index 0000000..795bb34 --- /dev/null +++ b/src/api/server/requestMock.ts @@ -0,0 +1,68 @@ +import axios, { type AxiosResponse, type InternalAxiosRequestConfig } from 'axios'; +import qs from 'qs'; + +import { TOKEN_KEY } from '@/enums/CacheEnum'; + +// 创建 axios 实例 +const service = axios.create({ + baseURL: import.meta.env.VITE_MOCK_BASE_API, + timeout: 50000, + headers: { 'Content-Type': 'application/json;charset=utf-8' }, + paramsSerializer: (params) => { + return qs.stringify(params); + }, +}); + +// 请求拦截器 +service.interceptors.request.use( + (config: InternalAxiosRequestConfig) => { + const accessToken = localStorage.getItem(TOKEN_KEY); + if (accessToken) { + config.headers.Authorization = accessToken; + } + return config; + }, + (error: any) => { + return Promise.reject(error); + } +); + +// 响应拦截器 +service.interceptors.response.use( + (response: AxiosResponse) => { + // 检查配置的响应类型是否为二进制类型('blob' 或 'arraybuffer'), 如果是,直接返回响应对象 + if (response.config.responseType === 'blob' || response.config.responseType === 'arraybuffer') { + return response; + } + // const { code, data, msg } = response.data; + // if (code === ResultEnum.SUCCESS) { + // return data; + // } + + if (response.status === 200) { + return response.data; + } + + // ElMessage.error(msg || '系统出错'); + return Promise.reject(msg || 'Error'); + }, + (error: any) => { + // 异常处理 + if (error.response.data) { + // const { code, msg } = error.response.data; + // if (code === ResultEnum.TOKEN_INVALID) { + // ElNotification({ + // title: '提示', + // message: '您的会话已过期,请重新登录', + // type: 'info', + // }); + // } else { + // ElMessage.error(msg || '系统出错'); + // } + } + return Promise.reject(error.message); + } +); + +// 导出 axios 实例 +export default service; diff --git a/src/api/test.ts b/src/api/test.ts new file mode 100644 index 0000000..0da1960 --- /dev/null +++ b/src/api/test.ts @@ -0,0 +1,6 @@ +import request from '@/api/server/requestMock'; +import type { BaseResult } from '@/types/request'; + +export const user = () => { + return request>({ url: '/users', method: 'get' }); +}; diff --git a/src/assets/styles/animations/animations.scss b/src/assets/styles/animations/animations.scss new file mode 100644 index 0000000..81e9eb9 --- /dev/null +++ b/src/assets/styles/animations/animations.scss @@ -0,0 +1 @@ +@use "src/rotate"; \ No newline at end of file diff --git a/src/assets/styles/animations/src/rotate.scss b/src/assets/styles/animations/src/rotate.scss new file mode 100644 index 0000000..7782abf --- /dev/null +++ b/src/assets/styles/animations/src/rotate.scss @@ -0,0 +1,19 @@ +/* 旋转动画 */ +@keyframes rotate { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} + +/* 反向旋转动画 */ +@keyframes rotate-reverse { + from { + transform: rotate(0deg); + } + to { + transform: rotate(-360deg); + } +} diff --git a/src/assets/styles/common/common.scss b/src/assets/styles/common/common.scss new file mode 100644 index 0000000..936448b --- /dev/null +++ b/src/assets/styles/common/common.scss @@ -0,0 +1,3 @@ +@use "src/element"; + + diff --git a/src/assets/styles/common/src/element.scss b/src/assets/styles/common/src/element.scss new file mode 100644 index 0000000..3b7b9a2 --- /dev/null +++ b/src/assets/styles/common/src/element.scss @@ -0,0 +1,10 @@ +// 空心的虚线圆 +.dashed-circle { + width: 46px; /* 圆圈的宽度 */ + height: 46px; /* 圆圈的高度 */ + line-height: 40px; + font-size: 16px; + text-align: center; + border: 2px dashed; /* 边框宽度、样式和颜色 */ + border-radius: 50%; /* 将元素变成圆形 */ +} diff --git a/src/assets/styles/global.scss b/src/assets/styles/global.scss new file mode 100644 index 0000000..52d1fb2 --- /dev/null +++ b/src/assets/styles/global.scss @@ -0,0 +1,2 @@ +@use "animations/animations"; +@use "common/common"; \ No newline at end of file diff --git a/src/enums/CacheEnum.ts b/src/enums/CacheEnum.ts new file mode 100644 index 0000000..f587bd4 --- /dev/null +++ b/src/enums/CacheEnum.ts @@ -0,0 +1,4 @@ +/** + * 令牌缓存Key + */ +export const TOKEN_KEY = 'accessToken'; diff --git a/src/enums/ResultEnum.ts b/src/enums/ResultEnum.ts new file mode 100644 index 0000000..2d69b46 --- /dev/null +++ b/src/enums/ResultEnum.ts @@ -0,0 +1,9 @@ +/** 响应码枚举 */ +export const enum ResultEnum { + // 成功 + SUCCESS = '200', + // 错误 + ERROR = 'B0001', + // 令牌无效或过期 + TOKEN_INVALID = '209', +} diff --git a/src/layout/index.vue b/src/layout/index.vue index 5399073..9abb037 100644 --- a/src/layout/index.vue +++ b/src/layout/index.vue @@ -1,4 +1,14 @@ - + - - diff --git a/src/plugins/autofit.ts b/src/plugins/autofit.ts new file mode 100644 index 0000000..0deffb2 --- /dev/null +++ b/src/plugins/autofit.ts @@ -0,0 +1,15 @@ +import autofit from 'autofit.js'; + +/** 使用autoFit 做大屏*/ +export const autoFit = () => { + const hasAutoFit = import.meta.env.VITE_POST_CSS_PX_TO_VIEWPORT8_PLUGIN; + + if (hasAutoFit !== 'autofit') return null; + + autofit.init({ + dh: 1080, + dw: 1920, + el: 'body', + resize: true, + }); +}; diff --git a/src/plugins/index.ts b/src/plugins/index.ts index 38fb6b8..bab9d90 100644 --- a/src/plugins/index.ts +++ b/src/plugins/index.ts @@ -1,6 +1,8 @@ import type { App } from 'vue'; import { setupDirective } from '@/directive'; +import { autoFit } from '@/plugins/autofit'; +import { useEcharts } from '@/plugins/echarts'; import { setUpRouter } from '@/router'; import { setupStore } from '@/store'; @@ -13,6 +15,7 @@ export default { // 设置指令 setupDirective(app); // 根据需求引入echarts - // useEcharts(app); + useEcharts(app); + autoFit(); }, }; diff --git a/src/store/modules/user.ts b/src/store/modules/user.ts new file mode 100644 index 0000000..7890df7 --- /dev/null +++ b/src/store/modules/user.ts @@ -0,0 +1,21 @@ +import { defineStore } from 'pinia'; + +import { user } from '@/api/test'; + +/** 用户信息 */ +export const useUserStore = defineStore('userStore', { + state() { + return { + userinfo: {}, + }; + }, + getters: {}, + actions: { + async getUserInfo() { + const response = await user(); + if (response.code == 200) { + this.userinfo = response.data; + } + }, + }, +}); diff --git a/src/types/global.d.ts b/src/types/global.d.ts index b27c3ca..73fc7cd 100644 --- a/src/types/global.d.ts +++ b/src/types/global.d.ts @@ -5,8 +5,11 @@ declare global { VITE_PORT: number; VITE_PUBLIC_PATH: string; VITE_APP_URL: string; + VITE_APP_BASE_API: string; VITE_STRICT_PORT: boolean; VITE_POST_CSS_PX_TO_VIEWPORT8_PLUGIN: boolean; + VITE_MOCK_DEV_SERVER: boolean; + VITE_MOCK_BASE_API: string; VITE_CDN: boolean; VITE_COMPRESSION: string; } diff --git a/src/types/request/index.d.ts b/src/types/request/index.d.ts new file mode 100644 index 0000000..b8e4f79 --- /dev/null +++ b/src/types/request/index.d.ts @@ -0,0 +1,6 @@ +// 基础后端返回内容 +export interface BaseResult { + code: number; + data: T; + message: string; +} diff --git a/uno.config.ts b/uno.config.ts index 1e67797..a7e32fe 100644 --- a/uno.config.ts +++ b/uno.config.ts @@ -15,10 +15,23 @@ export default defineConfig({ 'flex-x-between': 'flex items-center justify-between', 'flex-x-around': 'flex items-center justify-around', 'flex-y-center': 'flex flex-col flex-wrap justify-center items-center', + 'flex-y-between': 'flex flex-col flex-wrap justify-between items-center', + 'flex-y-around': 'flex flex-col flex-wrap justify-around items-center', + 'wh-full': 'w-full h-full', }, theme: { colors: { - // ... + primary: '#027AFF', + 'primary-secondary': '#00FFFF', + info: '#7CC1FF', + warning: '#FFBE44', + 'warning-secondary': '#FEDB65', + }, + fontSizes: { + sm: 'font-size-[14px]', + base: 'font-size-[16px]', + lg: 'font-size-[18px]', + xl: 'font-size-[22px]', }, }, presets: [