(function (root, factory) { // 反馈模块同时支持浏览器页面和 Node 测试。 if (typeof module === 'object' && module.exports) { module.exports = factory(root); return; } root.FeedbackPages = factory(root); if (root.document) { root.document.addEventListener('DOMContentLoaded', function () { root.FeedbackPages.init(); }); } })(typeof globalThis !== 'undefined' ? globalThis : window, function (root) { 'use strict'; var documentRef = root.document; function normalizeList(data) { // 兼容分页 rows、records、list 和直接数组。 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 buildFeedbackBody(values) { // 接口只接收类型、内容、联系方式;页面上的标题合并到内容前面。 var title = values.feedbackTitle ? '【' + values.feedbackTitle + '】' : ''; return { feedbackType: values.feedbackType || 'suggestion', feedbackContent: title + (values.feedbackContent || ''), contactInfo: values.contactInfo || '' }; } function buildFeedbackRow(item) { var type = pick(item, ['feedbackType', 'typeName'], '反馈'); var content = pick(item, ['feedbackContent', 'content'], '暂无描述'); var status = pick(item, ['status', 'statusName'], '已提交'); var time = pick(item, ['createTime', 'createDate', 'createdAt'], '时间待确认'); return '

' + type + '

' + status + ' · ' + time + ' · ' + content + '

查看
'; } function getApi() { return root.GenealogyApi && root.GenealogyApi.defaultClient; } function query(selector, rootNode) { return (rootNode || documentRef).querySelector(selector); } function queryAll(selector, rootNode) { return Array.prototype.slice.call((rootNode || documentRef).querySelectorAll(selector)); } function readForm(form) { // name 属性和反馈接口字段保持一致,减少页面文案变化带来的影响。 var values = {}; queryAll('input[name], textarea[name], select[name]', form).forEach(function (field) { values[field.name] = String(field.value || '').trim(); }); return values; } function setBusy(button, busy) { // 加载态只切换 class,具体样式在 CSS 中维护。 if (!button) return; button.classList.toggle('is-loading', busy); if ('disabled' in button) button.disabled = busy; button.setAttribute('aria-busy', busy ? 'true' : 'false'); } function showMessage(message) { if (root.layui && root.layui.layer) { root.layui.layer.msg(message); return; } root.alert(message); } function renderFeedbackList(items) { var container = query('[data-feedback-list]'); if (!container) return; if (!items.length) { container.innerHTML = '
暂无历史反馈
'; return; } container.innerHTML = items.map(buildFeedbackRow).join(''); } async function loadFeedbackList() { var api = getApi(); var container = query('[data-feedback-list]'); if (!api || !container) return; container.classList.add('is-loading'); try { renderFeedbackList(normalizeList(await api.feedbackList())); } catch (error) { showMessage(error.message || '历史反馈加载失败'); } finally { container.classList.remove('is-loading'); } } async function submitFeedback(form, button) { var api = getApi(); var values = readForm(form); if (!api) return; if (!values.feedbackContent) { showMessage('请填写反馈内容'); return; } setBusy(button, true); try { await api.submitFeedback(buildFeedbackBody(values)); form.reset(); showMessage('反馈已提交'); loadFeedbackList(); } catch (error) { showMessage(error.message || '反馈提交失败'); } finally { setBusy(button, false); } } function bindFeedbackForms() { queryAll('[data-feedback-form]').forEach(function (form) { form.addEventListener('submit', function (event) { event.preventDefault(); submitFeedback(form, query('[type="submit"]', form)); }); }); } function init() { if (!documentRef) return; bindFeedbackForms(); loadFeedbackList(); } return { normalizeList: normalizeList, buildFeedbackBody: buildFeedbackBody, buildFeedbackRow: buildFeedbackRow, init: init }; });