867 lines
30 KiB
JavaScript
867 lines
30 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: "Stream Center",
|
||
page_label: "Stream Center",
|
||
back: "Back",
|
||
title: "Stream Center",
|
||
language_button_aria: "Change language",
|
||
uid: "UID: 1234567890",
|
||
agency: "Agency: Bilibili(101013)",
|
||
streaming_duration: "Streaming Duration<br />(Minutes)",
|
||
current: "Current",
|
||
daily_details: "Daily data",
|
||
gift_points: "Gift points",
|
||
online_minutes: "Online minutes",
|
||
no_daily_data: "No daily data",
|
||
close: "Close",
|
||
open_daily_data: "Open daily data",
|
||
my_income: "My Income",
|
||
withdraw_exchange: "Withdraw/Exchange",
|
||
open_withdraw_exchange: "Open withdraw and exchange page",
|
||
open_anchor_policy: "Open anchor policy",
|
||
anchor_policy: "Anchor Policy",
|
||
policy_loading: "Loading policy...",
|
||
policy_empty: "No policy data",
|
||
policy_missing_token: "Missing token",
|
||
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: "مركز البث",
|
||
page_label: "مركز البث",
|
||
back: "رجوع",
|
||
title: "مركز البث",
|
||
language_button_aria: "تغيير اللغة",
|
||
uid: "معرّف المستخدم: 1234567890",
|
||
agency: "الوكالة: Bilibili(101013)",
|
||
streaming_duration: "مدة البث<br />(بالدقائق)",
|
||
current: "الحالي",
|
||
daily_details: "البيانات اليومية",
|
||
gift_points: "نقاط الهدايا",
|
||
online_minutes: "دقائق الاتصال",
|
||
no_daily_data: "لا توجد بيانات يومية",
|
||
close: "إغلاق",
|
||
open_daily_data: "فتح البيانات اليومية",
|
||
my_income: "دخلي",
|
||
withdraw_exchange: "سحب/استبدال",
|
||
open_withdraw_exchange: "فتح صفحة السحب والاستبدال",
|
||
open_anchor_policy: "فتح سياسة المضيف",
|
||
anchor_policy: "سياسة المضيف",
|
||
policy_loading: "جار تحميل السياسة...",
|
||
policy_empty: "لا توجد بيانات سياسة",
|
||
policy_missing_token: "رمز الدخول مفقود",
|
||
policy_load_failed: "فشل تحميل السياسة",
|
||
policy_level: "المستوى",
|
||
policy_online: "الاتصال (ساعة)",
|
||
policy_effective_day: "الأيام الصالحة",
|
||
policy_target: "الهدف",
|
||
policy_host_salary: "راتب المضيف",
|
||
policy_agent_salary: "راتب الوكيل",
|
||
policy_total_salary: "إجمالي الراتب"
|
||
},
|
||
tr: {
|
||
document_title: "Yayın Merkezi",
|
||
page_label: "Yayın Merkezi",
|
||
back: "Geri",
|
||
title: "Yayın Merkezi",
|
||
language_button_aria: "Dili değiştir",
|
||
uid: "UID: 1234567890",
|
||
agency: "Ajans: Bilibili(101013)",
|
||
streaming_duration: "Yayın Süresi<br />(Dakika)",
|
||
current: "Mevcut",
|
||
daily_details: "Günlük veri",
|
||
gift_points: "Hediye puanı",
|
||
online_minutes: "Online dakika",
|
||
no_daily_data: "Günlük veri yok",
|
||
close: "Kapat",
|
||
open_daily_data: "Günlük veriyi aç",
|
||
my_income: "Gelirim",
|
||
withdraw_exchange: "Çek/Değiştir",
|
||
open_withdraw_exchange: "Çekme ve değişim sayfasını aç",
|
||
open_anchor_policy: "Host politikasını aç",
|
||
anchor_policy: "Host Politikası",
|
||
policy_loading: "Politika yükleniyor...",
|
||
policy_empty: "Politika verisi yok",
|
||
policy_missing_token: "Token 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: "Pusat Streaming",
|
||
page_label: "Pusat Streaming",
|
||
back: "Kembali",
|
||
title: "Pusat Streaming",
|
||
language_button_aria: "Ubah bahasa",
|
||
uid: "UID: 1234567890",
|
||
agency: "Agensi: Bilibili(101013)",
|
||
streaming_duration: "Durasi Streaming<br />(Menit)",
|
||
current: "Saat ini",
|
||
daily_details: "Data harian",
|
||
gift_points: "Poin hadiah",
|
||
online_minutes: "Menit online",
|
||
no_daily_data: "Tidak ada data harian",
|
||
close: "Tutup",
|
||
open_daily_data: "Buka data harian",
|
||
my_income: "Penghasilan Saya",
|
||
withdraw_exchange: "Tarik/Tukar",
|
||
open_withdraw_exchange: "Buka halaman tarik dan tukar",
|
||
open_anchor_policy: "Buka kebijakan host",
|
||
anchor_policy: "Kebijakan Host",
|
||
policy_loading: "Memuat kebijakan...",
|
||
policy_empty: "Tidak ada data kebijakan",
|
||
policy_missing_token: "Token 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 currentProfile = null;
|
||
let currentAgencyProfile = null;
|
||
let currentTeamId = "";
|
||
let currentIdentity = null;
|
||
let currentSalary = "0.00";
|
||
let currentStreamingDuration = "0";
|
||
let currentGiftValue = "0";
|
||
let currentDailyTargets = [];
|
||
|
||
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-1610`, { cache: "no-store" });
|
||
if (response.ok) return await response.json();
|
||
} catch (error) {
|
||
return fallbackMessages[normalizedLang];
|
||
}
|
||
|
||
return fallbackMessages[normalizedLang];
|
||
}
|
||
|
||
function renderMessages(messages) {
|
||
document.querySelectorAll("[data-i18n]").forEach((node) => {
|
||
const value = messages[node.dataset.i18n];
|
||
if (value) node.textContent = value;
|
||
});
|
||
|
||
document.querySelectorAll("[data-i18n-html]").forEach((node) => {
|
||
const value = messages[node.dataset.i18nHtml];
|
||
if (value) node.innerHTML = value;
|
||
});
|
||
|
||
document.querySelectorAll("[data-i18n-aria]").forEach((node) => {
|
||
const value = messages[node.dataset.i18nAria];
|
||
if (value) node.setAttribute("aria-label", value);
|
||
});
|
||
}
|
||
|
||
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 profileUidPrefix(messages) {
|
||
const template = messages.uid || fallbackMessages.en.uid;
|
||
const marker = "1234567890";
|
||
return template.includes(marker) ? template.replace(marker, "").trim() : "UID:";
|
||
}
|
||
|
||
function pickProfileName(profile) {
|
||
return profile?.userNickname || profile?.name || "Oscar";
|
||
}
|
||
|
||
function pickProfileAccount(profile) {
|
||
return profile?.ownSpecialId?.account || profile?.account || profile?.id || "1234567890";
|
||
}
|
||
|
||
function agencyPrefix(messages) {
|
||
const template = messages.agency || fallbackMessages.en.agency;
|
||
const marker = "Bilibili(101013)";
|
||
return template.includes(marker) ? template.replace(marker, "").trim() : "Agency:";
|
||
}
|
||
|
||
function pickAgencyName(profile) {
|
||
return profile?.userNickname || profile?.name || profile?.teamName || "-";
|
||
}
|
||
|
||
function pickAgencyAccount(profile) {
|
||
return profile?.ownSpecialId?.account || profile?.account || profile?.id || "";
|
||
}
|
||
|
||
function formatAgencyText(profile, messages = currentMessages) {
|
||
const prefix = agencyPrefix(messages);
|
||
if (!profile) return `${prefix} -`;
|
||
|
||
const name = pickAgencyName(profile);
|
||
const account = pickAgencyAccount(profile);
|
||
return account ? `${prefix} ${name}(${account})` : `${prefix} ${name}`;
|
||
}
|
||
|
||
function renderAgencyProfile(profile, messages = currentMessages) {
|
||
const agencyButton = document.querySelector(".agency");
|
||
const agencyTextNode = document.querySelector(".agency span:first-child");
|
||
if (!agencyButton || !agencyTextNode) return;
|
||
|
||
agencyTextNode.textContent = formatAgencyText(profile, messages);
|
||
agencyButton.dataset.teamId = String(currentTeamId || pickAgencyTeamId(profile) || "");
|
||
agencyButton.dataset.account = String(profile?.account || "");
|
||
agencyButton.dataset.specialAccount = String(profile?.ownSpecialId?.account || "");
|
||
syncPolicyLink();
|
||
}
|
||
|
||
function pickAgencyTeamId(profile) {
|
||
return profile?.teamId || profile?.teamProfile?.id || profile?.id || "";
|
||
}
|
||
|
||
function pickTeamEntryId(entry) {
|
||
return entry?.teamProfile?.id || entry?.teamId || entry?.id || "";
|
||
}
|
||
|
||
function removeAvatarFallback() {
|
||
document.querySelector("#profileAvatarFallback")?.remove();
|
||
}
|
||
|
||
function ensureAvatarFallback(displayName) {
|
||
const avatarShell = document.querySelector(".avatar-shell");
|
||
if (!avatarShell) return null;
|
||
|
||
let avatarFallback = document.querySelector("#profileAvatarFallback");
|
||
if (avatarFallback) {
|
||
avatarFallback.hidden = false;
|
||
avatarFallback.setAttribute("aria-label", `${displayName} avatar`);
|
||
return avatarFallback;
|
||
}
|
||
|
||
const template = document.createElement("template");
|
||
template.innerHTML = `
|
||
<svg class="avatar-fallback" id="profileAvatarFallback" viewBox="0 0 72 72" role="img">
|
||
<defs>
|
||
<linearGradient id="avatarBg" x1="12" y1="8" x2="60" y2="64">
|
||
<stop stop-color="#5AF6E4"></stop>
|
||
<stop offset="1" stop-color="#D9FFF5"></stop>
|
||
</linearGradient>
|
||
</defs>
|
||
<circle cx="36" cy="36" r="35" fill="url(#avatarBg)"></circle>
|
||
<path d="M22 30 20 18l10 7M50 30l2-12-10 7" fill="#101820"></path>
|
||
<path d="M20 31c3-9 28-9 32 0 4 10-3 21-16 21S16 41 20 31Z" fill="#F7FBF7"></path>
|
||
<circle cx="29" cy="36" r="4" fill="#101820"></circle>
|
||
<circle cx="46" cy="36" r="4" fill="#101820"></circle>
|
||
<circle cx="25" cy="41" r="5" fill="#F0B64A" opacity=".9"></circle>
|
||
<path d="M35 42h3l-1.5 2Z" fill="#101820"></path>
|
||
<path d="M36 45c-2 2-5 3-8 2M38 45c2 2 5 3 8 2" fill="none" stroke="#101820" stroke-width="2" stroke-linecap="round"></path>
|
||
</svg>
|
||
`;
|
||
avatarFallback = template.content.firstElementChild;
|
||
avatarFallback.setAttribute("aria-label", `${displayName} avatar`);
|
||
avatarShell.appendChild(avatarFallback);
|
||
return avatarFallback;
|
||
}
|
||
|
||
function renderProfile(profile, messages = currentMessages) {
|
||
if (!profile) return;
|
||
|
||
const profileCard = document.querySelector(".profile-card");
|
||
const nameNode = document.querySelector("#profileName");
|
||
const uidNode = document.querySelector("#profileUid");
|
||
const avatarImage = document.querySelector("#profileAvatar");
|
||
const displayName = pickProfileName(profile);
|
||
const displayAccount = pickProfileAccount(profile);
|
||
|
||
if (profileCard) {
|
||
profileCard.dataset.userId = String(profile.id || "");
|
||
profileCard.dataset.account = String(profile.account || "");
|
||
profileCard.dataset.specialAccount = String(profile?.ownSpecialId?.account || "");
|
||
}
|
||
|
||
if (nameNode) nameNode.textContent = displayName;
|
||
if (uidNode) uidNode.textContent = `${profileUidPrefix(messages)} ${displayAccount}`.trim();
|
||
|
||
if (!avatarImage) return;
|
||
|
||
const avatar = profile.userAvatar ? String(profile.userAvatar) : "";
|
||
avatarImage.alt = displayName;
|
||
|
||
if (!avatar) {
|
||
avatarImage.hidden = true;
|
||
avatarImage.onerror = null;
|
||
avatarImage.removeAttribute("src");
|
||
ensureAvatarFallback(displayName);
|
||
return;
|
||
}
|
||
|
||
avatarImage.hidden = false;
|
||
removeAvatarFallback();
|
||
avatarImage.onerror = () => {
|
||
avatarImage.hidden = true;
|
||
avatarImage.removeAttribute("src");
|
||
ensureAvatarFallback(displayName);
|
||
};
|
||
avatarImage.src = avatar;
|
||
}
|
||
|
||
function hasOwn(object, key) {
|
||
return Boolean(object && Object.prototype.hasOwnProperty.call(object, key));
|
||
}
|
||
|
||
function isTruthyIdentityValue(value) {
|
||
if (typeof value === "boolean") return value;
|
||
if (typeof value === "number") return value === 1;
|
||
if (typeof value === "string") return ["true", "1", "yes"].includes(value.toLowerCase());
|
||
return false;
|
||
}
|
||
|
||
function shouldOpenJoinAgency(identity) {
|
||
if (!hasOwn(identity, "anchor")) return false;
|
||
return !isTruthyIdentityValue(identity.anchor);
|
||
}
|
||
|
||
function buildPageURL(path) {
|
||
const url = new URL(path, window.location.href);
|
||
const nextParams = new URLSearchParams(params);
|
||
const token = readRawParam("token");
|
||
if (token) nextParams.set("token", token);
|
||
if (currentLang) nextParams.set("lang", currentLang);
|
||
url.search = nextParams.toString();
|
||
return url.toString();
|
||
}
|
||
|
||
function openJoinAgencyPage() {
|
||
window.location.replace(buildPageURL("../join-agency/index.html"));
|
||
}
|
||
|
||
function formatCurrentSalary(value) {
|
||
const numericValue = Number(value);
|
||
if (Number.isFinite(numericValue)) return numericValue.toFixed(2);
|
||
return "0.00";
|
||
}
|
||
|
||
function pickCurrentSalary(body) {
|
||
if (typeof body === "number") return body;
|
||
if (body && typeof body === "object") {
|
||
return body.currentSalary ?? body.availableBalance ?? body.balance ?? 0;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
function renderCurrentSalary(value) {
|
||
currentSalary = formatCurrentSalary(value);
|
||
const salaryNode = document.querySelector("#currentSalary");
|
||
if (salaryNode) salaryNode.textContent = currentSalary;
|
||
}
|
||
|
||
function formatStreamingDuration(value) {
|
||
const numericValue = Number(value);
|
||
if (!Number.isFinite(numericValue)) return "0";
|
||
const safeValue = Math.max(0, numericValue);
|
||
return Number.isInteger(safeValue) ? String(safeValue) : String(Number(safeValue.toFixed(2)));
|
||
}
|
||
|
||
function pickStreamingDuration(body) {
|
||
const workTarget = pickFirstMemberWorkTarget(body);
|
||
return body?.onlineTime ?? body?.target?.onlineTime ?? workTarget?.target?.onlineTime ?? workTarget?.onlineTime ?? 0;
|
||
}
|
||
|
||
function renderStreamingDuration(value) {
|
||
currentStreamingDuration = formatStreamingDuration(value);
|
||
const durationNode = document.querySelector("#streamingDuration");
|
||
if (durationNode) durationNode.textContent = currentStreamingDuration;
|
||
}
|
||
|
||
function formatCountValue(value) {
|
||
if (value === null || value === undefined || value === "") return "-";
|
||
const number = Number(value);
|
||
if (Number.isFinite(number) && Number.isInteger(number)) return String(number);
|
||
if (Number.isFinite(number)) return String(Number(number.toFixed(2)));
|
||
return String(value);
|
||
}
|
||
|
||
function renderCurrentGiftValue(value) {
|
||
currentGiftValue = formatCountValue(value === null || value === undefined || value === "" ? 0 : value);
|
||
const giftNode = document.querySelector("#currentGiftValue");
|
||
const dailyGiftNode = document.querySelector("#dailyCurrentGift");
|
||
if (giftNode) giftNode.textContent = currentGiftValue;
|
||
if (dailyGiftNode) dailyGiftNode.textContent = currentGiftValue;
|
||
}
|
||
|
||
function pickFirstMemberWorkTarget(body) {
|
||
const targets = Array.isArray(body?.targets) ? body.targets : [];
|
||
return targets[0] || body?.target || null;
|
||
}
|
||
|
||
function pickGiftValue(workTarget) {
|
||
const target = workTarget?.target || workTarget || {};
|
||
return target.acceptGiftValue ?? target.giftValue ?? target.giftScore ?? target.currentGiftValue ?? null;
|
||
}
|
||
|
||
function pickDailyTargets(workTarget) {
|
||
const target = workTarget?.target || workTarget || {};
|
||
return Array.isArray(target.dailyTargets) ? target.dailyTargets : [];
|
||
}
|
||
|
||
function formatDateNumber(value) {
|
||
const text = String(value || "");
|
||
if (/^\d{8}$/.test(text)) {
|
||
return `${text.slice(0, 4)}.${text.slice(4, 6)}.${text.slice(6, 8)}`;
|
||
}
|
||
return text || "-";
|
||
}
|
||
|
||
function createDailyRow(item) {
|
||
const row = document.createElement("div");
|
||
row.className = "daily-row";
|
||
|
||
const date = document.createElement("div");
|
||
date.className = "daily-date";
|
||
date.textContent = formatDateNumber(item?.dateNumber);
|
||
|
||
const values = document.createElement("div");
|
||
values.className = "daily-values";
|
||
|
||
const gift = document.createElement("div");
|
||
gift.className = "daily-cell";
|
||
gift.innerHTML = `<span>${currentMessages.gift_points || fallbackMessages.en.gift_points}</span><strong>${formatCountValue(item?.acceptGiftValue ?? 0)}</strong>`;
|
||
|
||
const online = document.createElement("div");
|
||
online.className = "daily-cell";
|
||
online.innerHTML = `<span>${currentMessages.online_minutes || fallbackMessages.en.online_minutes}</span><strong>${formatCountValue(item?.onlineTime ?? 0)}</strong>`;
|
||
|
||
values.appendChild(gift);
|
||
values.appendChild(online);
|
||
row.appendChild(date);
|
||
row.appendChild(values);
|
||
return row;
|
||
}
|
||
|
||
function replaceNodeChildren(node, children) {
|
||
while (node.firstChild) node.removeChild(node.firstChild);
|
||
children.forEach((child) => node.appendChild(child));
|
||
}
|
||
|
||
function renderDailyTargets(targets = currentDailyTargets) {
|
||
currentDailyTargets = Array.isArray(targets) ? targets : [];
|
||
const list = document.querySelector("#dailyList");
|
||
if (!list) return;
|
||
|
||
if (!currentDailyTargets.length) {
|
||
const empty = document.createElement("div");
|
||
empty.className = "daily-empty";
|
||
empty.textContent = currentMessages.no_daily_data || fallbackMessages.en.no_daily_data;
|
||
replaceNodeChildren(list, [empty]);
|
||
return;
|
||
}
|
||
|
||
replaceNodeChildren(list, currentDailyTargets.map(createDailyRow));
|
||
}
|
||
|
||
function renderMemberWorkSummary(memberWork) {
|
||
const workTarget = pickFirstMemberWorkTarget(memberWork);
|
||
renderStreamingDuration(pickStreamingDuration(memberWork));
|
||
renderCurrentGiftValue(pickGiftValue(workTarget) ?? 0);
|
||
renderDailyTargets(pickDailyTargets(workTarget));
|
||
}
|
||
|
||
function setDailyModalOpen(open) {
|
||
const modal = document.querySelector("#dailyModal");
|
||
if (!modal) return;
|
||
modal.hidden = !open;
|
||
document.body.classList.toggle("daily-modal-open", open);
|
||
if (open) renderDailyTargets();
|
||
}
|
||
|
||
async function fetchUserProfile() {
|
||
const token = readRawParam("token");
|
||
if (!token) {
|
||
console.warn("Missing token for /team/member/profile");
|
||
return null;
|
||
}
|
||
|
||
try {
|
||
const url = new URL("/team/member/profile", `${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}`);
|
||
}
|
||
|
||
currentProfile = data.body || data.data || {};
|
||
renderProfile(currentProfile);
|
||
return currentProfile;
|
||
} catch (error) {
|
||
console.error("Failed to load user profile:", error);
|
||
return null;
|
||
}
|
||
}
|
||
|
||
async function fetchIdentity() {
|
||
const token = readRawParam("token");
|
||
if (!token) {
|
||
console.warn("Missing token for /app/h5/identity");
|
||
return null;
|
||
}
|
||
|
||
try {
|
||
const url = new URL("/app/h5/identity", `${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}`);
|
||
}
|
||
|
||
currentIdentity = data.body || data.data || {};
|
||
return currentIdentity;
|
||
} catch (error) {
|
||
console.error("Failed to load H5 identity:", error);
|
||
return null;
|
||
}
|
||
}
|
||
|
||
async function fetchAgencyProfile() {
|
||
const token = readRawParam("token");
|
||
if (!token) {
|
||
console.warn("Missing token for /team/team-own/profile");
|
||
renderAgencyProfile(null);
|
||
return null;
|
||
}
|
||
|
||
try {
|
||
const url = new URL("/team/team-own/profile", `${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}`);
|
||
}
|
||
|
||
currentAgencyProfile = data.body || data.data || null;
|
||
renderAgencyProfile(currentAgencyProfile);
|
||
return currentAgencyProfile;
|
||
} catch (error) {
|
||
console.error("Failed to load agency profile:", error);
|
||
renderAgencyProfile(null);
|
||
return null;
|
||
}
|
||
}
|
||
|
||
async function fetchTeamEntry() {
|
||
const token = readRawParam("token");
|
||
if (!token) {
|
||
console.warn("Missing token for /team/entry");
|
||
return "";
|
||
}
|
||
|
||
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}`);
|
||
}
|
||
|
||
currentTeamId = pickTeamEntryId(data.body || data.data || {});
|
||
renderAgencyProfile(currentAgencyProfile);
|
||
syncPolicyLink();
|
||
return currentTeamId;
|
||
} catch (error) {
|
||
console.error("Failed to load team entry:", error);
|
||
return "";
|
||
}
|
||
}
|
||
|
||
async function fetchBankBalance() {
|
||
const token = readRawParam("token");
|
||
if (!token) {
|
||
console.warn("Missing token for /wallet/bank/balance");
|
||
return;
|
||
}
|
||
|
||
try {
|
||
const url = new URL("/wallet/bank/balance", `${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}`);
|
||
}
|
||
|
||
renderCurrentSalary(pickCurrentSalary(data.body ?? data.data));
|
||
} catch (error) {
|
||
console.error("Failed to load bank balance:", error);
|
||
renderCurrentSalary(0);
|
||
}
|
||
}
|
||
|
||
async function fetchStreamingDuration(memberId) {
|
||
const memberWork = await fetchMemberWork(memberId);
|
||
renderMemberWorkSummary(memberWork);
|
||
return memberWork;
|
||
}
|
||
|
||
async function fetchMemberWork(memberId) {
|
||
if (!memberId) {
|
||
console.warn("Missing memberId for /team/member-work");
|
||
return null;
|
||
}
|
||
|
||
try {
|
||
const url = new URL("/team/member-work", `${apiBaseURL()}/`);
|
||
url.searchParams.set("userId", String(memberId));
|
||
const token = readRawParam("token");
|
||
if (!token) {
|
||
console.warn("Missing token for /team/member-work");
|
||
return null;
|
||
}
|
||
|
||
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 data.body || data.data || null;
|
||
} catch (error) {
|
||
console.error("Failed to load member work:", error);
|
||
return null;
|
||
}
|
||
}
|
||
|
||
function syncLocalizedLinks() {
|
||
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();
|
||
|
||
document.querySelectorAll('a[href^="../withdraw-exchange/index.html"]').forEach((link) => {
|
||
link.setAttribute("href", `../withdraw-exchange/index.html${query ? `?${query}` : ""}`);
|
||
});
|
||
}
|
||
|
||
function syncPolicyLink() {
|
||
const link = document.querySelector("#anchorPolicyLink");
|
||
if (!link) return;
|
||
|
||
const nextParams = new URLSearchParams(params);
|
||
const token = readRawParam("token");
|
||
const teamId = currentTeamId;
|
||
if (token) nextParams.set("token", token);
|
||
if (currentLang) nextParams.set("lang", currentLang);
|
||
if (teamId) nextParams.set("teamId", teamId);
|
||
|
||
const query = nextParams.toString();
|
||
link.setAttribute("href", `./policy.html${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.document_title || messages.title || "Stream Center";
|
||
renderMessages(messages);
|
||
renderLanguageControls(messages);
|
||
syncLocalizedLinks();
|
||
syncPolicyLink();
|
||
renderProfile(currentProfile, messages);
|
||
renderAgencyProfile(currentAgencyProfile, messages);
|
||
renderDailyTargets();
|
||
}
|
||
|
||
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);
|
||
});
|
||
|
||
document.querySelector(".back-button")?.addEventListener("click", () => {
|
||
if (window.history.length > 1) window.history.back();
|
||
});
|
||
|
||
document.querySelector(".agency")?.addEventListener("click", () => {
|
||
if (currentIdentity && shouldOpenJoinAgency(currentIdentity)) openJoinAgencyPage();
|
||
});
|
||
|
||
document.querySelector(".gift-value")?.addEventListener("click", () => {
|
||
setDailyModalOpen(true);
|
||
});
|
||
|
||
document.querySelectorAll("[data-close-daily]").forEach((node) => {
|
||
node.addEventListener("click", () => {
|
||
setDailyModalOpen(false);
|
||
});
|
||
});
|
||
|
||
document.addEventListener("keydown", (event) => {
|
||
if (event.key === "Escape") setDailyModalOpen(false);
|
||
});
|
||
|
||
ensureAvatarFallback("Oscar");
|
||
|
||
applyLanguage(currentLang).then(async () => {
|
||
const identity = await fetchIdentity();
|
||
if (shouldOpenJoinAgency(identity)) {
|
||
openJoinAgencyPage();
|
||
return;
|
||
}
|
||
|
||
fetchAgencyProfile();
|
||
fetchTeamEntry();
|
||
fetchUserProfile().then(async (profile) => {
|
||
const memberId = profile?.id || profile?.account;
|
||
if (memberId) {
|
||
await fetchStreamingDuration(memberId);
|
||
}
|
||
});
|
||
fetchBankBalance();
|
||
});
|
||
})();
|