2026-07-17 11:54:43 +08:00

303 lines
10 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

(function () {
var ui = window.FamiCenterUI;
var fallbackAvatar =
'../../products/fami/centers/assets/fami/host-avatar.png';
var dates = [];
var activeDate = '';
var contactController = null;
var state = {
loading: true,
profile: null,
agency: null,
balance: 0,
stats: null,
statsRequestSequence: 0,
};
var metricDefinitions = [
{
key: 'diamond_earnings',
label: 'fami.diamond_earnings',
fallback: 'Diamond Earnings',
},
{
key: 'diamond_exchanged',
label: 'fami.diamond_exchanged',
fallback: 'Diamond Exchanged',
},
{
key: 'gift_senders',
label: 'fami.gift_senders',
fallback: 'Gift Senders',
},
{
key: 'online_duration_ms',
label: 'fami.online_minutes',
fallback: 'Online Minutes',
minutes: true,
},
{
key: 'valid_mic_duration_ms',
label: 'fami.valid_mic_minutes',
fallback: 'Valid Mic Minutes',
minutes: true,
},
{
key: 'valid_mic_days',
label: 'fami.valid_mic_days',
fallback: 'Valid Mic Days',
},
{
key: 'private_message_senders',
label: 'fami.private_chats',
fallback: 'Private Chats',
},
{
key: 'new_followers',
label: 'fami.new_followers',
fallback: 'New Followers',
},
];
var mock = {
profile: {
user_id: 'host-123456789',
display_user_id: '123456789',
username: 'konghuimingc',
avatar: fallbackAvatar,
contact_info: '+65 1234 5678',
created_at_ms: Date.UTC(2025, 5, 12, 8, 0, 0),
},
agency: {
agency: {
agency_id: '123456789',
short_id: '123456789',
name: 'konghuimingc',
joined_at_ms: Date.UTC(2025, 5, 12, 8, 0, 0),
},
},
coins: {
balances: [{ asset_type: 'COIN', available_amount: 1000000000 }],
},
stats: {
metrics: {
diamond_earnings: 999999,
diamond_exchanged: 999999,
gift_senders: 999999,
online_duration_ms: 999999 * 60000,
valid_mic_duration_ms: 999999 * 60000,
valid_mic_days: 999999,
private_message_senders: 999999,
new_followers: 999999,
},
},
};
function agencyFrom(payload) {
var data = ui.unwrap(payload) || {};
return data.agency || {};
}
function metricValues() {
var metrics = (state.stats && state.stats.metrics) || {};
return metricDefinitions.map(function (definition) {
var value = ui.number(metrics[definition.key]);
return definition.minutes ? Math.floor(value / 60000) : value;
});
}
function renderDates() {
dates = ui.dateWindow(7);
if (!activeDate && dates.length) activeDate = dates[0].value;
ui.renderDateStrip(ui.$('dateStrip'), dates, activeDate, selectDate);
}
function renderProfile() {
var profile = state.profile || {};
var agency = state.agency || {};
ui.setAvatar(ui.$('profileAvatar'), profile.avatar, fallbackAvatar);
ui.$('profileName').textContent = profile.name || '-';
ui.$('profileUserId').textContent = ui
.t('fami.user_id', 'User ID:{id}')
.replace('{id}', profile.displayId || '-');
ui.$('profileAgencyId').textContent = ui
.t('fami.agency_id', 'Agency ID:{id}')
.replace(
'{id}',
String(agency.short_id || agency.agency_id || '-')
);
var joinedAt = agency.joined_at_ms || profile.createdAt;
var joinedDate = joinedAt ? new Date(joinedAt) : null;
var formatted = '';
if (joinedDate && !Number.isNaN(joinedDate.getTime())) {
// 设计稿要求月名与 24 小时时间之间使用固定英文标点;手工拼接可避免浏览器插入 at 或本地化逗号。
var month = ui.formatDate(joinedDate, { month: 'long' });
formatted =
month +
' ' +
joinedDate.getDate() +
', ' +
joinedDate.getFullYear() +
', ' +
String(joinedDate.getHours()).padStart(2, '0') +
':' +
String(joinedDate.getMinutes()).padStart(2, '0');
}
ui.$('profileJoinTime').textContent = ui
.t('fami.join_time', 'Join time: {time}')
.replace('{time}', formatted || '-');
ui.$('contactName').textContent = profile.name || '-';
ui.$('contactUserId').textContent = ui
.t('fami.user_id', 'User ID:{id}')
.replace('{id}', profile.displayId || '-');
if (contactController)
contactController.setContact(profile.contact || '');
}
function renderMetrics() {
var grid = ui.$('metricGrid');
var values = metricValues();
grid.replaceChildren();
values.forEach(function (value, index) {
var card = document.createElement('div');
card.className = 'host-metric';
var number = document.createElement('strong');
number.textContent = ui.formatNumber(value).replace(/,/g, '');
var label = document.createElement('span');
var definition = metricDefinitions[index];
label.textContent = ui.isMock()
? ui.t('fami.diamond_earnings', 'Diamond Earnings')
: ui.t(definition.label, definition.fallback);
card.appendChild(number);
card.appendChild(label);
grid.appendChild(card);
});
}
function render() {
renderProfile();
ui.$('goldBalance').textContent = ui.formatNumber(state.balance);
renderDates();
renderMetrics();
}
function applyPayloads(
profilePayload,
agencyPayload,
coinPayload,
statsPayload
) {
state.profile = ui.profileFrom(profilePayload, 'Host');
state.agency = agencyFrom(agencyPayload);
state.balance = ui.walletAvailable(coinPayload, 'COIN');
state.stats = ui.unwrap(statsPayload) || { metrics: {} };
state.loading = false;
render();
}
function selectDate(value) {
activeDate = value;
renderDates();
if (ui.isMock()) {
renderMetrics();
return;
}
var api = window.HyAppAPI && window.HyAppAPI.hostCenter;
if (!api || !api.stats) return;
var sequence = ++state.statsRequestSequence;
// 日期快速切换时旧响应可能晚到;仅最后一次请求可以覆盖卡片,避免用户选中 A 日却看到 B 日数据。
api.stats({ start_date: value, end_date: value })
.then(function (payload) {
if (sequence !== state.statsRequestSequence) return;
state.stats = ui.unwrap(payload) || { metrics: {} };
renderMetrics();
})
.catch(function (error) {
if (sequence !== state.statsRequestSequence) return;
ui.toast(
(error && error.message) ||
ui.t(
'host_center.load_failed',
'Load failed. Try again later.'
)
);
});
}
function load() {
dates = ui.dateWindow(7);
if (!activeDate && dates.length) activeDate = dates[0].value;
if (ui.isMock()) {
applyPayloads(mock.profile, mock.agency, mock.coins, mock.stats);
return;
}
var api = window.HyAppAPI;
if (!api || !api.hostCenter || !api.hostCenter.stats) {
state.loading = false;
render();
ui.toast(
ui.t('host_center.api_not_ready', 'API module is not ready.')
);
return;
}
// 资料、归属、COIN 余额和选中自然日统计来自四个独立 owner部分失败仍保留其他已确认数据不能用工资余额或政策字段伪造金币/收益。
Promise.all([
ui.safe('host-profile', function () {
return api.user.me();
}),
ui.safe('host-agency', function () {
return api.hostCenter.agency();
}),
ui.safe('host-coins', function () {
return api.wallet.balances('COIN');
}),
ui.safe('host-stats', function () {
return api.hostCenter.stats({
start_date: activeDate,
end_date: activeDate,
});
}),
]).then(function (results) {
applyPayloads(results[0], results[1], results[2], results[3]);
if (!results.some(Boolean)) {
ui.toast(
ui.t(
'host_center.load_failed',
'Load failed. Try again later.'
)
);
}
});
}
function openWithdraw() {
// Center 与 Wallet 只继承认证、环境、语言和 mock 上下文;页面筛选参数不能泄漏到资金页。
window.location.href = window.HyGuild.product.buildURL('../wallet/', {
identity: 'HOST',
});
}
function init() {
contactController = ui.bindContact();
ui.$('backButton').addEventListener('click', function () {
ui.goBack();
});
ui.$('withdrawButton').addEventListener('click', openWithdraw);
window.addEventListener('hyapp:i18n-ready', render);
render();
load();
if (window.HyAppBridge) {
window.HyAppBridge.ready({
page: 'fami-host-center',
app_code: 'fami',
mock: ui.isMock(),
});
}
}
document.addEventListener('DOMContentLoaded', init);
})();