From f776b87a01c3410697d57b862987131dd8e02218 Mon Sep 17 00:00:00 2001 From: zhx Date: Thu, 9 Jul 2026 18:15:08 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AD=90=E5=B8=81=E5=95=86=E4=BB=A5=E5=8F=8Aas?= =?UTF-8?q?lan=E5=85=85=E5=80=BC=E6=B4=BB=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- activity/cp-space/yumi.html | 2 +- aslan/recharge-activity/index.html | 65 ++- aslan/recharge-activity/script.js | 503 ++++++++++++++++-- aslan/recharge-activity/style.css | 46 +- common/locales/ar.json | 14 +- common/locales/en.json | 14 +- common/locales/es.json | 14 +- common/locales/id.json | 14 +- common/locales/tr.json | 14 +- common/locales/zh.json | 14 +- common_aslan/aslan-common.js | 516 +++++++++++++++++++ {yumi_commmon => common_yumi}/yumi-common.js | 0 gonghui/coinseller-center/script.js | 59 +-- 13 files changed, 1143 insertions(+), 132 deletions(-) create mode 100644 common_aslan/aslan-common.js rename {yumi_commmon => common_yumi}/yumi-common.js (100%) diff --git a/activity/cp-space/yumi.html b/activity/cp-space/yumi.html index cb43cdf..97404c4 100644 --- a/activity/cp-space/yumi.html +++ b/activity/cp-space/yumi.html @@ -204,7 +204,7 @@ - + diff --git a/aslan/recharge-activity/index.html b/aslan/recharge-activity/index.html index 8748808..b64436c 100644 --- a/aslan/recharge-activity/index.html +++ b/aslan/recharge-activity/index.html @@ -7,8 +7,8 @@ content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover" /> Recharge Reward - - + +
@@ -18,7 +18,11 @@ aria-label="Recharge Reward activity" data-i18n-aria="rechargeReward.pageLabel" > - + - 01 - 01 - 01 - 01 - Days - Hours - Minutes - Seconds + 01 + 01 + 01 + 01 + Days + Hours + Minutes + Seconds -
+
-

nanfangjian

+

+ nanfangjian +

ID: 12345678

