minerva-online assistant

此脚本能更方便使用minerva-online平台,可在顶端菜单栏右下角的按钮处设置功能开关,并查看功能详情

当前为 2021-10-20 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         minerva-online assistant
// @namespace    https://space.bilibili.com/17846288
// @version      2.3.5
// @description  此脚本能更方便使用minerva-online平台,可在顶端菜单栏右下角的按钮处设置功能开关,并查看功能详情
// @author       inoki
// @match        https://www.minerva-online.com/*
// @require      https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js
// @grant        GM_setValue
// @grant        GM_getValue
// @noframes
// ==/UserScript==

/*jshint esversion: 6 */

(()=>{
    'use strict';

    const $=window.$;
    const SET=[
        {
            'id':0,
            'name':'置顶置底',
            'func':()=>{GOTOPBOTTOM();},
            'unfunc':()=>{unGOTOPBOTTOM();},
            'detail':'在平台域名所有可滚动页面生效,页面右下方添加置顶置底按钮<br>按钮会根据页面滚动方向自动切换置顶和置底,按钮样式可在代码中自定义中修改',
            'switch':1,
        },
        {
            'id':1,
            'name':'菜单遮罩',
            'func':()=>{COVERMENU();},
            'unfunc':()=>{unCOVERMENU();},
            'detail':'在有顶端菜单栏的页面生效<br>让菜单栏需要点击一次后才可展开,防止鼠标经过时误触 (默认关闭)',
            'switch':0,
        },
        {
            'id':2,
            'name':'附件下载',
            'func':()=>{DOWNLOADFILE();},
            'unfunc':()=>{unDOWNLOADFILE();},
            'detail':'在问卷管理页面生效,每份报告前添加↓按钮<br>点击↓加载附件列表,点击√下载全部附件,点击附件名下载单个附件,鼠标悬停可预览图片',
            'switch':1,
        },
        {
            'id':3,
            'name':'扣分标记',
            'func':()=>{MARKQUESTION();},
            'unfunc':()=>{unMARKQUESTION();},
            'detail':'在单店报告页面生效<br>将题目选项中勾选n/a的标绿,扣分的标红,选项更改后需保存报告才会刷新标记,方便快速检查扣分n/a题评论',
            'switch':1,
        },
        {
            'id':4,
            'name':'评论编辑',
            'func':()=>{COMMENTEDIT();},
            'unfunc':()=>{unCOMMENTEDIT();},
            'detail':'在单店报告页面生效,右下方按钮展开操作界面<br>输入匹配内容(支持正则)会即时显示匹配框数量并标灰,点击一键替换可批量修改所有评论框内容<br>点击首字母大写可批量将首字母变为大写,只对英文生效',
            'switch':1,
        },
        {
            'id':5,
            'name':'验证输出',
            'func':()=>{VERIFYEXPORT();},
            'unfunc':()=>{unVERIFYEXPORT();},
            'detail':'在问卷管理页面生效,表头上方添加按钮<br>点击按钮弹出确认提示,确认后会验证输出当前页面勾选的所有报告,成功后会在每份报告下方小窗口显示绿色保存成功提示',
            'switch':1,
        },
    ];


    /*在顶端菜单栏添加MOassist设置按钮*/
    const menu=$('div#menu');
    if(menu.length){
        menu.find('ul.tools').append(`
<li class="MOassist">
<a class="toolsLink">
<div class="iconTools" style="background: url('/images/icons/menu/x16/tools-settings.png')"></div>
<ul class="textArea" style="visibility:visible; display:none"><li>MO助手设置</li></ul>
<ul id="MOoption" class="innerItemFirst" style="z-index: 11; display:none; top:25px; right:0px">`
                                    );
        menu.find('li.MOassist').on('click',function(){
            MOListSwitch(this);
        });
        //导入所有功能列表并显示开关状态
        for(let i in SET){
            menu.find('ul#MOoption').append(`
<li id="MOoptions" class="MOassist" style="width:100%">
<div class="menuItemText" style="color:#4C5057">${SET[i].name}</div>
<input type=checkbox id=${SET[i].id} class=menuIconSmall></input>
<ul class="textArea" style="visibility:visible; display: none; margin-top:0px; right:120px"><li style="padding:0px 5px !important">${SET[i].detail}</li>`
                                           );
            //运行开启状态的功能并打勾
            if(GM_getValue(SET[i].name,SET[i].switch)){
                SET[i].func();
                menu.find('input#'+SET[i].id).attr('checked',true);
            }
        }
        //根据是否选中即时启用或卸载功能并记录开关状态
        menu.find('li#MOoptions').on('click',function(){
            const checkbox=$(this).find('input');
            const id=$(checkbox).attr('id');
            if($(checkbox).attr('checked')){
                SET[id].unfunc();
                $(checkbox).attr('checked',false);
                GM_setValue(SET[id].name,0);
            }
            else{
                SET[id].func();
                $(checkbox).attr("checked",true);
                GM_setValue(SET[id].name,1);
            }
        });
        //鼠标聚焦时显示详情 【https://www.minerva-online.com/portal/menu/js/v2/menuRender.js?version=21-08 createToolOption : 】
        menu.find('li.MOassist').hover(function(){
            $(this).find('ul:first').stop().show(200);
        },function(){
            $(this).find('ul:first').stop().hide(200);
        });
    }

    //功能列表开关
    function MOListSwitch(self){
        const on=$(self).find('ul#MOoption').css('display');
        if(on==='none'){
            $(self).find('ul#MOoption').stop().slideDown(200);
        }
        else{
            $(self).find('ul#MOoption').stop().slideUp(200);
        }
    }
    /*在顶端菜单栏添加MOassist设置按钮*/


    /*置顶置底*/
    function GOTOPBOTTOM(){
        const scrollBar=$(document).height()>(window.innerHeight+1||document.documentElement.clientHeight);//如有滚动条
        if(scrollBar&&document.location.href.indexOf('alias=knowledgebase')===-1){//knowledgebase页面自带置顶按钮,不启用
            const goTopBottomButton=document.createElement('div');
            const toggleButton=document.createElement('img');
            $(toggleButton).appendTo(goTopBottomButton);
            $(goTopBottomButton).appendTo($('body')[0]);
            $(goTopBottomButton).css({'position':'fixed','zIndex':10000}).attr('id','goTopBottom');
            $(toggleButton).css({'display':'block','cursor':'pointer'}).attr('src','/knowledgebase/images/arrow_back_to_top.svg');//按钮显示图片(向下箭头)

            //以下按钮参数可自定义修改
            goTopBottomButton.style.bottom='50px';//按钮距离网页底部50px
            goTopBottomButton.style.right='30px';//按钮距离网页右边30px
            toggleButton.style.width='25px';//按钮图片宽25px
            toggleButton.style.height='25px';//按钮图片高25px
            toggleButton.style.opacity=0.5;//按钮不透明度,0.0(完全透明)到1.0(完全不透明)
            toggleButton.style.backgroundColor='grey';//按钮背景颜色,也可使用在excel等软件的自定义颜色界面的16进制代码
            const clickScrollTime=500;//点击按钮时,网页滚动到顶部或底部需要的时间,单位是毫秒

            //点击按钮时网页滚动到顶部或底部
            let scrollDirection='down';
            toggleButton.addEventListener('click',()=>{
                if(scrollDirection==='up'){
                    $('html,body').animate({scrollTop:'0px'},clickScrollTime);
                }
                else{
                    $('html,body').animate({scrollTop:$(document).height()},clickScrollTime);
                }
            });
            //页面滚动监听
            let scrollAction=window.pageYOffset;
            $(window).scroll(()=>{
                const diffY=scrollAction-window.pageYOffset;
                scrollAction=window.pageYOffset;
                scrollDirection= diffY<0? 'down' : 'up';
                toggleButton.style.transform= diffY<0? 'rotate(0deg)' : 'rotate(180deg)';
                if(getScrollTop()===0){
                    scrollDirection='down';
                    toggleButton.style.transform='rotate(0deg)';
                }
                if(getScrollTop()+window.innerHeight+20>=$(document).height()){
                    scrollDirection='up';
                    toggleButton.style.transform='rotate(180deg)';
                }
            });
        }
    }

    //获取垂直方向滑动距离
    function getScrollTop(){
        let scrollTop=0;
        if(document.documentElement&&document.documentElement.scrollTop){
            scrollTop=document.documentElement.scrollTop;
        }
        else if(document.body){
            scrollTop=document.body.scrollTop;
        }
        return scrollTop;
    }
    /*置顶置底*/

    /*卸载置顶置底*/
    function unGOTOPBOTTOM(){
        if($('div#goTopBottom').length) $('div#goTopBottom').remove();
    }
    /*卸载置顶置底*/


    /*菜单遮罩*/
    function COVERMENU(){
        const menu=$('div#menu');
        if(menu.length){
            //若存在menu则添加cover层
            const cover = document.createElement('div');
            cover.className = 'layout';
            cover.style = 'top:'+menu[0].style.top+';opacity:0.3;z-index:10000;right:16%';
            $(cover).appendTo($('body')[0]).attr('id','cover');
            //点击时将cover层下置
            cover.addEventListener('click',()=>{
                cover.style.zIndex = -1;
            });
            //离开menu时cover层还原
            menu[0].addEventListener('mouseleave',()=>{
                cover.style.zIndex = 10000;
            });
            //cover层位置跟随menu 【https://www.minerva-online.com/portal/menu/js/v2/menuRender.js?version=21-08 onScrollEventHandler : 】
            $(window).scroll(()=>{
                const SM=unsafeWindow.SM;
                const ind = SM.ui.headerHeight - SM.ui.getScrollTop();
                cover.style.top= ind>0? ind+'px' : '0px';
            });
        }
    }
    /*菜单遮罩*/

    /*卸载菜单遮罩*/
    function unCOVERMENU(){
        if($('div#cover').length) $('div#cover').remove();
    }
    /*卸载菜单遮罩*/


    /*附件下载*/
    function DOWNLOADFILE(){
        if (document.location.href.indexOf('alias=smngr.surveyexplorer')>=0&&$('tr.persist-header').length){
            $('tr.persist-header').each(function(){
                $(this).children().first().after($(this).children().first().clone(true));
            });
            $('div.sticky-wrap').find(':checkbox').each(function(){//checkbox后添加下载按钮
                const surveyid=$(this).val();
                $(this).parent().after('<td><button type=button id='+surveyid+' class=download><b>↓</td>');
                $('#'+surveyid+'.download').one('click',()=>{
                    DownloadButton(surveyid);
                });
            });
        }
    }

    //获取附件列表
    function DownloadButton(surveyid){
        $('button#'+surveyid+'.download').hide();
        $('button#'+surveyid+'.download').after('<p id='+surveyid+' class=loading><b>......');
        $.get('/open/data.asp?post={"action":"exec","dataset":{"datasetname":"/Apps/SM/Survey/SurveyInstanceGetData"},"parameters":[{"name":"SurveyInstanceID","value":"'+surveyid+'"}]}',(data,status)=>{//调用API获取当前survey数据[SurveyInstanceGetData]
            if (status==='success'){
                const filedata=data.dataset.data[3];
                const fileno=filedata.length;
                $('p#'+surveyid+'.loading').after('<ol id='+surveyid+' class=filelist>\t#='+fileno+'');
                if (fileno>0){
                    for(let i in filedata){
                        const filename=filedata[i].FileName+'.'+filedata[i].FileExtension;
                        const fileid=filedata[i].AttachmentID;
                        const fileurl='/mystservices/Attachments/getAttachment.asp?Attachment='+fileid+'&Password='+filedata[i].Password+'';
                        let filesize=Number(filedata[i].FileSizeInBytes)/1024;
                        filesize= (filesize>1024)? (filesize/1024).toFixed(2)+' MB' : filesize.toFixed(2)+' KB';
                        $('<tr id='+fileid+'>').appendTo('ol#'+surveyid+'.filelist');
                        $(`<td><li><a id=${surveyid} class='${filedata[i].AttachmentType} mailboxlink' href=${fileurl}>${filename}</a>`).appendTo('tr#'+fileid);
                        $('<td>'+filesize+'</td>').appendTo('tr#'+fileid);
                    }
                    $('a#'+surveyid+'.I,a#'+surveyid+'.V').mouseenter(function(){
                        FilePreview(1,$(this).attr('href'));
                    }).mouseleave(()=>{
                        FilePreview(0);
                    });
                    $('ol#'+surveyid+'.filelist').prepend('<button type=button id='+surveyid+' class=yes><b>√');
                    $('button#'+surveyid+'.yes').on('click',()=>{
                        DownloadAll(surveyid);
                    });
                    DownloadButton0(surveyid);
                }
                else {
                    DownloadButton0(surveyid);
                }
            }
            else {
                DownloadButton0(surveyid);
            }
        },"json");
    }

    //预览附件图片
    function FilePreview(show,src){
        if(show){
            const imgid=src.split('=')[2];
            if($('img#'+imgid+'.filepreview').length===0){
                $('<div><img id='+imgid+' class=filepreview>').appendTo('body');
                $('img#'+imgid+'.filepreview').attr('src',src+'&getThumbnail=1').css('height','200px')//视频附件预览图&getThumbnail=1
                    .parent().css({'position':'fixed','zIndex':10000,'height':'200px','background':'url(/images/icons/filtersv2/loading06.gif)'});
            }
            $('img#'+imgid+'.filepreview').parent().css({'top':event.clientY-200+'px','left':event.clientX+100+'px'});
            $('img#'+imgid+'.filepreview').show();
        }
        else{
            $('img.filepreview').hide();
        }
    }

    //按钮变为关闭
    function DownloadButton0(surveyid){
        $('p#'+surveyid+'.loading').remove();
        $('button#'+surveyid+'.download').one('click',()=>{
            DownloadButton1(surveyid);
        });
        $('button#'+surveyid+'.download').text('×');
        $('button#'+surveyid+'.download').show();
    }

    //按钮重置为初始
    function DownloadButton1(surveyid){
        $('ol').remove('#'+surveyid);
        $('button#'+surveyid+'.download').one('click',()=>{
            DownloadButton(surveyid);
        });
        $('button#'+surveyid+'.download').text('↓');
    }

    //下载全部
    function DownloadAll(surveyid){
        $('button#'+surveyid+'.yes').hide();
        const iframe=$('ol#'+surveyid+'.filelist').find('iframe');
        if(iframe.length)iframe.remove();
        setTimeout(()=>{
            $('button#'+surveyid+'.yes').show();
        },1000*$('ol#'+surveyid+'.filelist').find('a').length);//有几个附件就隐藏按钮几秒
        $('ol#'+surveyid+'.filelist').find('a').each(function(){
            $('<iframe src='+$(this).attr('href')+'>').appendTo(this).hide();
        });
        $('button#'+surveyid+'.yes').text('〇');
    }
    /*附件下载*/

    /*卸载附件下载*/
    function unDOWNLOADFILE(){
        if (document.location.href.indexOf('alias=smngr.surveyexplorer')>=0&&$('tr.persist-header').length){
            $('tr.persist-header').each(function(){
                $(this).children().first().remove();
            });
            $('button.download').each(function(){
                $(this).parent().remove();
            });
        }
    }
    /*卸载附件下载*/


    /*扣分标记*/
    function MARKQUESTION(){
        if(document.location.href.indexOf('alias=survey.view')>=0){
            $('span.surveyansweroption').each(function(){
                if($(this).prev('input').is(':checked')){
                    if($(this).prev('input').val()==='__na__'){
                        $(this).css('color','green');//标绿n/a项
                    }
                }
            });
            //获取所有扣分的题目
            const qidmark=[];
            $.get('/mystservices/v2new/getSurvey.asp?InstanceID='+$('input#instanceID').val(),(data,status)=>{
                if (status==='success'){
                    $(data).find('nobr').each(function(){
                        const score=$(this).text();
                        if(score!=''&&score.indexOf('%')===-1){//排除空值与section总分
                            const pts=score.split('/');
                            if(pts[0]<pts[1]){
                                const QidANS=$(this).parent().parent().parent().parent().parent('td.surveyquestioncell').prev().find('div').attr('id');
                                qidmark.push(QidANS);
                            }
                        }
                    });
                    for(let i in qidmark){
                        $('div#'+qidmark[i]).find('span.surveyansweroption').css('color','red');//标红扣分项
                    }
                }
            });
        }
    }
    /*扣分标记*/

    /*卸载扣分标记*/
    function unMARKQUESTION(){
        if(document.location.href.indexOf('alias=survey.view')>=0) $('span.surveyansweroption').removeAttr('style');
    }
    /*卸载扣分标记*/


    /*评论编辑*/
    function COMMENTEDIT(){
        if(document.location.href.indexOf('alias=survey.view')>=0){
            $('<div id=commentEdit>').appendTo($('body')[0])
                .css({'position':'fixed','zIndex':10000,
                      'right':'30px','bottom':'80px','height':'25px','width':'25px',
                      'background':'url("/images/icons/menu/x32/survet.png") 100%/100% #4C5157'})
                .on('click',()=>{
                commentEditSwitch();
            });
            $('<div id=commentFunc>').appendTo('div#commentEdit')
                .css({'position':'fixed','right':'40px','bottom':'110px'}).hide()
                .on('click',e=>{
                e.stopPropagation();//阻止子元素执行父元素click事件
            });
            //提示开关
            $('<b id=hint>点击获取提示</b>').appendTo('div#commentFunc');
            $('b#hint').on('click',function(){
                hintSwitch(this);
            });
            //评论匹配与替换
            $('<button type=button id=replaceAll class=surveyBottomButton>一键替换</button>').appendTo('div#commentFunc');
            $('button#replaceAll')
                .before('<textarea id=find placeholder=匹配内容></textarea><b>↓↓↓</b><textarea id=replace placeholder=替换内容></textarea>')
                .before('<b id=findNum>#</b>');
            $('textarea#find,textarea#replace').on('keydown',e=>{
                e.stopPropagation();//阻止页面自带keydown事件修改textarea的class值
            });
            $('textarea#find').on('input',function(){
                commentMatch(this);
            });
            $('button#replaceAll').on('click',()=>{
                commentReplace();
            });
            //首字母大写
            $('<button type=button id=initialUpper class=surveyBottomButton>首字母大写</button>').appendTo('div#commentFunc');
            $('button#initialUpper').on('click',()=>{
                initialUpper();
            });
            $('div#commentFunc').children().css({'display':'block','text-align':'center','margin':'auto'});
        }
    }

    //评论替换开关
    function commentEditSwitch(){
        const on=$('div#commentFunc').css('display');
        if(on==='none'){
            $('div#commentFunc').show();
            commentMatch($('textarea#find'));
        }
        else{
            $('div#commentFunc').hide();
            $('textarea.surveycomment').css('background','');
        }
    }

    //插入或移除提示
    function hintSwitch(self){
        if($(self).children().length){
            $(self).text('点击获取提示').children().remove();
        }
        else{
            $(self).text('点击关闭提示')
                .append('<a class=mailboxlink target=_blank href=https://tool.oschina.net/uploads/apidocs/jquery/regexp.html>匹配支持正则表达式</a>')
                .append('<a class=mailboxlink target=_blank href=https://c.runoob.com/front-end/854/>正则表达式测试</a>')
                .append(`<ol>
<li>正则实例:[。|.]$ 可匹配末尾处中英文句号;^[a-z] 可匹配开头处小写字母;甲|乙|丙 可匹配甲或乙或丙</li><br>
<li>如不使用正则,可当作一般替换使用,但如需替换一些特殊字符(\^$*+?.等,参照第一个链接中所列字符),请在前面使用\\标记转义,以避免识别为正则表达</li><br>
<li>报告评论框激活后按Ctrl可切换评论框是否标红,所有标红的评论框将被排除在匹配替换范围之外</li><br>
<li>匹配内容为空时会匹配所有字符</li></ol>`);
            $(self).children().css('display','block').on('click',e=>{
                e.stopPropagation();
            });
            $(self).find('li').css({'text-align':'left','width':'200px'});
        }
    }

    //即时标灰匹配到的评论框并计数
    function commentMatch(self){
        let find;
        try{//若不是正则表达式,按普通字符处理
            find=new RegExp($(self).val(),'gm');
        }
        catch(e){
            find=$(self).val();
        }
        let findNum=0;
        $('textarea.active').css('background','');
        $('textarea.surveycomment').each(function(){
            try{//
                if($(this).val().search(find)>=0){//search只接受正则
                    findNum++;
                    $(this).css('background','lightgrey');
                }
                else{
                    $(this).css('background','');
                }
            }
            catch(e){
                if($(this).val().indexOf(find)>=0){//indexOf只接受字符
                    findNum++;
                    $(this).css('background','lightgrey');
                }
                else{
                    $(this).css('background','');
                }
            }
        });
        $('b#findNum').text('#='+findNum);
    }

    //判断是否为正则并进行评论替换
    function commentReplace(){
        $('textarea.surveycomment').each(function(){
            let find;
            try{
                find=new RegExp($('textarea#find').val(),'gm');
            }
            catch(e){
                find=$('textarea#find').val();
            }
            const replace=$('textarea#replace').val();
            const text=$(this).val().replace(find,replace);
            $(this).val(text);
        });
    }

    //首字母大写
    function initialUpper(){
        $('textarea.surveycomment').each(function(){
            const text=$(this).val().slice(0, 1).toUpperCase()+$(this).val().slice(1);//.toLowerCase();如后面部分需强制小写
            $(this).val(text);
        });
    }
    /*评论编辑*/

    /*卸载评论编辑*/
    function unCOMMENTEDIT(){
        if($('div#commentEdit').length) $('div#commentEdit').remove();
    }
    /*卸载评论编辑*/


    /*验证输出*/
    function VERIFYEXPORT(){
        if (document.location.href.indexOf('alias=smngr.surveyexplorer')>=0&&$('div#filterdiv').length){
            $('div#filterdiv').before('<button type=button id=verifyExport class="rm-btn rm-btn-default">验证输出勾选的报告</button>');
            $('button#verifyExport').css({'margin':'10px 0px','display':'block'}).on('click',()=>{
                verifyExportAll();
            });
        }
    }

    //验证输出全部报告
    function verifyExportAll(){
        const apply=confirm('请确认是否要验证输出当前页面勾选的所有报告');
        if(apply){
            $('table#reporttable tbody').find('tr').each(function(){
                if($(this).find('input:checkbox').eq(0).is(':checked')){
                    const a=$(this).find('a.mailboxlink')[0];
                    const src=$(a).attr('href');
                    const iframe=document.createElement('iframe');
                    iframe.src=src;
                    iframe.style='height:80px; width:250px';
                    $(a).after(iframe);
                    iframe.onload=function(){
                        const doc=$(this).contents();
                        $(doc).find('div#addInfo,div#menu,div#pathContainer').remove();
                        if($(doc).find('input#scrverN').is(':checked')&&$(doc).find('input#questVerN').is(':checked')){//前2点均为否时才进行操作
                            $(doc).find('input#scrverY').click();
                            $(doc).find('input#questVerY').click();
                            $(doc).find('button#save').click();
                        }
                    };
                }
            });
            alert('请耐心等待所有小窗口加载完成,显示绿色保存成功提示后,再刷新页面检查是否全部验证输出成功');
        }
    }
    /*验证输出*/

    /*卸载验证输出*/
    function unVERIFYEXPORT(){
        if($('button#verifyExport').length) $('button#verifyExport').remove();
    }
    /*卸载验证输出*/


})();