Files
jiapu/public/js/join-apply-pages.js
T
2026-07-09 17:30:10 +08:00

272 lines
8.6 KiB
JavaScript

(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, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;');
}
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 '<div class="module-row join-apply-row" data-join-apply-id="' + escapeHtml(applyId) + '">' +
'<div><h3>' + escapeHtml(name) + '申请加入家谱</h3><p>' + escapeHtml(time) + ' · ' + escapeHtml(relation) + '</p></div>' +
'<div class="bottom-actions">' +
'<button class="btn primary" type="button" data-join-audit="approve" data-genealogy-id="' + escapeHtml(genealogyId) + '" data-apply-id="' + escapeHtml(applyId) + '">同意</button>' +
'<button class="btn ghost" type="button" data-join-audit="reject" data-genealogy-id="' + escapeHtml(genealogyId) + '" data-apply-id="' + escapeHtml(applyId) + '">拒绝</button>' +
'</div></div>';
}
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 === '待审核'
? '<button class="btn ghost" type="button" data-join-cancel="' + escapeHtml(applyId) + '">撤销申请</button>'
: '<span class="pill">' + escapeHtml(status) + '</span>';
return '<div class="module-row join-apply-row" data-join-apply-id="' + escapeHtml(applyId) + '">' +
'<div><h3>' + escapeHtml(genealogyName) + '</h3><p>' + escapeHtml(status) + ' · ' + escapeHtml(relation) + '</p></div>' +
action +
'</div>';
}
function renderPending(items, genealogyId) {
var container = query('[data-join-apply-list="pending"]');
if (!container) return;
if (!items.length) {
container.innerHTML = '<div class="api-empty">暂无待审核申请</div>';
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 = '<div class="api-empty">暂无加入申请记录</div>';
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 = '<div class="api-empty">请从具体家谱进入审核页</div>';
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
};
});