303 lines
10 KiB
JavaScript
303 lines
10 KiB
JavaScript
(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);
|
||
})();
|