2026-06-18 18:58:30 +08:00

189 lines
5.9 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 () {
var VALID_TABS = ['cp', 'brother', 'sister'];
var LEVEL_IMAGES = {
1: './assets/level-1@4x.png',
2: './assets/level-2@4x.png',
3: './assets/level-3@4x.png',
4: './assets/level-4@4x.png',
5: './assets/level-5@4x.png',
};
var page = document.getElementById('page');
var contentPanel = document.getElementById('contentPanel');
var backButton = document.getElementById('backButton');
var tabButtons = Array.prototype.slice.call(
document.querySelectorAll('.tab-button[data-tab]')
);
var state = {
activeTab: normalizeTab(readParam('tab')) || 'cp',
tabs: {
cp: [normalizeLevel(readParam('level')) || 1],
brother: [2, 2],
sister: [4, 5],
},
};
function readParam(name) {
var params = new URLSearchParams(window.location.search || '');
return params.get(name);
}
function normalizeTab(value) {
var tab = String(value || '')
.trim()
.toLowerCase();
return VALID_TABS.indexOf(tab) >= 0 ? tab : '';
}
function normalizeLevel(value) {
var level = Number(value);
return Number.isFinite(level) && level >= 1 && level <= 5
? Math.floor(level)
: 0;
}
function t(key, fallback) {
if (window.HyAppI18n && window.HyAppI18n.t) {
return window.HyAppI18n.t(key, fallback);
}
return fallback || key;
}
function escapeHTML(value) {
return String(value == null ? '' : value)
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;');
}
function setActiveTab(tab) {
var nextTab = normalizeTab(tab) || 'cp';
state.activeTab = nextTab;
page.setAttribute('data-tab', nextTab);
tabButtons.forEach(function (button) {
button.classList.toggle(
'is-active',
button.getAttribute('data-tab') === nextTab
);
});
render();
}
function cardHTML(level, index) {
var safeLevel = normalizeLevel(level) || 1;
var label = t('cpSpace.levelCard', 'Best friend level {level}').replace(
'{level}',
String(safeLevel)
);
return [
'<article class="relation-card" data-level="',
safeLevel,
'">',
'<img src="',
LEVEL_IMAGES[safeLevel],
'" alt="',
escapeHTML(label),
'" draggable="false" />',
'<button class="cancel-hotspot" type="button" data-cancel-index="',
index,
'" aria-label="',
escapeHTML(t('cpSpace.cancel', 'Cancel')),
'"></button>',
'</article>',
].join('');
}
function render() {
var levels = state.tabs[state.activeTab] || [];
if (!levels.length) {
contentPanel.innerHTML =
'<div class="empty-state">' +
escapeHTML(t('cpSpace.empty', 'No relationship data yet.')) +
'</div>';
return;
}
contentPanel.innerHTML =
'<div class="relation-list">' +
levels.map(cardHTML).join('') +
'</div>';
}
function applyExternalData(payload) {
var data = payload || {};
var nextTabs = {};
VALID_TABS.forEach(function (tab) {
var raw = data[tab];
if (!Array.isArray(raw)) return;
var normalized = raw
.map(function (item) {
return normalizeLevel(
typeof item === 'object' ? item.level : item
);
})
.filter(Boolean);
if (normalized.length) nextTabs[tab] = normalized;
});
// Flutter 可以在 WebView 注入 window.HyAppCPSpaceData 或派发 hyapp:cp-space-data
// 页面只接受 1-5 的等级编号,避免 H5 自己猜测关系状态或渲染后端未确认的数据。
Object.keys(nextTabs).forEach(function (tab) {
state.tabs[tab] = nextTabs[tab];
});
if (normalizeTab(data.activeTab)) state.activeTab = data.activeTab;
setActiveTab(state.activeTab);
}
function handleCancel(index) {
var level = (state.tabs[state.activeTab] || [])[Number(index)] || 0;
if (window.HyAppBridge && window.HyAppBridge.post) {
window.HyAppBridge.post('cpSpaceCancel', {
relation_type: state.activeTab,
level: level,
});
}
}
function bindEvents() {
if (backButton) {
backButton.addEventListener('click', function () {
if (window.HyAppBridge && window.HyAppBridge.back) {
window.HyAppBridge.back();
return;
}
window.history.back();
});
}
tabButtons.forEach(function (button) {
button.addEventListener('click', function () {
setActiveTab(button.getAttribute('data-tab'));
});
});
contentPanel.addEventListener('click', function (event) {
var target = event.target.closest('[data-cancel-index]');
if (!target) return;
handleCancel(target.getAttribute('data-cancel-index'));
});
window.addEventListener('hyapp:cp-space-data', function (event) {
applyExternalData(event.detail || {});
});
window.addEventListener('hyapp:i18n-ready', render);
}
bindEvents();
if (window.HyAppCPSpaceData) applyExternalData(window.HyAppCPSpaceData);
else setActiveTab(state.activeTab);
if (window.HyAppBridge && window.HyAppBridge.ready) {
window.HyAppBridge.ready({ page: 'cp-space' });
}
})();