309598bfa6
- 在ApiClient中新增submitFeedback、myFeedback、helpArticles、helpArticleDetail、 siteArticles、promotions、vipPackages、createVipOrder、vipOrders等方法 - 添加帮助文章和站点资讯的参数验证逻辑 - 更新测试文件添加新的API方法测试用例 - 在HTML页面中添加反馈、帮助和VIP服务相关页面的脚本引用 - 更新加入家谱页面为完整的申请流程界面 - 修改资讯详情页面为站点资讯展示页面 - 更新AxiosRequestUtil中认证处理逻辑 - 添加世系树渲染的HTML生成函数用于页面复用 - 更新文档中的API契约说明和页面规划
203 lines
6.8 KiB
JavaScript
203 lines
6.8 KiB
JavaScript
(function (root, factory) {
|
|
if (typeof module === 'object' && module.exports) {
|
|
module.exports = factory(root);
|
|
return;
|
|
}
|
|
|
|
root.FamilyHomePages = factory(root);
|
|
if (root.document) {
|
|
root.document.addEventListener('DOMContentLoaded', function () {
|
|
root.FamilyHomePages.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, '"')
|
|
.replace(/'/g, ''');
|
|
}
|
|
|
|
function normalizeId(value) {
|
|
var result;
|
|
|
|
if (typeof value === 'number' && !Number.isSafeInteger(value)) return '';
|
|
if (value === undefined || value === null) return '';
|
|
result = String(value).trim();
|
|
return /^[1-9][0-9]*$/.test(result) ? result : '';
|
|
}
|
|
|
|
function text(value) {
|
|
if (value === undefined || value === null) return '';
|
|
return String(value).trim();
|
|
}
|
|
|
|
function normalizeCount(value) {
|
|
var result = Number(value);
|
|
|
|
return Number.isSafeInteger(result) && result >= 0 ? result : null;
|
|
}
|
|
|
|
function normalizeFamilyOverview(item, expectedGenealogyId) {
|
|
var source = item || {};
|
|
var genealogyId = normalizeId(source.genealogyId);
|
|
var expectedId = normalizeId(expectedGenealogyId);
|
|
var memberCount = normalizeCount(source.memberCount);
|
|
var personCount = normalizeCount(source.personCount);
|
|
|
|
if (!genealogyId || genealogyId !== expectedId ||
|
|
!text(source.genealogyName) || String(source.status) !== '0' ||
|
|
memberCount === null || personCount === null) {
|
|
return null;
|
|
}
|
|
return {
|
|
genealogyId: genealogyId,
|
|
genealogyNo: text(source.genealogyNo),
|
|
genealogyName: text(source.genealogyName),
|
|
surname: text(source.surname),
|
|
ancestralHall: text(source.ancestralHall),
|
|
originPlace: text(source.originPlace),
|
|
regionFullName: text(source.regionFullName),
|
|
memberCount: memberCount,
|
|
personCount: personCount,
|
|
canManage: source.canManage === true,
|
|
canEditContent: source.canEditContent === true
|
|
};
|
|
}
|
|
|
|
function renderFamilyOverview(overview) {
|
|
var source = overview || {};
|
|
var details = [
|
|
source.genealogyNo ? '家谱编号 ' + source.genealogyNo : '',
|
|
source.surname ? '姓氏 ' + source.surname : '',
|
|
source.ancestralHall ? '堂号 ' + source.ancestralHall : '',
|
|
source.originPlace ? '祖籍 ' + source.originPlace : '',
|
|
source.regionFullName ? '地区 ' + source.regionFullName : ''
|
|
].filter(Boolean).join(' · ');
|
|
|
|
return '<h3>' + escapeHtml(source.genealogyName) + '</h3><p>' +
|
|
escapeHtml(details) + '</p><p>成员 ' + escapeHtml(source.memberCount) +
|
|
' 人 · 世系人物 ' + escapeHtml(source.personCount) + ' 人</p>';
|
|
}
|
|
|
|
function shouldShowFamilyManagement(overview) {
|
|
return !!overview && overview.canManage === true;
|
|
}
|
|
|
|
function shouldRedirectToLogin(api, error) {
|
|
var status = error && (error.status || error.code);
|
|
|
|
return !api || !api.getToken || !api.getToken() || Number(status) === 401;
|
|
}
|
|
|
|
async function loadFamilyHome(api, genealogyId) {
|
|
var normalizedId = normalizeId(genealogyId);
|
|
var results;
|
|
var overview;
|
|
|
|
if (!normalizedId || !api || !api.genealogyOverview || !api.lineageTree) {
|
|
throw new Error('家谱主页接口初始化失败');
|
|
}
|
|
results = await Promise.all([
|
|
api.genealogyOverview(normalizedId),
|
|
api.lineageTree(normalizedId)
|
|
]);
|
|
overview = normalizeFamilyOverview(results[0], normalizedId);
|
|
if (!overview) throw new Error('家谱概览响应无效');
|
|
return {
|
|
overview: overview,
|
|
tree: results[1]
|
|
};
|
|
}
|
|
|
|
function redirectToLogin(api) {
|
|
if (api && api.clearToken) api.clearToken();
|
|
if (!root.location) return;
|
|
if (typeof root.location.replace === 'function') root.location.replace('login.html');
|
|
else root.location.href = 'login.html';
|
|
}
|
|
|
|
function query(selector) {
|
|
return root.document && root.document.querySelector(selector);
|
|
}
|
|
|
|
function queryAll(selector) {
|
|
return root.document ? Array.prototype.slice.call(root.document.querySelectorAll(selector)) : [];
|
|
}
|
|
|
|
function setText(selector, value) {
|
|
var element = query(selector);
|
|
|
|
if (element) element.textContent = value;
|
|
}
|
|
|
|
async function initFamilyHomePage() {
|
|
var page = query('[data-family-home-page]');
|
|
var api = root.GenealogyApi && root.GenealogyApi.defaultClient;
|
|
var genealogyId;
|
|
var result;
|
|
|
|
if (!page) return;
|
|
if (shouldRedirectToLogin(api)) {
|
|
redirectToLogin(api);
|
|
return;
|
|
}
|
|
genealogyId = root.ProfileUI && root.ProfileUI.getGenealogyId();
|
|
if (!genealogyId) {
|
|
if (root.location && typeof root.location.replace === 'function') {
|
|
root.location.replace('profile-families.html?next=profile-family-home.html');
|
|
}
|
|
return;
|
|
}
|
|
if (root.ProfileUI && root.ProfileUI.syncGenealogyContextLinks) {
|
|
root.ProfileUI.syncGenealogyContextLinks();
|
|
}
|
|
if (!root.LineagePages || !root.LineagePages.renderLineageTreeHtml) {
|
|
setText('[data-family-home-status]', '世系预览初始化失败,请刷新后重试');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
result = await loadFamilyHome(api, genealogyId);
|
|
setText('[data-family-home-title]', result.overview.genealogyName);
|
|
query('[data-family-home-overview]').innerHTML = renderFamilyOverview(result.overview);
|
|
setText('[data-family-home-member-count]', String(result.overview.memberCount));
|
|
setText('[data-family-home-person-count]', String(result.overview.personCount));
|
|
queryAll('[data-family-home-management]').forEach(function (element) {
|
|
element.hidden = !shouldShowFamilyManagement(result.overview);
|
|
});
|
|
query('[data-lineage-home-tree]').innerHTML =
|
|
root.LineagePages.renderLineageTreeHtml(result.tree);
|
|
setText('[data-family-home-status]', '家谱概览已更新');
|
|
} catch (error) {
|
|
if (shouldRedirectToLogin(api, error)) {
|
|
redirectToLogin(api);
|
|
return;
|
|
}
|
|
query('[data-family-home-overview]').innerHTML =
|
|
'<div class="api-empty">家谱概览读取失败,请稍后重试</div>';
|
|
query('[data-lineage-home-tree]').innerHTML =
|
|
'<div class="api-empty">世系树读取失败,请稍后重试</div>';
|
|
setText('[data-family-home-status]', error.message || '家谱主页读取失败,请稍后重试');
|
|
}
|
|
}
|
|
|
|
function init() {
|
|
return initFamilyHomePage();
|
|
}
|
|
|
|
return {
|
|
normalizeFamilyOverview: normalizeFamilyOverview,
|
|
renderFamilyOverview: renderFamilyOverview,
|
|
shouldShowFamilyManagement: shouldShowFamilyManagement,
|
|
shouldRedirectToLogin: shouldRedirectToLogin,
|
|
loadFamilyHome: loadFamilyHome,
|
|
initFamilyHomePage: initFamilyHomePage,
|
|
init: init
|
|
};
|
|
});
|