- 删除 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 通过。
203 lines
5.4 KiB
JavaScript
203 lines
5.4 KiB
JavaScript
/**
|
|
* AKSRT Page Edit — 前台编辑增强
|
|
*
|
|
* 提供前台编辑页面的增强功能:
|
|
* - 自动保存草稿
|
|
* - 标签建议
|
|
* - 快捷键支持
|
|
*
|
|
* @package AKSRT
|
|
*/
|
|
|
|
(function () {
|
|
'use strict';
|
|
|
|
var DRAFT_KEY_PREFIX = 'aksrt_draft_';
|
|
|
|
/**
|
|
* 初始化页面编辑增强
|
|
*
|
|
* @param {Object} options 配置项
|
|
*/
|
|
function PageEdit(options) {
|
|
this.options = Object.assign({
|
|
formSelector: 'form[data-aksrt-edit]',
|
|
titleSelector: 'input[name="title"], input[name="topic_title"]',
|
|
contentSelector: 'textarea[name="content"], textarea[name="topic_content"]',
|
|
tagsSelector: 'input[name="tags"], input[name="topic_tags"]',
|
|
autoSaveInterval: 30000, // 30秒
|
|
draftKey: '',
|
|
}, options || {});
|
|
|
|
this.form = document.querySelector(this.options.formSelector);
|
|
if (!this.form) return;
|
|
|
|
this.autoSaveTimer = null;
|
|
this.lastSavedContent = '';
|
|
this.init();
|
|
}
|
|
|
|
PageEdit.prototype.init = function () {
|
|
var self = this;
|
|
|
|
this.titleInput = this.form.querySelector(this.options.titleSelector);
|
|
this.contentTextarea = this.form.querySelector(this.options.contentSelector);
|
|
this.tagsInput = this.form.querySelector(this.options.tagsSelector);
|
|
|
|
// 自动保存草稿
|
|
this.initAutoSave();
|
|
|
|
// 快捷键
|
|
this.initShortcuts();
|
|
|
|
// 标签输入增强
|
|
this.initTagInput();
|
|
|
|
// 表单提交时清除草稿
|
|
this.form.addEventListener('submit', function () {
|
|
self.clearDraft();
|
|
});
|
|
|
|
// 页面离开提醒
|
|
window.addEventListener('beforeunload', function (e) {
|
|
if (self.hasUnsavedChanges()) {
|
|
e.preventDefault();
|
|
e.returnValue = '您有未保存的修改,确定要离开吗?';
|
|
}
|
|
});
|
|
};
|
|
|
|
PageEdit.prototype.initAutoSave = function () {
|
|
var self = this;
|
|
|
|
if (!this.options.draftKey) {
|
|
// 从页面 URL 生成 draft key
|
|
this.options.draftKey = DRAFT_KEY_PREFIX + (window.location.pathname.replace(/\//g, '_') || 'page');
|
|
}
|
|
|
|
// 恢复草稿
|
|
this.restoreDraft();
|
|
|
|
// 定时自动保存
|
|
if (this.options.autoSaveInterval > 0) {
|
|
this.autoSaveTimer = setInterval(function () {
|
|
self.saveDraft();
|
|
}, this.options.autoSaveInterval);
|
|
}
|
|
};
|
|
|
|
PageEdit.prototype.saveDraft = function () {
|
|
if (!this.form) return;
|
|
|
|
var data = {};
|
|
if (this.titleInput) data.title = this.titleInput.value;
|
|
if (this.contentTextarea) data.content = this.contentTextarea.value;
|
|
if (this.tagsInput) data.tags = this.tagsInput.value;
|
|
|
|
var content = JSON.stringify(data);
|
|
if (content === this.lastSavedContent) return;
|
|
|
|
try {
|
|
localStorage.setItem(this.options.draftKey, content);
|
|
this.lastSavedContent = content;
|
|
|
|
// 显示保存提示
|
|
var toast = document.getElementById('aksrt-draft-toast');
|
|
if (!toast) {
|
|
toast = document.createElement('div');
|
|
toast.id = 'aksrt-draft-toast';
|
|
toast.className = 'aksrt-page-edit__toast';
|
|
document.body.appendChild(toast);
|
|
}
|
|
toast.textContent = '草稿已自动保存';
|
|
toast.classList.add('aksrt-page-edit__toast--visible');
|
|
setTimeout(function () {
|
|
toast.classList.remove('aksrt-page-edit__toast--visible');
|
|
}, 2000);
|
|
} catch (e) {
|
|
console.error('[AKSRT PageEdit] 保存草稿失败:', e);
|
|
}
|
|
};
|
|
|
|
PageEdit.prototype.restoreDraft = function () {
|
|
try {
|
|
var saved = localStorage.getItem(this.options.draftKey);
|
|
if (!saved) return;
|
|
|
|
var data = JSON.parse(saved);
|
|
var hasContent = false;
|
|
|
|
if (this.titleInput && data.title && !this.titleInput.value) {
|
|
this.titleInput.value = data.title;
|
|
hasContent = true;
|
|
}
|
|
if (this.contentTextarea && data.content && !this.contentTextarea.value) {
|
|
this.contentTextarea.value = data.content;
|
|
hasContent = true;
|
|
}
|
|
if (this.tagsInput && data.tags && !this.tagsInput.value) {
|
|
this.tagsInput.value = data.tags;
|
|
hasContent = true;
|
|
}
|
|
|
|
if (hasContent) {
|
|
this.lastSavedContent = saved;
|
|
}
|
|
} catch (e) {
|
|
console.error('[AKSRT PageEdit] 恢复草稿失败:', e);
|
|
}
|
|
};
|
|
|
|
PageEdit.prototype.clearDraft = function () {
|
|
try {
|
|
localStorage.removeItem(this.options.draftKey);
|
|
} catch (e) {}
|
|
};
|
|
|
|
PageEdit.prototype.hasUnsavedChanges = function () {
|
|
if (!this.form) return false;
|
|
|
|
var data = {};
|
|
if (this.titleInput) data.title = this.titleInput.value;
|
|
if (this.contentTextarea) data.content = this.contentTextarea.value;
|
|
if (this.tagsInput) data.tags = this.tagsInput.value;
|
|
|
|
return JSON.stringify(data) !== this.lastSavedContent;
|
|
};
|
|
|
|
PageEdit.prototype.initShortcuts = function () {
|
|
var self = this;
|
|
|
|
this.form.addEventListener('keydown', function (e) {
|
|
// Ctrl+S / Cmd+S 保存草稿
|
|
if ((e.ctrlKey || e.metaKey) && e.key === 's') {
|
|
e.preventDefault();
|
|
self.saveDraft();
|
|
}
|
|
});
|
|
};
|
|
|
|
PageEdit.prototype.initTagInput = function () {
|
|
if (!this.tagsInput) return;
|
|
|
|
// 回车键添加标签
|
|
this.tagsInput.addEventListener('keydown', function (e) {
|
|
if (e.key === 'Enter') {
|
|
e.preventDefault();
|
|
}
|
|
});
|
|
};
|
|
|
|
// 自动初始化
|
|
function autoInit() {
|
|
var form = document.querySelector('form[data-aksrt-edit]');
|
|
if (form) {
|
|
new PageEdit();
|
|
}
|
|
}
|
|
|
|
jQuery(document).off('auto_fun.aksrt-page-edit').on('auto_fun.aksrt-page-edit', autoInit);
|
|
|
|
window.AksrtPageEdit = PageEdit;
|
|
})();
|