123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348 |
- import { getCapturePhotoYunSign, saveCapturePhoto } from "@/api/login";
- import { HOST_FILE_HASH_MAP } from "@/constants/constants";
- import { throttle, xor } from "lodash-es";
- export function isElectron() {
- return typeof window.nodeRequire != "undefined";
- }
- const fs: typeof import("fs") = isElectron() && window.nodeRequire("fs");
- /** 执行本地exe文件 */
- export function execLocal(exeName: string): Promise<void> {
- if (!isElectron()) {
- logger({
- pgu: "AUTO",
- cnl: ["local", "server"],
- dtl: "不在Electron中,调用 " + exeName + " 失败",
- });
- throw new Error("不在Electron中,调用 fs 失败");
- }
- if (import.meta.env.DEV) {
- return Promise.resolve();
- }
- return new Promise<void>((resolve) => {
- // eslint-disable-next-line
- window
- .nodeRequire("node-cmd")
- .get(
- "cmd /c chcp 65001>nul && " + exeName,
- async (err: Error, data: string, stderr: string) => {
- console.log(exeName, err, data); // 未免过多日志,此处后续可以关闭
- logger({
- pgu: "AUTO",
- cnl: ["console", "local", "server"],
- act: exeName + " called",
- ejn: JSON.stringify(err),
- dtl: data,
- ext: {
- stderr: JSON.stringify(stderr),
- absPath: exeName.includes(":"),
- },
- });
- // 如果相对路径没找到,则通过绝对路径来执行
- if (!exeName.includes(":") && err) {
- const remote: typeof import("electron").remote =
- window.nodeRequire("electron").remote;
- const fs: typeof import("fs") = remote.require("fs");
- const path: typeof import("path") = remote.require("path");
- const [exePath, exeParams] = exeName.split(" ");
- const absPath = path.join(
- remote.app.getAppPath(),
- "../../",
- exePath
- );
- if (fs.existsSync(absPath)) {
- try {
- await execLocal([absPath, exeParams].join(" ").trim());
- } catch (error) {
- console.log("second try error", absPath);
- logger({
- cnl: ["local", "server"],
- dtl: "second try error: " + absPath,
- });
- }
- }
- }
- resolve();
- }
- );
- });
- }
- /** 文件路径是否存在 */
- export function fileExists(file: string): boolean {
- if (!isElectron()) {
- logger({
- pgu: "AUTO",
- cnl: ["local", "server"],
- dtl: "不在Electron中,调用 fs 失败",
- });
- throw new Error("不在Electron中,调用 fs 失败");
- }
- return fs.existsSync(file);
- }
- /** 检测当前运行的进程中是否有“向日葵” */
- export function nodeCheckRemoteDesktop(): boolean {
- logger({
- pgu: "AUTO",
- cnl: ["local", "server"],
- key: "nodeCheckRemoteDesktop",
- });
- // eslint-disable-next-line @typescript-eslint/no-unsafe-call
- const appList: string = window
- .nodeRequire("child_process")
- .execSync("cmd /c chcp 65001>nul && tasklist /FO CSV")
- .toString();
- // console.debug(appList);
- const regex = new RegExp("sunloginclient|选择免安装运行,截图识别", "gi");
- return !!(appList?.match(regex) || []).length;
- }
- let previousAppList: string[] = [];
- /** 将电脑运行的进程记录到日志 */
- export function nodeCheckProcess(): void {
- try {
- // eslint-disable-next-line @typescript-eslint/no-unsafe-call
- const appListCP: string = window
- .nodeRequire("child_process")
- .execSync("cmd /c chcp 65001>nul && tasklist /FO CSV")
- .toString();
- // 不能打印,electron-log 不能接收
- // console.log(appList);
- let appList = appListCP.split("\r\n");
- appList.shift();
- appList = appList.map((v) => v.split(",")[0]);
- const xorRes = xor(previousAppList, appList);
- if (xorRes && xorRes.length > 0) {
- logger({
- pgu: "AUTO",
- cnl: ["local", "server"],
- key: "nodeCheckProcess",
- dtl: xorRes.join(" ||| "),
- });
- }
- previousAppList = appList;
- } catch (error) {
- logger({
- cnl: ["console", "local", "server"],
- pgu: "AUTO",
- ejn: JSON.stringify(error),
- });
- }
- }
- /** 检测当前程序包的完整性。 */
- export function checkMainExe(): boolean {
- try {
- let iid: string = window.nodeRequire("process").pid;
- const cp: typeof import("child_process") =
- window.nodeRequire("child_process");
- iid = cp
- .execSync(
- `cmd /c chcp 65001>nul && C:\\Windows\\System32\\wbem\\wmic process where ^(processid^=${iid}^) get parentprocessid /value`
- )
- .toString();
- iid = iid.replace("ParentProcessId=", "").trim();
- console.log(iid);
- logger({
- cnl: ["local", "console", "server"],
- key: "checkMainExe",
- dtl: `iid1: ${iid}`,
- });
- iid = cp
- .execSync(
- `cmd /c chcp 65001>nul && C:\\Windows\\System32\\wbem\\wmic process where ^(processid^=${iid}^) get parentprocessid /value`
- )
- .toString();
- iid = iid.replace("ParentProcessId=", "").trim();
- logger({
- cnl: ["local", "console", "server"],
- key: "checkMainExe",
- dtl: `iid2: ${iid}`,
- });
- const executablePathBuffer = cp.execSync(
- `cmd /c chcp 65001>nul && C:\\Windows\\System32\\wbem\\wmic process where ^(processid^=${iid}^) get executablepath /value`
- );
- console.log(executablePathBuffer);
- const encoding = window.nodeRequire("encoding");
- // eslint-disable-next-line @typescript-eslint/no-unsafe-call
- let executablePath: string = encoding
- .convert(executablePathBuffer, "utf8", "gbk")
- .toString();
- logger({
- cnl: ["local", "console", "server"],
- key: "checkMainExe",
- dtl: executablePath,
- });
- executablePath = executablePath
- .replace("ExecutablePath=", "")
- .trim()
- .replace(/&/g, "&");
- if (executablePath === eval(`proceess.env.PORTABLE_EXECUTABLE_FILE`)) {
- const crypto: typeof import("crypto") = window.nodeRequire("crypto");
- const getHash = crypto
- .createHmac("sha256", "abcdefg")
- .update(fs.readFileSync(executablePath))
- .digest("hex");
- console.log("the hash: ", getHash);
- logger({
- cnl: ["local", "console", "server"],
- key: "checkMainExe",
- dtl: `the hash: ${getHash}`,
- });
- if (HOST_FILE_HASH_MAP.get(window.location.hostname) === getHash) {
- return true;
- }
- }
- // check filepath executablePath md5
- } catch (error) {
- console.log(error);
- logger({
- cnl: ["local", "console", "server"],
- key: "checkMainExe",
- ejn: JSON.stringify(error),
- });
- }
- return false;
- }
- /** 初始化桌面抓拍 */
- export function initScreenShot() {
- if (import.meta.env.DEV) return;
- if (!isElectron()) return;
- function handleStream(stream: MediaStream) {
- const video: HTMLVideoElement = document.querySelector("#ssVideo")!;
- video.srcObject = stream;
- video.onloadedmetadata = () => video.play();
- }
- const electron: typeof import("electron") = window.nodeRequire("electron");
- electron.desktopCapturer.getSources(
- { types: ["window", "screen"] },
- (e: any, sources: { id: string; name: string }[]) => {
- console.log(e, sources);
- for (const source of sources) {
- console.log(source);
- if (source.name === "Entire screen") {
- try {
- navigator.mediaDevices
- .getUserMedia({
- audio: false,
- video: {
- // @ts-expect-error 不确定是chrome/electron标准是否不一样,需要测试
- mandatory: {
- chromeMediaSource: "desktop",
- chromeMediaSourceId: source.id,
- minWidth: 600,
- maxWidth: 600,
- minHeight: 480,
- maxHeight: 480,
- },
- },
- })
- .then((stream) => handleStream(stream))
- .catch((e) =>
- logger({
- cnl: ["local", "server"],
- pgu: "AUTO",
- act: "ss-failed",
- possibleError: e,
- })
- );
- } catch (err) {
- logger({
- cnl: ["local", "server"],
- pgu: "AUTO",
- act: "ss-failed",
- ejn: JSON.stringify(err),
- });
- }
- return;
- }
- }
- }
- );
- }
- /** 保存当前屏幕截图 */
- export async function getScreenShot({ cause = "ss-none" }) {
- const video: HTMLVideoElement = document.querySelector("#ssVideo")!;
- async function getSnapShot() {
- return new Promise((resolve, reject) => {
- if (video.readyState !== 4 || !(<MediaStream>video.srcObject)?.active) {
- reject("desktop没有正常启用");
- }
- video.pause();
- const canvas = document.createElement("canvas");
- canvas.width = 220;
- canvas.height = 165;
- const context = canvas.getContext("2d");
- context?.drawImage(video, 0, 0, 220, 165);
- canvas.toBlob(resolve, "image/png", 0.95);
- });
- }
- if (window.location.pathname.includes("/login")) return;
- const captureBlob = await getSnapShot();
- const res = await getCapturePhotoYunSign({ fileSuffix: "png" });
- try {
- await saveCapturePhoto(res.data.formUrl, res.data.formParams, {
- file: captureBlob,
- });
- logger({
- pgu: "AUTO",
- cnl: ["server"],
- dtl: "桌面抓拍保存成功",
- ext: {
- resultUrl: res.data.accessUrl,
- cause,
- },
- });
- } catch (error) {
- console.log(error);
- logger({
- pgu: "AUTO",
- cnl: ["server"],
- dtl: "桌面抓拍失败",
- ejn: JSON.stringify(error),
- ext: {
- cause,
- },
- });
- } finally {
- video && video.play();
- }
- }
- /** 在app resize时触发 */
- export function registerOnResize() {
- const throttledResizeLog = throttle(() => {
- logger({
- cnl: ["local", "server"],
- pgu: "AUTO",
- act: "registerOnResize",
- ext: {
- width: window.screen.width,
- height: window.screen.height,
- screenX: window.screen.availWidth,
- screenY: window.screen.availHeight,
- clientWidth: document.documentElement.clientWidth,
- clientHeight: document.documentElement.clientHeight,
- windowInnerWidth: window.innerWidth,
- windowInnerHeight: window.innerHeight,
- windowOuterWidth: window.outerWidth,
- windowOuterHeight: window.outerHeight,
- },
- });
- void getScreenShot({ cause: "ss-registerOnResize" });
- }, 3000);
- window.onresize = throttledResizeLog;
- }
|