Browse Source

refactor: axios methods and env

xiaoxian521 3 years ago
parent
commit
11bf711838

+ 1 - 13
.env

@@ -1,14 +1,2 @@
-# port
+# 项目本地运行端口号
 VITE_PORT = 8848
-# title
-VITE_TITLE = vue-pure-admin
-# version
-VITE_VERSION = 2.6.0
-# open
-VITE_OPEN = false
-
-# public path
-VITE_PUBLIC_PATH = /
-
-# Cross-domain proxy, you can configure multiple
-VITE_PROXY = [ ["/api", "http://127.0.0.1:3000" ] ]

+ 9 - 11
.env.development

@@ -1,14 +1,12 @@
-# port
+# 项目本地运行端口号
 VITE_PORT = 8848
-# title
-VITE_TITLE = vue-pure-admin
-# version
-VITE_VERSION = 2.6.0
-# open
-VITE_OPEN = false
-
-# public path
+
+# 开发环境读取配置文件路径
 VITE_PUBLIC_PATH = /
 
-# Cross-domain proxy, you can configure multiple
-VITE_PROXY = [ ["/api", "http://127.0.0.1:3000" ] ]
+# 开发环境代理
+VITE_PROXY_DOMAIN = /api
+
+# 开发环境后端地址
+VITE_PROXY_DOMAIN_REAL = "http://127.0.0.1:3000"
+

+ 5 - 2
.env.production

@@ -1,2 +1,5 @@
-# public path
-VITE_PUBLIC_PATH = /manages/
+# 线上环境项目打包路径
+VITE_PUBLIC_PATH = /
+
+# 线上环境后端地址
+VITE_PROXY_DOMAIN_REAL = ""

+ 16 - 9
build/utils.ts → build/index.ts

