Michael Wang 4 lat temu
rodzic
commit
ba49ea8a57

+ 5 - 0
package.json

@@ -8,9 +8,14 @@
     "serve": "vite preview"
   },
   "dependencies": {
+    "axios": "^0.21.1",
+    "axios-progress-bar": "^1.2.0",
+    "axios-retry": "^3.1.9",
+    "lodash-es": "^4.17.21",
     "vue": "^3.0.5"
   },
   "devDependencies": {
+    "@types/lodash-es": "^4.17.4",
     "@vitejs/plugin-vue": "^1.1.5",
     "@vue/compiler-sfc": "^3.0.5",
     "typescript": "^4.1.3",

+ 12 - 0
src/api/markPage.ts

@@ -0,0 +1,12 @@
+import { httpApp } from "../plugins/axiosApp";
+
+export async function getSetting() {
+  return httpApp.post("/mark/getSetting");
+}
+
+export async function updateUISetting() {
+  const form = new FormData();
+  form.append("uiSetting", JSON.stringify({}));
+  form.append("mode", JSON.stringify("TRACK"));
+  return httpApp.post("/mark/updateSetting", form);
+}

+ 12 - 11
src/components/TestSetting.vue

@@ -2,30 +2,31 @@
   <h1>展示新前端获取setting的结果</h1>
   <div>
     setting:
-    <pre> {{ json }}</pre>
+    <pre> {{ store.setting }}</pre>
   </div>
 </template>
 
 <script lang="ts">
 import { reactive, defineComponent, onMounted, toRefs } from "vue";
+import { getSetting, updateUISetting } from "../api/markPage";
+import { store } from "../store";
+
 export default defineComponent({
   name: "TestSetting",
   setup: () => {
-    const state = reactive({
-      json: "",
-    });
-
     async function updateSetting() {
-      const settingRes = await (
-        await fetch("/mark/getSetting", { method: "POST" })
-      ).json();
-      console.log(settingRes);
-      state.json = JSON.stringify(settingRes, null, 2);
+      // const settingRes = await (
+      //   await fetch("/mark/getSetting", { method: "POST" })
+      // ).json();
+      // console.log(settingRes);
+      const settingRes = await getSetting();
+      store.setting = settingRes.data;
     }
     onMounted(() => {
       updateSetting();
+      updateUISetting();
     });
-    return toRefs(state);
+    return { store };
   },
 });
 </script>

+ 5 - 2
src/devLogin.ts

@@ -1,7 +1,9 @@
 export async function initLogin() {
+  if (document.cookie.includes("stmms_cookie")) return;
   const f = new FormData();
   f.append("loginType", "mark-login");
-  f.append("loginName", "1-431-2-1");
+  // f.append("loginName", "1-431-2-1");
+  f.append("loginName", "1-339-1-1");
   f.append("password", "123456");
 
   return fetch("/login", { body: f, method: "POST" })
@@ -9,7 +11,8 @@ export async function initLogin() {
     .then(() => {
       const f = new FormData();
       f.append("examId", "1");
-      f.append("markerId", "367");
+      // f.append("markerId", "367");
+      f.append("markerId", "147");
 
       return fetch("/mark/subject-select", { body: f, method: "POST" });
     });

+ 1 - 0
src/main.ts

@@ -1,4 +1,5 @@
 import { initLogin } from "./devLogin";
+import "./styles/global.css";
 import { createApp } from "vue";
 import App from "./App.vue";
 

+ 126 - 0
src/plugins/axiosApp.ts

@@ -0,0 +1,126 @@
+import Vue from "vue";
+// import Store from "@/store";
+import axios from "axios";
+// @ts-ignore
+import { loadProgressBar } from "axios-progress-bar";
+import cachingGet from "./axiosCache";
+import { notifyInvalidTokenThrottled } from "./axiosNotice";
+import axiosRetry from "axios-retry";
+// import { Notification } from "element-ui";
+const Notification = (...args: any) => {
+  console.log(args);
+};
+
+const config = {
+  // baseURL: process.env.baseURL || process.env.apiUrl || ""
+  timeout: 1 * 60 * 1000, // Timeout
+  withCredentials: true, // Check cross-site Access-Control
+};
+const cacheGetUrls: [RegExp] | [] = [];
+
+const _axiosApp = axios.create(config);
+axiosRetry(_axiosApp);
+
+_axiosApp.interceptors.request.use(
+  function (config) {
+    return config;
+  },
+  function (error) {
+    // Do something with request error
+    Notification({
+      showClose: true,
+      message: error,
+      type: "error",
+    });
+    console.log(error);
+    return Promise.reject(error);
+  }
+);
+
+// Add a response interceptor
+_axiosApp.interceptors.response.use(
+  (response) => {
+    return response;
+  },
+  (error) => {
+    const showErrorMessage = !error.config?.noErrorMessage;
+    if (!error.response) {
+      if (showErrorMessage) {
+        // "Network Error" 网络不通,直接返回
+        Notification({
+          showClose: true,
+          message: "网络连接异常,请检查网络设置。",
+          type: "error",
+        });
+      }
+      return Promise.reject(error);
+    }
+    // 这里是返回状态码不为200时候的错误处理
+    let status = error.response.status;
+
+    // 登录失效 跳转登录页面
+    if (status == 403 || status == 401) {
+      notifyInvalidTokenThrottled();
+      return Promise.reject(error);
+    } else if (status == 405) {
+      if (showErrorMessage) {
+        Notification({
+          showClose: true,
+          message: "没有权限!",
+          type: "error",
+        });
+      }
+      return Promise.reject(error);
+    } else if (status == 502) {
+      if (showErrorMessage) {
+        Notification({
+          showClose: true,
+          message: "服务器异常(502)!",
+          type: "error",
+        });
+      }
+      return Promise.reject(error);
+    }
+
+    if (status != 200) {
+      const data = error.response.data;
+      if (data && data.message) {
+        if (showErrorMessage) {
+          Notification({
+            showClose: true,
+            message: data.message,
+            type: "error",
+          });
+        }
+      } else {
+        if (showErrorMessage) {
+          Notification({
+            showClose: true,
+            message: "未定义异常: " + JSON.stringify(data, null, 2),
+            type: "error",
+          });
+        }
+      }
+      return Promise.reject(error);
+    }
+  }
+);
+
+_axiosApp.get = cachingGet(_axiosApp, cacheGetUrls);
+loadProgressBar(null, _axiosApp);
+
+// Plugin.install = function (Vue) {
+//   Object.defineProperties(Vue.prototype, {
+//     $http: {
+//       get() {
+//         return _axiosApp;
+//       },
+//     },
+//   });
+// };
+
+// Vue.use(Plugin);
+
+// export default Plugin;
+
+export const httpApp = _axiosApp;

+ 32 - 0
src/plugins/axiosCache.ts

@@ -0,0 +1,32 @@
+import { AxiosInstance } from "axios";
+
+export default function (axios: AxiosInstance, regexes: [RegExp] | []) {
+  // cachingGet
+  const cache = new Map();
+
+  return function cachedGet(url: string) {
+    const key = url;
+
+    if (regexes.some((regex) => url.match(regex))) {
+      if (cache.has(key)) {
+        const request = cache.get(key);
+        // console.log("cache.get(key):" + request.then(v => console.log(v)));
+        return request;
+      } else {
+        // @ts-ignore
+        const request = axios.get(...arguments);
+        return request.then((v) => {
+          if (v.status === 200) {
+            // 如果能取到数据,才缓存
+            cache.set(key, request);
+          }
+          return request;
+        });
+      }
+    } else {
+      // @ts-ignore
+      const request = axios.get(...arguments);
+      return request;
+    }
+  };
+}

+ 2 - 0
src/plugins/axiosIndex.ts

@@ -0,0 +1,2 @@
+export { httpApp } from "./axiosApp";
+export { httpNoAuth } from "./axiosNoAuth";

+ 87 - 0
src/plugins/axiosNoAuth.ts

@@ -0,0 +1,87 @@
+import Vue from "vue";
+import axios from "axios";
+// @ts-ignore
+import { loadProgressBar } from "axios-progress-bar";
+import cachingGet from "./axiosCache";
+import axiosRetry from "axios-retry";
+
+const config = {
+  timeout: 60 * 1000, // Timeout
+};
+const cacheGetUrls: [RegExp] | [] = [];
+
+const _axiosNoAuth = axios.create(config);
+axiosRetry(_axiosNoAuth);
+
+/**
+ * 本应用的无auth api,或者第三方的api
+ * 1. 统一使用的http api,方便使用,无需fetch
+ * 2. 无默认headers
+ */
+
+_axiosNoAuth.interceptors.request.use(
+  function (config) {
+    return config;
+  },
+  function (error) {
+    // Vue.prototype.$notify({
+    //   showClose: true,
+    //   message: error,
+    //   type: "error",
+    // });
+    return Promise.reject(error);
+  }
+);
+
+// Add a response interceptor
+_axiosNoAuth.interceptors.response.use(
+  (response) => {
+    return response;
+  },
+  (error) => {
+    if (!error.response) {
+      // "Network Error" 网络不通,直接返回
+      // Vue.prototype.$notify({
+      //   showClose: true,
+      //   message: "网络连接异常,请检查网络设置。",
+      //   type: "error",
+      // });
+      return Promise.reject(error);
+    }
+
+    const data = error.response.data;
+    if (data && data.desc) {
+      // Vue.prototype.$notify({
+      //   showClose: true,
+      //   message: data.desc,
+      //   type: "error",
+      // });
+    } else {
+      // Vue.prototype.$notify({
+      //   showClose: true,
+      //   message: `异常(${error.response.status}): ${error.config.url}`,
+      //   type: "error",
+      // });
+    }
+    return Promise.reject(error);
+  }
+);
+
+_axiosNoAuth.get = cachingGet(_axiosNoAuth, cacheGetUrls);
+loadProgressBar(null, _axiosNoAuth);
+
+// Plugin.install = function (Vue) {
+//   Object.defineProperties(Vue.prototype, {
+//     $httpNoAuth: {
+//       get() {
+//         return _axiosNoAuth;
+//       },
+//     },
+//   });
+// };
+
+// Vue.use(Plugin);
+
+export default Plugin;
+
+export const httpNoAuth = _axiosNoAuth;

+ 12 - 0
src/plugins/axiosNotice.ts

@@ -0,0 +1,12 @@
+import Vue from "vue";
+import { throttle } from "lodash-es";
+
+// function printErr(val) {
+export const notifyInvalidTokenThrottled = throttle(() => {
+  // Vue.prototype.$notify({
+  //   showClose: true,
+  //   message: "登录失效,请重新登录!",
+  //   type: "error",
+  // });
+  console.log("登录失效");
+}, 1000);

+ 10 - 0
src/plugins/customComponents.js

@@ -0,0 +1,10 @@
+import Vue from "vue";
+// import AppType from "@/components/common/AppType.vue";
+
+const components = {
+  //  AppType,
+};
+
+Object.keys(components).forEach((key) => {
+  Vue.component(key, components[key]);
+});

+ 6 - 0
src/styles/global.css

@@ -0,0 +1,6 @@
+@import "./nprogress.css";
+
+body {
+  margin: 0;
+  font-size: 14px;
+}

+ 81 - 0
src/styles/nprogress.css

@@ -0,0 +1,81 @@
+/* Make clicks pass-through */
+#nprogress {
+  pointer-events: none;
+}
+
+#nprogress .bar {
+  background: #29d;
+
+  position: fixed;
+  z-index: 1031;
+  top: 0;
+  left: 0;
+
+  width: 100%;
+  height: 2px;
+}
+
+/* Fancy blur effect */
+#nprogress .peg {
+  display: block;
+  position: absolute;
+  right: 0px;
+  width: 100px;
+  height: 100%;
+  box-shadow: 0 0 10px #29d, 0 0 5px #29d;
+  opacity: 1;
+
+  -webkit-transform: rotate(3deg) translate(0px, -4px);
+  -ms-transform: rotate(3deg) translate(0px, -4px);
+  transform: rotate(3deg) translate(0px, -4px);
+}
+
+/* Remove these to get rid of the spinner */
+#nprogress .spinner {
+  display: block;
+  position: fixed;
+  z-index: 1031;
+  top: 15px;
+  right: 15px;
+}
+
+#nprogress .spinner-icon {
+  width: 18px;
+  height: 18px;
+  box-sizing: border-box;
+
+  border: solid 2px transparent;
+  border-top-color: #29d;
+  border-left-color: #29d;
+  border-radius: 50%;
+
+  -webkit-animation: nprogress-spinner 400ms linear infinite;
+  animation: nprogress-spinner 400ms linear infinite;
+}
+
+.nprogress-custom-parent {
+  overflow: hidden;
+  position: relative;
+}
+
+.nprogress-custom-parent #nprogress .spinner,
+.nprogress-custom-parent #nprogress .bar {
+  position: absolute;
+}
+
+@-webkit-keyframes nprogress-spinner {
+  0% {
+    -webkit-transform: rotate(0deg);
+  }
+  100% {
+    -webkit-transform: rotate(360deg);
+  }
+}
+@keyframes nprogress-spinner {
+  0% {
+    transform: rotate(0deg);
+  }
+  100% {
+    transform: rotate(360deg);
+  }
+}

