(function (root, factory) { if (typeof module === 'object' && module.exports) { module.exports = factory(root); return; } root.PersonDocumentPages = factory(root); if (root.document) root.document.addEventListener('DOMContentLoaded', root.PersonDocumentPages.init); })(typeof globalThis !== 'undefined' ? globalThis : window, function (root) { 'use strict'; function confirmAction(message) { if (root.ProfileUI && typeof root.ProfileUI.confirmAction === 'function') { return root.ProfileUI.confirmAction(message); } return Promise.resolve(!root['confirm'] || root['confirm'](message)); } function promptAction(title) { if (root.ProfileUI && typeof root.ProfileUI.promptAction === 'function') { return root.ProfileUI.promptAction({ title: title, formType: 1, maxlength: 100 }); } return Promise.resolve(root['prompt'] ? root['prompt'](title) : null); } var USAGE_LABELS = { FRONT: '正面', BACK: '反面', ATTACHMENT: '附件' }; function escapeHtml(value) { return String(value === undefined || value === null ? '' : value) .replace(/&/g, '&').replace(//g, '>') .replace(/"/g, '"').replace(/'/g, '''); } function normalizeId(value) { var text = String(value === undefined || value === null ? '' : value).trim(); return /^[1-9][0-9]*$/.test(text) ? text : ''; } function normalizeDocument(item) { var source = item || {}; var documentId = normalizeId(source.documentId); var personId = normalizeId(source.lineagePersonId); var title = String(source.documentTitle || '').trim(); if (!documentId || !personId || !title || !Array.isArray(source.resources)) return null; return { documentId: documentId, lineagePersonId: personId, lineagePersonName: String(source.lineagePersonName || '').trim(), documentType: String(source.documentType || '').trim(), documentTypeLabel: String(source.documentTypeLabel || source.documentType || '').trim(), documentTitle: title, maskedIdentifier: String(source.maskedIdentifier || '').trim(), description: String(source.description || '').trim(), contentProtected: source.contentProtected === true, contentUnlocked: source.contentUnlocked === true, canEdit: source.canEdit === true, canDelete: source.canDelete === true, resources: source.resources.map(function (resource) { var resourceId = normalizeId(resource && resource.resourceId); var usageType = String(resource && resource.usageType || '').trim(); return resourceId && USAGE_LABELS[usageType] ? { resourceId: resourceId, usageType: usageType } : null; }).filter(Boolean) }; } function buildDocumentBody(values) { var source = values || {}; return { lineagePersonId: normalizeId(source.lineagePersonId), documentType: String(source.documentType || '').trim(), documentTitle: String(source.documentTitle || '').trim(), maskedIdentifier: String(source.maskedIdentifier || '').trim(), description: String(source.description || '').trim(), status: '0' }; } function validateDocumentBody(body) { if (!body.lineagePersonId) return '请选择关联人物'; if (!body.documentType) return '请选择证件类型'; if (!body.documentTitle) return '请填写证件标题'; if (body.documentTitle.length > 100) return '证件标题不能超过 100 个字符'; if (body.maskedIdentifier.length > 100) return '脱敏标识不能超过 100 个字符'; if (body.description.length > 1000) return '说明不能超过 1000 个字符'; return ''; } function renderDocuments(data) { var items = Array.isArray(data) ? data.map(normalizeDocument).filter(Boolean) : []; if (!items.length) return '
当前家谱还没有重要证件档案
'; return items.map(function (item) { var resources = item.resources.map(function (resource) { return ''; }).join(''); return '

' + escapeHtml(item.documentTitle) + '

' + escapeHtml([item.lineagePersonName, item.documentTypeLabel, item.maskedIdentifier, item.description].filter(Boolean).join(' · ')) + '

' + resources + (item.contentProtected && !item.contentUnlocked ? '' : '') + (item.canEdit ? '' : '') + (item.canDelete ? '' : '') + '
'; }).join(''); } async function init() { var page = root.document && root.document.querySelector('[data-person-document-page]'); var api = root.GenealogyApi && root.GenealogyApi.defaultClient; var genealogyId = root.ProfileUI && root.ProfileUI.getGenealogyId ? root.ProfileUI.getGenealogyId() : ''; var form = page && page.querySelector('[data-document-form]'); var list = page && page.querySelector('[data-document-list]'); var status = page && page.querySelector('[data-document-status]'); var personSelect = page && page.querySelector('[data-document-person]'); var typeSelect = page && page.querySelector('[data-document-type]'); var ossInput = page && page.querySelector('[data-document-oss-id]'); var usageSelect = page && page.querySelector('[data-document-usage]'); var documents = []; var accessTokens = {}; var pending = false; if (!page) return; if (!api || !api.getToken || !api.getToken()) { root.NavigationUtil.open('login.html'); return; } if (!genealogyId) { root.ProfileUI.setApiState(status, 'error', '缺少家谱上下文,请从“我的家谱”重新进入。'); return; } function setStatus(type, message) { if (type) root.ProfileUI.setApiState(status, type, message); else status.textContent = message || ''; } async function loadDocuments() { documents = (await api.personDocuments(genealogyId)).map(normalizeDocument).filter(Boolean); list.innerHTML = renderDocuments(documents); } try { var initial = await Promise.all([ api.lineagePersonOptions(genealogyId), api.businessDictionary('gen_person_document_type'), api.personDocuments(genealogyId) ]); personSelect.innerHTML = '' + (Array.isArray(initial[0]) ? initial[0] : []).map(function (item) { var id = normalizeId(item.personId || item.lineagePersonId); var name = String(item.displayName || item.personName || item.name || '').trim(); return id && name ? '' : ''; }).join(''); typeSelect.innerHTML = '' + (Array.isArray(initial[1]) ? initial[1] : []).filter(function (item) { return item && item.enabled === true && String(item.value || '').trim(); }).map(function (item) { return ''; }).join(''); documents = (Array.isArray(initial[2]) ? initial[2] : []).map(normalizeDocument).filter(Boolean); list.innerHTML = renderDocuments(documents); setStatus('', '重要证件档案已加载'); } catch (error) { setStatus('error', error.message || '重要证件档案读取失败'); return; } form.addEventListener('submit', async function (event) { var body; var validation; var created; var ossId; event.preventDefault(); if (pending) return; body = buildDocumentBody({ lineagePersonId: personSelect.value, documentType: typeSelect.value, documentTitle: form.elements.documentTitle.value, maskedIdentifier: form.elements.maskedIdentifier.value, description: form.elements.description.value }); validation = validateDocumentBody(body); if (validation) return setStatus('error', validation); ossId = normalizeId(ossInput.value); if (!ossId) return setStatus('error', '请先上传证件文件'); pending = true; setStatus('loading', '正在保存证件档案…'); try { created = normalizeDocument(await api.createPersonDocument(genealogyId, body)); if (!created) throw new Error('创建响应缺少有效档案信息'); await api.addPersonDocumentResource(genealogyId, created.documentId, { ossId: ossId, usageType: usageSelect.value }); form.reset(); ossInput.value = ''; await loadDocuments(); setStatus('', '证件档案已保存'); } catch (error) { setStatus('error', error.message || '证件档案保存失败'); } finally { pending = false; } }); list.addEventListener('click', async function (event) { var resourceButton = event.target.closest('[data-document-resource]'); var unlockButton = event.target.closest('[data-document-unlock]'); var protectButton = event.target.closest('[data-document-protect]'); var deleteButton = event.target.closest('[data-document-delete]'); var documentId; var password; var documentItem; var accessWindow; if (pending) return; try { if (resourceButton) { accessWindow = root.open('about:blank', '_blank', 'noopener'); documentId = resourceButton.getAttribute('data-document-id'); var access = await api.personDocumentResourceAccess( genealogyId, documentId, resourceButton.getAttribute('data-document-resource'), accessTokens[documentId] ); if (!access || !access.accessUrl) throw new Error('文件访问响应缺少地址'); if (accessWindow) accessWindow.location.replace(access.accessUrl); else root.NavigationUtil.open(access.accessUrl); return; } if (unlockButton) { documentId = unlockButton.getAttribute('data-document-unlock'); password = await promptAction('请输入档案访问密码'); if (!password) return; var grant = await api.unlockPersonDocument(genealogyId, documentId, password); if (!grant || !grant.accessToken) throw new Error('解锁响应缺少访问令牌'); accessTokens[documentId] = grant.accessToken; await loadDocuments(); setStatus('', '档案已临时解锁'); return; } if (protectButton) { documentId = protectButton.getAttribute('data-document-protect'); documentItem = documents.find(function (item) { return item.documentId === documentId; }); if (!documentItem) return; if (documentItem.contentProtected) { if (!await confirmAction('确认取消此档案的密码保护吗?')) return; await api.unprotectPersonDocument(genealogyId, documentId); } else { password = await promptAction('设置档案访问密码'); if (!password) return; await api.protectPersonDocument(genealogyId, documentId, password); } await loadDocuments(); setStatus('', '密码保护设置已更新'); return; } if (deleteButton) { documentId = deleteButton.getAttribute('data-document-delete'); if (!await confirmAction('确认删除这份证件档案吗?')) return; await api.deletePersonDocument(genealogyId, documentId); await loadDocuments(); setStatus('', '证件档案已删除'); } } catch (error) { if (accessWindow) accessWindow.close(); setStatus('error', error.message || '操作失败,请稍后重试'); } }); } return { normalizeDocument: normalizeDocument, buildDocumentBody: buildDocumentBody, validateDocumentBody: validateDocumentBody, renderDocuments: renderDocuments, init: init }; });