- 删除 AksrtFrontend registry/rehydrate 双路架构及 build/public.js 拼包入口,
前台唯一初始路径为 PHP 本地栈(jQuery 1.9.1 → Bootstrap 3.4.1)
→ loader_js(_win/aksrtData 唯一注入)→ tbquire(['main']) → runtime/main.min.js
- window.auto_fun = debounce(z_auto_fun, 100) 为唯一重扫入口;所有模块改为
执行一次 + off/on('auto_fun.aksrt-*') 命名空间重扫,data/class 标记幂等
- 局部更新协议统一:HTML 注入 → post_ajax.ed → auto_fun();
远程 modal → loaded.bs.modal → auto_fun();JSON 成功 → zib_ajax.success
- 灯箱恢复 Miniimgbox/imgbox 唯一 owner(imgbox-container、a[data-imgbox]、
imgbox_data),删除 AksrtLightbox/data-aksrt-lightbox 第二实现及 CSS/overlay,
_win.imgbox* 重新接上 post-display 设置
- 死代码清理:runtime 下 11 组被自有实现替代的旧模块副本、无消费 vendored 库、
顶层 grade.min.js、revenue.js、无调用方的 aksrt_get_win_runtime_config(),
以及 loader 中 16 条死 mapping
- PHP 入队改为本地栈 + loader_js,routed/widget/submit 依赖统一换绑;
用户卡片发布按钮恢复 nav_user_newposts_btn 设置门控
- 测试对齐:新增 frontend-lifecycle-contract,重写 navigation/lazyload/toast/
auth-source/comment/page-display/post-visual 等断言为目标架构契约
验证:node --test widget-system+navigation 223 通过 0 失败;
构建脚本重建 main/imgbox min 与 CSS bundles;改动 PHP php -l、JS node --check
全部通过;git diff --check 干净;credits 重入 harness 通过。
229 lines
8.4 KiB
JavaScript
229 lines
8.4 KiB
JavaScript
/**
|
|
* AKSRT message center DOM navigation.
|
|
*
|
|
* @package AKSRT
|
|
*/
|
|
(function () {
|
|
'use strict';
|
|
|
|
var root = document.querySelector('[data-message-center]');
|
|
if (!root) return;
|
|
|
|
var nonce = typeof aksrtData !== 'undefined' ? aksrtData.nonce : '';
|
|
var ajaxUrl = typeof aksrtData !== 'undefined' ? aksrtData.ajaxUrl : '/wp-admin/admin-ajax.php';
|
|
var content = root.querySelector('[data-message-content]');
|
|
var nav = root.querySelector('[data-message-nav]');
|
|
var state = {
|
|
view: root.dataset.view || 'unread',
|
|
page: 1,
|
|
detail: 0,
|
|
paginateType: root.dataset.paginateType || 'ajax_lists',
|
|
};
|
|
var pollInterval = 60000;
|
|
|
|
function post(action, data) {
|
|
var body = new URLSearchParams({ action: action, nonce: nonce });
|
|
Object.keys(data || {}).forEach(function (key) {
|
|
var value = data[key];
|
|
if (Array.isArray(value)) {
|
|
value.forEach(function (item) { body.append(key + '[]', item); });
|
|
} else {
|
|
body.append(key, value);
|
|
}
|
|
});
|
|
return fetch(ajaxUrl, { method: 'POST', body: body, credentials: 'same-origin' })
|
|
.then(function (response) { return response.json(); });
|
|
}
|
|
|
|
function routeFor(view) {
|
|
var link = nav.querySelector('[data-message-view="' + view + '"]');
|
|
return link ? link.href : window.location.href;
|
|
}
|
|
|
|
function updateHeaderBadge(unread) {
|
|
var count = Math.max(0, Number(unread) || 0);
|
|
var headerBadge = document.querySelector('.aksrt-notification-badge');
|
|
var avatarDot = document.querySelector('.nav-user__dot');
|
|
if (headerBadge) {
|
|
headerBadge.textContent = String(count);
|
|
headerBadge.style.display = count > 0 ? '' : 'none';
|
|
}
|
|
if (avatarDot) avatarDot.style.display = count > 0 ? '' : 'none';
|
|
}
|
|
|
|
function renderError(message) {
|
|
content.innerHTML = '<div class="messages-empty"><span class="messages-empty__icon"><i class="fa fas fa-exclamation-circle"></i></span><p class="messages-empty__text"></p></div>';
|
|
content.querySelector('.messages-empty__text').textContent = message || '加载失败,请稍后重试';
|
|
}
|
|
|
|
function appendMessagePage(markup) {
|
|
var incoming = document.createElement('div');
|
|
incoming.innerHTML = markup;
|
|
var currentList = content.querySelector('.messages-list');
|
|
var incomingList = incoming.querySelector('.messages-list');
|
|
if (!currentList || !incomingList) {
|
|
content.innerHTML = markup;
|
|
return null;
|
|
}
|
|
|
|
var existingIds = new Set();
|
|
currentList.querySelectorAll('[data-notification-id]').forEach(function (item) {
|
|
existingIds.add(item.dataset.notificationId);
|
|
});
|
|
var firstAdded = null;
|
|
incomingList.querySelectorAll('.message-item').forEach(function (item) {
|
|
if (existingIds.has(item.dataset.notificationId)) return;
|
|
if (!firstAdded) firstAdded = item;
|
|
currentList.appendChild(item);
|
|
});
|
|
|
|
var currentPagination = content.querySelector('.messages-pagination');
|
|
var incomingPagination = incoming.querySelector('.messages-pagination');
|
|
if (currentPagination) currentPagination.remove();
|
|
if (incomingPagination) content.appendChild(incomingPagination);
|
|
return firstAdded;
|
|
}
|
|
|
|
function load(next, options) {
|
|
var requested = {
|
|
view: next.view || state.view,
|
|
page: next.page || 1,
|
|
detail: next.detail || 0,
|
|
};
|
|
var settings = options || {};
|
|
root.classList.add('is-loading');
|
|
content.setAttribute('aria-busy', 'true');
|
|
|
|
return post('aksrt_load_message_center', {
|
|
view: requested.view,
|
|
page: requested.page,
|
|
notification_id: requested.detail,
|
|
}).then(function (result) {
|
|
if (!result.success || !result.data) {
|
|
throw new Error(result.data && result.data.message ? result.data.message : '加载失败,请稍后重试');
|
|
}
|
|
requested.paginateType = result.data.paginate_type || state.paginateType;
|
|
state = requested;
|
|
root.dataset.view = state.view;
|
|
root.dataset.paginateType = state.paginateType;
|
|
nav.innerHTML = result.data.nav;
|
|
var firstAdded = null;
|
|
if (settings.append && state.paginateType === 'ajax_lists') {
|
|
firstAdded = appendMessagePage(result.data.content);
|
|
} else {
|
|
content.innerHTML = result.data.content;
|
|
}
|
|
updateHeaderBadge(result.data.unread);
|
|
|
|
if (settings.history === 'push') {
|
|
window.history.pushState(state, '', routeFor(state.view));
|
|
} else if (settings.history === 'replace') {
|
|
window.history.replaceState(state, '', routeFor(state.view));
|
|
}
|
|
if (firstAdded) {
|
|
firstAdded.setAttribute('tabindex', '-1');
|
|
firstAdded.focus({ preventScroll: true });
|
|
} else {
|
|
content.focus({ preventScroll: true });
|
|
}
|
|
}).catch(function (error) {
|
|
renderError(error.message);
|
|
}).finally(function () {
|
|
root.classList.remove('is-loading');
|
|
content.removeAttribute('aria-busy');
|
|
});
|
|
}
|
|
|
|
function reloadList() {
|
|
return load({ view: state.view, page: state.page, detail: 0 });
|
|
}
|
|
|
|
document.addEventListener('click', function (event) {
|
|
var tab = event.target.closest('[data-message-view]');
|
|
if (!tab || !root.contains(tab) || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
|
|
event.preventDefault();
|
|
load({ view: tab.dataset.messageView, page: 1, detail: 0 }, { history: 'push' });
|
|
});
|
|
|
|
document.addEventListener('click', function (event) {
|
|
var button = event.target.closest('.js-msg-detail');
|
|
if (!button || !root.contains(button)) return;
|
|
event.preventDefault();
|
|
load({ view: button.dataset.view || state.view, page: state.page, detail: button.dataset.id });
|
|
});
|
|
|
|
document.addEventListener('click', function (event) {
|
|
var button = event.target.closest('[data-message-back]');
|
|
if (!button || !root.contains(button)) return;
|
|
load({ view: button.dataset.view || state.view, page: state.page, detail: 0 });
|
|
});
|
|
|
|
document.addEventListener('click', function (event) {
|
|
var button = event.target.closest('[data-message-page]');
|
|
if (!button || !root.contains(button)) return;
|
|
event.preventDefault();
|
|
load({ view: state.view, page: button.dataset.messagePage, detail: 0 });
|
|
});
|
|
|
|
document.addEventListener('click', function (event) {
|
|
var button = event.target.closest('[data-message-next-page]');
|
|
if (!button || !root.contains(button)) return;
|
|
event.preventDefault();
|
|
load(
|
|
{ view: state.view, page: button.dataset.messageNextPage, detail: 0 },
|
|
{ append: true }
|
|
);
|
|
});
|
|
|
|
document.addEventListener('click', function (event) {
|
|
var button = event.target.closest('.js-msg-mark-read');
|
|
if (!button || !root.contains(button)) return;
|
|
post('aksrt_mark_notification_read', { notification_id: button.dataset.id }).then(function (result) {
|
|
if (result.success) reloadList();
|
|
});
|
|
});
|
|
|
|
document.addEventListener('click', function (event) {
|
|
var button = event.target.closest('.js-msg-delete');
|
|
if (!button || !root.contains(button)) return;
|
|
post('aksrt_delete_notification', { notification_id: button.dataset.id }).then(function (result) {
|
|
if (result.success) reloadList();
|
|
});
|
|
});
|
|
|
|
document.addEventListener('click', function (event) {
|
|
var button = event.target.closest('.js-msg-mark-all-read');
|
|
if (!button || !root.contains(button)) return;
|
|
post('aksrt_mark_notification_read', { mark_all: '1' }).then(function (result) {
|
|
if (result.success) reloadList();
|
|
});
|
|
});
|
|
|
|
document.addEventListener('click', function (event) {
|
|
var button = event.target.closest('.js-msg-clear-read');
|
|
if (!button || !root.contains(button)) return;
|
|
var ids = [];
|
|
root.querySelectorAll('.message-item:not(.is-unread)[data-notification-id]').forEach(function (item) {
|
|
if (/^\d+$/.test(item.dataset.notificationId)) ids.push(item.dataset.notificationId);
|
|
});
|
|
if (!ids.length) return;
|
|
post('aksrt_delete_notifications', { notification_ids: ids }).then(function (result) {
|
|
if (result.success) reloadList();
|
|
});
|
|
});
|
|
|
|
window.addEventListener('popstate', function (event) {
|
|
var previous = event.state;
|
|
if (previous && previous.view) {
|
|
load(previous);
|
|
}
|
|
});
|
|
|
|
window.history.replaceState(state, '', routeFor(state.view));
|
|
window.setInterval(function () {
|
|
post('aksrt_check_new_notifications', {}).then(function (result) {
|
|
if (result.success && result.data) updateHeaderBadge(result.data.unread);
|
|
}).catch(function () {});
|
|
}, pollInterval);
|
|
})();
|