From d2cc6a3dd4e81c331c4d438148d23fb82a8f6132 Mon Sep 17 00:00:00 2001 From: zhx Date: Wed, 1 Jul 2026 15:17:30 +0800 Subject: [PATCH] fix: show coin seller transfer details --- gonghui/coinseller-center/script.js | 200 +++++++++++++++++++++------- gonghui/coinseller-center/style.css | 20 ++- 2 files changed, 173 insertions(+), 47 deletions(-) diff --git a/gonghui/coinseller-center/script.js b/gonghui/coinseller-center/script.js index 61056c0..e7abbf7 100644 --- a/gonghui/coinseller-center/script.js +++ b/gonghui/coinseller-center/script.js @@ -158,6 +158,11 @@ return Number.isFinite(number) ? number : 0; } + function positiveNumber(value) { + var number = toNumber(value); + return number > 0 ? number : 0; + } + function firstValue(source, keys) { if (!source) return ''; for (var i = 0; i < keys.length; i += 1) { @@ -210,9 +215,7 @@ function hasAPI() { return ( - window.HyAppAPI && - window.HyAppAPI.user && - window.HyAppAPI.wallet + window.HyAppAPI && window.HyAppAPI.user && window.HyAppAPI.wallet ); } @@ -340,6 +343,67 @@ ); } + function normalizeTransferAmount(item) { + // 转账美金来自服务端账务 metadata;不同入账来源汇率可能不同,前端不能用金币数反推,缺字段时保持不展示。 + var minor = positiveNumber( + firstValue(item, [ + 'transfer_usd_minor', + 'transferUsdMinor', + 'salary_usd_minor', + 'salaryUsdMinor', + 'recharge_usd_minor', + 'rechargeUsdMinor', + 'usd_minor_amount', + 'usdMinorAmount', + ]) + ); + if (minor > 0) return minor / 100; + var micro = positiveNumber( + firstValue(item, [ + 'paid_amount_micro', + 'paidAmountMicro', + 'amount_usdt_micro', + 'amountUsdtMicro', + ]) + ); + if (micro > 0) return micro / 1000000; + return positiveNumber( + firstValue(item, [ + 'amount_usd', + 'amountUsd', + 'transfer_amount_usd', + 'transferAmountUsd', + ]) + ); + } + + function normalizeTransferCurrency(item, amount) { + return amount > 0 + ? String( + firstValue(item, [ + 'transfer_currency_code', + 'transferCurrencyCode', + 'recharge_currency_code', + 'rechargeCurrencyCode', + 'paid_currency_code', + 'paidCurrencyCode', + 'currency_code', + 'currencyCode', + ]) || 'USD' + ).toUpperCase() + : ''; + } + + function formatTransferAmount(amount, currency) { + if (!amount || amount <= 0) return ''; + var code = String(currency || 'USD').toUpperCase(); + var value = Number(amount).toLocaleString('en-US', { + minimumFractionDigits: 2, + maximumFractionDigits: 2, + }); + return code + ' ' + value; + } + function normalizeResolvedUser(payload, keyword) { var source = unwrapData(payload) || {}; var identity = source.identity || source.user_identity || source; @@ -399,7 +463,8 @@ ); var type = delta >= 0 ? 'income' : 'expenditure'; var counterpartyUserID = String( - firstValue(item, ['counterparty_user_id', 'counterpartyUserId']) || '' + firstValue(item, ['counterparty_user_id', 'counterpartyUserId']) || + '' ); var counterpartyDisplayID = String( firstValue(item, [ @@ -419,19 +484,21 @@ 'counterpartyAvatar', ]); var counterpartyUID = counterpartyDisplayID || counterpartyUserID; + // 入账流水也可能来自某个用户的工资转币商,标题必须优先展示对方资料;只有后台进货这类没有对方用户的流水才展示库存入账。 var name = - type === 'income' - ? t('coinseller_center.stock_transfer', 'Stock transfer') - : counterpartyName || - (counterpartyUID - ? t( - 'coinseller_center.user_name_template', - 'User {id}' - ).replace('{id}', counterpartyUID) - : t('coinseller_center.transfer_out', 'Transfer out')); + counterpartyName || + (counterpartyUID + ? t( + 'coinseller_center.user_name_template', + 'User {id}' + ).replace('{id}', counterpartyUID) + : type === 'income' + ? t('coinseller_center.stock_transfer', 'Stock transfer') + : t('coinseller_center.transfer_out', 'Transfer out')); var uid = counterpartyUID || (type === 'income' ? t('coinseller_center.system', 'System') : '-'); + var transferAmount = normalizeTransferAmount(item); return { id: firstValue(item, ['transaction_id', 'transactionId']) || @@ -439,14 +506,16 @@ type: type, name: name, uid: uid, - avatar: counterpartyAvatar || avatarData( - name, - type === 'income' ? '#e7f7f3' : '#dbc8ff', - type === 'income' ? '#31a88f' : '#7d57c7' - ), + avatar: + counterpartyAvatar || + avatarData( + name, + type === 'income' ? '#e7f7f3' : '#dbc8ff', + type === 'income' ? '#31a88f' : '#7d57c7' + ), coins: Math.abs(delta), - amount: 0, - currency: '', + amount: transferAmount, + currency: normalizeTransferCurrency(item, transferAmount), time: timeLabelFromMS( firstValue(item, ['created_at_ms', 'createdAtMs']) ), @@ -485,7 +554,12 @@ function loadRealData() { if (!hasAPI()) { - toast(t('coinseller_center.load_failed', 'Load failed. Try again later.')); + toast( + t( + 'coinseller_center.load_failed', + 'Load failed. Try again later.' + ) + ); return Promise.resolve(); } state.loading = true; @@ -518,7 +592,10 @@ }) .catch(function (error) { if (window.console && window.console.warn) { - window.console.warn('[coinseller-center] api failed', error); + window.console.warn( + '[coinseller-center] api failed', + error + ); } toast( t( @@ -651,7 +728,8 @@ return data.records .filter(function (record) { return ( - record.type === state.historyTab && recordMatchesQuery(record) + record.type === state.historyTab && + recordMatchesQuery(record) ); }) .slice(0, state.historyLimit); @@ -662,7 +740,9 @@ var avatar = document.createElement('div'); var main = document.createElement('div'); var title = document.createElement('div'); + var metaGroup = document.createElement('div'); var meta = document.createElement('div'); + var transfer = document.createElement('span'); var side = document.createElement('div'); var amount = document.createElement('strong'); var time = document.createElement('span'); @@ -671,15 +751,21 @@ avatar.className = 'record-avatar'; main.className = 'record-main'; title.className = 'record-title'; + metaGroup.className = 'record-meta-group'; meta.className = 'record-meta'; + transfer.className = 'record-transfer'; side.className = 'record-side' + (record.type === 'income' ? ' is-income' : ''); renderAvatar(avatar, record); title.textContent = record.name || '-'; - meta.textContent = t('coinseller_center.uid_prefix', 'UID: {id}').replace( - '{id}', - record.uid || '-' + meta.textContent = t( + 'coinseller_center.uid_prefix', + 'UID: {id}' + ).replace('{id}', record.uid || '-'); + transfer.textContent = formatTransferAmount( + record.amount, + record.currency ); amount.textContent = (record.type === 'income' ? '+' : '-') + @@ -689,7 +775,9 @@ time.textContent = record.time || ''; main.appendChild(title); - main.appendChild(meta); + metaGroup.appendChild(meta); + if (transfer.textContent) metaGroup.appendChild(transfer); + main.appendChild(metaGroup); side.appendChild(amount); side.appendChild(time); row.appendChild(avatar); @@ -709,13 +797,16 @@ function renderHistory() { document.querySelectorAll('[data-history-tab]').forEach(function (tab) { - var active = tab.getAttribute('data-history-tab') === state.historyTab; + var active = + tab.getAttribute('data-history-tab') === state.historyTab; tab.classList.toggle('is-active', active); tab.setAttribute('aria-selected', String(active)); }); var all = data.records.filter(function (record) { - return record.type === state.historyTab && recordMatchesQuery(record); + return ( + record.type === state.historyTab && recordMatchesQuery(record) + ); }); var records = visibleHistoryRecords(); $('loadMoreButton').hidden = records.length >= all.length; @@ -783,7 +874,10 @@ renderRechargeState(); setStatus( $('searchStatus'), - t('coinseller_center.user_not_found', 'User not found.'), + t( + 'coinseller_center.user_not_found', + 'User not found.' + ), 'warning' ); return; @@ -795,7 +889,10 @@ }) .catch(function (error) { if (window.console && window.console.warn) { - window.console.warn('[coinseller-center] user search failed', error); + window.console.warn( + '[coinseller-center] user search failed', + error + ); } state.target = null; renderTarget(); @@ -832,12 +929,9 @@ function appendTransferRecord(amount, response) { var payload = unwrapData(response) || {}; var coins = toNumber( - firstValue(payload, [ - 'amount', - 'coin_amount', - 'coinAmount', - ]) + firstValue(payload, ['amount', 'coin_amount', 'coinAmount']) ); + var transferAmount = normalizeTransferAmount(payload); data.records.unshift({ id: firstValue(payload, ['transaction_id', 'transactionId']) || @@ -847,8 +941,8 @@ uid: state.target.uid, avatar: state.target.avatar, coins: coins || amount, - amount: 0, - currency: '', + amount: transferAmount, + currency: normalizeTransferCurrency(payload, transferAmount), time: currentTimeLabel(), }); } @@ -858,7 +952,10 @@ if (!state.target) { setStatus( $('rechargeStatus'), - t('coinseller_center.select_user_first', 'Select a user first.'), + t( + 'coinseller_center.select_user_first', + 'Select a user first.' + ), 'warning' ); return; @@ -877,7 +974,10 @@ if (amount > data.balance.coins) { setStatus( $('rechargeStatus'), - t('coinseller_center.amount_exceeds_stock', 'Amount exceeds stock.'), + t( + 'coinseller_center.amount_exceeds_stock', + 'Amount exceeds stock.' + ), 'warning' ); return; @@ -921,13 +1021,19 @@ }) .catch(function (error) { if (window.console && window.console.warn) { - window.console.warn('[coinseller-center] transfer failed', error); + window.console.warn( + '[coinseller-center] transfer failed', + error + ); } setStatus($('rechargeStatus'), '', ''); toast( error && error.message ? error.message - : t('coinseller_center.transfer_failed', 'Transfer failed.') + : t( + 'coinseller_center.transfer_failed', + 'Transfer failed.' + ) ); }) .finally(function () { @@ -1006,11 +1112,13 @@ $('helpButton').addEventListener('click', function () { openModal('helpModal'); }); - document.querySelectorAll('[data-close-modal]').forEach(function (node) { - node.addEventListener('click', function () { - closeModal(node.getAttribute('data-close-modal')); + document + .querySelectorAll('[data-close-modal]') + .forEach(function (node) { + node.addEventListener('click', function () { + closeModal(node.getAttribute('data-close-modal')); + }); }); - }); $('searchForm').addEventListener('submit', function (event) { event.preventDefault(); var value = $('userSearchInput').value.trim(); diff --git a/gonghui/coinseller-center/style.css b/gonghui/coinseller-center/style.css index 560bfca..32af4a9 100644 --- a/gonghui/coinseller-center/style.css +++ b/gonghui/coinseller-center/style.css @@ -405,9 +405,18 @@ white-space: nowrap; } -.record-meta { +.record-meta-group { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 4px 8px; margin-top: 5px; + min-width: 0; +} + +.record-meta { overflow: hidden; + min-width: 0; color: var(--muted); font-size: 12px; font-weight: 800; @@ -416,6 +425,15 @@ white-space: nowrap; } +.record-transfer { + flex: 0 0 auto; + color: var(--primary-deep); + font-size: 12px; + font-weight: 900; + line-height: 1.2; + white-space: nowrap; +} + .record-side { display: grid; justify-items: end;