2026-07-12 17:38:53 +08:00

438 lines
15 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 () {
'use strict';
var state = {
range: null,
data: null,
tab: 'agency',
loading: false,
mutating: false,
removingHost: null,
};
function $(id) {
return document.getElementById(id);
}
function t(key, fallback) {
return window.HyAppI18n && window.HyAppI18n.t
? window.HyAppI18n.t(key, fallback)
: fallback || key;
}
function toast(message) {
if (window.HyAppToast) window.HyAppToast.show(message);
}
function count(value) {
if (value === null || value === undefined || !Number.isFinite(value)) {
return '—';
}
return Number(value).toLocaleString(undefined, {
maximumFractionDigits: 0,
});
}
function duration(value) {
if (!Number.isFinite(value)) return '—';
var minutes = Math.max(0, Math.floor(Number(value) / 60000));
var hours = Math.floor(minutes / 60);
var rest = minutes % 60;
if (!hours) return rest + t('fami_unit.minute_short', 'm');
return (
hours +
t('fami_unit.hour_short', 'h') +
(rest ? ' ' + rest + t('fami_unit.minute_short', 'm') : '')
);
}
function dateTime(value) {
if (!Number(value)) return '—';
return new Date(Number(value)).toLocaleString(undefined, {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
});
}
function renderIdentity() {
if (!state.data) return;
var agency = state.data.agency || {};
$('agencyName').textContent = agency.name || '—';
$('agencyID').textContent =
t('fami_agency.id_prefix', 'Agency ID:') +
' ' +
(agency.shortId || agency.id || '—');
$('createdAt').textContent =
t('fami_agency.created_prefix', 'Created:') +
' ' +
dateTime(agency.createdAtMS);
$('agencyInitial').textContent = String(agency.name || 'A')
.trim()
.charAt(0)
.toUpperCase();
$('agencyAvatar').hidden = !agency.avatar;
$('agencyInitial').hidden = !!agency.avatar;
if (agency.avatar) $('agencyAvatar').src = agency.avatar;
$('contactValue').textContent = state.data.contact || '—';
$('diamondBalance').textContent = count(state.data.pointBalance);
}
function renderSummary() {
var summary =
state.data && state.data.stats
? state.data.stats.summary || {}
: {};
$('totalEarnings').textContent = count(summary.total_earnings);
$('giftIncome').textContent = count(summary.gift_income);
$('shareIncome').textContent = count(summary.share_income);
$('totalHosts').textContent = count(summary.total_hosts);
$('giftedHosts').textContent = count(summary.gifted_host_count);
var statsError = state.data && state.data.errors.stats;
$('statsStatus').hidden = !statsError;
if (statsError) {
$('statsStatus').textContent = t(
'fami_common.stats_unavailable',
'Statistics are temporarily unavailable.'
);
}
}
function hostAvatar(host) {
var shell = document.createElement('span');
shell.className = 'host-avatar';
if (host.avatar) {
var image = document.createElement('img');
image.src = host.avatar;
image.alt = '';
shell.appendChild(image);
} else {
shell.textContent = String(host.name || 'H')
.charAt(0)
.toUpperCase();
}
return shell;
}
function textCell(row, value) {
var cell = document.createElement('td');
cell.textContent = value;
row.appendChild(cell);
}
function renderHosts() {
var hosts =
state.data && state.data.stats ? state.data.stats.hosts || [] : [];
var body = $('hostTableBody');
body.textContent = '';
hosts.forEach(function (host) {
var row = document.createElement('tr');
var identityCell = document.createElement('td');
var identity = document.createElement('div');
identity.className = 'host-identity';
identity.appendChild(hostAvatar(host));
var copy = document.createElement('span');
copy.className = 'host-copy';
var name = document.createElement('strong');
name.textContent = host.name || '—';
var id = document.createElement('span');
id.textContent =
t('fami_common.uid_prefix', 'UID:') +
' ' +
(host.displayUserId || host.userId || '—');
copy.appendChild(name);
copy.appendChild(id);
identity.appendChild(copy);
identityCell.appendChild(identity);
row.appendChild(identityCell);
textCell(row, count(host.diamondEarnings));
textCell(row, count(host.diamondExchanged));
textCell(row, count(host.giftSenders));
textCell(row, duration(host.onlineDurationMS));
textCell(row, duration(host.validMicDurationMS));
textCell(row, count(host.validMicDays));
textCell(row, dateTime(host.joinedAtMS));
var actionCell = document.createElement('td');
var remove = document.createElement('button');
remove.type = 'button';
remove.className = 'remove-button';
if (host.removable) {
remove.setAttribute('data-remove-host', host.userId);
remove.textContent = t('fami_agency.remove', 'Remove');
} else {
remove.disabled = true;
remove.textContent = t('fami_agency.owner', 'Owner');
}
actionCell.appendChild(remove);
row.appendChild(actionCell);
body.appendChild(row);
});
$('hostEmpty').hidden = hosts.length > 0;
$('hostCountLabel').textContent = t(
'fami_agency.host_count',
'{count} hosts'
).replace('{count}', count(hosts.length));
}
function renderRange() {
document.querySelectorAll('[data-range]').forEach(function (button) {
button.setAttribute(
'aria-pressed',
button.getAttribute('data-range') === state.range.preset
? 'true'
: 'false'
);
button.disabled = state.loading;
});
$('rangeCaption').textContent =
state.range.startDate === state.range.endDate
? state.range.startDate
: state.range.startDate + ' ' + state.range.endDate;
}
function renderTabs() {
document.querySelectorAll('[data-tab]').forEach(function (button) {
button.setAttribute(
'aria-selected',
button.getAttribute('data-tab') === state.tab ? 'true' : 'false'
);
});
$('agencyPanel').hidden = state.tab !== 'agency';
$('hostsPanel').hidden = state.tab !== 'hosts';
$('dataTitle').textContent =
state.tab === 'agency'
? t('fami_agency.tab_agency', 'Agency data')
: t('fami_agency.tab_hosts', 'Host data');
}
function renderAll() {
renderIdentity();
renderSummary();
renderHosts();
renderRange();
renderTabs();
}
function setLoading(value) {
state.loading = value;
document.body.classList.toggle('is-loading', value);
renderRange();
}
function setMutating(value) {
state.mutating = value;
document.body.classList.toggle('is-mutating', value);
}
function load() {
setLoading(true);
return window.HyGuild.agencyCenter
.load(state.range)
.then(function (data) {
state.data = data;
renderAll();
})
.catch(function () {
toast(
t(
'fami_agency.load_failed',
'Unable to load Agency Center.'
)
);
$('statsStatus').hidden = false;
$('statsStatus').textContent = t(
'fami_agency.load_failed',
'Unable to load Agency Center.'
);
})
.finally(function () {
setLoading(false);
});
}
function selectRange(preset) {
if (preset === 'custom') {
$('rangeStart').value = state.range.startDate;
$('rangeEnd').value = state.range.endDate;
$('rangeDialog').showModal();
return;
}
state.range = window.HyGuild.dateRange.create(preset);
renderRange();
load();
}
function applyCustomRange(event) {
event.preventDefault();
try {
state.range = window.HyGuild.dateRange.create('custom', {
start: $('rangeStart').value,
end: $('rangeEnd').value,
});
} catch (_) {
toast(t('fami_range.invalid', 'Choose a valid date range.'));
return;
}
$('rangeDialog').close();
load();
}
function saveContact(event) {
event.preventDefault();
if (state.mutating) return;
var value = String($('contactInput').value || '').trim();
if (!value) {
toast(t('fami_agency.contact_required', 'Enter a contact number.'));
return;
}
setMutating(true);
window.HyGuild.agencyCenter
.saveContact(value)
.then(function () {
state.data.contact = value;
$('contactDialog').close();
renderIdentity();
toast(t('fami_agency.contact_saved', 'Contact saved.'));
})
.catch(function () {
toast(
t(
'fami_agency.contact_save_failed',
'Unable to save contact.'
)
);
})
.finally(function () {
setMutating(false);
});
}
function inviteHost(event) {
event.preventDefault();
if (state.mutating) return;
var displayID = String($('inviteHostID').value || '').trim();
if (!displayID) return;
setMutating(true);
window.HyGuild.agencyCenter
.inviteHost(displayID)
.then(function () {
$('inviteDialog').close();
toast(
t(
'fami_agency.invite_sent',
'Invitation sent. The host must accept it.'
)
);
})
.catch(function () {
toast(t('fami_agency.invite_failed', 'Unable to invite host.'));
})
.finally(function () {
setMutating(false);
});
}
function openRemove(hostUserID) {
var hosts = state.data.stats.hosts || [];
state.removingHost = hosts.find(function (host) {
return host.userId === hostUserID;
});
if (!state.removingHost) return;
$('removeMessage').textContent = t(
'fami_agency.remove_confirm',
'Remove {name} from this agency? Historical earnings will remain unchanged.'
).replace('{name}', state.removingHost.name || hostUserID);
$('removeDialog').showModal();
}
function removeHost(event) {
event.preventDefault();
if (state.mutating || !state.removingHost) return;
var target = state.removingHost;
setMutating(true);
window.HyGuild.agencyCenter
.removeHost(target.userId)
.then(function () {
// 成员关系由后端原子结束;成功后重拉统计,不能只在本地删行伪造 total_hosts。
$('removeDialog').close();
state.removingHost = null;
toast(t('fami_agency.host_removed', 'Host removed.'));
return load();
})
.catch(function () {
toast(t('fami_agency.remove_failed', 'Unable to remove host.'));
})
.finally(function () {
setMutating(false);
});
}
function bind() {
$('backButton').addEventListener('click', function () {
if (window.history.length > 1) window.history.back();
else if (window.HyAppBridge) window.HyAppBridge.back();
});
$('withdrawButton').addEventListener('click', function () {
window.location.href =
window.HyGuild.product.buildURL('../wallet/');
});
$('editContactButton').addEventListener('click', function () {
$('contactInput').value = (state.data && state.data.contact) || '';
$('contactDialog').showModal();
});
$('cancelContactButton').addEventListener('click', function () {
$('contactDialog').close();
});
$('contactForm').addEventListener('submit', saveContact);
document
.querySelector('.data-tabs')
.addEventListener('click', function (event) {
var button = event.target.closest('[data-tab]');
if (!button) return;
state.tab = button.getAttribute('data-tab');
renderTabs();
});
$('rangeFilters').addEventListener('click', function (event) {
var button = event.target.closest('[data-range]');
if (button && !state.loading)
selectRange(button.getAttribute('data-range'));
});
$('cancelRangeButton').addEventListener('click', function () {
$('rangeDialog').close();
});
$('rangeForm').addEventListener('submit', applyCustomRange);
$('addHostButton').addEventListener('click', function () {
$('inviteHostID').value = '';
$('inviteDialog').showModal();
});
$('cancelInviteButton').addEventListener('click', function () {
$('inviteDialog').close();
});
$('inviteForm').addEventListener('submit', inviteHost);
$('hostTableBody').addEventListener('click', function (event) {
var button = event.target.closest('[data-remove-host]');
if (button) openRemove(button.getAttribute('data-remove-host'));
});
$('cancelRemoveButton').addEventListener('click', function () {
$('removeDialog').close();
});
$('removeForm').addEventListener('submit', removeHost);
window.addEventListener('hyapp:i18n-ready', renderAll);
}
function init() {
state.range = window.HyGuild.dateRange.create('today');
bind();
renderRange();
load();
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();