打开/关闭菜单
Toggle preferences menu
打开/关闭个人菜单
未登录
未登录用户的IP地址会在进行任意编辑后公开展示。

MediaWiki:Gadget-tikuInlineEditModule.js

MediaWiki界面页面
Cirno.9讨论 | 贡献2023年6月13日 (二) 08:19的版本

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

  • Firefox或Safari:按住Shift的同时单击刷新,或按Ctrl-F5Ctrl-R(Mac为⌘-R
  • Google Chrome:Ctrl-Shift-R(Mac为⌘-Shift-R
  • Internet Explorer或Edge:按住Ctrl的同时单击刷新,或按Ctrl-F5
  • Opera:Ctrl-F5
editUrl = 'https://www.medforest.cn/medf/api.php'
editOrigin = 'https://www.medforest.cn'
inlineEditorPageText = {}

function editThis(id) {
    var timuList = gDomTimuList()
	console.log(timuList)
	var order = timuList.order
	var timu = timuList.timu
    var dataJSON = timu[id]
    var inputBoxes = loadPreview(dataJSON)
    console.log(inputBoxes)
    // var o = eval('newInlineEditor(' + id + ',' + JSON.stringify(jsonData) + ',false,true).' + jsonData.type + '()')
    // render(id, jsonData.type, o,'#'+id,true)
    // console.log('加载题目:' + (id + 1) + '/' + dataLength)
    // console.log($("#edit-"+id).position().top)
    // $("html,body").animate({scrollTop:$("#edit-"+id).position().top},500)
}

function confirmEdit(id) {
    var pageTitle = $('#firstHeading').text()
    var data = formToJSON('#edit-' + id, true, 's')
    console.log(data)
    var formatedData = formatEditText(data)
    var template = JSONtoTemplate(formatedData)
    console.log(template)
    try {
        inlineEditorPageText = getOriginalText(pageTitle, formatedData, template)
    } catch (e) {
        alert('获取本页内容失败,请检查网络并重试!\n如反复故障请先手动编辑并联系管理员。\n错误内容:' + e)
    }

    if (inlineEditorPageText !== false) {
        loadModule(id, {before: inlineEditorPageText.inner, after: template})
    }

}

function getOriginalText(pageTitle, timuData, editedText) {
    var latestPageData = getLatestPageRevision(editUrl, pageTitle)
    console.log(latestPageData)
    var regMatchInner = new RegExp('(?<=\\{\\{' + timuData.type + '型题\\n\\|source=' + timuData.source + '\\n)[^}}]*(?=\\}\\}?)', 'g')
    var regMatchFull = new RegExp('(\\{\\{' + timuData.type + '型题\\n\\|source=' + timuData.source + '\\n)[^}}]*(\\}\\})', 'g')
    if (timuData.type === 'B' || timuData.type === 'C') {
        regMatchInner = new RegExp('(?<=\\{\\{' + timuData.type + '型题\\n\\|source=' + timuData.source + '\\n\\|sourceRange=' + timuData.sourceRange + '\n)[^}}]*(?=\\}\\}?)', 'g')
        regMatchFull = new RegExp('(\\{\\{' + timuData.type + '型题\\n\\|source=' + timuData.source + '\\n\\|sourceRange=' + timuData.sourceRange + '\n)[^}}]*(\\}\\})', 'g')
    }
    console.log(regMatchInner)
    var inner = latestPageData.match(regMatchInner)
    var full = latestPageData.match(regMatchFull)
    console.log(inner)
    console.log(full)
    if (inner.length === 1 && full.length === 1) {
        latestPageData = latestPageData.replace(regMatchInner, editedText)
        return {full: full[0], inner: inner[0], replacedText: latestPageData}
    } else {
        var warnText = '匹配到重复内容,请点击确认转为手动编辑(已作的编辑会丢失,请注意保存!)'
        for(var i=0;i<full.length;i++){
            warnText += '\n===匹配数据:'+i+'===\n'+full[i]
        }
        var editSource = confirm(warnText)
        if (editSource){
            var confirmFresh = confirm('已作的编辑会丢失,如未保存请返回!')
            if(confirmFresh){
                $('#ca-edit').children('a')[0].click()
            }
        }
        return false
    }
}

function loadModule(id, data) {
    document.body.style.overflow = 'hidden'
    var mask = $('<div id="mask" style="background: #000;background-size: cover; position: absolute; left: 0px; top: 0px; width: 100%; filter: alpha(opacity=30); opacity: 0.3; display: none; z-index: 2;"></div>')
    mask.css('height', ($(window).height() + $(window).scrollTop()) + 'px')
    mask.prependTo('body')
    $('#mask').fadeIn(500)
    confirmEditModule(id, data)
}

function dismissModule() {
    document.body.style.overflow = 'visible'
    $('#mask').fadeOut(700)
    $('.confirmEditContainer').fadeOut(300)
    setTimeout(function () {
        $('#mask').remove()
        $('.confirmEditContainer').remove()
    }, 1000)
}

function confirmEditModule(id, data) {
    if (data.before === undefined) {
        data.before = '无内容'
    } else if (data.after === undefined) {
        data.after = '无内容'
    }
    var div = $('<div style="position:absolute;top:0;left:0;width: 100%;overflow: scroll"></div>')
    div.css('height', ($(window).height() + $(window).scrollTop()) + 'px')
    var container = $('<div class="confirmEditContainer"></div>')
    var header = $('<div class="confirmEditHeader"><h3>以下为修改结果 请认真耐心检查核对!</h3><hr></div>')
    var changesContainer = $('<div class="changesContainer"></div>')
    var changes = $('<div class="changes"></div>')
    var before = $('<div class="before-edit change"><b>编辑前:</b><br><textarea>' + data.before + '</textarea></div>')
    var after = $('<div class="after-edit change"><b>编辑后:</b><br><textarea>' + data.after + '</textarea></div>')
    var appendix = $('<div class="confirmEditAppendix"><hr></div>')
    var btnSubmit = $('<button id="confirmEditAndSubmit" class="confirmEditBtn btn button-primary button-rounded">确认并提交更改</button>')
    var btnCancel = $('<button id="confirmEditDismiss" class="confirmEditBtn btn button-caution button-rounded">关闭本窗口</button>')
    changes.append(before, after)
    changes.appendTo(changesContainer)
    appendix.append(btnCancel, btnSubmit)
    container.append(header, changesContainer, appendix)
    container.appendTo(div)
    div.prependTo('body')
    $('#confirmEditDismiss').bind('click', function () {
        dismissModule()
    })
    $('#confirmEditAndSubmit').bind('click', function () {
        submitChanges(id)
        dismissModule()
    })
    var width = container.width()
    if ($(window).width() >= 600) {
        var left = ($(window).width() * 1 - width * 1) / 2
        var top = $(window).scrollTop() * 1 + $(window).height() * 0.15
    } else {
        var left = 5
        var top = $(window).scrollTop() * 1 + $(window).height() * 0.001
    }
    container.css('left', left + 'px')
    container.css('top', top + 'px')

    console.log(left)
    $('.confirmEditContainer').fadeIn(500)

}
function submitChanges(id) {
    var pageTitle = $('#firstHeading').text()
    var data = formToJSON('#edit-' + id, true, 's')
    console.log(data)
    var formatedData = formatEditText(data)
    var template = JSONtoTemplate(formatedData)
    console.log(template)
    var pageData = inlineEditorPageText
    if (pageData !== false) {
        var confirmEdit = confirm('即将开始上传编辑,您的编辑会对所有题库用户产生影响,请再次确认您的编辑是否有误。\n感谢您对医林拾薪题库建设的贡献!')
        if (confirmEdit) {
            try {
                var token = get_token(editUrl, editOrigin)
                if(!token[0]){
                    alert('获取用户TOKEN失败,请检查是否注册并登录或网络状态!\n如反复故障请先手动编辑并联系管理员。\n错误内容:' + e)
                    dismissModule()
                    return false
                }
            } catch (e) {
                alert('获取用户TOKEN失败,请检查是否注册并登录或网络状态!\n如反复故障请先手动编辑并联系管理员。\n错误内容:' + e)
                dismissModule()
                return false
            }
            try {
                var edit = editpage_common(false, editUrl, token, pageTitle, pageData.replacedText, undefined, 'tiku-edit|tiku-inline-editor'
                    , '来自网页内题目的题目编辑,题目类型:' + formatedData.type + ';题号:' + formatedData.source + ';题目:' + formatedData.title)
                if (!edit[0]){
                    alert('上传编辑失败,请检查是否注册并登录或网络状态!\n如反复故障请先手动编辑并联系管理员。\n错误类型:' + edit[1].code+'\n错误内容'+edit[1].info)
                    dismissModule()
                    return false
                }
            } catch (e) {
                alert('上传编辑失败,请检查是否注册并登录或网络状态!\n如反复故障请先手动编辑并联系管理员。\n错误内容:' + e)
                dismissModule()
                return false
            }

            if (edit) {
                location.reload()
            }
        }
    }
}
function formatEditText(json) {
    var result = {}
    var choices = {}
    var title = {}
    var answer = {}
    var explain = {}
    for (var i in json) {
        var data = formToJSON(i, true, 't')
        if ((result.id && result.type) === undefined) {
            result.id = data.id
            result.type = data.type
            result.source = data.source
        }
    }
    console.log(result)
    var transor = {
        A: function () {
            for (var i in json) {
                var data = formToJSON(i, true, 't')
                if (data.key === 'choices') {
                    choices[data.value] = json[i]
                } else {
                    result[data.key] = json[i].replace(/\\/g, '\\' + '\\').replace(/"/g, '\\' + '"')
                }
                console.log(data)
            }
            JSON.stringify(choices).match(/(?<=\{)([^}]*)(?=\})/g)
            result.choices = RegExp.$1
            console.log(result)
        },
        A2 :function () {
            transor.A()
        },
        X: function () {
            transor.A()
        },
        B: function () {
            for (var i in json) {
                var data = formToJSON(i, true, 't')
                eval(data.key + '[data.value] = json[i]')
                console.log(data)
            }
            JSON.stringify(choices).match(/(?<=\{)([^}]*)(?=\})/g)
            result.choices = RegExp.$1
            result.title = arrayToString(dicValueToList(title))
            result.sourceRange = dicValueToList(title).length
            result.answer = arrayToString(dicValueToList(answer))
            result.explain = arrayToString(dicValueToList(explain))
            console.log(result)
        },
        C: function () {
            transor.B()
        }
    }
    transor[result.type]()

    return result
}

function arrayToString(array) {
    var text = ''
    for (var i = 0; i < array.length; i++) {
        if (i != 0) {
            text += ','
        }
        text += '"' + array[i].trim() + '"'
    }
    return text
}

function dicValueToList(obj) {
    var result = []
    for (var i in obj) {
        result.push(obj[i])
    }
    return result
}

function formToJSON(selector, decode, mode) {
    var result = {}
    var data = ''
    if (mode === 's') {
        data = $(selector).serialize()
    } else if (mode === 't') {
        data = selector
    }

    console.log(data)
    var dataSplitted = data.split('&')
    for (var i = 0; i < dataSplitted.length; i++) {
        var value = dataSplitted[i].split('=')[1]
        var key = dataSplitted[i].split('=')[0]
        if (decode === true) {
            key = decodeURIComponent(key)
            value = decodeURIComponent(value)
        }
        result[key] = value
    }
    return result
}

function JSONtoTemplate(json, templateName) {
    var order = ['inputbox', 'title', 'choices', 'answer', 'explain', 'info']
    // var result = '{{'+templateName +'\n'
    var result = ''
    for (var i = 0; i < order.length; i++) {
        if (json[order[i]] !== undefined) {
            result += '|' + order[i] + '=' + json[order[i]].replace('\n') + '\n'
        }
    }
    // result += '}}\n\n'
    return result
}
function loadPreview(dataJSON){
    var timuJSON = dataJSON
    var order = ['source', 'pos', 'inputbox', 'sourceRange', 'title', 'choices', 'answer', 'explain', 'info']
    var chineseName = {
        'source':'编号'
        , 'pos':'挖空点符号'
        , 'inputbox':'是否显示输入框'
        , 'sourceRange':'子题目数'
        , 'title':'题目'
        , 'choices':'选项'
        , 'answer':'答案'
        , 'explain':'解释'
        , 'info':'信息'
    }
    var sametypes = ['source', 'pos', 'inputbox', 'sourceRange', 'info']
    var notsametypes = ['title', 'titlesList', 'optionsDic','optionsList', 'answer', 'answersList', 'explain', 'explainsList']
    var inputboxes = {
        type:timuJSON.type
        ,typeHTML:inputGroup('题型',timuJSON.type,  'preview-input-type','preview-input-type','preview-input-type')
        ,title:[]
        ,choices:[]
        , answer:[]
        , explain:[]
    }
    for(var i=0;i<sametypes.length;i++){
        if(timuJSON[sametypes[i]]===undefined){
            continue
        }else if(timuJSON[sametypes[i]]==='info'){
            inputboxes[sametypes[i]] = textareaGroup(chineseName[sametypes[i]],timuJSON[sametypes[i]],  'preview-textarea-'+sametypes[i],'preview-textarea-'+sametypes[i],'preview-textarea-'+sametypes[i])
        }else{
            inputboxes[sametypes[i]] = inputGroup(chineseName[sametypes[i]],timuJSON[sametypes[i]],  'preview-input-'+sametypes[i],'preview-input-'+sametypes[i],'preview-input-'+sametypes[i])
        }
        
    }

    //处理题目
    var titles = timuJSON.titlesList === undefined ? [timuJSON.title] :  timuJSON.titlesList
    inputboxes.titlesNum = titles.length
    for(var i=0;i<titles.length;i++){
        inputboxes.title.push(textareaGroup(chineseName['title'],titles[i], 'preview-textarea-title-'+i,'preview-textarea-title-'+i,'preview-textarea-title'))
    }

    //处理答案
    var answers = timuJSON.answersList === undefined ? [timuJSON.answer] :  timuJSON.answersList
    inputboxes.answersNum = answers.length
    for(var i=0;i<answers.length;i++){
        inputboxes.answer.push(inputGroup(chineseName['answer'],answers[i], 'preview-input-answer-'+i,'preview-input-answer-'+i,'preview-input-answer'))
    }

    //处理解释
    var explains = timuJSON.explainsList === undefined ? [timuJSON.explain] :  timuJSON.explainsList
    inputboxes.explainsNum = explains.length
    for(var i=0;i<explains.length;i++){
        inputboxes.explain.push(textareaGroup(chineseName['explain'],explains[i], 'preview-textarea-explain-'+i,'preview-textarea-explain-'+i,'preview-textarea-explain'))
    }

    //处理选项
    var options = timuJSON.optionsDicList === undefined ? [timuJSON.optionsDic] :  timuJSON.optionsDicList
    for(var i=0;i<options.length;i++){
        var dic = options[i]
        for(var k in dic){
            options[i][k] = inputGroup(chineseName['choices']+' '+k,options[i][k], 'preview-input-choice-'+i+'-'+k,'preview-input-choice-'+i+'-'+k,'preview-input-choice')
        }
    }
    inputboxes.choices = options
    console.log(inputboxes)

    return inputboxes
}

function inputGroup(label, value, name, id, classes , placeholder=''){
    return $('<div class="mb-1">'+
    '<div class="input-group">'+
    '<div class="input-group-prepend">'+
    ' <div class="input-group-text"><b>'+label+'</b></div>'+
    '</div>'+
    '<input type="text" class="form-control '+classes+'" id="'+id+'" name="'+name+'" placeholder="'+ placeholder +'" value="'+value+'">'+
    '</div>'+
    '</div>')
}
function textareaGroup(label, value, name, id, classes){
    return $('<div class="mb-1"><div class="input-group">'+
    '<div class="input-group-prepend">'+
      '<span class="input-group-text"><b>'+label+'</b></span>'+
    '</div>'+
        '<textarea class="form-control" '+classes+'" id="'+id+'" name="'+name+'">'+value+'</textarea>'+
    '</div></div>')
}

function newInlineEditor(id, json, hideButton, addHr, parent) {
    parent = parent !== undefined ? parent : ''
    if (addHr === undefined) {
        addHr = true
    }
    if (hideButton === undefined) {
        hideButton = false
    }
    var type = json.type
    var o = new Object()
    o.temp = {
        main: $('<form name="edit-' + id + '" id="edit-' + id + '" class="type' + type + ' timuEditContainer">' +
            '<div style="border: 2px solid red">' +
            '<p style="color: red" class="editorTipsItem"><b>编辑器Tips</b><br></p>' +
            '<p class="editorTipsItem"><b>-->请勿同时编辑多个题目</b></p>' +
            '<p class="editorTipsItem"><b>-->本功能处于实验阶段,如果多次出现错误请使用手动编辑</b></p>' +
            '<p class="editorTipsItem"><b>-->本编辑器目前仅可编辑A1/A2, B, C, X型题</b></p></div></form>'),
        subject: $('<div class="subject"></div>'),
        range: $('<div class="sourceRange"></div>'),
        info: $('<textarea name="id=' + id + '&source=' + json.source + '&type=' + type + '&key=info" class="info oo-ui-inputWidget-input"></textarea>'),
        titleCon: $('<div class="titleContainer oo-ui-widget oo-ui-inputWidget oo-ui-textInputWidget oo-ui-textInputWidget-type-text oo-ui-widget-enabled"></div>'),
        source: $('<p class="source"></p>'),
        title: $('<textarea name="id=' + id + '&source=' + json.source + '&type=' + type + '&key=title" class="title-edit oo-ui-inputWidget-input" ></textarea>'),
        options: $('<div class="options"></div>'),
        btn: $('<div class="edit-button-set"><button class="btn button-primary confirm-edit-btn">确认更改</button>' +
            '<button style="margin-left: 5px" class="btn button-caution cancel-edit-btn">取   消</button></div>'),
        ansCon: $('<div id="ansContainer" class="ansContainer oo-ui-widget oo-ui-inputWidget oo-ui-textInputWidget oo-ui-textInputWidget-type-text oo-ui-widget-enabled"></div>'),
        correct: $('<p style="display:inline;"><b>正确答案:</b></p><br><textarea name="id=' + id + '&source=' + json.source + '&type=' + type + '&key=answer" class="correctAnswer oo-ui-inputWidget-input"></textarea><br>'),
        explain: $('<p style="display:inline;"><b>解析: </b></p><br><textarea name="id=' + id + '&source=' + json.source + '&type=' + type + '&key=explain" class="explain oo-ui-inputWidget-input"></textarea><br>'),
        select: $('<select class="button-small button-rounded button"></select>'),
        subTitle: $('<div id=""></div>')
    }
    o.hideButton = hideButton
    o.parent = parent
    if (type !== 'A3' && type !== 'PD') {
        o.temp.btn.children('.confirm-edit-btn').bind("click", function () {
            confirmEdit(id)
        })
    }
    o.temp.btn.children('.cancel-edit-btn').bind("click", function () {
        $('.edit-button-set').remove()
        $('#edit-' + id).remove()
        $('#' + id).fadeIn()
    })
    o.A = function () {
        this.temp.source.text(json.source)
        this.temp.title.html(json.title)
        this.temp.correct.nextAll('.correctAnswer').val(json.answer)
        this.temp.explain.nextAll('.explain').val(json.explain)
        var options = formatAnsDic(json.choices)
        for (var k in options) {
            var label = '<label id="' + k + '" class="oo-ui-widget oo-ui-inputWidget oo-ui-textInputWidget oo-ui-textInputWidget-type-text oo-ui-widget-enabled">' +
                '<p style="display: inline"><b>选项 ' + k + ':</b></p>' +
                '<input class="oo-ui-inputWidget-input option-input" style="display: inline" name="id=' + id + '&source=' + json.source + '&type=' + type + '&key=choices&value=' + k + '"  class="options-edit" type="text" value="' + options[k] + '" />' +
                '</label>'
            this.temp.options.append(label)
        }
        this.temp.titleCon.append(this.temp.source, this.temp.title)
        this.temp.ansCon.append(this.temp.correct, this.temp.explain)
        this.temp.subject.append(this.temp.titleCon, this.temp.options)
        this.temp.main.append(this.temp.subject, this.temp.ansCon)

        if (addHr) {
            this.temp.btn.append('<hr>')
        }
        this.temp.main = $('<div></div>').append(this.temp.main, this.temp.btn)
        console.log(this.temp.main)
        return this.temp.main
    }
    o.A2 = function () {
        this.temp.source.text(json.source)
        this.temp.title.html(json.title)
        this.temp.correct.nextAll('.correctAnswer').val(json.answer)
        this.temp.explain.nextAll('.explain').val(json.explain)
        var options = formatAnsDic(json.choices)
        for (var k in options) {
            var label = '<label id="' + k + '" class="oo-ui-widget oo-ui-inputWidget oo-ui-textInputWidget oo-ui-textInputWidget-type-text oo-ui-widget-enabled">' +
                '<p style="display: inline"><b>选项 ' + k + ':</b></p>' +
                '<input class="oo-ui-inputWidget-input option-input" style="display: inline" name="id=' + id + '&source=' + json.source + '&type=' + type + '&key=choices&value=' + k + '"  class="options-edit" type="text" value="' + options[k] + '" />' +
                '</label>'
            this.temp.options.append(label)
        }
        this.temp.titleCon.append(this.temp.source, this.temp.title)
        this.temp.ansCon.append(this.temp.correct, this.temp.explain)
        this.temp.subject.append(this.temp.titleCon, this.temp.options)
        this.temp.main.append(this.temp.subject, this.temp.ansCon)

        if (addHr) {
            this.temp.btn.append('<hr>')
        }
        this.temp.main = $('<div></div>').append(this.temp.main, this.temp.btn)
        console.log(this.temp.main)
        return this.temp.main
    }
    o.A3 = function () {
        var subIDs = []
        var s = json.source * 1;
        var e = json.source * 1 + json.sourceRange * 1 - 1
        this.temp.range.text('第 ' + s + ' 到 ' + e + ' 题')
        for (var i = 0; i < json.title.length; i++) {
            subIDs.push(id + '-' + i)
            if (json.explain[i] == undefined) {
                json.explain[i] = '暂无解析'
            }
            var data = {
                "type": "A",
                "source": json.source + '-' + (i + 1),
                "title": json.title[i],
                "answer": json.answer[i],
                "explain": json.explain[i],
                "choices": json.choices[i],
            }
            var newA = newTimu(id + '-' + i, data, true, false).A()
            render(id + '-' + i, 'A', newA, this.temp.titleCon)
        }
        o.temp.btn.bind("click", function () {
            showChoiceAnswer(subIDs, type, json.answer)
        })
        this.temp.info.text(json.info)
        this.temp.subject.append(this.temp.range, this.temp.info, this.temp.titleCon)
        if (!hideButton) {
            this.temp.main.append(this.temp.btn)
        }
        this.temp.main.append(this.temp.subject)

        if (addHr) {
            this.temp.btn.append('<hr>')
        }
        return this.temp.main
    }
    o.B = function () {
        var s = json.source * 1;
        var e = json.source * 1 + json.sourceRange * 1 - 1
        this.temp.range.text('第 ' + s + ' 到 ' + e + ' 题')

        var options = formatAnsDic(json.choices)
        for (var k in options) {
            var label = '<li id="' + k + '">' + k + ':<input class="oo-ui-inputWidget-input" name="id=' + id + '&source=' + json.source + '&type=' + type + '&key=choices&value=' + k + '"  class="options-edit" type="text" value="' + options[k] + '" /></li>'
            this.temp.options.append(label)
            this.temp.select.append('<option value="' + k + '">' + k + '</option>')
        }
        for (var i = 0; i < json.title.length; i++) {
            var reg1 = /\(\)/g
            var text = '<textarea name="id=' + id + '&source=' + json.source + '&type=' + type + '&key=title&value=' + i + '" class="title-edit oo-ui-inputWidget-input" >' + json.title[i] + '</textarea>'
            this.temp.subTitle.attr('id', id + '-' + i)
            this.temp.source.text(s + i)
            this.temp.subTitle.html(this.temp.source.prop("outerHTML") + text)
            this.temp.titleCon.append(this.temp.subTitle.prop("outerHTML"))
        }
        var correctAnsEditor = $('<div class="correctAnsEditor"><p><b>编辑答案</b></p></div>')
        for (var i = 0; i < json.answer.length; i++) {
            correctAnsEditor.append('<span>' + (s + i) + ':' + '<input name="id=' + id + '&source=' + json.source + '&type=' + type + '&key=answer&value=' + i + '" value="' + json.answer[i] + '"></span><br>')
        }
        this.temp.correct = correctAnsEditor
        var explain = $('<div class="correctExpEditor"><p><b>编辑解释</b></p></div>')
        for (var i = 0; i < json.explain.length; i++) {
            explain.append('<span>' + (s + i) + ':' + '<textarea class="title-edit oo-ui-inputWidget-input" name="id=' + id + '&source=' + json.source + '&type=' + type + '&key=explain&value=' + i + '">' + json.explain[i] + '</textarea></span><br>')
        }
        this.temp.explain = explain

        this.temp.subject.append(this.temp.range, this.temp.options, this.temp.titleCon)

        this.temp.ansCon.append(this.temp.correct, this.temp.explain)
        this.temp.main.append(this.temp.subject, this.temp.ansCon)
        if (addHr) {
            this.temp.btn.append('<hr>')
        }
        this.temp.main = $('<div></div>').append(this.temp.main, this.temp.btn)
        return this.temp.main
    }
    o.C = function () {
        var s = json.source * 1;
        var e = json.source * 1 + json.sourceRange * 1 - 1
        this.temp.range.text('第 ' + s + ' 到 ' + e + ' 题')

        var options = formatAnsDic(json.choices)
        for (var k in options) {
            var label = '<li id="' + k + '">' + k + ':<input class="oo-ui-inputWidget-input" name="id=' + id + '&source=' + json.source + '&type=' + type + '&key=choices&value=' + k + '"  class="options-edit" type="text" value="' + options[k] + '" /></li>'
            this.temp.options.append(label)
            this.temp.select.append('<option value="' + k + '">' + k + '</option>')
        }
        for (var i = 0; i < json.title.length; i++) {
            var reg1 = /\(\)/g
            var text = '<textarea name="id=' + id + '&type=' + type + '&source=' + json.source + '&key=title&value=' + i + '" class="title-edit oo-ui-inputWidget-input" >' + json.title[i] + '</textarea>'
            this.temp.subTitle.attr('id', id + '-' + i)
            this.temp.source.text(s + i)
            this.temp.subTitle.html(this.temp.source.prop("outerHTML") + text)
            this.temp.titleCon.append(this.temp.subTitle.prop("outerHTML"))
        }
        var correctAnsEditor = $('<div class="correctAnsEditor"><p><b>编辑答案</b></p></div>')
        for (var i = 0; i < json.answer.length; i++) {
            correctAnsEditor.append('<span>' + (s + i) + ':' + '<input name="id=' + id + '&type=' + type + '&source=' + json.source + '&key=answer&value=' + i + '" value="' + json.answer[i] + '"></span><br>')
        }
        this.temp.correct = correctAnsEditor
        var explain = $('<div class="correctExpEditor"><p><b>编辑解释</b></p></div>')
        for (var i = 0; i < json.explain.length; i++) {
            explain.append('<span>' + (s + i) + ':' + '<textarea class="title-edit oo-ui-inputWidget-input" name="id=' + id + '&source=' + json.source + '&type=' + type + '&key=explain&value=' + i + '">' + json.explain[i] + '</textarea></span><br>')
        }
        this.temp.explain = explain
        this.temp.subject.append(this.temp.range, this.temp.titleCon, this.temp.options)
        this.temp.ansCon.append(this.temp.correct, this.temp.explain)
        this.temp.main.append(this.temp.subject, this.temp.ansCon)
        if (addHr) {
            this.temp.btn.append('<hr>')
        }
        this.temp.main = $('<div></div>').append(this.temp.main, this.temp.btn)
        return this.temp.main
    }
    o.X = function () {
        this.temp.source.text(json.source)
        this.temp.title.text(json.title)
        this.temp.correct.nextAll('.correctAnswer').text(json.answer)
        this.temp.explain.nextAll('.correctAnswer').text(json.explain)
        var options = formatAnsDic(json.choices)
        for (var k in options) {
            var label = '<label id="' + k + '">' + k + ':<input class="oo-ui-inputWidget-input" name="id=' + id + '&source=' + json.source + '&type=' + type + '&key=choices&value=' + k + '"  class="options-edit" type="text" value="' + options[k] + '" /></label>'
            this.temp.options.append(label)
        }

        this.temp.titleCon.append(this.temp.source, this.temp.title)
        this.temp.ansCon.append(this.temp.correct, this.temp.explain)
        this.temp.subject.append(this.temp.titleCon, this.temp.options)
        this.temp.main.append(this.temp.subject, this.temp.ansCon)
        if (addHr) {
            this.temp.btn.append('<hr>')
        }
        this.temp.main = $('<div></div>').append(this.temp.main, this.temp.btn)
        return this.temp.main
    }
    o.PD = function () {
        this.temp.source.text(json.source)
        this.temp.title.text(json.title)
        this.temp.explain.nextAll('.correctAnswer').text(json.explain)
        var ans = ''
        if (json.answer == 'T' || json.answer == '正确' || json.answer == '1' || json.answer == '√') {
            ans = '正确'
        } else if (json.answer == 'F' || json.answer == '错误' || json.answer == '0' || json.answer == '×') {
            ans = '错误'
        }
        this.temp.correct.nextAll('.correctAnswer').text(ans)
        o.temp.btn.bind("click", function () {
            showChoiceAnswer(id, 'A', ans)
        })
        this.temp.options.append('<label id="正确" style="display: inline;"><input name="singelChoice-' + id + '" type="radio" value="正确" />正确</label>' +
            '<label id="错误" style="display: inline;"><input name="singelChoice-' + id + '" type="radio" value="错误" />错误</label>')
        this.temp.titleCon.append(this.temp.source, this.temp.title)
        this.temp.ansCon.append(this.temp.correct, this.temp.explain)
        this.temp.subject.append(this.temp.titleCon, this.temp.options)
        if (!hideButton) {
            this.temp.main.append(this.temp.btn)
        }
        this.temp.main.append(this.temp.subject, this.temp.ansCon)

        if (addHr) {
            this.temp.main.append('<hr>')
        }
        return this.temp.main
    }
    o.TK = function () {
        this.temp.source.text(json.source)
        var form = $('<form id="form-' + id + '" class="title"></form>')
        var pos = json.pos
        var posReg = new RegExp(pos, 'g')
        var posCount = json.title.match(posReg).length
        for (var i = 0; i < posCount; i++) {
            json.title = json.title.replace(pos, '<input name="' + id + '-' + i + '" id="' + id + '-' + i + '" type="text" form="form-' + id + '"/>')
        }
        form.html(json.title)
        this.temp.title.text(json.title)
        this.temp.correct.nextAll('.correctAnswer').text(json.answer)
        this.temp.explain.nextAll('.correctAnswer').text(json.explain)

        this.temp.titleCon.append(this.temp.source, form)
        this.temp.ansCon.append(this.temp.correct, this.temp.explain)
        this.temp.subject.append(this.temp.titleCon, this.temp.options)
        if (!hideButton) {
            this.temp.main.append(this.temp.btn)
        }
        this.temp.main.append(this.temp.subject, this.temp.ansCon)

        if (addHr) {
            this.temp.main.append('<hr>')
        }
        return this.temp.main
    }
    o.MJ = function () {
        this.temp.source.text(json.source)
        this.temp.title.html(json.title + ':<span class="blur" tabindex="0" style="display:inline;outline=0;" onclick="">' + json.answer + '</span>')
        this.temp.titleCon.append(this.temp.source, this.temp.title)
        this.temp.subject.append(this.temp.titleCon, this.temp.options)
        this.temp.main.append(this.temp.subject)

        if (addHr) {
            this.temp.main.append('<hr>')
        }
        return this.temp.main
    }
    return o
}

//获取某个页面的历史版本
function getPageRevision(url, title, pageCount) {
    pageCount = pageCount !== undefined ? pageCount : 1
    var PARAMS = {
        "action": "query",
        "format": "json",
        "prop": "revisions",
        "titles": title,
        "utf8": 1,
        "rvprop": "content",
        "rvlimit": pageCount,
        "rvdir": "older",
        'origin': '*',
    }
    var isSuccess = {}
    $.ajax(
        {
            url: url,
            method: "post",
            async: false,
            data: PARAMS,
            timeout: 5000,
            success: function (results) {
                if ('-1' in results.query.pages) {
                    console.log('===无此页面===')
                    isSuccess = {isSuccess: false, result: results}
                } else {
                    isSuccess = {isSuccess: true, result: results}
                }
            }
        })
    return isSuccess
}

function getLatestPageRevision(url, title) {
    var pages = getPageRevision(url, title, 1)
    if (pages.isSuccess) {
        pages = pages.result.query.pages
        for (var key in pages) {
            var page = pages[key].revisions[0]['*']
        }
        return page
    } else {
        return false
    }
}

//编辑页面
function editpage_common(async, url, token, title, content, model, tags, summary, message) {
    async = async !== undefined ? async : true
    model = model !== undefined ? model : 'wikitext'
    tags = tags !== undefined ? tags : ''
    summary = summary !== undefined ? summary : ''
    message = message !== undefined ? message : ''
    var isSuccess = false
    var PARAMS = {
        "action": "edit",
        "format": "json",
        "title": title,
        "text": content,
        "token": token,
        'contentmodel': model,
        "summary": summary,
        "tags": tags,
    }
    $.ajax({
        url: url,
        method: "post",
        async: async,
        data: PARAMS,
        timeout: 5000,
        success: function (results) {
            var apiResult = results['edit']['result']
            if (apiResult == "Success") {
                isSuccess = [true]
                console.log("===editpage_common 成功===")
                // newMessage('成功:上传成功','#88F888')
            } else {
                isSuccess = [false,results['error']]
            }
            processingOff()
        },
        error: function () {
            // newMessage('失败:上传失败','#ffaca6')
        }

    })
    return isSuccess
}

//获取token
function get_token(url, origin) {
    var isSuccess = [false, '0']
    var PARAMS = {
        "action": "query",
        "format": "json",
        'meta': 'tokens',
        'origin': origin,
    }
    $.ajax(
        {
            url: url,
            method: "post",
            async: false,
            data: PARAMS,
            timeout: 5000,
            success: function (results) {
                var token = results.query.tokens.csrftoken
                if (token.length >= 5) {
                    isSuccess = {isSuccess: true, token: token}
                }
            }
        })
    return isSuccess
}