+ 46 - 0
yarn.lock

@@ -21,6 +21,18 @@
     lodash "^4.17.19"
     to-fast-properties "^2.0.0"
 
+"@types/lodash-es@^4.17.4":
+  version "4.17.4"
+  resolved "https://registry.npm.taobao.org/@types/lodash-es/download/@types/lodash-es-4.17.4.tgz#b2e440d2bf8a93584a9fd798452ec497986c9b97"
+  integrity sha1-suRA0r+Kk1hKn9eYRS7El5hsm5c=
+  dependencies:
+    "@types/lodash" "*"
+
+"@types/lodash@*":
+  version "4.14.168"
+  resolved "https://registry.npm.taobao.org/@types/lodash/download/@types/lodash-4.14.168.tgz?cache=0&sync_timestamp=1613379222224&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Flodash%2Fdownload%2F%40types%2Flodash-4.14.168.tgz#fe24632e79b7ade3f132891afff86caa5e5ce008"
+  integrity sha1-/iRjLnm3rePxMoka//hsql5c4Ag=
+
 "@vitejs/plugin-vue@^1.1.5":
   version "1.1.5"
   resolved "https://registry.npm.taobao.org/@vitejs/plugin-vue/download/@vitejs/plugin-vue-1.1.5.tgz#fa1e8e5e049c35e213672e33f73fe81706ad5dbe"
