From f1643dc3af9efe910a97daef406d6435e65ed320 Mon Sep 17 00:00:00 2001 From: ZuoZuo <68836346+Mrz-sakura@users.noreply.github.com> Date: Sat, 25 Apr 2026 14:38:02 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=97=B6=E9=97=B4=E9=AA=8C?= =?UTF-8?q?=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- h5/agency-list/team-list.js | 10 +- h5/bd-leader-center/bd-leader-center.js | 16 +++- h5/bd-list/bd-list.js | 8 +- h5/bd-static/shared.js | 117 +++++++++++++++++++++++- 4 files changed, 135 insertions(+), 16 deletions(-) diff --git a/h5/agency-list/team-list.js b/h5/agency-list/team-list.js index 1602655..e49bfc7 100644 --- a/h5/agency-list/team-list.js +++ b/h5/agency-list/team-list.js @@ -1,4 +1,4 @@ -import { applyLang, avatarError, bindHeader, connectToApp, createMask, get, money, statusClass, statusText, t, toast } from "../bd-static/shared.js"; +import { applyLang, avatarError, bindHeader, connectToApp, createMask, get, historyMoreUrl, isCompletedStatus, money, statusClass, statusText, t, toast } from "../bd-static/shared.js"; const config = { title: "agency_list_link", @@ -7,7 +7,7 @@ const config = { listSummary: (data) => `${t("team_recharge")}: ${data.totalRecharge || 0} ${t("team_salary")}: $${data.totalSalary || 0}`, itemSide: (item) => [`${t("salary")}: $${item.teamSalaryAmount || 0}`, `${t("recharge")}: $${item.teamRechargeAmount || 0}`, `${t("host")}: ${item.teamMemberCount || 0}`], historyEndpoint: "/team/bd/history", - moreEndpoint: (billBelong) => `/team/bd/history/more?billBelong=${encodeURIComponent(billBelong)}`, + moreEndpoint: (billBelong) => historyMoreUrl("/team/bd/history/more", billBelong), countLabel: "agency_number" }; @@ -93,7 +93,7 @@ function historyItem(item, settings) { `
${t("num_teams") || t(settings.countLabel)} ${item.agencyNumber || item.bdNumber || 0}
` ]; card.innerHTML = `
${statusText(item.statusText)}
${details.join("")}`; - if (item.statusText === "Completed") { + if (isCompletedStatus(item.statusText)) { const more = document.createElement("button"); more.className = "more-btn"; more.type = "button"; @@ -106,7 +106,9 @@ function historyItem(item, settings) { async function showMore(billBelong, settings) { try { - const response = await get(settings.moreEndpoint(billBelong)); + const endpoint = settings.moreEndpoint(billBelong); + if (!endpoint) return; + const response = await get(endpoint); const data = response.body || {}; const sheet = document.createElement("section"); sheet.className = "sheet"; diff --git a/h5/bd-leader-center/bd-leader-center.js b/h5/bd-leader-center/bd-leader-center.js index d26799e..8a2050a 100644 --- a/h5/bd-leader-center/bd-leader-center.js +++ b/h5/bd-leader-center/bd-leader-center.js @@ -1,3 +1,5 @@ +import { historyMoreUrl } from "../bd-static/shared.js"; + const API_BASE_URL = "https://jvapi.haiyihy.com"; const labels = { @@ -284,12 +286,16 @@ async function fetchBalanceTotal() { } async function fetchBDHistoryMore(billBelong) { - const result = await apiGet(`/team/bd/history/more?billBelong=${encodeURIComponent(billBelong)}`); + const endpoint = historyMoreUrl("/team/bd/history/more", billBelong); + if (!endpoint) throw new Error(t("request_not_available")); + const result = await apiGet(endpoint); if (result.status && result.body) state.historyMore = result.body || {}; } async function fetchBDLeaderHistoryMore(billBelong) { - const result = await apiGet(`/team/bd/leader/history/more?billBelong=${encodeURIComponent(billBelong)}`); + const endpoint = historyMoreUrl("/team/bd/leader/history/more", billBelong); + if (!endpoint) throw new Error(t("request_not_available")); + const result = await apiGet(endpoint); if (result.status && result.body) state.historyMore = result.body || {}; } @@ -315,10 +321,10 @@ function formatMoney(value) { } function normalizeStatus(status) { - if (status === "In Progress" || status === t("in_progress")) return t("in_progress"); + if (status === "UNPAID" || status === "In Progress" || status === t("in_progress")) return t("in_progress"); if (status === "Pending" || status === t("pending")) return t("pending"); - if (status === "Completed" || status === t("completed")) return t("completed"); - if (status === "Out of account" || status === t("out_of_account")) return t("out_of_account"); + if (status === "SETTLED" || status === "PAY_OUT" || status === "Completed" || status === t("completed")) return t("completed"); + if (status === "HANG_UP" || status === "Out of account" || status === "Out Of Account" || status === t("out_of_account")) return t("out_of_account"); return status || ""; } diff --git a/h5/bd-list/bd-list.js b/h5/bd-list/bd-list.js index fa846cf..6c06e08 100644 --- a/h5/bd-list/bd-list.js +++ b/h5/bd-list/bd-list.js @@ -1,4 +1,4 @@ -import { applyLang, avatarError, bindHeader, connectToApp, createMask, get, money, statusClass, statusText, t, toast } from "../bd-static/shared.js"; +import { applyLang, avatarError, bindHeader, connectToApp, createMask, get, historyMoreUrl, isCompletedStatus, money, statusClass, statusText, t, toast } from "../bd-static/shared.js"; bindHeader("bd_list_link"); applyLang(); @@ -79,7 +79,7 @@ function historyItem(item) { ${t("team_salary")}: $${item.teamSalaryAmount || 0} `; - if (item.statusText === "Completed") { + if (isCompletedStatus(item.statusText)) { const more = document.createElement("button"); more.className = "more-btn"; more.type = "button"; @@ -92,7 +92,9 @@ function historyItem(item) { async function showMore(billBelong) { try { - const response = await get(`/team/bd/leader/history/more?billBelong=${encodeURIComponent(billBelong)}`); + const endpoint = historyMoreUrl("/team/bd/leader/history/more", billBelong); + if (!endpoint) return; + const response = await get(endpoint); const data = response.body || {}; const sheet = document.createElement("section"); sheet.className = "sheet"; diff --git a/h5/bd-static/shared.js b/h5/bd-static/shared.js index 092ab2e..1ec5da8 100644 --- a/h5/bd-static/shared.js +++ b/h5/bd-static/shared.js @@ -386,6 +386,109 @@ export function money(value) { return Number.isInteger(number) ? String(number) : number.toFixed(2); } +const digitMaps = [ + ["٠", "0"], ["١", "1"], ["٢", "2"], ["٣", "3"], ["٤", "4"], ["٥", "5"], ["٦", "6"], ["٧", "7"], ["٨", "8"], ["٩", "9"], + ["۰", "0"], ["۱", "1"], ["۲", "2"], ["۳", "3"], ["۴", "4"], ["۵", "5"], ["۶", "6"], ["۷", "7"], ["۸", "8"], ["۹", "9"], + ["০", "0"], ["১", "1"], ["২", "2"], ["৩", "3"], ["৪", "4"], ["৫", "5"], ["৬", "6"], ["৭", "7"], ["৮", "8"], ["৯", "9"] +]; + +const monthNames = new Map(Object.entries({ + january: 1, jan: 1, "يناير": 1, "كانون الثاني": 1, ocak: 1, "জানুয়ারি": 1, + february: 2, feb: 2, "فبراير": 2, "شباط": 2, subat: 2, "şubat": 2, "ফেব্রুয়ারি": 2, + march: 3, mar: 3, "مارس": 3, "آذار": 3, mart: 3, "মার্চ": 3, + april: 4, apr: 4, "أبريل": 4, "ابريل": 4, "نيسان": 4, nisan: 4, "এপ্রিল": 4, + may: 5, "مايو": 5, "أيار": 5, mayis: 5, "mayıs": 5, "মে": 5, + june: 6, jun: 6, "يونيو": 6, "حزيران": 6, haziran: 6, "জুন": 6, + july: 7, jul: 7, "يوليو": 7, "تموز": 7, temmuz: 7, "জুলাই": 7, + august: 8, aug: 8, "أغسطس": 8, "اغسطس": 8, "آب": 8, agustos: 8, "ağustos": 8, "আগস্ট": 8, + september: 9, sep: 9, "سبتمبر": 9, "أيلول": 9, eylul: 9, "eylül": 9, "সেপ্টেম্বর": 9, + october: 10, oct: 10, "أكتوبر": 10, "اكتوبر": 10, "تشرين الأول": 10, ekim: 10, "অক্টোবর": 10, + november: 11, nov: 11, "نوفمبر": 11, "تشرين الثاني": 11, kasim: 11, "kasım": 11, "নভেম্বর": 11, + december: 12, dec: 12, "ديسمبر": 12, "كانون الأول": 12, aralik: 12, "aralık": 12, "ডিসেম্বর": 12 +})); + +function pad2(value) { + return String(value).padStart(2, "0"); +} + +function formatBillBelong(year, month, day, time) { + const monthNumber = Number(month); + const dayNumber = Number(day); + if (monthNumber < 1 || monthNumber > 12 || dayNumber < 1 || dayNumber > 31) return ""; + return `${year}-${pad2(monthNumber)}-${pad2(dayNumber)}T${time}`; +} + +function normalizeDateText(value) { + return digitMaps.reduce((textValue, [from, to]) => textValue.split(from).join(to), String(value || "")) + .replace(/&(?:rlm|lrm|nbsp);/gi, " ") + .replace(/[\u061c\u200e\u200f]/g, "") + .replace(/[،]/g, ",") + .replace(/\s+/g, " ") + .trim(); +} + +function normalizeTime(value, markerText = "") { + const match = String(value || "").match(/(\d{1,2}):(\d{2})(?::(\d{2}))?/); + if (!match) return "00:00:00"; + let hour = Number(match[1]); + const marker = markerText.toLowerCase(); + const isPm = /\bpm\b|مساء|(?:^|\s)م(?:\s|$)/.test(marker); + const isAm = /\bam\b|صباح|(?:^|\s)ص(?:\s|$)/.test(marker); + if (isPm && hour < 12) hour += 12; + if (isAm && hour === 12) hour = 0; + return `${pad2(hour)}:${match[2]}:${match[3] || "00"}`; +} + +export function normalizeBillBelong(value) { + const textValue = normalizeDateText(value); + if (!textValue) return ""; + + const isoMatch = textValue.match(/^(\d{4})-(\d{2})-(\d{2})(?:[ T](\d{2}):(\d{2})(?::(\d{2}))?)?/); + if (isoMatch) { + return formatBillBelong(isoMatch[1], isoMatch[2], isoMatch[3], `${isoMatch[4] || "00"}:${isoMatch[5] || "00"}:${isoMatch[6] || "00"}`); + } + + const compactDateTime = textValue.match(/^(\d{4})(\d{2})(\d{2})(?:\D?(\d{2})(\d{2})(\d{2})?)?$/); + if (compactDateTime) { + return formatBillBelong(compactDateTime[1], compactDateTime[2], compactDateTime[3], `${compactDateTime[4] || "00"}:${compactDateTime[5] || "00"}:${compactDateTime[6] || "00"}`); + } + + const numericDate = textValue.match(/\b(?:(\d{4})[./-](\d{1,2})[./-](\d{1,2})|(\d{1,2})[./-](\d{1,2})[./-](\d{4}))\b/); + if (numericDate) { + const time = normalizeTime(textValue, textValue); + if (numericDate[1]) return formatBillBelong(numericDate[1], numericDate[2], numericDate[3], time); + const first = Number(numericDate[4]); + const second = Number(numericDate[5]); + const month = first > 12 && second <= 12 ? second : first; + const day = second > 12 && first <= 12 ? second : first > 12 ? first : second; + return formatBillBelong(numericDate[6], month, day, time); + } + + const lowerText = textValue.toLowerCase(); + let month = 0; + for (const [name, valueForMonth] of monthNames) { + if (lowerText.includes(name)) { + month = valueForMonth; + break; + } + } + const yearMatch = textValue.match(/\b(20\d{2})\b/); + if (month && yearMatch) { + const withoutYear = textValue.replace(yearMatch[1], ""); + const dayMatch = withoutYear.match(/\b([0-3]?\d)\b/); + if (dayMatch) { + return formatBillBelong(yearMatch[1], month, dayMatch[1], normalizeTime(textValue, textValue)); + } + } + + return ""; +} + +export function historyMoreUrl(basePath, billBelong) { + const normalized = normalizeBillBelong(billBelong); + return normalized ? `${basePath}?billBelong=${encodeURIComponent(normalized)}` : ""; +} + export function safeJsonArray(value) { try { const result = JSON.parse(value || "[]"); @@ -438,9 +541,10 @@ export function createMask(content) { } export function statusClass(status) { - if (status === "Completed") return "completed"; - if (status === "Pending") return "pending"; - if (status === "Out of account" || status === "HANG_UP") return "out"; + const normalized = statusText(status); + if (normalized === t("completed")) return "completed"; + if (normalized === t("pending")) return "pending"; + if (normalized === t("out_of_account")) return "out"; return ""; } @@ -453,11 +557,16 @@ export function statusText(status) { "In Progress": t("in_progress"), Pending: t("pending"), Completed: t("completed"), - "Out of account": t("out_of_account") + "Out of account": t("out_of_account"), + "Out Of Account": t("out_of_account") }; return map[status] || status || ""; } +export function isCompletedStatus(status) { + return status === "SETTLED" || status === "PAY_OUT" || statusText(status) === t("completed"); +} + export function avatarError(img) { img.addEventListener("error", () => { img.removeAttribute("src");