cp 的h5活动相关
|
Before Width: | Height: | Size: 107 KiB After Width: | Height: | Size: 8.7 KiB |
|
Before Width: | Height: | Size: 109 KiB After Width: | Height: | Size: 8.9 KiB |
|
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 9.1 KiB |
|
Before Width: | Height: | Size: 113 KiB After Width: | Height: | Size: 6.9 KiB |
|
Before Width: | Height: | Size: 147 KiB After Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 3.3 MiB After Width: | Height: | Size: 207 KiB |
|
Before Width: | Height: | Size: 230 KiB After Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 313 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 230 KiB After Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 979 KiB After Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 167 KiB After Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 183 KiB After Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 127 KiB After Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 129 KiB After Width: | Height: | Size: 2.9 KiB |
@ -8,11 +8,14 @@
|
|||||||
/>
|
/>
|
||||||
<title>Last Weekly CP</title>
|
<title>Last Weekly CP</title>
|
||||||
<link rel="stylesheet" href="../../common/theme.css?v=20260608-cp" />
|
<link rel="stylesheet" href="../../common/theme.css?v=20260608-cp" />
|
||||||
<link rel="stylesheet" href="./style.css?v=20260625-cp-reward-center" />
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="./style.css?v=20260625-cp-plaza-api-reward-auto"
|
||||||
|
/>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="app-viewport" id="appViewport">
|
<div class="app-viewport" id="appViewport">
|
||||||
<main class="page" id="page" data-tab="plaza">
|
<main class="page" id="page" data-tab="rank">
|
||||||
<div class="stage-wrap" id="stageWrap">
|
<div class="stage-wrap" id="stageWrap">
|
||||||
<section
|
<section
|
||||||
class="stage"
|
class="stage"
|
||||||
@ -111,21 +114,21 @@
|
|||||||
aria-label="CP activity tabs"
|
aria-label="CP activity tabs"
|
||||||
data-i18n-aria="cp.tabsLabel"
|
data-i18n-aria="cp.tabsLabel"
|
||||||
>
|
>
|
||||||
<button
|
<button class="tab" type="button" data-tab="plaza">
|
||||||
class="tab is-active"
|
|
||||||
type="button"
|
|
||||||
data-tab="plaza"
|
|
||||||
>
|
|
||||||
<img
|
<img
|
||||||
src="./assets/tab-active.png"
|
src="./assets/tab-inactive.png"
|
||||||
alt=""
|
alt=""
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
/>
|
/>
|
||||||
<span data-i18n="cp.tabPlaza">CP Plaza</span>
|
<span data-i18n="cp.tabPlaza">CP Plaza</span>
|
||||||
</button>
|
</button>
|
||||||
<button class="tab" type="button" data-tab="rank">
|
<button
|
||||||
|
class="tab is-active"
|
||||||
|
type="button"
|
||||||
|
data-tab="rank"
|
||||||
|
>
|
||||||
<img
|
<img
|
||||||
src="./assets/tab-inactive.png"
|
src="./assets/tab-active.png"
|
||||||
alt=""
|
alt=""
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
/>
|
/>
|
||||||
@ -174,7 +177,7 @@
|
|||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
<script src="../../common/i18n.js?v=20260608-cp"></script>
|
<script src="../../common/i18n.js?v=20260608-cp"></script>
|
||||||
<script src="../../common/api.js?v=20260608-cp"></script>
|
<script src="../../common/api.js?v=20260625-cp-plaza-api"></script>
|
||||||
<script src="./script.js?v=20260625-cp-width768"></script>
|
<script src="./script.js?v=20260625-cp-plaza-api-reward-auto-coin"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@ -1,17 +1,29 @@
|
|||||||
(function () {
|
(function () {
|
||||||
var DESIGN_WIDTH = 1080;
|
var DESIGN_WIDTH = 1080;
|
||||||
var MAX_PAGE_WIDTH = 768;
|
var MAX_PAGE_WIDTH = 768;
|
||||||
|
var LALU_COIN_IMAGE = '../../common/png/lalu-coin.png';
|
||||||
|
var REWARD_FIRST_TOP = 1816;
|
||||||
|
var REWARD_PANEL_GAP = 56;
|
||||||
|
var REWARD_GRID_TOP = 220;
|
||||||
|
var REWARD_CARD_MIN_HEIGHT = 264;
|
||||||
|
var REWARD_GRID_ROW_GAP = 24;
|
||||||
|
var REWARD_PANEL_BOTTOM_PADDING = 80;
|
||||||
|
var REWARD_STAGE_BOTTOM_PADDING = 133;
|
||||||
|
var REWARD_MIN_PANEL_HEIGHT = 320;
|
||||||
var STORAGE_KEY = 'hy_cp_activity_end_at';
|
var STORAGE_KEY = 'hy_cp_activity_end_at';
|
||||||
var stageHeights = {
|
var stageHeights = {
|
||||||
plaza: 4283,
|
plaza: 4283,
|
||||||
rank: 3670,
|
rank: 3670,
|
||||||
rewards: 4797,
|
rewards: 4797,
|
||||||
};
|
};
|
||||||
var activeTab = 'plaza';
|
var rewardStageHeight = stageHeights.rewards;
|
||||||
|
var activeTab = 'rank';
|
||||||
var countdownEndAt = 0;
|
var countdownEndAt = 0;
|
||||||
var countdownTimer = 0;
|
var countdownTimer = 0;
|
||||||
var activityData = {
|
var activityData = {
|
||||||
rank: null,
|
plazaRows: [],
|
||||||
|
previousRows: [],
|
||||||
|
rank: [],
|
||||||
rewards: null,
|
rewards: null,
|
||||||
periodEndMS: 0,
|
periodEndMS: 0,
|
||||||
};
|
};
|
||||||
@ -25,30 +37,6 @@
|
|||||||
var tabs = Array.prototype.slice.call(document.querySelectorAll('.tab'));
|
var tabs = Array.prototype.slice.call(document.querySelectorAll('.tab'));
|
||||||
|
|
||||||
var mockData = {
|
var mockData = {
|
||||||
plaza: {
|
|
||||||
exchangeRows: buildRows('gift', 4),
|
|
||||||
previousRows: buildRows('score', 4),
|
|
||||||
},
|
|
||||||
rank: [
|
|
||||||
{
|
|
||||||
place: 1,
|
|
||||||
score: '1,234,567',
|
|
||||||
leftName: 'Namename',
|
|
||||||
rightName: 'Namename',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
place: 2,
|
|
||||||
score: '987,654',
|
|
||||||
leftName: 'Namename',
|
|
||||||
rightName: 'Namename',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
place: 3,
|
|
||||||
score: '876,543',
|
|
||||||
leftName: 'Namename',
|
|
||||||
rightName: 'Namename',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
rewards: [
|
rewards: [
|
||||||
{
|
{
|
||||||
crown: 'crown-gold.png',
|
crown: 'crown-gold.png',
|
||||||
@ -83,19 +71,6 @@
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
function buildRows(type, count) {
|
|
||||||
var rows = [];
|
|
||||||
for (var index = 0; index < count; index += 1) {
|
|
||||||
rows.push({
|
|
||||||
type: type,
|
|
||||||
leftName: 'Namename',
|
|
||||||
rightName: 'Namename',
|
|
||||||
score: '1234567',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return rows;
|
|
||||||
}
|
|
||||||
|
|
||||||
function t(key, fallback) {
|
function t(key, fallback) {
|
||||||
if (window.HyAppI18n && window.HyAppI18n.t) {
|
if (window.HyAppI18n && window.HyAppI18n.t) {
|
||||||
return window.HyAppI18n.t(key, fallback);
|
return window.HyAppI18n.t(key, fallback);
|
||||||
@ -187,6 +162,34 @@
|
|||||||
].join('');
|
].join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function estimateRewardPanelHeight(section) {
|
||||||
|
var count =
|
||||||
|
section && Array.isArray(section.items) ? section.items.length : 0;
|
||||||
|
var rows = count > 0 ? Math.ceil(count / 3) : 0;
|
||||||
|
var gridHeight =
|
||||||
|
rows > 0
|
||||||
|
? rows * REWARD_CARD_MIN_HEIGHT +
|
||||||
|
Math.max(0, rows - 1) * REWARD_GRID_ROW_GAP
|
||||||
|
: 0;
|
||||||
|
return Math.max(
|
||||||
|
REWARD_MIN_PANEL_HEIGHT,
|
||||||
|
REWARD_GRID_TOP + gridHeight + REWARD_PANEL_BOTTOM_PADDING
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderAvatar(className, avatar) {
|
||||||
|
if (!avatar) return '';
|
||||||
|
return [
|
||||||
|
'<div class="avatar ',
|
||||||
|
className,
|
||||||
|
'">',
|
||||||
|
'<img src="',
|
||||||
|
escapeHTML(avatar),
|
||||||
|
'" alt="" />',
|
||||||
|
'</div>',
|
||||||
|
].join('');
|
||||||
|
}
|
||||||
|
|
||||||
function renderCPRow(row) {
|
function renderCPRow(row) {
|
||||||
var center =
|
var center =
|
||||||
row.type === 'score'
|
row.type === 'score'
|
||||||
@ -204,12 +207,8 @@
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
'<article class="cp-row">',
|
'<article class="cp-row">',
|
||||||
'<div class="avatar avatar-left"><img src="',
|
renderAvatar('avatar-left', row.leftAvatar),
|
||||||
escapeHTML(row.leftAvatar || './assets/avatar-sample.png'),
|
renderAvatar('avatar-right', row.rightAvatar),
|
||||||
'" alt="" /></div>',
|
|
||||||
'<div class="avatar avatar-right"><img src="',
|
|
||||||
escapeHTML(row.rightAvatar || './assets/avatar-sample.png'),
|
|
||||||
'" alt="" /></div>',
|
|
||||||
'<span class="name name-left">',
|
'<span class="name name-left">',
|
||||||
escapeHTML(row.leftName),
|
escapeHTML(row.leftName),
|
||||||
'</span>',
|
'</span>',
|
||||||
@ -224,42 +223,33 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function renderPlaza() {
|
function renderPlaza() {
|
||||||
|
var plazaRows = activityData.plazaRows || [];
|
||||||
|
var previousRows = activityData.previousRows || [];
|
||||||
var firstBody = [
|
var firstBody = [
|
||||||
'<h2 class="panel-title">',
|
'<h2 class="panel-title">',
|
||||||
t(
|
t(
|
||||||
'cp.plazaGiftTitle',
|
'cp.plazaGiftTitle',
|
||||||
'Gifts exchanged between CPs ≥ 5000 gold will be displayed here'
|
'CP pairs with intimacy ≥ 5000 are shown here'
|
||||||
),
|
),
|
||||||
'</h2>',
|
'</h2>',
|
||||||
'<p class="panel-subtitle">',
|
|
||||||
t(
|
|
||||||
'cp.plazaGiftSubtitle',
|
|
||||||
'(Display the last 10 records, sorted in ascending order.)'
|
|
||||||
),
|
|
||||||
'</p>',
|
|
||||||
'<div class="cp-list">',
|
'<div class="cp-list">',
|
||||||
mockData.plaza.exchangeRows.map(renderCPRow).join(''),
|
plazaRows.map(renderCPRow).join(''),
|
||||||
'</div>',
|
|
||||||
].join('');
|
|
||||||
var secondBody = [
|
|
||||||
'<h2 class="panel-title">',
|
|
||||||
t('cp.previousNo1Title', 'The previous number one position'),
|
|
||||||
'</h2>',
|
|
||||||
'<p class="panel-subtitle">',
|
|
||||||
t(
|
|
||||||
'cp.plazaGiftSubtitle',
|
|
||||||
'(Display the last 10 records, sorted in ascending order.)'
|
|
||||||
),
|
|
||||||
'</p>',
|
|
||||||
'<div class="cp-list">',
|
|
||||||
mockData.plaza.previousRows.map(renderCPRow).join(''),
|
|
||||||
'</div>',
|
'</div>',
|
||||||
].join('');
|
].join('');
|
||||||
|
var panels = [renderPanel('plaza-panel-a', 1816, 1152, firstBody)];
|
||||||
|
if (previousRows.length) {
|
||||||
|
var secondBody = [
|
||||||
|
'<h2 class="panel-title">',
|
||||||
|
t('cp.previousNo1Title', 'Previous Top 3'),
|
||||||
|
'</h2>',
|
||||||
|
'<div class="cp-list">',
|
||||||
|
previousRows.map(renderCPRow).join(''),
|
||||||
|
'</div>',
|
||||||
|
].join('');
|
||||||
|
panels.push(renderPanel('plaza-panel-b', 3024, 1126, secondBody));
|
||||||
|
}
|
||||||
|
|
||||||
return [
|
return panels.join('');
|
||||||
renderPanel('plaza-panel-a', 1816, 1152, firstBody),
|
|
||||||
renderPanel('plaza-panel-b', 3024, 1126, secondBody),
|
|
||||||
].join('');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderInlineCountdown() {
|
function renderInlineCountdown() {
|
||||||
@ -305,12 +295,8 @@
|
|||||||
'<img class="podium-crown" src="./assets/',
|
'<img class="podium-crown" src="./assets/',
|
||||||
crown,
|
crown,
|
||||||
'" alt="" aria-hidden="true" />',
|
'" alt="" aria-hidden="true" />',
|
||||||
'<div class="avatar podium-avatar left"><img src="',
|
renderAvatar('podium-avatar left', item.leftAvatar),
|
||||||
escapeHTML(item.leftAvatar || './assets/avatar-sample.png'),
|
renderAvatar('podium-avatar right', item.rightAvatar),
|
||||||
'" alt="" /></div>',
|
|
||||||
'<div class="avatar podium-avatar right"><img src="',
|
|
||||||
escapeHTML(item.rightAvatar || './assets/avatar-sample.png'),
|
|
||||||
'" alt="" /></div>',
|
|
||||||
'<div class="podium-names"><span>',
|
'<div class="podium-names"><span>',
|
||||||
escapeHTML(item.leftName),
|
escapeHTML(item.leftName),
|
||||||
'</span><span>',
|
'</span><span>',
|
||||||
@ -325,22 +311,23 @@
|
|||||||
type: 'score',
|
type: 'score',
|
||||||
leftName: item.leftName,
|
leftName: item.leftName,
|
||||||
rightName: item.rightName,
|
rightName: item.rightName,
|
||||||
|
leftAvatar: item.leftAvatar,
|
||||||
|
rightAvatar: item.rightAvatar,
|
||||||
score: item.score,
|
score: item.score,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderRank() {
|
function renderRank() {
|
||||||
var rankRows = activityData.rank || mockData.rank;
|
var rankRows = activityData.rank || [];
|
||||||
var podium = [
|
var podium = [
|
||||||
'<section class="rank-podium">',
|
'<section class="rank-podium">',
|
||||||
rankRows.slice(0, 3).map(renderPodiumCard).join(''),
|
rankRows.slice(0, 3).map(renderPodiumCard).join(''),
|
||||||
'</section>',
|
'</section>',
|
||||||
].join('');
|
].join('');
|
||||||
var panelRows = rankRows.length ? rankRows : mockData.rank;
|
|
||||||
var panelBody = [
|
var panelBody = [
|
||||||
renderInlineCountdown(),
|
renderInlineCountdown(),
|
||||||
'<div class="cp-list">',
|
'<div class="cp-list">',
|
||||||
panelRows.map(renderRankRow).join(''),
|
rankRows.map(renderRankRow).join(''),
|
||||||
'</div>',
|
'</div>',
|
||||||
].join('');
|
].join('');
|
||||||
return podium + renderPanel('rank-panel', 2430, 1107, panelBody);
|
return podium + renderPanel('rank-panel', 2430, 1107, panelBody);
|
||||||
@ -350,8 +337,14 @@
|
|||||||
var name = item.name || t(item.key, item.key);
|
var name = item.name || t(item.key, item.key);
|
||||||
var note = item.note || (item.noteKey ? t(item.noteKey, '') : '');
|
var note = item.note || (item.noteKey ? t(item.noteKey, '') : '');
|
||||||
var cover = item.coverUrl || './assets/reward-frame.png';
|
var cover = item.coverUrl || './assets/reward-frame.png';
|
||||||
|
var cardClass =
|
||||||
|
item.resourceType === 'coin'
|
||||||
|
? 'reward-card is-coin'
|
||||||
|
: 'reward-card';
|
||||||
return [
|
return [
|
||||||
'<article class="reward-card">',
|
'<article class="',
|
||||||
|
cardClass,
|
||||||
|
'">',
|
||||||
'<div class="reward-icon-box"><img src="',
|
'<div class="reward-icon-box"><img src="',
|
||||||
escapeHTML(cover),
|
escapeHTML(cover),
|
||||||
'" alt="" aria-hidden="true" /></div>',
|
'" alt="" aria-hidden="true" /></div>',
|
||||||
@ -370,7 +363,14 @@
|
|||||||
'reward-panel',
|
'reward-panel',
|
||||||
'reward-' + ['a', 'b', 'c'][index],
|
'reward-' + ['a', 'b', 'c'][index],
|
||||||
].join(' ');
|
].join(' ');
|
||||||
var top = [1816, 2784, 3752][index];
|
var top = REWARD_FIRST_TOP;
|
||||||
|
for (var cursor = 0; cursor < index; cursor += 1) {
|
||||||
|
top +=
|
||||||
|
estimateRewardPanelHeight(
|
||||||
|
(activityData.rewards || mockData.rewards)[cursor]
|
||||||
|
) + REWARD_PANEL_GAP;
|
||||||
|
}
|
||||||
|
var height = estimateRewardPanelHeight(section);
|
||||||
var body = [
|
var body = [
|
||||||
'<img class="reward-crown" src="./assets/',
|
'<img class="reward-crown" src="./assets/',
|
||||||
section.crown,
|
section.crown,
|
||||||
@ -379,13 +379,51 @@
|
|||||||
section.items.map(renderRewardItem).join(''),
|
section.items.map(renderRewardItem).join(''),
|
||||||
'</div>',
|
'</div>',
|
||||||
].join('');
|
].join('');
|
||||||
return renderPanel(className, top, 912, body);
|
return renderPanel(className, top, height, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderRewards() {
|
function renderRewards() {
|
||||||
return (activityData.rewards || mockData.rewards)
|
var sections = activityData.rewards || mockData.rewards;
|
||||||
.map(renderRewardPanel)
|
var bottom = REWARD_FIRST_TOP;
|
||||||
|
var html = sections
|
||||||
|
.map(function (section, index) {
|
||||||
|
var panel = renderRewardPanel(section, index);
|
||||||
|
bottom += estimateRewardPanelHeight(section) + REWARD_PANEL_GAP;
|
||||||
|
return panel;
|
||||||
|
})
|
||||||
.join('');
|
.join('');
|
||||||
|
rewardStageHeight =
|
||||||
|
bottom - REWARD_PANEL_GAP + REWARD_STAGE_BOTTOM_PADDING;
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
|
||||||
|
function syncRewardPanelLayout() {
|
||||||
|
if (activeTab !== 'rewards') return;
|
||||||
|
var nextTop = REWARD_FIRST_TOP;
|
||||||
|
var panels = Array.prototype.slice.call(
|
||||||
|
tabContent.querySelectorAll('.reward-panel')
|
||||||
|
);
|
||||||
|
panels.forEach(function (panel) {
|
||||||
|
var grid = panel.querySelector('.reward-grid');
|
||||||
|
var measuredHeight = REWARD_MIN_PANEL_HEIGHT;
|
||||||
|
// 奖励内容来自接口,不同档位数量和多语言换行都可能变化;渲染后用真实 grid 高度回写面板高度,避免固定 912px 留出大空白。
|
||||||
|
if (grid) {
|
||||||
|
measuredHeight = Math.max(
|
||||||
|
measuredHeight,
|
||||||
|
grid.offsetTop +
|
||||||
|
grid.offsetHeight +
|
||||||
|
REWARD_PANEL_BOTTOM_PADDING
|
||||||
|
);
|
||||||
|
}
|
||||||
|
measuredHeight = Math.ceil(measuredHeight);
|
||||||
|
panel.style.top = nextTop + 'px';
|
||||||
|
panel.style.height = measuredHeight + 'px';
|
||||||
|
nextTop += measuredHeight + REWARD_PANEL_GAP;
|
||||||
|
});
|
||||||
|
if (panels.length) {
|
||||||
|
rewardStageHeight =
|
||||||
|
nextTop - REWARD_PANEL_GAP + REWARD_STAGE_BOTTOM_PADDING;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatScore(value) {
|
function formatScore(value) {
|
||||||
@ -398,16 +436,48 @@
|
|||||||
return user || {};
|
return user || {};
|
||||||
}
|
}
|
||||||
|
|
||||||
function normalizeRankEntry(entry) {
|
function normalizePairUser(user) {
|
||||||
var userA = normalizeUser(entry.user_a);
|
var source = normalizeUser(user);
|
||||||
var userB = normalizeUser(entry.user_b);
|
var userID = source.user_id || source.userId || '';
|
||||||
|
var displayID = source.display_user_id || source.displayUserId || '';
|
||||||
|
var name = source.username || source.name || displayID || userID || '';
|
||||||
|
if (!name && !source.avatar) return null;
|
||||||
return {
|
return {
|
||||||
|
name: name,
|
||||||
|
avatar: source.avatar || '',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeRankEntry(entry) {
|
||||||
|
var userA = normalizePairUser(entry.user_a);
|
||||||
|
var userB = normalizePairUser(entry.user_b);
|
||||||
|
if (!userA || !userB) return null;
|
||||||
|
return {
|
||||||
|
type: 'score',
|
||||||
place: Number(entry.rank || 0),
|
place: Number(entry.rank || 0),
|
||||||
score: formatScore(entry.score),
|
score: formatScore(entry.score),
|
||||||
leftName: userA.username || userA.display_user_id || 'Namename',
|
leftName: userA.name,
|
||||||
rightName: userB.username || userB.display_user_id || 'Namename',
|
rightName: userB.name,
|
||||||
leftAvatar: userA.avatar || '',
|
leftAvatar: userA.avatar,
|
||||||
rightAvatar: userB.avatar || '',
|
rightAvatar: userB.avatar,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizePlazaEntry(entry) {
|
||||||
|
var intimacyValue = Number(
|
||||||
|
entry.intimacy_value || entry.intimacyValue || 0
|
||||||
|
);
|
||||||
|
var userA = normalizePairUser(entry.user_a);
|
||||||
|
var userB = normalizePairUser(entry.user_b);
|
||||||
|
if (intimacyValue < 5000 || !userA || !userB) return null;
|
||||||
|
return {
|
||||||
|
type: 'score',
|
||||||
|
rawScore: intimacyValue,
|
||||||
|
score: formatScore(intimacyValue),
|
||||||
|
leftName: userA.name,
|
||||||
|
rightName: userB.name,
|
||||||
|
leftAvatar: userA.avatar,
|
||||||
|
rightAvatar: userB.avatar,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -419,20 +489,34 @@
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function rewardResourceType(item) {
|
||||||
|
return String(
|
||||||
|
item.resource_type || item.resourceType || ''
|
||||||
|
).toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
function rewardCoverUrl(item) {
|
||||||
|
var resourceType = rewardResourceType(item);
|
||||||
|
if (resourceType === 'coin') return LALU_COIN_IMAGE;
|
||||||
|
return item.cover_url || item.coverUrl || '';
|
||||||
|
}
|
||||||
|
|
||||||
function normalizeRewardSection(reward, index) {
|
function normalizeRewardSection(reward, index) {
|
||||||
var crowns = ['crown-gold.png', 'crown-silver.png', 'crown-bronze.png'];
|
var crowns = ['crown-gold.png', 'crown-silver.png', 'crown-bronze.png'];
|
||||||
return {
|
return {
|
||||||
crown: crowns[index] || 'crown-bronze.png',
|
crown: crowns[index] || 'crown-bronze.png',
|
||||||
items: (reward.items || []).map(function (item) {
|
items: (reward.items || []).map(function (item) {
|
||||||
|
var resourceType = rewardResourceType(item);
|
||||||
return {
|
return {
|
||||||
name: rewardName(item),
|
name: rewardName(item),
|
||||||
|
resourceType: resourceType,
|
||||||
note:
|
note:
|
||||||
item.duration_days > 0
|
item.duration_days > 0
|
||||||
? item.duration_days + ' days'
|
? item.duration_days + ' days'
|
||||||
: item.quantity > 0
|
: item.quantity > 0
|
||||||
? 'x' + item.quantity
|
? 'x' + item.quantity
|
||||||
: '',
|
: '',
|
||||||
coverUrl: item.cover_url || '',
|
coverUrl: rewardCoverUrl(item),
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
@ -444,14 +528,41 @@
|
|||||||
activityData.periodEndMS = status.period.end_ms;
|
activityData.periodEndMS = status.period.end_ms;
|
||||||
countdownEndAt = status.period.end_ms;
|
countdownEndAt = status.period.end_ms;
|
||||||
}
|
}
|
||||||
if (Array.isArray(status.entries) && status.entries.length) {
|
if (Array.isArray(status.entries)) {
|
||||||
activityData.rank = status.entries.map(normalizeRankEntry);
|
var rankRows = status.entries
|
||||||
|
.map(normalizeRankEntry)
|
||||||
|
.filter(function (item) {
|
||||||
|
return Boolean(item);
|
||||||
|
});
|
||||||
|
activityData.rank = rankRows;
|
||||||
|
}
|
||||||
|
if (Array.isArray(status.previous_entries)) {
|
||||||
|
activityData.previousRows = status.previous_entries
|
||||||
|
.map(normalizeRankEntry)
|
||||||
|
.filter(function (item) {
|
||||||
|
return Boolean(item);
|
||||||
|
})
|
||||||
|
.slice(0, 3);
|
||||||
}
|
}
|
||||||
if (Array.isArray(status.rewards) && status.rewards.length) {
|
if (Array.isArray(status.rewards) && status.rewards.length) {
|
||||||
activityData.rewards = status.rewards.map(normalizeRewardSection);
|
activityData.rewards = status.rewards.map(normalizeRewardSection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function applyPlazaLeaderboard(data) {
|
||||||
|
var items = data && Array.isArray(data.items) ? data.items : [];
|
||||||
|
// CP 广场只展示真实接口里亲密值达到门槛的 CP;接口为空或低于门槛时保持空列表,不再用 mock 用户兜底。
|
||||||
|
activityData.plazaRows = items
|
||||||
|
.map(normalizePlazaEntry)
|
||||||
|
.filter(function (item) {
|
||||||
|
return Boolean(item);
|
||||||
|
})
|
||||||
|
.sort(function (left, right) {
|
||||||
|
return right.rawScore - left.rawScore;
|
||||||
|
})
|
||||||
|
.slice(0, 4);
|
||||||
|
}
|
||||||
|
|
||||||
function loadActivityStatus() {
|
function loadActivityStatus() {
|
||||||
if (!window.HyAppAPI || !window.HyAppAPI.cpWeeklyRank) return;
|
if (!window.HyAppAPI || !window.HyAppAPI.cpWeeklyRank) return;
|
||||||
// 周榜配置和奖励由后端控制;H5 只在接口成功时替换展示数据,失败保持静态兜底,避免活动页因为鉴权或网络问题白屏。
|
// 周榜配置和奖励由后端控制;H5 只在接口成功时替换展示数据,失败保持静态兜底,避免活动页因为鉴权或网络问题白屏。
|
||||||
@ -464,6 +575,28 @@
|
|||||||
.catch(function () {});
|
.catch(function () {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function loadPlazaLeaderboard() {
|
||||||
|
if (
|
||||||
|
!window.HyAppAPI ||
|
||||||
|
!window.HyAppAPI.cpSpace ||
|
||||||
|
!window.HyAppAPI.cpSpace.intimacyLeaderboard
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 后端亲密榜已按亲密值降序聚合;H5 仍二次过滤 5000 门槛并限制 4 个,防止旧数据或异常分页把低亲密 CP 展示出来。
|
||||||
|
window.HyAppAPI.cpSpace
|
||||||
|
.intimacyLeaderboard({
|
||||||
|
relation_type: 'cp',
|
||||||
|
page: 1,
|
||||||
|
page_size: 4,
|
||||||
|
})
|
||||||
|
.then(function (data) {
|
||||||
|
applyPlazaLeaderboard(data);
|
||||||
|
render();
|
||||||
|
})
|
||||||
|
.catch(function () {});
|
||||||
|
}
|
||||||
|
|
||||||
function render() {
|
function render() {
|
||||||
document.title = t('cp.pageTitle', 'Last Weekly CP');
|
document.title = t('cp.pageTitle', 'Last Weekly CP');
|
||||||
tabContent.innerHTML =
|
tabContent.innerHTML =
|
||||||
@ -473,6 +606,7 @@
|
|||||||
? renderRewards()
|
? renderRewards()
|
||||||
: renderPlaza();
|
: renderPlaza();
|
||||||
applyTabState();
|
applyTabState();
|
||||||
|
syncRewardPanelLayout();
|
||||||
updateStageHeight();
|
updateStageHeight();
|
||||||
updateCountdown();
|
updateCountdown();
|
||||||
}
|
}
|
||||||
@ -497,7 +631,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function updateStageHeight() {
|
function updateStageHeight() {
|
||||||
var designHeight = stageHeights[activeTab] || stageHeights.plaza;
|
var designHeight =
|
||||||
|
activeTab === 'rewards'
|
||||||
|
? rewardStageHeight
|
||||||
|
: stageHeights[activeTab] || stageHeights.plaza;
|
||||||
var pageWidth = getPageWidth();
|
var pageWidth = getPageWidth();
|
||||||
var designScale = pageWidth / DESIGN_WIDTH;
|
var designScale = pageWidth / DESIGN_WIDTH;
|
||||||
stage.style.minHeight = designHeight + 'px';
|
stage.style.minHeight = designHeight + 'px';
|
||||||
@ -531,6 +668,7 @@
|
|||||||
countdownEndAt = resolveFallbackEndAt();
|
countdownEndAt = resolveFallbackEndAt();
|
||||||
bindTabs();
|
bindTabs();
|
||||||
render();
|
render();
|
||||||
|
loadPlazaLeaderboard();
|
||||||
loadActivityStatus();
|
loadActivityStatus();
|
||||||
countdownTimer = window.setInterval(updateCountdown, 1000);
|
countdownTimer = window.setInterval(updateCountdown, 1000);
|
||||||
window.addEventListener('resize', updateStageHeight);
|
window.addEventListener('resize', updateStageHeight);
|
||||||
|
|||||||
@ -367,6 +367,11 @@ button {
|
|||||||
height: 1126px;
|
height: 1126px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.plaza-panel-a .cp-list,
|
||||||
|
.plaza-panel-b .cp-list {
|
||||||
|
top: 170px;
|
||||||
|
}
|
||||||
|
|
||||||
.panel-title {
|
.panel-title {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 55px;
|
left: 55px;
|
||||||
@ -689,6 +694,14 @@ button {
|
|||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.reward-card.is-coin img {
|
||||||
|
left: 56px;
|
||||||
|
top: 56px;
|
||||||
|
width: 106px;
|
||||||
|
height: 106px;
|
||||||
|
filter: drop-shadow(0 12px 16px rgba(233, 151, 33, 0.28));
|
||||||
|
}
|
||||||
|
|
||||||
.reward-name {
|
.reward-name {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
color: #9f1c32;
|
color: #9f1c32;
|
||||||
|
|||||||
@ -1476,6 +1476,12 @@ var default_api = 'https://api.global-interaction.com/';
|
|||||||
query: params || {},
|
query: params || {},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
intimacyLeaderboard: function (params) {
|
||||||
|
return request('/api/v1/cp/intimacy-leaderboard', {
|
||||||
|
method: 'GET',
|
||||||
|
query: params || {},
|
||||||
|
});
|
||||||
|
},
|
||||||
breakRelationship: function (relationshipID, payload) {
|
breakRelationship: function (relationshipID, payload) {
|
||||||
return request(
|
return request(
|
||||||
'/api/v1/cp/relationships/' +
|
'/api/v1/cp/relationships/' +
|
||||||
|
|||||||
@ -470,9 +470,9 @@
|
|||||||
"cp.tabPlaza": "ساحة CP",
|
"cp.tabPlaza": "ساحة CP",
|
||||||
"cp.tabRank": "ترتيب CP",
|
"cp.tabRank": "ترتيب CP",
|
||||||
"cp.tabRewards": "المكافآت",
|
"cp.tabRewards": "المكافآت",
|
||||||
"cp.plazaGiftTitle": "الهدايا المتبادلة بين CP بقيمة >= 5000 ذهب ستظهر هنا",
|
"cp.plazaGiftTitle": "سيتم عرض أزواج CP التي لديها قيمة ألفة >= 5000 هنا",
|
||||||
"cp.plazaGiftSubtitle": "(عرض آخر 10 سجلات مرتبة تصاعديا.)",
|
"cp.plazaGiftSubtitle": "(عرض آخر 10 سجلات مرتبة تصاعديا.)",
|
||||||
"cp.previousNo1Title": "مركز الرقم واحد السابق",
|
"cp.previousNo1Title": "أفضل 3 في الفترة السابقة",
|
||||||
"cp.rewardMedal7": "وسام*7 أيام",
|
"cp.rewardMedal7": "وسام*7 أيام",
|
||||||
"cp.rewardMedalNote": "(وسام دائم بعد الحصول عليه 3 مرات)",
|
"cp.rewardMedalNote": "(وسام دائم بعد الحصول عليه 3 مرات)",
|
||||||
"cp.rewardHonorBanner7": "لافتة شرف*7 أيام",
|
"cp.rewardHonorBanner7": "لافتة شرف*7 أيام",
|
||||||
|
|||||||
@ -476,9 +476,9 @@
|
|||||||
"cp.tabPlaza": "CP Plaza",
|
"cp.tabPlaza": "CP Plaza",
|
||||||
"cp.tabRank": "CP Rank",
|
"cp.tabRank": "CP Rank",
|
||||||
"cp.tabRewards": "Rewards",
|
"cp.tabRewards": "Rewards",
|
||||||
"cp.plazaGiftTitle": "Gifts exchanged between CPs >= 5000 gold will be displayed here",
|
"cp.plazaGiftTitle": "CP pairs with intimacy >= 5000 are shown here",
|
||||||
"cp.plazaGiftSubtitle": "(Display the last 10 records, sorted in ascending order.)",
|
"cp.plazaGiftSubtitle": "(Display the last 10 records, sorted in ascending order.)",
|
||||||
"cp.previousNo1Title": "The previous number one position",
|
"cp.previousNo1Title": "Previous Top 3",
|
||||||
"cp.rewardMedal7": "Medal*7 days",
|
"cp.rewardMedal7": "Medal*7 days",
|
||||||
"cp.rewardMedalNote": "(Permanent medal after getting 3 times)",
|
"cp.rewardMedalNote": "(Permanent medal after getting 3 times)",
|
||||||
"cp.rewardHonorBanner7": "Honor banner*7 days",
|
"cp.rewardHonorBanner7": "Honor banner*7 days",
|
||||||
|
|||||||
@ -470,9 +470,9 @@
|
|||||||
"cp.tabPlaza": "Plaza CP",
|
"cp.tabPlaza": "Plaza CP",
|
||||||
"cp.tabRank": "Ranking CP",
|
"cp.tabRank": "Ranking CP",
|
||||||
"cp.tabRewards": "Recompensas",
|
"cp.tabRewards": "Recompensas",
|
||||||
"cp.plazaGiftTitle": "Los regalos entre CPs >= 5000 de oro se mostrarán aquí",
|
"cp.plazaGiftTitle": "Los CP con intimidad >= 5000 se mostrarán aquí",
|
||||||
"cp.plazaGiftSubtitle": "(Muestra los últimos 10 registros en orden ascendente.)",
|
"cp.plazaGiftSubtitle": "(Muestra los últimos 10 registros en orden ascendente.)",
|
||||||
"cp.previousNo1Title": "La posición número uno anterior",
|
"cp.previousNo1Title": "Top 3 anterior",
|
||||||
"cp.rewardMedal7": "Medalla*7 días",
|
"cp.rewardMedal7": "Medalla*7 días",
|
||||||
"cp.rewardMedalNote": "(Medalla permanente tras obtenerla 3 veces)",
|
"cp.rewardMedalNote": "(Medalla permanente tras obtenerla 3 veces)",
|
||||||
"cp.rewardHonorBanner7": "Banner de honor*7 días",
|
"cp.rewardHonorBanner7": "Banner de honor*7 días",
|
||||||
|
|||||||
@ -437,9 +437,9 @@
|
|||||||
"cp.tabPlaza": "CP Plaza",
|
"cp.tabPlaza": "CP Plaza",
|
||||||
"cp.tabRank": "Peringkat CP",
|
"cp.tabRank": "Peringkat CP",
|
||||||
"cp.tabRewards": "Hadiah",
|
"cp.tabRewards": "Hadiah",
|
||||||
"cp.plazaGiftTitle": "Hadiah antar CP >= 5000 gold akan ditampilkan di sini",
|
"cp.plazaGiftTitle": "CP dengan intimacy >= 5000 akan ditampilkan di sini",
|
||||||
"cp.plazaGiftSubtitle": "(Menampilkan 10 catatan terbaru, diurutkan naik.)",
|
"cp.plazaGiftSubtitle": "(Menampilkan 10 catatan terbaru, diurutkan naik.)",
|
||||||
"cp.previousNo1Title": "Posisi nomor satu sebelumnya",
|
"cp.previousNo1Title": "Top 3 periode sebelumnya",
|
||||||
"cp.rewardMedal7": "Medali*7 hari",
|
"cp.rewardMedal7": "Medali*7 hari",
|
||||||
"cp.rewardMedalNote": "(Medali permanen setelah mendapatkannya 3 kali)",
|
"cp.rewardMedalNote": "(Medali permanen setelah mendapatkannya 3 kali)",
|
||||||
"cp.rewardHonorBanner7": "Banner kehormatan*7 hari",
|
"cp.rewardHonorBanner7": "Banner kehormatan*7 hari",
|
||||||
|
|||||||
@ -437,9 +437,9 @@
|
|||||||
"cp.tabPlaza": "CP Plaza",
|
"cp.tabPlaza": "CP Plaza",
|
||||||
"cp.tabRank": "CP Sıralaması",
|
"cp.tabRank": "CP Sıralaması",
|
||||||
"cp.tabRewards": "Ödüller",
|
"cp.tabRewards": "Ödüller",
|
||||||
"cp.plazaGiftTitle": "CPler arasında >= 5000 altın değerinde gönderilen hediyeler burada görünür",
|
"cp.plazaGiftTitle": "Samimiyet değeri >= 5000 olan CP çiftleri burada görünür",
|
||||||
"cp.plazaGiftSubtitle": "(Son 10 kayıt artan sırayla gösterilir.)",
|
"cp.plazaGiftSubtitle": "(Son 10 kayıt artan sırayla gösterilir.)",
|
||||||
"cp.previousNo1Title": "Önceki birincilik konumu",
|
"cp.previousNo1Title": "Önceki Top 3",
|
||||||
"cp.rewardMedal7": "Madalya*7 gün",
|
"cp.rewardMedal7": "Madalya*7 gün",
|
||||||
"cp.rewardMedalNote": "(3 kez alındıktan sonra kalıcı madalya)",
|
"cp.rewardMedalNote": "(3 kez alındıktan sonra kalıcı madalya)",
|
||||||
"cp.rewardHonorBanner7": "Onur afişi*7 gün",
|
"cp.rewardHonorBanner7": "Onur afişi*7 gün",
|
||||||
|
|||||||
@ -443,9 +443,9 @@
|
|||||||
"cp.tabPlaza": "CP 广场",
|
"cp.tabPlaza": "CP 广场",
|
||||||
"cp.tabRank": "CP 排行",
|
"cp.tabRank": "CP 排行",
|
||||||
"cp.tabRewards": "奖励",
|
"cp.tabRewards": "奖励",
|
||||||
"cp.plazaGiftTitle": "CP 之间互赠 >= 5000 金币的礼物会展示在这里",
|
"cp.plazaGiftTitle": "CP 之间亲密值 >= 5000 的 CP 会展示在这里",
|
||||||
"cp.plazaGiftSubtitle": "(展示最近 10 条记录,按时间升序排列。)",
|
"cp.plazaGiftSubtitle": "(展示最近 10 条记录,按时间升序排列。)",
|
||||||
"cp.previousNo1Title": "上期第一名位置",
|
"cp.previousNo1Title": "上期前三名",
|
||||||
"cp.rewardMedal7": "勋章*7天",
|
"cp.rewardMedal7": "勋章*7天",
|
||||||
"cp.rewardMedalNote": "(获得 3 次后永久)",
|
"cp.rewardMedalNote": "(获得 3 次后永久)",
|
||||||
"cp.rewardHonorBanner7": "荣誉横幅*7天",
|
"cp.rewardHonorBanner7": "荣誉横幅*7天",
|
||||||
|
|||||||
BIN
common/png/lalu-coin.png
Normal file
|
After Width: | Height: | Size: 46 KiB |