User:Techmoe/mgDuplicateFilesClean.js

来自萌娘共享
跳转至: 导航搜索

注意:在保存之后,您可能需要清除浏览器缓存才能看到所作出的变更的影响。

  • Firefox或Safari:按住Shift的同时单击刷新,或按Ctrl-F5Ctrl-R(Mac为⌘-R
  • Google Chrome:Ctrl-Shift-R(Mac为⌘-Shift-R
  • Internet Explorer:按住Ctrl的同时单击刷新,或按Ctrl-F5
  • Opera:前往菜单 → 设置(Mac为Opera → Preferences),然后隐私和安全 → 清除浏览数据 → 缓存的图片和文件
$(function(){ 
    if ($(".mw-special-ListDuplicatedFiles")[0] && $('.mw-spcontent > p')[1]) {
        var mgDuplicateFilesCleanDate = function mgDuplicateFilesCleanDate(timestamp) {
            var _date = new Date(timestamp);
            ['getDate', 'getFullYear', 'getHours', 'getMilliseconds', 'getMinutes', 'getMonth', 'getSeconds', 'getTime', 'getUTCDate', 'getUTCFullYear', 'getUTCHours', 'getUTCMilliseconds', 'getUTCMinutes', 'getUTCMonth', 'getUTCSeconds', 'getYear'].forEach(function(key) {
                _date[key] = function() {
                    var result = Date.prototype[key].apply(_date, arguments);
                    if (key.includes('Month')) result++;
                    if (typeof result === 'number' && (result + '').length === 1) return '0' + result;
                    else return result + '';
                };
            });
            return _date;
        };
        var mgDuplicateFilesClean = function mgDuplicateFilesClean() {
            mw.loader.using(["oojs-ui"]).then(function() {
                var list = $("#picOl, #MP3Ol").find('li').map(function() {
                    return 'File:' + $(this).find('a:first').text();
                }).toArray();
                var api = new mw.Api();
                var duplicateFilesList = {};
                var globalusage = {};
                var context = $('.mw-spcontent').addClass('duplicateFilesDeletion-context').empty();
                context.append('<div class="duplicateFilesDeletion-loading">正在加载中(<span class="duplicateFilesDeletion-loading-step">0</span>/3)……</div>');
                $('.duplicateFilesDeletion-loading').css('left', (context.width() - $('.duplicateFilesDeletion-loading').width()) / 2);
                step = $('.duplicateFilesDeletion-loading-step');
                api.post({
                    action: 'query',
                    format: 'json',
                    titles: list.join('|'),
                    prop: 'duplicatefiles',
                    dflimit: 500
                }).then(function(data) {
                    step.text('1');
                    var _name = [];
                    data = data.query.pages;
                    for (var i in data) {
                        duplicateFilesList[data[i].title] = (data[i].duplicatefiles || []).map(function(n) {
                            if (n.name) n.name = ('File:' + n.name).replace(/_/g, ' ');
                            return n;
                        });
                        _name.push(data[i].title);
                    }
                    return api.post({
                        action: 'query',
                        format: 'json',
                        titles: _name.join('|'),
                        prop: 'imageinfo',
                        iiprop: 'timestamp|user|url'
                    });
                }).then(function(d) {
                    step.text('2');
                    var result = d.query.pages;
                    for (var i in result) {
                        duplicateFilesList[result[i].title].push({
                            name: result[i].title,
                            user: result[i].imageinfo[0].user,
                            timestamp: result[i].imageinfo[0].timestamp,
                            url: result[i].imageinfo[0].url
                        });
                    }
                    var _name = [];
                    for (var idx in duplicateFilesList) {
                        duplicateFilesList[idx].forEach(function(n) {
                            _name.push(n.name);
                        });
                    }
                    return api.post({
                        action: 'query',
                        format: 'json',
                        titles: _name.join('|'),
                        gulimit: 500,
                        prop: 'globalusage'
                    });
                }).then(function(d) {
                    step.text('3');
                    var result = d.query.pages;
                    for (var i in result) {
                        globalusage[result[i].title] = result[i].globalusage;
                    }
                    return Promise.resolve();
                }).then(function() {
                    var menuLayout = new OO.ui.MenuLayout({
                        classes: ['duplicateFilesDeletion-container']
                    });
                    context.empty().append(new OO.ui.PanelLayout({
                        padded: true,
                        expanded: false,
                        framed: true,
                        content: [menuLayout]
                    }).$element);
                    var menuPanel = new OO.ui.PanelLayout({
                            padded: true,
                            expanded: true,
                            scrollable: true,
                        }),
                        contentPanel = new OO.ui.PanelLayout({
                            padded: true,
                            expanded: true,
                            scrollable: true
                        });
                    var selectOption = {
                        items: []
                    };
                    var pageLayout = {};
                    var deletionList = '';
                    var ifFirstPageLayoutIsAppended = true;
                    for (var i in duplicateFilesList) {
                        selectOption.items.push(new OO.ui.OptionWidget({
                            data: i,
                            label: i.replace('File:', ''),
                            classes: ['duplicateFilesDeletion-menu-label']
                        }));
                        pageLayout[i] = new OO.ui.PageLayout({
                            data: i,
                            padded: true,
                            expanded: true,
                            scrollable: true,
                            classes: ['duplicateFilesDeletion-content-page']
                        });
                        pageLayout[i].on('active', function() {
                            menuLayout.$element.height($(this).outerHeight(true));
                        });
                        contentPanel.$element.append(pageLayout[i].$element);
                        pageLayout[i].setActive(ifFirstPageLayoutIsAppended);
                        ifFirstPageLayoutIsAppended = false;
                        var fieldset = new OO.ui.FieldsetLayout({
                            label: '重复文件详细信息'
                        });
                        fieldset.addItems([
                            new OO.ui.Element({
                                classes: ['duplicateFilesDeletion-content-page-introdution'],
                                content: [
                                    new OO.ui.HtmlSnippet('此处显示该组重复文件的详细信息以及使用情况。<br>右侧显示该图片画面,下方显示该组重复文件的信息。<br>已根据情况自动进行默认选择,但<span style="font-weight: bold;">强烈建议</span>您检查一次,以免意外发生。')
                                ]
                            })
                        ]);
                        var img = [];
                        var flag = {
                            last: null,
                            globaluse: false
                        };
                        var pageBody = [];
                        duplicateFilesList[i].forEach(function(n) {
                            if (n.url) img.push(new OO.ui.Element({
                                classes: ['duplicateFilesDeletion-img-preview'],
                                content: [
                                    new OO.ui.HtmlSnippet('<img src="' + n.url + '">')
                                ]
                            }));
                            if (!flag.last) flag.last = {
                                name: n.name + '',
                                timestamp: new Date(n.timestamp).getTime()
                            };
                            else {
                                var timestamp = new Date(n.timestamp).getTime();
                                if (timestamp > flag.last.timestamp) flag.last = {
                                    name: n.name,
                                    timestamp: timestamp
                                };
                            }
                            var date = mgDuplicateFilesCleanDate(n.timestamp);
                            pageBody.push(new OO.ui.CheckboxInputWidget({
                                value: n.name + '',
                                data: {
                                    uploadTime: date.getFullYear() + '-' + date.getMonth() + '-' + date.getDate() + ' ' + date.getHours() + ':' + date.getMinutes() + ':' + date.getSeconds(),
                                    uploader: $('<a/>').addClass("external").attr({
                                        href: '//zh.moegirl.org/User:' + n.user,
                                        title: '萌百上的用户 ' + n.user,
                                        target: '_blank'
                                    }).text('User:' + n.user)
                                }
                            }));
                            if (globalusage[n.name] && globalusage[n.name].length) flag.globaluse = true;
                        });
                        if (img.length) fieldset.addItems(img);
                        fieldset.addItems(pageBody.map(function(checkbox) {
                            checkbox.on('change', function(b) {
                                var v = checkbox.getValue();
                                if (b) {
                                    if (deletionList.includes(v)) return;
                                    else deletionList += v + '|';
                                } else {
                                    if (!deletionList.includes(v)) return;
                                    else deletionList.replace(v + '|', '');
                                }
                            });
                            var data = checkbox.getData();
                            var name = checkbox.getValue();
                            var ifGU = globalusage[name] && globalusage[name].length;
                            if (flag.globaluse) checkbox.setSelected(!ifGU);
                            else checkbox.setSelected(name !== flag.last.name);
                            var filedLayout = new OO.ui.FieldLayout(checkbox, {
                                label: new OO.ui.HtmlSnippet('<a class="external" href="/' + name + '" title=' + name + ' target="_blank">' + name + '</a>'),
                                classes: ['duplicateFilesDeletion-img']
                            });
                            var content = $('<div/>');
                            content.addClass('duplicateFilesDeletion-img-content');
                            $('<p/>')
                                .append($('<div/>').addClass('duplicateFilesDeletion-img-content-left').text('上传时间:'))
                                .append($('<div/>').addClass('duplicateFilesDeletion-img-content-right').text(data.uploadTime + (name === flag.last.name ? '(这是该组文件最后上传的一份副本)' : '')))
                                .appendTo(content);
                            $('<p/>')
                                .append($('<div/>').addClass('duplicateFilesDeletion-img-content-left').text('上传者:'))
                                .append($('<div/>').addClass('duplicateFilesDeletion-img-content-right').append(data.uploader))
                                .appendTo(content);
                            if (ifGU) {
                                var guP = $('<p/>');
                                guP.append($('<div/>').addClass('duplicateFilesDeletion-img-content-left').text('全域使用页面:'));
                                var guList = $('<div/>').addClass('duplicateFilesDeletion-img-content-right');
                                globalusage[name].forEach(function(n, i) {
                                    var link = $('<a/>');
                                    link.addClass("external").attr({
                                        title: '全域使用页面:' + name,
                                        target: '_blank'
                                    });
                                    if (n.url) link.attr('href', n.url).text(decodeURI(n.url.substring(1)).replace(/\_/g, ' '));
                                    else {
                                        var url = n.wiki = n.wiki ? n.wiki + ':' + n.title : n.title;
                                        link.attr('href', '/' + url).text(url);
                                    }
                                    if (i) guList.append('、');
                                    guList.append(link);
                                });
                                guP.append(guList).appendTo(content);
                            }
                            filedLayout.$element.append(content);
                            return filedLayout;
                        }));
                        pageLayout[i].$element.append(fieldset.$element);
                    }
                    var select = new OO.ui.SelectWidget(selectOption);
                    selectOption.items[0].setSelected(true);
                    select.on('select', function(item) {
                        var id = item.getData();
                        for (var i in pageLayout)
                            pageLayout[i].setActive(i === id);
                    });
                    menuLayout.$menu.append(
                        menuPanel.$element.append('<b>重复文件列表</b>', select.$element)
                    );
                    menuLayout.$content.append(
                        contentPanel.$element
                    );
                });
            });
        };
        
        /* load css */
        mw.loader.load('https://common.moegirl.org/User:Techmoe/mgDuplicateFilesClean.css?action=raw&ctype=text/css&_=' + new Date().getTime(), 'text/css');
        mgDuplicateFilesClean();
        
        /*
        function addStyle(css) {
            return $('<style/>').text(css.replace(/\<[^\>]+\>/g, '')).appendTo('body');
        }
        $.get('https://common.moegirl.org/User:Techmoe/mgDuplicateFilesClean.css?action=raw&ctype=text/css&_=' + new Date().getTime(), addStyle);
        mgDuplicateFilesClean();
        */
        /*
                mw.config.get('mgDuplicateFilesClean ');*/
    }
});