- 删除 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 通过。
306 lines
10 KiB
JavaScript
306 lines
10 KiB
JavaScript
/**
|
|
* AKSRT Post Share
|
|
*
|
|
* Handles share dropdowns, social share targets, copy link,
|
|
* and WeChat bridge handoff with QR fallback.
|
|
*
|
|
* @package AKSRT
|
|
*/
|
|
|
|
(function () {
|
|
'use strict';
|
|
|
|
function getMetaContent(selectors) {
|
|
for (var i = 0; i < selectors.length; i += 1) {
|
|
var node = document.querySelector(selectors[i]);
|
|
var content = node ? node.getAttribute('content') : '';
|
|
if (content) return content;
|
|
}
|
|
return '';
|
|
}
|
|
|
|
function getPlatform(node) {
|
|
if (!node) return '';
|
|
return node.getAttribute('data-share-platform') || node.getAttribute('data-platform') || '';
|
|
}
|
|
|
|
function resolvePayload(node) {
|
|
// Unified payload via the shared builder; fall back to local resolution
|
|
// only if the builder script is unavailable.
|
|
if (window.AksrtShareData && typeof window.AksrtShareData.resolve === 'function') {
|
|
return window.AksrtShareData.resolve(node);
|
|
}
|
|
|
|
var dropdown = document.getElementById('share-dropdown');
|
|
var source = node && typeof node.closest === 'function'
|
|
? node.closest('[data-share-url], [data-share-title], [data-share-desc], [data-share-image]')
|
|
: null;
|
|
var context = source || dropdown;
|
|
|
|
function readAttr(name) {
|
|
return (node && node.getAttribute(name)) || (context && context.getAttribute(name)) || '';
|
|
}
|
|
|
|
return {
|
|
title: readAttr('data-share-title') || document.title,
|
|
url: readAttr('data-share-url') || window.location.href,
|
|
desc: readAttr('data-share-desc') || getMetaContent(['meta[property="og:description"]', 'meta[name="description"]']),
|
|
text: readAttr('data-share-text') || '',
|
|
image: readAttr('data-share-image') || getMetaContent(['meta[property="og:image"]']),
|
|
qrcode: readAttr('data-share-qrcode') || ''
|
|
};
|
|
}
|
|
|
|
function openWindow(url) {
|
|
if (!url) return;
|
|
window.open(url, '_blank', 'width=640,height=560,scrollbars=yes,resizable=yes');
|
|
}
|
|
|
|
function buildShareUrl(platform, payload) {
|
|
switch (platform) {
|
|
case 'weibo':
|
|
return 'https://service.weibo.com/share/share.php?url=' + encodeURIComponent(payload.url) + '&title=' + encodeURIComponent(payload.title + (payload.text ? ' ' + payload.text : ''));
|
|
case 'qq':
|
|
return 'https://connect.qq.com/widget/shareqq/index.html?url=' + encodeURIComponent(payload.url) + '&title=' + encodeURIComponent(payload.title) + '&desc=' + encodeURIComponent(payload.desc || payload.text || '');
|
|
case 'twitter':
|
|
return 'https://x.com/intent/tweet?url=' + encodeURIComponent(payload.url) + '&text=' + encodeURIComponent(payload.title);
|
|
case 'telegram':
|
|
return 'https://t.me/share/url?url=' + encodeURIComponent(payload.url) + '&text=' + encodeURIComponent(payload.title);
|
|
case 'linkedin':
|
|
return 'https://www.linkedin.com/sharing/share-offsite/?url=' + encodeURIComponent(payload.url);
|
|
default:
|
|
return '';
|
|
}
|
|
}
|
|
|
|
function fallbackCopy(text) {
|
|
var textarea = document.createElement('textarea');
|
|
textarea.value = text;
|
|
textarea.style.cssText = 'position:fixed;left:-9999px;top:-9999px;opacity:0;';
|
|
textarea.setAttribute('readonly', '');
|
|
document.body.appendChild(textarea);
|
|
try {
|
|
textarea.select();
|
|
textarea.setSelectionRange(0, textarea.value.length);
|
|
if (!document.execCommand('copy')) {
|
|
throw new Error('copy command failed');
|
|
}
|
|
} finally {
|
|
document.body.removeChild(textarea);
|
|
}
|
|
}
|
|
|
|
function copyLink(text) {
|
|
if (navigator.clipboard && navigator.clipboard.writeText) {
|
|
return navigator.clipboard.writeText(text).catch(function () {
|
|
fallbackCopy(text);
|
|
});
|
|
}
|
|
|
|
try {
|
|
fallbackCopy(text);
|
|
return Promise.resolve();
|
|
} catch (error) {
|
|
return Promise.reject(error);
|
|
}
|
|
}
|
|
|
|
function initShareDropdown() {
|
|
var dropdown = document.getElementById('share-dropdown');
|
|
var triggers = Array.prototype.slice.call(document.querySelectorAll('#action-share-trigger, .action-share[data-type="share"], .footer-tabbar .action-share')).filter(function (el, idx, arr) { return arr.indexOf(el) === idx; });
|
|
var trigger = triggers[0] || null;
|
|
if (!trigger || !dropdown || dropdown.dataset.aksrtShareBound === '1') return;
|
|
|
|
dropdown.dataset.aksrtShareBound = '1';
|
|
|
|
var qrBox = document.getElementById('share-qrcode-box');
|
|
var qrImage = document.getElementById('share-qrcode-image');
|
|
|
|
function closeDropdown() {
|
|
dropdown.setAttribute('aria-hidden', 'true');
|
|
triggers.forEach(function (t) { t.setAttribute('aria-expanded', 'false'); });
|
|
document.body.classList.remove('aksrt-share-sheet-open');
|
|
if (window.AksrtShare && typeof window.AksrtShare.hideQrFallback === 'function') {
|
|
window.AksrtShare.hideQrFallback(qrBox);
|
|
} else if (qrBox) {
|
|
qrBox.classList.remove('is-visible');
|
|
qrBox.setAttribute('aria-hidden', 'true');
|
|
}
|
|
}
|
|
|
|
function toggleDropdown() {
|
|
var isOpen = dropdown.getAttribute('aria-hidden') === 'false';
|
|
if (isOpen) {
|
|
closeDropdown();
|
|
return;
|
|
}
|
|
|
|
dropdown.setAttribute('aria-hidden', 'false');
|
|
triggers.forEach(function (t) { t.setAttribute('aria-expanded', 'true'); });
|
|
if (window.matchMedia && window.matchMedia('(max-width: 767px)').matches) {
|
|
document.body.classList.add('aksrt-share-sheet-open');
|
|
}
|
|
}
|
|
|
|
trigger.addEventListener('click', function (event) {
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
toggleDropdown();
|
|
});
|
|
|
|
triggers.slice(1).forEach(function (extraTrigger) {
|
|
extraTrigger.addEventListener('click', function (event) {
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
// Reuse primary trigger click semantics by synthetic toggle
|
|
trigger.click();
|
|
});
|
|
});
|
|
|
|
|
|
document.addEventListener('click', function (event) {
|
|
if (!trigger.contains(event.target) && !dropdown.contains(event.target)) {
|
|
closeDropdown();
|
|
}
|
|
});
|
|
|
|
document.addEventListener('keydown', function (event) {
|
|
if (event.key === 'Escape') {
|
|
closeDropdown();
|
|
}
|
|
});
|
|
|
|
dropdown.addEventListener('click', function (event) {
|
|
var item = event.target.closest('.share-item');
|
|
if (!item) return;
|
|
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
|
|
handleShareAction(item, {
|
|
qrBox: qrBox,
|
|
qrImage: qrImage,
|
|
closeDropdown: closeDropdown,
|
|
withinDropdown: true
|
|
});
|
|
});
|
|
}
|
|
|
|
function handleWeixinShare(node, payload, options) {
|
|
options = options || {};
|
|
|
|
var share = window.AksrtShare;
|
|
if (!share || typeof share.openWeixinShare !== 'function') {
|
|
notyf('微信分享模块未加载', 'danger');
|
|
return Promise.resolve({ mode: 'error' });
|
|
}
|
|
|
|
if (
|
|
options.qrBox &&
|
|
options.qrBox.classList.contains('is-visible') &&
|
|
(!share.isWeixinEnv || !share.isWeixinEnv())
|
|
) {
|
|
share.hideQrFallback(options.qrBox);
|
|
return Promise.resolve({ mode: 'closed' });
|
|
}
|
|
|
|
return share.openWeixinShare({
|
|
title: payload.title,
|
|
url: payload.url,
|
|
desc: payload.desc || payload.text || '',
|
|
image: payload.image,
|
|
qrBox: options.qrBox || null,
|
|
qrImage: options.qrImage || null
|
|
}).then(function (result) {
|
|
if (result && result.message) {
|
|
notyf(result.message, result.mode === 'error' ? 'danger' : (result.mode === 'bridge' ? 'success' : 'info'));
|
|
}
|
|
return result;
|
|
});
|
|
}
|
|
|
|
function handleShareAction(node, options) {
|
|
var platform = getPlatform(node);
|
|
if (!platform) return Promise.resolve({ mode: 'noop' });
|
|
|
|
var payload = resolvePayload(node);
|
|
if (!payload.url) return Promise.resolve({ mode: 'noop' });
|
|
|
|
if (platform === 'copy') {
|
|
return copyLink(payload.url).then(function () {
|
|
notyf('链接已复制', 'success');
|
|
if (options && typeof options.closeDropdown === 'function') {
|
|
options.closeDropdown();
|
|
}
|
|
return { mode: 'copy' };
|
|
}).catch(function () {
|
|
notyf('复制失败,请手动复制链接', 'danger');
|
|
return { mode: 'error' };
|
|
});
|
|
}
|
|
|
|
if (platform === 'wechat') {
|
|
return handleWeixinShare(node, payload, options).then(function (result) {
|
|
if (result && result.mode !== 'qr' && result.mode !== 'error' && options && typeof options.closeDropdown === 'function') {
|
|
options.closeDropdown();
|
|
}
|
|
return result;
|
|
});
|
|
}
|
|
|
|
if (platform === 'poster') {
|
|
if (window.AksrtPosterShare && typeof window.AksrtPosterShare.open === 'function') {
|
|
window.AksrtPosterShare.open(payload);
|
|
if (options && typeof options.closeDropdown === 'function') options.closeDropdown();
|
|
return Promise.resolve({ mode: 'poster' });
|
|
}
|
|
notyf('海报模块未加载', 'danger');
|
|
return Promise.resolve({ mode: 'error' });
|
|
}
|
|
|
|
var shareUrl = buildShareUrl(platform, payload);
|
|
if (!shareUrl) {
|
|
return Promise.resolve({ mode: 'noop' });
|
|
}
|
|
|
|
openWindow(shareUrl);
|
|
if (options && typeof options.closeDropdown === 'function') {
|
|
options.closeDropdown();
|
|
}
|
|
|
|
return Promise.resolve({ mode: 'window' });
|
|
}
|
|
|
|
function bindGenericShareButtons() {
|
|
document.addEventListener('click', function (event) {
|
|
var node = event.target.closest('[data-share-platform]');
|
|
if (!node || node.closest('#share-dropdown')) return;
|
|
|
|
event.preventDefault();
|
|
handleShareAction(node, {});
|
|
});
|
|
|
|
document.addEventListener('click', function (event) {
|
|
var node = event.target.closest('[data-share-copy]');
|
|
if (!node) return;
|
|
|
|
event.preventDefault();
|
|
var url = node.getAttribute('data-share-url') || window.location.href;
|
|
copyLink(url).then(function () {
|
|
notyf('链接已复制', 'success');
|
|
}).catch(function () {
|
|
notyf('复制失败,请手动复制链接', 'danger');
|
|
});
|
|
});
|
|
}
|
|
|
|
function init() {
|
|
if (document.documentElement.dataset.aksrtPostShareInitialized === '1') return;
|
|
document.documentElement.dataset.aksrtPostShareInitialized = '1';
|
|
initShareDropdown();
|
|
bindGenericShareButtons();
|
|
}
|
|
|
|
jQuery(document).off('auto_fun.aksrt-post-share').on('auto_fun.aksrt-post-share', function () { init(document); });
|
|
})();
|