Files
jiapu/public/js/profile-common.js
T
2026-07-31 11:31:26 +08:00

481 lines
16 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
(function (window, $) {
'use strict';
if (!$) return;
var layuiReady = false;
var layerApi = null;
var genealogyContextStorageKey = 'genealogy_current_context_v1';
var mobileMenuId = 'profile-mobile-menu';
function getSessionStorage() {
try {
return window.sessionStorage;
} catch (error) {
return null;
}
}
function normalizeGenealogyName(value) {
var name = String(value === undefined || value === null ? '' : value).trim();
return name && name.length <= 80 ? name : '';
}
function getStoredGenealogyContext() {
var storage = getSessionStorage();
var stored;
var context;
var genealogyId;
var genealogyName;
if (!storage) return null;
try {
stored = storage.getItem(genealogyContextStorageKey);
context = stored ? JSON.parse(stored) : null;
} catch (error) {
return null;
}
genealogyId = normalizeGenealogyId(context && context.genealogyId);
genealogyName = normalizeGenealogyName(context && context.genealogyName);
return genealogyId && genealogyName ? {
genealogyId: genealogyId,
genealogyName: genealogyName
} : null;
}
function setCurrentGenealogyContext(genealogyId, genealogyName) {
var storage = getSessionStorage();
var context = {
genealogyId: normalizeGenealogyId(genealogyId),
genealogyName: normalizeGenealogyName(genealogyName)
};
if (!context.genealogyId || !context.genealogyName) return null;
if (storage) {
try {
storage.setItem(genealogyContextStorageKey, JSON.stringify(context));
} catch (error) {}
}
renderCurrentGenealogyContext();
return context;
}
function clearCurrentGenealogyContext() {
var storage = getSessionStorage();
if (!storage) return;
try {
storage.removeItem(genealogyContextStorageKey);
} catch (error) {}
}
function getCurrentGenealogyContext() {
var genealogyId = getGenealogyId();
var context = getStoredGenealogyContext();
return context && context.genealogyId === genealogyId ? context : null;
}
function openLegacyLogout() {
var $modal = $('#logoutModal');
if (!$modal.length) return;
$modal.addClass('show').attr('aria-hidden', 'false');
$('body').addClass('logout-modal-open');
}
function closeLegacyLogout() {
var $modal = $('#logoutModal');
$modal.removeClass('show').attr('aria-hidden', 'true');
$('body').removeClass('logout-modal-open');
}
function openConfirm(options) {
var settings = $.extend({
title: '确认操作',
content: '确定继续吗?',
confirmText: '确定',
cancelText: '取消',
onConfirm: $.noop
}, options || {});
if (layerApi) {
layerApi.confirm(settings.content, {
title: settings.title,
btn: [settings.confirmText, settings.cancelText],
skin: 'profile-layer-confirm'
}, function (index) {
settings.onConfirm();
layerApi.close(index);
});
return;
}
if (window.confirm(settings.content)) settings.onConfirm();
}
function initLayui() {
if (!window.layui || layuiReady) return;
layuiReady = true;
window.layui.use(['layer', 'form'], function () {
layerApi = window.layui.layer;
if (window.layui.form) window.layui.form.render();
});
}
function performLogout(targetUrl) {
var api = window.GenealogyApi && window.GenealogyApi.defaultClient;
var redirect = function () {
clearCurrentGenealogyContext();
window.location.href = targetUrl || 'index.html';
};
if (!api || !api.logout) {
redirect();
return;
}
api.logout().catch(function () {}).then(redirect);
}
function bindLogout() {
$(document).on('click', '[data-logout-open]', function (event) {
var targetUrl = $(this).attr('data-logout-url') || 'index.html';
event.preventDefault();
if (!layerApi) {
openLegacyLogout();
return;
}
openConfirm({
title: '退出登录',
content: '确认退出当前账号吗?退出后需要重新登录才能继续管理家谱。',
confirmText: '确认退出',
onConfirm: function () {
performLogout(targetUrl);
}
});
});
$(document).on('click', '[data-logout-confirm]', function (event) {
event.preventDefault();
closeLegacyLogout();
performLogout($(this).attr('href') || 'index.html');
});
$(document).on('click', '[data-logout-close]', function () {
closeLegacyLogout();
});
$(document).on('keydown', function (event) {
if (event.key === 'Escape') closeLegacyLogout();
});
}
function bindConfirmActions() {
$(document).on('click', '[data-layer-confirm]', function (event) {
var $item = $(this);
var href = $item.attr('href');
event.preventDefault();
openConfirm({
title: $item.attr('data-confirm-title') || '确认操作',
content: $item.attr('data-layer-confirm') || '确定继续吗?',
confirmText: $item.attr('data-confirm-text') || '确定',
onConfirm: function () {
if (href && href !== '#') window.location.href = href;
}
});
});
}
function normalizeGenealogyId(value) {
var text = String(value === undefined || value === null ? '' : value).trim();
return /^[1-9][0-9]*$/.test(text) ? text : '';
}
function getGenealogyId(search) {
var source = search === undefined ? (window.location && window.location.search) : search;
var params = new URLSearchParams(String(source || '').replace(/^\?/, ''));
return normalizeGenealogyId(params.get('genealogyId'));
}
function withGenealogyId(href, genealogyId) {
var value = String(href || '');
var hashIndex;
var hash = '';
var parts;
var params;
genealogyId = normalizeGenealogyId(genealogyId);
if (!genealogyId || !value || value.charAt(0) === '#' || /^(?:https?:|mailto:|tel:)/i.test(value)) return value;
hashIndex = value.indexOf('#');
if (hashIndex >= 0) {
hash = value.slice(hashIndex);
value = value.slice(0, hashIndex);
}
parts = value.split('?');
params = new URLSearchParams(parts[1] || '');
params.set('genealogyId', genealogyId);
return parts[0] + '?' + params.toString() + hash;
}
function getGenealogyEntryUrl(href) {
var value = String(href || '');
if (!value || value.charAt(0) === '#' || /^(?:https?:|mailto:|tel:)/i.test(value)) return value;
if (value.indexOf('profile-families.html') === 0) return value;
return 'profile-families.html?next=' + encodeURIComponent(value.split('?')[0]);
}
function syncGenealogyContextLinks() {
var genealogyId = getGenealogyId();
$('[data-genealogy-context-link]').each(function () {
var $link = $(this);
$link.attr('href', genealogyId ? withGenealogyId($link.attr('href'), genealogyId) : getGenealogyEntryUrl($link.attr('href')));
});
}
function renderCurrentGenealogyContext() {
var context = getCurrentGenealogyContext();
var name = context ? context.genealogyName : '正在识别家谱';
$('[data-current-genealogy-name]').text(name);
$('[data-current-genealogy-link]').attr('aria-label', context ?
'当前家谱:' + context.genealogyName + ',点击切换家谱' :
'当前家谱,点击切换家谱');
}
function refreshCurrentGenealogyContext() {
var genealogyId = getGenealogyId();
var api = window.GenealogyApi && window.GenealogyApi.defaultClient;
if (!genealogyId || getCurrentGenealogyContext() || !api || !api.genealogyDetail) return;
api.genealogyDetail(genealogyId).then(function (detail) {
var detailId = normalizeGenealogyId(detail && detail.genealogyId);
var detailName = normalizeGenealogyName(detail && detail.genealogyName);
if (detailId === genealogyId && detailName) {
setCurrentGenealogyContext(detailId, detailName);
}
}).catch(function () {
$('[data-current-genealogy-name]').text('当前家谱');
});
}
function initCurrentGenealogyContext() {
var genealogyId = getGenealogyId();
var $nav;
var $actions;
var $context;
if (!genealogyId) return;
$nav = $('.site-header .nav').first();
if (!$nav.length || $nav.find('[data-current-genealogy-link]').length) return;
$context = $('<a class="profile-current-genealogy" data-current-genealogy-link href="profile-families.html">' +
'<span>当前家谱</span><strong data-current-genealogy-name>正在识别家谱</strong></a>');
$actions = $nav.find('.nav-actions').first();
if ($actions.length) $context.insertBefore($actions);
else $nav.append($context);
renderCurrentGenealogyContext();
refreshCurrentGenealogyContext();
}
function setMobileMenuOpen(isOpen) {
var $menu = $('[data-profile-mobile-menu]').first();
var $toggle = $('[data-profile-mobile-menu-toggle]').first();
if (!$menu.length || !$toggle.length) return;
$menu.prop('hidden', !isOpen).toggleClass('is-open', !!isOpen).attr('aria-hidden', isOpen ? 'false' : 'true');
$toggle.attr('aria-expanded', isOpen ? 'true' : 'false');
}
function initMobileMenu() {
var $header = $('.site-header').first();
var $nav;
var currentPage;
if (!$header.length || $header.find('[data-profile-mobile-menu]').length) return;
$nav = $header.find('.nav').first();
if (!$nav.length) return;
$nav.append('<button class="profile-mobile-menu-toggle" type="button" data-profile-mobile-menu-toggle ' +
'aria-expanded="false" aria-controls="' + mobileMenuId + '">菜单</button>');
$header.append('<div class="profile-mobile-menu" id="' + mobileMenuId + '" data-profile-mobile-menu hidden aria-hidden="true">' +
'<div class="container profile-mobile-menu-inner">' +
'<a href="profile.html">个人中心</a>' +
'<a href="profile-families.html">我的家谱</a>' +
'<a href="profile-create-family.html">创建家谱</a>' +
'<a href="profile-family-home.html" data-genealogy-context-link>家谱主页</a>' +
'<a href="profile-content.html" data-genealogy-context-link>内容发布</a>' +
'<a href="profile-family-admin.html" data-genealogy-context-link>家族管理</a>' +
'<a href="profile-data.html">个人资料</a>' +
'<a href="profile-messages.html">消息中心</a>' +
'<a href="profile-services.html">帮助与服务</a>' +
'<button type="button" data-logout-open data-logout-url="index.html">退出登录</button>' +
'</div></div>');
currentPage = (window.location.pathname.split('/').pop() || 'profile.html').split('?')[0];
$header.find('[data-profile-mobile-menu] a').each(function () {
var $link = $(this);
var target = ($link.attr('href') || '').split('?')[0];
if (target === currentPage) $link.addClass('is-current').attr('aria-current', 'page');
});
}
function bindGenealogySelection() {
$(document).on('click', '[data-genealogy-id][data-genealogy-name]', function () {
setCurrentGenealogyContext($(this).attr('data-genealogy-id'), $(this).attr('data-genealogy-name'));
});
}
function bindMobileMenu() {
$(document).on('click', '[data-profile-mobile-menu-toggle]', function () {
setMobileMenuOpen($(this).attr('aria-expanded') !== 'true');
});
$(document).on('click', '[data-profile-mobile-menu] a, [data-profile-mobile-menu] button', function () {
setMobileMenuOpen(false);
});
$(document).on('click', function (event) {
if (!$(event.target).closest('.site-header').length) setMobileMenuOpen(false);
});
$(document).on('keydown', function (event) {
if (event.key === 'Escape') setMobileMenuOpen(false);
});
}
function updateDisplay($trigger, value) {
var target = $trigger.attr('data-update-target');
var $target = target ? $(target) : $trigger.closest('p').find('b').first();
var $title;
if (!value) return;
if ($target.length) {
$target.text(value);
return;
}
$title = $trigger.closest('.module-row').find('h3').first();
if ($title.length) {
$title.text($title.text().replace(/([:]).*$/, '$1' + value));
}
}
function bindPromptActions() {
$(document).on('click', '[data-layer-prompt]', function (event) {
var $item = $(this);
var title = $item.attr('data-prompt-title') || $item.text() || '填写内容';
var placeholder = $item.attr('data-layer-prompt') || '';
var formType = $item.attr('data-prompt-type') === 'textarea' ? 2 : 0;
event.preventDefault();
if (!layerApi) {
var fallbackValue = window.prompt(placeholder || title, '');
if (fallbackValue) updateDisplay($item, fallbackValue);
return;
}
layerApi.prompt({
title: title,
value: $item.attr('data-prompt-value') || '',
formType: formType,
maxlength: Number($item.attr('data-prompt-maxlength')) || 200
}, function (value, index) {
updateDisplay($item, value);
layerApi.close(index);
layerApi.msg('已更新');
});
});
}
function bindSelectActions() {
$(document).on('click', '[data-layer-select]', function (event) {
var $item = $(this);
var values = ($item.attr('data-layer-select') || '').split('|').filter(Boolean);
var title = $item.attr('data-select-title') || '请选择';
var html = '<div class="profile-popup-select">';
event.preventDefault();
if (!values.length) return;
$.each(values, function (_, value) {
html += '<button type="button" data-popup-value="' + value + '">' + value + '</button>';
});
html += '</div>';
if (!layerApi) {
updateDisplay($item, values[0]);
return;
}
layerApi.open({
title: title,
content: html,
area: ['360px', 'auto'],
skin: 'profile-layer-confirm',
success: function (layero, index) {
layero.find('[data-popup-value]').on('click', function () {
updateDisplay($item, $(this).attr('data-popup-value'));
layerApi.close(index);
layerApi.msg('已选择');
});
}
});
});
}
function bindMessageActions() {
$(document).on('click', '[data-layer-msg]', function (event) {
event.preventDefault();
if (layerApi) layerApi.msg($(this).attr('data-layer-msg'));
});
}
function bindSelectableCards() {
$(document).on('click', '[data-select-card]', function () {
var $card = $(this);
var group = $card.attr('data-select-card');
if (group) $('[data-select-card="' + group + '"]').removeClass('is-selected');
$card.addClass('is-selected');
});
}
$(function () {
initLayui();
bindLogout();
bindConfirmActions();
bindPromptActions();
bindSelectActions();
bindMessageActions();
bindSelectableCards();
bindGenealogySelection();
bindMobileMenu();
initCurrentGenealogyContext();
initMobileMenu();
syncGenealogyContextLinks();
});
window.ProfileUI = {
confirm: openConfirm,
closeLogout: closeLegacyLogout,
initLayui: initLayui,
getGenealogyId: getGenealogyId,
normalizeGenealogyId: normalizeGenealogyId,
withGenealogyId: withGenealogyId,
getGenealogyEntryUrl: getGenealogyEntryUrl,
getCurrentGenealogyContext: getCurrentGenealogyContext,
setCurrentGenealogyContext: setCurrentGenealogyContext,
clearCurrentGenealogyContext: clearCurrentGenealogyContext,
refreshCurrentGenealogyContext: refreshCurrentGenealogyContext,
syncGenealogyContextLinks: syncGenealogyContextLinks
};
})(window, window.jQuery || (window.layui && window.layui.$));