lalu store

This commit is contained in:
zhx 2026-06-04 23:47:28 +08:00
parent 0c5d01072d
commit 527484d3d8
4 changed files with 197 additions and 126 deletions

View File

@ -232,7 +232,11 @@
overflow: hidden;
border-radius: 12px;
background:
linear-gradient(145deg, rgba(255, 255, 255, 0.14), transparent),
linear-gradient(
145deg,
rgba(255, 255, 255, 0.14),
transparent
),
#1a1822;
box-shadow:
inset 0 0 0 1px rgba(255, 255, 255, 0.08),
@ -448,10 +452,7 @@
<p class="brand-name" id="hostName">Lalu</p>
</div>
<p
class="message"
data-i18n="lalu_landing.message"
>
<p class="message" data-i18n="lalu_landing.message">
送你一份礼物,快来和我一起玩吧!
</p>
@ -511,9 +512,7 @@
<img src="assets/lalu-logo.png" alt="Lalu" />
<div class="app-copy">
<strong>Lalu</strong>
<span data-i18n="lalu_landing.tagline">
结识新朋友
</span>
<span data-i18n="lalu_landing.tagline"> 结识新朋友 </span>
</div>
</div>
<button
@ -556,7 +555,11 @@
}
function resolveDownloadURL() {
var commonURL = firstParam(['downloadUrl', 'download_url', 'url']);
var commonURL = firstParam([
'downloadUrl',
'download_url',
'url',
]);
var iosURL = firstParam(['iosUrl', 'ios_url']);
var androidURL =
firstParam(['androidUrl', 'android_url']) ||

View File

@ -9,7 +9,10 @@
<title>BD Center</title>
<link rel="stylesheet" href="../../common/theme.css" />
<link rel="stylesheet" href="../common/center.css" />
<link rel="stylesheet" href="./style.css" />
<link
rel="stylesheet"
href="./style.css?v=20260604-bd-center-real-skeleton"
/>
</head>
<body>
@ -292,6 +295,6 @@
<script src="../../common/jsbridge.js"></script>
<script src="../../common/i18n.js"></script>
<script src="../../common/api.js?v=20260604-bd-center"></script>
<script src="./script.js?v=20260604-bd-center-api"></script>
<script src="./script.js?v=20260604-bd-center-real-skeleton"></script>
</body>
</html>

View File

@ -1,85 +1,30 @@
(function () {
var FIRST_BILL_MONTH = '2026-06';
var BD_SALARY_ASSET = 'BD_SALARY_USD';
var query = new URLSearchParams(window.location.search);
var mock = {
profile: {
name: 'BD_Jasmine',
uid: 'BD-163008',
avatar: avatarData('B', '#dbc8ff', '#7d57c7'),
},
balance: {
available: 48620.8,
},
billMonth: currentMonth(),
agencyBill: {
billTitle: '2026.06',
agencyNumber: 12,
totalSalary: 128450.35,
totalRecharge: 356900.0,
memberBillList: [
{
name: 'Yumi Star Agency',
account: '163003',
avatar: avatarData('Y', '#dbc8ff', '#7d57c7'),
teamSalaryAmount: 38420.55,
teamRechargeAmount: 126880,
teamMemberCount: 28,
},
{
name: 'Moon Live Agency',
account: '163086',
avatar: avatarData('M', '#f4ebff', '#7d57c7'),
teamSalaryAmount: 29106.2,
teamRechargeAmount: 98540,
teamMemberCount: 19,
},
{
name: 'Nova Host Guild',
account: '163221',
avatar: avatarData('N', '#dbc8ff', '#7d57c7'),
teamSalaryAmount: 22450,
teamRechargeAmount: 73150,
teamMemberCount: 16,
},
],
},
inviteRecords: [],
searchPool: [
{
userId: '3187099',
id: '3187099',
name: 'Agent_River',
account: '168899',
avatar: avatarData('R', '#dbc8ff', '#7d57c7'),
},
{
userId: '3187100',
id: '3187100',
name: 'Agent_Sara',
account: '168900',
avatar: avatarData('S', '#f4ebff', '#7d57c7'),
},
],
};
var data = {
profile: mock.profile,
balance: mock.balance,
billMonth: mock.billMonth,
agencyBill: mock.agencyBill,
inviteRecords: mock.inviteRecords,
profile: null,
balance: { available: 0 },
billMonth: currentMonth(),
agencyBill: {
agencyNumber: 0,
totalSalary: 0,
totalRecharge: 0,
memberBillList: [],
},
inviteRecords: [],
};
var state = {
billMonth: normalizeBillMonth(mock.billMonth),
billMonth: normalizeBillMonth(data.billMonth),
inviteQuery: '',
inviteMode: 'records',
inviteStatus: '',
inviteStatusType: '',
searched: [],
inviting: {},
isMock: query.get('mock') === '1',
searching: false,
loading: true,
};
function $(id) {
@ -256,6 +201,16 @@
});
}
function setSkeleton(element, loading, text) {
if (!element) return;
element.classList.toggle('skeleton-line', Boolean(loading));
if (loading) {
element.textContent = '';
return;
}
element.textContent = text || '';
}
function renderImageAvatar(container, src, name, fallbackClass) {
container.textContent = '';
if (!src) {
@ -355,9 +310,22 @@
function renderProfile() {
var image = $('profileAvatar');
var fallback = $('profileAvatarFallback');
var profile = data.profile || mock.profile;
$('profileName').textContent = profile.name || '-';
$('profileUID').textContent = 'UID: ' + (profile.uid || '-');
var profile = data.profile || {};
var loading = Boolean(state.loading);
setSkeleton($('profileName'), loading, profile.name || '-');
setSkeleton(
$('profileUID'),
loading,
'UID: ' + (profile.uid || '-')
);
fallback.classList.toggle('avatar-skeleton', loading);
if (loading) {
image.hidden = true;
image.removeAttribute('src');
fallback.hidden = false;
fallback.textContent = '';
return;
}
fallback.textContent = initial(profile.name) || 'B';
image.onload = function () {
image.hidden = false;
@ -375,7 +343,14 @@
}
function renderBalance() {
$('availableBalance').textContent = money(data.balance && data.balance.available);
var loading = Boolean(state.loading);
var coinIcon = document.querySelector('.salary-value .coin-icon');
if (coinIcon) coinIcon.classList.toggle('skeleton-coin', loading);
setSkeleton(
$('availableBalance'),
loading,
money(data.balance && data.balance.available)
);
}
function summaryCell(label, value) {
@ -389,6 +364,43 @@
return cell;
}
function summarySkeletonCell() {
var cell = document.createElement('div');
var labelNode = document.createElement('span');
var valueNode = document.createElement('strong');
labelNode.className = 'skeleton-line';
valueNode.className = 'skeleton-line';
cell.appendChild(labelNode);
cell.appendChild(valueNode);
return cell;
}
function skeletonMemberRow() {
var row = document.createElement('article');
var avatar = document.createElement('div');
var main = document.createElement('div');
var name = document.createElement('div');
var meta = document.createElement('div');
var side = document.createElement('div');
row.className = 'member-row is-skeleton';
avatar.className = 'member-avatar avatar-skeleton';
main.className = 'member-main';
name.className = 'member-name skeleton-line';
meta.className = 'member-meta skeleton-line';
side.className = 'member-side';
for (var i = 0; i < 3; i += 1) {
var line = document.createElement('div');
line.className = 'skeleton-line';
side.appendChild(line);
}
main.appendChild(name);
main.appendChild(meta);
row.appendChild(avatar);
row.appendChild(main);
row.appendChild(side);
return row;
}
function memberRow(item) {
var row = document.createElement('article');
var avatar = document.createElement('div');
@ -427,10 +439,23 @@
}
function renderTeamList() {
var bill = data.agencyBill || mock.agencyBill;
var bill = data.agencyBill;
$('billMonthText').textContent = monthLabel(state.billMonth);
$('billRange').textContent = state.billMonth.replace('-', '.');
if (state.loading) {
replaceChildren($('teamListSummary'), [
summarySkeletonCell(),
summarySkeletonCell(),
]);
replaceChildren($('teamListContent'), [
skeletonMemberRow(),
skeletonMemberRow(),
skeletonMemberRow(),
]);
return;
}
replaceChildren($('teamListSummary'), [
summaryCell(
t('bd_center.agency_number', 'Agency number'),
@ -502,9 +527,6 @@
state.billMonth = nextMonth;
closeMonthSheet();
renderTeamList();
if (state.isMock) {
toast(t('bd_center.mock_bill_loaded', 'Mock bill loaded.'));
}
}
function inviteProfile(item) {
@ -599,7 +621,8 @@
replaceChildren($('inviteList'), rows);
$('inviteEmpty').hidden =
rows.length > 0 || Boolean(state.inviteStatus);
$('inviteSearchButton').disabled = !state.inviteQuery.trim();
$('inviteSearchButton').disabled =
!state.inviteQuery.trim() || Boolean(state.searching);
}
function openInviteModal() {
@ -608,6 +631,7 @@
state.searched = [];
state.inviteStatus = '';
state.inviteStatusType = '';
state.searching = false;
$('inviteSearchInput').value = '';
$('inviteModal').hidden = false;
$('inviteModal').setAttribute('aria-hidden', 'false');
@ -624,17 +648,6 @@
document.body.classList.remove('modal-open');
}
function searchMockInvite(queryValue) {
var queryLower = queryValue.toLowerCase();
return mock.searchPool.filter(function (profile) {
return (
profile.name.toLowerCase().indexOf(queryLower) >= 0 ||
profile.account.indexOf(queryLower) >= 0 ||
profile.id.indexOf(queryLower) >= 0
);
});
}
function searchInvite(event) {
event.preventDefault();
var queryValue = state.inviteQuery.trim();
@ -646,17 +659,6 @@
renderInviteModal();
return;
}
if (state.isMock) {
state.searched = searchMockInvite(queryValue);
if (!state.searched.length) {
state.inviteStatus = t(
'bd_center.no_users_found',
'No users found'
);
}
renderInviteModal();
return;
}
if (!api().user || !api().user.resolveDisplayUserID) {
state.inviteStatus = t(
'bd_center.api_not_ready',
@ -667,6 +669,7 @@
return;
}
state.inviteStatus = t('bd_center.searching', 'Searching...');
state.searching = true;
renderInviteModal();
api()
.user.resolveDisplayUserID(queryValue)
@ -686,25 +689,16 @@
state.inviteStatusType = 'error';
state.searched = [];
renderInviteModal();
})
.finally(function () {
state.searching = false;
renderInviteModal();
});
}
function submitInvite(profile) {
var targetUserID = String(profile.userId || profile.id || '');
if (!targetUserID) return;
if (state.isMock) {
data.inviteRecords.unshift({
id: 'inv-' + Date.now(),
status: 'success',
profile: profile,
});
state.inviteMode = 'records';
state.searched = [];
state.inviteStatus = t('bd_center.agency_added', 'Agency added.');
state.inviteStatusType = 'success';
renderInviteModal();
return;
}
if (!centerAPI() || !centerAPI().inviteAgency) {
state.inviteStatus = t(
'bd_center.api_not_ready',
@ -758,17 +752,44 @@
'../withdraw-exchange/index.html?' + params.toString();
}
function setLoading(loading) {
state.loading = Boolean(loading);
render();
}
function loadRealData() {
var service = centerAPI();
if (state.isMock || !service) return Promise.resolve(false);
setLoading(true);
if (
!service ||
!service.overview ||
!service.agencies ||
!service.inviteAgency
) {
setLoading(false);
return Promise.reject(
new Error(t('bd_center.api_not_ready', 'API module is not ready.'))
);
}
return Promise.all([
service.overview(),
service.agencies(50),
]).then(function (results) {
applyOverview(results[0] || {});
applyAgencies(results[1] || {});
render();
return true;
}).catch(function (error) {
data.profile = null;
data.balance = { available: 0 };
data.agencyBill = {
agencyNumber: 0,
totalSalary: 0,
totalRecharge: 0,
memberBillList: [],
};
throw error;
}).finally(function () {
setLoading(false);
});
}
@ -827,7 +848,6 @@
if (window.HyAppBridge) {
window.HyAppBridge.ready({
page: 'bd-center',
mock: state.isMock,
});
}
});

View File

@ -70,6 +70,12 @@
overflow-wrap: anywhere;
}
.bd-center .salary-value strong.skeleton-line {
width: 180px;
height: 42px;
border-radius: 10px;
}
.team-stats-card,
.team-users-card {
display: grid;
@ -180,6 +186,18 @@
line-height: 1.15;
}
.team-list-summary span.skeleton-line {
width: 96px;
height: 13px;
border-radius: 7px;
}
.team-list-summary strong.skeleton-line {
width: 112px;
height: 19px;
border-radius: 8px;
}
.team-list-content {
display: grid;
gap: 10px;
@ -265,6 +283,33 @@
text-align: right;
}
.member-row.is-skeleton {
pointer-events: none;
}
.member-row.is-skeleton .member-avatar {
background: transparent;
}
.member-row.is-skeleton .member-name.skeleton-line {
width: min(132px, 100%);
height: 18px;
border-radius: 7px;
}
.member-row.is-skeleton .member-meta.skeleton-line {
width: 92px;
height: 14px;
border-radius: 7px;
}
.member-row.is-skeleton .member-side .skeleton-line {
width: 122px;
max-width: 28vw;
height: 13px;
border-radius: 6px;
}
.empty-state,
.invite-empty {
display: flex;