diff --git a/h5/app-invite/app.js b/h5/app-invite/app.js
new file mode 100644
index 0000000..02397f2
--- /dev/null
+++ b/h5/app-invite/app.js
@@ -0,0 +1,794 @@
+const query = new URLSearchParams(window.location.search);
+
+const DEFAULT_INVITE_API_BASE = "https://jvapi.haiyihy.com/";
+const DEFAULT_AVATAR = "./assets/avatar-sample.png";
+const DEFAULT_TASK_NOTES = {
+ transport: "(Only the highest-level bonuses may be awarded)",
+ quota: "(You'll receive a reward upon reaching each level)",
+};
+
+const DEFAULTS = {
+ view: "invite",
+ inviteLink: "http://yourappbalbalanal",
+ inviteCode: "123455678",
+ invitees: "168",
+ eligibleVoters: "01",
+ rechargeTotal: "01",
+ myRewards: "12354",
+ friendName: "Name",
+ downloadUrl: "https://example.com/download",
+ endAt: "",
+ inviterBindReward: 2000,
+ rechargeReward: 1000,
+ giftReward: 1000,
+};
+
+const FALLBACK_TASKS = {
+ transport: [
+ {
+ title: "Milestone 1",
+ desc: "Total invitee recharge reaches 49,999 coins",
+ buttonLabel: "Incomplete",
+ disabled: true,
+ claimed: false,
+ achieved: false,
+ ruleId: 0,
+ },
+ {
+ title: "Milestone 2",
+ desc: "Total invitee recharge reaches 99,999 coins",
+ buttonLabel: "Incomplete",
+ disabled: true,
+ claimed: false,
+ achieved: false,
+ ruleId: 0,
+ },
+ {
+ title: "Milestone 3",
+ desc: "Total invitee recharge reaches 149,999 coins",
+ buttonLabel: "Incomplete",
+ disabled: true,
+ claimed: false,
+ achieved: false,
+ ruleId: 0,
+ },
+ ],
+ quota: [
+ {
+ title: "Milestone 1",
+ desc: "Invite 10 friends who have already made a payment",
+ buttonLabel: "Claim",
+ disabled: false,
+ claimed: false,
+ achieved: true,
+ ruleId: 0,
+ },
+ {
+ title: "Milestone 2",
+ desc: "Invite 20 friends who have already made a payment",
+ buttonLabel: "Incomplete",
+ disabled: true,
+ claimed: false,
+ achieved: false,
+ ruleId: 0,
+ },
+ {
+ title: "Milestone 3",
+ desc: "Invite 30 friends who have already made a payment",
+ buttonLabel: "Claim",
+ disabled: false,
+ claimed: false,
+ achieved: true,
+ ruleId: 0,
+ },
+ ],
+};
+
+const DEFAULT_RANKS = Array.from({ length: 30 }, (_, index) => ({
+ rank: index + 1,
+ name:
+ [
+ "hanneem",
+ "layan",
+ "amira",
+ "sami",
+ "noura",
+ "huda",
+ "rami",
+ "selim",
+ "mira",
+ "yael",
+ ][index % 10],
+ score: `${123 - Math.floor(index / 3)} people`,
+}));
+
+const state = {
+ view: normalizeView(query.get("view") || DEFAULTS.view),
+ apiBase: resolveAPIBase(),
+ authorization: resolveAuthorization(),
+ landingCode: trimValue(query.get("code") || query.get("inviteCode")),
+ inviteLink: query.get("inviteLink") || DEFAULTS.inviteLink,
+ inviteCode: query.get("inviteCode") || DEFAULTS.inviteCode,
+ invitees: query.get("invitees") || DEFAULTS.invitees,
+ eligibleVoters: query.get("eligible") || DEFAULTS.eligibleVoters,
+ rechargeTotal: query.get("recharge") || DEFAULTS.rechargeTotal,
+ myRewards: query.get("rewards") || DEFAULTS.myRewards,
+ friendName: query.get("friendName") || DEFAULTS.friendName,
+ inviterAvatar: DEFAULT_AVATAR,
+ downloadUrl: query.get("downloadUrl") || DEFAULTS.downloadUrl,
+ inviterBindReward: query.get("inviterReward") || DEFAULTS.inviterBindReward,
+ rechargeReward: query.get("rechargeReward") || DEFAULTS.rechargeReward,
+ giftReward: query.get("giftReward") || DEFAULTS.giftReward,
+ taskSet: normalizeTaskSet(query.get("taskSet") || "quota"),
+ tasks: {
+ transport: cloneTasks(FALLBACK_TASKS.transport),
+ quota: cloneTasks(FALLBACK_TASKS.quota),
+ },
+ countdownTimer: null,
+ pendingClaimRuleId: 0,
+};
+
+const els = {
+ views: [...document.querySelectorAll("[data-view]")],
+ inviteLinkText: document.getElementById("inviteLinkText"),
+ inviteCodeText: document.getElementById("inviteCodeText"),
+ statInvitees: document.getElementById("statInvitees"),
+ statEligible: document.getElementById("statEligible"),
+ statRecharge: document.getElementById("statRecharge"),
+ statRewards: document.getElementById("statRewards"),
+ taskList: document.getElementById("taskList"),
+ taskNote: document.getElementById("taskNote"),
+ taskTabs: [...document.querySelectorAll("[data-task-set]")],
+ navButtons: [...document.querySelectorAll("[data-nav-view]")],
+ copyButtons: [...document.querySelectorAll("[data-copy-target]")],
+ rankList: document.getElementById("rankList"),
+ giftTitle: document.getElementById("giftTitle"),
+ giftAvatarImage: document.getElementById("giftAvatarImage"),
+ downloadButton: document.getElementById("downloadButton"),
+ inviteRewardAmounts: [
+ ...document.querySelectorAll('.reward-panel .reward-amount'),
+ ],
+ giftRewardAmount: document.querySelector('.gift-panel .reward-amount'),
+ toast: document.getElementById("pageToast"),
+ countdown: {
+ days: document.querySelector('[data-countdown="days"]'),
+ hours: document.querySelector('[data-countdown="hours"]'),
+ minutes: document.querySelector('[data-countdown="minutes"]'),
+ seconds: document.querySelector('[data-countdown="seconds"]'),
+ },
+};
+
+function normalizeView(value) {
+ if (value === "rank" || value === "gift") {
+ return value;
+ }
+
+ return "invite";
+}
+
+function normalizeTaskSet(value) {
+ return value === "transport" ? "transport" : "quota";
+}
+
+function trimValue(value) {
+ return value == null ? "" : String(value).trim();
+}
+
+function normalizeBaseURL(base) {
+ const value = trimValue(base);
+ if (!value) {
+ return DEFAULT_INVITE_API_BASE;
+ }
+
+ return value.endsWith("/") ? value : `${value}/`;
+}
+
+function resolveAPIBase() {
+ const queryBase = trimValue(query.get("apiBase"));
+ if (queryBase) {
+ return normalizeBaseURL(queryBase);
+ }
+
+ if (typeof window.__APP_INVITE_API_BASE__ === "string") {
+ return normalizeBaseURL(window.__APP_INVITE_API_BASE__);
+ }
+
+ return normalizeBaseURL(DEFAULT_INVITE_API_BASE);
+}
+
+function resolveAuthorization() {
+ const candidates = [
+ query.get("authorization"),
+ query.get("Authorization"),
+ query.get("token"),
+ query.get("auth"),
+ typeof window.__APP_INVITE_AUTHORIZATION__ === "string"
+ ? window.__APP_INVITE_AUTHORIZATION__
+ : "",
+ typeof window.__APP_INVITE_TOKEN__ === "string" ? window.__APP_INVITE_TOKEN__ : "",
+ ];
+
+ const value = candidates.find((item) => trimValue(item));
+ if (!value) {
+ return "";
+ }
+
+ const normalized = trimValue(value);
+ if (/^bearer\s+/i.test(normalized)) {
+ return normalized;
+ }
+
+ return `Bearer ${normalized}`;
+}
+
+function escapeHtml(value) {
+ return String(value).replace(/[&<>"']/g, (match) => {
+ const entityMap = {
+ "&": "&",
+ "<": "<",
+ ">": ">",
+ '"': """,
+ "'": "'",
+ };
+ return entityMap[match] || match;
+ });
+}
+
+function cloneTasks(list) {
+ return list.map((item) => ({ ...item }));
+}
+
+function showToast(text) {
+ if (!text) {
+ return;
+ }
+
+ els.toast.textContent = text;
+ els.toast.classList.add("show");
+
+ window.clearTimeout(showToast.timer);
+ showToast.timer = window.setTimeout(() => {
+ els.toast.classList.remove("show");
+ }, 1800);
+}
+
+function loadImage(image) {
+ if (!image || image.getAttribute("src")) {
+ return;
+ }
+
+ const src = image.getAttribute("data-src");
+ if (src) {
+ image.setAttribute("src", src);
+ }
+}
+
+function setImageSource(image, src, fallbackSrc = "") {
+ if (!(image instanceof HTMLImageElement)) {
+ return;
+ }
+
+ const nextSrc = trimValue(src) || fallbackSrc;
+ if (!nextSrc) {
+ return;
+ }
+
+ image.setAttribute("src", nextSrc);
+ image.setAttribute("data-src", nextSrc);
+}
+
+function hydrateViewAssets(view) {
+ const targets = {
+ invite: [
+ document.getElementById("inviteHeroImage"),
+ ...document.querySelectorAll('.view[data-view="invite"] .lazy-image'),
+ ],
+ rank: [
+ ...document.querySelectorAll('.view[data-view="rank"] [data-badge-src]'),
+ ...document.querySelectorAll('.view[data-view="rank"] [data-avatar-src]'),
+ ],
+ gift: [
+ document.getElementById("giftBgImage"),
+ document.getElementById("giftAvatarImage"),
+ document.getElementById("phoneHomeImage"),
+ document.getElementById("phoneGiftImage"),
+ ...document.querySelectorAll('.view[data-view="gift"] .lazy-image'),
+ ],
+ };
+
+ (targets[view] || []).forEach((item) => {
+ if (item instanceof HTMLImageElement) {
+ loadImage(item);
+ }
+ });
+}
+
+function setView(view) {
+ state.view = normalizeView(view);
+ els.views.forEach((section) => {
+ section.classList.toggle("active", section.getAttribute("data-view") === state.view);
+ });
+
+ hydrateViewAssets(state.view);
+
+ const url = new URL(window.location.href);
+ if (state.view === DEFAULTS.view) {
+ url.searchParams.delete("view");
+ } else {
+ url.searchParams.set("view", state.view);
+ }
+ window.history.replaceState({}, "", url.toString());
+}
+
+function formatMetric(value) {
+ const raw = trimValue(value);
+ if (!raw) {
+ return "--";
+ }
+
+ if (/^-?\d+(\.\d+)?$/.test(raw)) {
+ return new Intl.NumberFormat("en-US").format(Number(raw));
+ }
+
+ return raw;
+}
+
+function formatSignedReward(value) {
+ const raw = trimValue(value);
+ if (!raw) {
+ return "+0";
+ }
+
+ if (raw.startsWith("+")) {
+ return raw;
+ }
+
+ return `+${formatMetric(raw)}`;
+}
+
+function renderStats() {
+ els.inviteLinkText.textContent = trimValue(state.inviteLink) || "--";
+ els.inviteCodeText.textContent = trimValue(state.inviteCode) || "--";
+ els.statInvitees.textContent = formatMetric(state.invitees);
+ els.statEligible.textContent = formatMetric(state.eligibleVoters);
+ els.statRecharge.textContent = formatMetric(state.rechargeTotal);
+ els.statRewards.textContent = formatMetric(state.myRewards);
+ els.giftTitle.innerHTML = `Your friend [${escapeHtml(state.friendName)}]
has invited you to join`;
+ setImageSource(els.giftAvatarImage, state.inviterAvatar, DEFAULT_AVATAR);
+
+ if (els.inviteRewardAmounts[0]) {
+ els.inviteRewardAmounts[0].textContent = formatSignedReward(state.inviterBindReward);
+ }
+ if (els.inviteRewardAmounts[1]) {
+ els.inviteRewardAmounts[1].textContent = formatSignedReward(state.rechargeReward);
+ }
+ if (els.giftRewardAmount) {
+ els.giftRewardAmount.textContent = formatSignedReward(state.giftReward);
+ }
+}
+
+function renderTasks() {
+ const current = state.tasks[state.taskSet] || cloneTasks(FALLBACK_TASKS[state.taskSet]);
+ els.taskTabs.forEach((tab) => {
+ const active = tab.getAttribute("data-task-set") === state.taskSet;
+ tab.classList.toggle("active", active);
+ tab.classList.toggle("passive", !active);
+ });
+
+ els.taskList.innerHTML = current
+ .map((item) => {
+ const isLoading = Number(item.ruleId) > 0 && state.pendingClaimRuleId === Number(item.ruleId);
+ const disabled = item.disabled || isLoading || Number(item.ruleId) <= 0;
+ const buttonLabel = isLoading ? "Loading..." : item.buttonLabel;
+ let buttonStateClass = " is-pending";
+
+ if (isLoading) {
+ buttonStateClass = " is-loading";
+ } else if (item.claimed) {
+ buttonStateClass = " is-claimed";
+ } else if (item.achieved && !item.claimed) {
+ buttonStateClass = " is-claimable";
+ }
+
+ return `
+
+
+
${escapeHtml(item.title)}
+
${escapeHtml(item.desc)}
+
+
+
+ `;
+ })
+ .join("");
+ els.taskNote.textContent = DEFAULT_TASK_NOTES[state.taskSet] || "";
+}
+
+function renderRankList() {
+ els.rankList.innerHTML = DEFAULT_RANKS.map((item) => {
+ const badgeMap = {
+ 1: "./assets/rank-top1.png",
+ 2: "./assets/rank-top2.png",
+ 3: "./assets/rank-top3.png",
+ };
+
+ const badge = badgeMap[item.rank];
+ return `
+
+
+ ${
+ badge
+ ? `

`
+ : escapeHtml(String(item.rank))
+ }
+
+
+

+
+ ${escapeHtml(item.name)}
+ ${escapeHtml(item.score)}
+
+ `;
+ }).join("");
+}
+
+function parseEndAt() {
+ const raw = query.get("endAt") || DEFAULTS.endAt;
+ if (!raw) {
+ return null;
+ }
+
+ const timestamp = Date.parse(raw);
+ if (Number.isNaN(timestamp)) {
+ return null;
+ }
+
+ return timestamp;
+}
+
+function pad(number) {
+ return String(number).padStart(2, "0");
+}
+
+function updateCountdown() {
+ const endAt = parseEndAt();
+ if (!endAt) {
+ return;
+ }
+
+ const diff = Math.max(0, endAt - Date.now());
+ const seconds = Math.floor(diff / 1000);
+ const days = Math.floor(seconds / 86400);
+ const hours = Math.floor((seconds % 86400) / 3600);
+ const minutes = Math.floor((seconds % 3600) / 60);
+ const secs = seconds % 60;
+
+ els.countdown.days.textContent = pad(days);
+ els.countdown.hours.textContent = pad(hours);
+ els.countdown.minutes.textContent = pad(minutes);
+ els.countdown.seconds.textContent = pad(secs);
+}
+
+function setupCountdown() {
+ const endAt = parseEndAt();
+ if (!endAt) {
+ return;
+ }
+
+ updateCountdown();
+ state.countdownTimer = window.setInterval(updateCountdown, 1000);
+}
+
+async function copyText(text) {
+ if (navigator.clipboard?.writeText) {
+ await navigator.clipboard.writeText(text);
+ return;
+ }
+
+ const input = document.createElement("textarea");
+ input.value = text;
+ input.setAttribute("readonly", "");
+ input.style.position = "absolute";
+ input.style.left = "-9999px";
+ document.body.appendChild(input);
+ input.select();
+ document.execCommand("copy");
+ document.body.removeChild(input);
+}
+
+function extractErrorMessage(payload) {
+ const candidates = [
+ payload?.errorMsg,
+ payload?.message,
+ payload?.errorCodeName,
+ payload?.code,
+ ];
+
+ return candidates.find((item) => trimValue(item)) || "";
+}
+
+async function requestJSON(path, options = {}) {
+ const { method = "GET", headers = {}, body, searchParams } = options;
+ const url = new URL(path, state.apiBase);
+
+ Object.entries(searchParams || {}).forEach(([key, value]) => {
+ const raw = trimValue(value);
+ if (raw) {
+ url.searchParams.set(key, raw);
+ }
+ });
+
+ const response = await fetch(url.toString(), {
+ method,
+ headers: {
+ Accept: "application/json",
+ ...headers,
+ },
+ body,
+ });
+
+ const contentType = response.headers.get("content-type") || "";
+ const payload = contentType.includes("application/json") ? await response.json() : null;
+
+ if (!response.ok || payload?.status === false) {
+ const message = extractErrorMessage(payload) || `Request failed (${response.status})`;
+ throw new Error(message);
+ }
+
+ return payload?.body || payload?.data || payload || null;
+}
+
+function normalizeTaskList(list, taskSet) {
+ if (!Array.isArray(list) || list.length === 0) {
+ return cloneTasks(FALLBACK_TASKS[taskSet]);
+ }
+
+ return list.map((item, index) => {
+ const threshold = Number(item?.threshold || 0);
+ const goldAmount = Number(item?.goldAmount || 0);
+ const achieved = Boolean(item?.achieved);
+ const claimed = Boolean(item?.claimed);
+ const desc =
+ taskSet === "quota"
+ ? `Invite ${formatMetric(threshold)} valid friends to claim ${formatMetric(goldAmount)} coins`
+ : `Reach ${formatMetric(threshold)} recharge coins to claim ${formatMetric(goldAmount)} coins`;
+
+ return {
+ title: `Milestone ${index + 1}`,
+ desc,
+ buttonLabel: claimed ? "Claimed" : achieved ? "Claim" : "Incomplete",
+ disabled: claimed || !achieved,
+ claimed,
+ achieved,
+ ruleId: Number(item?.ruleId) || 0,
+ };
+ });
+}
+
+function markTaskClaimed(ruleId) {
+ ["quota", "transport"].forEach((taskSet) => {
+ state.tasks[taskSet] = (state.tasks[taskSet] || []).map((item) => {
+ if (Number(item.ruleId) !== Number(ruleId)) {
+ return item;
+ }
+
+ return {
+ ...item,
+ claimed: true,
+ disabled: true,
+ buttonLabel: "Claimed",
+ };
+ });
+ });
+}
+
+function applyHomeData(body) {
+ if (!body || typeof body !== "object") {
+ return;
+ }
+
+ const stats = body.stats || {};
+ state.inviteLink = trimValue(body.inviteLink) || state.inviteLink;
+ state.inviteCode = trimValue(body.inviteCode) || state.inviteCode;
+ state.downloadUrl = trimValue(body.downloadUrl) || state.downloadUrl;
+ state.invitees = stats.totalInvitedUsers ?? state.invitees;
+ state.eligibleVoters = stats.totalValidUsers ?? state.eligibleVoters;
+ state.rechargeTotal = stats.totalRechargeCoins ?? state.rechargeTotal;
+ state.myRewards = stats.rewardGoldCoins ?? state.myRewards;
+
+ const inviterBindReward = body.inviterBindReward?.goldAmount;
+ if (inviterBindReward != null) {
+ state.inviterBindReward = inviterBindReward;
+ }
+
+ const rechargeReward =
+ body.inviterTotalRechargeTasks?.[0]?.goldAmount ??
+ body.inviteeRechargeRules?.[0]?.goldAmount;
+ if (rechargeReward != null) {
+ state.rechargeReward = rechargeReward;
+ }
+
+ state.tasks.quota = normalizeTaskList(body.inviterValidCountTasks, "quota");
+ state.tasks.transport = normalizeTaskList(body.inviterTotalRechargeTasks, "transport");
+
+ const shareTitle = trimValue(body.shareTitle);
+ if (shareTitle) {
+ document.title = shareTitle;
+ }
+}
+
+function applyLandingData(body) {
+ if (!body || typeof body !== "object") {
+ return;
+ }
+
+ state.friendName = trimValue(body.inviterNickname) || state.friendName;
+ state.inviterAvatar = trimValue(body.inviterAvatar) || DEFAULT_AVATAR;
+ state.downloadUrl = trimValue(body.downloadUrl) || state.downloadUrl;
+ state.giftReward = body.inviteeReward?.goldAmount ?? state.giftReward;
+
+ const inviteCode = trimValue(body.inviteCode);
+ if (inviteCode) {
+ state.landingCode = inviteCode;
+ }
+
+ const shareTitle = trimValue(body.shareTitle);
+ if (shareTitle) {
+ document.title = shareTitle;
+ }
+}
+
+async function fetchHomeData() {
+ if (!state.authorization) {
+ return false;
+ }
+
+ const body = await requestJSON("/go/app/h5/invite-campaign/home", {
+ headers: {
+ Authorization: state.authorization,
+ },
+ });
+ applyHomeData(body);
+ return true;
+}
+
+async function fetchLandingData() {
+ if (!state.landingCode) {
+ return false;
+ }
+
+ const body = await requestJSON("/go/public/h5/invite-campaign/landing", {
+ searchParams: {
+ code: state.landingCode,
+ },
+ });
+ applyLandingData(body);
+ return true;
+}
+
+async function refreshPageData() {
+ try {
+ if (state.view === "gift") {
+ await fetchLandingData();
+ } else {
+ await fetchHomeData();
+ }
+ } catch (error) {
+ const message = trimValue(error?.message);
+ if (message) {
+ showToast(message);
+ }
+ } finally {
+ renderStats();
+ renderTasks();
+ }
+}
+
+async function claimTask(ruleId) {
+ if (!ruleId) {
+ return;
+ }
+
+ if (!state.authorization) {
+ showToast("Token is missing");
+ return;
+ }
+
+ state.pendingClaimRuleId = ruleId;
+ renderTasks();
+
+ try {
+ const body = await requestJSON("/go/app/h5/invite-campaign/tasks/claim", {
+ method: "POST",
+ headers: {
+ Authorization: state.authorization,
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({ ruleId }),
+ });
+
+ markTaskClaimed(ruleId);
+ showToast(body?.alreadyClaimed ? "Already claimed" : "Claim succeeded");
+ await fetchHomeData().catch(() => {});
+ } catch (error) {
+ showToast(trimValue(error?.message) || "Claim failed");
+ } finally {
+ state.pendingClaimRuleId = 0;
+ renderStats();
+ renderTasks();
+ }
+}
+
+function bindEvents() {
+ els.taskTabs.forEach((button) => {
+ button.addEventListener("click", () => {
+ state.taskSet = normalizeTaskSet(button.getAttribute("data-task-set"));
+ renderTasks();
+ });
+ });
+
+ els.navButtons.forEach((button) => {
+ button.addEventListener("click", () => {
+ setView(button.getAttribute("data-nav-view") || "invite");
+ });
+ });
+
+ els.copyButtons.forEach((button) => {
+ button.addEventListener("click", async () => {
+ const target = button.getAttribute("data-copy-target");
+ const value = target === "invite-code" ? state.inviteCode : state.inviteLink;
+
+ try {
+ await copyText(trimValue(value));
+ showToast(target === "invite-code" ? "Invitation code copied" : "Invitation link copied");
+ } catch (error) {
+ showToast("Copy failed");
+ }
+ });
+ });
+
+ els.taskList.addEventListener("click", (event) => {
+ const button = event.target.closest("[data-rule-id]");
+ if (!(button instanceof HTMLButtonElement)) {
+ return;
+ }
+
+ const ruleId = Number(button.getAttribute("data-rule-id") || 0);
+ if (!ruleId || button.disabled) {
+ return;
+ }
+
+ claimTask(ruleId);
+ });
+
+ els.downloadButton.addEventListener("click", () => {
+ if (!state.downloadUrl) {
+ showToast("Download link is not configured");
+ return;
+ }
+
+ window.location.href = state.downloadUrl;
+ });
+}
+
+async function init() {
+ renderStats();
+ renderTasks();
+ renderRankList();
+ bindEvents();
+ setView(state.view);
+ setupCountdown();
+ await refreshPageData();
+}
+
+init();
diff --git a/h5/app-invite/assets/avatar-sample.png b/h5/app-invite/assets/avatar-sample.png
new file mode 100644
index 0000000..6d0410b
Binary files /dev/null and b/h5/app-invite/assets/avatar-sample.png differ
diff --git a/h5/app-invite/assets/button-active-bg.png b/h5/app-invite/assets/button-active-bg.png
new file mode 100644
index 0000000..07ac42a
Binary files /dev/null and b/h5/app-invite/assets/button-active-bg.png differ
diff --git a/h5/app-invite/assets/button-inactive-bg.png b/h5/app-invite/assets/button-inactive-bg.png
new file mode 100644
index 0000000..b5bb466
Binary files /dev/null and b/h5/app-invite/assets/button-inactive-bg.png differ
diff --git a/h5/app-invite/assets/claim-active-art.png b/h5/app-invite/assets/claim-active-art.png
new file mode 100644
index 0000000..e90fa13
Binary files /dev/null and b/h5/app-invite/assets/claim-active-art.png differ
diff --git a/h5/app-invite/assets/claim-active-core.png b/h5/app-invite/assets/claim-active-core.png
new file mode 100644
index 0000000..409dd50
Binary files /dev/null and b/h5/app-invite/assets/claim-active-core.png differ
diff --git a/h5/app-invite/assets/claim-active-mask.svg b/h5/app-invite/assets/claim-active-mask.svg
new file mode 100644
index 0000000..9250ace
--- /dev/null
+++ b/h5/app-invite/assets/claim-active-mask.svg
@@ -0,0 +1,3 @@
+
diff --git a/h5/app-invite/assets/claim-active.png b/h5/app-invite/assets/claim-active.png
new file mode 100644
index 0000000..d34e8bb
Binary files /dev/null and b/h5/app-invite/assets/claim-active.png differ
diff --git a/h5/app-invite/assets/claim-inactive.png b/h5/app-invite/assets/claim-inactive.png
new file mode 100644
index 0000000..d34e8bb
Binary files /dev/null and b/h5/app-invite/assets/claim-inactive.png differ
diff --git a/h5/app-invite/assets/copy-button.png b/h5/app-invite/assets/copy-button.png
new file mode 100644
index 0000000..55bb4db
Binary files /dev/null and b/h5/app-invite/assets/copy-button.png differ
diff --git a/h5/app-invite/assets/copy-core.png b/h5/app-invite/assets/copy-core.png
new file mode 100644
index 0000000..409dd50
Binary files /dev/null and b/h5/app-invite/assets/copy-core.png differ
diff --git a/h5/app-invite/assets/copy-mask.svg b/h5/app-invite/assets/copy-mask.svg
new file mode 100644
index 0000000..a94f823
--- /dev/null
+++ b/h5/app-invite/assets/copy-mask.svg
@@ -0,0 +1,21 @@
+
diff --git a/h5/app-invite/assets/gift-bg.png b/h5/app-invite/assets/gift-bg.png
new file mode 100644
index 0000000..55386de
Binary files /dev/null and b/h5/app-invite/assets/gift-bg.png differ
diff --git a/h5/app-invite/assets/gift-cta-core.png b/h5/app-invite/assets/gift-cta-core.png
new file mode 100644
index 0000000..409dd50
Binary files /dev/null and b/h5/app-invite/assets/gift-cta-core.png differ
diff --git a/h5/app-invite/assets/gift-cta-mask.svg b/h5/app-invite/assets/gift-cta-mask.svg
new file mode 100644
index 0000000..c1da41a
--- /dev/null
+++ b/h5/app-invite/assets/gift-cta-mask.svg
@@ -0,0 +1,21 @@
+
diff --git a/h5/app-invite/assets/gift-cta.png b/h5/app-invite/assets/gift-cta.png
new file mode 100644
index 0000000..0adfc8c
Binary files /dev/null and b/h5/app-invite/assets/gift-cta.png differ
diff --git a/h5/app-invite/assets/hero-title-combined.png b/h5/app-invite/assets/hero-title-combined.png
new file mode 100644
index 0000000..e7c6474
Binary files /dev/null and b/h5/app-invite/assets/hero-title-combined.png differ
diff --git a/h5/app-invite/assets/hero-title-full.png b/h5/app-invite/assets/hero-title-full.png
new file mode 100644
index 0000000..fcce241
Binary files /dev/null and b/h5/app-invite/assets/hero-title-full.png differ
diff --git a/h5/app-invite/assets/hero-title-top-shift4.png b/h5/app-invite/assets/hero-title-top-shift4.png
new file mode 100644
index 0000000..5e37547
Binary files /dev/null and b/h5/app-invite/assets/hero-title-top-shift4.png differ
diff --git a/h5/app-invite/assets/hero-title-top.png b/h5/app-invite/assets/hero-title-top.png
new file mode 100644
index 0000000..fccbdaf
Binary files /dev/null and b/h5/app-invite/assets/hero-title-top.png differ
diff --git a/h5/app-invite/assets/invite-hero-bg.png b/h5/app-invite/assets/invite-hero-bg.png
new file mode 100644
index 0000000..55386de
Binary files /dev/null and b/h5/app-invite/assets/invite-hero-bg.png differ
diff --git a/h5/app-invite/assets/monthly-tasks-button.png b/h5/app-invite/assets/monthly-tasks-button.png
new file mode 100644
index 0000000..5dca0c8
Binary files /dev/null and b/h5/app-invite/assets/monthly-tasks-button.png differ
diff --git a/h5/app-invite/assets/panel-bottom.png b/h5/app-invite/assets/panel-bottom.png
new file mode 100644
index 0000000..1ed2000
Binary files /dev/null and b/h5/app-invite/assets/panel-bottom.png differ
diff --git a/h5/app-invite/assets/panel-middle.png b/h5/app-invite/assets/panel-middle.png
new file mode 100644
index 0000000..c3f9e50
Binary files /dev/null and b/h5/app-invite/assets/panel-middle.png differ
diff --git a/h5/app-invite/assets/panel-top.png b/h5/app-invite/assets/panel-top.png
new file mode 100644
index 0000000..3444635
Binary files /dev/null and b/h5/app-invite/assets/panel-top.png differ
diff --git a/h5/app-invite/assets/phone-gift.png b/h5/app-invite/assets/phone-gift.png
new file mode 100644
index 0000000..7e621a9
Binary files /dev/null and b/h5/app-invite/assets/phone-gift.png differ
diff --git a/h5/app-invite/assets/phone-home.png b/h5/app-invite/assets/phone-home.png
new file mode 100644
index 0000000..bbb7523
Binary files /dev/null and b/h5/app-invite/assets/phone-home.png differ
diff --git a/h5/app-invite/assets/rank-button.png b/h5/app-invite/assets/rank-button.png
new file mode 100644
index 0000000..6a19075
Binary files /dev/null and b/h5/app-invite/assets/rank-button.png differ
diff --git a/h5/app-invite/assets/rank-row.svg b/h5/app-invite/assets/rank-row.svg
new file mode 100644
index 0000000..c77d5be
--- /dev/null
+++ b/h5/app-invite/assets/rank-row.svg
@@ -0,0 +1,3 @@
+
diff --git a/h5/app-invite/assets/rank-title-button.png b/h5/app-invite/assets/rank-title-button.png
new file mode 100644
index 0000000..14ea6bd
Binary files /dev/null and b/h5/app-invite/assets/rank-title-button.png differ
diff --git a/h5/app-invite/assets/rank-top1.png b/h5/app-invite/assets/rank-top1.png
new file mode 100644
index 0000000..df7b345
Binary files /dev/null and b/h5/app-invite/assets/rank-top1.png differ
diff --git a/h5/app-invite/assets/rank-top2.png b/h5/app-invite/assets/rank-top2.png
new file mode 100644
index 0000000..67ad74d
Binary files /dev/null and b/h5/app-invite/assets/rank-top2.png differ
diff --git a/h5/app-invite/assets/rank-top3.png b/h5/app-invite/assets/rank-top3.png
new file mode 100644
index 0000000..5ee50f6
Binary files /dev/null and b/h5/app-invite/assets/rank-top3.png differ
diff --git a/h5/app-invite/assets/reward-bag.png b/h5/app-invite/assets/reward-bag.png
new file mode 100644
index 0000000..44e5294
Binary files /dev/null and b/h5/app-invite/assets/reward-bag.png differ
diff --git a/h5/app-invite/assets/tab-active-core.png b/h5/app-invite/assets/tab-active-core.png
new file mode 100644
index 0000000..409dd50
Binary files /dev/null and b/h5/app-invite/assets/tab-active-core.png differ
diff --git a/h5/app-invite/assets/tab-active-mask.png b/h5/app-invite/assets/tab-active-mask.png
new file mode 100644
index 0000000..dcf6876
--- /dev/null
+++ b/h5/app-invite/assets/tab-active-mask.png
@@ -0,0 +1,3 @@
+
diff --git a/h5/app-invite/assets/tab-inactive-core.png b/h5/app-invite/assets/tab-inactive-core.png
new file mode 100644
index 0000000..dcf6876
--- /dev/null
+++ b/h5/app-invite/assets/tab-inactive-core.png
@@ -0,0 +1,3 @@
+
diff --git a/h5/app-invite/assets/tab-quota-active.png b/h5/app-invite/assets/tab-quota-active.png
new file mode 100644
index 0000000..8b48731
Binary files /dev/null and b/h5/app-invite/assets/tab-quota-active.png differ
diff --git a/h5/app-invite/assets/tab-quota-inactive.png b/h5/app-invite/assets/tab-quota-inactive.png
new file mode 100644
index 0000000..9983733
Binary files /dev/null and b/h5/app-invite/assets/tab-quota-inactive.png differ
diff --git a/h5/app-invite/assets/tab-transport-active.png b/h5/app-invite/assets/tab-transport-active.png
new file mode 100644
index 0000000..0634916
Binary files /dev/null and b/h5/app-invite/assets/tab-transport-active.png differ
diff --git a/h5/app-invite/assets/tab-transport-inactive.png b/h5/app-invite/assets/tab-transport-inactive.png
new file mode 100644
index 0000000..a4f0d2f
Binary files /dev/null and b/h5/app-invite/assets/tab-transport-inactive.png differ
diff --git a/h5/app-invite/assets/task-row-bg.svg b/h5/app-invite/assets/task-row-bg.svg
new file mode 100644
index 0000000..4e0391e
--- /dev/null
+++ b/h5/app-invite/assets/task-row-bg.svg
@@ -0,0 +1,3 @@
+
diff --git a/h5/app-invite/assets/title-image.png b/h5/app-invite/assets/title-image.png
new file mode 100644
index 0000000..707104a
Binary files /dev/null and b/h5/app-invite/assets/title-image.png differ
diff --git a/h5/app-invite/assets/title-top-core.png b/h5/app-invite/assets/title-top-core.png
new file mode 100644
index 0000000..a85badf
Binary files /dev/null and b/h5/app-invite/assets/title-top-core.png differ
diff --git a/h5/app-invite/assets/title-top-mask.svg b/h5/app-invite/assets/title-top-mask.svg
new file mode 100644
index 0000000..8383326
--- /dev/null
+++ b/h5/app-invite/assets/title-top-mask.svg
@@ -0,0 +1,3 @@
+
diff --git a/h5/app-invite/assets/任务标题背景按钮.png b/h5/app-invite/assets/任务标题背景按钮.png
new file mode 100644
index 0000000..7ca5fa2
Binary files /dev/null and b/h5/app-invite/assets/任务标题背景按钮.png differ
diff --git a/h5/app-invite/assets/按钮未选中.png b/h5/app-invite/assets/按钮未选中.png
new file mode 100644
index 0000000..efde023
Binary files /dev/null and b/h5/app-invite/assets/按钮未选中.png differ
diff --git a/h5/app-invite/assets/按钮选中.png b/h5/app-invite/assets/按钮选中.png
new file mode 100644
index 0000000..3bcd7c1
Binary files /dev/null and b/h5/app-invite/assets/按钮选中.png differ
diff --git a/h5/app-invite/dev-test-server.mjs b/h5/app-invite/dev-test-server.mjs
new file mode 100644
index 0000000..af776a5
--- /dev/null
+++ b/h5/app-invite/dev-test-server.mjs
@@ -0,0 +1,96 @@
+import { createServer } from "node:http";
+import { createReadStream, statSync } from "node:fs";
+import { extname, join, normalize } from "node:path";
+import { fileURLToPath } from "node:url";
+
+const rootDir = fileURLToPath(new URL(".", import.meta.url));
+const port = Number(process.env.INVITE_TEST_PORT || 65248);
+const apiTarget = String(process.env.INVITE_API_TARGET || "http://127.0.0.1:2900").replace(/\/$/, "");
+
+const mimeTypes = {
+ ".html": "text/html; charset=utf-8",
+ ".js": "text/javascript; charset=utf-8",
+ ".css": "text/css; charset=utf-8",
+ ".json": "application/json; charset=utf-8",
+ ".png": "image/png",
+ ".jpg": "image/jpeg",
+ ".jpeg": "image/jpeg",
+ ".svg": "image/svg+xml",
+};
+
+function sendText(response, status, text) {
+ response.writeHead(status, { "content-type": "text/plain; charset=utf-8" });
+ response.end(text);
+}
+
+function serveStatic(request, response) {
+ const requestPath = new URL(request.url, "http://localhost").pathname;
+ const pathname = requestPath === "/" ? "/dev-test.html" : requestPath;
+ const filePath = normalize(join(rootDir, pathname));
+ if (!filePath.startsWith(rootDir)) {
+ sendText(response, 403, "Forbidden");
+ return;
+ }
+
+ try {
+ const stat = statSync(filePath);
+ if (!stat.isFile()) {
+ sendText(response, 404, "Not found");
+ return;
+ }
+ response.writeHead(200, {
+ "content-type": mimeTypes[extname(filePath)] || "application/octet-stream",
+ "content-length": stat.size,
+ });
+ createReadStream(filePath).pipe(response);
+ } catch {
+ sendText(response, 404, "Not found");
+ }
+}
+
+async function proxyAPI(request, response) {
+ const incomingURL = new URL(request.url, "http://localhost");
+ const targetURL = new URL(incomingURL.pathname.replace(/^\/api/, "") + incomingURL.search, apiTarget);
+ const headers = new Headers();
+ for (const [key, value] of Object.entries(request.headers)) {
+ if (value !== undefined && key.toLowerCase() !== "host") {
+ headers.set(key, Array.isArray(value) ? value.join(",") : value);
+ }
+ }
+
+ try {
+ const upstream = await fetch(targetURL, {
+ method: request.method,
+ headers,
+ body: request.method === "GET" || request.method === "HEAD" ? undefined : request,
+ duplex: "half",
+ });
+ response.writeHead(upstream.status, {
+ "content-type": upstream.headers.get("content-type") || "application/octet-stream",
+ });
+ if (upstream.body) {
+ for await (const chunk of upstream.body) {
+ response.write(chunk);
+ }
+ }
+ response.end();
+ } catch (error) {
+ response.writeHead(502, { "content-type": "application/json; charset=utf-8" });
+ response.end(JSON.stringify({
+ status: false,
+ code: "proxy_error",
+ message: error instanceof Error ? error.message : "proxy error",
+ }));
+ }
+}
+
+createServer((request, response) => {
+ if (request.url?.startsWith("/api/") || request.url === "/api") {
+ proxyAPI(request, response);
+ return;
+ }
+ serveStatic(request, response);
+}).listen(port, "127.0.0.1", () => {
+ console.log(`Invite dev test page: http://127.0.0.1:${port}/dev-test.html`);
+ console.log(`Proxy target: ${apiTarget}`);
+});
diff --git a/h5/app-invite/dev-test.html b/h5/app-invite/dev-test.html
new file mode 100644
index 0000000..d78ba8b
--- /dev/null
+++ b/h5/app-invite/dev-test.html
@@ -0,0 +1,799 @@
+
+
+
+
+
+ 邀请活动本地接口测试
+
+
+
+
+
+
+
邀请活动本地接口测试
+
+ 默认通过本页同源的 /api 代理到本地 Go 服务,避免浏览器 CORS 限制。
+
+
+
等待操作
+
+
+
+
+
+
+
+
流程操作
+
+
+
+
+
+
+
+
+
+
+ 推荐顺序:填邀请人 token -> 查首页 -> 填被邀请人 token 和 userId -> 绑码 -> 充值回调 -> 刷新 -> 点任务 Claim。
+
+
+
+
+
首页结果
+
+
+
+
月度倒计时未加载
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/h5/app-invite/index.html b/h5/app-invite/index.html
new file mode 100644
index 0000000..c06f98d
--- /dev/null
+++ b/h5/app-invite/index.html
@@ -0,0 +1,1033 @@
+
+
+
+
+
+ App Invite
+
+
+
+
+
+
+
+
+
![Invite friends Make money]()
+
+
+
+
+
+
+
+
Your Reward
+
(Earn for every friend you invite)
+
+
+ +2000
+
+
![Invitation reward]()
+
+ Invitation received
+
+
+
+
+ +1000
+
+
![Recharge reward]()
+
+ Top up via friends
+
+
+
+
+
+
Start inviting people now
+
(Copy your invitation link and share it with your friends)
+
+
+
+ Invitation link:
+
+
+
+
+
+
+ Invitation code:
+
+
+
+
+
+
+
+
+
+
+
168
+
Total number of invitees
+
+
+
01
+
Number of eligible voters
+
+
+
01
+
Total amount recharged by invitees
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
![Invite gift background]()
+
+
+
+
![Inviter avatar]()
+
+
+
Join him to receive an exclusive welcome gift
+
+
+
Your Personal Gift
+
(This is a special gift from your friend)
+
+ +1000
+
+
![Personal gift]()
+
+
+
+ (Available only through this invitation link! Don't miss out!)
+
+
+
+
+
+
![App home preview]()
+
+
+
![Gift preview]()
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/h5/assets/loading-ranking.gif b/h5/assets/loading-ranking.gif
new file mode 100644
index 0000000..e1656fd
Binary files /dev/null and b/h5/assets/loading-ranking.gif differ
diff --git a/h5/assets/yumi-ranking/Ranking/Overall/bgCharm.png b/h5/assets/yumi-ranking/Ranking/Overall/bgCharm.png
index 0b7a8cc..afc2828 100644
Binary files a/h5/assets/yumi-ranking/Ranking/Overall/bgCharm.png and b/h5/assets/yumi-ranking/Ranking/Overall/bgCharm.png differ
diff --git a/h5/assets/yumi-ranking/Ranking/Overall/bgRoom.png b/h5/assets/yumi-ranking/Ranking/Overall/bgRoom.png
index 52cbe41..afc2828 100644
Binary files a/h5/assets/yumi-ranking/Ranking/Overall/bgRoom.png and b/h5/assets/yumi-ranking/Ranking/Overall/bgRoom.png differ
diff --git a/h5/assets/yumi-ranking/Ranking/Overall/bgWealth.png b/h5/assets/yumi-ranking/Ranking/Overall/bgWealth.png
index 0114a72..afc2828 100644
Binary files a/h5/assets/yumi-ranking/Ranking/Overall/bgWealth.png and b/h5/assets/yumi-ranking/Ranking/Overall/bgWealth.png differ
diff --git a/h5/js/Ranking-xafVKSSF-1776148658686.js b/h5/js/Ranking-xafVKSSF-1776148658686.js
index a59d965..19ea82b 100644
--- a/h5/js/Ranking-xafVKSSF-1776148658686.js
+++ b/h5/js/Ranking-xafVKSSF-1776148658686.js
@@ -1 +1 @@
-import{L as H,_ as ce,w as be,j as A,c as O,b as e,D as b,n as h,q as s,Q as U,t as c,v as X,S as _,an as ve,k as Ae,r as n,a$ as _e,o as Te,i as xe,Y as J,l as C,ac as Ie,ay as ie,F as Re,x as Ce,G as ne,m as re,J as Be,X as se,b0 as Oe,a_ as Se}from"./index-CIAVq8iD-1776148658686.js";import{_ as K}from"./coin-Dqu2_ND9-1776148658686.js";import{c as Ue}from"./appConnector-B5Pbaops-1776148658686.js";import{p as Fe}from"./imagePreloader-C_QM-Nv8-1776148658686.js";import{g as Ee}from"./imagePaths-Bi1Bwe4Z-1776148658686.js";import{h as B}from"./imageHandler-DstQGL3Z-1776148658686.js";import{B as ue}from"./BackgroundLayer-DJYogygx-1776148658686.js";import{i as de}from"./itemCenter-DveKthYv-1776148658686.js";const De="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAYAAABV7bNHAAAACXBIWXMAACE4AAAhOAFFljFgAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAADxSURBVHgB7dvBDYJAFEXRHyuhBEuzA+3EWAmlUIJ2MDJCNATy5m1I1H9PwoZhww3Mgh8iAAAAAACllG48joGlOUxfPoZ6LvCOM5S1PrITcV4is1acuhY7O8SXmveX+gp14rJbZGQ8OdUlMiKOQByBOAJxBOIIxBGIIxBHII5AHIE4AnEE4gjEEYgjEKeBOMJ488d/irPHN+lHYz33JKIqywHflnNkZm7SRCJSA5EMRDIQyUAkA5EMRDIQyUAkA5EMRDIQyUAkA5EMRDIQyWBGOkVmRqR7ZNeKFJCRroHJRqS+8DvUWpkGk10AAAAAwO96AiOznp1YXpZWAAAAAElFTkSuQmCC",Me=async()=>{try{return await H("/activity/leaderboard/gifts-send")}catch(i){throw console.error("Failed to fetch get wealth ranking:",i),console.error("error:"+i.response.errorMsg),i}},We=async()=>{try{return await H("/activity/leaderboard/gifts-received")}catch(i){throw console.error("Failed to fetch get charm ranking:",i),console.error("error:"+i.response.errorMsg),i}},$e=async()=>{try{return await H("/activity/leaderboard/room-gifts")}catch(i){throw console.error("Failed to fetch get room ranking:",i),console.error("error:"+i.response.errorMsg),i}},je=async(i,a)=>{try{return await H(`/activity/leaderboard/my-rank?type=${i}&dateType=${a}`)}catch(v){throw console.error("Failed to fetch get my ranking:",v),console.error("error:"+v.response.errorMsg),v}},He={style:{width:"100%"}},Ve=["src"],ze=["src"],Ge={style:{position:"absolute",bottom:"0",left:"0",right:"0","z-index":"3",display:"flex","flex-direction":"column","justify-content":"flex-end","align-items":"center",gap:"1vw"}},Ne={style:{display:"flex","justify-content":"center","align-items":"center",gap:"2px",padding:"3px 5px"}},Pe={src:K,alt:"",style:{display:"block",width:"1.3em","object-fit":"cover"}},qe={__name:"topUser",props:{Type:{type:Boolean,default:""},isTopOne:{type:Boolean,default:!1},avatarUrl:{type:String,default:"/src/assets/icon/Atu/defaultAvatar.png"},BorderImgUrl:{type:String,required:!0},name:{type:String,default:""},distributionValue:{type:String,default:""}},setup(i){const a=i;be(()=>a.Type,(d,g)=>{console.log("Type 变化 =>","新值:",d,"旧值:",g)});const v=_(()=>{if(a.Type=="Wealth")return a.isTopOne?"76.5vw":"44vw";if(a.Type=="Charm")return a.isTopOne?"80vw":"44vw";if(a.Type=="Room")return a.isTopOne?"76vw":"52vw"}),Z=_(()=>{if(a.Type=="Wealth")return a.isTopOne?"height:110%":"height:72%";if(a.Type=="Charm")return a.isTopOne?"height:98%":"height:74%";if(a.Type=="Room")return a.isTopOne?"height:110%":"height:80%"}),o=_(()=>{if(a.Type=="Wealth")return a.isTopOne?"31%":"45%";if(a.Type=="Charm")return a.isTopOne?"30%":"45%";if(a.Type=="Room")return a.isTopOne?"30%":"50%"}),F=_(()=>{if(a.Type=="Wealth")return a.isTopOne?"height: 8vw;width: 30%;":"height: 5vw;width: 50%;";if(a.Type=="Charm")return a.isTopOne?"height: 10vw;width: 40%;":"height: 5vw;width: 40%;";if(a.Type=="Room")return a.isTopOne?"height: 7vw;width: 28%;":"height: 4.5vw;width: 40%;"}),r=_(()=>{if(a.Type=="Wealth")return a.isTopOne?"30%":"50%";if(a.Type=="Charm")return a.isTopOne?"35%":"50%";if(a.Type=="Room")return a.isTopOne?"30%":"50%"});return(d,g)=>{const f=ve("smart-img");return A(),O("div",He,[e("div",{style:h([{position:"relative"},{minHeight:v.value}])},[b((A(),O("img",{src:i.BorderImgUrl,key:i.BorderImgUrl,alt:"",width:"100%",style:{display:"block",position:"relative","z-index":"2"}},null,8,Ve)),[[f]]),e("div",{style:h([{position:"absolute",top:"0",left:"0",right:"0","z-index":"1",display:"flex","justify-content":"center","align-items":"center"},Z.value])},[e("div",{style:h({width:o.value})},[e("img",{src:i.avatarUrl||"",alt:"",width:"100%",style:{display:"block","aspect-ratio":"1/1","border-radius":"50%","object-fit":"cover"},onError:g[0]||(g[0]=(...p)=>s(B)&&s(B)(...p))},null,40,ze)],4)],4),e("div",Ge,[e("div",{style:h([{display:"flex","justify-content":"center","align-items":"center"},F.value])},[e("div",{style:{"font-weight":"860"},class:U(["showText",i.isTopOne?"top1Text":"text"])},c(i.name),3)],4),i.distributionValue?(A(),O("div",{key:0,style:h([{position:"relative","border-radius":"80px",border:"1px solid #ffdf36",background:"linear-gradient(270deg, #000 0%, #3b3b3b 47.45%, #000 100%)","box-shadow":"0 0 4px 0 rgba(0, 0, 0, 0.4) inset"},{width:r.value}])},[e("div",Ne,[b(e("img",Pe,null,512),[[f]]),e("div",{style:{"font-weight":"700",background:"linear-gradient(180deg, #ffe656 0%, #fff 100%)","background-clip":"text","-webkit-background-clip":"text","-webkit-text-fill-color":"transparent"},class:U(["showText",i.isTopOne?"top1Text":"text"])},c(i.distributionValue),3)])],4)):X("",!0)])],4)])}}},Q=ce(qe,[["__scopeId","data-v-7e43213b"]]),Le={class:"loading-container"},Ye={style:{position:"relative","z-index":"4"}},Je={style:{padding:"4px 8%"}},Qe={style:{display:"flex","justify-content":"space-around",position:"relative"}},Xe={style:{margin:"1vw 6vw 4vw",padding:"4px","border-radius":"32px",border:"1px solid #b2a67d",background:"linear-gradient(90deg, #0d0d0d 0%, #232323 100%)","backdrop-filter":"blur(32px)",display:"grid","grid-template-columns":"repeat(3, 1fr)"}},Ke={style:{}},Ze={style:{margin:"0 10px"}},et={style:{display:"flex","justify-content":"center"}},tt={style:{display:"flex","justify-content":"space-between","margin-top":"0"}},at={style:{padding:"3vw 3vw 0",display:"flex","flex-direction":"column",gap:"2vw"}},lt={style:{flex:"1","min-width":"0","align-self":"stretch",display:"flex","justify-content":"space-around","align-items":"center",gap:"8px"}},ot={style:{width:"auto","min-width":"0","align-self":"stretch",display:"flex","justify-content":"center","align-items":"center"}},it={style:{"font-weight":"700"}},nt=["src"],rt={style:{flex:"1","min-width":"0",padding:"0 4px","font-weight":"700",overflow:"hidden","white-space":"nowrap","text-overflow":"ellipsis"}},st={style:{width:"auto","min-width":"0","align-self":"stretch",display:"flex","align-items":"center"}},ut={src:K,alt:"",style:{display:"block",width:"1.3em","aspect-ratio":"1/1"}},dt={style:{"font-weight":"500",color:"rgba(248, 182, 45, 1)"}},ct={key:0,style:{height:"26vw"}},vt={style:{flex:"1","min-width":"0","align-self":"stretch",display:"flex","justify-content":"space-around","align-items":"center",gap:"8px"}},gt={style:{width:"auto","min-width":"0","align-self":"stretch",display:"flex","justify-content":"center","align-items":"center"}},pt={style:{"font-weight":"700"}},yt=["src"],mt={style:{flex:"1","min-width":"0","font-weight":"700",padding:"0 4px",overflow:"hidden","white-space":"nowrap","text-overflow":"ellipsis"}},ht={style:{width:"auto","min-width":"0","align-self":"stretch",display:"flex","align-items":"center"}},ft={src:K,alt:"",style:{display:"block",width:"1.3em","aspect-ratio":"1/1"}},kt={style:{"font-weight":"500",color:"rgba(248, 182, 45, 1)"}},wt={__name:"Ranking",setup(i){const a=Be(),{t:v,locale:Z}=Ae(),o=t=>Ee("Ranking/Overall/",t),F=n(!1),r=n(a.query.first||"Wealth"),d=n("Daily"),g=n("GIFTS_SEND"),f=n("DAY"),p=n({}),y=n([]),k=n({}),S=n(!0),V=n(null),x=n(!0),T=n(10),ee=_(()=>r.value=="Wealth"?o("bgWealth"):r.value=="Charm"?o("bgCharm"):r.value=="Room"?o("bgRoom"):""),ge=async()=>{const t=[o("bgWealth"),o("bgCharm"),o("bgRoom"),o("top1-wealth"),o("top1-charm"),o("top1-room"),o("top2"),o("top3"),o("top2-room"),o("top3-room")];await Fe(t)},te=()=>{console.log("updateTimeRanking()//筛选展示榜单"),d.value=="Hourly"&&p.value.hourly?(y.value=p.value.hourly,console.log("showRanking.value:",y.value)):d.value=="Daily"&&p.value.daily?y.value=p.value.daily:d.value=="Weekly"&&p.value.weekly?y.value=p.value.weekly:d.value=="Monthly"&&p.value.monthly&&(y.value=p.value.monthly),T.value=10,x.value=!0},z=se(t=>{r.value!=t&&(console.log("改变rankingType"),r.value=t,d.value="Daily",f.value="DAY",t=="Wealth"?g.value="GIFTS_SEND":t=="Charm"?g.value="GIFTS_RECEIVED":t=="Room"&&(g.value="ROOM_GIFTS"),p.value={},y.value=[],k.value={},T.value=10,x.value=!0,le(),Y())},1e3),G=se(t=>{d.value!=t&&(console.log("改变rankingType"),d.value=t,t=="Hourly"?f.value="HOUR":t=="Daily"?f.value="DAY":t=="Weekly"?f.value="WEEK":t=="Monthly"&&(f.value="MONTH"),y.value=[],k.value={},te(),Y())},500),m=_(()=>{console.log("刷新RankingTop3");let t=[...y.value];if(y.value.length<3){let l=Array.from({length:3-y.value.length},()=>({avatar:"",nickname:"",quantityFormat:""}));t.push(...l)}return t}),pe=_(()=>y.value.filter((l,w)=>w>=3).slice(0,T.value)),ye=n(""),N=n(""),P=n(""),I=n(""),q=n(""),L=n(""),E=n(""),D=n(""),M=n(""),ae=n(null),W=n(null);_e(()=>{r.value=="Wealth"&&(E.value=o("top1-wealth"),D.value=o("top2"),M.value=o("top3"),I.value=o("tabSelectedBg"),N.value="1px solid rgba(221, 114, 0, 0.39)",P.value="rgba(252, 194, 147, 0.20)",q.value="linear-gradient(97deg, rgba(50, 34, 21, 0.60) 12.03%, rgba(99, 52, 33, 0.60) 100.37%)",L.value="solid #FFA166",g.value="GIFTS_SEND"),r.value=="Charm"&&(E.value=o("top1-charm"),D.value=o("top2"),M.value=o("top3"),I.value=o("tabSelectedBg"),N.value="1px solid rgba(0, 221, 74, 0.39)",P.value="rgba(147, 252, 166, 0.20)",q.value="linear-gradient(97deg, rgba(21, 50, 22, 0.60) 12.03%, rgba(33, 99, 40, 0.60) 100.37%)",L.value="solid #66FF82",g.value="GIFTS_RECEIVED"),r.value=="Room"&&(E.value=o("top1-room"),D.value=o("top2-room"),M.value=o("top3-room"),I.value=o("tabSelectedBg"),N.value="1px solid rgba(155, 0, 221, 0.39)",P.value="rgba(219, 147, 252, 0.20)",q.value="linear-gradient(97deg, rgba(33, 21, 50, 0.60) 12.03%, rgba(60, 33, 99, 0.60) 100.37%)",L.value="solid #A366FF",g.value="ROOM_GIFTS")});const me=new IntersectionObserver(t=>{t.forEach(l=>{l.isIntersecting?W.value.classList.remove("stuck"):(console.log("哨兵元素离开视口"),W.value?(W.value.classList.add("stuck"),console.log("添加stuck类")):console.log("元素未找到!"))})}),he=new IntersectionObserver(t=>{t.forEach(l=>{if(l.isIntersecting&&x.value){console.log("触发上拉加载更多");const w=y.value.filter((u,j)=>j>=3).length,R=T.value;R=w&&(x.value=!1,console.log("没有更多数据了"))):(x.value=!1,console.log("没有更多数据了"))}})},{rootMargin:"100px"}),$=t=>{F.value&&(r.value=="Room"?Oe(t):Se(t))},le=async()=>{console.log("获取榜单");let t={};r.value=="Wealth"?t=await Me():r.value=="Charm"?t=await We():r.value=="Room"&&(t=await $e()),t.status&&t.body&&(p.value=t.body,te())},Y=async()=>{console.log("获取我的排名");const t=await je(g.value,f.value);t.status&&t.body?k.value=t.body:k.value={}},fe=async()=>{await Promise.all([le(),Y()])},ke=async()=>{try{await Promise.all([fe(),ge()])}catch(t){console.error("预加载过程中发生错误:",t)}finally{S.value=!1}},we=async()=>{await Ue(()=>{ke()})};return Te(()=>{we(),F.value=xe(),me.observe(ae.value),V.value&&he.observe(V.value)}),(t,l)=>{const w=Ie,R=ve("smart-img");return A(),O("div",{class:"fullPage",style:h({backgroundColor:ye.value})},[b(e("div",Le,[C(ue,{backgroundImages:[ee.value]},null,8,["backgroundImages"]),C(w),e("p",null,c(t.$t("loading"))+"...",1)],512),[[J,S.value]]),b(e("div",Ye,[C(ue,{backgroundImages:[ee.value],layerStyle:{zIndex:-1}},null,8,["backgroundImages"]),e("div",{ref_key:"sentinel",ref:ae},null,512),e("div",{ref_key:"stickyHeader",ref:W,style:{position:"sticky",top:"0","z-index":"999","border-radius":"0 0 12px 12px",transition:"all 0.3s",height:"35vw"}},[l[12]||(l[12]=e("div",{style:{height:"13vw"}},null,-1)),e("div",Je,[e("div",Qe,[e("div",{class:"tab",onClick:l[0]||(l[0]=u=>s(z)("Wealth")),style:h([{},{color:r.value=="Wealth"?"#FF9500":"#fff"}])},c(s(v)("ranking_wealth")),5),e("div",{class:"tab",onClick:l[1]||(l[1]=u=>s(z)("Charm")),style:h([{},{color:r.value=="Charm"?"#FF9500":"#fff"}])},c(s(v)("ranking_charm")),5),e("div",{class:"tab",onClick:l[2]||(l[2]=u=>s(z)("Room")),style:h([{},{color:r.value=="Room"?"#FF9500":"#fff"}])},c(s(v)("ranking_room")),5),b(e("img",{src:De,alt:"",style:{position:"absolute",left:"-4%",top:"45%",transform:"translateY(-50%)"},width:"6%",onClick:l[3]||(l[3]=(...u)=>s(ie)&&s(ie)(...u))},null,512),[[R]])])]),e("div",Xe,[e("div",{class:"tabItem",style:h(d.value=="Daily"?{backgroundImage:`url(${I.value})`,backgroundSize:"100% 100%",backgroundRepeat:"no-repeat",backgroundPosition:"center"}:{})},[e("div",{class:U(["tag",{tagActive:d.value=="Daily"}]),onClick:l[4]||(l[4]=u=>s(G)("Daily"))},c(s(v)("ranking_daily")),3)],4),e("div",{class:"tabItem",style:h(d.value=="Weekly"?{backgroundImage:`url(${I.value})`,backgroundSize:"100% 100%",backgroundRepeat:"no-repeat",backgroundPosition:"center"}:{})},[e("div",{class:U(["tag",{tagActive:d.value=="Weekly"}]),onClick:l[5]||(l[5]=u=>s(G)("Weekly"))},c(s(v)("ranking_weekly")),3)],4),e("div",{class:"tabItem",style:h(d.value=="Monthly"?{backgroundImage:`url(${I.value})`,backgroundSize:"100% 100%",backgroundRepeat:"no-repeat",backgroundPosition:"center"}:{})},[e("div",{class:U(["tag",{tagActive:d.value=="Monthly"}]),onClick:l[6]||(l[6]=u=>s(G)("Monthly"))},c(s(v)("ranking_monthly")),3)],4)])],512),e("div",Ke,[e("div",Ze,[e("div",et,[C(Q,{Type:r.value,isTopOne:!0,BorderImgUrl:E.value,avatarUrl:m.value[0].avatar||"",name:m.value[0].nickname||"",distributionValue:m.value[0].quantityFormat||"",style:{width:"85%"},onClick:l[7]||(l[7]=u=>$(m.value[0].id))},null,8,["Type","BorderImgUrl","avatarUrl","name","distributionValue"])]),e("div",tt,[C(Q,{Type:r.value,BorderImgUrl:D.value,avatarUrl:m.value[1].avatar||"",name:m.value[1].nickname||"",distributionValue:m.value[1].quantityFormat||"",style:{width:"43%"},onClick:l[8]||(l[8]=u=>$(m.value[1].id))},null,8,["Type","BorderImgUrl","avatarUrl","name","distributionValue"]),C(Q,{Type:r.value,BorderImgUrl:M.value,avatarUrl:m.value[2].avatar||"",name:m.value[2].nickname||"",distributionValue:m.value[2].quantityFormat||"",style:{width:"43%"},onClick:l[9]||(l[9]=u=>$(m.value[2].id))},null,8,["Type","BorderImgUrl","avatarUrl","name","distributionValue"])])]),e("div",at,[(A(!0),O(Re,null,Ce(pe.value,(u,j)=>(A(),ne(de,{style:{"min-height":"19vw"},key:u.id,imgUrl:o("RankingItem"),contentStyle:"padding: 3vw;justify-content: space-between;gap: 8px;",lazy:!0,immediate:j<10,onClick:oe=>$(u.id)},{default:re(()=>[e("div",lt,[e("div",ot,[e("div",it,c(j+4),1)]),e("img",{src:u.avatar||"",alt:"",style:{display:"block",width:"3em","aspect-ratio":"1/1","border-radius":"50%","object-fit":"cover"},onError:l[10]||(l[10]=(...oe)=>s(B)&&s(B)(...oe))},null,40,nt),e("div",rt,c(u.nickname),1)]),e("div",st,[b(e("img",ut,null,512),[[R]]),e("div",dt,c(u.quantityFormat),1)])]),_:2},1032,["imgUrl","immediate","onClick"]))),128)),b(e("div",{ref_key:"RankingLoadmore",ref:V},null,512),[[J,x.value]])])])],512),[[J,!S.value]]),S.value?X("",!0):(A(),O("div",ct)),S.value?X("",!0):(A(),ne(de,{key:1,style:{"min-height":"25vw",position:"fixed",bottom:"0","z-index":"999",padding:"0 1px"},imgUrl:o("myRankingBg"),contentStyle:"padding:4vw 4vw 0;justify-content: space-between;gap: 8px;"},{default:re(()=>[e("div",vt,[e("div",gt,[e("div",pt,c(k.value.rank||999),1)]),e("img",{src:k.value.avatar||"",alt:"",style:{display:"block",width:"3em","aspect-ratio":"1/1","border-radius":"50%","object-fit":"cover"},onError:l[11]||(l[11]=(...u)=>s(B)&&s(B)(...u))},null,40,yt),e("div",mt,c(k.value.nickname||""),1)]),e("div",ht,[b(e("img",ft,null,512),[[R]]),e("div",kt,c(k.value.quantityFormat||0),1)])]),_:1},8,["imgUrl"]))],4)}}},St=ce(wt,[["__scopeId","data-v-93c53aed"]]);export{St as default};
+import{L as H,_ as ce,w as be,j as A,c as O,b as e,D as b,n as h,q as s,Q as U,t as c,v as X,S as _,an as ve,k as Ae,r as n,a$ as _e,o as Te,i as xe,Y as J,l as C,ac as Ie,ay as ie,F as Re,x as Ce,G as ne,m as re,J as Be,X as se,b0 as Oe,a_ as Se}from"./index-CIAVq8iD-1776148658686.js";import{_ as K}from"./coin-Dqu2_ND9-1776148658686.js";import{c as Ue}from"./appConnector-B5Pbaops-1776148658686.js";import{p as Fe}from"./imagePreloader-C_QM-Nv8-1776148658686.js";import{g as Ee}from"./imagePaths-Bi1Bwe4Z-1776148658686.js";import{h as B}from"./imageHandler-DstQGL3Z-1776148658686.js";import{B as ue}from"./BackgroundLayer-DJYogygx-1776148658686.js";import{i as de}from"./itemCenter-DveKthYv-1776148658686.js";const De="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAYAAABV7bNHAAAACXBIWXMAACE4AAAhOAFFljFgAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAADxSURBVHgB7dvBDYJAFEXRHyuhBEuzA+3EWAmlUIJ2MDJCNATy5m1I1H9PwoZhww3Mgh8iAAAAAACllG48joGlOUxfPoZ6LvCOM5S1PrITcV4is1acuhY7O8SXmveX+gp14rJbZGQ8OdUlMiKOQByBOAJxBOIIxBGIIxBHII5AHIE4AnEE4gjEEYgjEKeBOMJ488d/irPHN+lHYz33JKIqywHflnNkZm7SRCJSA5EMRDIQyUAkA5EMRDIQyUAkA5EMRDIQyUAkA5EMRDIQyWBGOkVmRqR7ZNeKFJCRroHJRqS+8DvUWpkGk10AAAAAwO96AiOznp1YXpZWAAAAAElFTkSuQmCC",Me=async()=>{try{return await H("/activity/leaderboard/gifts-send")}catch(i){throw console.error("Failed to fetch get wealth ranking:",i),console.error("error:"+i.response.errorMsg),i}},We=async()=>{try{return await H("/activity/leaderboard/gifts-received")}catch(i){throw console.error("Failed to fetch get charm ranking:",i),console.error("error:"+i.response.errorMsg),i}},$e=async()=>{try{return await H("/activity/leaderboard/room-gifts")}catch(i){throw console.error("Failed to fetch get room ranking:",i),console.error("error:"+i.response.errorMsg),i}},je=async(i,a)=>{try{return await H(`/activity/leaderboard/my-rank?type=${i}&dateType=${a}`)}catch(v){throw console.error("Failed to fetch get my ranking:",v),console.error("error:"+v.response.errorMsg),v}},He={style:{width:"100%"}},Ve=["src"],ze=["src"],Ge={style:{position:"absolute",bottom:"0",left:"0",right:"0","z-index":"3",display:"flex","flex-direction":"column","justify-content":"flex-end","align-items":"center",gap:"1vw"}},Ne={style:{display:"flex","justify-content":"center","align-items":"center",gap:"2px",padding:"3px 5px"}},Pe={src:K,alt:"",style:{display:"block",width:"1.3em","object-fit":"cover"}},qe={__name:"topUser",props:{Type:{type:Boolean,default:""},isTopOne:{type:Boolean,default:!1},avatarUrl:{type:String,default:"/src/assets/icon/Atu/defaultAvatar.png"},BorderImgUrl:{type:String,required:!0},name:{type:String,default:""},distributionValue:{type:String,default:""}},setup(i){const a=i;be(()=>a.Type,(d,g)=>{console.log("Type 变化 =>","新值:",d,"旧值:",g)});const v=_(()=>{if(a.Type=="Wealth")return a.isTopOne?"76.5vw":"44vw";if(a.Type=="Charm")return a.isTopOne?"80vw":"44vw";if(a.Type=="Room")return a.isTopOne?"76vw":"52vw"}),Z=_(()=>{if(a.Type=="Wealth")return a.isTopOne?"height:110%":"height:72%";if(a.Type=="Charm")return a.isTopOne?"height:98%":"height:74%";if(a.Type=="Room")return a.isTopOne?"height:110%":"height:80%"}),o=_(()=>{if(a.Type=="Wealth")return a.isTopOne?"31%":"45%";if(a.Type=="Charm")return a.isTopOne?"30%":"45%";if(a.Type=="Room")return a.isTopOne?"30%":"50%"}),F=_(()=>{if(a.Type=="Wealth")return a.isTopOne?"height: 8vw;width: 30%;":"height: 5vw;width: 50%;";if(a.Type=="Charm")return a.isTopOne?"height: 10vw;width: 40%;":"height: 5vw;width: 40%;";if(a.Type=="Room")return a.isTopOne?"height: 7vw;width: 28%;":"height: 4.5vw;width: 40%;"}),r=_(()=>{if(a.Type=="Wealth")return a.isTopOne?"30%":"50%";if(a.Type=="Charm")return a.isTopOne?"35%":"50%";if(a.Type=="Room")return a.isTopOne?"30%":"50%"});return(d,g)=>{const f=ve("smart-img");return A(),O("div",He,[e("div",{style:h([{position:"relative"},{minHeight:v.value}])},[b((A(),O("img",{src:i.BorderImgUrl,key:i.BorderImgUrl,alt:"",width:"100%",style:{display:"block",position:"relative","z-index":"2"}},null,8,Ve)),[[f]]),e("div",{style:h([{position:"absolute",top:"0",left:"0",right:"0","z-index":"1",display:"flex","justify-content":"center","align-items":"center"},Z.value])},[e("div",{style:h({width:o.value})},[e("img",{src:i.avatarUrl||"",alt:"",width:"100%",style:{display:"block","aspect-ratio":"1/1","border-radius":"50%","object-fit":"cover"},onError:g[0]||(g[0]=(...p)=>s(B)&&s(B)(...p))},null,40,ze)],4)],4),e("div",Ge,[e("div",{style:h([{display:"flex","justify-content":"center","align-items":"center"},F.value])},[e("div",{style:{"font-weight":"860"},class:U(["showText",i.isTopOne?"top1Text":"text"])},c(i.name),3)],4),i.distributionValue?(A(),O("div",{key:0,style:h([{position:"relative","border-radius":"80px",border:"1px solid #ffdf36",background:"linear-gradient(270deg, #000 0%, #3b3b3b 47.45%, #000 100%)","box-shadow":"0 0 4px 0 rgba(0, 0, 0, 0.4) inset"},{width:r.value}])},[e("div",Ne,[b(e("img",Pe,null,512),[[f]]),e("div",{style:{"font-weight":"700",background:"linear-gradient(180deg, #ffe656 0%, #fff 100%)","background-clip":"text","-webkit-background-clip":"text","-webkit-text-fill-color":"transparent"},class:U(["showText",i.isTopOne?"top1Text":"text"])},c(i.distributionValue),3)])],4)):X("",!0)])],4)])}}},Q=ce(qe,[["__scopeId","data-v-7e43213b"]]),Le={class:"loading-container"},Ye={style:{position:"relative","z-index":"4"}},Je={style:{padding:"4px 8%"}},Qe={style:{display:"flex","justify-content":"space-around",position:"relative"}},Xe={style:{margin:"1vw 6vw 4vw",padding:"4px","border-radius":"32px",border:"1px solid #b2a67d",background:"linear-gradient(90deg, #0d0d0d 0%, #232323 100%)","backdrop-filter":"blur(32px)",display:"grid","grid-template-columns":"repeat(3, 1fr)"}},Ke={style:{}},Ze={style:{margin:"0 10px"}},et={style:{display:"flex","justify-content":"center"}},tt={style:{display:"flex","justify-content":"space-between","margin-top":"0"}},at={style:{padding:"3vw 3vw 0",display:"flex","flex-direction":"column",gap:"2vw"}},lt={style:{flex:"1","min-width":"0","align-self":"stretch",display:"flex","justify-content":"space-around","align-items":"center",gap:"8px"}},ot={style:{width:"auto","min-width":"0","align-self":"stretch",display:"flex","justify-content":"center","align-items":"center"}},it={style:{"font-weight":"700"}},nt=["src"],rt={style:{flex:"1","min-width":"0",padding:"0 4px","font-weight":"700",overflow:"hidden","white-space":"nowrap","text-overflow":"ellipsis"}},st={style:{width:"auto","min-width":"0","align-self":"stretch",display:"flex","align-items":"center"}},ut={src:K,alt:"",style:{display:"block",width:"1.3em","aspect-ratio":"1/1"}},dt={style:{"font-weight":"500",color:"rgba(248, 182, 45, 1)"}},ct={key:0,style:{height:"26vw"}},vt={style:{flex:"1","min-width":"0","align-self":"stretch",display:"flex","justify-content":"space-around","align-items":"center",gap:"8px"}},gt={style:{width:"auto","min-width":"0","align-self":"stretch",display:"flex","justify-content":"center","align-items":"center"}},pt={style:{"font-weight":"700"}},yt=["src"],mt={style:{flex:"1","min-width":"0","font-weight":"700",padding:"0 4px",overflow:"hidden","white-space":"nowrap","text-overflow":"ellipsis"}},ht={style:{width:"auto","min-width":"0","align-self":"stretch",display:"flex","align-items":"center"}},ft={src:K,alt:"",style:{display:"block",width:"1.3em","aspect-ratio":"1/1"}},kt={style:{"font-weight":"500",color:"rgba(248, 182, 45, 1)"}},wt={__name:"Ranking",setup(i){const a=Be(),{t:v,locale:Z}=Ae(),o=t=>Ee("Ranking/Overall/",t),F=n(!1),r=n(a.query.first||"Wealth"),d=n("Daily"),g=n("GIFTS_SEND"),f=n("DAY"),p=n({}),y=n([]),k=n({}),S=n(!0),V=n(null),x=n(!0),T=n(10),ee=_(()=>r.value=="Wealth"?o("bgWealth")+"?v=20260424c":r.value=="Charm"?o("bgCharm")+"?v=20260424c":r.value=="Room"?o("bgRoom")+"?v=20260424c":""),ge=async()=>{const t=[o("bgWealth")+"?v=20260424c",o("bgCharm")+"?v=20260424c",o("bgRoom")+"?v=20260424c",o("top1-wealth"),o("top1-charm"),o("top1-room"),o("top2"),o("top3"),o("top2-room"),o("top3-room")];await Fe(t)},te=()=>{console.log("updateTimeRanking()//筛选展示榜单"),d.value=="Hourly"&&p.value.hourly?(y.value=p.value.hourly,console.log("showRanking.value:",y.value)):d.value=="Daily"&&p.value.daily?y.value=p.value.daily:d.value=="Weekly"&&p.value.weekly?y.value=p.value.weekly:d.value=="Monthly"&&p.value.monthly&&(y.value=p.value.monthly),T.value=10,x.value=!0},z=se(t=>{r.value!=t&&(console.log("改变rankingType"),r.value=t,d.value="Daily",f.value="DAY",t=="Wealth"?g.value="GIFTS_SEND":t=="Charm"?g.value="GIFTS_RECEIVED":t=="Room"&&(g.value="ROOM_GIFTS"),p.value={},y.value=[],k.value={},T.value=10,x.value=!0,le(),Y())},1e3),G=se(t=>{d.value!=t&&(console.log("改变rankingType"),d.value=t,t=="Hourly"?f.value="HOUR":t=="Daily"?f.value="DAY":t=="Weekly"?f.value="WEEK":t=="Monthly"&&(f.value="MONTH"),y.value=[],k.value={},te(),Y())},500),m=_(()=>{console.log("刷新RankingTop3");let t=[...y.value];if(y.value.length<3){let l=Array.from({length:3-y.value.length},()=>({avatar:"",nickname:"",quantityFormat:""}));t.push(...l)}return t}),pe=_(()=>y.value.filter((l,w)=>w>=3).slice(0,T.value)),ye=n(""),N=n(""),P=n(""),I=n(""),q=n(""),L=n(""),E=n(""),D=n(""),M=n(""),ae=n(null),W=n(null);_e(()=>{r.value=="Wealth"&&(E.value=o("top1-wealth"),D.value=o("top2"),M.value=o("top3"),I.value=o("tabSelectedBg"),N.value="1px solid rgba(221, 114, 0, 0.39)",P.value="rgba(252, 194, 147, 0.20)",q.value="linear-gradient(97deg, rgba(50, 34, 21, 0.60) 12.03%, rgba(99, 52, 33, 0.60) 100.37%)",L.value="solid #FFA166",g.value="GIFTS_SEND"),r.value=="Charm"&&(E.value=o("top1-charm"),D.value=o("top2"),M.value=o("top3"),I.value=o("tabSelectedBg"),N.value="1px solid rgba(0, 221, 74, 0.39)",P.value="rgba(147, 252, 166, 0.20)",q.value="linear-gradient(97deg, rgba(21, 50, 22, 0.60) 12.03%, rgba(33, 99, 40, 0.60) 100.37%)",L.value="solid #66FF82",g.value="GIFTS_RECEIVED"),r.value=="Room"&&(E.value=o("top1-room"),D.value=o("top2-room"),M.value=o("top3-room"),I.value=o("tabSelectedBg"),N.value="1px solid rgba(155, 0, 221, 0.39)",P.value="rgba(219, 147, 252, 0.20)",q.value="linear-gradient(97deg, rgba(33, 21, 50, 0.60) 12.03%, rgba(60, 33, 99, 0.60) 100.37%)",L.value="solid #A366FF",g.value="ROOM_GIFTS")});const me=new IntersectionObserver(t=>{t.forEach(l=>{l.isIntersecting?W.value.classList.remove("stuck"):(console.log("哨兵元素离开视口"),W.value?(W.value.classList.add("stuck"),console.log("添加stuck类")):console.log("元素未找到!"))})}),he=new IntersectionObserver(t=>{t.forEach(l=>{if(l.isIntersecting&&x.value){console.log("触发上拉加载更多");const w=y.value.filter((u,j)=>j>=3).length,R=T.value;R=w&&(x.value=!1,console.log("没有更多数据了"))):(x.value=!1,console.log("没有更多数据了"))}})},{rootMargin:"100px"}),$=t=>{F.value&&(r.value=="Room"?Oe(t):Se(t))},le=async()=>{console.log("获取榜单");let t={};r.value=="Wealth"?t=await Me():r.value=="Charm"?t=await We():r.value=="Room"&&(t=await $e()),t.status&&t.body&&(p.value=t.body,te())},Y=async()=>{console.log("获取我的排名");const t=await je(g.value,f.value);t.status&&t.body?k.value=t.body:k.value={}},fe=async()=>{await Promise.all([le(),Y()])},ke=async()=>{try{await Promise.all([fe(),ge()])}catch(t){console.error("预加载过程中发生错误:",t)}finally{S.value=!1}},we=async()=>{await Ue(()=>{ke()})};return Te(()=>{we(),F.value=xe(),me.observe(ae.value),V.value&&he.observe(V.value)}),(t,l)=>{const w=Ie,R=ve("smart-img");return A(),O("div",{class:"fullPage",style:h({backgroundColor:ye.value})},[b(e("div",Le,[C(ue,{backgroundImages:[ee.value]},null,8,["backgroundImages"]),e("img",{src:"/assets/loading-ranking.gif",alt:"",class:"ranking-loading-image",style:{display:"block",width:"180px",maxWidth:"70vw",height:"auto",margin:"0 auto 12px","object-fit":"contain"}},null,-1),e("p",null,c(t.$t("loading"))+"...",1)],512),[[J,S.value]]),b(e("div",Ye,[C(ue,{backgroundImages:[ee.value],layerStyle:{zIndex:-1}},null,8,["backgroundImages"]),e("div",{ref_key:"sentinel",ref:ae},null,512),e("div",{ref_key:"stickyHeader",ref:W,style:{position:"sticky",top:"0","z-index":"999","border-radius":"0 0 12px 12px",transition:"all 0.3s",height:"35vw"}},[l[12]||(l[12]=e("div",{style:{height:"13vw"}},null,-1)),e("div",Je,[e("div",Qe,[e("div",{class:"tab",onClick:l[0]||(l[0]=u=>s(z)("Wealth")),style:h([{},{color:r.value=="Wealth"?"#FF9500":"#fff"}])},c(s(v)("ranking_wealth")),5),e("div",{class:"tab",onClick:l[1]||(l[1]=u=>s(z)("Charm")),style:h([{},{color:r.value=="Charm"?"#FF9500":"#fff"}])},c(s(v)("ranking_charm")),5),e("div",{class:"tab",onClick:l[2]||(l[2]=u=>s(z)("Room")),style:h([{},{color:r.value=="Room"?"#FF9500":"#fff"}])},c(s(v)("ranking_room")),5),b(e("img",{src:De,alt:"",style:{position:"absolute",left:"-4%",top:"45%",transform:"translateY(-50%)"},width:"6%",onClick:l[3]||(l[3]=(...u)=>s(ie)&&s(ie)(...u))},null,512),[[R]])])]),e("div",Xe,[e("div",{class:"tabItem",style:h(d.value=="Daily"?{backgroundImage:`url(${I.value})`,backgroundSize:"100% 100%",backgroundRepeat:"no-repeat",backgroundPosition:"center"}:{})},[e("div",{class:U(["tag",{tagActive:d.value=="Daily"}]),onClick:l[4]||(l[4]=u=>s(G)("Daily"))},c(s(v)("ranking_daily")),3)],4),e("div",{class:"tabItem",style:h(d.value=="Weekly"?{backgroundImage:`url(${I.value})`,backgroundSize:"100% 100%",backgroundRepeat:"no-repeat",backgroundPosition:"center"}:{})},[e("div",{class:U(["tag",{tagActive:d.value=="Weekly"}]),onClick:l[5]||(l[5]=u=>s(G)("Weekly"))},c(s(v)("ranking_weekly")),3)],4),e("div",{class:"tabItem",style:h(d.value=="Monthly"?{backgroundImage:`url(${I.value})`,backgroundSize:"100% 100%",backgroundRepeat:"no-repeat",backgroundPosition:"center"}:{})},[e("div",{class:U(["tag",{tagActive:d.value=="Monthly"}]),onClick:l[6]||(l[6]=u=>s(G)("Monthly"))},c(s(v)("ranking_monthly")),3)],4)])],512),e("div",Ke,[e("div",Ze,[e("div",et,[C(Q,{Type:r.value,isTopOne:!0,BorderImgUrl:E.value,avatarUrl:m.value[0].avatar||"",name:m.value[0].nickname||"",distributionValue:m.value[0].quantityFormat||"",style:{width:"85%"},onClick:l[7]||(l[7]=u=>$(m.value[0].id))},null,8,["Type","BorderImgUrl","avatarUrl","name","distributionValue"])]),e("div",tt,[C(Q,{Type:r.value,BorderImgUrl:D.value,avatarUrl:m.value[1].avatar||"",name:m.value[1].nickname||"",distributionValue:m.value[1].quantityFormat||"",style:{width:"43%"},onClick:l[8]||(l[8]=u=>$(m.value[1].id))},null,8,["Type","BorderImgUrl","avatarUrl","name","distributionValue"]),C(Q,{Type:r.value,BorderImgUrl:M.value,avatarUrl:m.value[2].avatar||"",name:m.value[2].nickname||"",distributionValue:m.value[2].quantityFormat||"",style:{width:"43%"},onClick:l[9]||(l[9]=u=>$(m.value[2].id))},null,8,["Type","BorderImgUrl","avatarUrl","name","distributionValue"])])]),e("div",at,[(A(!0),O(Re,null,Ce(pe.value,(u,j)=>(A(),ne(de,{style:{"min-height":"19vw"},key:u.id,imgUrl:o("RankingItem"),contentStyle:"padding: 3vw;justify-content: space-between;gap: 8px;",lazy:!0,immediate:j<10,onClick:oe=>$(u.id)},{default:re(()=>[e("div",lt,[e("div",ot,[e("div",it,c(j+4),1)]),e("img",{src:u.avatar||"",alt:"",style:{display:"block",width:"3em","aspect-ratio":"1/1","border-radius":"50%","object-fit":"cover"},onError:l[10]||(l[10]=(...oe)=>s(B)&&s(B)(...oe))},null,40,nt),e("div",rt,c(u.nickname),1)]),e("div",st,[b(e("img",ut,null,512),[[R]]),e("div",dt,c(u.quantityFormat),1)])]),_:2},1032,["imgUrl","immediate","onClick"]))),128)),b(e("div",{ref_key:"RankingLoadmore",ref:V},null,512),[[J,x.value]])])])],512),[[J,!S.value]]),S.value?X("",!0):(A(),O("div",ct)),S.value?X("",!0):(A(),ne(de,{key:1,style:{"min-height":"25vw",position:"fixed",bottom:"0","z-index":"999",padding:"0 1px"},imgUrl:o("myRankingBg"),contentStyle:"padding:4vw 4vw 0;justify-content: space-between;gap: 8px;"},{default:re(()=>[e("div",vt,[e("div",gt,[e("div",pt,c(k.value.rank||999),1)]),e("img",{src:k.value.avatar||"",alt:"",style:{display:"block",width:"3em","aspect-ratio":"1/1","border-radius":"50%","object-fit":"cover"},onError:l[11]||(l[11]=(...u)=>s(B)&&s(B)(...u))},null,40,yt),e("div",mt,c(k.value.nickname||""),1)]),e("div",ht,[b(e("img",ft,null,512),[[R]]),e("div",kt,c(k.value.quantityFormat||0),1)])]),_:1},8,["imgUrl"]))],4)}}},St=ce(wt,[["__scopeId","data-v-93c53aed"]]);export{St as default};
diff --git a/h5/mifa-pay/app.js b/h5/mifa-pay/app.js
new file mode 100644
index 0000000..9af609e
--- /dev/null
+++ b/h5/mifa-pay/app.js
@@ -0,0 +1,407 @@
+const query = new URLSearchParams(window.location.search);
+const storedAppId = window.localStorage.getItem("mifa-pay-application-id") || "";
+const LOGO_SRC = "./mifapay-logo.png";
+
+function getPathApplicationId() {
+ const segments = window.location.pathname.split("/").filter(Boolean);
+ const pageIndex = segments.lastIndexOf("mifa-pay");
+ if (pageIndex === -1) {
+ return "";
+ }
+
+ return segments[pageIndex + 1] || "";
+}
+
+const defaults = {
+ applicationId:
+ getPathApplicationId() ||
+ query.get("applicationId") ||
+ query.get("appId") ||
+ storedAppId ||
+ "2048200000000000701",
+ productType: query.get("type") || "GOLD",
+};
+
+const deps = {
+ getApi: null,
+ postApi: null,
+ fetchCurrentUser: null,
+ getCachedUserProfile: null,
+ connectApp: null,
+};
+
+const state = {
+ applicationId: defaults.applicationId,
+ productType: defaults.productType,
+ userProfile: null,
+ countries: [],
+ selectedCountryId: "",
+ commodityCard: null,
+ selectedGoodsId: "",
+ selectedGoods: null,
+ pendingChannelCode: "",
+ dependencyPromise: null,
+};
+
+const els = {
+ applicationId: document.getElementById("applicationId"),
+ productList: document.getElementById("productList"),
+ channelList: document.getElementById("channelList"),
+ pageStatus: document.getElementById("pageStatus"),
+};
+
+function setStatus(text = "") {
+ if (!text) {
+ els.pageStatus.textContent = "";
+ els.pageStatus.className = "status";
+ return;
+ }
+
+ els.pageStatus.textContent = text;
+ els.pageStatus.className = "status show";
+}
+
+function persistSettings() {
+ window.localStorage.setItem("mifa-pay-application-id", state.applicationId);
+}
+
+function extractErrorMessage(error) {
+ return (
+ error?.response?.errorMsg ||
+ error?.response?.body?.errorMsg ||
+ error?.errorMsg ||
+ error?.message ||
+ "Unknown error"
+ );
+}
+
+function readStoredUserProfile() {
+ const raw = window.localStorage.getItem("userProfile");
+ if (!raw) {
+ return null;
+ }
+
+ try {
+ const parsed = JSON.parse(raw);
+ return parsed && typeof parsed === "object" ? parsed : null;
+ } catch (error) {
+ return null;
+ }
+}
+
+function resolveUserProfile(response = null) {
+ if (response?.body && typeof response.body === "object") {
+ return response.body;
+ }
+
+ if (typeof deps.getCachedUserProfile === "function") {
+ const cached = deps.getCachedUserProfile();
+ if (cached && typeof cached === "object") {
+ return cached;
+ }
+ }
+
+ return readStoredUserProfile();
+}
+
+function currentUserId() {
+ return String(state.userProfile?.id || "").trim();
+}
+
+function currentCountryId() {
+ return state.selectedCountryId;
+}
+
+function getCountryLabel(item) {
+ return (
+ item?.label ||
+ item?.countryName ||
+ item?.country?.aliasName ||
+ item?.country?.countryName ||
+ String(item?.id || "")
+ );
+}
+
+function getGoodsList() {
+ return state.commodityCard?.commodity || [];
+}
+
+function getChannelList() {
+ return state.commodityCard?.channels || [];
+}
+
+function getChannelCode(item) {
+ return item?.details?.channelCode || item?.channel?.channelCode || "";
+}
+
+function getAmountText(item) {
+ const content = item?.content || item?.obtainGoldsQuantity || "-";
+ return `${content} ${item?.type || ""}`.trim();
+}
+
+function getPriceText(item) {
+ const currency = item?.currency || state.commodityCard?.payCountry?.currency || "USD";
+ return `${item?.amount || item?.amountUsd || "-"} ${currency}`;
+}
+
+function ensureSelectedGoods() {
+ const goods = getGoodsList();
+ if (!goods.length) {
+ state.selectedGoodsId = "";
+ state.selectedGoods = null;
+ return;
+ }
+
+ const matched =
+ goods.find((item) => String(item.id) === state.selectedGoodsId) ||
+ goods.find((item) => item.type === state.productType) ||
+ goods[0];
+ state.selectedGoods = matched;
+ state.selectedGoodsId = String(matched.id);
+}
+
+function renderProducts() {
+ const goods = getGoodsList();
+ ensureSelectedGoods();
+
+ if (!goods.length) {
+ els.productList.innerHTML = 'No amount available.
';
+ return;
+ }
+
+ els.productList.innerHTML = goods
+ .map((item) => {
+ const selected = String(item.id) === state.selectedGoodsId;
+ return `
+
+ `;
+ })
+ .join("");
+
+ els.productList.querySelectorAll("[data-goods-id]").forEach((button) => {
+ button.addEventListener("click", () => {
+ const goodsId = button.getAttribute("data-goods-id");
+ state.selectedGoodsId = goodsId;
+ state.selectedGoods =
+ getGoodsList().find((item) => String(item.id) === goodsId) || null;
+ renderProducts();
+ });
+ });
+}
+
+function renderChannels() {
+ const channels = getChannelList();
+ if (!channels.length) {
+ els.channelList.innerHTML = 'No payment method available.
';
+ return;
+ }
+
+ els.channelList.innerHTML = channels
+ .map((item) => {
+ const code = getChannelCode(item);
+ const pending = state.pendingChannelCode === code;
+ return `
+
+ `;
+ })
+ .join("");
+
+ els.channelList.querySelectorAll("[data-channel-code]").forEach((button) => {
+ button.addEventListener("click", async () => {
+ const channelCode = button.getAttribute("data-channel-code");
+ try {
+ await createOrder(channelCode);
+ } catch (error) {
+ state.pendingChannelCode = "";
+ renderChannels();
+ setStatus(extractErrorMessage(error));
+ }
+ });
+ });
+}
+
+function selectCountryByProfile() {
+ const userCountryCode = state.userProfile?.countryCode;
+ if (!userCountryCode) {
+ return false;
+ }
+
+ const matched = state.countries.find((item) =>
+ getCountryLabel(item).toUpperCase().includes(userCountryCode.toUpperCase())
+ );
+
+ if (!matched) {
+ return false;
+ }
+
+ state.selectedCountryId = String(matched.id);
+ return true;
+}
+
+async function ensureDependencies() {
+ if (!state.dependencyPromise) {
+ state.dependencyPromise = Promise.all([
+ import("../js/index-CIAVq8iD-1776148658686.js"),
+ import("../js/appConnector-B5Pbaops-1776148658686.js"),
+ ]).then(([indexModule, connectorModule]) => {
+ deps.getApi = indexModule.L;
+ deps.postApi = indexModule.W;
+ deps.fetchCurrentUser = indexModule.au;
+ deps.getCachedUserProfile = indexModule.at;
+ deps.connectApp = connectorModule.c;
+ return deps;
+ });
+ }
+
+ return state.dependencyPromise;
+}
+
+async function connectSession() {
+ await ensureDependencies();
+
+ const connection = await deps.connectApp();
+ if (!connection?.success) {
+ throw new Error(connection?.error || "Failed to initialize app session");
+ }
+
+ const cachedUserProfile = resolveUserProfile();
+ if (cachedUserProfile?.id) {
+ state.userProfile = cachedUserProfile;
+ return;
+ }
+
+ const response = await deps.fetchCurrentUser();
+ const userProfile = resolveUserProfile(response);
+ if (!userProfile?.id) {
+ throw new Error("Please open this page inside the app");
+ }
+
+ state.userProfile = userProfile;
+}
+
+async function refreshMeta() {
+ if (!state.applicationId) {
+ throw new Error("Missing applicationId");
+ }
+
+ persistSettings();
+ els.applicationId.value = state.applicationId;
+
+ const countriesResp = await deps.getApi("/order/web/pay/country");
+ state.countries = Array.isArray(countriesResp?.body) ? countriesResp.body : [];
+ if (!state.countries.length) {
+ state.selectedCountryId = "";
+ state.commodityCard = null;
+ renderProducts();
+ renderChannels();
+ throw new Error("No supported country");
+ }
+
+ if (
+ !state.selectedCountryId ||
+ !state.countries.some((item) => String(item.id) === String(state.selectedCountryId))
+ ) {
+ if (!selectCountryByProfile()) {
+ state.selectedCountryId = String(state.countries[0].id);
+ }
+ }
+
+ const commodityResp = await deps.getApi(
+ `/order/web/pay/commodity?applicationId=${encodeURIComponent(
+ state.applicationId
+ )}&payCountryId=${encodeURIComponent(currentCountryId())}&type=${encodeURIComponent(
+ state.productType
+ )}`
+ );
+
+ state.commodityCard = commodityResp?.body || {};
+ renderProducts();
+ renderChannels();
+ setStatus("");
+}
+
+function safeDecodeUrl(url) {
+ if (!url) {
+ return "";
+ }
+
+ try {
+ return decodeURIComponent(url);
+ } catch (error) {
+ return url;
+ }
+}
+
+async function createOrder(channelCode) {
+ if (!state.selectedGoods) {
+ throw new Error("Select an amount first");
+ }
+
+ if (!currentUserId()) {
+ throw new Error("Account not available");
+ }
+
+ state.pendingChannelCode = channelCode;
+ setStatus("");
+ renderChannels();
+
+ const payload = {
+ applicationId: Number(state.applicationId),
+ goodsId: Number(state.selectedGoodsId),
+ payCountryId: Number(currentCountryId()),
+ userId: Number(currentUserId()),
+ channelCode,
+ newVersion: true,
+ };
+
+ const response = await deps.postApi("/order/web/pay/recharge", payload);
+ const requestUrl = safeDecodeUrl(response?.body?.requestUrl || "");
+ if (!requestUrl) {
+ throw new Error("Missing payment url");
+ }
+
+ window.location.href = requestUrl;
+}
+
+async function reloadPageData() {
+ await ensureDependencies();
+ await connectSession();
+ await refreshMeta();
+}
+
+async function init() {
+ renderProducts();
+ renderChannels();
+
+ try {
+ await reloadPageData();
+ } catch (error) {
+ setStatus(extractErrorMessage(error));
+ }
+}
+
+init();
diff --git a/h5/mifa-pay/index.html b/h5/mifa-pay/index.html
new file mode 100644
index 0000000..86c94ae
--- /dev/null
+++ b/h5/mifa-pay/index.html
@@ -0,0 +1,249 @@
+
+
+
+
+
+ Recharge
+
+
+
+
+
+
+
+
+
+
diff --git a/h5/mifa-pay/mifapay-logo.png b/h5/mifa-pay/mifapay-logo.png
new file mode 100644
index 0000000..eded9ca
Binary files /dev/null and b/h5/mifa-pay/mifapay-logo.png differ
diff --git a/h5/yumi-invite-agency/index.html b/h5/yumi-invite-agency/index.html
new file mode 100644
index 0000000..8a8a08c
--- /dev/null
+++ b/h5/yumi-invite-agency/index.html
@@ -0,0 +1,120 @@
+
+
+
+
+
+ Invite User To Become Agent
+
+
+
+
+
+
+
+
+
+
+
Information:
+
+
+
+
![]()
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/h5/yumi-invite-agency/yumi-invite-agency.css b/h5/yumi-invite-agency/yumi-invite-agency.css
new file mode 100644
index 0000000..9d8eff2
--- /dev/null
+++ b/h5/yumi-invite-agency/yumi-invite-agency.css
@@ -0,0 +1,456 @@
+html {
+ -webkit-text-size-adjust: 100%;
+ -webkit-overflow-scrolling: touch;
+}
+
+body {
+ margin: 0;
+ min-height: 100%;
+ font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Helvetica Neue", Arial, sans-serif;
+}
+
+* {
+ box-sizing: border-box;
+}
+
+button,
+input {
+ font: inherit;
+}
+
+[hidden] {
+ display: none !important;
+}
+
+.fullPage {
+ width: 100vw;
+ min-height: 100vh;
+ background-color: #fff;
+ background-image: url("../assets/secondBg-CSqvFWr0-1776148661447.png");
+ background-size: 100% auto;
+ background-repeat: no-repeat;
+ position: relative;
+ color: rgba(0, 0, 0, 0.8);
+}
+
+.fullPage input::placeholder {
+ font-weight: 700;
+ color: rgba(0, 0, 0, 0.4);
+}
+
+.invite-btn {
+ padding: 4px 12px;
+ border-radius: 32px;
+ background: linear-gradient(269deg, #feb219 7.04%, #ff9326 96.78%);
+ color: #fff;
+ border: none;
+ font-weight: 600;
+ cursor: pointer;
+ transition: all 0.2s;
+}
+
+.invite-btn:disabled {
+ background: #d1d5db;
+ cursor: not-allowed;
+}
+
+.no-data {
+ text-align: center;
+ padding: 40px 20px;
+ color: #666;
+}
+
+.user-card {
+ cursor: default;
+}
+
+.result-action-btn {
+ padding: 4px 10px;
+ border-radius: 32px;
+ background: linear-gradient(269deg, #feb219 7.04%, #ff9326 96.78%);
+ color: #fff;
+ border: none;
+ font-weight: 600;
+ cursor: pointer;
+ transition: all 0.2s;
+ white-space: nowrap;
+}
+
+.result-action-btn:disabled {
+ background: #d1d5db;
+ cursor: not-allowed;
+}
+
+.status-bar-placeholder {
+ display: none;
+ height: 30px;
+}
+
+.status-bar-placeholder.is-visible {
+ display: block;
+}
+
+.header-container {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 12px 16px;
+ height: 60px;
+ font-size: 16px;
+}
+
+.side-area,
+.actions-area {
+ min-width: 1.5em;
+ display: flex;
+ align-items: center;
+}
+
+.actions-area {
+ justify-content: flex-end;
+ gap: 8px;
+}
+
+.header-title {
+ flex: 1;
+ margin: 0;
+ font-size: 1.2em;
+ font-weight: 600;
+ text-align: center;
+ letter-spacing: 0.3px;
+}
+
+.back-btn,
+.help-btn {
+ width: 1.5em;
+ border: none;
+ background: transparent;
+ transition: all 0.2s ease;
+ padding: 0;
+}
+
+.back-btn:active,
+.help-btn:active {
+ transform: scale(0.9);
+}
+
+.language-entry {
+ display: flex;
+ align-items: center;
+ color: #f59e0b !important;
+ cursor: pointer;
+}
+
+.language-name {
+ font-weight: 700;
+}
+
+.gradient-border-wrapper {
+ position: relative;
+}
+
+.gradient-border-wrapper::before {
+ content: "";
+ position: absolute;
+ inset: 0;
+ border-radius: inherit;
+ padding: var(--gradient-border-width, 1.5px);
+ background: linear-gradient(
+ var(--gradient-direction, to bottom),
+ var(--gradient-start-color, #ffc4c4),
+ var(--gradient-end-color, #fff6a6)
+ );
+ -webkit-mask:
+ linear-gradient(#fff 0 0) content-box,
+ linear-gradient(#fff 0 0);
+ -webkit-mask-composite: xor;
+ mask-composite: exclude;
+ pointer-events: none;
+}
+
+.gradient-border-content {
+ position: relative;
+ border-radius: inherit;
+ width: 100%;
+ height: 100%;
+ background: var(
+ --gradient-background,
+ linear-gradient(120deg, rgba(255, 216, 0, 0.1) 39.13%, rgba(255, 149, 0, 0.1) 119.28%)
+ );
+}
+
+.modal-overlay {
+ position: fixed;
+ inset: 0;
+ background-color: rgba(0, 0, 0, 0.6);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 9999;
+ padding: 20px;
+}
+
+.modal {
+ background: #fff;
+ border-radius: 16px;
+ box-shadow:
+ 0 20px 25px rgba(0, 0, 0, 0.1),
+ 0 10px 10px rgba(0, 0, 0, 0.04);
+ width: 100%;
+ max-width: 320px;
+ padding: 24px 20px 20px;
+ text-align: center;
+ position: relative;
+}
+
+.modal-icon {
+ margin-bottom: 16px;
+ display: flex;
+ justify-content: center;
+}
+
+.icon-circle {
+ width: 56px;
+ height: 56px;
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ animation: iconPulse 0.6s ease-out;
+ border: 3px solid;
+}
+
+.icon-symbol {
+ font-size: 24px;
+ font-weight: 700;
+ line-height: 1;
+}
+
+.modal-title {
+ font-size: 18px;
+ font-weight: 600;
+ color: #1f2937;
+ margin-bottom: 12px;
+ line-height: 1.4;
+}
+
+.modal-message {
+ font-size: 14px;
+ color: #6b7280;
+ line-height: 1.5;
+ margin-bottom: 20px;
+ word-wrap: break-word;
+}
+
+.modal-actions {
+ display: flex;
+ justify-content: center;
+}
+
+.modal-btn {
+ border: none;
+ border-radius: 8px;
+ padding: 10px 32px;
+ font-size: 14px;
+ font-weight: 600;
+ cursor: pointer;
+ transition: all 0.2s;
+ min-width: 80px;
+ color: #fff;
+}
+
+.modal-btn:active {
+ transform: scale(0.98);
+}
+
+.modal-error .icon-circle-error {
+ background-color: #fee2e2;
+ border-color: #fecaca;
+}
+
+.modal-error .icon-symbol-error {
+ color: #dc2626;
+}
+
+.modal-error .modal-btn-error {
+ background-color: #dc2626;
+}
+
+.modal-warning .icon-circle-warning {
+ background-color: #fef3c7;
+ border-color: #fde68a;
+}
+
+.modal-warning .icon-symbol-warning {
+ color: #d97706;
+}
+
+.modal-warning .modal-btn-warning {
+ background-color: #d97706;
+}
+
+.modal-success .icon-circle-success {
+ background-color: #d1fae5;
+ border-color: #a7f3d0;
+}
+
+.modal-success .icon-symbol-success {
+ color: #059669;
+}
+
+.modal-success .modal-btn-success {
+ background-color: #059669;
+}
+
+.modal-info .icon-circle-info {
+ background-color: #dbeafe;
+ border-color: #bfdbfe;
+}
+
+.modal-info .icon-symbol-info {
+ color: #2563eb;
+}
+
+.modal-info .modal-btn-info {
+ background-color: #2563eb;
+}
+
+.modal-simple .modal-message {
+ font-size: 15px;
+ color: #374151;
+ margin-bottom: 24px;
+}
+
+.modal-simple .modal-btn {
+ background-color: #2563eb;
+}
+
+.modal-enter {
+ animation: modalEnter 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
+}
+
+.modal-leave {
+ animation: modalLeave 0.2s ease-in;
+}
+
+[dir="rtl"] .flip-img {
+ transform: scaleX(-1);
+}
+
+[dir="rtl"] .avatar {
+ margin-right: 0;
+ margin-left: 12px;
+}
+
+[dir="rtl"] .user-info {
+ text-align: right;
+}
+
+[dir="rtl"] .language-entry,
+[dir="rtl"] .header-title {
+ direction: rtl;
+}
+
+@keyframes modalEnter {
+ 0% {
+ opacity: 0;
+ transform: scale(0.7) translateY(-10px);
+ }
+
+ 100% {
+ opacity: 1;
+ transform: scale(1) translateY(0);
+ }
+}
+
+@keyframes modalLeave {
+ 0% {
+ opacity: 1;
+ transform: scale(1) translateY(0);
+ }
+
+ 100% {
+ opacity: 0;
+ transform: scale(0.9) translateY(-5px);
+ }
+}
+
+@keyframes iconPulse {
+ 0% {
+ transform: scale(0.8);
+ opacity: 0.5;
+ }
+
+ 50% {
+ transform: scale(1.1);
+ }
+
+ 100% {
+ transform: scale(1);
+ opacity: 1;
+ }
+}
+
+@media screen and (max-width: 360px) {
+ .fullPage {
+ font-size: 10px;
+ }
+
+ .header-container {
+ font-size: 10px;
+ }
+}
+
+@media screen and (min-width: 360px) {
+ .fullPage {
+ font-size: 12px;
+ }
+
+ .header-container {
+ font-size: 16px;
+ }
+}
+
+@media screen and (min-width: 768px) {
+ .fullPage {
+ font-size: 24px;
+ }
+
+ .header-container {
+ font-size: 24px;
+ }
+}
+
+@media screen and (min-width: 1024px) {
+ .fullPage {
+ font-size: 32px;
+ }
+
+ .header-container {
+ font-size: 32px;
+ }
+}
+
+@media (max-width: 480px) {
+ .modal {
+ max-width: 280px;
+ padding: 20px 16px 16px;
+ }
+
+ .icon-circle {
+ width: 48px;
+ height: 48px;
+ }
+
+ .icon-symbol {
+ font-size: 20px;
+ }
+
+ .modal-title {
+ font-size: 16px;
+ }
+
+ .modal-message {
+ font-size: 13px;
+ }
+}
diff --git a/h5/yumi-invite-agency/yumi-invite-agency.js b/h5/yumi-invite-agency/yumi-invite-agency.js
new file mode 100644
index 0000000..49c6dad
--- /dev/null
+++ b/h5/yumi-invite-agency/yumi-invite-agency.js
@@ -0,0 +1,694 @@
+(function () {
+ const API_BASE = "https://jvapi.haiyihy.com";
+ const BACK_ICON =
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAYAAABV7bNHAAAACXBIWXMAACE4AAAhOAFFljFgAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAGXSURBVHgB7dvBTcNAFIThB5xTQFwADVBBmqEnUgZQAAXAjRqgACgAj2wfECbJZXZnrPmkVRT5lF9ODn4vVRERERERETEaxnNb8cd+PA/jeZ3PY02xqG7KA+Ic6/eds5vfPxfRdelb4uxXrt0VmXqgU3Hgo8iUA52LA9SvF1yVpkviHOdDpRhIJg6oBZKKA0qB5OKASiDJOKAQSDYO9A4kHQd6BpKPA70CWcSBHoFs4kDrQFZxoGUguzjQKpBlHGgRyDYOsANZxwFmIPs4wAq0iTjACvRUG4gDjEeumDRsIg4wAn3VhjDmYt81jWOGf64vo5q3MsAaHOLDH2oa7q2xicQKhLvopTYQiTl63kQk9mzePlKL5QXrSK22O2wjtVx/sYzUej/ILlKPBSqrSL02zGwi9VzBs4jUe0dRPpLCEqd0JJUtV9lISmvAkpHU9qTlIikukktFUt20vzQSHu++F5HqGvDi3PgIgQ5FpL5p/zme+/l1za7IHP6rcSoSfdPeIRCsRcIPtM18rSUMJoeKiIiIiIjw9QNKh3OJhFQBoAAAAABJRU5ErkJggg==";
+ const DEFAULT_AVATAR = "../assets/defaultAvatar-CdxWBK1k-1776148661448.png";
+
+ const TEXT = {
+ pageTitle: "Invite User To Become Agent",
+ language: "English",
+ placeholder: "Enter User ID",
+ search: "Search",
+ invite: "Invite",
+ idlePrompt: "please input user id",
+ noUsersFound: "No users found",
+ information: "Information:",
+ userIdPrefix: "User ID:",
+ pending: "Pending",
+ success: "Success",
+ cancel: "Cancel",
+ invitationSubmitted: "Invitation submitted",
+ applicationCancelled: "Application cancelled",
+ somethingWentWrong: "Something went wrong",
+ cancellationFailed: "Cancellation failed, try again",
+ informationTitle: "Information",
+ successTitle: "Success",
+ errorTitle: "Error",
+ ok: "OK",
+ };
+
+ const state = {
+ query: "",
+ invitedList: [],
+ searchResults: [],
+ showSearchResults: false,
+ searching: false,
+ hasSearched: false,
+ };
+
+ const dom = {
+ statusBarPlaceholder: document.getElementById("statusBarPlaceholder"),
+ backButton: document.getElementById("backButton"),
+ backButtonIcon: document.getElementById("backButtonIcon"),
+ pageTitle: document.getElementById("pageTitle"),
+ languageEntry: document.getElementById("languageEntry"),
+ languageName: document.getElementById("languageName"),
+ searchInput: document.getElementById("searchInput"),
+ clearButton: document.getElementById("clearButton"),
+ searchButton: document.getElementById("searchButton"),
+ resultList: document.getElementById("resultList"),
+ noData: document.getElementById("noData"),
+ userCardTemplate: document.getElementById("userCardTemplate"),
+ };
+
+ init();
+
+ function init() {
+ document.title = TEXT.pageTitle;
+ document.documentElement.lang = "en";
+ document.documentElement.dir = resolveDocumentDirection();
+
+ dom.backButtonIcon.src = BACK_ICON;
+ dom.pageTitle.textContent = TEXT.pageTitle;
+ dom.languageName.textContent = TEXT.language;
+ dom.searchInput.placeholder = TEXT.placeholder;
+ dom.searchButton.textContent = TEXT.search;
+ dom.noData.textContent = TEXT.idlePrompt;
+
+ syncStatusBarPlaceholder();
+ bindEvents();
+ render();
+ loadInvitedList();
+ }
+
+ function bindEvents() {
+ dom.backButton.addEventListener("click", handleBack);
+ dom.languageEntry.addEventListener("click", handleLanguageClick);
+ dom.searchInput.addEventListener("input", handleSearchInput);
+ dom.clearButton.addEventListener("click", clearSearch);
+ dom.searchButton.addEventListener("click", triggerSearchNow);
+ }
+
+ function resolveDocumentDirection() {
+ const lang = (new URLSearchParams(window.location.search).get("lang") || "").toLowerCase();
+ return lang.startsWith("ar") ? "rtl" : "ltr";
+ }
+
+ function syncStatusBarPlaceholder() {
+ const hasAppBridge =
+ Boolean(window.app) ||
+ Boolean(window.FlutterPageControl) ||
+ Boolean(window.webkit && window.webkit.messageHandlers);
+ const isIOS = /iphone|ipad|ipod/i.test(window.navigator.userAgent || "");
+ dom.statusBarPlaceholder.classList.toggle("is-visible", hasAppBridge && isIOS);
+ }
+
+ function handleBack() {
+ if (window.history.length > 1) {
+ window.history.back();
+ return;
+ }
+
+ window.location.href = "/";
+ }
+
+ function handleLanguageClick() {
+ window.location.href = "/language";
+ }
+
+ function handleSearchInput(event) {
+ state.query = event.target.value;
+ dom.clearButton.hidden = !state.query;
+ state.showSearchResults = false;
+ state.hasSearched = false;
+ render();
+ }
+
+ function clearSearch() {
+ state.query = "";
+ state.searchResults = [];
+ state.showSearchResults = false;
+ state.hasSearched = false;
+ dom.searchInput.value = "";
+ dom.clearButton.hidden = true;
+ render();
+ }
+
+ async function triggerSearchNow() {
+ if (state.searching) {
+ return;
+ }
+
+ const query = state.query.trim();
+
+ if (!query) {
+ state.showSearchResults = false;
+ state.hasSearched = false;
+ render();
+ return;
+ }
+
+ state.searching = true;
+ state.showSearchResults = true;
+ state.hasSearched = true;
+ state.searchResults = [];
+ render();
+
+ try {
+ const payload = await searchUser(query);
+ state.searchResults = payload ? [mergeWithInvitationStatus(payload.userProfile)] : [];
+ } catch (error) {
+ state.searchResults = [];
+ showToast(extractErrorMessage(error), {
+ title: TEXT.errorTitle,
+ type: "error",
+ });
+ } finally {
+ state.searching = false;
+ render();
+ }
+ }
+
+ async function loadInvitedList() {
+ try {
+ const response = await request("GET", "/team/bd/invite-message-own");
+ state.invitedList = response && response.status && Array.isArray(response.body) ? response.body : [];
+ state.searchResults = state.searchResults.map(function (item) {
+ return mergeWithInvitationStatus(item.userProfile || {});
+ });
+ render();
+ } catch (error) {
+ state.invitedList = [];
+ render();
+ }
+ }
+
+ async function searchUser(query) {
+ try {
+ const response = await request(
+ "GET",
+ "/user/user-profile/open-search?account=" + encodeURIComponent(query)
+ );
+
+ if (response && response.status && response.body) {
+ return { userProfile: response.body };
+ }
+ } catch (error) {
+ if (!/^\d+$/.test(query)) {
+ throw error;
+ }
+ }
+
+ if (!/^\d+$/.test(query)) {
+ return null;
+ }
+
+ const fallbackResponse = await request(
+ "GET",
+ "/user/user-profile?userId=" + encodeURIComponent(query)
+ );
+
+ if (fallbackResponse && fallbackResponse.status && fallbackResponse.body) {
+ return { userProfile: fallbackResponse.body };
+ }
+
+ return null;
+ }
+
+ function mergeWithInvitationStatus(userProfile) {
+ const matchedInvitation = state.invitedList.find(function (item) {
+ return (
+ item &&
+ item.userProfile &&
+ userProfile &&
+ item.userProfile.id === userProfile.id
+ );
+ });
+
+ return Object.assign({}, matchedInvitation || {}, {
+ userProfile: userProfile || {},
+ });
+ }
+
+ async function inviteUser(item) {
+ if (!item || !item.userProfile || !item.userProfile.id) {
+ return;
+ }
+
+ try {
+ const response = await request("POST", "/team/bd/invite-agent", {
+ body: {
+ inviteUserId: item.userProfile.id,
+ },
+ });
+
+ if (response && response.status) {
+ showToast(TEXT.invitationSubmitted, {
+ title: TEXT.successTitle,
+ type: "success",
+ });
+ await loadInvitedList();
+ }
+ } catch (error) {
+ showToast(extractErrorMessage(error, TEXT.somethingWentWrong), {
+ title: TEXT.errorTitle,
+ type: "error",
+ });
+ }
+ }
+
+ async function cancelInvitation(invitationId) {
+ try {
+ const response = await request("POST", "/team/bd/invite-agent-cancel/" + invitationId);
+
+ if (response && response.status) {
+ showToast(TEXT.applicationCancelled, {
+ title: TEXT.informationTitle,
+ type: "info",
+ });
+ await loadInvitedList();
+ }
+ } catch (error) {
+ showToast(extractErrorMessage(error, TEXT.cancellationFailed), {
+ title: TEXT.errorTitle,
+ type: "error",
+ });
+ }
+ }
+
+ function render() {
+ renderSearchButton();
+ renderList();
+ }
+
+ function renderSearchButton() {
+ dom.searchButton.disabled = !state.query.trim() || state.searching;
+ }
+
+ function renderList() {
+ const currentList = state.showSearchResults ? state.searchResults : state.invitedList;
+ dom.resultList.innerHTML = "";
+
+ currentList.forEach(function (item) {
+ dom.resultList.appendChild(createUserCard(item, state.showSearchResults ? "search" : "invited"));
+ });
+
+ if (currentList.length > 0 || (state.searching && state.showSearchResults)) {
+ dom.noData.hidden = true;
+ return;
+ }
+
+ dom.noData.hidden = false;
+ dom.noData.textContent =
+ state.showSearchResults && state.hasSearched ? TEXT.noUsersFound : TEXT.idlePrompt;
+ }
+
+ function createUserCard(item, mode) {
+ const fragment = dom.userCardTemplate.content.cloneNode(true);
+ const statusBadge = fragment.querySelector(".status-badge");
+ const avatarImage = fragment.querySelector(".avatar-image");
+ const nickname = fragment.querySelector(".nickname");
+ const account = fragment.querySelector(".account");
+ const pendingActions = fragment.querySelector(".pending-actions");
+ const userProfile = item.userProfile || {};
+
+ avatarImage.src = userProfile.userAvatar || DEFAULT_AVATAR;
+ avatarImage.alt = userProfile.userNickname || "";
+ avatarImage.onerror = handleAvatarError;
+ nickname.textContent = userProfile.userNickname || "";
+ account.textContent = TEXT.userIdPrefix + " " + (userProfile.account || userProfile.id || "");
+
+ if (item.status === 0) {
+ statusBadge.innerHTML =
+ '' +
+ TEXT.pending +
+ "
";
+ } else if (item.status === 1) {
+ statusBadge.innerHTML =
+ '' +
+ TEXT.success +
+ "
";
+ }
+
+ if (mode === "search") {
+ const inviteButton = document.createElement("button");
+ inviteButton.type = "button";
+ inviteButton.className = "result-action-btn";
+ inviteButton.textContent = TEXT.invite;
+ inviteButton.disabled = item.status === 0 || item.status === 1;
+ inviteButton.addEventListener("click", function (event) {
+ event.stopPropagation();
+ inviteUser(item);
+ });
+ pendingActions.appendChild(inviteButton);
+ } else if (item.status === 0) {
+ const cancelButton = document.createElement("div");
+ cancelButton.textContent = TEXT.cancel;
+ cancelButton.style.padding = "4px 8px";
+ cancelButton.style.borderRadius = "32px";
+ cancelButton.style.backgroundColor = "red";
+ cancelButton.style.color = "white";
+ cancelButton.style.fontWeight = "600";
+ cancelButton.style.zIndex = "5";
+ cancelButton.addEventListener("click", function (event) {
+ event.stopPropagation();
+ cancelInvitation(item.id);
+ });
+ pendingActions.appendChild(cancelButton);
+ }
+
+ return fragment;
+ }
+
+ function handleAvatarError(event) {
+ event.target.onerror = null;
+ event.target.src = DEFAULT_AVATAR;
+ }
+
+ function extractErrorMessage(error, fallback) {
+ return (
+ (error &&
+ error.response &&
+ (error.response.errorMsg || error.response.message || error.response.error)) ||
+ (error && error.message) ||
+ fallback ||
+ TEXT.somethingWentWrong
+ );
+ }
+
+ function showToast(message, options) {
+ const config = Object.assign(
+ {
+ title: TEXT.informationTitle,
+ type: "info",
+ confirmText: TEXT.ok,
+ },
+ options || {}
+ );
+
+ const iconMap = {
+ error: "✕",
+ warning: "⚠",
+ success: "✓",
+ info: "i",
+ simple: "",
+ };
+
+ const overlay = document.createElement("div");
+ overlay.className = "modal-overlay";
+ overlay.innerHTML =
+ '' +
+ (config.type === "simple"
+ ? ""
+ : '
' +
+ iconMap[config.type] +
+ "
") +
+ (config.type === "simple" || !config.title
+ ? ""
+ : '
' + escapeHtml(config.title) + "
") +
+ '
' +
+ escapeHtml(message) +
+ "
" +
+ '
" +
+ "
";
+
+ const modal = overlay.querySelector(".modal");
+ const closeButton = overlay.querySelector(".modal-btn");
+ const close = function () {
+ modal.classList.remove("modal-enter");
+ modal.classList.add("modal-leave");
+ window.setTimeout(function () {
+ overlay.remove();
+ }, 200);
+ };
+
+ closeButton.addEventListener("click", close);
+ overlay.addEventListener("click", function (event) {
+ if (event.target === overlay) {
+ close();
+ }
+ });
+
+ document.body.appendChild(overlay);
+ }
+
+ function escapeHtml(value) {
+ return String(value)
+ .replace(/&/g, "&")
+ .replace(//g, ">")
+ .replace(/"/g, """)
+ .replace(/'/g, "'");
+ }
+
+ async function request(method, path, options) {
+ const config = options || {};
+ const headers = buildRequestHeaders(Boolean(config.body), config.headers || {});
+ const response = await fetch(API_BASE + path, {
+ method: method,
+ credentials: "include",
+ headers: headers,
+ body: config.body ? JSON.stringify(config.body) : undefined,
+ });
+ const text = await response.text();
+ let payload = {};
+
+ if (text) {
+ try {
+ payload = JSON.parse(text);
+ } catch (error) {
+ payload = {
+ status: response.ok,
+ body: text,
+ };
+ }
+ }
+
+ if (!response.ok || payload.status === false) {
+ const requestError = new Error(
+ payload.errorMsg || payload.message || response.statusText || TEXT.somethingWentWrong
+ );
+ requestError.response = payload;
+ throw requestError;
+ }
+
+ return payload;
+ }
+
+ function buildRequestHeaders(hasBody, overrideHeaders) {
+ const discovered = discoverAppHeaders();
+ const headers = Object.assign({}, overrideHeaders || {});
+
+ if (hasBody) {
+ headers["Content-Type"] = headers["Content-Type"] || "application/json";
+ }
+
+ headers.Accept = headers.Accept || "application/json, text/plain, */*";
+
+ if (discovered.authorization) {
+ headers.Authorization = headers.Authorization || discovered.authorization;
+ }
+
+ if (discovered.reqLang) {
+ headers["Req-Lang"] = headers["Req-Lang"] || discovered.reqLang;
+ }
+
+ if (discovered.appVersion) {
+ headers["App-Version"] = headers["App-Version"] || discovered.appVersion;
+ }
+
+ if (discovered.buildVersion) {
+ headers["Build-Version"] = headers["Build-Version"] || discovered.buildVersion;
+ }
+
+ if (discovered.appChannel) {
+ headers["App-Channel"] = headers["App-Channel"] || discovered.appChannel;
+ }
+
+ if (discovered.reqImei) {
+ headers["Req-Imei"] = headers["Req-Imei"] || discovered.reqImei;
+ }
+
+ if (discovered.sysOrigin) {
+ headers["Sys-Origin"] = headers["Sys-Origin"] || discovered.sysOrigin;
+ }
+
+ if (discovered.sysOriginChild) {
+ headers["Sys-Origin-Child"] =
+ headers["Sys-Origin-Child"] || discovered.sysOriginChild;
+ }
+
+ return headers;
+ }
+
+ function discoverAppHeaders() {
+ const query = new URLSearchParams(window.location.search);
+ const collected = [];
+
+ collectCandidate(collected, window.__APP_HEADERS__);
+ collectCandidate(collected, window.__HEADER_INFO__);
+ collectCandidate(collected, window.headerInfo);
+ collectCandidate(collected, parseHeaderObjectFromQuery(query));
+
+ collectFromStorage(collected, window.localStorage);
+ collectFromStorage(collected, window.sessionStorage);
+
+ return collected.reduce(function (result, candidate) {
+ return Object.assign(result, candidate);
+ }, {
+ reqLang: query.get("lang") || document.documentElement.lang || "en",
+ });
+ }
+
+ function parseHeaderObjectFromQuery(query) {
+ const candidate = {};
+ mapHeaderValue(candidate, "authorization", query.get("authorization"));
+ mapHeaderValue(candidate, "authorization", query.get("token"));
+ mapHeaderValue(candidate, "reqLang", query.get("lang"));
+ mapHeaderValue(candidate, "appVersion", query.get("appVersion"));
+ mapHeaderValue(candidate, "buildVersion", query.get("buildVersion"));
+ mapHeaderValue(candidate, "appChannel", query.get("appChannel"));
+ mapHeaderValue(candidate, "reqImei", query.get("reqImei"));
+ mapHeaderValue(candidate, "sysOrigin", query.get("sysOrigin"));
+ mapHeaderValue(candidate, "sysOriginChild", query.get("sysOriginChild"));
+ return candidate;
+ }
+
+ function collectFromStorage(collected, storage) {
+ if (!storage) {
+ return;
+ }
+
+ const preferredKeys = [
+ "authorization",
+ "Authorization",
+ "token",
+ "accessToken",
+ "headerInfo",
+ "headersFromApp",
+ "appHeaders",
+ "persist:root",
+ "user",
+ "userInfo",
+ ];
+
+ preferredKeys.forEach(function (key) {
+ try {
+ collectCandidate(collected, storage.getItem(key));
+ } catch (error) {
+ return;
+ }
+ });
+
+ for (let index = 0; index < storage.length; index += 1) {
+ try {
+ const key = storage.key(index);
+ collectCandidate(collected, storage.getItem(key));
+ } catch (error) {
+ return;
+ }
+ }
+ }
+
+ function collectCandidate(collected, value) {
+ const normalized = normalizeHeaderCandidate(value, 0);
+ if (normalized && Object.keys(normalized).length > 0) {
+ collected.push(normalized);
+ }
+ }
+
+ function normalizeHeaderCandidate(value, depth) {
+ if (depth > 4 || value == null) {
+ return null;
+ }
+
+ if (typeof value === "string") {
+ const trimmed = value.trim();
+
+ if (!trimmed) {
+ return null;
+ }
+
+ if (trimmed[0] === "{" || trimmed[0] === "[") {
+ try {
+ return normalizeHeaderCandidate(JSON.parse(trimmed), depth + 1);
+ } catch (error) {
+ return null;
+ }
+ }
+
+ if (/bearer\s+/i.test(trimmed)) {
+ return {
+ authorization: trimmed,
+ };
+ }
+
+ return null;
+ }
+
+ if (Array.isArray(value)) {
+ return value.reduce(function (result, entry) {
+ const normalized = normalizeHeaderCandidate(entry, depth + 1);
+ return normalized ? Object.assign(result, normalized) : result;
+ }, {});
+ }
+
+ if (typeof value !== "object") {
+ return null;
+ }
+
+ const normalized = {};
+ const aliasMap = {
+ authorization: ["authorization", "Authorization", "token", "accessToken"],
+ reqLang: ["reqLang", "Req-Lang", "lang", "language"],
+ appVersion: ["appVersion", "App-Version"],
+ buildVersion: ["buildVersion", "Build-Version"],
+ appChannel: ["appChannel", "App-Channel"],
+ reqImei: ["reqImei", "Req-Imei"],
+ sysOrigin: ["sysOrigin", "Sys-Origin"],
+ sysOriginChild: ["sysOriginChild", "Sys-Origin-Child"],
+ };
+
+ Object.keys(aliasMap).forEach(function (targetKey) {
+ aliasMap[targetKey].forEach(function (sourceKey) {
+ mapHeaderValue(normalized, targetKey, value[sourceKey]);
+ });
+ });
+
+ ["headerInfo", "headers", "auth", "data", "state"].forEach(function (nestedKey) {
+ const nestedValue = normalizeHeaderCandidate(value[nestedKey], depth + 1);
+ if (nestedValue) {
+ Object.assign(normalized, nestedValue);
+ }
+ });
+
+ Object.keys(value).forEach(function (key) {
+ if (
+ key === "headerInfo" ||
+ key === "headers" ||
+ key === "auth" ||
+ key === "data" ||
+ key === "state"
+ ) {
+ return;
+ }
+
+ if (typeof value[key] === "object") {
+ const nestedValue = normalizeHeaderCandidate(value[key], depth + 1);
+ if (nestedValue) {
+ Object.assign(normalized, nestedValue);
+ }
+ }
+ });
+
+ return normalized;
+ }
+
+ function mapHeaderValue(target, key, value) {
+ if (value == null || value === "" || target[key]) {
+ return;
+ }
+
+ target[key] = String(value);
+ }
+})();
diff --git a/h5/yumi-invite-bd-leader/index.html b/h5/yumi-invite-bd-leader/index.html
new file mode 100644
index 0000000..96b0a2c
--- /dev/null
+++ b/h5/yumi-invite-bd-leader/index.html
@@ -0,0 +1,119 @@
+
+
+
+
+
+ Invite User To Become BD Leader
+
+
+
+
+
+
+
+
+
+
+
Information:
+
+
+
+
![]()
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/h5/yumi-invite-bd-leader/yumi-invite-bd-leader.css b/h5/yumi-invite-bd-leader/yumi-invite-bd-leader.css
new file mode 100644
index 0000000..9d8eff2
--- /dev/null
+++ b/h5/yumi-invite-bd-leader/yumi-invite-bd-leader.css
@@ -0,0 +1,456 @@
+html {
+ -webkit-text-size-adjust: 100%;
+ -webkit-overflow-scrolling: touch;
+}
+
+body {
+ margin: 0;
+ min-height: 100%;
+ font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Helvetica Neue", Arial, sans-serif;
+}
+
+* {
+ box-sizing: border-box;
+}
+
+button,
+input {
+ font: inherit;
+}
+
+[hidden] {
+ display: none !important;
+}
+
+.fullPage {
+ width: 100vw;
+ min-height: 100vh;
+ background-color: #fff;
+ background-image: url("../assets/secondBg-CSqvFWr0-1776148661447.png");
+ background-size: 100% auto;
+ background-repeat: no-repeat;
+ position: relative;
+ color: rgba(0, 0, 0, 0.8);
+}
+
+.fullPage input::placeholder {
+ font-weight: 700;
+ color: rgba(0, 0, 0, 0.4);
+}
+
+.invite-btn {
+ padding: 4px 12px;
+ border-radius: 32px;
+ background: linear-gradient(269deg, #feb219 7.04%, #ff9326 96.78%);
+ color: #fff;
+ border: none;
+ font-weight: 600;
+ cursor: pointer;
+ transition: all 0.2s;
+}
+
+.invite-btn:disabled {
+ background: #d1d5db;
+ cursor: not-allowed;
+}
+
+.no-data {
+ text-align: center;
+ padding: 40px 20px;
+ color: #666;
+}
+
+.user-card {
+ cursor: default;
+}
+
+.result-action-btn {
+ padding: 4px 10px;
+ border-radius: 32px;
+ background: linear-gradient(269deg, #feb219 7.04%, #ff9326 96.78%);
+ color: #fff;
+ border: none;
+ font-weight: 600;
+ cursor: pointer;
+ transition: all 0.2s;
+ white-space: nowrap;
+}
+
+.result-action-btn:disabled {
+ background: #d1d5db;
+ cursor: not-allowed;
+}
+
+.status-bar-placeholder {
+ display: none;
+ height: 30px;
+}
+
+.status-bar-placeholder.is-visible {
+ display: block;
+}
+
+.header-container {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 12px 16px;
+ height: 60px;
+ font-size: 16px;
+}
+
+.side-area,
+.actions-area {
+ min-width: 1.5em;
+ display: flex;
+ align-items: center;
+}
+
+.actions-area {
+ justify-content: flex-end;
+ gap: 8px;
+}
+
+.header-title {
+ flex: 1;
+ margin: 0;
+ font-size: 1.2em;
+ font-weight: 600;
+ text-align: center;
+ letter-spacing: 0.3px;
+}
+
+.back-btn,
+.help-btn {
+ width: 1.5em;
+ border: none;
+ background: transparent;
+ transition: all 0.2s ease;
+ padding: 0;
+}
+
+.back-btn:active,
+.help-btn:active {
+ transform: scale(0.9);
+}
+
+.language-entry {
+ display: flex;
+ align-items: center;
+ color: #f59e0b !important;
+ cursor: pointer;
+}
+
+.language-name {
+ font-weight: 700;
+}
+
+.gradient-border-wrapper {
+ position: relative;
+}
+
+.gradient-border-wrapper::before {
+ content: "";
+ position: absolute;
+ inset: 0;
+ border-radius: inherit;
+ padding: var(--gradient-border-width, 1.5px);
+ background: linear-gradient(
+ var(--gradient-direction, to bottom),
+ var(--gradient-start-color, #ffc4c4),
+ var(--gradient-end-color, #fff6a6)
+ );
+ -webkit-mask:
+ linear-gradient(#fff 0 0) content-box,
+ linear-gradient(#fff 0 0);
+ -webkit-mask-composite: xor;
+ mask-composite: exclude;
+ pointer-events: none;
+}
+
+.gradient-border-content {
+ position: relative;
+ border-radius: inherit;
+ width: 100%;
+ height: 100%;
+ background: var(
+ --gradient-background,
+ linear-gradient(120deg, rgba(255, 216, 0, 0.1) 39.13%, rgba(255, 149, 0, 0.1) 119.28%)
+ );
+}
+
+.modal-overlay {
+ position: fixed;
+ inset: 0;
+ background-color: rgba(0, 0, 0, 0.6);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 9999;
+ padding: 20px;
+}
+
+.modal {
+ background: #fff;
+ border-radius: 16px;
+ box-shadow:
+ 0 20px 25px rgba(0, 0, 0, 0.1),
+ 0 10px 10px rgba(0, 0, 0, 0.04);
+ width: 100%;
+ max-width: 320px;
+ padding: 24px 20px 20px;
+ text-align: center;
+ position: relative;
+}
+
+.modal-icon {
+ margin-bottom: 16px;
+ display: flex;
+ justify-content: center;
+}
+
+.icon-circle {
+ width: 56px;
+ height: 56px;
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ animation: iconPulse 0.6s ease-out;
+ border: 3px solid;
+}
+
+.icon-symbol {
+ font-size: 24px;
+ font-weight: 700;
+ line-height: 1;
+}
+
+.modal-title {
+ font-size: 18px;
+ font-weight: 600;
+ color: #1f2937;
+ margin-bottom: 12px;
+ line-height: 1.4;
+}
+
+.modal-message {
+ font-size: 14px;
+ color: #6b7280;
+ line-height: 1.5;
+ margin-bottom: 20px;
+ word-wrap: break-word;
+}
+
+.modal-actions {
+ display: flex;
+ justify-content: center;
+}
+
+.modal-btn {
+ border: none;
+ border-radius: 8px;
+ padding: 10px 32px;
+ font-size: 14px;
+ font-weight: 600;
+ cursor: pointer;
+ transition: all 0.2s;
+ min-width: 80px;
+ color: #fff;
+}
+
+.modal-btn:active {
+ transform: scale(0.98);
+}
+
+.modal-error .icon-circle-error {
+ background-color: #fee2e2;
+ border-color: #fecaca;
+}
+
+.modal-error .icon-symbol-error {
+ color: #dc2626;
+}
+
+.modal-error .modal-btn-error {
+ background-color: #dc2626;
+}
+
+.modal-warning .icon-circle-warning {
+ background-color: #fef3c7;
+ border-color: #fde68a;
+}
+
+.modal-warning .icon-symbol-warning {
+ color: #d97706;
+}
+
+.modal-warning .modal-btn-warning {
+ background-color: #d97706;
+}
+
+.modal-success .icon-circle-success {
+ background-color: #d1fae5;
+ border-color: #a7f3d0;
+}
+
+.modal-success .icon-symbol-success {
+ color: #059669;
+}
+
+.modal-success .modal-btn-success {
+ background-color: #059669;
+}
+
+.modal-info .icon-circle-info {
+ background-color: #dbeafe;
+ border-color: #bfdbfe;
+}
+
+.modal-info .icon-symbol-info {
+ color: #2563eb;
+}
+
+.modal-info .modal-btn-info {
+ background-color: #2563eb;
+}
+
+.modal-simple .modal-message {
+ font-size: 15px;
+ color: #374151;
+ margin-bottom: 24px;
+}
+
+.modal-simple .modal-btn {
+ background-color: #2563eb;
+}
+
+.modal-enter {
+ animation: modalEnter 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
+}
+
+.modal-leave {
+ animation: modalLeave 0.2s ease-in;
+}
+
+[dir="rtl"] .flip-img {
+ transform: scaleX(-1);
+}
+
+[dir="rtl"] .avatar {
+ margin-right: 0;
+ margin-left: 12px;
+}
+
+[dir="rtl"] .user-info {
+ text-align: right;
+}
+
+[dir="rtl"] .language-entry,
+[dir="rtl"] .header-title {
+ direction: rtl;
+}
+
+@keyframes modalEnter {
+ 0% {
+ opacity: 0;
+ transform: scale(0.7) translateY(-10px);
+ }
+
+ 100% {
+ opacity: 1;
+ transform: scale(1) translateY(0);
+ }
+}
+
+@keyframes modalLeave {
+ 0% {
+ opacity: 1;
+ transform: scale(1) translateY(0);
+ }
+
+ 100% {
+ opacity: 0;
+ transform: scale(0.9) translateY(-5px);
+ }
+}
+
+@keyframes iconPulse {
+ 0% {
+ transform: scale(0.8);
+ opacity: 0.5;
+ }
+
+ 50% {
+ transform: scale(1.1);
+ }
+
+ 100% {
+ transform: scale(1);
+ opacity: 1;
+ }
+}
+
+@media screen and (max-width: 360px) {
+ .fullPage {
+ font-size: 10px;
+ }
+
+ .header-container {
+ font-size: 10px;
+ }
+}
+
+@media screen and (min-width: 360px) {
+ .fullPage {
+ font-size: 12px;
+ }
+
+ .header-container {
+ font-size: 16px;
+ }
+}
+
+@media screen and (min-width: 768px) {
+ .fullPage {
+ font-size: 24px;
+ }
+
+ .header-container {
+ font-size: 24px;
+ }
+}
+
+@media screen and (min-width: 1024px) {
+ .fullPage {
+ font-size: 32px;
+ }
+
+ .header-container {
+ font-size: 32px;
+ }
+}
+
+@media (max-width: 480px) {
+ .modal {
+ max-width: 280px;
+ padding: 20px 16px 16px;
+ }
+
+ .icon-circle {
+ width: 48px;
+ height: 48px;
+ }
+
+ .icon-symbol {
+ font-size: 20px;
+ }
+
+ .modal-title {
+ font-size: 16px;
+ }
+
+ .modal-message {
+ font-size: 13px;
+ }
+}
diff --git a/h5/yumi-invite-bd-leader/yumi-invite-bd-leader.js b/h5/yumi-invite-bd-leader/yumi-invite-bd-leader.js
new file mode 100644
index 0000000..8437fba
--- /dev/null
+++ b/h5/yumi-invite-bd-leader/yumi-invite-bd-leader.js
@@ -0,0 +1,699 @@
+(function () {
+ const API_BASE = "https://jvapi.haiyihy.com";
+ const BACK_ICON =
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAYAAABV7bNHAAAACXBIWXMAACE4AAAhOAFFljFgAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAGXSURBVHgB7dvBTcNAFIThB5xTQFwADVBBmqEnUgZQAAXAjRqgACgAj2wfECbJZXZnrPmkVRT5lF9ODn4vVRERERERETEaxnNb8cd+PA/jeZ3PY02xqG7KA+Ic6/eds5vfPxfRdelb4uxXrt0VmXqgU3Hgo8iUA52LA9SvF1yVpkviHOdDpRhIJg6oBZKKA0qB5OKASiDJOKAQSDYO9A4kHQd6BpKPA70CWcSBHoFs4kDrQFZxoGUguzjQKpBlHGgRyDYOsANZxwFmIPs4wAq0iTjACvRUG4gDjEeumDRsIg4wAn3VhjDmYt81jWOGf64vo5q3MsAaHOLDH2oa7q2xicQKhLvopTYQiTl63kQk9mzePlKL5QXrSK22O2wjtVx/sYzUej/ILlKPBSqrSL02zGwi9VzBs4jUe0dRPpLCEqd0JJUtV9lISmvAkpHU9qTlIikukktFUt20vzQSHu++F5HqGvDi3PgIgQ5FpL5p/zme+/l1za7IHP6rcSoSfdPeIRCsRcIPtM18rSUMJoeKiIiIiIjw9QNKh3OJhFQBoAAAAABJRU5ErkJggg==";
+ const DEFAULT_AVATAR = "../assets/defaultAvatar-CdxWBK1k-1776148661448.png";
+ const ENDPOINTS = {
+ invitedList: "/team/bd/invite-bdleader-message-own",
+ invite: "/team/bd/invite-bdleader",
+ cancelPrefix: "/team/bd/invite-bdleader-cancel/",
+ };
+
+ const TEXT = {
+ pageTitle: "Invite User To Become BD Leader",
+ language: "English",
+ placeholder: "Enter User ID",
+ search: "Search",
+ invite: "Invite",
+ idlePrompt: "please input user id",
+ noUsersFound: "No users found",
+ information: "Information:",
+ userIdPrefix: "User ID:",
+ pending: "Pending",
+ success: "Success",
+ cancel: "Cancel",
+ invitationSubmitted: "Invitation submitted",
+ applicationCancelled: "Application cancelled",
+ somethingWentWrong: "Something went wrong",
+ cancellationFailed: "Cancellation failed, try again",
+ informationTitle: "Information",
+ successTitle: "Success",
+ errorTitle: "Error",
+ ok: "OK",
+ };
+
+ const state = {
+ query: "",
+ invitedList: [],
+ searchResults: [],
+ showSearchResults: false,
+ searching: false,
+ hasSearched: false,
+ };
+
+ const dom = {
+ statusBarPlaceholder: document.getElementById("statusBarPlaceholder"),
+ backButton: document.getElementById("backButton"),
+ backButtonIcon: document.getElementById("backButtonIcon"),
+ pageTitle: document.getElementById("pageTitle"),
+ languageEntry: document.getElementById("languageEntry"),
+ languageName: document.getElementById("languageName"),
+ searchInput: document.getElementById("searchInput"),
+ clearButton: document.getElementById("clearButton"),
+ searchButton: document.getElementById("searchButton"),
+ resultList: document.getElementById("resultList"),
+ noData: document.getElementById("noData"),
+ userCardTemplate: document.getElementById("userCardTemplate"),
+ };
+
+ init();
+
+ function init() {
+ document.title = TEXT.pageTitle;
+ document.documentElement.lang = "en";
+ document.documentElement.dir = resolveDocumentDirection();
+
+ dom.backButtonIcon.src = BACK_ICON;
+ dom.pageTitle.textContent = TEXT.pageTitle;
+ dom.languageName.textContent = TEXT.language;
+ dom.searchInput.placeholder = TEXT.placeholder;
+ dom.searchButton.textContent = TEXT.search;
+ dom.noData.textContent = TEXT.idlePrompt;
+
+ syncStatusBarPlaceholder();
+ bindEvents();
+ render();
+ loadInvitedList();
+ }
+
+ function bindEvents() {
+ dom.backButton.addEventListener("click", handleBack);
+ dom.languageEntry.addEventListener("click", handleLanguageClick);
+ dom.searchInput.addEventListener("input", handleSearchInput);
+ dom.clearButton.addEventListener("click", clearSearch);
+ dom.searchButton.addEventListener("click", triggerSearchNow);
+ }
+
+ function resolveDocumentDirection() {
+ const lang = (new URLSearchParams(window.location.search).get("lang") || "").toLowerCase();
+ return lang.startsWith("ar") ? "rtl" : "ltr";
+ }
+
+ function syncStatusBarPlaceholder() {
+ const hasAppBridge =
+ Boolean(window.app) ||
+ Boolean(window.FlutterPageControl) ||
+ Boolean(window.webkit && window.webkit.messageHandlers);
+ const isIOS = /iphone|ipad|ipod/i.test(window.navigator.userAgent || "");
+ dom.statusBarPlaceholder.classList.toggle("is-visible", hasAppBridge && isIOS);
+ }
+
+ function handleBack() {
+ if (window.history.length > 1) {
+ window.history.back();
+ return;
+ }
+
+ window.location.href = "/";
+ }
+
+ function handleLanguageClick() {
+ window.location.href = "/language";
+ }
+
+ function handleSearchInput(event) {
+ state.query = event.target.value;
+ dom.clearButton.hidden = !state.query;
+ state.showSearchResults = false;
+ state.hasSearched = false;
+ render();
+ }
+
+ function clearSearch() {
+ state.query = "";
+ state.searchResults = [];
+ state.showSearchResults = false;
+ state.hasSearched = false;
+ dom.searchInput.value = "";
+ dom.clearButton.hidden = true;
+ render();
+ }
+
+ async function triggerSearchNow() {
+ if (state.searching) {
+ return;
+ }
+
+ const query = state.query.trim();
+
+ if (!query) {
+ state.showSearchResults = false;
+ state.hasSearched = false;
+ render();
+ return;
+ }
+
+ state.searching = true;
+ state.showSearchResults = true;
+ state.hasSearched = true;
+ state.searchResults = [];
+ render();
+
+ try {
+ const payload = await searchUser(query);
+ state.searchResults = payload ? [mergeWithInvitationStatus(payload.userProfile)] : [];
+ } catch (error) {
+ state.searchResults = [];
+ showToast(extractErrorMessage(error), {
+ title: TEXT.errorTitle,
+ type: "error",
+ });
+ } finally {
+ state.searching = false;
+ render();
+ }
+ }
+
+ async function loadInvitedList() {
+ try {
+ const response = await request("GET", ENDPOINTS.invitedList);
+ state.invitedList = response && response.status && Array.isArray(response.body) ? response.body : [];
+ state.searchResults = state.searchResults.map(function (item) {
+ return mergeWithInvitationStatus(item.userProfile || {});
+ });
+ render();
+ } catch (error) {
+ state.invitedList = [];
+ render();
+ }
+ }
+
+ async function searchUser(query) {
+ try {
+ const response = await request(
+ "GET",
+ "/user/user-profile/open-search?account=" + encodeURIComponent(query)
+ );
+
+ if (response && response.status && response.body) {
+ return { userProfile: response.body };
+ }
+ } catch (error) {
+ if (!/^\d+$/.test(query)) {
+ throw error;
+ }
+ }
+
+ if (!/^\d+$/.test(query)) {
+ return null;
+ }
+
+ const fallbackResponse = await request(
+ "GET",
+ "/user/user-profile?userId=" + encodeURIComponent(query)
+ );
+
+ if (fallbackResponse && fallbackResponse.status && fallbackResponse.body) {
+ return { userProfile: fallbackResponse.body };
+ }
+
+ return null;
+ }
+
+ function mergeWithInvitationStatus(userProfile) {
+ const matchedInvitation = state.invitedList.find(function (item) {
+ return (
+ item &&
+ item.userProfile &&
+ userProfile &&
+ item.userProfile.id === userProfile.id
+ );
+ });
+
+ return Object.assign({}, matchedInvitation || {}, {
+ userProfile: userProfile || {},
+ });
+ }
+
+ async function inviteUser(item) {
+ if (!item || !item.userProfile || !item.userProfile.id) {
+ return;
+ }
+
+ try {
+ const response = await request("POST", ENDPOINTS.invite, {
+ body: {
+ inviteUserId: item.userProfile.id,
+ },
+ });
+
+ if (response && response.status) {
+ showToast(TEXT.invitationSubmitted, {
+ title: TEXT.successTitle,
+ type: "success",
+ });
+ await loadInvitedList();
+ }
+ } catch (error) {
+ showToast(extractErrorMessage(error, TEXT.somethingWentWrong), {
+ title: TEXT.errorTitle,
+ type: "error",
+ });
+ }
+ }
+
+ async function cancelInvitation(invitationId) {
+ try {
+ const response = await request("POST", ENDPOINTS.cancelPrefix + invitationId);
+
+ if (response && response.status) {
+ showToast(TEXT.applicationCancelled, {
+ title: TEXT.informationTitle,
+ type: "info",
+ });
+ await loadInvitedList();
+ }
+ } catch (error) {
+ showToast(extractErrorMessage(error, TEXT.cancellationFailed), {
+ title: TEXT.errorTitle,
+ type: "error",
+ });
+ }
+ }
+
+ function render() {
+ renderSearchButton();
+ renderList();
+ }
+
+ function renderSearchButton() {
+ dom.searchButton.disabled = !state.query.trim() || state.searching;
+ }
+
+ function renderList() {
+ const currentList = state.showSearchResults ? state.searchResults : state.invitedList;
+ dom.resultList.innerHTML = "";
+
+ currentList.forEach(function (item) {
+ dom.resultList.appendChild(createUserCard(item, state.showSearchResults ? "search" : "invited"));
+ });
+
+ if (currentList.length > 0 || (state.searching && state.showSearchResults)) {
+ dom.noData.hidden = true;
+ return;
+ }
+
+ dom.noData.hidden = false;
+ dom.noData.textContent =
+ state.showSearchResults && state.hasSearched ? TEXT.noUsersFound : TEXT.idlePrompt;
+ }
+
+ function createUserCard(item, mode) {
+ const fragment = dom.userCardTemplate.content.cloneNode(true);
+ const statusBadge = fragment.querySelector(".status-badge");
+ const avatarImage = fragment.querySelector(".avatar-image");
+ const nickname = fragment.querySelector(".nickname");
+ const account = fragment.querySelector(".account");
+ const pendingActions = fragment.querySelector(".pending-actions");
+ const userProfile = item.userProfile || {};
+
+ avatarImage.src = userProfile.userAvatar || DEFAULT_AVATAR;
+ avatarImage.alt = userProfile.userNickname || "";
+ avatarImage.onerror = handleAvatarError;
+ nickname.textContent = userProfile.userNickname || "";
+ account.textContent = TEXT.userIdPrefix + " " + (userProfile.account || userProfile.id || "");
+
+ if (item.status === 0) {
+ statusBadge.innerHTML =
+ '' +
+ TEXT.pending +
+ "
";
+ } else if (item.status === 1) {
+ statusBadge.innerHTML =
+ '' +
+ TEXT.success +
+ "
";
+ }
+
+ if (mode === "search") {
+ const inviteButton = document.createElement("button");
+ inviteButton.type = "button";
+ inviteButton.className = "result-action-btn";
+ inviteButton.textContent = TEXT.invite;
+ inviteButton.disabled = item.status === 0 || item.status === 1;
+ inviteButton.addEventListener("click", function (event) {
+ event.stopPropagation();
+ inviteUser(item);
+ });
+ pendingActions.appendChild(inviteButton);
+ } else if (item.status === 0) {
+ const cancelButton = document.createElement("div");
+ cancelButton.textContent = TEXT.cancel;
+ cancelButton.style.padding = "4px 8px";
+ cancelButton.style.borderRadius = "32px";
+ cancelButton.style.backgroundColor = "red";
+ cancelButton.style.color = "white";
+ cancelButton.style.fontWeight = "600";
+ cancelButton.style.zIndex = "5";
+ cancelButton.addEventListener("click", function (event) {
+ event.stopPropagation();
+ cancelInvitation(item.id);
+ });
+ pendingActions.appendChild(cancelButton);
+ }
+
+ return fragment;
+ }
+
+ function handleAvatarError(event) {
+ event.target.onerror = null;
+ event.target.src = DEFAULT_AVATAR;
+ }
+
+ function extractErrorMessage(error, fallback) {
+ return (
+ (error &&
+ error.response &&
+ (error.response.errorMsg || error.response.message || error.response.error)) ||
+ (error && error.message) ||
+ fallback ||
+ TEXT.somethingWentWrong
+ );
+ }
+
+ function showToast(message, options) {
+ const config = Object.assign(
+ {
+ title: TEXT.informationTitle,
+ type: "info",
+ confirmText: TEXT.ok,
+ },
+ options || {}
+ );
+
+ const iconMap = {
+ error: "✕",
+ warning: "⚠",
+ success: "✓",
+ info: "i",
+ simple: "",
+ };
+
+ const overlay = document.createElement("div");
+ overlay.className = "modal-overlay";
+ overlay.innerHTML =
+ '' +
+ (config.type === "simple"
+ ? ""
+ : '
' +
+ iconMap[config.type] +
+ "
") +
+ (config.type === "simple" || !config.title
+ ? ""
+ : '
' + escapeHtml(config.title) + "
") +
+ '
' +
+ escapeHtml(message) +
+ "
" +
+ '
" +
+ "
";
+
+ const modal = overlay.querySelector(".modal");
+ const closeButton = overlay.querySelector(".modal-btn");
+ const close = function () {
+ modal.classList.remove("modal-enter");
+ modal.classList.add("modal-leave");
+ window.setTimeout(function () {
+ overlay.remove();
+ }, 200);
+ };
+
+ closeButton.addEventListener("click", close);
+ overlay.addEventListener("click", function (event) {
+ if (event.target === overlay) {
+ close();
+ }
+ });
+
+ document.body.appendChild(overlay);
+ }
+
+ function escapeHtml(value) {
+ return String(value)
+ .replace(/&/g, "&")
+ .replace(//g, ">")
+ .replace(/"/g, """)
+ .replace(/'/g, "'");
+ }
+
+ async function request(method, path, options) {
+ const config = options || {};
+ const headers = buildRequestHeaders(Boolean(config.body), config.headers || {});
+ const response = await fetch(API_BASE + path, {
+ method: method,
+ credentials: "include",
+ headers: headers,
+ body: config.body ? JSON.stringify(config.body) : undefined,
+ });
+ const text = await response.text();
+ let payload = {};
+
+ if (text) {
+ try {
+ payload = JSON.parse(text);
+ } catch (error) {
+ payload = {
+ status: response.ok,
+ body: text,
+ };
+ }
+ }
+
+ if (!response.ok || payload.status === false) {
+ const requestError = new Error(
+ payload.errorMsg || payload.message || response.statusText || TEXT.somethingWentWrong
+ );
+ requestError.response = payload;
+ throw requestError;
+ }
+
+ return payload;
+ }
+
+ function buildRequestHeaders(hasBody, overrideHeaders) {
+ const discovered = discoverAppHeaders();
+ const headers = Object.assign({}, overrideHeaders || {});
+
+ if (hasBody) {
+ headers["Content-Type"] = headers["Content-Type"] || "application/json";
+ }
+
+ headers.Accept = headers.Accept || "application/json, text/plain, */*";
+
+ if (discovered.authorization) {
+ headers.Authorization = headers.Authorization || discovered.authorization;
+ }
+
+ if (discovered.reqLang) {
+ headers["Req-Lang"] = headers["Req-Lang"] || discovered.reqLang;
+ }
+
+ if (discovered.appVersion) {
+ headers["App-Version"] = headers["App-Version"] || discovered.appVersion;
+ }
+
+ if (discovered.buildVersion) {
+ headers["Build-Version"] = headers["Build-Version"] || discovered.buildVersion;
+ }
+
+ if (discovered.appChannel) {
+ headers["App-Channel"] = headers["App-Channel"] || discovered.appChannel;
+ }
+
+ if (discovered.reqImei) {
+ headers["Req-Imei"] = headers["Req-Imei"] || discovered.reqImei;
+ }
+
+ if (discovered.sysOrigin) {
+ headers["Sys-Origin"] = headers["Sys-Origin"] || discovered.sysOrigin;
+ }
+
+ if (discovered.sysOriginChild) {
+ headers["Sys-Origin-Child"] =
+ headers["Sys-Origin-Child"] || discovered.sysOriginChild;
+ }
+
+ return headers;
+ }
+
+ function discoverAppHeaders() {
+ const query = new URLSearchParams(window.location.search);
+ const collected = [];
+
+ collectCandidate(collected, window.__APP_HEADERS__);
+ collectCandidate(collected, window.__HEADER_INFO__);
+ collectCandidate(collected, window.headerInfo);
+ collectCandidate(collected, parseHeaderObjectFromQuery(query));
+
+ collectFromStorage(collected, window.localStorage);
+ collectFromStorage(collected, window.sessionStorage);
+
+ return collected.reduce(function (result, candidate) {
+ return Object.assign(result, candidate);
+ }, {
+ reqLang: query.get("lang") || document.documentElement.lang || "en",
+ });
+ }
+
+ function parseHeaderObjectFromQuery(query) {
+ const candidate = {};
+ mapHeaderValue(candidate, "authorization", query.get("authorization"));
+ mapHeaderValue(candidate, "authorization", query.get("token"));
+ mapHeaderValue(candidate, "reqLang", query.get("lang"));
+ mapHeaderValue(candidate, "appVersion", query.get("appVersion"));
+ mapHeaderValue(candidate, "buildVersion", query.get("buildVersion"));
+ mapHeaderValue(candidate, "appChannel", query.get("appChannel"));
+ mapHeaderValue(candidate, "reqImei", query.get("reqImei"));
+ mapHeaderValue(candidate, "sysOrigin", query.get("sysOrigin"));
+ mapHeaderValue(candidate, "sysOriginChild", query.get("sysOriginChild"));
+ return candidate;
+ }
+
+ function collectFromStorage(collected, storage) {
+ if (!storage) {
+ return;
+ }
+
+ const preferredKeys = [
+ "authorization",
+ "Authorization",
+ "token",
+ "accessToken",
+ "headerInfo",
+ "headersFromApp",
+ "appHeaders",
+ "persist:root",
+ "user",
+ "userInfo",
+ ];
+
+ preferredKeys.forEach(function (key) {
+ try {
+ collectCandidate(collected, storage.getItem(key));
+ } catch (error) {
+ return;
+ }
+ });
+
+ for (let index = 0; index < storage.length; index += 1) {
+ try {
+ const key = storage.key(index);
+ collectCandidate(collected, storage.getItem(key));
+ } catch (error) {
+ return;
+ }
+ }
+ }
+
+ function collectCandidate(collected, value) {
+ const normalized = normalizeHeaderCandidate(value, 0);
+ if (normalized && Object.keys(normalized).length > 0) {
+ collected.push(normalized);
+ }
+ }
+
+ function normalizeHeaderCandidate(value, depth) {
+ if (depth > 4 || value == null) {
+ return null;
+ }
+
+ if (typeof value === "string") {
+ const trimmed = value.trim();
+
+ if (!trimmed) {
+ return null;
+ }
+
+ if (trimmed[0] === "{" || trimmed[0] === "[") {
+ try {
+ return normalizeHeaderCandidate(JSON.parse(trimmed), depth + 1);
+ } catch (error) {
+ return null;
+ }
+ }
+
+ if (/bearer\\s+/i.test(trimmed)) {
+ return {
+ authorization: trimmed,
+ };
+ }
+
+ return null;
+ }
+
+ if (Array.isArray(value)) {
+ return value.reduce(function (result, entry) {
+ const normalized = normalizeHeaderCandidate(entry, depth + 1);
+ return normalized ? Object.assign(result, normalized) : result;
+ }, {});
+ }
+
+ if (typeof value !== "object") {
+ return null;
+ }
+
+ const normalized = {};
+ const aliasMap = {
+ authorization: ["authorization", "Authorization", "token", "accessToken"],
+ reqLang: ["reqLang", "Req-Lang", "lang", "language"],
+ appVersion: ["appVersion", "App-Version"],
+ buildVersion: ["buildVersion", "Build-Version"],
+ appChannel: ["appChannel", "App-Channel"],
+ reqImei: ["reqImei", "Req-Imei"],
+ sysOrigin: ["sysOrigin", "Sys-Origin"],
+ sysOriginChild: ["sysOriginChild", "Sys-Origin-Child"],
+ };
+
+ Object.keys(aliasMap).forEach(function (targetKey) {
+ aliasMap[targetKey].forEach(function (sourceKey) {
+ mapHeaderValue(normalized, targetKey, value[sourceKey]);
+ });
+ });
+
+ ["headerInfo", "headers", "auth", "data", "state"].forEach(function (nestedKey) {
+ const nestedValue = normalizeHeaderCandidate(value[nestedKey], depth + 1);
+ if (nestedValue) {
+ Object.assign(normalized, nestedValue);
+ }
+ });
+
+ Object.keys(value).forEach(function (key) {
+ if (
+ key === "headerInfo" ||
+ key === "headers" ||
+ key === "auth" ||
+ key === "data" ||
+ key === "state"
+ ) {
+ return;
+ }
+
+ if (typeof value[key] === "object") {
+ const nestedValue = normalizeHeaderCandidate(value[key], depth + 1);
+ if (nestedValue) {
+ Object.assign(normalized, nestedValue);
+ }
+ }
+ });
+
+ return normalized;
+ }
+
+ function mapHeaderValue(target, key, value) {
+ if (value == null || value === "" || target[key]) {
+ return;
+ }
+
+ target[key] = String(value);
+ }
+})();
diff --git a/h5/yumi-invite-bd/index.html b/h5/yumi-invite-bd/index.html
new file mode 100644
index 0000000..31e3471
--- /dev/null
+++ b/h5/yumi-invite-bd/index.html
@@ -0,0 +1,119 @@
+
+
+
+
+
+ Invite User To Become BD
+
+
+
+
+
+
+
+
+
+
+
Information:
+
+
+
+
![]()
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/h5/yumi-invite-bd/yumi-invite-bd.css b/h5/yumi-invite-bd/yumi-invite-bd.css
new file mode 100644
index 0000000..9d8eff2
--- /dev/null
+++ b/h5/yumi-invite-bd/yumi-invite-bd.css
@@ -0,0 +1,456 @@
+html {
+ -webkit-text-size-adjust: 100%;
+ -webkit-overflow-scrolling: touch;
+}
+
+body {
+ margin: 0;
+ min-height: 100%;
+ font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Helvetica Neue", Arial, sans-serif;
+}
+
+* {
+ box-sizing: border-box;
+}
+
+button,
+input {
+ font: inherit;
+}
+
+[hidden] {
+ display: none !important;
+}
+
+.fullPage {
+ width: 100vw;
+ min-height: 100vh;
+ background-color: #fff;
+ background-image: url("../assets/secondBg-CSqvFWr0-1776148661447.png");
+ background-size: 100% auto;
+ background-repeat: no-repeat;
+ position: relative;
+ color: rgba(0, 0, 0, 0.8);
+}
+
+.fullPage input::placeholder {
+ font-weight: 700;
+ color: rgba(0, 0, 0, 0.4);
+}
+
+.invite-btn {
+ padding: 4px 12px;
+ border-radius: 32px;
+ background: linear-gradient(269deg, #feb219 7.04%, #ff9326 96.78%);
+ color: #fff;
+ border: none;
+ font-weight: 600;
+ cursor: pointer;
+ transition: all 0.2s;
+}
+
+.invite-btn:disabled {
+ background: #d1d5db;
+ cursor: not-allowed;
+}
+
+.no-data {
+ text-align: center;
+ padding: 40px 20px;
+ color: #666;
+}
+
+.user-card {
+ cursor: default;
+}
+
+.result-action-btn {
+ padding: 4px 10px;
+ border-radius: 32px;
+ background: linear-gradient(269deg, #feb219 7.04%, #ff9326 96.78%);
+ color: #fff;
+ border: none;
+ font-weight: 600;
+ cursor: pointer;
+ transition: all 0.2s;
+ white-space: nowrap;
+}
+
+.result-action-btn:disabled {
+ background: #d1d5db;
+ cursor: not-allowed;
+}
+
+.status-bar-placeholder {
+ display: none;
+ height: 30px;
+}
+
+.status-bar-placeholder.is-visible {
+ display: block;
+}
+
+.header-container {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 12px 16px;
+ height: 60px;
+ font-size: 16px;
+}
+
+.side-area,
+.actions-area {
+ min-width: 1.5em;
+ display: flex;
+ align-items: center;
+}
+
+.actions-area {
+ justify-content: flex-end;
+ gap: 8px;
+}
+
+.header-title {
+ flex: 1;
+ margin: 0;
+ font-size: 1.2em;
+ font-weight: 600;
+ text-align: center;
+ letter-spacing: 0.3px;
+}
+
+.back-btn,
+.help-btn {
+ width: 1.5em;
+ border: none;
+ background: transparent;
+ transition: all 0.2s ease;
+ padding: 0;
+}
+
+.back-btn:active,
+.help-btn:active {
+ transform: scale(0.9);
+}
+
+.language-entry {
+ display: flex;
+ align-items: center;
+ color: #f59e0b !important;
+ cursor: pointer;
+}
+
+.language-name {
+ font-weight: 700;
+}
+
+.gradient-border-wrapper {
+ position: relative;
+}
+
+.gradient-border-wrapper::before {
+ content: "";
+ position: absolute;
+ inset: 0;
+ border-radius: inherit;
+ padding: var(--gradient-border-width, 1.5px);
+ background: linear-gradient(
+ var(--gradient-direction, to bottom),
+ var(--gradient-start-color, #ffc4c4),
+ var(--gradient-end-color, #fff6a6)
+ );
+ -webkit-mask:
+ linear-gradient(#fff 0 0) content-box,
+ linear-gradient(#fff 0 0);
+ -webkit-mask-composite: xor;
+ mask-composite: exclude;
+ pointer-events: none;
+}
+
+.gradient-border-content {
+ position: relative;
+ border-radius: inherit;
+ width: 100%;
+ height: 100%;
+ background: var(
+ --gradient-background,
+ linear-gradient(120deg, rgba(255, 216, 0, 0.1) 39.13%, rgba(255, 149, 0, 0.1) 119.28%)
+ );
+}
+
+.modal-overlay {
+ position: fixed;
+ inset: 0;
+ background-color: rgba(0, 0, 0, 0.6);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 9999;
+ padding: 20px;
+}
+
+.modal {
+ background: #fff;
+ border-radius: 16px;
+ box-shadow:
+ 0 20px 25px rgba(0, 0, 0, 0.1),
+ 0 10px 10px rgba(0, 0, 0, 0.04);
+ width: 100%;
+ max-width: 320px;
+ padding: 24px 20px 20px;
+ text-align: center;
+ position: relative;
+}
+
+.modal-icon {
+ margin-bottom: 16px;
+ display: flex;
+ justify-content: center;
+}
+
+.icon-circle {
+ width: 56px;
+ height: 56px;
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ animation: iconPulse 0.6s ease-out;
+ border: 3px solid;
+}
+
+.icon-symbol {
+ font-size: 24px;
+ font-weight: 700;
+ line-height: 1;
+}
+
+.modal-title {
+ font-size: 18px;
+ font-weight: 600;
+ color: #1f2937;
+ margin-bottom: 12px;
+ line-height: 1.4;
+}
+
+.modal-message {
+ font-size: 14px;
+ color: #6b7280;
+ line-height: 1.5;
+ margin-bottom: 20px;
+ word-wrap: break-word;
+}
+
+.modal-actions {
+ display: flex;
+ justify-content: center;
+}
+
+.modal-btn {
+ border: none;
+ border-radius: 8px;
+ padding: 10px 32px;
+ font-size: 14px;
+ font-weight: 600;
+ cursor: pointer;
+ transition: all 0.2s;
+ min-width: 80px;
+ color: #fff;
+}
+
+.modal-btn:active {
+ transform: scale(0.98);
+}
+
+.modal-error .icon-circle-error {
+ background-color: #fee2e2;
+ border-color: #fecaca;
+}
+
+.modal-error .icon-symbol-error {
+ color: #dc2626;
+}
+
+.modal-error .modal-btn-error {
+ background-color: #dc2626;
+}
+
+.modal-warning .icon-circle-warning {
+ background-color: #fef3c7;
+ border-color: #fde68a;
+}
+
+.modal-warning .icon-symbol-warning {
+ color: #d97706;
+}
+
+.modal-warning .modal-btn-warning {
+ background-color: #d97706;
+}
+
+.modal-success .icon-circle-success {
+ background-color: #d1fae5;
+ border-color: #a7f3d0;
+}
+
+.modal-success .icon-symbol-success {
+ color: #059669;
+}
+
+.modal-success .modal-btn-success {
+ background-color: #059669;
+}
+
+.modal-info .icon-circle-info {
+ background-color: #dbeafe;
+ border-color: #bfdbfe;
+}
+
+.modal-info .icon-symbol-info {
+ color: #2563eb;
+}
+
+.modal-info .modal-btn-info {
+ background-color: #2563eb;
+}
+
+.modal-simple .modal-message {
+ font-size: 15px;
+ color: #374151;
+ margin-bottom: 24px;
+}
+
+.modal-simple .modal-btn {
+ background-color: #2563eb;
+}
+
+.modal-enter {
+ animation: modalEnter 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
+}
+
+.modal-leave {
+ animation: modalLeave 0.2s ease-in;
+}
+
+[dir="rtl"] .flip-img {
+ transform: scaleX(-1);
+}
+
+[dir="rtl"] .avatar {
+ margin-right: 0;
+ margin-left: 12px;
+}
+
+[dir="rtl"] .user-info {
+ text-align: right;
+}
+
+[dir="rtl"] .language-entry,
+[dir="rtl"] .header-title {
+ direction: rtl;
+}
+
+@keyframes modalEnter {
+ 0% {
+ opacity: 0;
+ transform: scale(0.7) translateY(-10px);
+ }
+
+ 100% {
+ opacity: 1;
+ transform: scale(1) translateY(0);
+ }
+}
+
+@keyframes modalLeave {
+ 0% {
+ opacity: 1;
+ transform: scale(1) translateY(0);
+ }
+
+ 100% {
+ opacity: 0;
+ transform: scale(0.9) translateY(-5px);
+ }
+}
+
+@keyframes iconPulse {
+ 0% {
+ transform: scale(0.8);
+ opacity: 0.5;
+ }
+
+ 50% {
+ transform: scale(1.1);
+ }
+
+ 100% {
+ transform: scale(1);
+ opacity: 1;
+ }
+}
+
+@media screen and (max-width: 360px) {
+ .fullPage {
+ font-size: 10px;
+ }
+
+ .header-container {
+ font-size: 10px;
+ }
+}
+
+@media screen and (min-width: 360px) {
+ .fullPage {
+ font-size: 12px;
+ }
+
+ .header-container {
+ font-size: 16px;
+ }
+}
+
+@media screen and (min-width: 768px) {
+ .fullPage {
+ font-size: 24px;
+ }
+
+ .header-container {
+ font-size: 24px;
+ }
+}
+
+@media screen and (min-width: 1024px) {
+ .fullPage {
+ font-size: 32px;
+ }
+
+ .header-container {
+ font-size: 32px;
+ }
+}
+
+@media (max-width: 480px) {
+ .modal {
+ max-width: 280px;
+ padding: 20px 16px 16px;
+ }
+
+ .icon-circle {
+ width: 48px;
+ height: 48px;
+ }
+
+ .icon-symbol {
+ font-size: 20px;
+ }
+
+ .modal-title {
+ font-size: 16px;
+ }
+
+ .modal-message {
+ font-size: 13px;
+ }
+}
diff --git a/h5/yumi-invite-bd/yumi-invite-bd.js b/h5/yumi-invite-bd/yumi-invite-bd.js
new file mode 100644
index 0000000..763787b
--- /dev/null
+++ b/h5/yumi-invite-bd/yumi-invite-bd.js
@@ -0,0 +1,699 @@
+(function () {
+ const API_BASE = "https://jvapi.haiyihy.com";
+ const BACK_ICON =
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAYAAABV7bNHAAAACXBIWXMAACE4AAAhOAFFljFgAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAGXSURBVHgB7dvBTcNAFIThB5xTQFwADVBBmqEnUgZQAAXAjRqgACgAj2wfECbJZXZnrPmkVRT5lF9ODn4vVRERERERETEaxnNb8cd+PA/jeZ3PY02xqG7KA+Ic6/eds5vfPxfRdelb4uxXrt0VmXqgU3Hgo8iUA52LA9SvF1yVpkviHOdDpRhIJg6oBZKKA0qB5OKASiDJOKAQSDYO9A4kHQd6BpKPA70CWcSBHoFs4kDrQFZxoGUguzjQKpBlHGgRyDYOsANZxwFmIPs4wAq0iTjACvRUG4gDjEeumDRsIg4wAn3VhjDmYt81jWOGf64vo5q3MsAaHOLDH2oa7q2xicQKhLvopTYQiTl63kQk9mzePlKL5QXrSK22O2wjtVx/sYzUej/ILlKPBSqrSL02zGwi9VzBs4jUe0dRPpLCEqd0JJUtV9lISmvAkpHU9qTlIikukktFUt20vzQSHu++F5HqGvDi3PgIgQ5FpL5p/zme+/l1za7IHP6rcSoSfdPeIRCsRcIPtM18rSUMJoeKiIiIiIjw9QNKh3OJhFQBoAAAAABJRU5ErkJggg==";
+ const DEFAULT_AVATAR = "../assets/defaultAvatar-CdxWBK1k-1776148661448.png";
+ const ENDPOINTS = {
+ invitedList: "/team/bd/invite-bd-message-own",
+ invite: "/team/bd/invite-bd",
+ cancelPrefix: "/team/bd/invite-bd-cancel/",
+ };
+
+ const TEXT = {
+ pageTitle: "Invite User To Become BD",
+ language: "English",
+ placeholder: "Enter User ID",
+ search: "Search",
+ invite: "Invite",
+ idlePrompt: "please input user id",
+ noUsersFound: "No users found",
+ information: "Information:",
+ userIdPrefix: "User ID:",
+ pending: "Pending",
+ success: "Success",
+ cancel: "Cancel",
+ invitationSubmitted: "Invitation submitted",
+ applicationCancelled: "Application cancelled",
+ somethingWentWrong: "Something went wrong",
+ cancellationFailed: "Cancellation failed, try again",
+ informationTitle: "Information",
+ successTitle: "Success",
+ errorTitle: "Error",
+ ok: "OK",
+ };
+
+ const state = {
+ query: "",
+ invitedList: [],
+ searchResults: [],
+ showSearchResults: false,
+ searching: false,
+ hasSearched: false,
+ };
+
+ const dom = {
+ statusBarPlaceholder: document.getElementById("statusBarPlaceholder"),
+ backButton: document.getElementById("backButton"),
+ backButtonIcon: document.getElementById("backButtonIcon"),
+ pageTitle: document.getElementById("pageTitle"),
+ languageEntry: document.getElementById("languageEntry"),
+ languageName: document.getElementById("languageName"),
+ searchInput: document.getElementById("searchInput"),
+ clearButton: document.getElementById("clearButton"),
+ searchButton: document.getElementById("searchButton"),
+ resultList: document.getElementById("resultList"),
+ noData: document.getElementById("noData"),
+ userCardTemplate: document.getElementById("userCardTemplate"),
+ };
+
+ init();
+
+ function init() {
+ document.title = TEXT.pageTitle;
+ document.documentElement.lang = "en";
+ document.documentElement.dir = resolveDocumentDirection();
+
+ dom.backButtonIcon.src = BACK_ICON;
+ dom.pageTitle.textContent = TEXT.pageTitle;
+ dom.languageName.textContent = TEXT.language;
+ dom.searchInput.placeholder = TEXT.placeholder;
+ dom.searchButton.textContent = TEXT.search;
+ dom.noData.textContent = TEXT.idlePrompt;
+
+ syncStatusBarPlaceholder();
+ bindEvents();
+ render();
+ loadInvitedList();
+ }
+
+ function bindEvents() {
+ dom.backButton.addEventListener("click", handleBack);
+ dom.languageEntry.addEventListener("click", handleLanguageClick);
+ dom.searchInput.addEventListener("input", handleSearchInput);
+ dom.clearButton.addEventListener("click", clearSearch);
+ dom.searchButton.addEventListener("click", triggerSearchNow);
+ }
+
+ function resolveDocumentDirection() {
+ const lang = (new URLSearchParams(window.location.search).get("lang") || "").toLowerCase();
+ return lang.startsWith("ar") ? "rtl" : "ltr";
+ }
+
+ function syncStatusBarPlaceholder() {
+ const hasAppBridge =
+ Boolean(window.app) ||
+ Boolean(window.FlutterPageControl) ||
+ Boolean(window.webkit && window.webkit.messageHandlers);
+ const isIOS = /iphone|ipad|ipod/i.test(window.navigator.userAgent || "");
+ dom.statusBarPlaceholder.classList.toggle("is-visible", hasAppBridge && isIOS);
+ }
+
+ function handleBack() {
+ if (window.history.length > 1) {
+ window.history.back();
+ return;
+ }
+
+ window.location.href = "/";
+ }
+
+ function handleLanguageClick() {
+ window.location.href = "/language";
+ }
+
+ function handleSearchInput(event) {
+ state.query = event.target.value;
+ dom.clearButton.hidden = !state.query;
+ state.showSearchResults = false;
+ state.hasSearched = false;
+ render();
+ }
+
+ function clearSearch() {
+ state.query = "";
+ state.searchResults = [];
+ state.showSearchResults = false;
+ state.hasSearched = false;
+ dom.searchInput.value = "";
+ dom.clearButton.hidden = true;
+ render();
+ }
+
+ async function triggerSearchNow() {
+ if (state.searching) {
+ return;
+ }
+
+ const query = state.query.trim();
+
+ if (!query) {
+ state.showSearchResults = false;
+ state.hasSearched = false;
+ render();
+ return;
+ }
+
+ state.searching = true;
+ state.showSearchResults = true;
+ state.hasSearched = true;
+ state.searchResults = [];
+ render();
+
+ try {
+ const payload = await searchUser(query);
+ state.searchResults = payload ? [mergeWithInvitationStatus(payload.userProfile)] : [];
+ } catch (error) {
+ state.searchResults = [];
+ showToast(extractErrorMessage(error), {
+ title: TEXT.errorTitle,
+ type: "error",
+ });
+ } finally {
+ state.searching = false;
+ render();
+ }
+ }
+
+ async function loadInvitedList() {
+ try {
+ const response = await request("GET", ENDPOINTS.invitedList);
+ state.invitedList = response && response.status && Array.isArray(response.body) ? response.body : [];
+ state.searchResults = state.searchResults.map(function (item) {
+ return mergeWithInvitationStatus(item.userProfile || {});
+ });
+ render();
+ } catch (error) {
+ state.invitedList = [];
+ render();
+ }
+ }
+
+ async function searchUser(query) {
+ try {
+ const response = await request(
+ "GET",
+ "/user/user-profile/open-search?account=" + encodeURIComponent(query)
+ );
+
+ if (response && response.status && response.body) {
+ return { userProfile: response.body };
+ }
+ } catch (error) {
+ if (!/^\d+$/.test(query)) {
+ throw error;
+ }
+ }
+
+ if (!/^\d+$/.test(query)) {
+ return null;
+ }
+
+ const fallbackResponse = await request(
+ "GET",
+ "/user/user-profile?userId=" + encodeURIComponent(query)
+ );
+
+ if (fallbackResponse && fallbackResponse.status && fallbackResponse.body) {
+ return { userProfile: fallbackResponse.body };
+ }
+
+ return null;
+ }
+
+ function mergeWithInvitationStatus(userProfile) {
+ const matchedInvitation = state.invitedList.find(function (item) {
+ return (
+ item &&
+ item.userProfile &&
+ userProfile &&
+ item.userProfile.id === userProfile.id
+ );
+ });
+
+ return Object.assign({}, matchedInvitation || {}, {
+ userProfile: userProfile || {},
+ });
+ }
+
+ async function inviteUser(item) {
+ if (!item || !item.userProfile || !item.userProfile.id) {
+ return;
+ }
+
+ try {
+ const response = await request("POST", ENDPOINTS.invite, {
+ body: {
+ inviteUserId: item.userProfile.id,
+ },
+ });
+
+ if (response && response.status) {
+ showToast(TEXT.invitationSubmitted, {
+ title: TEXT.successTitle,
+ type: "success",
+ });
+ await loadInvitedList();
+ }
+ } catch (error) {
+ showToast(extractErrorMessage(error, TEXT.somethingWentWrong), {
+ title: TEXT.errorTitle,
+ type: "error",
+ });
+ }
+ }
+
+ async function cancelInvitation(invitationId) {
+ try {
+ const response = await request("POST", ENDPOINTS.cancelPrefix + invitationId);
+
+ if (response && response.status) {
+ showToast(TEXT.applicationCancelled, {
+ title: TEXT.informationTitle,
+ type: "info",
+ });
+ await loadInvitedList();
+ }
+ } catch (error) {
+ showToast(extractErrorMessage(error, TEXT.cancellationFailed), {
+ title: TEXT.errorTitle,
+ type: "error",
+ });
+ }
+ }
+
+ function render() {
+ renderSearchButton();
+ renderList();
+ }
+
+ function renderSearchButton() {
+ dom.searchButton.disabled = !state.query.trim() || state.searching;
+ }
+
+ function renderList() {
+ const currentList = state.showSearchResults ? state.searchResults : state.invitedList;
+ dom.resultList.innerHTML = "";
+
+ currentList.forEach(function (item) {
+ dom.resultList.appendChild(createUserCard(item, state.showSearchResults ? "search" : "invited"));
+ });
+
+ if (currentList.length > 0 || (state.searching && state.showSearchResults)) {
+ dom.noData.hidden = true;
+ return;
+ }
+
+ dom.noData.hidden = false;
+ dom.noData.textContent =
+ state.showSearchResults && state.hasSearched ? TEXT.noUsersFound : TEXT.idlePrompt;
+ }
+
+ function createUserCard(item, mode) {
+ const fragment = dom.userCardTemplate.content.cloneNode(true);
+ const statusBadge = fragment.querySelector(".status-badge");
+ const avatarImage = fragment.querySelector(".avatar-image");
+ const nickname = fragment.querySelector(".nickname");
+ const account = fragment.querySelector(".account");
+ const pendingActions = fragment.querySelector(".pending-actions");
+ const userProfile = item.userProfile || {};
+
+ avatarImage.src = userProfile.userAvatar || DEFAULT_AVATAR;
+ avatarImage.alt = userProfile.userNickname || "";
+ avatarImage.onerror = handleAvatarError;
+ nickname.textContent = userProfile.userNickname || "";
+ account.textContent = TEXT.userIdPrefix + " " + (userProfile.account || userProfile.id || "");
+
+ if (item.status === 0) {
+ statusBadge.innerHTML =
+ '' +
+ TEXT.pending +
+ "
";
+ } else if (item.status === 1) {
+ statusBadge.innerHTML =
+ '' +
+ TEXT.success +
+ "
";
+ }
+
+ if (mode === "search") {
+ const inviteButton = document.createElement("button");
+ inviteButton.type = "button";
+ inviteButton.className = "result-action-btn";
+ inviteButton.textContent = TEXT.invite;
+ inviteButton.disabled = item.status === 0 || item.status === 1;
+ inviteButton.addEventListener("click", function (event) {
+ event.stopPropagation();
+ inviteUser(item);
+ });
+ pendingActions.appendChild(inviteButton);
+ } else if (item.status === 0) {
+ const cancelButton = document.createElement("div");
+ cancelButton.textContent = TEXT.cancel;
+ cancelButton.style.padding = "4px 8px";
+ cancelButton.style.borderRadius = "32px";
+ cancelButton.style.backgroundColor = "red";
+ cancelButton.style.color = "white";
+ cancelButton.style.fontWeight = "600";
+ cancelButton.style.zIndex = "5";
+ cancelButton.addEventListener("click", function (event) {
+ event.stopPropagation();
+ cancelInvitation(item.id);
+ });
+ pendingActions.appendChild(cancelButton);
+ }
+
+ return fragment;
+ }
+
+ function handleAvatarError(event) {
+ event.target.onerror = null;
+ event.target.src = DEFAULT_AVATAR;
+ }
+
+ function extractErrorMessage(error, fallback) {
+ return (
+ (error &&
+ error.response &&
+ (error.response.errorMsg || error.response.message || error.response.error)) ||
+ (error && error.message) ||
+ fallback ||
+ TEXT.somethingWentWrong
+ );
+ }
+
+ function showToast(message, options) {
+ const config = Object.assign(
+ {
+ title: TEXT.informationTitle,
+ type: "info",
+ confirmText: TEXT.ok,
+ },
+ options || {}
+ );
+
+ const iconMap = {
+ error: "✕",
+ warning: "⚠",
+ success: "✓",
+ info: "i",
+ simple: "",
+ };
+
+ const overlay = document.createElement("div");
+ overlay.className = "modal-overlay";
+ overlay.innerHTML =
+ '' +
+ (config.type === "simple"
+ ? ""
+ : '
' +
+ iconMap[config.type] +
+ "
") +
+ (config.type === "simple" || !config.title
+ ? ""
+ : '
' + escapeHtml(config.title) + "
") +
+ '
' +
+ escapeHtml(message) +
+ "
" +
+ '
" +
+ "
";
+
+ const modal = overlay.querySelector(".modal");
+ const closeButton = overlay.querySelector(".modal-btn");
+ const close = function () {
+ modal.classList.remove("modal-enter");
+ modal.classList.add("modal-leave");
+ window.setTimeout(function () {
+ overlay.remove();
+ }, 200);
+ };
+
+ closeButton.addEventListener("click", close);
+ overlay.addEventListener("click", function (event) {
+ if (event.target === overlay) {
+ close();
+ }
+ });
+
+ document.body.appendChild(overlay);
+ }
+
+ function escapeHtml(value) {
+ return String(value)
+ .replace(/&/g, "&")
+ .replace(//g, ">")
+ .replace(/"/g, """)
+ .replace(/'/g, "'");
+ }
+
+ async function request(method, path, options) {
+ const config = options || {};
+ const headers = buildRequestHeaders(Boolean(config.body), config.headers || {});
+ const response = await fetch(API_BASE + path, {
+ method: method,
+ credentials: "include",
+ headers: headers,
+ body: config.body ? JSON.stringify(config.body) : undefined,
+ });
+ const text = await response.text();
+ let payload = {};
+
+ if (text) {
+ try {
+ payload = JSON.parse(text);
+ } catch (error) {
+ payload = {
+ status: response.ok,
+ body: text,
+ };
+ }
+ }
+
+ if (!response.ok || payload.status === false) {
+ const requestError = new Error(
+ payload.errorMsg || payload.message || response.statusText || TEXT.somethingWentWrong
+ );
+ requestError.response = payload;
+ throw requestError;
+ }
+
+ return payload;
+ }
+
+ function buildRequestHeaders(hasBody, overrideHeaders) {
+ const discovered = discoverAppHeaders();
+ const headers = Object.assign({}, overrideHeaders || {});
+
+ if (hasBody) {
+ headers["Content-Type"] = headers["Content-Type"] || "application/json";
+ }
+
+ headers.Accept = headers.Accept || "application/json, text/plain, */*";
+
+ if (discovered.authorization) {
+ headers.Authorization = headers.Authorization || discovered.authorization;
+ }
+
+ if (discovered.reqLang) {
+ headers["Req-Lang"] = headers["Req-Lang"] || discovered.reqLang;
+ }
+
+ if (discovered.appVersion) {
+ headers["App-Version"] = headers["App-Version"] || discovered.appVersion;
+ }
+
+ if (discovered.buildVersion) {
+ headers["Build-Version"] = headers["Build-Version"] || discovered.buildVersion;
+ }
+
+ if (discovered.appChannel) {
+ headers["App-Channel"] = headers["App-Channel"] || discovered.appChannel;
+ }
+
+ if (discovered.reqImei) {
+ headers["Req-Imei"] = headers["Req-Imei"] || discovered.reqImei;
+ }
+
+ if (discovered.sysOrigin) {
+ headers["Sys-Origin"] = headers["Sys-Origin"] || discovered.sysOrigin;
+ }
+
+ if (discovered.sysOriginChild) {
+ headers["Sys-Origin-Child"] =
+ headers["Sys-Origin-Child"] || discovered.sysOriginChild;
+ }
+
+ return headers;
+ }
+
+ function discoverAppHeaders() {
+ const query = new URLSearchParams(window.location.search);
+ const collected = [];
+
+ collectCandidate(collected, window.__APP_HEADERS__);
+ collectCandidate(collected, window.__HEADER_INFO__);
+ collectCandidate(collected, window.headerInfo);
+ collectCandidate(collected, parseHeaderObjectFromQuery(query));
+
+ collectFromStorage(collected, window.localStorage);
+ collectFromStorage(collected, window.sessionStorage);
+
+ return collected.reduce(function (result, candidate) {
+ return Object.assign(result, candidate);
+ }, {
+ reqLang: query.get("lang") || document.documentElement.lang || "en",
+ });
+ }
+
+ function parseHeaderObjectFromQuery(query) {
+ const candidate = {};
+ mapHeaderValue(candidate, "authorization", query.get("authorization"));
+ mapHeaderValue(candidate, "authorization", query.get("token"));
+ mapHeaderValue(candidate, "reqLang", query.get("lang"));
+ mapHeaderValue(candidate, "appVersion", query.get("appVersion"));
+ mapHeaderValue(candidate, "buildVersion", query.get("buildVersion"));
+ mapHeaderValue(candidate, "appChannel", query.get("appChannel"));
+ mapHeaderValue(candidate, "reqImei", query.get("reqImei"));
+ mapHeaderValue(candidate, "sysOrigin", query.get("sysOrigin"));
+ mapHeaderValue(candidate, "sysOriginChild", query.get("sysOriginChild"));
+ return candidate;
+ }
+
+ function collectFromStorage(collected, storage) {
+ if (!storage) {
+ return;
+ }
+
+ const preferredKeys = [
+ "authorization",
+ "Authorization",
+ "token",
+ "accessToken",
+ "headerInfo",
+ "headersFromApp",
+ "appHeaders",
+ "persist:root",
+ "user",
+ "userInfo",
+ ];
+
+ preferredKeys.forEach(function (key) {
+ try {
+ collectCandidate(collected, storage.getItem(key));
+ } catch (error) {
+ return;
+ }
+ });
+
+ for (let index = 0; index < storage.length; index += 1) {
+ try {
+ const key = storage.key(index);
+ collectCandidate(collected, storage.getItem(key));
+ } catch (error) {
+ return;
+ }
+ }
+ }
+
+ function collectCandidate(collected, value) {
+ const normalized = normalizeHeaderCandidate(value, 0);
+ if (normalized && Object.keys(normalized).length > 0) {
+ collected.push(normalized);
+ }
+ }
+
+ function normalizeHeaderCandidate(value, depth) {
+ if (depth > 4 || value == null) {
+ return null;
+ }
+
+ if (typeof value === "string") {
+ const trimmed = value.trim();
+
+ if (!trimmed) {
+ return null;
+ }
+
+ if (trimmed[0] === "{" || trimmed[0] === "[") {
+ try {
+ return normalizeHeaderCandidate(JSON.parse(trimmed), depth + 1);
+ } catch (error) {
+ return null;
+ }
+ }
+
+ if (/bearer\\s+/i.test(trimmed)) {
+ return {
+ authorization: trimmed,
+ };
+ }
+
+ return null;
+ }
+
+ if (Array.isArray(value)) {
+ return value.reduce(function (result, entry) {
+ const normalized = normalizeHeaderCandidate(entry, depth + 1);
+ return normalized ? Object.assign(result, normalized) : result;
+ }, {});
+ }
+
+ if (typeof value !== "object") {
+ return null;
+ }
+
+ const normalized = {};
+ const aliasMap = {
+ authorization: ["authorization", "Authorization", "token", "accessToken"],
+ reqLang: ["reqLang", "Req-Lang", "lang", "language"],
+ appVersion: ["appVersion", "App-Version"],
+ buildVersion: ["buildVersion", "Build-Version"],
+ appChannel: ["appChannel", "App-Channel"],
+ reqImei: ["reqImei", "Req-Imei"],
+ sysOrigin: ["sysOrigin", "Sys-Origin"],
+ sysOriginChild: ["sysOriginChild", "Sys-Origin-Child"],
+ };
+
+ Object.keys(aliasMap).forEach(function (targetKey) {
+ aliasMap[targetKey].forEach(function (sourceKey) {
+ mapHeaderValue(normalized, targetKey, value[sourceKey]);
+ });
+ });
+
+ ["headerInfo", "headers", "auth", "data", "state"].forEach(function (nestedKey) {
+ const nestedValue = normalizeHeaderCandidate(value[nestedKey], depth + 1);
+ if (nestedValue) {
+ Object.assign(normalized, nestedValue);
+ }
+ });
+
+ Object.keys(value).forEach(function (key) {
+ if (
+ key === "headerInfo" ||
+ key === "headers" ||
+ key === "auth" ||
+ key === "data" ||
+ key === "state"
+ ) {
+ return;
+ }
+
+ if (typeof value[key] === "object") {
+ const nestedValue = normalizeHeaderCandidate(value[key], depth + 1);
+ if (nestedValue) {
+ Object.assign(normalized, nestedValue);
+ }
+ }
+ });
+
+ return normalized;
+ }
+
+ function mapHeaderValue(target, key, value) {
+ if (value == null || value === "" || target[key]) {
+ return;
+ }
+
+ target[key] = String(value);
+ }
+})();
diff --git a/h5/yumi-invite-recharge-agency/index.html b/h5/yumi-invite-recharge-agency/index.html
new file mode 100644
index 0000000..8cc7a8e
--- /dev/null
+++ b/h5/yumi-invite-recharge-agency/index.html
@@ -0,0 +1,119 @@
+
+
+
+
+
+ Invite User To Become Recharge Agent
+
+
+
+
+
+
+
+
+
+
+
Information:
+
+
+
+
![]()
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/h5/yumi-invite-recharge-agency/yumi-invite-recharge-agency.css b/h5/yumi-invite-recharge-agency/yumi-invite-recharge-agency.css
new file mode 100644
index 0000000..9d8eff2
--- /dev/null
+++ b/h5/yumi-invite-recharge-agency/yumi-invite-recharge-agency.css
@@ -0,0 +1,456 @@
+html {
+ -webkit-text-size-adjust: 100%;
+ -webkit-overflow-scrolling: touch;
+}
+
+body {
+ margin: 0;
+ min-height: 100%;
+ font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Helvetica Neue", Arial, sans-serif;
+}
+
+* {
+ box-sizing: border-box;
+}
+
+button,
+input {
+ font: inherit;
+}
+
+[hidden] {
+ display: none !important;
+}
+
+.fullPage {
+ width: 100vw;
+ min-height: 100vh;
+ background-color: #fff;
+ background-image: url("../assets/secondBg-CSqvFWr0-1776148661447.png");
+ background-size: 100% auto;
+ background-repeat: no-repeat;
+ position: relative;
+ color: rgba(0, 0, 0, 0.8);
+}
+
+.fullPage input::placeholder {
+ font-weight: 700;
+ color: rgba(0, 0, 0, 0.4);
+}
+
+.invite-btn {
+ padding: 4px 12px;
+ border-radius: 32px;
+ background: linear-gradient(269deg, #feb219 7.04%, #ff9326 96.78%);
+ color: #fff;
+ border: none;
+ font-weight: 600;
+ cursor: pointer;
+ transition: all 0.2s;
+}
+
+.invite-btn:disabled {
+ background: #d1d5db;
+ cursor: not-allowed;
+}
+
+.no-data {
+ text-align: center;
+ padding: 40px 20px;
+ color: #666;
+}
+
+.user-card {
+ cursor: default;
+}
+
+.result-action-btn {
+ padding: 4px 10px;
+ border-radius: 32px;
+ background: linear-gradient(269deg, #feb219 7.04%, #ff9326 96.78%);
+ color: #fff;
+ border: none;
+ font-weight: 600;
+ cursor: pointer;
+ transition: all 0.2s;
+ white-space: nowrap;
+}
+
+.result-action-btn:disabled {
+ background: #d1d5db;
+ cursor: not-allowed;
+}
+
+.status-bar-placeholder {
+ display: none;
+ height: 30px;
+}
+
+.status-bar-placeholder.is-visible {
+ display: block;
+}
+
+.header-container {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 12px 16px;
+ height: 60px;
+ font-size: 16px;
+}
+
+.side-area,
+.actions-area {
+ min-width: 1.5em;
+ display: flex;
+ align-items: center;
+}
+
+.actions-area {
+ justify-content: flex-end;
+ gap: 8px;
+}
+
+.header-title {
+ flex: 1;
+ margin: 0;
+ font-size: 1.2em;
+ font-weight: 600;
+ text-align: center;
+ letter-spacing: 0.3px;
+}
+
+.back-btn,
+.help-btn {
+ width: 1.5em;
+ border: none;
+ background: transparent;
+ transition: all 0.2s ease;
+ padding: 0;
+}
+
+.back-btn:active,
+.help-btn:active {
+ transform: scale(0.9);
+}
+
+.language-entry {
+ display: flex;
+ align-items: center;
+ color: #f59e0b !important;
+ cursor: pointer;
+}
+
+.language-name {
+ font-weight: 700;
+}
+
+.gradient-border-wrapper {
+ position: relative;
+}
+
+.gradient-border-wrapper::before {
+ content: "";
+ position: absolute;
+ inset: 0;
+ border-radius: inherit;
+ padding: var(--gradient-border-width, 1.5px);
+ background: linear-gradient(
+ var(--gradient-direction, to bottom),
+ var(--gradient-start-color, #ffc4c4),
+ var(--gradient-end-color, #fff6a6)
+ );
+ -webkit-mask:
+ linear-gradient(#fff 0 0) content-box,
+ linear-gradient(#fff 0 0);
+ -webkit-mask-composite: xor;
+ mask-composite: exclude;
+ pointer-events: none;
+}
+
+.gradient-border-content {
+ position: relative;
+ border-radius: inherit;
+ width: 100%;
+ height: 100%;
+ background: var(
+ --gradient-background,
+ linear-gradient(120deg, rgba(255, 216, 0, 0.1) 39.13%, rgba(255, 149, 0, 0.1) 119.28%)
+ );
+}
+
+.modal-overlay {
+ position: fixed;
+ inset: 0;
+ background-color: rgba(0, 0, 0, 0.6);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 9999;
+ padding: 20px;
+}
+
+.modal {
+ background: #fff;
+ border-radius: 16px;
+ box-shadow:
+ 0 20px 25px rgba(0, 0, 0, 0.1),
+ 0 10px 10px rgba(0, 0, 0, 0.04);
+ width: 100%;
+ max-width: 320px;
+ padding: 24px 20px 20px;
+ text-align: center;
+ position: relative;
+}
+
+.modal-icon {
+ margin-bottom: 16px;
+ display: flex;
+ justify-content: center;
+}
+
+.icon-circle {
+ width: 56px;
+ height: 56px;
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ animation: iconPulse 0.6s ease-out;
+ border: 3px solid;
+}
+
+.icon-symbol {
+ font-size: 24px;
+ font-weight: 700;
+ line-height: 1;
+}
+
+.modal-title {
+ font-size: 18px;
+ font-weight: 600;
+ color: #1f2937;
+ margin-bottom: 12px;
+ line-height: 1.4;
+}
+
+.modal-message {
+ font-size: 14px;
+ color: #6b7280;
+ line-height: 1.5;
+ margin-bottom: 20px;
+ word-wrap: break-word;
+}
+
+.modal-actions {
+ display: flex;
+ justify-content: center;
+}
+
+.modal-btn {
+ border: none;
+ border-radius: 8px;
+ padding: 10px 32px;
+ font-size: 14px;
+ font-weight: 600;
+ cursor: pointer;
+ transition: all 0.2s;
+ min-width: 80px;
+ color: #fff;
+}
+
+.modal-btn:active {
+ transform: scale(0.98);
+}
+
+.modal-error .icon-circle-error {
+ background-color: #fee2e2;
+ border-color: #fecaca;
+}
+
+.modal-error .icon-symbol-error {
+ color: #dc2626;
+}
+
+.modal-error .modal-btn-error {
+ background-color: #dc2626;
+}
+
+.modal-warning .icon-circle-warning {
+ background-color: #fef3c7;
+ border-color: #fde68a;
+}
+
+.modal-warning .icon-symbol-warning {
+ color: #d97706;
+}
+
+.modal-warning .modal-btn-warning {
+ background-color: #d97706;
+}
+
+.modal-success .icon-circle-success {
+ background-color: #d1fae5;
+ border-color: #a7f3d0;
+}
+
+.modal-success .icon-symbol-success {
+ color: #059669;
+}
+
+.modal-success .modal-btn-success {
+ background-color: #059669;
+}
+
+.modal-info .icon-circle-info {
+ background-color: #dbeafe;
+ border-color: #bfdbfe;
+}
+
+.modal-info .icon-symbol-info {
+ color: #2563eb;
+}
+
+.modal-info .modal-btn-info {
+ background-color: #2563eb;
+}
+
+.modal-simple .modal-message {
+ font-size: 15px;
+ color: #374151;
+ margin-bottom: 24px;
+}
+
+.modal-simple .modal-btn {
+ background-color: #2563eb;
+}
+
+.modal-enter {
+ animation: modalEnter 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
+}
+
+.modal-leave {
+ animation: modalLeave 0.2s ease-in;
+}
+
+[dir="rtl"] .flip-img {
+ transform: scaleX(-1);
+}
+
+[dir="rtl"] .avatar {
+ margin-right: 0;
+ margin-left: 12px;
+}
+
+[dir="rtl"] .user-info {
+ text-align: right;
+}
+
+[dir="rtl"] .language-entry,
+[dir="rtl"] .header-title {
+ direction: rtl;
+}
+
+@keyframes modalEnter {
+ 0% {
+ opacity: 0;
+ transform: scale(0.7) translateY(-10px);
+ }
+
+ 100% {
+ opacity: 1;
+ transform: scale(1) translateY(0);
+ }
+}
+
+@keyframes modalLeave {
+ 0% {
+ opacity: 1;
+ transform: scale(1) translateY(0);
+ }
+
+ 100% {
+ opacity: 0;
+ transform: scale(0.9) translateY(-5px);
+ }
+}
+
+@keyframes iconPulse {
+ 0% {
+ transform: scale(0.8);
+ opacity: 0.5;
+ }
+
+ 50% {
+ transform: scale(1.1);
+ }
+
+ 100% {
+ transform: scale(1);
+ opacity: 1;
+ }
+}
+
+@media screen and (max-width: 360px) {
+ .fullPage {
+ font-size: 10px;
+ }
+
+ .header-container {
+ font-size: 10px;
+ }
+}
+
+@media screen and (min-width: 360px) {
+ .fullPage {
+ font-size: 12px;
+ }
+
+ .header-container {
+ font-size: 16px;
+ }
+}
+
+@media screen and (min-width: 768px) {
+ .fullPage {
+ font-size: 24px;
+ }
+
+ .header-container {
+ font-size: 24px;
+ }
+}
+
+@media screen and (min-width: 1024px) {
+ .fullPage {
+ font-size: 32px;
+ }
+
+ .header-container {
+ font-size: 32px;
+ }
+}
+
+@media (max-width: 480px) {
+ .modal {
+ max-width: 280px;
+ padding: 20px 16px 16px;
+ }
+
+ .icon-circle {
+ width: 48px;
+ height: 48px;
+ }
+
+ .icon-symbol {
+ font-size: 20px;
+ }
+
+ .modal-title {
+ font-size: 16px;
+ }
+
+ .modal-message {
+ font-size: 13px;
+ }
+}
diff --git a/h5/yumi-invite-recharge-agency/yumi-invite-recharge-agency.js b/h5/yumi-invite-recharge-agency/yumi-invite-recharge-agency.js
new file mode 100644
index 0000000..64453ca
--- /dev/null
+++ b/h5/yumi-invite-recharge-agency/yumi-invite-recharge-agency.js
@@ -0,0 +1,699 @@
+(function () {
+ const API_BASE = "https://jvapi.haiyihy.com";
+ const BACK_ICON =
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAYAAABV7bNHAAAACXBIWXMAACE4AAAhOAFFljFgAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAGXSURBVHgB7dvBTcNAFIThB5xTQFwADVBBmqEnUgZQAAXAjRqgACgAj2wfECbJZXZnrPmkVRT5lF9ODn4vVRERERERETEaxnNb8cd+PA/jeZ3PY02xqG7KA+Ic6/eds5vfPxfRdelb4uxXrt0VmXqgU3Hgo8iUA52LA9SvF1yVpkviHOdDpRhIJg6oBZKKA0qB5OKASiDJOKAQSDYO9A4kHQd6BpKPA70CWcSBHoFs4kDrQFZxoGUguzjQKpBlHGgRyDYOsANZxwFmIPs4wAq0iTjACvRUG4gDjEeumDRsIg4wAn3VhjDmYt81jWOGf64vo5q3MsAaHOLDH2oa7q2xicQKhLvopTYQiTl63kQk9mzePlKL5QXrSK22O2wjtVx/sYzUej/ILlKPBSqrSL02zGwi9VzBs4jUe0dRPpLCEqd0JJUtV9lISmvAkpHU9qTlIikukktFUt20vzQSHu++F5HqGvDi3PgIgQ5FpL5p/zme+/l1za7IHP6rcSoSfdPeIRCsRcIPtM18rSUMJoeKiIiIiIjw9QNKh3OJhFQBoAAAAABJRU5ErkJggg==";
+ const DEFAULT_AVATAR = "../assets/defaultAvatar-CdxWBK1k-1776148661448.png";
+ const ENDPOINTS = {
+ invitedList: "/team/bd/invite-recharge-agent-message-own",
+ invite: "/team/bd/invite-recharge-agent",
+ cancelPrefix: "/team/bd/invite-recharge-agent-cancel/",
+ };
+
+ const TEXT = {
+ pageTitle: "Invite User To Become Recharge Agent",
+ language: "English",
+ placeholder: "Enter User ID",
+ search: "Search",
+ invite: "Invite",
+ idlePrompt: "please input user id",
+ noUsersFound: "No users found",
+ information: "Information:",
+ userIdPrefix: "User ID:",
+ pending: "Pending",
+ success: "Success",
+ cancel: "Cancel",
+ invitationSubmitted: "Invitation submitted",
+ applicationCancelled: "Application cancelled",
+ somethingWentWrong: "Something went wrong",
+ cancellationFailed: "Cancellation failed, try again",
+ informationTitle: "Information",
+ successTitle: "Success",
+ errorTitle: "Error",
+ ok: "OK",
+ };
+
+ const state = {
+ query: "",
+ invitedList: [],
+ searchResults: [],
+ showSearchResults: false,
+ searching: false,
+ hasSearched: false,
+ };
+
+ const dom = {
+ statusBarPlaceholder: document.getElementById("statusBarPlaceholder"),
+ backButton: document.getElementById("backButton"),
+ backButtonIcon: document.getElementById("backButtonIcon"),
+ pageTitle: document.getElementById("pageTitle"),
+ languageEntry: document.getElementById("languageEntry"),
+ languageName: document.getElementById("languageName"),
+ searchInput: document.getElementById("searchInput"),
+ clearButton: document.getElementById("clearButton"),
+ searchButton: document.getElementById("searchButton"),
+ resultList: document.getElementById("resultList"),
+ noData: document.getElementById("noData"),
+ userCardTemplate: document.getElementById("userCardTemplate"),
+ };
+
+ init();
+
+ function init() {
+ document.title = TEXT.pageTitle;
+ document.documentElement.lang = "en";
+ document.documentElement.dir = resolveDocumentDirection();
+
+ dom.backButtonIcon.src = BACK_ICON;
+ dom.pageTitle.textContent = TEXT.pageTitle;
+ dom.languageName.textContent = TEXT.language;
+ dom.searchInput.placeholder = TEXT.placeholder;
+ dom.searchButton.textContent = TEXT.search;
+ dom.noData.textContent = TEXT.idlePrompt;
+
+ syncStatusBarPlaceholder();
+ bindEvents();
+ render();
+ loadInvitedList();
+ }
+
+ function bindEvents() {
+ dom.backButton.addEventListener("click", handleBack);
+ dom.languageEntry.addEventListener("click", handleLanguageClick);
+ dom.searchInput.addEventListener("input", handleSearchInput);
+ dom.clearButton.addEventListener("click", clearSearch);
+ dom.searchButton.addEventListener("click", triggerSearchNow);
+ }
+
+ function resolveDocumentDirection() {
+ const lang = (new URLSearchParams(window.location.search).get("lang") || "").toLowerCase();
+ return lang.startsWith("ar") ? "rtl" : "ltr";
+ }
+
+ function syncStatusBarPlaceholder() {
+ const hasAppBridge =
+ Boolean(window.app) ||
+ Boolean(window.FlutterPageControl) ||
+ Boolean(window.webkit && window.webkit.messageHandlers);
+ const isIOS = /iphone|ipad|ipod/i.test(window.navigator.userAgent || "");
+ dom.statusBarPlaceholder.classList.toggle("is-visible", hasAppBridge && isIOS);
+ }
+
+ function handleBack() {
+ if (window.history.length > 1) {
+ window.history.back();
+ return;
+ }
+
+ window.location.href = "/";
+ }
+
+ function handleLanguageClick() {
+ window.location.href = "/language";
+ }
+
+ function handleSearchInput(event) {
+ state.query = event.target.value;
+ dom.clearButton.hidden = !state.query;
+ state.showSearchResults = false;
+ state.hasSearched = false;
+ render();
+ }
+
+ function clearSearch() {
+ state.query = "";
+ state.searchResults = [];
+ state.showSearchResults = false;
+ state.hasSearched = false;
+ dom.searchInput.value = "";
+ dom.clearButton.hidden = true;
+ render();
+ }
+
+ async function triggerSearchNow() {
+ if (state.searching) {
+ return;
+ }
+
+ const query = state.query.trim();
+
+ if (!query) {
+ state.showSearchResults = false;
+ state.hasSearched = false;
+ render();
+ return;
+ }
+
+ state.searching = true;
+ state.showSearchResults = true;
+ state.hasSearched = true;
+ state.searchResults = [];
+ render();
+
+ try {
+ const payload = await searchUser(query);
+ state.searchResults = payload ? [mergeWithInvitationStatus(payload.userProfile)] : [];
+ } catch (error) {
+ state.searchResults = [];
+ showToast(extractErrorMessage(error), {
+ title: TEXT.errorTitle,
+ type: "error",
+ });
+ } finally {
+ state.searching = false;
+ render();
+ }
+ }
+
+ async function loadInvitedList() {
+ try {
+ const response = await request("GET", ENDPOINTS.invitedList);
+ state.invitedList = response && response.status && Array.isArray(response.body) ? response.body : [];
+ state.searchResults = state.searchResults.map(function (item) {
+ return mergeWithInvitationStatus(item.userProfile || {});
+ });
+ render();
+ } catch (error) {
+ state.invitedList = [];
+ render();
+ }
+ }
+
+ async function searchUser(query) {
+ try {
+ const response = await request(
+ "GET",
+ "/user/user-profile/open-search?account=" + encodeURIComponent(query)
+ );
+
+ if (response && response.status && response.body) {
+ return { userProfile: response.body };
+ }
+ } catch (error) {
+ if (!/^\d+$/.test(query)) {
+ throw error;
+ }
+ }
+
+ if (!/^\d+$/.test(query)) {
+ return null;
+ }
+
+ const fallbackResponse = await request(
+ "GET",
+ "/user/user-profile?userId=" + encodeURIComponent(query)
+ );
+
+ if (fallbackResponse && fallbackResponse.status && fallbackResponse.body) {
+ return { userProfile: fallbackResponse.body };
+ }
+
+ return null;
+ }
+
+ function mergeWithInvitationStatus(userProfile) {
+ const matchedInvitation = state.invitedList.find(function (item) {
+ return (
+ item &&
+ item.userProfile &&
+ userProfile &&
+ item.userProfile.id === userProfile.id
+ );
+ });
+
+ return Object.assign({}, matchedInvitation || {}, {
+ userProfile: userProfile || {},
+ });
+ }
+
+ async function inviteUser(item) {
+ if (!item || !item.userProfile || !item.userProfile.id) {
+ return;
+ }
+
+ try {
+ const response = await request("POST", ENDPOINTS.invite, {
+ body: {
+ inviteUserId: item.userProfile.id,
+ },
+ });
+
+ if (response && response.status) {
+ showToast(TEXT.invitationSubmitted, {
+ title: TEXT.successTitle,
+ type: "success",
+ });
+ await loadInvitedList();
+ }
+ } catch (error) {
+ showToast(extractErrorMessage(error, TEXT.somethingWentWrong), {
+ title: TEXT.errorTitle,
+ type: "error",
+ });
+ }
+ }
+
+ async function cancelInvitation(invitationId) {
+ try {
+ const response = await request("POST", ENDPOINTS.cancelPrefix + invitationId);
+
+ if (response && response.status) {
+ showToast(TEXT.applicationCancelled, {
+ title: TEXT.informationTitle,
+ type: "info",
+ });
+ await loadInvitedList();
+ }
+ } catch (error) {
+ showToast(extractErrorMessage(error, TEXT.cancellationFailed), {
+ title: TEXT.errorTitle,
+ type: "error",
+ });
+ }
+ }
+
+ function render() {
+ renderSearchButton();
+ renderList();
+ }
+
+ function renderSearchButton() {
+ dom.searchButton.disabled = !state.query.trim() || state.searching;
+ }
+
+ function renderList() {
+ const currentList = state.showSearchResults ? state.searchResults : state.invitedList;
+ dom.resultList.innerHTML = "";
+
+ currentList.forEach(function (item) {
+ dom.resultList.appendChild(createUserCard(item, state.showSearchResults ? "search" : "invited"));
+ });
+
+ if (currentList.length > 0 || (state.searching && state.showSearchResults)) {
+ dom.noData.hidden = true;
+ return;
+ }
+
+ dom.noData.hidden = false;
+ dom.noData.textContent =
+ state.showSearchResults && state.hasSearched ? TEXT.noUsersFound : TEXT.idlePrompt;
+ }
+
+ function createUserCard(item, mode) {
+ const fragment = dom.userCardTemplate.content.cloneNode(true);
+ const statusBadge = fragment.querySelector(".status-badge");
+ const avatarImage = fragment.querySelector(".avatar-image");
+ const nickname = fragment.querySelector(".nickname");
+ const account = fragment.querySelector(".account");
+ const pendingActions = fragment.querySelector(".pending-actions");
+ const userProfile = item.userProfile || {};
+
+ avatarImage.src = userProfile.userAvatar || DEFAULT_AVATAR;
+ avatarImage.alt = userProfile.userNickname || "";
+ avatarImage.onerror = handleAvatarError;
+ nickname.textContent = userProfile.userNickname || "";
+ account.textContent = TEXT.userIdPrefix + " " + (userProfile.account || userProfile.id || "");
+
+ if (item.status === 0) {
+ statusBadge.innerHTML =
+ '' +
+ TEXT.pending +
+ "
";
+ } else if (item.status === 1) {
+ statusBadge.innerHTML =
+ '' +
+ TEXT.success +
+ "
";
+ }
+
+ if (mode === "search") {
+ const inviteButton = document.createElement("button");
+ inviteButton.type = "button";
+ inviteButton.className = "result-action-btn";
+ inviteButton.textContent = TEXT.invite;
+ inviteButton.disabled = item.status === 0 || item.status === 1;
+ inviteButton.addEventListener("click", function (event) {
+ event.stopPropagation();
+ inviteUser(item);
+ });
+ pendingActions.appendChild(inviteButton);
+ } else if (item.status === 0) {
+ const cancelButton = document.createElement("div");
+ cancelButton.textContent = TEXT.cancel;
+ cancelButton.style.padding = "4px 8px";
+ cancelButton.style.borderRadius = "32px";
+ cancelButton.style.backgroundColor = "red";
+ cancelButton.style.color = "white";
+ cancelButton.style.fontWeight = "600";
+ cancelButton.style.zIndex = "5";
+ cancelButton.addEventListener("click", function (event) {
+ event.stopPropagation();
+ cancelInvitation(item.id);
+ });
+ pendingActions.appendChild(cancelButton);
+ }
+
+ return fragment;
+ }
+
+ function handleAvatarError(event) {
+ event.target.onerror = null;
+ event.target.src = DEFAULT_AVATAR;
+ }
+
+ function extractErrorMessage(error, fallback) {
+ return (
+ (error &&
+ error.response &&
+ (error.response.errorMsg || error.response.message || error.response.error)) ||
+ (error && error.message) ||
+ fallback ||
+ TEXT.somethingWentWrong
+ );
+ }
+
+ function showToast(message, options) {
+ const config = Object.assign(
+ {
+ title: TEXT.informationTitle,
+ type: "info",
+ confirmText: TEXT.ok,
+ },
+ options || {}
+ );
+
+ const iconMap = {
+ error: "✕",
+ warning: "⚠",
+ success: "✓",
+ info: "i",
+ simple: "",
+ };
+
+ const overlay = document.createElement("div");
+ overlay.className = "modal-overlay";
+ overlay.innerHTML =
+ '' +
+ (config.type === "simple"
+ ? ""
+ : '
' +
+ iconMap[config.type] +
+ "
") +
+ (config.type === "simple" || !config.title
+ ? ""
+ : '
' + escapeHtml(config.title) + "
") +
+ '
' +
+ escapeHtml(message) +
+ "
" +
+ '
" +
+ "
";
+
+ const modal = overlay.querySelector(".modal");
+ const closeButton = overlay.querySelector(".modal-btn");
+ const close = function () {
+ modal.classList.remove("modal-enter");
+ modal.classList.add("modal-leave");
+ window.setTimeout(function () {
+ overlay.remove();
+ }, 200);
+ };
+
+ closeButton.addEventListener("click", close);
+ overlay.addEventListener("click", function (event) {
+ if (event.target === overlay) {
+ close();
+ }
+ });
+
+ document.body.appendChild(overlay);
+ }
+
+ function escapeHtml(value) {
+ return String(value)
+ .replace(/&/g, "&")
+ .replace(//g, ">")
+ .replace(/"/g, """)
+ .replace(/'/g, "'");
+ }
+
+ async function request(method, path, options) {
+ const config = options || {};
+ const headers = buildRequestHeaders(Boolean(config.body), config.headers || {});
+ const response = await fetch(API_BASE + path, {
+ method: method,
+ credentials: "include",
+ headers: headers,
+ body: config.body ? JSON.stringify(config.body) : undefined,
+ });
+ const text = await response.text();
+ let payload = {};
+
+ if (text) {
+ try {
+ payload = JSON.parse(text);
+ } catch (error) {
+ payload = {
+ status: response.ok,
+ body: text,
+ };
+ }
+ }
+
+ if (!response.ok || payload.status === false) {
+ const requestError = new Error(
+ payload.errorMsg || payload.message || response.statusText || TEXT.somethingWentWrong
+ );
+ requestError.response = payload;
+ throw requestError;
+ }
+
+ return payload;
+ }
+
+ function buildRequestHeaders(hasBody, overrideHeaders) {
+ const discovered = discoverAppHeaders();
+ const headers = Object.assign({}, overrideHeaders || {});
+
+ if (hasBody) {
+ headers["Content-Type"] = headers["Content-Type"] || "application/json";
+ }
+
+ headers.Accept = headers.Accept || "application/json, text/plain, */*";
+
+ if (discovered.authorization) {
+ headers.Authorization = headers.Authorization || discovered.authorization;
+ }
+
+ if (discovered.reqLang) {
+ headers["Req-Lang"] = headers["Req-Lang"] || discovered.reqLang;
+ }
+
+ if (discovered.appVersion) {
+ headers["App-Version"] = headers["App-Version"] || discovered.appVersion;
+ }
+
+ if (discovered.buildVersion) {
+ headers["Build-Version"] = headers["Build-Version"] || discovered.buildVersion;
+ }
+
+ if (discovered.appChannel) {
+ headers["App-Channel"] = headers["App-Channel"] || discovered.appChannel;
+ }
+
+ if (discovered.reqImei) {
+ headers["Req-Imei"] = headers["Req-Imei"] || discovered.reqImei;
+ }
+
+ if (discovered.sysOrigin) {
+ headers["Sys-Origin"] = headers["Sys-Origin"] || discovered.sysOrigin;
+ }
+
+ if (discovered.sysOriginChild) {
+ headers["Sys-Origin-Child"] =
+ headers["Sys-Origin-Child"] || discovered.sysOriginChild;
+ }
+
+ return headers;
+ }
+
+ function discoverAppHeaders() {
+ const query = new URLSearchParams(window.location.search);
+ const collected = [];
+
+ collectCandidate(collected, window.__APP_HEADERS__);
+ collectCandidate(collected, window.__HEADER_INFO__);
+ collectCandidate(collected, window.headerInfo);
+ collectCandidate(collected, parseHeaderObjectFromQuery(query));
+
+ collectFromStorage(collected, window.localStorage);
+ collectFromStorage(collected, window.sessionStorage);
+
+ return collected.reduce(function (result, candidate) {
+ return Object.assign(result, candidate);
+ }, {
+ reqLang: query.get("lang") || document.documentElement.lang || "en",
+ });
+ }
+
+ function parseHeaderObjectFromQuery(query) {
+ const candidate = {};
+ mapHeaderValue(candidate, "authorization", query.get("authorization"));
+ mapHeaderValue(candidate, "authorization", query.get("token"));
+ mapHeaderValue(candidate, "reqLang", query.get("lang"));
+ mapHeaderValue(candidate, "appVersion", query.get("appVersion"));
+ mapHeaderValue(candidate, "buildVersion", query.get("buildVersion"));
+ mapHeaderValue(candidate, "appChannel", query.get("appChannel"));
+ mapHeaderValue(candidate, "reqImei", query.get("reqImei"));
+ mapHeaderValue(candidate, "sysOrigin", query.get("sysOrigin"));
+ mapHeaderValue(candidate, "sysOriginChild", query.get("sysOriginChild"));
+ return candidate;
+ }
+
+ function collectFromStorage(collected, storage) {
+ if (!storage) {
+ return;
+ }
+
+ const preferredKeys = [
+ "authorization",
+ "Authorization",
+ "token",
+ "accessToken",
+ "headerInfo",
+ "headersFromApp",
+ "appHeaders",
+ "persist:root",
+ "user",
+ "userInfo",
+ ];
+
+ preferredKeys.forEach(function (key) {
+ try {
+ collectCandidate(collected, storage.getItem(key));
+ } catch (error) {
+ return;
+ }
+ });
+
+ for (let index = 0; index < storage.length; index += 1) {
+ try {
+ const key = storage.key(index);
+ collectCandidate(collected, storage.getItem(key));
+ } catch (error) {
+ return;
+ }
+ }
+ }
+
+ function collectCandidate(collected, value) {
+ const normalized = normalizeHeaderCandidate(value, 0);
+ if (normalized && Object.keys(normalized).length > 0) {
+ collected.push(normalized);
+ }
+ }
+
+ function normalizeHeaderCandidate(value, depth) {
+ if (depth > 4 || value == null) {
+ return null;
+ }
+
+ if (typeof value === "string") {
+ const trimmed = value.trim();
+
+ if (!trimmed) {
+ return null;
+ }
+
+ if (trimmed[0] === "{" || trimmed[0] === "[") {
+ try {
+ return normalizeHeaderCandidate(JSON.parse(trimmed), depth + 1);
+ } catch (error) {
+ return null;
+ }
+ }
+
+ if (/bearer\\s+/i.test(trimmed)) {
+ return {
+ authorization: trimmed,
+ };
+ }
+
+ return null;
+ }
+
+ if (Array.isArray(value)) {
+ return value.reduce(function (result, entry) {
+ const normalized = normalizeHeaderCandidate(entry, depth + 1);
+ return normalized ? Object.assign(result, normalized) : result;
+ }, {});
+ }
+
+ if (typeof value !== "object") {
+ return null;
+ }
+
+ const normalized = {};
+ const aliasMap = {
+ authorization: ["authorization", "Authorization", "token", "accessToken"],
+ reqLang: ["reqLang", "Req-Lang", "lang", "language"],
+ appVersion: ["appVersion", "App-Version"],
+ buildVersion: ["buildVersion", "Build-Version"],
+ appChannel: ["appChannel", "App-Channel"],
+ reqImei: ["reqImei", "Req-Imei"],
+ sysOrigin: ["sysOrigin", "Sys-Origin"],
+ sysOriginChild: ["sysOriginChild", "Sys-Origin-Child"],
+ };
+
+ Object.keys(aliasMap).forEach(function (targetKey) {
+ aliasMap[targetKey].forEach(function (sourceKey) {
+ mapHeaderValue(normalized, targetKey, value[sourceKey]);
+ });
+ });
+
+ ["headerInfo", "headers", "auth", "data", "state"].forEach(function (nestedKey) {
+ const nestedValue = normalizeHeaderCandidate(value[nestedKey], depth + 1);
+ if (nestedValue) {
+ Object.assign(normalized, nestedValue);
+ }
+ });
+
+ Object.keys(value).forEach(function (key) {
+ if (
+ key === "headerInfo" ||
+ key === "headers" ||
+ key === "auth" ||
+ key === "data" ||
+ key === "state"
+ ) {
+ return;
+ }
+
+ if (typeof value[key] === "object") {
+ const nestedValue = normalizeHeaderCandidate(value[key], depth + 1);
+ if (nestedValue) {
+ Object.assign(normalized, nestedValue);
+ }
+ }
+ });
+
+ return normalized;
+ }
+
+ function mapHeaderValue(target, key, value) {
+ if (value == null || value === "" || target[key]) {
+ return;
+ }
+
+ target[key] = String(value);
+ }
+})();