398 lines
14 KiB
JavaScript
398 lines
14 KiB
JavaScript
(function () {
|
||
var ui = window.FamiCenterUI;
|
||
var fallbackAvatar =
|
||
'../../products/fami/centers/assets/fami/bd-avatar.png';
|
||
var dates = [];
|
||
var contactController = null;
|
||
var state = {
|
||
profile: null,
|
||
owner: null,
|
||
agencies: [],
|
||
dailyAgencies: {},
|
||
dailyRequestSequence: 0,
|
||
inviteProfile: null,
|
||
inviting: false,
|
||
};
|
||
|
||
var mockItems = Array.from({ length: 5 }, function (_, index) {
|
||
return {
|
||
agency: {
|
||
agency_id: 'agency-' + index,
|
||
name: 'agency ' + (index + 1),
|
||
avatar: fallbackAvatar,
|
||
},
|
||
owner: {
|
||
user_id: 'owner-' + index,
|
||
display_user_id: '12345' + (index + 10),
|
||
username: 'agency ' + (index + 1),
|
||
avatar: fallbackAvatar,
|
||
},
|
||
diamond_earnings: 123214,
|
||
};
|
||
});
|
||
|
||
var mock = {
|
||
user: {
|
||
user_id: 'bd-123456789',
|
||
display_user_id: '123456789',
|
||
username: 'konghuimingc',
|
||
avatar: fallbackAvatar,
|
||
contact_info: '+65 1234 5678',
|
||
},
|
||
overview: {
|
||
profile: {
|
||
user_id: 'bd-123456789',
|
||
display_user_id: '123456789',
|
||
username: 'konghuimingc',
|
||
avatar: fallbackAvatar,
|
||
},
|
||
},
|
||
stats: { items: mockItems },
|
||
};
|
||
|
||
function normalizeAgency(item) {
|
||
item = item || {};
|
||
var agency = item.agency || {};
|
||
var owner = item.owner || {};
|
||
return {
|
||
id: String(agency.agency_id || ''),
|
||
displayId: String(owner.display_user_id || ''),
|
||
name: String(owner.username || agency.name || 'Agency'),
|
||
avatar: String(owner.avatar || agency.avatar || ''),
|
||
diamondEarnings: ui.number(item.diamond_earnings),
|
||
};
|
||
}
|
||
|
||
function applyStats(payload, date) {
|
||
var data = ui.unwrap(payload) || {};
|
||
var items = Array.isArray(data.items)
|
||
? data.items.map(normalizeAgency)
|
||
: [];
|
||
state.agencies = items;
|
||
if (date) state.dailyAgencies[date] = items;
|
||
}
|
||
|
||
function agencyValue(agency, index) {
|
||
var date = dates[index] && dates[index].value;
|
||
var daily = state.dailyAgencies[date] || [];
|
||
var item = daily.find(function (candidate) {
|
||
return candidate.id === agency.id;
|
||
});
|
||
return item ? item.diamondEarnings : 0;
|
||
}
|
||
|
||
function renderProfile() {
|
||
var profile = state.profile || {};
|
||
var owner = state.owner || profile;
|
||
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.$('contactName').textContent = owner.name || profile.name || '-';
|
||
ui.$('contactUserId').textContent = ui
|
||
.t('fami.user_id', 'User ID:{id}')
|
||
.replace('{id}', owner.displayId || profile.displayId || '-');
|
||
if (contactController)
|
||
contactController.setContact(owner.contact || '');
|
||
}
|
||
|
||
function renderTable() {
|
||
dates = ui.dateWindow(9);
|
||
var grid = document.createElement('div');
|
||
grid.className = 'bd-agency-table__grid';
|
||
var header = document.createElement('div');
|
||
header.className = 'bd-agency-table__header';
|
||
dates.forEach(function (date) {
|
||
var head = document.createElement('span');
|
||
head.className = 'bd-agency-table__head';
|
||
head.textContent = ui.isMock()
|
||
? ui.t('fami.today', 'Today')
|
||
: date.label;
|
||
head.setAttribute('aria-label', date.label + ' ' + date.value);
|
||
header.appendChild(head);
|
||
});
|
||
var rows = document.createElement('div');
|
||
rows.className = 'bd-agency-table__rows';
|
||
state.agencies.forEach(function (agency) {
|
||
var avatar = document.createElement('img');
|
||
avatar.className = 'bd-agency-table__avatar';
|
||
avatar.alt = '';
|
||
ui.setAvatar(avatar, agency.avatar, fallbackAvatar);
|
||
rows.appendChild(avatar);
|
||
dates.slice(0, 8).forEach(function (_, index) {
|
||
var value = document.createElement('span');
|
||
value.className = 'bd-agency-table__value';
|
||
value.textContent = ui
|
||
.formatNumber(agencyValue(agency, index))
|
||
.replace(/,/g, '');
|
||
rows.appendChild(value);
|
||
});
|
||
});
|
||
grid.appendChild(header);
|
||
grid.appendChild(rows);
|
||
ui.$('agencyTable').replaceChildren(grid);
|
||
}
|
||
|
||
function render() {
|
||
renderProfile();
|
||
renderTable();
|
||
}
|
||
|
||
function applyPayloads(userPayload, overviewPayload, statsPayload) {
|
||
var overview = ui.unwrap(overviewPayload) || {};
|
||
state.profile = ui.profileFrom(overview.profile || overview, 'BD');
|
||
state.owner = ui.profileFrom(userPayload, state.profile.name);
|
||
applyStats(statsPayload, dates[0] && dates[0].value);
|
||
render();
|
||
}
|
||
|
||
function loadDailyMatrix() {
|
||
if (ui.isMock()) {
|
||
dates.slice(0, 8).forEach(function (date) {
|
||
state.dailyAgencies[date.value] =
|
||
mockItems.map(normalizeAgency);
|
||
});
|
||
renderTable();
|
||
return;
|
||
}
|
||
var api = window.HyAppAPI && window.HyAppAPI.bdCenter;
|
||
if (!api || !api.stats) return;
|
||
var sequence = ++state.dailyRequestSequence;
|
||
// 每列独立读取对应 UTC 日,单日失败只留空该列;复制聚合值会把真实团队收益错误归到其他日期。
|
||
Promise.all(
|
||
dates.slice(0, 8).map(function (date) {
|
||
return ui.safe('bd-stats-' + date.value, function () {
|
||
return api.stats({
|
||
start_date: date.value,
|
||
end_date: date.value,
|
||
});
|
||
});
|
||
})
|
||
).then(function (payloads) {
|
||
if (sequence !== state.dailyRequestSequence) return;
|
||
payloads.forEach(function (payload, index) {
|
||
var day = dates[index] && dates[index].value;
|
||
var data = ui.unwrap(payload) || {};
|
||
state.dailyAgencies[day] = Array.isArray(data.items)
|
||
? data.items.map(normalizeAgency)
|
||
: [];
|
||
});
|
||
renderTable();
|
||
});
|
||
}
|
||
|
||
function load() {
|
||
dates = ui.dateWindow(9);
|
||
if (ui.isMock()) {
|
||
applyPayloads(mock.user, mock.overview, mock.stats);
|
||
loadDailyMatrix();
|
||
return;
|
||
}
|
||
var api = window.HyAppAPI;
|
||
if (!api || !api.bdCenter || !api.bdCenter.stats) {
|
||
render();
|
||
ui.toast(
|
||
ui.t('bd_center.api_not_ready', 'API module is not ready.')
|
||
);
|
||
return;
|
||
}
|
||
|
||
// BD 资料和团队收益属于不同 owner;初始只取今天建立行集合,随后并行补齐八日矩阵,避免用 agency 列表里的 host_count/工资字段冒充收益。
|
||
Promise.all([
|
||
ui.safe('bd-owner', function () {
|
||
return api.user.me();
|
||
}),
|
||
ui.safe('bd-overview', function () {
|
||
return api.bdCenter.overview();
|
||
}),
|
||
ui.safe('bd-stats', function () {
|
||
return api.bdCenter.stats({
|
||
start_date: dates[0].value,
|
||
end_date: dates[0].value,
|
||
});
|
||
}),
|
||
]).then(function (results) {
|
||
applyPayloads(results[0], results[1], results[2]);
|
||
loadDailyMatrix();
|
||
if (!results.some(Boolean)) {
|
||
ui.toast(
|
||
ui.t(
|
||
'bd_center.load_failed',
|
||
'Load failed. Try again later.'
|
||
)
|
||
);
|
||
}
|
||
});
|
||
}
|
||
|
||
function setInviteStatus(message, success) {
|
||
var node = ui.$('inviteStatus');
|
||
node.textContent = message || '';
|
||
node.hidden = !message;
|
||
node.classList.toggle('is-success', !!success);
|
||
}
|
||
|
||
function renderInviteResult() {
|
||
var root = ui.$('inviteResult');
|
||
root.replaceChildren();
|
||
if (!state.inviteProfile) return;
|
||
var row = document.createElement('div');
|
||
row.className = 'fami-search-result';
|
||
var avatar = document.createElement('img');
|
||
avatar.alt = '';
|
||
ui.setAvatar(avatar, state.inviteProfile.avatar, fallbackAvatar);
|
||
var copy = document.createElement('div');
|
||
copy.className = 'fami-search-result__copy';
|
||
var name = document.createElement('strong');
|
||
name.textContent = state.inviteProfile.name || 'Agency';
|
||
var id = document.createElement('span');
|
||
id.textContent = 'ID: ' + state.inviteProfile.displayId;
|
||
var action = document.createElement('button');
|
||
action.className = 'fami-search-result__action';
|
||
action.type = 'button';
|
||
action.disabled = state.inviting;
|
||
action.textContent = state.inviting
|
||
? ui.t('bd_center.pending', 'Pending')
|
||
: ui.t('bd_center.invite', 'Invite');
|
||
action.addEventListener('click', inviteAgency);
|
||
copy.appendChild(name);
|
||
copy.appendChild(id);
|
||
row.appendChild(avatar);
|
||
row.appendChild(copy);
|
||
row.appendChild(action);
|
||
root.appendChild(row);
|
||
}
|
||
|
||
function searchInvite(event) {
|
||
event.preventDefault();
|
||
var value = String(ui.$('inviteSearchInput').value || '').trim();
|
||
state.inviteProfile = null;
|
||
renderInviteResult();
|
||
if (!value) return;
|
||
if (ui.isMock()) {
|
||
state.inviteProfile = ui.profileFrom(mock.user, 'Agency');
|
||
state.inviteProfile.id = 'mock-agency-' + value;
|
||
state.inviteProfile.displayId = value;
|
||
renderInviteResult();
|
||
return;
|
||
}
|
||
var api = window.HyAppAPI && window.HyAppAPI.user;
|
||
if (!api || !api.resolveDisplayUserID) {
|
||
setInviteStatus(
|
||
ui.t('bd_center.api_not_ready', 'API module is not ready.')
|
||
);
|
||
return;
|
||
}
|
||
ui.$('inviteSearchButton').disabled = true;
|
||
setInviteStatus(ui.t('bd_center.searching', 'Searching...'));
|
||
api.resolveDisplayUserID(value)
|
||
.then(function (payload) {
|
||
state.inviteProfile = ui.profileFrom(payload, 'Agency');
|
||
if (!state.inviteProfile.id) state.inviteProfile = null;
|
||
if (state.inviteProfile && !state.inviteProfile.displayId) {
|
||
state.inviteProfile.displayId = value;
|
||
}
|
||
setInviteStatus(
|
||
state.inviteProfile
|
||
? ''
|
||
: ui.t('bd_center.no_users_found', 'No users found')
|
||
);
|
||
renderInviteResult();
|
||
})
|
||
.catch(function (error) {
|
||
setInviteStatus(
|
||
(error && error.message) ||
|
||
ui.t(
|
||
'bd_center.search_failed',
|
||
'Search failed. Try again later.'
|
||
)
|
||
);
|
||
})
|
||
.finally(function () {
|
||
ui.$('inviteSearchButton').disabled = false;
|
||
});
|
||
}
|
||
|
||
function inviteAgency() {
|
||
if (!state.inviteProfile || state.inviting) return;
|
||
if (ui.isMock()) {
|
||
setInviteStatus(
|
||
ui.t('bd_center.invitation_submitted', 'Invitation submitted'),
|
||
true
|
||
);
|
||
return;
|
||
}
|
||
var api = window.HyAppAPI && window.HyAppAPI.bdCenter;
|
||
if (!api || !api.inviteAgency) return;
|
||
state.inviting = true;
|
||
renderInviteResult();
|
||
// 创建公会邀请会触发角色与归属流转;command_id 保证重试幂等,后端确认前不本地伪造公会记录。
|
||
api.inviteAgency({
|
||
command_id: ui.commandId('bd-agency'),
|
||
target_user_id: state.inviteProfile.id,
|
||
agency_name: state.inviteProfile.name,
|
||
})
|
||
.then(function () {
|
||
setInviteStatus(
|
||
ui.t(
|
||
'bd_center.invitation_submitted',
|
||
'Invitation submitted'
|
||
),
|
||
true
|
||
);
|
||
state.inviteProfile = null;
|
||
renderInviteResult();
|
||
})
|
||
.catch(function (error) {
|
||
setInviteStatus(
|
||
(error && error.message) ||
|
||
ui.t(
|
||
'bd_center.invite_failed',
|
||
'Invite failed. Try again later.'
|
||
)
|
||
);
|
||
})
|
||
.finally(function () {
|
||
state.inviting = false;
|
||
renderInviteResult();
|
||
});
|
||
}
|
||
|
||
function openInvite() {
|
||
state.inviteProfile = null;
|
||
ui.$('inviteSearchInput').value = '';
|
||
setInviteStatus('');
|
||
renderInviteResult();
|
||
ui.openModal('inviteModal');
|
||
}
|
||
|
||
function init() {
|
||
contactController = ui.bindContact();
|
||
ui.$('backButton').addEventListener('click', function () {
|
||
ui.goBack();
|
||
});
|
||
ui.$('addGuildButton').addEventListener('click', openInvite);
|
||
ui.$('inviteSearchForm').addEventListener('submit', searchInvite);
|
||
document
|
||
.querySelectorAll('[data-invite-close]')
|
||
.forEach(function (node) {
|
||
node.addEventListener('click', function () {
|
||
ui.closeModal('inviteModal');
|
||
});
|
||
});
|
||
window.addEventListener('hyapp:i18n-ready', render);
|
||
render();
|
||
load();
|
||
if (window.HyAppBridge) {
|
||
window.HyAppBridge.ready({
|
||
page: 'bd-center',
|
||
app_code: 'fami',
|
||
mock: ui.isMock(),
|
||
});
|
||
}
|
||
}
|
||
|
||
document.addEventListener('DOMContentLoaded', init);
|
||
})();
|