(function (root, factory) { if (typeof module === 'object' && module.exports) { module.exports = factory(root); return; } root.HelpPages = factory(root); if (root.document) { root.document.addEventListener('DOMContentLoaded', function () { root.HelpPages.init(); }); } })(typeof globalThis !== 'undefined' ? globalThis : window, function (root) { 'use strict'; function escapeHtml(value) { return String(value === undefined || value === null ? '' : value) .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"') .replace(/'/g, '''); } function normalizeId(value) { var text; if (typeof value === 'number' && !Number.isSafeInteger(value)) return ''; if (value === undefined || value === null) return ''; text = String(value).trim(); return /^[1-9][0-9]*$/.test(text) ? text : ''; } function normalizeCount(value) { var text; if (value === undefined || value === null || value === '') return '0'; if (typeof value === 'number' && (!Number.isSafeInteger(value) || value < 0)) return ''; text = String(value).trim(); return /^(?:0|[1-9][0-9]*)$/.test(text) ? text : ''; } function text(value) { return value === undefined || value === null ? '' : String(value).trim(); } function normalizeHelpArticle(item) { var source = item || {}; var helpId = normalizeId(source.helpId); var helpTitle = text(source.helpTitle); var helpContent = text(source.helpContent); var viewCount = normalizeCount(source.viewCount); if (!helpId || !helpTitle || !helpContent || !viewCount || String(source.status) !== '0') { return null; } return { helpId: helpId, helpCategory: text(source.helpCategory), helpTitle: helpTitle, helpContent: helpContent, viewCount: viewCount }; } function normalizeHelpArticleList(data) { var items; if (!Array.isArray(data)) return []; items = data.map(normalizeHelpArticle); return items.some(function (item) { return !item; }) ? [] : items; } function renderHelpArticleList(data) { var items = normalizeHelpArticleList(data); if (!items.length) return '
当前暂无帮助文章
'; return items.map(function (item) { var meta = [item.helpCategory, '浏览 ' + item.viewCount + ' 次'].filter(Boolean).join(' · '); return '
' + '' + escapeHtml(item.helpTitle) + '' + '

' + escapeHtml(meta) + '

' + '
' + '
'; }).join(''); } function renderHelpArticleDetail(item) { var article = normalizeHelpArticle(item); var meta; if (!article) return '
帮助文章不存在或已停用
'; meta = [article.helpCategory, '浏览 ' + article.viewCount + ' 次'].filter(Boolean).join(' · '); return '

' + escapeHtml(meta) + '

' + escapeHtml(article.helpContent).replace(/\r?\n/g, '
') + '

'; } async function loadHelpArticleDetail(api, helpId) { var targetId = normalizeId(helpId); var article; if (!api || typeof api.helpArticleDetail !== 'function') throw new Error('帮助文章接口不可用'); if (!targetId) throw new Error('帮助文章编号无效'); article = normalizeHelpArticle(await api.helpArticleDetail(targetId)); if (!article) throw new Error('帮助文章详情响应无效'); if (article.helpId !== targetId) throw new Error('详情响应与请求编号不一致'); return article; } async function loadHelpArticles(api) { var data; var items; if (!api || typeof api.helpArticles !== 'function') throw new Error('帮助文章接口不可用'); data = await api.helpArticles(); items = normalizeHelpArticleList(data); if (!Array.isArray(data) || items.length !== data.length) throw new Error('帮助文章列表响应无效'); return items; } function shouldRedirectToLogin(api, error) { var status = error && (error.status || error.code); return !api || !api.getToken || !api.getToken() || Number(status) === 401; } function redirectToLogin(api) { if (api && api.clearToken) api.clearToken(); root.NavigationUtil.open('login.html'); } function isForbidden(error) { return Number(error && (error.status || error.code)) === 403; } async function init() { var list = root.document && root.document.querySelector('[data-help-list]'); var status = root.document && root.document.querySelector('[data-help-status]'); var refresh = root.document && root.document.querySelector('[data-help-refresh]'); var api = root.GenealogyApi && root.GenealogyApi.defaultClient; if (!list) return; if (shouldRedirectToLogin(api)) { redirectToLogin(api); return; } function setApiState(target, type, message) { if (!target) return; if (root.ProfileUI && root.ProfileUI.setApiState && type) { root.ProfileUI.setApiState(target, type, message); return; } target.textContent = message || ''; } function setStatus(type, message) { setApiState(status, type, message); } function setHelpList(items) { if (!items.length) { setApiState(list, 'empty', '当前暂无帮助文章。'); return; } list.innerHTML = renderHelpArticleList(items); } function setPendingButton(button, pending, label) { if (!button) return; if (!button.dataset.defaultLabel) button.dataset.defaultLabel = button.textContent; button.disabled = pending; button.textContent = pending ? label : button.dataset.defaultLabel; } async function refreshList() { try { list.classList.add('is-loading'); setApiState(list, 'loading', '正在读取帮助文章…'); setStatus('loading', '正在读取帮助文章…'); setHelpList(await loadHelpArticles(api)); setStatus('', ''); } catch (error) { if (shouldRedirectToLogin(api, error)) { redirectToLogin(api); return; } setApiState(list, isForbidden(error) ? 'forbidden' : 'error', isForbidden(error) ? '暂无权限查看帮助文章。' : '帮助文章读取失败,请稍后重试。'); setStatus(isForbidden(error) ? 'forbidden' : 'error', isForbidden(error) ? '暂无权限查看帮助文章。' : (error.message || '帮助文章读取失败,请稍后重试。')); } finally { list.classList.remove('is-loading'); } } list.addEventListener('click', async function (event) { var button = event.target.closest('[data-help-detail-id]'); var helpId; var panel; if (!button || button.disabled) return; helpId = button.getAttribute('data-help-detail-id'); panel = list.querySelector('[data-help-detail-panel="' + helpId + '"]'); if (!panel) return; button.disabled = true; setApiState(panel, 'loading', '正在读取完整解答…'); try { panel.innerHTML = renderHelpArticleDetail(await loadHelpArticleDetail(api, helpId)); } catch (error) { if (shouldRedirectToLogin(api, error)) { redirectToLogin(api); return; } setApiState(panel, isForbidden(error) ? 'forbidden' : 'error', isForbidden(error) ? '暂无权限查看该帮助文章。' : (error.message || '帮助文章详情读取失败,请稍后重试。')); } }); if (refresh) refresh.addEventListener('click', async function () { setPendingButton(refresh, true, '正在刷新…'); try { await refreshList(); } finally { setPendingButton(refresh, false, '正在刷新…'); } }); await refreshList(); } return { normalizeHelpArticle: normalizeHelpArticle, normalizeHelpArticleList: normalizeHelpArticleList, renderHelpArticleList: renderHelpArticleList, renderHelpArticleDetail: renderHelpArticleDetail, loadHelpArticleDetail: loadHelpArticleDetail, loadHelpArticles: loadHelpArticles, isForbidden: isForbidden, shouldRedirectToLogin: shouldRedirectToLogin, init: init }; });