468 lines
16 KiB
JavaScript
468 lines
16 KiB
JavaScript
(function () {
|
||
const supportedLanguages = ["en", "ar", "tr", "id"];
|
||
const languageLabels = {
|
||
en: "EN",
|
||
ar: "AR",
|
||
tr: "TR",
|
||
id: "ID"
|
||
};
|
||
const API_BASE_URL = "https://jvapi.haiyihy.com";
|
||
|
||
const fallbackMessages = {
|
||
en: {
|
||
document_title: "Host Policy",
|
||
back: "Back",
|
||
language_button_aria: "Change language",
|
||
anchor_policy: "Host Policy",
|
||
platform_policy: "Agency Policy",
|
||
policy_loading: "Loading policy...",
|
||
policy_empty: "No policy data",
|
||
policy_missing_token: "Missing token",
|
||
policy_missing_team: "Missing team ID",
|
||
policy_load_failed: "Failed to load policy",
|
||
policy_level: "Level",
|
||
policy_online: "Online (Hour)",
|
||
policy_effective_day: "Valid days",
|
||
policy_target: "Target",
|
||
policy_host_salary: "Host salary",
|
||
policy_agent_salary: "Agent salary",
|
||
policy_total_salary: "Total salary"
|
||
},
|
||
ar: {
|
||
document_title: "سياسة المضيف",
|
||
back: "رجوع",
|
||
language_button_aria: "تغيير اللغة",
|
||
anchor_policy: "سياسة المضيف",
|
||
platform_policy: "سياسة الوكالة",
|
||
policy_loading: "جار تحميل السياسة...",
|
||
policy_empty: "لا توجد بيانات سياسة",
|
||
policy_missing_token: "رمز الدخول مفقود",
|
||
policy_missing_team: "معرّف الفريق مفقود",
|
||
policy_load_failed: "فشل تحميل السياسة",
|
||
policy_level: "المستوى",
|
||
policy_online: "الاتصال (ساعة)",
|
||
policy_effective_day: "الأيام الصالحة",
|
||
policy_target: "الهدف",
|
||
policy_host_salary: "راتب المضيف",
|
||
policy_agent_salary: "راتب الوكيل",
|
||
policy_total_salary: "إجمالي الراتب"
|
||
},
|
||
tr: {
|
||
document_title: "Host Politikası",
|
||
back: "Geri",
|
||
language_button_aria: "Dili değiştir",
|
||
anchor_policy: "Host Politikası",
|
||
platform_policy: "Ajans Politikası",
|
||
policy_loading: "Politika yükleniyor...",
|
||
policy_empty: "Politika verisi yok",
|
||
policy_missing_token: "Token eksik",
|
||
policy_missing_team: "Takım ID eksik",
|
||
policy_load_failed: "Politika yüklenemedi",
|
||
policy_level: "Seviye",
|
||
policy_online: "Online (Saat)",
|
||
policy_effective_day: "Geçerli gün",
|
||
policy_target: "Hedef",
|
||
policy_host_salary: "Host maaşı",
|
||
policy_agent_salary: "Ajans maaşı",
|
||
policy_total_salary: "Toplam maaş"
|
||
},
|
||
id: {
|
||
document_title: "Kebijakan Host",
|
||
back: "Kembali",
|
||
language_button_aria: "Ubah bahasa",
|
||
anchor_policy: "Kebijakan Host",
|
||
platform_policy: "Kebijakan Agensi",
|
||
policy_loading: "Memuat kebijakan...",
|
||
policy_empty: "Tidak ada data kebijakan",
|
||
policy_missing_token: "Token tidak ditemukan",
|
||
policy_missing_team: "ID tim tidak ditemukan",
|
||
policy_load_failed: "Gagal memuat kebijakan",
|
||
policy_level: "Level",
|
||
policy_online: "Online (Jam)",
|
||
policy_effective_day: "Hari valid",
|
||
policy_target: "Target",
|
||
policy_host_salary: "Gaji host",
|
||
policy_agent_salary: "Gaji agensi",
|
||
policy_total_salary: "Total gaji"
|
||
}
|
||
};
|
||
|
||
const params = readURLParams();
|
||
let currentLang = normalizeLanguage(params.get("lang"));
|
||
let currentMessages = fallbackMessages[currentLang] || fallbackMessages.en;
|
||
let currentPolicy = null;
|
||
let policyStatusKey = "policy_loading";
|
||
|
||
function isAgencyPolicy() {
|
||
return params.get("from") === "agencycenter";
|
||
}
|
||
|
||
function policyTitleKey() {
|
||
return isAgencyPolicy() ? "platform_policy" : "anchor_policy";
|
||
}
|
||
|
||
function readURLParams() {
|
||
const result = new URLSearchParams(window.location.search);
|
||
const hashQuery = window.location.hash.includes("?") ? window.location.hash.split("?")[1] : "";
|
||
const hashParams = new URLSearchParams(hashQuery);
|
||
hashParams.forEach((value, key) => {
|
||
if (!result.has(key)) result.set(key, value);
|
||
});
|
||
return result;
|
||
}
|
||
|
||
function readRawParam(name) {
|
||
const queries = [window.location.search.replace(/^\?/, "")];
|
||
if (window.location.hash.includes("?")) queries.push(window.location.hash.split("?")[1]);
|
||
|
||
for (const query of queries) {
|
||
for (const part of query.split("&")) {
|
||
if (!part) continue;
|
||
const equalIndex = part.indexOf("=");
|
||
const rawKey = equalIndex >= 0 ? part.slice(0, equalIndex) : part;
|
||
const rawValue = equalIndex >= 0 ? part.slice(equalIndex + 1) : "";
|
||
let decodedKey = "";
|
||
try {
|
||
decodedKey = decodeURIComponent(rawKey);
|
||
} catch (error) {
|
||
continue;
|
||
}
|
||
if (decodedKey !== name) continue;
|
||
try {
|
||
return decodeURIComponent(rawValue.replace(/\+/g, "%2B"));
|
||
} catch (error) {
|
||
return rawValue;
|
||
}
|
||
}
|
||
}
|
||
return "";
|
||
}
|
||
|
||
function normalizeLanguage(lang) {
|
||
const value = String(lang || "en").toLowerCase();
|
||
return supportedLanguages.includes(value) ? value : "en";
|
||
}
|
||
|
||
async function loadMessages(lang) {
|
||
const normalizedLang = normalizeLanguage(lang);
|
||
if (window.location.protocol === "file:") return fallbackMessages[normalizedLang];
|
||
|
||
try {
|
||
const response = await fetch(`./locales/${normalizedLang}.json?v=20260428-2100`, { cache: "no-store" });
|
||
if (response.ok) return await response.json();
|
||
} catch (error) {
|
||
return fallbackMessages[normalizedLang];
|
||
}
|
||
|
||
return fallbackMessages[normalizedLang];
|
||
}
|
||
|
||
function message(key, fallback) {
|
||
return currentMessages[key] || fallbackMessages.en[key] || fallback || key;
|
||
}
|
||
|
||
function renderMessages(messages) {
|
||
document.querySelectorAll("[data-i18n]").forEach((node) => {
|
||
const value = messages[node.dataset.i18n];
|
||
if (value) node.textContent = value;
|
||
});
|
||
|
||
document.querySelectorAll("[data-i18n-aria]").forEach((node) => {
|
||
const value = messages[node.dataset.i18nAria];
|
||
if (value) node.setAttribute("aria-label", value);
|
||
});
|
||
|
||
const title = messages[policyTitleKey()] || messages.anchor_policy || fallbackMessages.en.anchor_policy;
|
||
document.querySelectorAll("[data-policy-title]").forEach((node) => {
|
||
node.textContent = title;
|
||
});
|
||
document.querySelector(".policy-page")?.setAttribute("aria-label", title);
|
||
}
|
||
|
||
function apiBaseURL() {
|
||
const override = window.HYAPP_API_BASE_URL || params.get("apiBase");
|
||
if (override) return String(override).replace(/\/+$/, "");
|
||
return API_BASE_URL.replace(/\/+$/, "");
|
||
}
|
||
|
||
function normalizeAuthorization(token) {
|
||
const value = String(token || "").trim();
|
||
if (!value) return "";
|
||
return /^bearer\s+/i.test(value) ? value : `Bearer ${value}`;
|
||
}
|
||
|
||
function authHeadersFromToken(token) {
|
||
return {
|
||
Authorization: normalizeAuthorization(token),
|
||
"req-lang": currentLang,
|
||
"req-client": "H5",
|
||
"req-version": "V2",
|
||
"req-zone": Intl.DateTimeFormat().resolvedOptions().timeZone || "Asia/Shanghai",
|
||
"req-app-intel": "version=1.0.0;build=1;model=H5;sysVersion=Web;channel=Web",
|
||
"req-sys-origin": "origin=ATYOU;originChild=ATYOU"
|
||
};
|
||
}
|
||
|
||
function renderPolicyStatus(key, fallback) {
|
||
policyStatusKey = key;
|
||
const status = document.querySelector("#policyStatus");
|
||
const list = document.querySelector("#policyList");
|
||
const region = document.querySelector("#policyRegion");
|
||
if (status) {
|
||
status.textContent = message(key, fallback);
|
||
status.hidden = false;
|
||
}
|
||
if (list) {
|
||
list.hidden = true;
|
||
list.replaceChildren();
|
||
}
|
||
if (region) region.textContent = "";
|
||
}
|
||
|
||
function formatPlainValue(value) {
|
||
if (value === null || value === undefined || value === "") return "0";
|
||
return String(value);
|
||
}
|
||
|
||
function formatTarget(value) {
|
||
const number = Number(value);
|
||
if (!Number.isFinite(number)) return formatPlainValue(value);
|
||
if (number >= 1000000) return `${(number / 1000000).toFixed(1)}M`;
|
||
if (number >= 1000) return `${(number / 1000).toFixed(1)}K`;
|
||
return String(number);
|
||
}
|
||
|
||
function formatSalary(value, policyType) {
|
||
const text = formatPlainValue(value);
|
||
return policyType === "SALARY_DIAMOND" ? text : `$${text}`;
|
||
}
|
||
|
||
function createPolicyCell(label, value) {
|
||
const cell = document.createElement("div");
|
||
cell.className = "policy-cell";
|
||
|
||
const labelNode = document.createElement("div");
|
||
labelNode.className = "policy-cell-label";
|
||
labelNode.textContent = label;
|
||
|
||
const valueNode = document.createElement("div");
|
||
valueNode.className = "policy-cell-value";
|
||
valueNode.textContent = value;
|
||
|
||
cell.append(labelNode, valueNode);
|
||
return cell;
|
||
}
|
||
|
||
function createPolicyRow(item, policyType) {
|
||
const row = document.createElement("article");
|
||
row.className = "policy-row";
|
||
|
||
const head = document.createElement("div");
|
||
head.className = "policy-row-head";
|
||
|
||
const level = document.createElement("div");
|
||
level.className = "policy-level";
|
||
level.textContent = `${message("policy_level")} ${formatPlainValue(item.level)}`;
|
||
|
||
const effectiveDay = document.createElement("div");
|
||
effectiveDay.className = "policy-effective-day";
|
||
effectiveDay.textContent = `${message("policy_effective_day")}: ${formatPlainValue(item.effectiveDay)}`;
|
||
head.append(level, effectiveDay);
|
||
|
||
const grid = document.createElement("div");
|
||
grid.className = "policy-grid";
|
||
grid.append(
|
||
createPolicyCell(message("policy_online"), formatPlainValue(item.onlineTime)),
|
||
createPolicyCell(message("policy_target"), formatTarget(item.target)),
|
||
createPolicyCell(message("policy_host_salary"), formatSalary(item.memberSalary, policyType)),
|
||
createPolicyCell(message("policy_agent_salary"), formatSalary(item.ownSalary, policyType)),
|
||
createPolicyCell(message("policy_total_salary"), formatSalary(item.totalSalary, policyType))
|
||
);
|
||
|
||
row.append(head, grid);
|
||
return row;
|
||
}
|
||
|
||
function pickTeamId(entry) {
|
||
return entry?.teamProfile?.id || entry?.teamId || entry?.id || "";
|
||
}
|
||
|
||
async function fetchTeamEntryId(token) {
|
||
try {
|
||
const url = new URL("/team/entry", `${apiBaseURL()}/`);
|
||
const response = await fetch(url.toString(), {
|
||
cache: "no-store",
|
||
headers: authHeadersFromToken(token)
|
||
});
|
||
const data = await response.json().catch(() => ({}));
|
||
if (!response.ok || data.status === false) {
|
||
throw new Error(data.errorMsg || data.message || `Request failed: ${response.status}`);
|
||
}
|
||
|
||
return pickTeamId(data.body || data.data || {});
|
||
} catch (error) {
|
||
console.error("Failed to resolve team ID:", error);
|
||
return "";
|
||
}
|
||
}
|
||
|
||
async function resolveTeamId(token, forceTeamEntry = false) {
|
||
const directTeamId = params.get("teamId") || params.get("team_id") || params.get("TEAM_ID");
|
||
if (directTeamId && !forceTeamEntry) return directTeamId;
|
||
return fetchTeamEntryId(token);
|
||
}
|
||
|
||
async function requestTeamPolicy(token, teamId) {
|
||
const url = new URL("/team/release/policy", `${apiBaseURL()}/`);
|
||
url.searchParams.set("id", teamId);
|
||
|
||
const response = await fetch(url.toString(), {
|
||
cache: "no-store",
|
||
headers: authHeadersFromToken(token)
|
||
});
|
||
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.body || data.data || {};
|
||
}
|
||
|
||
function renderAnchorPolicy(policy) {
|
||
const rows = Array.isArray(policy?.policy) ? policy.policy : [];
|
||
const list = document.querySelector("#policyList");
|
||
const status = document.querySelector("#policyStatus");
|
||
const region = document.querySelector("#policyRegion");
|
||
if (!list || !status) return;
|
||
|
||
if (region) {
|
||
region.textContent = [policy?.regionCode || policy?.region, policy?.countryCode].filter(Boolean).join(" · ");
|
||
}
|
||
|
||
if (!rows.length || policy?.empty) {
|
||
renderPolicyStatus("policy_empty");
|
||
return;
|
||
}
|
||
|
||
status.textContent = "";
|
||
status.hidden = true;
|
||
list.hidden = false;
|
||
list.replaceChildren(...rows.map((item) => createPolicyRow(item, policy?.policyType)));
|
||
}
|
||
|
||
async function fetchAnchorPolicy() {
|
||
renderPolicyStatus("policy_loading");
|
||
|
||
const token = readRawParam("token");
|
||
if (!token) {
|
||
renderPolicyStatus("policy_missing_token");
|
||
return;
|
||
}
|
||
|
||
try {
|
||
const teamId = await resolveTeamId(token);
|
||
if (!teamId) {
|
||
renderPolicyStatus("policy_missing_team");
|
||
return;
|
||
}
|
||
|
||
try {
|
||
currentPolicy = await requestTeamPolicy(token, teamId);
|
||
} catch (error) {
|
||
const fallbackTeamId = await resolveTeamId(token, true);
|
||
if (!fallbackTeamId || fallbackTeamId === teamId) throw error;
|
||
currentPolicy = await requestTeamPolicy(token, fallbackTeamId);
|
||
}
|
||
|
||
renderAnchorPolicy(currentPolicy);
|
||
} catch (error) {
|
||
console.error("Failed to load anchor policy:", error);
|
||
currentPolicy = null;
|
||
renderPolicyStatus("policy_load_failed", error.message);
|
||
}
|
||
}
|
||
|
||
function syncBackFallback() {
|
||
const backButton = document.querySelector(".back-button");
|
||
if (!backButton) return;
|
||
|
||
backButton.addEventListener("click", () => {
|
||
if (window.history.length > 1) {
|
||
window.history.back();
|
||
return;
|
||
}
|
||
|
||
const nextParams = new URLSearchParams(params);
|
||
const token = readRawParam("token");
|
||
if (token) nextParams.set("token", token);
|
||
if (currentLang) nextParams.set("lang", currentLang);
|
||
const query = nextParams.toString();
|
||
const fallbackPath = isAgencyPolicy() ? "../agency-center/index.html" : "./index.html";
|
||
window.location.href = `${fallbackPath}${query ? `?${query}` : ""}`;
|
||
});
|
||
}
|
||
|
||
function setLanguageMenuOpen(open) {
|
||
const languageButton = document.querySelector(".language-button");
|
||
const languageMenu = document.querySelector(".language-menu");
|
||
if (!languageButton || !languageMenu) return;
|
||
|
||
languageMenu.hidden = !open;
|
||
languageButton.setAttribute("aria-expanded", String(open));
|
||
}
|
||
|
||
function renderLanguageControls(messages) {
|
||
const languageButton = document.querySelector(".language-button");
|
||
if (languageButton) {
|
||
languageButton.textContent = languageLabels[currentLang];
|
||
languageButton.setAttribute("aria-label", messages.language_button_aria || "Change language");
|
||
}
|
||
|
||
document.querySelectorAll(".language-menu [data-lang]").forEach((button) => {
|
||
const isActive = button.dataset.lang === currentLang;
|
||
button.classList.toggle("is-active", isActive);
|
||
button.setAttribute("aria-pressed", String(isActive));
|
||
});
|
||
}
|
||
|
||
async function applyLanguage(lang) {
|
||
currentLang = normalizeLanguage(lang);
|
||
const messages = await loadMessages(currentLang);
|
||
currentMessages = messages;
|
||
|
||
document.documentElement.lang = currentLang;
|
||
document.documentElement.dir = currentLang === "ar" ? "rtl" : "ltr";
|
||
document.title = messages[policyTitleKey()] || messages.anchor_policy || messages.document_title || "Host Policy";
|
||
renderMessages(messages);
|
||
renderLanguageControls(messages);
|
||
if (currentPolicy) {
|
||
renderAnchorPolicy(currentPolicy);
|
||
} else {
|
||
renderPolicyStatus(policyStatusKey);
|
||
}
|
||
}
|
||
|
||
document.querySelector(".language-button")?.addEventListener("click", (event) => {
|
||
event.stopPropagation();
|
||
const languageMenu = document.querySelector(".language-menu");
|
||
setLanguageMenuOpen(Boolean(languageMenu?.hidden));
|
||
});
|
||
|
||
document.querySelectorAll(".language-menu [data-lang]").forEach((button) => {
|
||
button.addEventListener("click", (event) => {
|
||
event.stopPropagation();
|
||
setLanguageMenuOpen(false);
|
||
applyLanguage(button.dataset.lang);
|
||
});
|
||
});
|
||
|
||
document.addEventListener("click", () => {
|
||
setLanguageMenuOpen(false);
|
||
});
|
||
|
||
syncBackFallback();
|
||
applyLanguage(currentLang).then(fetchAnchorPolicy);
|
||
})();
|