LLWiki正在建设中,欢迎加入我们!
MediaWiki:Gadget-contentBackup.js
跳转到导航
跳转到搜索
注意:在保存之后,您可能需要清除浏览器缓存才能看到所作出的变更的影响。
- Firefox或Safari:按住Shift的同时单击刷新,或按Ctrl-F5或Ctrl-R(Mac为⌘-R)
- Google Chrome:按Ctrl-Shift-R(Mac为⌘-Shift-R)
- Internet Explorer:按住Ctrl的同时单击刷新,或按Ctrl-F5
- Opera:前往菜单 → 设置(Mac为Opera → Preferences),然后隐私和安全 → 清除浏览数据 → 缓存的图片和文件。
//<nowiki> // 由ResourceLoader直接调用,不可使用ES6语法 /** * @Function: 点击“提交编辑、显示预览、显示更改”中任意一个按钮,或在编辑页面每隔一段时间自动备份当前的编辑。 备份会保存一段时间后自动清除。支持Wikiplus和代码编辑器。 * @Dependencies: ext.gadget.SettingsDialog, localforage * @Source: [[moegirl:User:东东君/js/contentBackup.js]] * @EditedBy: [[User:Bhsd]] */ "use strict"; /* global OO, wgULS, localforage */ // 默认只用于桌面版、备份保存12小时、每隔30分钟自动更新备份 mw.gadgets.contentBackup = $.extend({range: ['vector'], exp: 12, stay: 30}, mw.storage.getObject( 'gadget-contentBackup' ), mw.gadgets.contentBackup ); const action = mw.config.get( 'wgAction' ), isEditable = mw.config.get( 'wgIsProbablyEditable' ), skin = mw.config.get( 'skin' ), isWikiplus = action == 'view' && (mw.isModule('Wikiplus', true) || mw.isModule('mobile-Wikiplus', true)), settings = mw.gadgets.contentBackup; if (isEditable && settings.range.includes( skin ) && (['edit', 'submit'].includes(action) || isWikiplus)) { var codeEditor, // 实时更新的Ace Editor Session backup = '', // 因为localforage提取backup是个Promise,这里先初始化 expList = mw.storage.getObject( 'LLWiki-contentBackup-exp' ) || {}; // 单独存储备份过期时间,这是个Object const id = mw.config.get( 'wgArticleId' ).toString(), // 所有新建页面共用备份 btns = '#wpSaveWidget, #wpPreviewWidget, #wpDiffWidget, #wpTemplateSandboxPreview', // MW原生编辑页面 editor = '#wpTextbox1, #Wikiplus-Quickedit', // 部分编辑器需动态生成,所以这里只保存选择器 expArray = Object.entries( expList ), expired = mw.now() - settings.exp * 1000 * 3600, stay = settings.stay * 1000 * 60; // 通过设置改动stay时若立即生效会造成bug // 1. 设置本地化消息 mw.messages.set( wgULS({ 'gadget-cb-label': '编辑内容自动备份', 'gadget-cb-range': '使用范围', 'gadget-cb-d': '桌面版', 'gadget-cb-m': '手机版', 'gadget-cb-rhelp': '可用于代码编辑器和Wikiplus小工具。', 'gadget-cb-text': '还原备份', 'gadget-cb-exp': '备份有效期(小时)', 'gadget-cb-stay': '自动备份间隔(分)', 'gadget-cb-success': '已还原备份!', 'gadget-cb-shelp': "仅用于原生编辑页面。值为'0'时不会自动更新备份,变动后需刷新页面才会生效。" }, { 'gadget-cb-label': '編輯內容自動備份', 'gadget-cb-range': '使用範圍', 'gadget-cb-d': '桌面版', 'gadget-cb-m': '手機版', 'gadget-cb-rhelp': '可用於代碼編輯器和Wikiplus小工具。', 'gadget-cb-text': '還原備份', 'gadget-cb-exp': '備份有效期(小時)', 'gadget-cb-stay': '自動備份間隔(分)', 'gadget-cb-success': '已還原備份!', 'gadget-cb-shelp': "僅用於原生編輯頁面。值為'0'時不會自動更新備份,變動後需重新整理頁面才會生效。" }) ); // 2. 小工具设置 mw.settingsDialog.addTab({name: 'contentBackup', label: 'gadget-cb-label', items: [ {key: 'range', type: 'CheckboxMultiselect', label: 'gadget-cb-range', help: mw.msg( 'gadget-cb-rhelp' ), config: {options: [ {data: 'vector', label: mw.msg( 'gadget-cb-d' )}, {data: 'minerva', label: mw.msg( 'gadget-cb-m' )} ]} }, {key: 'stay', type: 'Number', label: 'gadget-cb-stay', help: mw.msg('gadget-cb-shelp'), config: {min: 0, buttonStep: 5, required: true} }, {key: 'exp', type: 'Number', label: 'gadget-cb-exp', config: {min: 1, buttonStep: 1, required: true}} ], help: '编辑内容备份'}); // 3. 核心函数 const loadBackup = function() { // 加载备份函数 // CodeEditor需特殊处理 if ($( '.codeEditor-ui-toolbar' ).length) { codeEditor.setValue( backup ); } else { $(editor).val( backup ); } mw.notify( mw.msg('gadget-cb-success'), {type: 'success'} ); update(); }, saveBackup = function() { // 保存备份函数 // CodeEditor需特殊处理 if ($( '.codeEditor-ui-toolbar' ).length) { backup = codeEditor.getValue(); } else { backup = $(editor).val(); } expList[id] = mw.now(); mw.storage.setObject('LLWiki-contentBackup-exp', expList); localforage.setItem(id, backup); update(); }, // 自动更新函数,不支持Wikiplus update = isWikiplus || stay === 0 ? function() {} : mw.util.debounce(stay, function() { // jshint ignore: line saveBackup(); console.log('备份自动更新于' + new Date().toLocaleTimeString( 'zh' )); }), btn = isWikiplus ? {setDisabled: function() {}} : new OO.ui.ButtonWidget({label: mw.msg('gadget-cb-text'), disabled: true}).on('click', loadBackup); mw.loader.getScript( 'https://cdn.jsdelivr.net/npm/localforage/dist/localforage.min.js' ).then(function() { localforage.config({name: 'LLWiki-contentBackup'}); // 4. 先更新备份 if (expArray.length) { expArray.filter(function(ele) { return ele[1] <= expired; }) .forEach(function(ele) { localforage.removeItem( ele[0] ); }); expList = Object.fromEntries( expArray.filter(function(ele) { return ele[1] > expired; }) ); mw.storage.setObject('LLWiki-contentBackup-exp', expList); } else { mw.storage.remove( 'LLWiki-contentBackup' ); } // 移除旧版小工具的备份存档 if (expList[id]) { localforage.getItem(id, function(_, item) { backup = item; btn.setDisabled( !backup ); }); } // 5. 初始化延时保存备份功能 update(); // 6. 添加备份按钮和按键保存备份功能 if (isWikiplus) { const $btnPro = $('<button>', {text: mw.msg('gadget-cb-text')}).click( loadBackup ); mw.hook( 'wikiplus.dialog' ).add(function() { // Wikiplus需动态添加备份按钮 const $previewBtn = $('#Wikiplus-Quickedit-Preview-Submit'); if ($previewBtn.next( 'button' ).length) { return; } // 防止按钮已存在 console.log('Hook: wikiplus.dialog, 开始添加备份按钮'); const $btn = $btnPro.clone( true ).prop('disabled', !backup).insertAfter( $previewBtn ); // Wikiplus的上层为body,delegate效率太低 $('#Wikiplus-Quickedit-Submit, #Wikiplus-Quickedit-Preview-Submit').mousedown(function() { saveBackup(); $btn.prop('disabled', !backup); }); }); } else { $(function() { // 只添加一次按钮 btn.$element.insertAfter( '#wpDiffWidget' ); // #wpTemplateSandboxPreview可能由小工具生成,这里避免麻烦直接delegate $('.editOptions').on('mousedown', btns, function() { saveBackup(); btn.setDisabled( !backup ); }); }); } }, function() { console.error( '无法获得localforage!' ); }); // 7. 更新Ace Editor Session mw.hook( 'codeEditor.configure' ).add(function(session) { console.log('Hook: codeEditor.configure, 更新CodeEditor编辑器'); codeEditor = session; }); } //</nowiki> // [[category:作为模块的小工具]] [[category:编辑工具]] [[category:需要用户权限的小工具]] [[category:桌面版小工具]] [[category:手机版小工具]] // {{DEFAULTSORT:contentBackup.js}}