chatapp-h5/h5/host-setting/host-setting.js
2026-04-24 21:13:53 +08:00

453 lines
14 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const API_BASE_URL = "https://jvapi.haiyihy.com";
const icons = {
back: "./icons/back.svg",
arrow: "./icons/arrow.svg"
};
let commonHeaders = {
authorization: "Bearer undefined",
"req-app-intel": "version=1.0.0;build=1;model=SM-G9550;sysVersion=9;channel=Google",
"req-client": "Android",
"req-imei": "8fa54d728ab449e04f9292329ed44bda",
"req-lang": "id-ID",
"req-sys-origin": "origin=ATYOU;originChild=ATYOU",
"req-version": "V2",
"req-zone": "Asia/Shanghai"
};
const i18n = {
en: {
host_setting: "Host Setting",
bank_card: "Bank card",
more: "More",
add_payment_method: "Add payment method",
category: "Category",
card_number_label: "Card number",
payee: "Payee",
kyc: "KYC",
review_passed: "Review passed",
review_failed: "Review failed",
awaiting_review: "Awaiting review",
complete_information: "Complete information",
passport_id_card_title: "Passport / ID card",
contact_number: "Contact number",
other_description: "Other description",
something_went_wrong: "Something went wrong."
},
ar: {
host_setting: "إعدادات المضيف",
bank_card: "البطاقة البنكية",
more: "المزيد",
add_payment_method: "إضافة طريقة دفع",
category: "الفئة",
card_number_label: "رقم البطاقة",
payee: "المستفيد",
kyc: "KYC",
review_passed: "تمت الموافقة",
review_failed: "فشل التحقق",
awaiting_review: "بانتظار المراجعة",
complete_information: "إكمال المعلومات",
passport_id_card_title: "جواز السفر / الهوية",
contact_number: "رقم التواصل",
other_description: "وصف آخر",
something_went_wrong: "حدث خطأ ما."
},
tr: {
host_setting: "Host Ayarı",
bank_card: "Banka kartı",
more: "Daha fazla",
add_payment_method: "Ödeme yöntemi ekle",
category: "Kategori",
card_number_label: "Kart numarası",
payee: "Alacaklı",
kyc: "KYC",
review_passed: "İnceleme geçti",
review_failed: "İnceleme başarısız",
awaiting_review: "İnceleme bekliyor",
complete_information: "Bilgileri tamamla",
passport_id_card_title: "Pasaport / kimlik kartı",
contact_number: "İletişim numarası",
other_description: "Diğer açıklama",
something_went_wrong: "Bir şeyler ters gitti."
},
bn: {
host_setting: "হোস্ট সেটিং",
bank_card: "ব্যাংক কার্ড",
more: "আরও",
add_payment_method: "পেমেন্ট পদ্ধতি যোগ করুন",
category: "ক্যাটাগরি",
card_number_label: "কার্ড নম্বর",
payee: "প্রাপক",
kyc: "KYC",
review_passed: "রিভিউ পাস হয়েছে",
review_failed: "রিভিউ ব্যর্থ হয়েছে",
awaiting_review: "রিভিউ অপেক্ষমাণ",
complete_information: "তথ্য সম্পূর্ণ করুন",
passport_id_card_title: "পাসপোর্ট / আইডি কার্ড",
contact_number: "যোগাযোগ নম্বর",
other_description: "অন্যান্য বিবরণ",
something_went_wrong: "কিছু ভুল হয়েছে।"
}
};
const state = {
lang: resolveLanguage(),
bankCard: null,
withdrawInfo: null,
profile: {}
};
const $ = (selector) => document.querySelector(selector);
const $$ = (selector) => Array.from(document.querySelectorAll(selector));
const t = (key) => (i18n[state.lang] && i18n[state.lang][key]) || i18n.en[key] || key;
function resolveLanguage() {
const params = new URLSearchParams(window.location.search);
const hashQuery = window.location.hash.includes("?") ? window.location.hash.split("?")[1] : "";
const hashParams = new URLSearchParams(hashQuery);
const lang = params.get("lang") || hashParams.get("lang") || navigator.language || "en";
if (lang.startsWith("ar")) return "ar";
if (lang.startsWith("tr")) return "tr";
if (lang.startsWith("bn")) return "bn";
return "en";
}
function splitHeaderPairs(value) {
const result = {};
if (!value) return result;
value.split(";").forEach((item) => {
const index = item.indexOf("=");
if (index > -1) result[item.slice(0, index)] = item.slice(index + 1);
});
return result;
}
function parseAccessOrigin(raw) {
const data = JSON.parse(raw);
const appIntel = splitHeaderPairs(data["Req-App-Intel"]);
const sysOrigin = splitHeaderPairs(data["Req-Sys-Origin"]);
return {
reqLang: data["Req-Lang"],
authorization: data.Authorization,
buildVersion: appIntel.build,
appVersion: appIntel.version,
appChannel: appIntel.channel,
reqImei: appIntel["Req-Imei"],
sysOrigin: sysOrigin.origin,
sysOriginChild: sysOrigin.child
};
}
function setHeadersFromApp(headers) {
const next = {};
if (headers.authorization) next.authorization = headers.authorization;
if (headers.reqLang) next["req-lang"] = headers.reqLang;
if (headers.appVersion || headers.buildVersion || headers.appChannel) {
const intel = [];
if (headers.appVersion) intel.push(`version=${headers.appVersion}`);
if (headers.buildVersion) intel.push(`build=${headers.buildVersion}`);
if (headers.appChannel) intel.push(`channel=${headers.appChannel}`);
next["req-app-intel"] = intel.join(";");
}
if (headers.reqImei) next["req-imei"] = headers.reqImei;
if (headers.sysOrigin) {
const origin = [`origin=${headers.sysOrigin}`];
if (headers.sysOriginChild) origin.push(`child=${headers.sysOriginChild}`);
next["req-sys-origin"] = origin.join(";");
}
commonHeaders = { ...commonHeaders, ...next };
}
function connectToApp() {
return new Promise((resolve) => {
window.renderData = resolve;
window.getIosAccessOriginParam = resolve;
if (!(window.app || window.webkit || window.FlutterPageControl)) {
resolve({ success: true, environment: "browser" });
return;
}
let attempt = 0;
const poll = () => {
attempt += 1;
if (window.app && typeof window.app.getAccessOrigin === "function") {
const raw = window.app.getAccessOrigin();
if (raw) setHeadersFromApp(parseAccessOrigin(raw));
resolve({ success: true, environment: "app" });
return;
}
if (attempt < 50) {
window.setTimeout(poll, 100);
return;
}
if (window.FlutterApp && typeof window.FlutterApp.postMessage === "function") {
window.FlutterApp.postMessage("requestAccessOrigin");
}
resolve({ success: true, environment: "app" });
};
poll();
}).then((result) => {
if (typeof result === "string") {
setHeadersFromApp(parseAccessOrigin(result));
return { success: true, environment: "app" };
}
return result;
});
}
async function apiGet(path) {
const response = await fetch(`${API_BASE_URL}${path}`, {
method: "GET",
headers: commonHeaders
});
const data = await response.json().catch(() => ({}));
if (!response.ok || data.status === false) {
const error = new Error(data.errorMsg || data.message || `Request failed: ${response.status}`);
error.response = data;
throw error;
}
return data;
}
async function fetchUserProfile() {
const cached = localStorage.getItem("userProfile");
if (cached) {
try {
state.profile = JSON.parse(cached) || {};
} catch (error) {
console.error("Failed to parse userProfile:", error);
}
}
try {
const result = await apiGet("/team/member/profile");
if (result.status && result.body) {
state.profile = result.body;
localStorage.setItem("userProfile", JSON.stringify(result.body));
}
} catch (error) {
console.error("Failed to fetch user profile:", error);
}
}
function getMemberId() {
return state.profile.id || state.profile.userId || state.profile.account || null;
}
function calculateRoles(identity) {
if (!identity) return ["guest"];
const roles = [];
if (identity.freightAgent) roles.push("freightAgent");
if (identity.agent) roles.push("agent");
if (identity.bdLeader) roles.push("bdLeader");
if (identity.bd) roles.push("bd");
if (identity.anchor) roles.push("anchor");
if (identity.admin) roles.push("admin");
return roles.length ? roles : ["guest"];
}
function getPrimaryRole(roles) {
const weight = {
guest: 0,
anchor: 1,
agent: 2,
bd: 3,
bdLeader: 4,
freightAgent: 5,
admin: 6
};
return roles.reduce((current, role) => (weight[role] > weight[current] ? role : current), "guest");
}
function getDefaultPage(role) {
return {
admin: "/admin-center",
freightAgent: "/coin-seller",
agent: "/agency-center",
bdLeader: "/bd-leader-center",
bd: "/bd-center",
anchor: "/host-center",
guest: "/apply"
}[role] || "/apply";
}
async function checkIdentityAndRedirect() {
const memberId = getMemberId();
if (!memberId) {
navigateTo("/apply");
return;
}
const result = await apiGet("/app/h5/identity");
if (!result.status || !result.body) return;
const roles = calculateRoles(result.body);
if (!roles.includes("anchor")) {
navigateTo(getDefaultPage(getPrimaryRole(roles)));
}
}
async function fetchBankCards() {
const result = await apiGet("/wallet/bank-card/list");
if (result.status && result.body) {
state.bankCard = result.body.find((item) => item.use) || null;
}
}
async function fetchWithdrawInfo() {
const result = await apiGet("/wallet/withdraw-info/list");
if (result.status && result.body && result.body.length > 0) {
const first = result.body[0];
let previewUrls = [];
try {
previewUrls = JSON.parse(first.passportFrontUrl || "[]").map((item) => item);
} catch (error) {
console.error("Failed to parse passportFrontUrl:", error);
}
state.withdrawInfo = { previewUrls, ...first };
}
}
function normalizeRoute(target) {
const url = new URL(target, window.location.origin);
const currentLang = new URLSearchParams(window.location.search).get("lang");
if (currentLang && !url.searchParams.has("lang")) url.searchParams.set("lang", currentLang);
return `${url.pathname}${url.search}${url.hash}`;
}
function navigateTo(target) {
window.location.href = normalizeRoute(target);
}
function closePage() {
if (window.history.length > 1) {
window.history.back();
return;
}
if (window.app && typeof window.app.closePage === "function") {
window.app.closePage();
return;
}
if (window.FlutterPageControl && typeof window.FlutterPageControl.postMessage === "function") {
window.FlutterPageControl.postMessage("close_page");
}
}
function showToast(message) {
const toast = $("#toast");
toast.textContent = message;
toast.hidden = false;
window.clearTimeout(showToast.timer);
showToast.timer = window.setTimeout(() => {
toast.hidden = true;
}, 2500);
}
function renderI18n() {
document.documentElement.lang = state.lang;
document.documentElement.dir = state.lang === "ar" ? "rtl" : "ltr";
$("[data-action='language']").textContent = state.lang.toUpperCase();
$$("[data-i18n]").forEach((node) => {
node.textContent = t(node.dataset.i18n);
});
}
function renderIcons() {
$("#backIcon").src = icons.back;
["#bankAddArrow", "#kycHeaderArrow", "#kycAddArrow"].forEach((selector) => {
$(selector).src = icons.arrow;
});
}
function renderBankCard() {
const hasCard = Boolean(state.bankCard);
$("#bankMoreButton").hidden = !hasCard;
$("#addBankCardRow").hidden = hasCard;
$("#bankDetail").hidden = !hasCard;
if (!hasCard) return;
$("#cardType").textContent = state.bankCard.cardType || "-";
$("#cardNo").textContent = state.bankCard.cardNo || "-";
$("#payee").textContent = state.bankCard.payee || "-";
}
function renderKyc() {
const info = state.withdrawInfo;
const hasInfo = Boolean(info);
$("#kycColon").hidden = !hasInfo;
$("#kycStatus").hidden = !hasInfo;
$("#kycHeaderButton").hidden = !hasInfo;
$("#completeKycRow").hidden = hasInfo;
$("#kycDetail").hidden = !hasInfo;
if (!hasInfo) return;
const status = $("#kycStatus");
status.className = "status-text";
if (info.status === "PASS") {
status.textContent = t("review_passed");
status.classList.add("status-pass");
} else if (info.status === "NOT_PASS") {
status.textContent = t("review_failed");
status.classList.add("status-failed");
} else if (info.status === "PENDING") {
status.textContent = t("awaiting_review");
status.classList.add("status-pending");
} else {
status.textContent = info.status || "";
}
const previewList = $("#previewList");
previewList.innerHTML = "";
(info.previewUrls || []).forEach((url) => {
const image = document.createElement("img");
image.src = url;
image.alt = "";
previewList.appendChild(image);
});
$("#contactNumber").textContent = info.contactNumber || "-";
$("#otherDescription").textContent = info.otherDescription || "-";
}
function render() {
renderI18n();
renderIcons();
renderBankCard();
renderKyc();
}
function bindEvents() {
$("[data-action='back']").addEventListener("click", closePage);
$("[data-action='language']").addEventListener("click", () => navigateTo("/language"));
$$("[data-route]").forEach((node) => {
node.addEventListener("click", () => navigateTo(node.dataset.route));
});
}
async function runTask(task, label) {
try {
await task();
} catch (error) {
console.error(`${label} failed:`, error);
if (label === "withdraw info") showToast(error.response?.errorMsg || error.message || t("something_went_wrong"));
}
}
async function init() {
localStorage.setItem("identity", JSON.stringify({ identity: "HOST" }));
bindEvents();
render();
try {
await connectToApp();
await fetchUserProfile();
await runTask(checkIdentityAndRedirect, "identity check");
await Promise.all([
runTask(fetchBankCards, "bank cards"),
runTask(fetchWithdrawInfo, "withdraw info")
]);
} catch (error) {
console.error("Host setting initialization failed:", error);
showToast(error.response?.errorMsg || error.message || t("something_went_wrong"));
} finally {
render();
}
}
init();