(function () { const API_BASE_URL = "https://jvapi.haiyihy.com"; const GO_API_PATH_PREFIX = "/go"; const LOCAL_GO_API_BASE_URL = "http://127.0.0.1:1100"; const defaultPropsType = "RIDE"; const state = { manager: null, target: null, propsType: defaultPropsType, props: [], selectedPropsId: "" }; const params = readURLParams(); 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 $(selector) { return document.querySelector(selector); } function apiBaseURL() { const override = window.HYAPP_API_BASE_URL || params.get("apiBase"); if (override) return String(override).replace(/\/+$/, ""); return API_BASE_URL.replace(/\/+$/, ""); } function isLocalDocumentsFile() { if (window.location.protocol !== "file:") return false; let pathname = window.location.pathname || ""; try { pathname = decodeURIComponent(pathname); } catch (error) { return false; } return pathname.startsWith("/Users/hy/Documents/"); } function goApiBaseURL() { const override = window.HYAPP_GO_API_BASE_URL || params.get("goApiBase") || params.get("goBase"); if (override) return String(override).replace(/\/+$/, ""); if (isLocalDocumentsFile()) return `${LOCAL_GO_API_BASE_URL}${GO_API_PATH_PREFIX}`; return `${apiBaseURL()}${GO_API_PATH_PREFIX}`; } function buildRequestURL(baseURL, path) { const base = `${String(baseURL || API_BASE_URL).replace(/\/+$/, "")}/`; const target = String(path || "").replace(/^\/+/, ""); return new URL(target, base).toString(); } function normalizeAuthorization(token) { const value = String(token || "").trim(); if (!value) return ""; return /^bearer\s+/i.test(value) ? value : `Bearer ${value}`; } function authHeadersFromToken(token) { const sysOrigin = params.get("sysOrigin") || params.get("origin") || "ATYOU"; return { Authorization: normalizeAuthorization(token), "req-lang": params.get("lang") || "zh-CN", "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=${sysOrigin};originChild=${sysOrigin}` }; } async function requestGoJSON(path, options = {}) { const token = readRawParam("token"); if (!token) { const error = new Error("缺少登录信息"); error.code = "missing_token"; throw error; } const headers = authHeadersFromToken(token); const request = { method: options.method || "GET", cache: "no-store", headers }; if (options.body !== undefined) { headers["Content-Type"] = "application/json"; request.body = JSON.stringify(options.body); } const response = await fetch(buildRequestURL(goApiBaseURL(), path), request); 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.code = data.code || data.errorCodeName || ""; error.response = data; throw error; } return data.body ?? data.data ?? null; } function endpointProfile() { return "/app/h5/manager-center/profile"; } function endpointSearchUser(account) { return `/app/h5/manager-center/users/search?account=${encodeURIComponent(account)}`; } function endpointProps(type) { return `/app/h5/manager-center/props?type=${encodeURIComponent(type || "")}`; } function endpointSendProps() { return "/app/h5/manager-center/props/send"; } function endpointBanUser() { return "/app/h5/manager-center/users/ban"; } function setLoading(isLoading) { const root = $(".manager-center"); const mask = $("#loadingMask"); if (root) root.dataset.loading = isLoading ? "true" : "false"; if (mask) mask.hidden = !isLoading; } function setStatus(node, text, type = "") { if (!node) return; node.textContent = text || ""; node.hidden = !text; node.classList.toggle("is-error", type === "error"); } function showToast(text) { const toast = $("#toast"); if (!toast) return; toast.textContent = text || ""; toast.hidden = !text; window.clearTimeout(showToast.timer); showToast.timer = window.setTimeout(() => { toast.hidden = true; }, 2300); } function closePage() { try { 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"); return; } if (window.history.length > 1) window.history.back(); } catch (error) { console.error("close manager center failed:", error); if (window.history.length > 1) window.history.back(); } } function firstLetter(name, fallback) { const value = String(name || fallback || "U").trim(); return value ? value.slice(0, 1).toUpperCase() : "U"; } function renderAvatar(imgSelector, fallbackSelector, url, name, fallback) { const img = $(imgSelector); const fallbackNode = $(fallbackSelector); if (!img || !fallbackNode) return; const src = String(url || "").trim(); fallbackNode.textContent = firstLetter(name, fallback); if (src) { img.src = src; img.hidden = false; fallbackNode.hidden = true; } else { img.removeAttribute("src"); img.hidden = true; fallbackNode.hidden = false; } } function displayName(user) { return user?.userNickname || user?.nickname || user?.name || "-"; } function displayUserID(user) { return String(user?.userId || user?.id || "-"); } function displayAccount(user) { return user?.account ? ` (${user.account})` : ""; } function canBanTarget(target) { return Boolean(target) && target.canBan !== false && !target.hasRecharge; } function renderManager(manager) { $("#managerName").textContent = displayName(manager); $("#managerUid").textContent = `UID: ${displayUserID(manager)}${displayAccount(manager)}`; renderAvatar("#managerAvatar", "#managerAvatarFallback", manager?.userAvatar, displayName(manager), "M"); } function renderTarget() { const card = $("#targetCard"); const banCard = $("#banCard"); if (!state.target) { if (card) card.hidden = true; if (banCard) banCard.hidden = true; updateActionState(); return; } const target = state.target; card.hidden = false; banCard.hidden = false; $("#targetName").textContent = displayName(target); $("#targetUid").textContent = `UID: ${displayUserID(target)}${displayAccount(target)}`; $("#targetAccountStatus").textContent = target.accountStatus || "-"; const rechargeStatus = $("#targetRechargeStatus"); const canBan = canBanTarget(target); rechargeStatus.textContent = target.hasRecharge ? "已充值" : (canBan ? "未充值" : "充值状态未知"); rechargeStatus.classList.toggle("is-danger", Boolean(target.hasRecharge) || !canBan); const banEligibility = $("#banEligibility"); banEligibility.textContent = canBan ? "可封禁" : "不可封禁"; banEligibility.classList.toggle("is-danger", !canBan); renderAvatar("#targetAvatar", "#targetAvatarFallback", target.userAvatar, displayName(target), "U"); updateActionState(); } function renderProps() { const list = $("#propsList"); if (!list) return; list.replaceChildren(); if (!state.props.length) { setStatus($("#propsStatus"), "没有可赠送道具"); updateActionState(); return; } setStatus($("#propsStatus"), ""); state.props.forEach((item) => { const button = document.createElement("button"); button.type = "button"; button.className = "prop-option"; button.dataset.propsId = String(item.id); if (String(item.id) === String(state.selectedPropsId)) { button.classList.add("is-selected"); } const cover = document.createElement("span"); cover.className = "prop-cover"; if (item.cover || item.sourceUrl) { const img = document.createElement("img"); img.alt = ""; img.src = item.cover || item.sourceUrl; cover.appendChild(img); } else { const fallback = document.createElement("span"); fallback.textContent = firstLetter(item.name, "G"); cover.appendChild(fallback); } const copy = document.createElement("span"); copy.className = "prop-copy"; const name = document.createElement("span"); name.className = "prop-name"; name.textContent = item.name || `ID ${item.id}`; const meta = document.createElement("span"); meta.className = "prop-meta"; meta.textContent = item.vipLevel ? `${item.type} · VIP ${item.vipLevel}` : item.type; copy.append(name, meta); const days = document.createElement("span"); days.className = "prop-days"; days.textContent = `${item.days || 0}天`; button.append(cover, copy, days); button.addEventListener("click", () => { state.selectedPropsId = String(item.id); renderProps(); updateActionState(); }); list.appendChild(button); }); updateActionState(); } function updateActionState() { const sendButton = $("#sendPropsButton"); const banButton = $("#banButton"); if (sendButton) sendButton.disabled = !state.target || !state.selectedPropsId; if (banButton) banButton.disabled = !canBanTarget(state.target); } async function loadProfile() { const body = await requestGoJSON(endpointProfile()); state.manager = body?.manager || body || {}; renderManager(state.manager); } async function loadProps() { setStatus($("#propsStatus"), "加载中..."); state.props = []; state.selectedPropsId = ""; renderProps(); const body = await requestGoJSON(endpointProps(state.propsType)); state.props = Array.isArray(body?.records) ? body.records : []; state.selectedPropsId = state.props.length ? String(state.props[0].id) : ""; renderProps(); } async function searchUser(event) { event.preventDefault(); const input = $("#accountInput"); const account = String(input?.value || "").trim(); if (!account) { setStatus($("#searchStatus"), "请输入用户 ID 或账号", "error"); return; } $("#searchButton").disabled = true; setStatus($("#searchStatus"), "搜索中..."); try { const body = await requestGoJSON(endpointSearchUser(account)); state.target = body?.user || body || null; renderTarget(); setStatus($("#searchStatus"), ""); } catch (error) { state.target = null; renderTarget(); setStatus($("#searchStatus"), friendlyError(error), "error"); } finally { $("#searchButton").disabled = false; } } async function sendProps() { if (!state.target || !state.selectedPropsId) return; if (!window.confirm("确认赠送该道具?")) return; const button = $("#sendPropsButton"); button.disabled = true; try { await requestGoJSON(endpointSendProps(), { method: "POST", body: { acceptUserId: displayUserID(state.target), propsId: state.selectedPropsId } }); showToast("赠送成功"); } catch (error) { showToast(friendlyError(error)); } finally { updateActionState(); } } async function banUser() { if (!canBanTarget(state.target)) return; if (!window.confirm("确认封禁该用户?")) return; const button = $("#banButton"); button.disabled = true; setStatus($("#banStatus"), "提交中..."); try { await requestGoJSON(endpointBanUser(), { method: "POST", body: { userId: displayUserID(state.target), reason: $("#banReason").value || "" } }); state.target.accountStatus = "ARCHIVE"; renderTarget(); setStatus($("#banStatus"), ""); showToast("封禁成功"); } catch (error) { setStatus($("#banStatus"), friendlyError(error), "error"); } finally { updateActionState(); } } function friendlyError(error) { const code = error?.code || error?.response?.code || error?.response?.errorCodeName || ""; if (code === "missing_token") return "缺少登录信息"; if (code === "not_manager") return "当前账号不是经理"; if (code === "user_not_found") return "用户不存在"; if (code === "user_recharged") return "该用户已有充值记录,不能封禁"; if (code === "prop_not_giftable") return "该道具未开放经理赠送"; if (code === "vip_not_giftable") return "该贵族道具不可赠送"; return error?.message || "请求失败"; } function bindEvents() { $(".back-button")?.addEventListener("click", closePage); $("#searchForm")?.addEventListener("submit", searchUser); $("#propsTypeSelect")?.addEventListener("change", async (event) => { state.propsType = event.target.value || defaultPropsType; try { await loadProps(); } catch (error) { setStatus($("#propsStatus"), friendlyError(error), "error"); } }); $("#sendPropsButton")?.addEventListener("click", sendProps); $("#banButton")?.addEventListener("click", banUser); } async function init() { bindEvents(); $("#propsTypeSelect").value = state.propsType; if (!readRawParam("token")) { setLoading(false); setStatus($("#searchStatus"), "缺少登录信息", "error"); return; } try { await Promise.all([loadProfile(), loadProps()]); } catch (error) { showToast(friendlyError(error)); } finally { setLoading(false); } } init(); })();