跳转到内容

User:Addonian1123/QuickCopy.js

维基百科,自由的百科全书
注意:保存之后,你必须清除浏览器缓存才能看到做出的更改。Google Chrome、Firefox、Microsoft Edge及Safari:按住⇧ Shift键并单击工具栏的“刷新”按钮。参阅Help:绕过浏览器缓存以获取更多帮助。
// <nowiki>
/*
var _addText="{{工具警告|QuickCopy}}";
var _addText="{{Notice|<big>'''文檔請見:[[User:Addonian1123/QuickCopy]]'''</big>}}";
*/
$(() => {
    mw.loader.using('mediawiki.util').then(() => {
        const userLang = mw.config.get('wgUserLanguage') || mw.config.get('wgUserVariant') || 'zh-hant';
        const isHans = ['zh-hans', 'zh-cn', 'zh-my', 'zh-sg'].some(l => userLang.toLowerCase().startsWith(l));

        const skin = mw.config.get('skin');
        let portletId = 'p-cactions';
        if (!document.getElementById('p-cactions') || skin === 'minerva') {
            portletId = 'p-tb';
        }

        const copyNode = mw.util.addPortletLink(
            portletId,
            '#',
            isHans ? '复制页面' : '複製頁面',
            'ca-quickcopy',
            isHans ? '复制本页内容或从其他页面复制' : '複製本頁內容或從其他頁面複製'
        );

        if (!copyNode) {
            return;
        }

        let windowManager;

        $(copyNode).on('click', (e) => {
            e.preventDefault();
            mw.loader.using(['mediawiki.api', 'mediawiki.Title', 'oojs-ui-core', 'oojs-ui-windows']).then(() => {
                openOOUIDialog();
            });
        });

        function openOOUIDialog() {
            if (!windowManager) {
                const msg = {
                    title: isHans ? 'QuickCopy 复制页面' : 'QuickCopy 複製頁面',
                    direction_label: isHans ? '复制方向:' : '複製方向:',
                    direction_forward: isHans ? '从本页复制至目标页面' : '從本頁複製至目標頁面',
                    direction_reverse: isHans ? '从目标页面复制至本页' : '從目標頁面複製至本頁',
                    target_label_forward: isHans ? '目标页面(必填):' : '目標頁面(必填):',
                    target_label_reverse: isHans ? '来源页面(必填):' : '來源頁面(必填):',
                    target_placeholder_forward: isHans ? '批量请用 | 或换行分隔,例如:User:Example/沙盒1 | User:Example/沙盒2' : '批量請用 | 或換行分隔,例如:User:Example/沙盒1 | User:Example/沙盒2',
                    target_placeholder_reverse: isHans ? '例如:User:Example/沙盒' : '例如:User:Example/沙盒',
                    summary_label: isHans ? '编辑摘要(可选):' : '編輯摘要(可選):',
                    submit: isHans ? '发布编辑' : '發布編輯',
                    cancel: isHans ? '取消' : '取消',
                    empty_target: isHans ? '页面名称不能为空' : '頁面名稱不能為空',
                    copying: isHans ? '正在复制页面...' : '正在複製頁面...',
                    success: isHans ? '复制成功。' : '複製成功。',
                    error_get: isHans ? '无法获取页面内容' : '無法抓取頁面內容',
                    warn_mainspace: isHans ? '警告:您正在将草稿、用户页或沙盒的内容复制到主条目空间,请优先使用移动功能。' : '警告:您正在將草稿、用戶頁或沙盒的內容複製到主條目空間,請優先使用移動功能。',
                    summary_placeholder: isHans ? '输入编辑摘要' : '輸入編輯摘要',
                };

                function QuickCopyDialog(config) {
                    QuickCopyDialog.super.call(this, config);
                }
                OO.inheritClass(QuickCopyDialog, OO.ui.ProcessDialog);

                QuickCopyDialog.static.name = 'quickcopy';
                QuickCopyDialog.static.title = msg.title;
                QuickCopyDialog.static.actions = [
                    { action: 'save', label: msg.submit, flags: ['primary', 'progressive'] },
                    { label: msg.cancel, flags: 'safe' }
                ];

                QuickCopyDialog.prototype.initialize = function () {
                    QuickCopyDialog.super.prototype.initialize.apply(this, arguments);

                    this.directionSelect = new OO.ui.RadioSelectWidget({
                        items: [
                            new OO.ui.RadioOptionWidget({ data: 'forward', label: msg.direction_forward }),
                            new OO.ui.RadioOptionWidget({ data: 'reverse', label: msg.direction_reverse })
                        ]
                    });
                    this.directionSelect.selectItemByData('forward');

                    this.targetInput = new OO.ui.MultilineTextInputWidget({
                        autosize: true,
                        rows: 2,
                        required: true,
                        placeholder: msg.target_placeholder_forward
                    });

                    this.targetField = new OO.ui.FieldLayout(this.targetInput, {
                        label: msg.target_label_forward,
                        align: 'top'
                    });

                    this.summaryInput = new OO.ui.TextInputWidget({
                        placeholder: msg.summary_placeholder
                    });

                    this.warningMessage = new OO.ui.MessageWidget({
                        type: 'warning',
                        inline: true,
                        label: msg.warn_mainspace
                    });
                    this.warningMessage.toggle(false);

                    this.panel = new OO.ui.PanelLayout({ padded: true, expanded: false });
                    this.fieldsetLayout = new OO.ui.FieldsetLayout();

                    this.fieldsetLayout.addItems([
                        new OO.ui.FieldLayout(this.directionSelect, { label: msg.direction_label, align: 'top' }),
                        this.targetField,
                        new OO.ui.FieldLayout(this.summaryInput, { label: msg.summary_label, align: 'top' })
                    ]);

                    this.panel.$element.append(this.fieldsetLayout.$element, this.warningMessage.$element);
                    this.$body.append(this.panel.$element);

                    this.directionSelect.on('select', this.onInputChange.bind(this));
                    this.targetInput.on('change', this.onInputChange.bind(this));
                };

                QuickCopyDialog.prototype.onInputChange = function () {
                    const direction = this.directionSelect.findSelectedItem()?.getData() || 'forward';
                    const rawVal = this.targetInput.getValue();
                    const targets = rawVal.split(/[\n|,,、]/).map(s => s.trim()).filter(Boolean);

                    if (direction === 'forward') {
                        this.targetField.setLabel(msg.target_label_forward);
                        this.targetInput.$input.attr('placeholder', msg.target_placeholder_forward);
                    } else {
                        this.targetField.setLabel(msg.target_label_reverse);
                        this.targetInput.$input.attr('placeholder', msg.target_placeholder_reverse);
                    }

                    this.actions.setAbilities({ save: targets.length > 0 });

                    this.checkNamespaceWarning(direction, targets);
                    this.updateSize();
                };

                QuickCopyDialog.prototype.checkNamespaceWarning = function (direction, targets) {
                    if (targets.length === 0) {
                        this.warningMessage.toggle(false);
                        return;
                    }

                    const isDraftUserSandbox = (ns, title) => {
                        if (ns === 2 || ns === 118) return true;
                        const t = title.toLowerCase();
                        return t.includes('sandbox') || t.includes('沙盒');
                    };

                    let showWarning = false;

                    if (direction === 'forward') {
                        const sourceNs = mw.config.get('wgNamespaceNumber');
                        const sourceTitle = mw.config.get('wgTitle');
                        if (isDraftUserSandbox(sourceNs, sourceTitle)) {
                            showWarning = targets.some(t => {
                                const titleObj = mw.Title.newFromText(t);
                                return titleObj && titleObj.getNamespaceId() === 0;
                            });
                        }
                    } else {
                        const currentNs = mw.config.get('wgNamespaceNumber');
                        if (currentNs === 0) {
                            const sourceTitleObj = mw.Title.newFromText(targets[0]);
                            if (sourceTitleObj) {
                                showWarning = isDraftUserSandbox(
                                    sourceTitleObj.getNamespaceId(),
                                    sourceTitleObj.getMainText()
                                );
                            }
                        }
                    }

                    this.warningMessage.toggle(showWarning);
                };

                QuickCopyDialog.prototype.getSetupProcess = function (data) {
                    return QuickCopyDialog.super.prototype.getSetupProcess.call(this, data)
                        .next(function () {
                            this.directionSelect.selectItemByData('forward');
                            this.targetInput.setValue('');
                            this.summaryInput.setValue('');
                            this.warningMessage.toggle(false);
                            this.actions.setAbilities({ save: false });
                        }, this);
                };

                QuickCopyDialog.prototype.getReadyProcess = function (data) {
                    return QuickCopyDialog.super.prototype.getReadyProcess.call(this, data)
                        .next(function () {
                            this.targetInput.focus();
                        }, this);
                };

                QuickCopyDialog.prototype.getActionProcess = function (action) {
                    const dialog = this;

                    if (action === 'save') {
                        const direction = this.directionSelect.findSelectedItem()?.getData() || 'forward';
                        const rawVal = this.targetInput.getValue();
                        const targets = rawVal.split(/[\n|,,、]/).map(s => s.trim()).filter(Boolean);
                        const userSummary = this.summaryInput.getValue().trim();

                        if (targets.length === 0) {
                            return new OO.ui.Process(function () {
                                return $.Deferred().reject(new OO.ui.Error(msg.empty_target)).promise();
                            });
                        }

                        return new OO.ui.Process(function () {
                            return executeCopy(targets, userSummary, direction, msg).then(function () {
                                dialog.close();
                            });
                        });
                    }

                    return QuickCopyDialog.super.prototype.getActionProcess.call(this, action);
                };

                windowManager = new OO.ui.WindowManager();
                $('body').append(windowManager.$element);

                const dialog = new QuickCopyDialog();
                windowManager.addWindows([dialog]);
            }

            windowManager.openWindow('quickcopy');
        }

        function executeCopy(targets, userSummary, direction, msg) {
            const api = new mw.Api();
            const currentTitle = mw.config.get('wgPageName');
            const suffix = '[[User:Addonian1123/QuickCopy|QuickCopy]]';
            const finalSummary = userSummary ? `${userSummary} // ${suffix}` : suffix;

            mw.notify(msg.copying);

            if (direction === 'forward') {
                return api.get({
                    action: 'query',
                    prop: 'revisions',
                    titles: currentTitle,
                    rvprop: 'content',
                    rvslots: 'main',
                    formatversion: 2
                }).then((data) => {
                    const pages = data.query.pages;
                    if (!pages || !pages[0] || !pages[0].revisions) {
                        return $.Deferred().reject(new OO.ui.Error(msg.error_get));
                    }
                    const content = pages[0].revisions[0].slots.main.content;

                    const promises = targets.map(t => {
                        return api.postWithToken('csrf', {
                            action: 'edit',
                            title: t,
                            text: content,
                            summary: finalSummary
                        });
                    });
                    return $.when.apply($, promises);
                }).then(() => {
                    mw.notify(msg.success, { type: 'success' });
                    setTimeout(() => {
                        window.location.href = mw.util.getUrl(targets[0]);
                    }, 1000);
                    return $.Deferred().resolve().promise();
                }).catch((err) => {
                    const errMsg = (err instanceof OO.ui.Error) ? err : new OO.ui.Error(typeof err === 'string' ? err : JSON.stringify(err));
                    return $.Deferred().reject(errMsg).promise();
                });
            } else {
                const sourceTitle = targets[0];
                return api.get({
                    action: 'query',
                    prop: 'revisions',
                    titles: sourceTitle,
                    rvprop: 'content',
                    rvslots: 'main',
                    formatversion: 2
                }).then((data) => {
                    const pages = data.query.pages;
                    if (!pages || !pages[0] || !pages[0].revisions) {
                        return $.Deferred().reject(new OO.ui.Error(msg.error_get));
                    }
                    const content = pages[0].revisions[0].slots.main.content;

                    return api.postWithToken('csrf', {
                        action: 'edit',
                        title: currentTitle,
                        text: content,
                        summary: finalSummary
                    });
                }).then((result) => {
                    if (result && result.edit && result.edit.result === 'Success') {
                        mw.notify(msg.success, { type: 'success' });
                        setTimeout(() => {
                            window.location.reload();
                        }, 1000);
                        return $.Deferred().resolve().promise();
                    } else {
                        return $.Deferred().reject(new OO.ui.Error(JSON.stringify(result))).promise();
                    }
                }).catch((err) => {
                    const errMsg = (err instanceof OO.ui.Error) ? err : new OO.ui.Error(typeof err === 'string' ? err : JSON.stringify(err));
                    return $.Deferred().reject(errMsg).promise();
                });
            }
        }
    });
});
// </nowiki>