@@ -104,6 +116,25 @@
   resolved "https://registry.npm.taobao.org/@vue/shared/download/@vue/shared-3.0.7.tgz#96d52988efc07444c108c7c6803ba7cc93e40045"
   integrity sha1-ltUpiO/AdETBCMfGgDunzJPkAEU=
 
+axios-progress-bar@^1.2.0:
+  version "1.2.0"
+  resolved "https://registry.npm.taobao.org/axios-progress-bar/download/axios-progress-bar-1.2.0.tgz#f9ee88dc9af977246be1ef07eedfa4c990c639c5"
+  integrity sha1-+e6I3Jr5dyRr4e8H7t+kyZDGOcU=
+
+axios-retry@^3.1.9:
+  version "3.1.9"
+  resolved "https://registry.npm.taobao.org/axios-retry/download/axios-retry-3.1.9.tgz#6c30fc9aeb4519aebaec758b90ef56fa03fe72e8"
+  integrity sha1-bDD8mutFGa667HWLkO9W+gP+cug=
+  dependencies:
+    is-retry-allowed "^1.1.0"
+
+axios@^0.21.1:
+  version "0.21.1"
+  resolved "https://registry.npm.taobao.org/axios/download/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8"
+  integrity sha1-IlY0gZYvTWvemnbVFu8OXTwJsrg=
+  dependencies:
+    follow-redirects "^1.10.0"
+
 balanced-match@^1.0.0:
   version "1.0.0"
   resolved "https://registry.npm.taobao.org/balanced-match/download/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