Accumlated Recharge:5998 @@ -92,7 +125,9 @@ - - + + + + diff --git a/aslan/recharge-activity/script.js b/aslan/recharge-activity/script.js index eca233b..c1e4ee2 100644 --- a/aslan/recharge-activity/script.js +++ b/aslan/recharge-activity/script.js @@ -1,7 +1,10 @@ (function () { var ASSET_BASE = './assets/recharge-activity/'; var viewport = document.getElementById('appViewport'); + var page = document.getElementById('page'); + var stage = document.querySelector('.stage'); var rewardSections = document.getElementById('rewardSections'); + var bgBottom = document.querySelector('.bg-bottom'); var countNodes = { days: document.querySelector('[data-count="days"]'), hours: document.querySelector('[data-count="hours"]'), @@ -10,40 +13,37 @@ }; var DESIGN_WIDTH = 1080; - var DESIGN_HEIGHT = 3273; var VIEWPORT_WIDTH = 375; + var DEFAULT_DESIGN_HEIGHT = 3273; + var designHeight = DEFAULT_DESIGN_HEIGHT; var countdownEndAt = resolveCountdownEndAt(); - var activityData = { + var countdownTimer = 0; + var state = { user: { - name: 'nanfangjian', - id: '12345678', + name: '', + id: '', avatar: ASSET_BASE + 'profile-avatar.png', - accumulatedRecharge: '5998', + accumulatedRecharge: 0, }, - rewards: [ - { - amount: '$100', - top: 1776, - background: ASSET_BASE + 'reward-section-a.png', - claim: { text: 'Receive', claimable: true, claimed: false }, - cards: [ - { price: '$100', icon: ASSET_BASE + 'reward-icon.png', left: 111, top: 293 }, - { price: '$100', icon: ASSET_BASE + 'reward-icon.png', left: 560, top: 293 }, - ], - }, - { - amount: '$100', - top: 2466, - background: ASSET_BASE + 'reward-section-b.png', - claim: { text: 'Receive', claimable: true, claimed: false }, - cards: [ - { price: '$100', icon: ASSET_BASE + 'reward-icon.png', left: 70.5, top: 278 }, - { price: '$100', icon: ASSET_BASE + 'reward-icon.png', left: 339.5, top: 278 }, - { price: '$100', icon: ASSET_BASE + 'reward-icon.png', left: 608.5, top: 278 }, - ], - }, - ], + rewards: [], + claiming: {}, + loading: true, + error: '', }; + var fallbackCards = [ + { + price: '$100', + icon: ASSET_BASE + 'reward-icon.png', + left: 111, + top: 293, + }, + { + price: '$100', + icon: ASSET_BASE + 'reward-icon.png', + left: 560, + top: 293, + }, + ]; function getParams() { return new URLSearchParams(window.location.search || ''); @@ -68,25 +68,78 @@ return String(Math.max(0, value)).padStart(2, '0'); } + function showToast(message) { + if (window.HyAppToast && window.HyAppToast.show) { + window.HyAppToast.show(message); + return; + } + window.dispatchEvent( + new CustomEvent('hyapp:toast', { detail: { message: message } }) + ); + } + + function numeric(value, fallback) { + var number = Number(value); + return Number.isFinite(number) ? number : fallback || 0; + } + + function parseJSON(value) { + if (!value || typeof value !== 'string') return null; + try { + return JSON.parse(value); + } catch (_) { + return null; + } + } + + function firstValue() { + for (var i = 0; i < arguments.length; i += 1) { + var value = arguments[i]; + if (value !== undefined && value !== null && value !== '') + return value; + } + return ''; + } + + function formatUSD(value) { + var amount = numeric(value, 0); + return ( + '$' + + amount.toLocaleString('en-US', { + maximumFractionDigits: 2, + minimumFractionDigits: amount % 1 === 0 ? 0 : 2, + }) + ); + } + function resolveCountdownEndAt() { var params = getParams(); - var explicitEnd = Date.parse(params.get('end_at') || params.get('endAt') || ''); - if (Number.isFinite(explicitEnd) && explicitEnd > Date.now()) return explicitEnd; + var explicitEnd = Date.parse( + params.get('end_at') || params.get('endAt') || '' + ); + if (Number.isFinite(explicitEnd) && explicitEnd > Date.now()) + return explicitEnd; var hours = Number(params.get('hours')); - if (Number.isFinite(hours) && hours > 0) return Date.now() + hours * 60 * 60 * 1000; + if (Number.isFinite(hours) && hours > 0) + return Date.now() + hours * 60 * 60 * 1000; - // This page is intentionally interface-free for now; when an API is added, - // use the server period end time here and do not recover failed requests with mock data. + // 后端月累充接口当前只返回活动文案周期,不返回毫秒级结束时间;倒计时仍支持 URL 显式覆盖,默认只作为页面视觉计时。 return Date.now() + 25 * 60 * 60 * 1000 + 61 * 1000; } function updateScale() { var scale = Math.min(window.innerWidth / VIEWPORT_WIDTH, 1); - var scaledHeight = Math.ceil(DESIGN_HEIGHT * (VIEWPORT_WIDTH / DESIGN_WIDTH)); + var scaledHeight = Math.ceil( + designHeight * (VIEWPORT_WIDTH / DESIGN_WIDTH) + ); - document.documentElement.style.setProperty('--app-scale', String(scale)); + document.documentElement.style.setProperty( + '--app-scale', + String(scale) + ); viewport.style.minHeight = scaledHeight + 'px'; + page.style.minHeight = scaledHeight + 'px'; document.body.style.minHeight = Math.ceil(scaledHeight * scale) + 'px'; } @@ -104,14 +157,175 @@ countNodes.seconds.textContent = twoDigits(seconds); } + function normalizeUser(profile, statusData) { + profile = profile || {}; + var params = getParams(); + return { + name: firstValue( + profile.userNickname, + profile.username, + profile.name, + params.get('name'), + 'Aslan' + ), + id: String( + firstValue( + profile.specialId, + profile.displayUserId, + profile.display_user_id, + profile.account, + profile.id, + profile.userId, + params.get('uid'), + params.get('id'), + '' + ) + ), + avatar: firstValue( + profile.userAvatar, + profile.avatar, + profile.headImg, + profile.headImage, + params.get('avatar'), + ASSET_BASE + 'profile-avatar.png' + ), + accumulatedRecharge: firstValue( + statusData && statusData.monthlyRecharge, + params.get('recharge'), + 0 + ), + }; + } + + function rewardProps(resource) { + var group = + resource && resource.activityResource + ? resource.activityResource.propsGroup || {} + : {}; + return Array.isArray(group.activityRewardProps) + ? group.activityRewardProps + : []; + } + + function rule(resource) { + return resource && resource.activityResource + ? resource.activityResource.rule || {} + : {}; + } + + function thresholdAmount(resource) { + var data = parseJSON(rule(resource).jsonData) || {}; + return numeric(data.quantity, 0); + } + + function cardLayout(count, index) { + if (count >= 4) { + return ( + [ + { left: 70.5, top: 278 }, + { left: 292.5, top: 278 }, + { left: 514.5, top: 278 }, + { left: 736.5, top: 278 }, + ][index] || { left: 736.5, top: 278 } + ); + } + if (count === 3) { + return ( + [ + { left: 70.5, top: 278 }, + { left: 339.5, top: 278 }, + { left: 608.5, top: 278 }, + ][index] || { left: 608.5, top: 278 } + ); + } + return ( + [ + { left: 111, top: 293 }, + { left: 560, top: 293 }, + ][index] || { left: 560, top: 293 } + ); + } + + function normalizeCard(item, threshold, count, index) { + var pos = cardLayout(count, index); + return { + price: + item && item.amount + ? formatUSD(item.amount) + : formatUSD(threshold), + icon: (item && item.cover) || ASSET_BASE + 'reward-icon.png', + left: pos.left, + top: pos.top, + }; + } + + function normalizeReward(resource, index) { + var currentRule = rule(resource); + var ruleId = String(currentRule.id || resource.ruleId || ''); + var threshold = thresholdAmount(resource); + var props = rewardProps(resource).slice(0, 4); + var receiveStatus = String(resource.receiveStatus || '').toUpperCase(); + var claimed = receiveStatus === 'RECEIVED'; + var claimable = receiveStatus === 'NOT_RECEIVED'; + var cardCount = props.length || fallbackCards.length; + + return { + ruleId: ruleId, + amount: formatUSD(threshold), + top: 1776 + index * 690, + background: + index % 2 === 0 + ? ASSET_BASE + 'reward-section-a.png' + : ASSET_BASE + 'reward-section-b.png', + claim: { + text: claimed + ? t('rechargeReward.claimed', 'Claimed') + : t('rechargeReward.claim', 'Claim'), + claimable: claimable, + claimed: claimed, + loading: Boolean(state.claiming[ruleId]), + }, + cards: props.length + ? props.map(function (item, cardIndex) { + return normalizeCard( + item, + threshold, + cardCount, + cardIndex + ); + }) + : fallbackCards.map(function (card) { + return Object.assign({}, card, { + price: formatUSD(threshold), + }); + }), + }; + } + + function normalizeRewards(statusData) { + var resources = + statusData && Array.isArray(statusData.activityResources) + ? statusData.activityResources + : []; + return resources + .map(function (item, index) { + return normalizeReward(item, index); + }) + .filter(function (item) { + return item.ruleId; + }); + } + function renderProfile(user) { - document.querySelector('[data-profile-avatar]').src = user.avatar; - document.querySelector('[data-profile-name]').textContent = user.name; + document.querySelector('[data-profile-avatar]').src = + user.avatar || ASSET_BASE + 'profile-avatar.png'; + document.querySelector('[data-profile-name]').textContent = + user.name || 'Aslan'; document.querySelector('[data-profile-id]').textContent = - t('rechargeReward.idPrefix', 'ID:') + ' ' + user.id; + t('rechargeReward.idPrefix', 'ID:') + ' ' + (user.id || '-'); document.querySelector('[data-profile-recharge]').textContent = - t('rechargeReward.accumulatedRecharge', 'Accumlated Recharge:') + - user.accumulatedRecharge; + t('rechargeReward.accumulatedRecharge', 'Accumulated Recharge:') + + formatUSD(user.accumulatedRecharge || 0); } function renderRewardCard(card) { @@ -135,31 +349,65 @@ ].join(''); } - function renderClaimButton(claim) { - var stateClass = claim.claimed ? ' is-claimed' : claim.claimable ? ' is-claimable' : ' is-disabled'; + function renderClaimButton(section) { + var claim = section.claim || {}; + var stateClass = claim.claimed + ? ' is-claimed' + : claim.claimable + ? ' is-claimable' + : ' is-disabled'; + var disabled = !claim.claimable || claim.claimed || claim.loading; return [ '', ].join(''); } function renderRewards(rewards) { + if (state.loading) { + rewardSections.innerHTML = + '

' + + escapeHTML(t('rechargeReward.loading', 'Loading...')) + + '

'; + return; + } + if (state.error) { + rewardSections.innerHTML = + '

' + + escapeHTML(state.error) + + '

'; + return; + } + if (!rewards.length) { + rewardSections.innerHTML = + '

' + + escapeHTML(t('rechargeReward.noRewards', 'No rewards yet')) + + '

'; + return; + } + rewardSections.innerHTML = rewards .map(function (section) { - var title = t('rechargeReward.rechargeTitle', 'Recharge {amount}').replace( - '{amount}', - section.amount - ); + var title = t( + 'rechargeReward.rechargeTitle', + 'Recharge {amount}' + ).replace('{amount}', section.amount); return [ '
= 0) { + new URLSearchParams(hash.split('?').slice(1).join('?')).forEach( + function (value, key) { + if (!params.has(key)) params.set(key, value); + } + ); + } + return params; + } + + function query(name) { + return currentParams().get(name); + } + + function normalizeBaseURL(value) { + return String(value || '').replace(/\/+$/, ''); + } + + function resolveEnv() { + var env = String(query('env') || '') + .trim() + .toLowerCase(); + return env === 'local' || env === 'test' || env === 'dev' ? env : ''; + } + + function baseURL() { + var override = + query('apiBase') || + query('api_base') || + query('aslan_api_base') || + window.ASLAN_API_BASE_URL || + (window.AslanCommonConfig && window.AslanCommonConfig.apiBase); + if (override) return normalizeBaseURL(override); + return resolveEnv() === 'local' + ? normalizeBaseURL(LOCAL_API_BASE) + : normalizeBaseURL(PROD_API_BASE); + } + + function buildURL(path, queryData) { + var url = new URL( + String(path || '').replace(/^\/+/, ''), + baseURL() + '/' + ); + Object.keys(queryData || {}).forEach(function (key) { + var value = queryData[key]; + if (value === undefined || value === null || value === '') return; + url.searchParams.set(key, value); + }); + return url.toString(); + } + + function normalizeAuthorization(value) { + var text = String(value || '').trim(); + if (!text) return ''; + return /^Bearer\s+/i.test(text) ? text : 'Bearer ' + text; + } + + function splitHeaderPairs(value) { + var result = {}; + String(value || '') + .split(';') + .forEach(function (item) { + var index = item.indexOf('='); + if (index > -1) { + result[item.slice(0, index).trim()] = item + .slice(index + 1) + .trim(); + } + }); + return result; + } + + function putHeader(target, key, value) { + if ( + value === undefined || + value === null || + value === '' || + target[key] + ) { + return; + } + target[key] = String(value); + } + + function normalizeHeaderCandidate(value, depth) { + depth = depth || 0; + if (depth > 4 || value === null || value === undefined) return {}; + if (typeof value === 'string') { + var trimmed = value.trim(); + if (!trimmed) return {}; + if (trimmed.charAt(0) === '{' || trimmed.charAt(0) === '[') { + try { + return normalizeHeaderCandidate( + JSON.parse(trimmed), + depth + 1 + ); + } catch (_) { + return {}; + } + } + return { authorization: trimmed }; + } + if (Array.isArray(value)) { + return value.reduce(function (result, item) { + return Object.assign( + result, + normalizeHeaderCandidate(item, depth + 1) + ); + }, {}); + } + if (typeof value !== 'object') return {}; + + var appIntel = splitHeaderPairs( + value['Req-App-Intel'] || value['req-app-intel'] + ); + var sysOrigin = splitHeaderPairs( + value['Req-Sys-Origin'] || value['req-sys-origin'] + ); + var normalized = {}; + putHeader( + normalized, + 'authorization', + value.Authorization || + value.authorization || + value.token || + value.accessToken + ); + putHeader( + normalized, + 'reqLang', + value['Req-Lang'] || + value['req-lang'] || + value.reqLang || + value.lang + ); + putHeader( + normalized, + 'appVersion', + appIntel.version || value.appVersion || value['App-Version'] + ); + putHeader( + normalized, + 'buildVersion', + appIntel.build || value.buildVersion + ); + putHeader(normalized, 'model', appIntel.model || value.model); + putHeader(normalized, 'channel', appIntel.channel || value.channel); + putHeader( + normalized, + 'reqImei', + appIntel['Req-Imei'] || + appIntel.imei || + value['Req-Imei'] || + value['req-imei'] || + value.reqImei + ); + putHeader( + normalized, + 'origin', + sysOrigin.origin || value.sysOrigin || value.origin + ); + putHeader( + normalized, + 'child', + sysOrigin.originChild || + sysOrigin.child || + value.sysOriginChild || + value.child + ); + + ['headerInfo', 'headers', 'auth', 'data', 'state'].forEach( + function (key) { + Object.assign( + normalized, + normalizeHeaderCandidate(value[key], depth + 1) + ); + } + ); + return normalized; + } + + function setHeadersFromApp(rawOrObject) { + var data = normalizeHeaderCandidate(rawOrObject || {}); + var next = {}; + if (data.authorization) { + next.authorization = normalizeAuthorization(data.authorization); + } + if (data.reqLang) next['req-lang'] = data.reqLang; + if ( + data.appVersion || + data.buildVersion || + data.model || + data.channel + ) { + next['req-app-intel'] = [ + data.appVersion ? 'version=' + data.appVersion : '', + data.buildVersion ? 'build=' + data.buildVersion : '', + data.model ? 'model=' + data.model : '', + data.channel ? 'channel=' + data.channel : '', + ] + .filter(Boolean) + .join(';'); + } + if (data.reqImei) next['req-imei'] = data.reqImei; + if (data.origin) { + next['req-sys-origin'] = [ + 'origin=' + data.origin, + 'originChild=' + (data.child || data.origin), + ].join(';'); + } + headers = Object.assign(headers, next); + return headers; + } + + function discoverQueryHeaders() { + return { + authorization: + query('authorization') || + query('Authorization') || + query('token') || + query('accessToken') || + query('access_token'), + reqLang: query('lang') || query('language') || query('locale'), + origin: query('sysOrigin') || query('origin') || DEFAULT_ORIGIN, + child: + query('sysOriginChild') || + query('originChild') || + DEFAULT_ORIGIN, + channel: query('channel') || query('appChannel'), + }; + } + + function readStorageHeaders(storage) { + var collected = {}; + if (!storage) return collected; + [ + 'authorization', + 'Authorization', + 'token', + 'accessToken', + 'headerInfo', + 'headersFromApp', + 'appHeaders', + 'user', + 'userInfo', + ].forEach(function (key) { + try { + Object.assign( + collected, + normalizeHeaderCandidate(storage.getItem(key)) + ); + } catch (_) {} + }); + return collected; + } + + function applyDiscoveredHeaders() { + setHeadersFromApp(discoverQueryHeaders()); + setHeadersFromApp(window.__APP_HEADERS__); + setHeadersFromApp(window.__HEADER_INFO__); + setHeadersFromApp(window.headerInfo); + try { + setHeadersFromApp(readStorageHeaders(window.localStorage)); + setHeadersFromApp(readStorageHeaders(window.sessionStorage)); + } catch (_) {} + } + + function ensureAslanAppCode() { + document.documentElement.dataset.hyAppCode = APP_CODE; + var params = currentParams(); + if ( + params.get('app_code') || + params.get('app') || + params.get('appCode') || + !window.history || + !window.history.replaceState + ) { + return; + } + var url = new URL(window.location.href); + url.searchParams.set('app_code', APP_CODE); + window.history.replaceState(null, '', url.toString()); + } + + function isAppEnvironment() { + return Boolean( + window.app || + window.FlutterApp || + window.FlutterPageControl || + window.webkit + ); + } + + function requestAccessOrigin() { + return new Promise(function (resolve) { + var settled = false; + var timeoutId = null; + function finish(raw) { + if (raw) setHeadersFromApp(raw); + if (settled) return; + settled = true; + if (timeoutId) window.clearTimeout(timeoutId); + resolve(raw || null); + } + + window.renderData = finish; + window.getIosAccessOriginParam = finish; + + if (!isAppEnvironment()) { + finish(null); + return; + } + + // Aslan Flutter 在页面完成后注入 window.app.getAccessOrigin;这里轮询短时间等待,避免首屏请求早于注入而丢登录态。 + if ( + window.app && + typeof window.app.getAccessOrigin === 'function' + ) { + try { + finish(window.app.getAccessOrigin()); + return; + } catch (_) {} + } + if ( + window.FlutterApp && + typeof window.FlutterApp.postMessage === 'function' + ) { + try { + window.FlutterApp.postMessage('requestAccessOrigin'); + } catch (_) {} + } + + var attempt = 0; + var poll = function () { + attempt += 1; + if ( + window.app && + typeof window.app.getAccessOrigin === 'function' + ) { + try { + finish(window.app.getAccessOrigin()); + return; + } catch (_) {} + } + if (!settled && attempt < 30) window.setTimeout(poll, 80); + }; + poll(); + timeoutId = window.setTimeout(function () { + finish(null); + }, 2400); + }); + } + + function connectToApp() { + if (readyPromise) return readyPromise; + ensureAslanAppCode(); + applyDiscoveredHeaders(); + readyPromise = requestAccessOrigin().then(function () { + return { + baseURL: baseURL(), + headers: Object.assign({}, headers), + authenticated: Boolean(headers.authorization), + }; + }); + return readyPromise; + } + + function parseResponse(response) { + return response.text().then(function (text) { + var payload = text ? JSON.parse(text) : {}; + if (!response.ok) { + var httpError = new Error( + payload.message || + payload.errorMsg || + response.statusText || + 'request_failed' + ); + httpError.status = response.status; + httpError.payload = payload; + throw httpError; + } + if (payload && payload.status === false) { + var apiError = new Error( + payload.message || + payload.errorMsg || + payload.error || + 'api_request_failed' + ); + apiError.payload = payload; + apiError.code = payload.errorCode || payload.code; + throw apiError; + } + if ( + payload && + Object.prototype.hasOwnProperty.call(payload, 'body') + ) { + return payload.body; + } + if ( + payload && + Object.prototype.hasOwnProperty.call(payload, 'data') + ) { + return payload.data; + } + return payload; + }); + } + + function request(path, options) { + var opts = options || {}; + var body = opts.body; + if (body && typeof body === 'object' && !(body instanceof FormData)) { + body = JSON.stringify(body); + } + return connectToApp().then(function () { + var requestHeaders = Object.assign({}, headers, opts.headers || {}); + if (!requestHeaders.authorization) + delete requestHeaders.authorization; + if (body) { + requestHeaders['content-type'] = + requestHeaders['content-type'] || 'application/json'; + } + return window + .fetch(buildURL(path, opts.query), { + method: opts.method || 'GET', + headers: requestHeaders, + body: body, + credentials: 'omit', + cache: 'no-store', + }) + .then(parseResponse); + }); + } + + function back() { + if ( + window.FlutterPageControl && + window.FlutterPageControl.postMessage + ) { + window.FlutterPageControl.postMessage('close_page'); + return; + } + if (window.HyAppBridge && window.HyAppBridge.back) { + window.HyAppBridge.back(); + return; + } + window.history.back(); + } + + window.AslanCommon = { + baseURL: baseURL, + buildURL: buildURL, + headers: function () { + return Object.assign({}, headers); + }, + connectToApp: connectToApp, + setHeadersFromApp: setHeadersFromApp, + request: request, + get: function (path, queryData) { + return request(path, { method: 'GET', query: queryData }); + }, + post: function (path, body, queryData) { + return request(path, { + method: 'POST', + body: body, + query: queryData, + }); + }, + back: back, + user: { + profile: function () { + return request('/user/user-profile/user-id', { method: 'GET' }); + }, + }, + rechargeReward: { + status: function () { + return request( + '/activity/cumulative-recharge/recharge-reward', + { + method: 'GET', + } + ); + }, + claim: function (ruleId) { + return request('/activity/cumulative-recharge', { + method: 'POST', + body: { id: String(ruleId || '') }, + }); + }, + }, + }; +})(); diff --git a/yumi_commmon/yumi-common.js b/common_yumi/yumi-common.js similarity index 100% rename from yumi_commmon/yumi-common.js rename to common_yumi/yumi-common.js diff --git a/gonghui/coinseller-center/script.js b/gonghui/coinseller-center/script.js index c9be237..b2b7b32 100644 --- a/gonghui/coinseller-center/script.js +++ b/gonghui/coinseller-center/script.js @@ -701,9 +701,15 @@ : Array.isArray(source) ? source : []; - return items.map(function (item, index) { - return normalizeSubSeller(item, index); - }); + return items + .map(function (item, index) { + return normalizeSubSeller(item, index); + }) + .filter(function (item) { + var status = String(item.status || '').toLowerCase(); + // 列表接口的服务端契约只返回 active 直属关系;这里再过滤一次,避免异常数据把 pending 申请展示成可转账子币商。 + return !status || status === 'active'; + }); } function applyMockData() { @@ -1301,6 +1307,14 @@ function inviteSubSeller() { var input = $('inviteSubSellerInput'); var displayID = String(input.value || '').trim(); + if (!data.subSellerPermission.canInvite) { + setStatus( + $('inviteSubSellerStatus'), + t('coinseller_center.invite_failed', 'Invite failed.'), + 'warning' + ); + return; + } if (!displayID) { setStatus( $('inviteSubSellerStatus'), @@ -1310,22 +1324,13 @@ return; } if (state.isMock) { - data.subSellers.unshift({ - uid: displayID, - userId: displayID, - name: t( - 'coinseller_center.user_name_template', - 'User {id}' - ).replace('{id}', displayID), - avatar: avatarData(displayID, '#efe4ff', '#7d57c7'), - status: 'active', - balance: 0, - }); input.value = ''; - renderSubSellers(); closeModal('inviteSubSellerModal'); toast( - t('coinseller_center.invite_success', 'Invitation submitted.') + t( + 'coinseller_center.invite_success', + 'Official will review your invitation within 24 hours.' + ) ); return; } @@ -1345,41 +1350,27 @@ t('coinseller_center.loading', 'Loading...'), '' ); - // 直开子币商是有状态写操作,必须使用 command_id 让移动端重试或重复点击时由服务端保持幂等。 + // 邀请子币商现在只创建待审核申请;command_id 保证移动端重试不会重复生成多个 pending 申请。 window.HyAppAPI.wallet .inviteCoinSellerSubSeller({ command_id: subSellerCommandID('invite'), target_display_user_id: displayID, }) .then(function (response) { - var payload = unwrapData(response) || {}; - var seller = normalizeSubSeller( - payload.child || - payload.sub_seller || - payload.subSeller || - payload, - data.subSellers.length - ); - if (seller.uid) { - data.subSellers = data.subSellers.filter(function (item) { - return String(item.uid) !== String(seller.uid); - }); - data.subSellers.unshift(seller); - } input.value = ''; setStatus( $('inviteSubSellerStatus'), t( 'coinseller_center.invite_success', - 'Invitation submitted.' + 'Official will review your invitation within 24 hours.' ), 'success' ); - renderSubSellers(); + // 申请提交成功不代表父子关系已经生效,列表必须继续以服务端 active 关系为准。 toast( t( 'coinseller_center.invite_success', - 'Invitation submitted.' + 'Official will review your invitation within 24 hours.' ) ); closeModal('inviteSubSellerModal');