(function (root, factory) { // 字辈谱模块同时支持浏览器页面和 Node 单元测试。 if (typeof module === 'object' && module.exports) { module.exports = factory(root); return; } root.GenerationPages = factory(root); if (root.document) { root.document.addEventListener('DOMContentLoaded', function () { root.GenerationPages.init(); }); } })(typeof globalThis !== 'undefined' ? globalThis : window, function (root) { 'use strict'; var documentRef = root.document; function normalizeList(data) { // 通用列表响应可能是数组,也可能包在 rows、records、list 或 data 中。 if (Array.isArray(data)) return data; if (!data || typeof data !== 'object') return []; if (Array.isArray(data.rows)) return data.rows; if (Array.isArray(data.records)) return data.records; if (Array.isArray(data.list)) return data.list; if (Array.isArray(data.data)) return data.data; return []; } function pick(item, keys, fallback) { var source = item || {}; var index; var value; for (index = 0; index < keys.length; index += 1) { value = source[keys[index]]; if (value !== undefined && value !== null && value !== '') return value; } return fallback || ''; } function escapeHtml(value) { // 字辈文本进入 innerHTML 前统一转义。 return String(value === undefined || value === null ? '' : value) .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"') .replace(/'/g, '''); } function getApi() { return root.GenealogyApi && root.GenealogyApi.defaultClient; } function query(selector, rootNode) { if (!documentRef) return null; return (rootNode || documentRef).querySelector(selector); } function queryAll(selector, rootNode) { if (!documentRef) return []; return Array.prototype.slice.call((rootNode || documentRef).querySelectorAll(selector)); } function showMessage(message) { if (root.layui && root.layui.layer) { root.layui.layer.msg(message); return; } if (root.alert) { root.alert(message); } } function getQueryParam(search, name) { var params = new URLSearchParams(String(search || '').replace(/^\?/, '')); return params.get(name) || ''; } function getCurrentGenealogyId() { var search = root.location && root.location.search; var page = query('[data-generation-page]'); return getQueryParam(search, 'id') || getQueryParam(search, 'genealogyId') || (page && page.getAttribute('data-genealogy-id')) || ''; } function toNumber(value, fallback) { var number = Number(String(value || '').trim()); return Number.isFinite(number) && number > 0 ? number : fallback; } function toBoolean(value) { return value === true || value === 'true' || value === '1' || value === 'on'; } function buildGenerationBody(values) { // GenerationPoemBody 必填 generationNo、generationText,其余字段给接口默认值。 var source = values || {}; var generationNo = toNumber(source.generationNo, 1); return { generationNo: generationNo, generationText: String(source.generationText || '').trim(), description: String(source.description || '').trim(), sortOrder: toNumber(source.sortOrder, generationNo), status: String(source.status || '').trim() || '0' }; } function buildGenerationBatchBody(values) { // GenerationPoemBatchBody 只包含批量文本和是否遇到断代即停止。 var source = values || {}; return { content: String(source.content || '').trim(), stopMissingOldGeneration: toBoolean(source.stopMissingOldGeneration) }; } function getFormValues(form) { var values = {}; queryAll('[name]', form).forEach(function (field) { if (field.type === 'checkbox') { values[field.name] = field.checked ? 'on' : ''; return; } values[field.name] = field.value; }); return values; } function setBatchStatus(message) { var statusNode = query('[data-generation-batch-status]'); if (statusNode) { statusNode.textContent = message || ''; } } function buildGenerationRow(item, genealogyId) { var poemId = pick(item, ['poemId', 'id'], ''); var generationNo = pick(item, ['generationNo', 'generation', 'sortOrder'], '1'); var text = pick(item, ['generationText', 'content', 'text'], '未设置'); var memberCount = pick(item, ['memberCount', 'personCount', 'count'], '0'); var description = pick(item, ['description', 'remark'], '暂无备注'); return '
' + '

第 ' + escapeHtml(generationNo) + ' 代:' + escapeHtml(text) + '

' + escapeHtml(memberCount) + ' 人 · ' + escapeHtml(description) + '

' + '' + '
'; } function renderGenerations(items, genealogyId) { var container = query('[data-generation-list]'); if (!container) return; if (!items.length) { container.innerHTML = '
暂无字辈记录
'; return; } container.innerHTML = items.map(function (item) { return buildGenerationRow(item, genealogyId); }).join(''); } function renderBatchPreview(data) { var container = query('[data-generation-batch-preview]'); var items = normalizeList(data); if (!container) return; if (!items.length) { container.innerHTML = '
预览完成,接口未返回明细
'; return; } container.innerHTML = items.map(function (item) { return buildGenerationRow(item, getCurrentGenealogyId()); }).join(''); } async function loadGenerations() { var api = getApi(); var container = query('[data-generation-list]'); var genealogyId = getCurrentGenealogyId(); if (!api || !container) return; if (!genealogyId) { container.innerHTML = '
请从具体家谱进入字辈谱
'; return; } container.classList.add('is-loading'); try { renderGenerations(normalizeList(await api.generationPoems(genealogyId)), genealogyId); } catch (error) { showMessage(error.message || '字辈谱加载失败'); } finally { container.classList.remove('is-loading'); } } async function createGeneration() { var api = getApi(); var genealogyId = getCurrentGenealogyId(); var generationNo; var generationText; var body; if (!api || !genealogyId) { showMessage('请从具体家谱进入字辈谱'); return; } generationNo = root.prompt('请输入世代序号', ''); if (!generationNo) return; generationText = root.prompt('请输入字辈内容', ''); if (!generationText) return; body = buildGenerationBody({ generationNo: generationNo, generationText: generationText }); try { await api.createGenerationPoem(genealogyId, body); showMessage('字辈已新增'); loadGenerations(); } catch (error) { showMessage(error.message || '新增字辈失败'); } } async function editGeneration(button) { var api = getApi(); var genealogyId = button.getAttribute('data-genealogy-id') || getCurrentGenealogyId(); var poemId = button.getAttribute('data-generation-edit'); var currentText = button.getAttribute('data-generation-text') || ''; var generationNo = button.getAttribute('data-generation-no') || '1'; var nextText; if (!api || !genealogyId || !poemId) return; nextText = root.prompt('请输入新的字辈', currentText); if (!nextText) return; button.classList.add('is-loading'); try { await api.updateGenerationPoem(genealogyId, poemId, buildGenerationBody({ generationNo: generationNo, generationText: nextText })); showMessage('字辈已更新'); loadGenerations(); } catch (error) { showMessage(error.message || '更新字辈失败'); } finally { button.classList.remove('is-loading'); } } async function submitGenerationBatch(action) { var api = getApi(); var genealogyId = getCurrentGenealogyId(); var form = query('[data-generation-batch-form]'); var body; var result; if (!api || !genealogyId || !form) { showMessage('请从具体家谱进入字辈谱'); return; } body = buildGenerationBatchBody(getFormValues(form)); if (!body.content) { showMessage('请填写批量字辈内容'); return; } try { setBatchStatus(action === 'save' ? '批量保存中...' : '批量预览中...'); if (action === 'save') { await api.saveGenerationPoemsBatch(genealogyId, body); setBatchStatus('批量保存完成'); showMessage('批量字辈已保存'); loadGenerations(); return; } result = await api.previewGenerationPoems(genealogyId, body); renderBatchPreview(result); setBatchStatus('批量预览完成'); } catch (error) { setBatchStatus('批量处理失败'); showMessage(error.message || '批量字辈处理失败'); } } function bindActions() { if (!documentRef) return; documentRef.addEventListener('click', function (event) { var addButton = event.target.closest('[data-generation-add]'); var editButton = event.target.closest('[data-generation-edit]'); var batchButton = event.target.closest('[data-generation-batch-action]'); if (addButton) { event.preventDefault(); createGeneration(); } if (editButton) { event.preventDefault(); editGeneration(editButton); } if (batchButton) { event.preventDefault(); submitGenerationBatch(batchButton.getAttribute('data-generation-batch-action')); } }); } function init() { if (!documentRef) return; bindActions(); loadGenerations(); } return { normalizeList: normalizeList, buildGenerationBody: buildGenerationBody, buildGenerationBatchBody: buildGenerationBatchBody, buildGenerationRow: buildGenerationRow, init: init }; });