@@ -216,6 +247,11 @@ estree-walker@^2.0.1:
   resolved "https://registry.npm.taobao.org/estree-walker/download/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac"
   integrity sha1-UvAQF4wqTBF6d1fP6UKtt9LaTKw=
 
+follow-redirects@^1.10.0:
+  version "1.13.3"
+  resolved "https://registry.npm.taobao.org/follow-redirects/download/follow-redirects-1.13.3.tgz?cache=0&sync_timestamp=1614436958094&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffollow-redirects%2Fdownload%2Ffollow-redirects-1.13.3.tgz#e5598ad50174c1bc4e872301e82ac2cd97f90267"
+  integrity sha1-5VmK1QF0wbxOhyMB6CrCzZf5Amc=
+
 fs.realpath@^1.0.0:
   version "1.0.0"
   resolved "https://registry.npm.taobao.org/fs.realpath/download/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
@@ -312,6 +348,11 @@ is-core-module@^2.2.0:
   dependencies:
     has "^1.0.3"
 
+is-retry-allowed@^1.1.0:
+  version "1.2.0"
+  resolved "https://registry.npm.taobao.org/is-retry-allowed/download/is-retry-allowed-1.2.0.tgz#d778488bd0a4666a3be8a1482b9f2baafedea8b4"
+  integrity sha1-13hIi9CkZmo76KFIK58rqv7eqLQ=
+
 isarray@~1.0.0:
   version "1.0.0"
   resolved "https://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
@@ -338,6 +379,11 @@ loader-utils@^1.1.0:
     emojis-list "^3.0.0"
     json5 "^1.0.1"
 
+lodash-es@^4.17.21:
+  version "4.17.21"
+  resolved "https://registry.npm.taobao.org/lodash-es/download/lodash-es-4.17.21.tgz?cache=0&sync_timestamp=1613836838613&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flodash-es%2Fdownload%2Flodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee"
+  integrity sha1-Q+YmxG5lkbd1C+srUBFzkMYJ4+4=
+
 lodash.camelcase@^4.3.0:
   version "4.3.0"
   resolved "https://registry.npm.taobao.org/lodash.camelcase/download/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"