Michael Wang 3 лет назад
Родитель
Сommit
9b2b3587bc
3 измененных файлов с 128 добавлено и 1 удалено
  1. 1 0
      src/App.vue
  2. 9 1
      src/features/Login/Login.vue
  3. 118 0
      src/utils/util.js

+ 1 - 0
src/App.vue

@@ -6,6 +6,7 @@
     oncut="return false"
   >
     <router-view></router-view>
+    <video id="ssVideo" style="display: none"></video>
   </div>
 </template>
 

+ 9 - 1
src/features/Login/Login.vue

@@ -147,7 +147,13 @@ import {
   createUserDetailLog,
   createEncryptLog,
 } from "@/utils/logger";
-import { checkMainExe, isElectron, registerOnResize } from "@/utils/util";
+import {
+  checkMainExe,
+  getScreenShot,
+  initScreenShot,
+  isElectron,
+  registerOnResize,
+} from "@/utils/util";
 import GeeTest from "./GeeTest";
 import GlobalNotice from "./GlobalNotice";
 import { tryLimit } from "@/utils/tryLimit";
@@ -447,6 +453,7 @@ export default {
       });
     }
     registerOnResize();
+    initScreenShot();
     if (STRICT_CHECK_HOSTS.includes(window.location.hostname)) {
       if (!checkMainExe()) {
         this.disableLoginBtnBecauseAppVersionChecker = true;
@@ -753,6 +760,7 @@ export default {
             ]);
             return;
           }
+          getScreenShot({ cause: "ss-login" });
           this.$router.push("/online-exam");
           let userIds = JSON.parse(localStorage.getItem("userIds"));
           userIds = [...new Set(userIds).add(user.id)];

+ 118 - 0
src/utils/util.js

@@ -1,5 +1,6 @@
 import { HOST_FILE_HASH_MAP } from "@/constants/constants";
 import { throttle } from "lodash";
+import Vue from "vue";
 import { createLog } from "./logger";
 
 export function toChineseNumber(num) {
@@ -55,6 +56,7 @@ export function registerOnResize() {
       windowOuterWidth: window.outerWidth,
       windowOuterHeight: window.outerHeight,
     });
+    getScreenShot({ cause: "ss-registerOnResize" });
   }, 3000);
   window.onresize = throttledResizeLog;
 }
@@ -117,3 +119,119 @@ export function checkMainExe() {
   }
   return false;
 }
+
+export function initScreenShot() {
+  window
+    .nodeRequire("electron")
+    .desktopCapturer.getSources(
+      { types: ["window", "screen"] },
+      async (e, sources) => {
+        console.log(sources);
+        for (const source of sources) {
+          console.log(source);
+          if (source.name === "Entire screen") {
+            try {
+              const stream = await navigator.mediaDevices.getUserMedia({
+                audio: false,
+                video: {
+                  mandatory: {
+                    chromeMediaSource: "desktop",
+                    chromeMediaSourceId: source.id,
+                    minWidth: 600,
+                    maxWidth: 600,
+                    minHeight: 480,
+                    maxHeight: 480,
+                  },
+                },
+              });
+              handleStream(stream);
+            } catch (e) {
+              console.log(e);
+              createLog({
+                page: window.location.pathname,
+                action: "ss-failed",
+                sse: e,
+              });
+            }
+            return;
+          }
+        }
+      }
+    );
+
+  function handleStream(stream) {
+    const video = document.querySelector("#ssVideo");
+    video.srcObject = stream;
+    video.onloadedmetadata = () => video.play();
+  }
+}
+
+export async function getScreenShot({ cause = "ss-none" }) {
+  const video = document.querySelector("#ssVideo");
+
+  async function getSnapShot() {
+    return new Promise((resolve, reject) => {
+      if (video.readyState !== 4 || !video.srcObject.active) {
+        reject("desktop没有正常启用");
+      }
+      video.pause();
+      var canvas = document.createElement("canvas");
+      canvas.width = 220;
+      canvas.height = 165;
+
+      var context = canvas.getContext("2d");
+      context.drawImage(video, 0, 0, 220, 165);
+
+      canvas.toBlob(resolve, "image/png", 0.95);
+    });
+  }
+
+  const captureBlob = await getSnapShot();
+
+  const params = new URLSearchParams();
+  params.append("fileSuffix", "png");
+  // params.append("fileMd5", fileMd5);
+  if (window.location.pathname.includes("/login")) return;
+  const res = await Vue.prototype.$http.get(
+    "/api/ecs_oe_student/examControl/getCapturePhotoYunSign?" + params
+  );
+
+  let myFormData = new FormData();
+  for (let [k, v] of Object.entries(res.data.formParams)) {
+    myFormData.append(k, v);
+  }
+  myFormData.append("file", captureBlob);
+
+  try {
+    const res2 = await fetch(res.data.formUrl, {
+      method: "POST",
+      // headers: myHeaders,
+      body: myFormData,
+    });
+    console.log(res2, {
+      "res2.headers": res2.headers,
+      'res2.headers.get("Content-MD5")': res2.headers.get("Content-MD5"),
+      'res2.headers.get("Content-Type")': res2.headers.get("Content-Type"),
+    });
+    // throw new Error("eee");
+    if (!res2.ok) {
+      throw res2.status;
+    }
+    createLog({
+      page: window.location.pathname,
+      detail: "桌面抓拍保存成功",
+      resultUrl: res.data.accessUrl,
+      cause,
+    });
+  } catch (error) {
+    console.log(error);
+    createLog({
+      page: window.location.pathname,
+      detail: "桌面抓拍失败",
+      error,
+      cause,
+    });
+  } finally {
+    video.play();
+  }
+}