家谱现有接口调试50%
This commit is contained in:
@@ -0,0 +1,349 @@
|
||||
(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, '"')
|
||||
.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 '<div class="module-row generation-row" data-generation-id="' + escapeHtml(poemId) + '">' +
|
||||
'<div><h3>第 ' + escapeHtml(generationNo) + ' 代:' + escapeHtml(text) + '</h3><p>' + escapeHtml(memberCount) + ' 人 · ' + escapeHtml(description) + '</p></div>' +
|
||||
'<button class="pill" type="button" data-generation-edit="' + escapeHtml(poemId) + '" data-generation-no="' + escapeHtml(generationNo) + '" data-generation-text="' + escapeHtml(text) + '" data-genealogy-id="' + escapeHtml(genealogyId) + '">编辑</button>' +
|
||||
'</div>';
|
||||
}
|
||||
|
||||
function renderGenerations(items, genealogyId) {
|
||||
var container = query('[data-generation-list]');
|
||||
|
||||
if (!container) return;
|
||||
if (!items.length) {
|
||||
container.innerHTML = '<div class="api-empty">暂无字辈记录</div>';
|
||||
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 = '<div class="api-empty">预览完成,接口未返回明细</div>';
|
||||
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 = '<div class="api-empty">请从具体家谱进入字辈谱</div>';
|
||||
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
|
||||
};
|
||||
});
|
||||
Reference in New Issue
Block a user