(function (root, factory) { // 加入申请模块同时支持浏览器页面和 Node 单元测试。 if (typeof module === 'object' && module.exports) { module.exports = factory(root); return; } root.JoinApplyPages = factory(root); if (root.document) { root.document.addEventListener('DOMContentLoaded', function () { root.JoinApplyPages.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) { // 申请人信息来自接口,渲染前统一转义。 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) { return (rootNode || documentRef).querySelector(selector); } function showMessage(message) { if (root.layui && root.layui.layer) { root.layui.layer.msg(message); return; } 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 fromQuery = getQueryParam(search, 'id') || getQueryParam(search, 'genealogyId'); var fromPage = query('[data-genealogy-id]'); return fromQuery || (fromPage && fromPage.getAttribute('data-genealogy-id')) || ''; } function formatApplyStatus(status) { // 审核接口要求 status,按常见字典值做页面中文展示。 var map = { 0: '待审核', 1: '已通过', 2: '已拒绝' }; return map[status] || status || '待审核'; } function buildAuditBody(action, remark) { var isReject = action === 'reject'; return { status: isReject ? '2' : '1', auditRemark: remark || (isReject ? '信息核验未通过' : '信息核验通过') }; } function buildPendingRow(item, genealogyId) { var applyId = pick(item, ['applyId', 'id'], ''); var name = pick(item, ['applicantName', 'name', 'nickName'], '未命名申请人'); var relation = pick(item, ['relationDesc', 'applyReason', 'remark'], '关系说明待确认'); var time = pick(item, ['createTime', 'createdAt', 'applyTime'], '提交时间待确认'); return '
' + '

' + escapeHtml(name) + '申请加入家谱

' + escapeHtml(time) + ' · ' + escapeHtml(relation) + '

' + '
' + '' + '' + '
'; } function buildMineRow(item) { var applyId = pick(item, ['applyId', 'id'], ''); var genealogyName = pick(item, ['genealogyName', 'familyName', 'name'], '未命名家谱'); var status = formatApplyStatus(pick(item, ['status', 'auditStatus'], '0')); var relation = pick(item, ['relationDesc', 'applyReason', 'auditRemark'], '关系说明待确认'); var action = status === '待审核' ? '' : '' + escapeHtml(status) + ''; return '
' + '

' + escapeHtml(genealogyName) + '

' + escapeHtml(status) + ' · ' + escapeHtml(relation) + '

' + action + '
'; } function renderPending(items, genealogyId) { var container = query('[data-join-apply-list="pending"]'); if (!container) return; if (!items.length) { container.innerHTML = '
暂无待审核申请
'; return; } container.innerHTML = items.map(function (item) { return buildPendingRow(item, genealogyId); }).join(''); } function renderMine(items) { var container = query('[data-join-apply-list="mine"]'); if (!container) return; if (!items.length) { container.innerHTML = '
暂无加入申请记录
'; return; } container.innerHTML = items.map(buildMineRow).join(''); } async function loadPending() { var api = getApi(); var container = query('[data-join-apply-list="pending"]'); var genealogyId = getCurrentGenealogyId(); if (!api || !container) return; if (!genealogyId) { container.innerHTML = '
请从具体家谱进入审核页
'; return; } container.classList.add('is-loading'); try { renderPending(normalizeList(await api.pendingJoinApplies(genealogyId)), genealogyId); } catch (error) { showMessage(error.message || '待审核申请加载失败'); } finally { container.classList.remove('is-loading'); } } async function loadMine() { var api = getApi(); var container = query('[data-join-apply-list="mine"]'); if (!api || !container) return; container.classList.add('is-loading'); try { renderMine(normalizeList(await api.myJoinApplies())); } catch (error) { showMessage(error.message || '加入申请记录加载失败'); } finally { container.classList.remove('is-loading'); } } async function audit(button) { var api = getApi(); var action = button.getAttribute('data-join-audit'); var genealogyId = button.getAttribute('data-genealogy-id'); var applyId = button.getAttribute('data-apply-id'); var remark = action === 'reject' ? root.prompt('请输入拒绝原因', '') : ''; if (!api || !genealogyId || !applyId) return; if (action === 'reject' && remark === null) return; button.classList.add('is-loading'); try { await api.auditJoinApply(genealogyId, applyId, buildAuditBody(action, remark)); showMessage(action === 'reject' ? '已拒绝申请' : '已同意申请'); loadPending(); } catch (error) { showMessage(error.message || '审核申请失败'); } finally { button.classList.remove('is-loading'); } } async function cancel(button) { var api = getApi(); var applyId = button.getAttribute('data-join-cancel'); if (!api || !applyId) return; if (root.confirm && !root.confirm('确认撤销当前加入申请?')) return; button.classList.add('is-loading'); try { await api.cancelJoinApply(applyId); showMessage('已撤销加入申请'); loadMine(); } catch (error) { showMessage(error.message || '撤销申请失败'); } finally { button.classList.remove('is-loading'); } } function bindActions() { if (!documentRef) return; documentRef.addEventListener('click', function (event) { var auditButton = event.target.closest('[data-join-audit]'); var cancelButton = event.target.closest('[data-join-cancel]'); if (auditButton) { event.preventDefault(); audit(auditButton); } if (cancelButton) { event.preventDefault(); cancel(cancelButton); } }); } function init() { if (!documentRef) return; bindActions(); loadPending(); loadMine(); } return { normalizeList: normalizeList, formatApplyStatus: formatApplyStatus, buildAuditBody: buildAuditBody, buildPendingRow: buildPendingRow, buildMineRow: buildMineRow, init: init }; });