@@ -1,5 +1,12 @@
+// 处理环境变量
 const warpperEnv = (envConf: Recordable): ViteEnv => {
-  const ret: any = {};
+  // 此处为默认值,无需修改
+  const ret: ViteEnv = {
+    VITE_PORT: 8848,
+    VITE_PUBLIC_PATH: "",
+    VITE_PROXY_DOMAIN: "",
+    VITE_PROXY_DOMAIN_REAL: ""
+  };
 
   for (const envName of Object.keys(envConf)) {
     let realName = envConf[envName].replace(/\\n/g, "\n");
@@ -9,13 +16,6 @@ const warpperEnv = (envConf: Recordable): ViteEnv => {
     if (envName === "VITE_PORT") {
       realName = Number(realName);
     }
-    if (envName === "VITE_PROXY" && realName) {
-      try {
-        realName = JSON.parse(realName.replace(/'/g, '"'));
-      } catch (error) {
-        realName = "";
-      }
-    }
     ret[envName] = realName;
     if (typeof realName === "string") {
       process.env[envName] = realName;
@@ -25,8 +25,15 @@ const warpperEnv = (envConf: Recordable): ViteEnv => {
   }
   return ret;
 };
+
+// 跨域代理重写
+const regExps = (value: string, reg: string): string => {
+  return value.replace(new RegExp(reg, "g"), "");
+};
+
+// 环境变量
 const loadEnv = (): ViteEnv => {
   return import.meta.env;
 };
 
-export { loadEnv, warpperEnv };
+export { warpperEnv, regExps, loadEnv };

+ 0 - 19
build/proxy.ts

@@ -1,19 +0,0 @@
-type ProxyItem = [string, string];
-
-type ProxyList = ProxyItem[];
-
-const regExps = (value: string, reg: string): string => {
-  return value.replace(new RegExp(reg, "g"), "");
-};
-
-export function createProxy(list: ProxyList = []) {
-  const ret: any = {};
-  for (const [prefix, target] of list) {
-    ret[prefix] = {
-      target: target,
-      changeOrigin: true,
-      rewrite: (path: string) => regExps(path, prefix)
-    };
-  }
-  return ret;
-}

+ 4 - 0
package.json

@@ -46,6 +46,7 @@
     "element-plus": "1.2.0-beta.3",
     "element-resize-detector": "^1.2.3",
     "font-awesome": "^4.7.0",
+    "js-cookie": "^3.0.1",
     "lodash-es": "^4.17.21",
     "lowdb": "^3.0.0",
     "mitt": "^3.0.0",
@@ -54,6 +55,7 @@
     "path": "^0.12.7",
     "path-to-regexp": "^6.2.0",
     "pinia": "^2.0.0-rc.14",
+    "qs": "^6.10.1",
     "remixicon": "^2.5.0",
     "resize-observer-polyfill": "^1.5.1",
     "responsive-storage": "^1.0.11",
@@ -76,9 +78,11 @@
     "@commitlint/cli": "13.1.0",
     "@commitlint/config-conventional": "13.1.0",
     "@types/element-resize-detector": "1.1.3",
+    "@types/js-cookie": "^3.0.1",
     "@types/mockjs": "1.0.3",
     "@types/node": "14.14.14",
     "@types/nprogress": "0.2.0",
+    "@types/qs": "^6.9.7",
     "@typescript-eslint/eslint-plugin": "4.31.0",
     "@typescript-eslint/parser": "4.31.0",
     "@vitejs/plugin-vue": "^1.9.4",

+ 87 - 2
pnpm-lock.yaml

@@ -11,9 +11,11 @@ specifiers:
   "@logicflow/core": 0.7.1
   "@logicflow/extension": 0.7.1
   "@types/element-resize-detector": 1.1.3
+  "@types/js-cookie": ^3.0.1
   "@types/mockjs": 1.0.3
   "@types/node": 14.14.14
   "@types/nprogress": 0.2.0
+  "@types/qs": ^6.9.7
   "@typescript-eslint/eslint-plugin": 4.31.0
   "@typescript-eslint/parser": 4.31.0
   "@vitejs/plugin-vue": ^1.9.4
@@ -41,6 +43,7 @@ specifiers:
   eslint-plugin-vue: 7.17.0
   font-awesome: ^4.7.0
   husky: 7.0.2
+  js-cookie: ^3.0.1
   lint-staged: 11.1.2
   lodash-es: ^4.17.21
   lowdb: ^3.0.0
@@ -54,6 +57,7 @@ specifiers:
   postcss-import: 14.0.0
   prettier: 2.3.2
   pretty-quick: 3.1.1
+  qs: ^6.10.1
   remixicon: ^2.5.0
   resize-observer-polyfill: ^1.5.1
   responsive-storage: ^1.0.11
@@ -105,6 +109,7 @@ dependencies:
   element-plus: 1.2.0-beta.3_vue@3.2.21
   element-resize-detector: 1.2.3
   font-awesome: 4.7.0
+  js-cookie: 3.0.1
   lodash-es: 4.17.21
   lowdb: 3.0.0
   mitt: 3.0.0
@@ -113,6 +118,7 @@ dependencies:
   path: 0.12.7
   path-to-regexp: 6.2.0
   pinia: 2.0.2_typescript@4.4.2+vue@3.2.21
+  qs: 6.10.1
   remixicon: 2.5.0
   resize-observer-polyfill: 1.5.1
   responsive-storage: 1.0.11_vue@3.2.21
@@ -135,9 +141,11 @@ devDependencies:
   "@commitlint/cli": 13.1.0
   "@commitlint/config-conventional": 13.1.0
   "@types/element-resize-detector": 1.1.3
+  "@types/js-cookie": 3.0.1
   "@types/mockjs": 1.0.3
   "@types/node": 14.14.14
   "@types/nprogress": 0.2.0
+  "@types/qs": 6.9.7
   "@typescript-eslint/eslint-plugin": 4.31.0_f4e6dc0776b3600ef484e3c64a523136
   "@typescript-eslint/parser": 4.31.0_eslint@7.30.0+typescript@4.4.2
   "@vitejs/plugin-vue": 1.9.4_vite@2.6.14
@@ -1094,6 +1102,13 @@ packages:
       }
     dev: true
 
+  /@types/js-cookie/3.0.1:
+    resolution:
+      {
+        integrity: sha512-7wg/8gfHltklehP+oyJnZrz9XBuX5ZPP4zB6UsI84utdlkRYLnOm2HfpLXazTwZA+fpGn0ir8tGNgVnMEleBGQ==
+      }
+    dev: true
+
   /@types/json-schema/7.0.9:
     resolution:
       {
@@ -1173,6 +1188,13 @@ packages:
       }
     dev: true
 
+  /@types/qs/6.9.7:
+    resolution:
+      {
+        integrity: sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==
+      }
+    dev: true
+
   /@types/resolve/1.17.1:
     resolution:
       {
@@ -1958,6 +1980,16 @@ packages:
     engines: { node: ">=6" }
     dev: true
 
+  /call-bind/1.0.2:
+    resolution:
+      {
+        integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==
+      }
+    dependencies:
+      function-bind: 1.1.1
+      get-intrinsic: 1.1.1
+    dev: false
+
   /callsites/3.1.0:
     resolution:
       {
@@ -3604,7 +3636,6 @@ packages:
       {
         integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
       }
-    dev: true
 
   /functional-red-black-tree/1.0.1:
     resolution: { integrity: sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= }
@@ -3633,6 +3664,17 @@ packages:
     engines: { node: 6.* || 8.* || >= 10.* }
     dev: true
 
+  /get-intrinsic/1.1.1:
+    resolution:
+      {
+        integrity: sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==
+      }
+    dependencies:
+      function-bind: 1.1.1
+      has: 1.0.3
+      has-symbols: 1.0.2
+    dev: false
+
   /get-own-enumerable-property-symbols/3.0.2:
     resolution:
       {
@@ -3823,6 +3865,14 @@ packages:
     engines: { node: ">=8" }
     dev: true
 
+  /has-symbols/1.0.2:
+    resolution:
+      {
+        integrity: sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==
+      }
+    engines: { node: ">= 0.4" }
+    dev: false
+
   /has/1.0.3:
     resolution:
       {
@@ -3831,7 +3881,6 @@ packages:
     engines: { node: ">= 0.4.0" }
     dependencies:
       function-bind: 1.1.1
-    dev: true
 
   /hash-sum/2.0.0:
     resolution:
@@ -4176,6 +4225,14 @@ packages:
     resolution: { integrity: sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= }
     dev: true
 
+  /js-cookie/3.0.1:
+    resolution:
+      {
+        integrity: sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw==
+      }
+    engines: { node: ">=12" }
+    dev: false
+
   /js-tokens/4.0.0:
     resolution:
       {
@@ -4837,6 +4894,13 @@ packages:
     resolution: { integrity: sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4= }
     dev: true
 
+  /object-inspect/1.11.0:
+    resolution:
+      {
+        integrity: sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==
+      }
+    dev: false
+
   /on-finished/2.3.0:
     resolution: { integrity: sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= }
     engines: { node: ">= 0.8" }
@@ -5371,6 +5435,16 @@ packages:
     engines: { node: ">=0.6.0", teleport: ">=0.2.0" }
     dev: true
 
+  /qs/6.10.1:
+    resolution:
+      {
+        integrity: sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==
+      }
+    engines: { node: ">=0.6" }
+    dependencies:
+      side-channel: 1.0.4
+    dev: false
+
   /queue-microtask/1.2.3:
     resolution:
       {
@@ -5744,6 +5818,17 @@ packages:
     engines: { node: ">=8" }
     dev: true
 
+  /side-channel/1.0.4:
+    resolution:
+      {
+        integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==
+      }
+    dependencies:
+      call-bind: 1.0.2
+      get-intrinsic: 1.1.1
+      object-inspect: 1.11.0
+    dev: false
+
   /signal-exit/3.0.5:
     resolution:
       {

+ 4 - 4
src/api/mock.ts

@@ -1,11 +1,11 @@
 import { http } from "../utils/http";
 
 // 地图数据
-export const mapJson = (data?: object) => {
-  return http.request("get", "/getMapInfo", data);
+export const mapJson = (params?: object) => {
+  return http.request("get", "/getMapInfo", { params });
 };
 
 // echarts数据
-export const echartsJson = (data?: object) => {
-  return http.request("get", "/getEchartsInfo", data);
+export const echartsJson = (params?: object) => {
+  return http.request("get", "/getEchartsInfo", { params });
 };

+ 1 - 1
src/api/routes.ts

@@ -1,5 +1,5 @@
 import { http } from "../utils/http";
 
 export const getAsyncRoutes = (data?: object) => {
-  return http.request("get", "/getAsyncRoutes", data);
+  return http.request("get", "/getAsyncRoutes", { data });
 };

+ 10 - 1
src/api/user.ts

@@ -13,5 +13,14 @@ export const getVerify = (): userType => {
 
 // 登录
 export const getLogin = (data: object) => {
-  return http.request("post", "/login", data);
+  return http.request("post", "/login", { data });
 };
+
+// 刷新token
+export const refreshToken = (data: object) => {
+  return http.request("post", "/refreshToken", { data });
+};
+
+// export const searchVague = (data: object) => {
+//   return http.request("post", "/searchVague", { data });
+// };

+ 4 - 4
src/config/index.ts

@@ -1,6 +1,9 @@
 import { App } from "vue";
 import axios from "axios";
+import { loadEnv } from "@build/index";
+
 let config: object = {};
+const { VITE_PUBLIC_PATH } = loadEnv();
 
 const setConfig = (cfg?: unknown) => {
   config = Object.assign(config, cfg);
@@ -30,10 +33,7 @@ export const getServerConfig = async (app: App): Promise<undefined> => {
   return axios({
     baseURL: "",
     method: "get",
-    url:
-      process.env.NODE_ENV === "production"
-        ? "/manages/serverConfig.json"
-        : "/serverConfig.json"
+    url: `${VITE_PUBLIC_PATH}serverConfig.json`
   })
     .then(({ data: config }) => {
       let $config = app.config.globalProperties.$config;

+ 5 - 0
src/store/modules/types.ts

@@ -33,3 +33,8 @@ export type setType = {
   fixedHeader: boolean;
   hiddenSideBar: boolean;
 };
+
+export type userType = {
+  token: string;
+  name?: string;
+};

+ 84 - 0
src/store/modules/user.ts

@@ -0,0 +1,84 @@
+import { defineStore } from "pinia";
+import { store } from "/@/store";
+import { userType } from "./types";
+import { useRouter } from "vue-router";
+import { getLogin, refreshToken } from "/@/api/user";
+import { storageLocal, storageSession } from "/@/utils/storage";
+import { getToken, setToken, removeToken } from "/@/utils/auth";
+import { useMultiTagsStoreHook } from "/@/store/modules/multiTags";
+
+const data = getToken();
+let token = "";
+let name = "";
+if (data) {
+  const dataJson = JSON.parse(data);
+  if (dataJson) {
+    token = dataJson?.accessToken;
+    name = dataJson?.name ?? "admin";
+  }
+}
+
+export const useUserStore = defineStore({
+  id: "pure-user",
+  state: (): userType => ({
+    token,
+    name
+  }),
+  actions: {
+    SET_TOKEN(token) {
+      this.token = token;
+    },
+    SET_NAME(name) {
+      this.name = name;
+    },
+    // 登入
+    async loginByUsername(data) {
+      return new Promise<void>((resolve, reject) => {
+        getLogin(data)
+          .then(data => {
+            if (data) {
+              setToken(data);
+              resolve();
+            }
+          })
+          .catch(error => {
+            reject(error);
+          });
+      });
+    },
+    // 登出 清空缓存
+    logOut() {
+      this.token = "";
+      this.name = "";
+      removeToken();
+      storageLocal.clear();
+      storageSession.clear();
+      useMultiTagsStoreHook().handleTags("equal", [
+        {
+          path: "/welcome",
+          parentPath: "/",
+          meta: {
+            title: "message.hshome",
+            icon: "el-icon-s-home",
+            i18n: true,
+            showLink: true
+          }
+        }
+      ]);
+      useRouter().push("/login");
+    },
+    // 刷新token
+    async refreshToken(data) {
+      return refreshToken(data).then(data => {
+        if (data) {
+          setToken(data);
+          return data;
+        }
+      });
+    }
+  }
+});
+
+export function useUserStoreHook() {
+  return useUserStore(store);
+}

+ 43 - 0
src/utils/auth.ts

@@ -0,0 +1,43 @@
+import Cookies from "js-cookie";
+import { useUserStoreHook } from "/@/store/modules/user";
+
+const TokenKey = "authorized-token";
+
+type paramsMapType = {
+  name: string;
+  expires: number;
+  accessToken: string;
+};
+
+// 获取token
+export function getToken() {
+  // 此处与TokenKey相同,此写法解决初始化时Cookies中不存在TokenKey报错
+  return Cookies.get("authorized-token");
+}
+
+// 设置token以及过期时间(cookies、sessionStorage各一份)
+// 后端需要将用户信息和token以及过期时间都返回给前端,过期时间主要用于刷新token
+export function setToken(data) {
+  const { accessToken, expires, name } = data;
+  // 提取关键信息进行存储
+  const paramsMap: paramsMapType = {
+    name,
+    expires: Date.now() + parseInt(expires),
+    accessToken
+  };
+  const dataString = JSON.stringify(paramsMap);
+  useUserStoreHook().SET_TOKEN(accessToken);
+  useUserStoreHook().SET_NAME(name);
+  expires > 0
+    ? Cookies.set(TokenKey, dataString, {
+        expires: expires / 86400000
+      })
+    : Cookies.set(TokenKey, dataString);
+  sessionStorage.setItem(TokenKey, dataString);
+}
+
+// 删除token
+export function removeToken() {
+  Cookies.remove(TokenKey);
+  sessionStorage.removeItem(TokenKey);
+}

+ 25 - 0
src/utils/http/README.md

@@ -0,0 +1,25 @@
+## 用法
+
+### Get 请求
+
+```
+import { http } from "/@/utils/http";
+
+// params传参
+http.request('get', '/xxx', { params: param });
+
+// url拼接传参
+http.request('get', '/xxx?message=' + msg);
+```
+
+### Post 请求
+
+```
+import { http } from "/@/utils/http";
+
+// params传参
+http.request('get', '/xxx', { params: param });
+
+// data传参
+http.request('get', '/xxx', { data: param });
+```

+ 0 - 32
src/utils/http/config.ts

@@ -1,32 +0,0 @@
-import { AxiosRequestConfig } from "axios";
-import { excludeProps } from "./utils";
-/**
- * 默认配置
- */
-export const defaultConfig: AxiosRequestConfig = {
-  baseURL: "",
-  //10秒超时
-  timeout: 10000,
-  headers: {
-    Accept: "application/json, text/plain, */*",
-    "Content-Type": "application/json",
-    "X-Requested-With": "XMLHttpRequest"
-  }
-};
-
-export function genConfig(config?: AxiosRequestConfig): AxiosRequestConfig {
-  if (!config) {
-    return defaultConfig;
-  }
-
-  const { headers } = config;
-  if (headers && typeof headers === "object") {
-    defaultConfig.headers = {
-      ...defaultConfig.headers,
-      ...headers
-    };
-  }
-  return { ...excludeProps(config!, "headers"), ...defaultConfig };
-}
-
-export const METHODS = ["post", "get", "put", "delete", "option", "patch"];

+ 0 - 236
src/utils/http/core.ts

@@ -1,236 +0,0 @@
-import Axios, {
-  AxiosRequestConfig,
-  CancelTokenStatic,
-  AxiosInstance
-} from "axios";
-
-import NProgress from "../progress";
-
-import { genConfig } from "./config";
-
-import { transformConfigByMethod } from "./utils";
-
-import {
-  cancelTokenType,
-  RequestMethods,
-  EnclosureHttpRequestConfig,
-  EnclosureHttpResoponse,
-  EnclosureHttpError
-} from "./types.d";
-
-class EnclosureHttp {
-  constructor() {
-    this.httpInterceptorsRequest();
-    this.httpInterceptorsResponse();
-  }
-  // 初始化配置对象
-  private static initConfig: EnclosureHttpRequestConfig = {};
-
-  // 保存当前Axios实例对象
-  private static axiosInstance: AxiosInstance = Axios.create(genConfig());
-
-  // 保存 EnclosureHttp实例
-  private static EnclosureHttpInstance: EnclosureHttp;
-
-  // axios取消对象
-  private CancelToken: CancelTokenStatic = Axios.CancelToken;
-
-  // 取消的凭证数组
-  private sourceTokenList: Array<cancelTokenType> = [];
-
-  // 记录当前这一次cancelToken的key
-  private currentCancelTokenKey = "";
-
-  public get cancelTokenList(): Array<cancelTokenType> {
-    return this.sourceTokenList;
-  }
-
-  // eslint-disable-next-line class-methods-use-this
-  public set cancelTokenList(value) {
-    throw new Error("cancelTokenList不允许赋值");
-  }
-
-  /**
-   * @description 私有构造不允许实例化
-   * @returns void 0
-   */
-  // constructor() {}
-
-  /**
-   * @description 生成唯一取消key
-   * @param config axios配置
-   * @returns string
-   */
-  // eslint-disable-next-line class-methods-use-this
-  private static genUniqueKey(config: EnclosureHttpRequestConfig): string {
-    return `${config.url}--${JSON.stringify(config.data)}`;
-  }
-
-  /**
-   * @description 取消重复请求
-   * @returns void 0
-   */
-  private cancelRepeatRequest(): void {
-    const temp: { [key: string]: boolean } = {};
-
-    this.sourceTokenList = this.sourceTokenList.reduce<Array<cancelTokenType>>(
-      (res: Array<cancelTokenType>, cancelToken: cancelTokenType) => {
-        const { cancelKey, cancelExecutor } = cancelToken;
-        if (!temp[cancelKey]) {
-          temp[cancelKey] = true;
-          res.push(cancelToken);
-        } else {
-          cancelExecutor();
-        }
-        return res;
-      },
-      []
-    );
-  }
-
-  /**
-   * @description 删除指定的CancelToken
-   * @returns void 0
-   */
-  private deleteCancelTokenByCancelKey(cancelKey: string): void {
-    this.sourceTokenList =
-      this.sourceTokenList.length < 1
-        ? this.sourceTokenList.filter(
-            cancelToken => cancelToken.cancelKey !== cancelKey
-          )
-        : [];
-  }
-
-  /**
-   * @description 拦截请求
-   * @returns void 0
-   */
-
-  private httpInterceptorsRequest(): void {
-    EnclosureHttp.axiosInstance.interceptors.request.use(
-      (config: EnclosureHttpRequestConfig) => {
-        const $config = config;
-        NProgress.start(); // 每次切换页面时,调用进度条
-        const cancelKey = EnclosureHttp.genUniqueKey($config);
-        $config.cancelToken = new this.CancelToken(
-          (cancelExecutor: (cancel: any) => void) => {
-            this.sourceTokenList.push({ cancelKey, cancelExecutor });
-          }
-        );
-        this.cancelRepeatRequest();
-        this.currentCancelTokenKey = cancelKey;
-        // 优先判断post/get等方法是否传入回掉,否则执行初始化设置等回掉
-        if (typeof config.beforeRequestCallback === "function") {
-          config.beforeRequestCallback($config);
-          return $config;
-        }
-        if (EnclosureHttp.initConfig.beforeRequestCallback) {
-          EnclosureHttp.initConfig.beforeRequestCallback($config);
-          return $config;
-        }
-        return $config;
-      },
-      error => {
-        return Promise.reject(error);
-      }
-    );
-  }
-
-  /**
-   * @description 清空当前cancelTokenList
-   * @returns void 0
-   */
-  public clearCancelTokenList(): void {
-    this.sourceTokenList.length = 0;
-  }
-
-  /**
-   * @description 拦截响应
-   * @returns void 0
-   */
-  private httpInterceptorsResponse(): void {
-    const instance = EnclosureHttp.axiosInstance;
-    instance.interceptors.response.use(
-      (response: EnclosureHttpResoponse) => {
-        const $config = response.config;
-        // 请求每次成功一次就删除当前canceltoken标记
-        const cancelKey = EnclosureHttp.genUniqueKey($config);
-        this.deleteCancelTokenByCancelKey(cancelKey);
-
-        NProgress.done();
-        // 优先判断post/get等方法是否传入回掉,否则执行初始化设置等回掉
-        if (typeof $config.beforeResponseCallback === "function") {
-          $config.beforeResponseCallback(response);
-          return response.data;
-        }
-        if (EnclosureHttp.initConfig.beforeResponseCallback) {
-          EnclosureHttp.initConfig.beforeResponseCallback(response);
-          return response.data;
-        }
-        return response.data;
-      },
-      (error: EnclosureHttpError) => {
-        const $error = error;
-        // 判断当前的请求中是否在 取消token数组理存在,如果存在则移除(单次请求流程)
-        if (this.currentCancelTokenKey) {
-          const haskey = this.sourceTokenList.filter(
-            cancelToken => cancelToken.cancelKey === this.currentCancelTokenKey
-          ).length;
-          if (haskey) {
-            this.sourceTokenList = this.sourceTokenList.filter(
-              cancelToken =>
-                cancelToken.cancelKey !== this.currentCancelTokenKey
-            );
-            this.currentCancelTokenKey = "";
-          }
-        }
-        $error.isCancelRequest = Axios.isCancel($error);
-        NProgress.done();
-        // 所有的响应异常 区分来源为取消请求/非取消请求
-        return Promise.reject($error);
-      }
-    );
-  }
-
-  public request<T>(
-    method: RequestMethods,
-    url: string,
-    param?: AxiosRequestConfig,
-    axiosConfig?: EnclosureHttpRequestConfig
-  ): Promise<T> {
-    const config = transformConfigByMethod(param, {
-      method,
-      url,
-      ...axiosConfig
-    } as EnclosureHttpRequestConfig);
-    // 单独处理自定义请求/响应回掉
-    return new Promise((resolve, reject) => {
-      EnclosureHttp.axiosInstance
-        .request(config)
-        .then((response: undefined) => {
-          resolve(response);
-        })
-        .catch((error: any) => {
-          reject(error);
-        });
-    });
-  }
-
-  public post<T>(
-    url: string,
-    params?: T,
-    config?: EnclosureHttpRequestConfig
-  ): Promise<T> {
-    return this.request<T>("post", url, params, config);
-  }
-
-  public get<T>(
-    url: string,
-    params?: T,
-    config?: EnclosureHttpRequestConfig
-  ): Promise<T> {
-    return this.request<T>("get", url, params, config);
-  }
-}
-
-export default EnclosureHttp;

+ 166 - 2
src/utils/http/index.ts

@@ -1,2 +1,166 @@
-import EnclosureHttp from "./core";
-export const http = new EnclosureHttp();
+import Axios, { AxiosInstance, AxiosRequestConfig } from "axios";
+import {
+  resultType,
+  PureHttpError,
+  RequestMethods,
+  PureHttpResoponse,
+  PureHttpRequestConfig
+} from "./types.d";
+import qs from "qs";
+import NProgress from "../progress";
+// import { loadEnv } from "@build/index";
+import { getToken } from "/@/utils/auth";
+import { useUserStoreHook } from "/@/store/modules/user";
+
+// 加载环境变量 VITE_PROXY_DOMAIN(开发环境)  VITE_PROXY_DOMAIN_REAL(打包后的线上环境)
+// const { VITE_PROXY_DOMAIN, VITE_PROXY_DOMAIN_REAL } = loadEnv();
+
+// 相关配置请参考:www.axios-js.com/zh-cn/docs/#axios-request-config-1
+const defaultConfig: AxiosRequestConfig = {
+  // baseURL:
+  //   process.env.NODE_ENV === "production"
+  //     ? VITE_PROXY_DOMAIN_REAL
+  //     : VITE_PROXY_DOMAIN,
+  // 当前使用mock模拟请求,将baseURL制空,如果你的环境用到了http请求,请删除下面的baseURL启用上面的baseURL,并将11行、16行代码注释取消
+  baseURL: "",
+  timeout: 10000,
+  headers: {
+    Accept: "application/json, text/plain, */*",
+    "Content-Type": "application/json",
+    "X-Requested-With": "XMLHttpRequest"
+  },
+  // 数组格式参数序列化
+  paramsSerializer: params => qs.stringify(params, { indices: false })
+};
+
+class PureHttp {
+  constructor() {
+    this.httpInterceptorsRequest();
+    this.httpInterceptorsResponse();
+  }
+  // 初始化配置对象
+  private static initConfig: PureHttpRequestConfig = {};
+
+  // 保存当前Axios实例对象
+  private static axiosInstance: AxiosInstance = Axios.create(defaultConfig);
+
+  // 请求拦截
+  private httpInterceptorsRequest(): void {
+    PureHttp.axiosInstance.interceptors.request.use(
+      (config: PureHttpRequestConfig) => {
+        const $config = config;
+        // 开启进度条动画
+        NProgress.start();
+        // 优先判断post/get等方法是否传入回掉,否则执行初始化设置等回掉
+        if (typeof config.beforeRequestCallback === "function") {
+          config.beforeRequestCallback($config);
+          return $config;
+        }
+        if (PureHttp.initConfig.beforeRequestCallback) {
+          PureHttp.initConfig.beforeRequestCallback($config);
+          return $config;
+        }
+        const token = getToken();
+        if (token) {
+          const data = JSON.parse(token);
+          const now = new Date().getTime();
+          const expired = parseInt(data.expires) - now <= 0;
+          if (expired) {
+            // token过期刷新
+            useUserStoreHook()
+              .refreshToken(data)
+              .then((res: resultType) => {
+                config.headers["Authorization"] = "Bearer " + res.accessToken;
+                return $config;
+              });
+          } else {
+            config.headers["Authorization"] = "Bearer " + data.accessToken;
+            return $config;
+          }
+        } else {
+          return $config;
+        }
+      },
+      error => {
+        return Promise.reject(error);
+      }
+    );
+  }
+
+  // 响应拦截
+  private httpInterceptorsResponse(): void {
+    const instance = PureHttp.axiosInstance;
+    instance.interceptors.response.use(
+      (response: PureHttpResoponse) => {
+        const $config = response.config;
+        // 关闭进度条动画
+        NProgress.done();
+        // 优先判断post/get等方法是否传入回掉,否则执行初始化设置等回掉
+        if (typeof $config.beforeResponseCallback === "function") {
+          $config.beforeResponseCallback(response);
+          return response.data;
+        }
+        if (PureHttp.initConfig.beforeResponseCallback) {
+          PureHttp.initConfig.beforeResponseCallback(response);
+          return response.data;
+        }
+        return response.data;
+      },
+      (error: PureHttpError) => {
+        const $error = error;
+        $error.isCancelRequest = Axios.isCancel($error);
+        // 关闭进度条动画
+        NProgress.done();
+        // 所有的响应异常 区分来源为取消请求/非取消请求
+        return Promise.reject($error);
+      }
+    );
+  }
+
+  // 通用请求工具函数
+  public request<T>(
+    method: RequestMethods,
+    url: string,
+    param?: AxiosRequestConfig,
+    axiosConfig?: PureHttpRequestConfig
+  ): Promise<T> {
+    const config = {
+      method,
+      url,
+      ...param,
+      ...axiosConfig
+    } as PureHttpRequestConfig;
+
+    // 单独处理自定义请求/响应回掉
+    return new Promise((resolve, reject) => {
+      PureHttp.axiosInstance
+        .request(config)
+        .then((response: undefined) => {
+          resolve(response);
+        })
+        .catch(error => {
+          reject(error);
+        });
+    });
+  }
+
+  // 单独抽离的post工具函数
+  public post<T>(
+    url: string,
+    params?: T,
+    config?: PureHttpRequestConfig
+  ): Promise<T> {
+    return this.request<T>("post", url, params, config);
+  }
+
+  // 单独抽离的get工具函数
+  public get<T>(
+    url: string,
+    params?: T,
+    config?: PureHttpRequestConfig
+  ): Promise<T> {
+    return this.request<T>("get", url, params, config);
+  }
+}
+
+export const http = new PureHttp();

+ 17 - 28
src/utils/http/types.d.ts

@@ -1,50 +1,39 @@
 import Axios, {
-  AxiosRequestConfig,
-  Canceler,
-  AxiosResponse,
   Method,
-  AxiosError
+  AxiosError,
+  AxiosResponse,
+  AxiosRequestConfig
 } from "axios";
 
-import { METHODS } from "./config";
-
-export type cancelTokenType = { cancelKey: string; cancelExecutor: Canceler };
+export type resultType = {
+  accessToken?: string;
+};
 
 export type RequestMethods = Extract<
   Method,
   "get" | "post" | "put" | "delete" | "patch" | "option" | "head"
 >;
 
-export interface EnclosureHttpRequestConfig extends AxiosRequestConfig {
-  beforeRequestCallback?: (request: EnclosureHttpRequestConfig) => void; // 请求发送之前
-  beforeResponseCallback?: (response: EnclosureHttpResoponse) => void; // 相应返回之前
+export interface PureHttpError extends AxiosError {
+  isCancelRequest?: boolean;
 }
 
-export interface EnclosureHttpResoponse extends AxiosResponse {
-  config: EnclosureHttpRequestConfig;
+export interface PureHttpResoponse extends AxiosResponse {
+  config: PureHttpRequestConfig;
 }
 
-export interface EnclosureHttpError extends AxiosError {
-  isCancelRequest?: boolean;
+export interface PureHttpRequestConfig extends AxiosRequestConfig {
+  beforeRequestCallback?: (request: PureHttpRequestConfig) => void;
+  beforeResponseCallback?: (response: PureHttpResoponse) => void;
 }
 
-export default class EnclosureHttp {
-  cancelTokenList: Array<cancelTokenType>;
-  clearCancelTokenList(): void;
+export default class PureHttp {
   request<T>(
     method: RequestMethods,
     url: string,
     param?: AxiosRequestConfig,
-    axiosConfig?: EnclosureHttpRequestConfig
-  ): Promise<T>;
-  post<T>(
-    url: string,
-    params?: T,
-    config?: EnclosureHttpRequestConfig
-  ): Promise<T>;
-  get<T>(
-    url: string,
-    params?: T,
-    config?: EnclosureHttpRequestConfig
+    axiosConfig?: PureHttpRequestConfig
   ): Promise<T>;
+  post<T>(url: string, params?: T, config?: PureHttpRequestConfig): Promise<T>;
+  get<T>(url: string, params?: T, config?: PureHttpRequestConfig): Promise<T>;
 }

+ 0 - 29
src/utils/http/utils.ts

@@ -1,29 +0,0 @@
-import { EnclosureHttpRequestConfig } from "./types.d";
-
-export function excludeProps<T extends { [key: string]: any }>(
-  origin: T,
-  prop: string
-): { [key: string]: T } {
-  return Object.keys(origin)
-    .filter(key => !prop.includes(key))
-    .reduce((res, key) => {
-      res[key] = origin[key];
-      return res;
-    }, {} as { [key: string]: T });
-}
-
-export function transformConfigByMethod(
-  params: any,
-  config: EnclosureHttpRequestConfig
-): EnclosureHttpRequestConfig {
-  const { method } = config;
-  const props = ["delete", "get", "head", "options"].includes(
-    method!.toLocaleLowerCase()
-  )
-    ? "params"
-    : "data";
-  return {
-    ...config,
-    [props]: params
-  };
-}

+ 0 - 53
src/utils/storage/cookie.ts

@@ -1,53 +0,0 @@
-import { loadEnv } from "@build/utils";
-import { merge } from "lodash-es";
-import tsCookies from "typescript-cookie/dist/src/compat";
-
-class Cookies {
-  private static env = loadEnv();
-  constructor() {}
-  /**
-   *  存储 cookie 值
-   * @param name
-   * @param value
-   * @param cookieSetting
-   */
-  set(name = "default", value = "", cookieSetting = {}) {
-    const currentCookieSetting = {
-      expires: 1
-    };
-    merge(currentCookieSetting, cookieSetting);
-    tsCookies.set(
-      `${Cookies.env.VITE_TITLE}-${Cookies.env.VITE_VERSION}-${name}`,
-      value,
-      currentCookieSetting
-    );
-  }
-  /**
-   * 拿到 cookie 值
-   * @param name
-   * @returns
-   */
-  get(name = "default") {
-    return tsCookies.get(
-      `${Cookies.env.VITE_TITLE}-${Cookies.env.VITE_VERSION}-${name}`
-    );
-  }
-  /**
-   * 拿到 cookie 全部的值
-   * @returns
-   */
-  getAll() {
-    return tsCookies.get();
-  }
-  /**
-   * 删除 cookie
-   * @param name
-   */
-  remove(name = "default") {
-    tsCookies.remove(
-      `${Cookies.env.VITE_TITLE}-${Cookies.env.VITE_VERSION}-${name}`
-    );
-  }
-}
-
-export const cookies = new Cookies();

+ 0 - 93
src/utils/storage/db.ts

@@ -1,93 +0,0 @@
-import { loadEnv } from "@build/utils";
-import { LocalStorage, LowSync } from "lowdb";
-import { chain, cloneDeep } from "lodash-es";
-import { storageLocal } from ".";
-import { cookies } from "./cookie";
-type Data = {
-  database: {};
-  sys: {};
-};
-/**
- * db 数据存储,采用 LocalStorage存储
- */
-class DB {
-  private db: LowSync<Data>;
-  private static env = loadEnv();
-  constructor() {
-    this.db = new LowSync<Data>(
-      new LocalStorage<Data>(`${DB.env.VITE_TITLE}-${DB.env.VITE_VERSION}`)
-    );
-    this.initialization();
-    // @ts-ignore
-    this.db.chain = chain(this.db.data);
-  }
-  private initialization() {
-    this.db.data = storageLocal.getItem(
-      `${DB.env.VITE_TITLE}-${DB.env.VITE_VERSION}`
-    ) || { database: {}, sys: {} };
-    this.db.write();
-  }
-  /**
-   * 检查路径是否存在 不存在的话初始化
-   * @param param0
-   * @returns path
-   */
-  pathInit({
-    dbName = "database",
-    path = "",
-    user = true,
-    validator = () => true,
-    defaultValue = ""
-  }): string {
-    const uuid = cookies.get("uuid") || "ghost-uuid";
-    const currentPath = `${dbName}.${user ? `user.${uuid}` : "public"}${
-      path ? `.${path}` : ""
-    }`;
-    // @ts-ignore
-    const value = this.db.chain.get(currentPath).value();
-    // @ts-ignore
-    if (!(value !== undefined && validator(value))) {
-      // @ts-ignore
-      this.db.chain.set(currentPath, defaultValue).value();
-      this.db.write();
-    }
-    return currentPath;
-  }
-  /**
-   *将数据存储到指定位置 | 路径不存在会自动初始化
-   *
-   * 效果类似于取值 dbName.path = value
-   * @param param0
-   */
-  dbSet({ dbName = "database", path = "", value = "", user = false }): void {
-    const currentPath = this.pathInit({
-      dbName,
-      path,
-      user
-    });
-    // @ts-ignore
-    this.db.chain.set(currentPath, value).value();
-    this.db.write();
-  }
-  /**
-   * 获取数据
-   *
-   * 效果类似于取值 dbName.path || defaultValue
-   * @param param0
-   * @returns
-   */
-  dbGet({
-    dbName = "database",
-    path = "",
-    defaultValue = "",
-    user = false
-  }): any {
-    // @ts-ignore
-    const values = this.db.chain
-      .get(this.pathInit({ dbName, path, user, defaultValue }))
-      .value();
-    return cloneDeep(values);
-  }
-}
-
-export const db = new DB();

+ 3 - 5
src/views/components/button/index.vue

@@ -1,11 +1,9 @@
 <script setup lang="ts">
 import { ref } from "vue";
+import { loadEnv } from "@build/index";
+const { VITE_PUBLIC_PATH } = loadEnv();
 
-const url = ref(
-  process.env.NODE_ENV === "production"
-    ? "/manages/html/button.html"
-    : "/html/button.html"
-);
+const url = ref(`${VITE_PUBLIC_PATH}html/button.html`);
 </script>
 
 <template>

+ 2 - 14
types/global.d.ts

@@ -65,21 +65,9 @@ declare global {
 
   declare interface ViteEnv {
     VITE_PORT: number;
-    VITE_TITLE: string;
-    VITE_VERSION: string;
-    VITE_USE_MOCK: boolean;
-    VITE_USE_PWA: boolean;
     VITE_PUBLIC_PATH: string;
-    VITE_PROXY: [string, string][];
-    VITE_GLOB_APP_TITLE: string;
-    VITE_GLOB_APP_SHORT_NAME: string;
-    VITE_USE_CDN: boolean;
-    VITE_DROP_CONSOLE: boolean;
-    VITE_BUILD_COMPRESS: "gzip" | "brotli" | "none";
-    VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE: boolean;
-    VITE_LEGACY: boolean;
-    VITE_USE_IMAGEMIN: boolean;
-    VITE_GENERATE_UI: string;
+    VITE_PROXY_DOMAIN: string;
+    VITE_PROXY_DOMAIN_REAL: string;
   }
 
   declare interface ServerConfigs {

+ 33 - 24
vite.config.ts

@@ -1,41 +1,40 @@
 import { resolve } from "path";
-import { UserConfigExport, ConfigEnv, loadEnv } from "vite";
 import vue from "@vitejs/plugin-vue";
+import svgLoader from "vite-svg-loader";
 import vueJsx from "@vitejs/plugin-vue-jsx";
-import { warpperEnv } from "./build/utils";
-import { createProxy } from "./build/proxy";
+import { warpperEnv, regExps } from "./build";
 import { viteMockServe } from "vite-plugin-mock";
-import svgLoader from "vite-svg-loader";
 import styleImport from "vite-plugin-style-import";
 import ElementPlus from "unplugin-element-plus/vite";
+import { UserConfigExport, ConfigEnv, loadEnv } from "vite";
 import themePreprocessorPlugin from "@zougt/vite-plugin-theme-preprocessor";
 
+// 当前执行node命令时文件夹的地址(工作目录)
+const root: string = process.cwd();
+
+// 路径查找
 const pathResolve = (dir: string): string => {
   return resolve(__dirname, ".", dir);
 };
 
+// 设置别名
 const alias: Record<string, string> = {
   "/@": pathResolve("src"),
   "@build": pathResolve("build"),
-  //解决开发环境下的警告 You are running the esm-bundler build of vue-i18n. It is recommended to configure your bundler to explicitly replace feature flag globals with boolean literals to get proper tree-shaking in the final bundle.
+  //解决开发环境下的警告
   "vue-i18n": "vue-i18n/dist/vue-i18n.cjs.js"
 };
 
-const root: string = process.cwd();
-
 export default ({ command, mode }: ConfigEnv): UserConfigExport => {
-  const { VITE_PORT, VITE_PUBLIC_PATH, VITE_PROXY } = warpperEnv(
-    loadEnv(mode, root)
-  );
+  const {
+    VITE_PORT,
+    VITE_PUBLIC_PATH,
+    VITE_PROXY_DOMAIN,
+    VITE_PROXY_DOMAIN_REAL
+  } = warpperEnv(loadEnv(mode, root));
   const prodMock = true;
   return {
-    /**
-     * 基本公共路径
-     * /manages/ 可根据项目部署域名的后缀自行填写(全局搜/manages/替换)
-     * @default '/'
-     */
-    base:
-      process.env.NODE_ENV === "production" ? "/manages/" : VITE_PUBLIC_PATH,
+    base: VITE_PUBLIC_PATH,
     root,
     resolve: {
       alias
@@ -44,18 +43,27 @@ export default ({ command, mode }: ConfigEnv): UserConfigExport => {
     server: {
       // 是否开启 https
       https: false,
-      /**
-       * 端口号
-       * @default 3000
-       */
+      // 端口号
       port: VITE_PORT,
       host: "0.0.0.0",
       // 本地跨域代理
-      proxy: createProxy(VITE_PROXY)
+      proxy:
+        VITE_PROXY_DOMAIN_REAL.length > 0
+          ? {
+              [VITE_PROXY_DOMAIN]: {
+                target: VITE_PROXY_DOMAIN_REAL,
+                // ws: true,
+                changeOrigin: true,
+                rewrite: (path: string) => regExps(path, VITE_PROXY_DOMAIN)
+              }
+            }
+          : null
     },
     plugins: [
       vue(),
+      // jsx、tsx语法支持
       vueJsx(),
+      // 自定义主题
       themePreprocessorPlugin({
         scss: {
           multipleScopeVars: [
@@ -112,10 +120,11 @@ export default ({ command, mode }: ConfigEnv): UserConfigExport => {
           customThemeCssFileName: scopeName => scopeName
         }
       }),
+      // svg组件化支持
       svgLoader(),
+      // 按需加载vxe-table
       styleImport({
         libs: [
-          // 按需加载vxe-table
           {
             libraryName: "vxe-table",
             esModule: true,
@@ -126,6 +135,7 @@ export default ({ command, mode }: ConfigEnv): UserConfigExport => {
         ]
       }),
       ElementPlus({}),
+      // mock支持
       viteMockServe({
         mockPath: "mock",
         localEnabled: command === "serve",
@@ -147,7 +157,6 @@ export default ({ command, mode }: ConfigEnv): UserConfigExport => {
       exclude: ["@zougt/vite-plugin-theme-preprocessor/dist/browser-utils"]
     },
     build: {
-      // @ts-ignore
       sourcemap: false,
       brotliSize: false,
       // 消除打包大小超过500kb警告