邀请活动ui优化
@ -86,6 +86,7 @@ const els = {
|
||||
navButtons: [...document.querySelectorAll("[data-nav-view]")],
|
||||
copyButtons: [...document.querySelectorAll("[data-copy-target]")],
|
||||
rankList: document.getElementById("rankList"),
|
||||
rankLists: [...document.querySelectorAll("[data-rank-list]")],
|
||||
giftTitle: document.getElementById("giftTitle"),
|
||||
giftAvatarImage: document.getElementById("giftAvatarImage"),
|
||||
downloadButton: document.getElementById("downloadButton"),
|
||||
@ -694,10 +695,38 @@ function renderTasks() {
|
||||
els.taskNote.textContent = DEFAULT_TASK_NOTES[state.taskSet] || "";
|
||||
}
|
||||
|
||||
function renderRankList() {
|
||||
function rankBadgeMarkup(item) {
|
||||
const badgeMap = {
|
||||
1: "./assets/rank-top1.png",
|
||||
2: "./assets/rank-top2.png",
|
||||
3: "./assets/rank-top3.png",
|
||||
};
|
||||
const badge = badgeMap[item.rank];
|
||||
return badge
|
||||
? `<img src="${badge}" alt="Rank ${item.rank}" />`
|
||||
: escapeHtml(String(item.rank));
|
||||
}
|
||||
|
||||
function renderRankRows(container) {
|
||||
const list = state.rankItems;
|
||||
const inline = container?.dataset?.rankVariant === "inline";
|
||||
if (!Array.isArray(list) || list.length === 0) {
|
||||
els.rankList.innerHTML = `
|
||||
return inline
|
||||
? `
|
||||
<article
|
||||
class="rank-row"
|
||||
style="background-image:url('./assets/rank-row.svg')"
|
||||
>
|
||||
<div class="rank-badge">--</div>
|
||||
<div class="avatar">
|
||||
<img src="${DEFAULT_AVATAR}" alt="" />
|
||||
</div>
|
||||
<div class="rank-name">No ranking data yet</div>
|
||||
<div class="rank-score">0人</div>
|
||||
<div class="rank-reward">0</div>
|
||||
</article>
|
||||
`
|
||||
: `
|
||||
<article
|
||||
class="rank-row"
|
||||
style="background-image:url('./assets/rank-row.svg')"
|
||||
@ -710,29 +739,31 @@ function renderRankList() {
|
||||
<div class="rank-score">0 people</div>
|
||||
</article>
|
||||
`;
|
||||
return;
|
||||
}
|
||||
|
||||
els.rankList.innerHTML = list.map((item) => {
|
||||
const badgeMap = {
|
||||
1: "./assets/rank-top1.png",
|
||||
2: "./assets/rank-top2.png",
|
||||
3: "./assets/rank-top3.png",
|
||||
};
|
||||
|
||||
const badge = badgeMap[item.rank];
|
||||
return list.map((item) => {
|
||||
if (inline) {
|
||||
return `
|
||||
<article
|
||||
class="rank-row"
|
||||
style="background-image:url('./assets/rank-row.svg')"
|
||||
>
|
||||
<div class="rank-badge">${rankBadgeMarkup(item)}</div>
|
||||
<div class="avatar">
|
||||
<img src="${escapeHtml(item.avatar || DEFAULT_AVATAR)}" alt="${escapeHtml(item.name)}" />
|
||||
</div>
|
||||
<div class="rank-name">${escapeHtml(item.name)}</div>
|
||||
<div class="rank-score">${escapeHtml(item.inviteCountText)}</div>
|
||||
<div class="rank-reward">${escapeHtml(item.rewardText)}</div>
|
||||
</article>
|
||||
`;
|
||||
}
|
||||
return `
|
||||
<article
|
||||
class="rank-row"
|
||||
style="background-image:url('./assets/rank-row.svg')"
|
||||
>
|
||||
<div class="rank-badge">
|
||||
${
|
||||
badge
|
||||
? `<img src="${badge}" alt="Rank ${item.rank}" />`
|
||||
: escapeHtml(String(item.rank))
|
||||
}
|
||||
</div>
|
||||
<div class="rank-badge">${rankBadgeMarkup(item)}</div>
|
||||
<div class="avatar">
|
||||
<img src="${escapeHtml(item.avatar || DEFAULT_AVATAR)}" alt="${escapeHtml(item.name)}" />
|
||||
</div>
|
||||
@ -743,6 +774,15 @@ function renderRankList() {
|
||||
}).join("");
|
||||
}
|
||||
|
||||
function renderRankList() {
|
||||
const containers = els.rankLists.length > 0
|
||||
? els.rankLists
|
||||
: [els.rankList].filter(Boolean);
|
||||
containers.forEach((container) => {
|
||||
container.innerHTML = renderRankRows(container);
|
||||
});
|
||||
}
|
||||
|
||||
function pad(number) {
|
||||
return String(number).padStart(2, "0");
|
||||
}
|
||||
@ -899,6 +939,8 @@ function normalizeRankList(list) {
|
||||
rank,
|
||||
name: userName,
|
||||
avatar: trimValue(item?.avatar) || DEFAULT_AVATAR,
|
||||
inviteCountText: `${formatMetric(inviteCount)}人`,
|
||||
rewardText: formatMetric(rewardGoldCoins),
|
||||
score: scoreParts.join(" · "),
|
||||
};
|
||||
});
|
||||
@ -1087,9 +1129,13 @@ async function refreshPageData() {
|
||||
if (state.view === "gift") {
|
||||
await fetchLandingData();
|
||||
} else {
|
||||
const hasHome = await fetchHomeData();
|
||||
if (hasHome) {
|
||||
await fetchRankData();
|
||||
const results = await Promise.allSettled([
|
||||
fetchHomeData(),
|
||||
fetchRankData(),
|
||||
]);
|
||||
const rejected = results.find((item) => item.status === "rejected");
|
||||
if (rejected) {
|
||||
throw rejected.reason;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
BIN
h5/app-invite/assets/btnselect.png
Normal file
|
After Width: | Height: | Size: 75 KiB |
BIN
h5/app-invite/assets/btnunselect.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
h5/app-invite/assets/djs.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
h5/app-invite/assets/mt1.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 62 KiB |
@ -28,8 +28,12 @@
|
||||
--ornate-top: url("./assets/panel-top.png");
|
||||
--ornate-middle: url("./assets/panel-middle.png");
|
||||
--ornate-bottom: url("./assets/panel-bottom.png");
|
||||
--button-active-bg: url("./assets/button-active-bg.png");
|
||||
--button-inactive-bg: url("./assets/button-inactive-bg.png");
|
||||
--monthly-title-bg: url("./assets/mt1.png");
|
||||
--task-tab-active-bg: url("./assets/btnselect.png");
|
||||
--task-tab-inactive-bg: url("./assets/btnunselect.png");
|
||||
--countdown-card-bg: url("./assets/djs.png");
|
||||
--button-active-bg: url("./assets/btnselect.png");
|
||||
--button-inactive-bg: url("./assets/btnunselect.png");
|
||||
}
|
||||
|
||||
* {
|
||||
@ -143,12 +147,27 @@
|
||||
|
||||
.ornate-panel {
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
isolation: isolate;
|
||||
background-color: #0b3a08;
|
||||
box-shadow: 0 10px 24px rgba(0, 0, 0, 0.22);
|
||||
}
|
||||
|
||||
.ornate-panel::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: 0;
|
||||
background-image: var(--ornate-top), var(--ornate-bottom), var(--ornate-middle);
|
||||
background-position: top center, bottom center, top center;
|
||||
background-size: 100% auto, 100% auto, 100% auto;
|
||||
background-repeat: no-repeat, no-repeat, repeat-y;
|
||||
box-shadow: 0 10px 24px rgba(0, 0, 0, 0.22);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.ornate-panel > * {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.timer-panel {
|
||||
@ -163,22 +182,29 @@
|
||||
}
|
||||
|
||||
.timer-box {
|
||||
border: 1.5px solid rgba(249, 244, 120, 0.55);
|
||||
border-radius: 10px;
|
||||
padding: 10px 4px 9px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
background: rgba(4, 31, 7, 0.34);
|
||||
}
|
||||
|
||||
.timer-value {
|
||||
font-size: 24px;
|
||||
width: 58px;
|
||||
aspect-ratio: 113 / 131;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding-top: 1px;
|
||||
background: center / 100% 100% no-repeat var(--countdown-card-bg);
|
||||
font-size: 22px;
|
||||
line-height: 1;
|
||||
font-weight: 700;
|
||||
color: #fff7dd;
|
||||
}
|
||||
|
||||
.timer-label {
|
||||
margin-top: 8px;
|
||||
margin-top: 9px;
|
||||
font-size: 10px;
|
||||
line-height: 1;
|
||||
color: var(--text-muted);
|
||||
@ -245,10 +271,12 @@
|
||||
|
||||
.reward-orb img {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
left: 50%;
|
||||
top: 55%;
|
||||
width: 66%;
|
||||
height: 66%;
|
||||
object-fit: contain;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.reward-label {
|
||||
@ -347,6 +375,16 @@
|
||||
|
||||
.copy-action-button {
|
||||
width: 100%;
|
||||
height: 36px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: center / 100% 100% no-repeat var(--button-active-bg);
|
||||
color: #fff8d5;
|
||||
font-size: 16px;
|
||||
font-weight: 800;
|
||||
line-height: 1;
|
||||
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
|
||||
.meta-inline {
|
||||
@ -416,50 +454,70 @@
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.monthly-task-panel {
|
||||
margin-top: 32px;
|
||||
padding: 58px 18px 20px;
|
||||
}
|
||||
|
||||
.inline-rank-panel {
|
||||
margin-top: 20px;
|
||||
padding: 44px 16px 18px;
|
||||
}
|
||||
|
||||
.monthly-title {
|
||||
position: absolute;
|
||||
top: -24px;
|
||||
left: 50%;
|
||||
z-index: 2;
|
||||
width: 140px;
|
||||
aspect-ratio: 419 / 120;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 10px;
|
||||
transform: translateX(-50%);
|
||||
background: center / 100% 100% no-repeat var(--monthly-title-bg);
|
||||
color: #fff7d7;
|
||||
font-size: 16px;
|
||||
font-weight: 800;
|
||||
line-height: 1;
|
||||
text-align: center;
|
||||
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
|
||||
.inline-rank-title {
|
||||
top: -16px;
|
||||
width: 88px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.task-tabs {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 7px;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.task-tab {
|
||||
position: relative;
|
||||
min-height: 0;
|
||||
aspect-ratio: 430 / 130;
|
||||
padding: 0;
|
||||
aspect-ratio: 419 / 120;
|
||||
padding: 0 6px;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
color: transparent;
|
||||
font-size: 0;
|
||||
background: center / 100% 100% no-repeat var(--task-tab-inactive-bg);
|
||||
color: #fff4b9;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
line-height: 1.05;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.55);
|
||||
}
|
||||
|
||||
.task-tab::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.task-tab[data-task-set="transport"].passive::after {
|
||||
background-image: url("./assets/tab-transport-inactive.png");
|
||||
}
|
||||
|
||||
.task-tab[data-task-set="transport"].active::after {
|
||||
background-image: url("./assets/tab-transport-active.png");
|
||||
}
|
||||
|
||||
.task-tab[data-task-set="quota"].passive::after {
|
||||
background-image: url("./assets/tab-quota-inactive.png");
|
||||
}
|
||||
|
||||
.task-tab[data-task-set="quota"].active::after {
|
||||
background-image: url("./assets/tab-quota-active.png");
|
||||
.task-tab.active {
|
||||
background-image: var(--task-tab-active-bg);
|
||||
color: #fff8d5;
|
||||
}
|
||||
|
||||
.task-list-panel {
|
||||
@ -470,6 +528,7 @@
|
||||
.task-list {
|
||||
display: grid;
|
||||
gap: 9px;
|
||||
margin-top: 14px;
|
||||
}
|
||||
|
||||
.task-card {
|
||||
@ -513,9 +572,8 @@
|
||||
}
|
||||
|
||||
.claim-button.is-claimable {
|
||||
padding: 0;
|
||||
background-image: var(--button-active-bg);
|
||||
color: transparent;
|
||||
color: #fff8d5;
|
||||
}
|
||||
|
||||
.claim-button.disabled,
|
||||
@ -526,14 +584,6 @@
|
||||
color: rgba(246, 224, 178, 0.75);
|
||||
}
|
||||
|
||||
.claim-button.is-claimable::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: center / 52px auto no-repeat url("./assets/claim-active.png");
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.task-note {
|
||||
margin: 14px 4px 0;
|
||||
font-size: 10px;
|
||||
@ -542,14 +592,6 @@
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.footer-button {
|
||||
width: min(100%, 269px);
|
||||
margin: 16px auto 32px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.rank-view {
|
||||
padding: 18px 12px 28px;
|
||||
}
|
||||
@ -597,6 +639,10 @@
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.inline-rank-list {
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.rank-row {
|
||||
display: grid;
|
||||
grid-template-columns: 30px 42px minmax(0, 1fr) auto;
|
||||
@ -658,6 +704,41 @@
|
||||
color: #f8ead2;
|
||||
}
|
||||
|
||||
.inline-rank-panel .rank-row {
|
||||
grid-template-columns: 22px 30px minmax(0, 1fr) 48px 48px;
|
||||
min-height: 37px;
|
||||
gap: 6px;
|
||||
padding: 4px 10px;
|
||||
}
|
||||
|
||||
.inline-rank-panel .rank-badge {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.inline-rank-panel .rank-badge img {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.inline-rank-panel .avatar {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.inline-rank-panel .rank-name,
|
||||
.inline-rank-panel .rank-score,
|
||||
.inline-rank-panel .rank-reward {
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.inline-rank-panel .rank-score,
|
||||
.inline-rank-panel .rank-reward {
|
||||
text-align: right;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.gift-view {
|
||||
position: relative;
|
||||
min-height: 100vh;
|
||||
@ -875,7 +956,7 @@
|
||||
data-copy-target="invite-link"
|
||||
aria-label="Copy invitation link"
|
||||
>
|
||||
<img data-src="./assets/copy-button.png" alt="" class="lazy-image" />
|
||||
Copy
|
||||
</button>
|
||||
</div>
|
||||
<div class="copy-row">
|
||||
@ -889,7 +970,7 @@
|
||||
data-copy-target="invite-code"
|
||||
aria-label="Copy invitation code"
|
||||
>
|
||||
<img data-src="./assets/copy-button.png" alt="" class="lazy-image" />
|
||||
Copy
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -916,33 +997,30 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section-header-art">
|
||||
<img
|
||||
data-src="./assets/monthly-tasks-button.png"
|
||||
alt="Monthly Tasks"
|
||||
class="lazy-image"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="task-tabs">
|
||||
<button type="button" class="task-tab passive" data-task-set="transport">
|
||||
Total Transportation Volume
|
||||
</button>
|
||||
<button type="button" class="task-tab active" data-task-set="quota">
|
||||
Invitation Quota Task
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="ornate-panel task-list-panel">
|
||||
<div class="ornate-panel monthly-task-panel">
|
||||
<div class="monthly-title">Monthly Tasks</div>
|
||||
<div class="task-tabs">
|
||||
<button type="button" class="task-tab passive" data-task-set="transport">
|
||||
Total Transportation<br />Volume
|
||||
</button>
|
||||
<button type="button" class="task-tab active" data-task-set="quota">
|
||||
Invitation Quota<br />Task
|
||||
</button>
|
||||
</div>
|
||||
<div class="task-list" id="taskList"></div>
|
||||
<p class="task-note" id="taskNote"></p>
|
||||
</div>
|
||||
|
||||
<div class="footer-button">
|
||||
<button type="button" class="art-button" data-nav-view="rank" aria-label="View rank">
|
||||
<img data-src="./assets/rank-button.png" alt="" class="lazy-image" />
|
||||
</button>
|
||||
<div class="ornate-panel inline-rank-panel">
|
||||
<div class="monthly-title inline-rank-title">Rank</div>
|
||||
<div
|
||||
class="rank-list inline-rank-list"
|
||||
id="inlineRankList"
|
||||
data-rank-list
|
||||
data-rank-variant="inline"
|
||||
></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@ -957,7 +1035,7 @@
|
||||
<img src="./assets/rank-title-button.png" alt="Rank" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="rank-list" id="rankList"></div>
|
||||
<div class="rank-list" id="rankList" data-rank-list></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||