当前位置: 首页 > news >正文

网站是可以做的吗局域网网站建设

网站是可以做的吗,局域网网站建设,山东省市场监督管理局官网,网站 外包合同习惯了将解析写在代码注释#xff0c;这里就直接上代码啦#xff0c;里面用到的bxm-ui3组件库是博主基于element-Plus做的#xff0c;可以通过npm i bxm-ui3自行安装使用 // 识别方法#xff1a; // dom 当前识别数据所在区域, questionType 当前点击编辑选择的题目类型这里就直接上代码啦里面用到的bxm-ui3组件库是博主基于element-Plus做的可以通过npm i bxm-ui3自行安装使用 // 识别方法 // dom 当前识别数据所在区域, questionType 当前点击编辑选择的题目类型论述题、简答题要用 export const recognitionMethod (inputText, dom, questionType) {// 存一份let newInputText inputText.trim()let data {questionContent: ,questionType: ,questionAnalysis: ,answerList: []}// 解析答案let { result, newText } recognitionResult(newInputText)data.questionAnalysis result || // 单选多选题匹配const regx1 /(?:^\d、)?(.*?)\s*[\(]\s*([A-Za-z]*)\s*[\)]\s*([\s\S])/// 填空题匹配 若下划线上无答案则三个下划线为一个空const regx2 /(?:^\d、)?(.*?)[\_]\s*/g// const regx2 /(?:^\d、)?(.*?)(_{3})\s*/g// 判断题匹配 含有(√|×|对|错|正确|错误)const regx3 /(?:^\d、)?(.*?)\([√×对错正确错误])\\s*/let match newText.match(regx1)let match2 newText.match(regx2)let match3 newText.match(regx3)// 填空题去根据dom获取出来有下划线的部分即为答案let underLineList getUnderlineList(dom, newText)if (match) { // 基本的单选多选let answer match[2] || let optionsStr match[3]// 没有答案或者只有一个答案识别为单选多个答案为多选if (answer.length 1 || !answer.length) {data.questionType 00} else {data.questionType 01}// 单选/多选有选项if (optionsStr) {let options []let regexOption /[A-Za-z][.、]\s*(?:.*?)(\([^)]*\))?(?[A-Za-z][.、]|$)/gsulet matchOption nullwhile((matchOption regexOption.exec(optionsStr)) ! null) {options.push(matchOption[0].replace(/[A-Za-z][\.、]\s*/, ) (matchOption[1] ? matchOption[1] : ));}if (!options.length) {// 选项let optionRegx1 /[A-Za-z](\.|、)/options optionsStr.split(optionRegx1).filter(option { return ![, ., 、, ].includes(option) })}if (options.length) {options.map((item, index) {let obj {answerContent: item,answerOrd: ${index 1},answerRight: false,answerTitle: checkIndex(index)}// 单选if (data.questionType 00) {obj.answerRight (checkIndex(index) answer || checkIndex(index).toLocaleLowerCase() answer) ? 0 : false} else { // 多选let answers answer.split()obj.answerRight (answers.includes(checkIndex(index)) || answers.includes(checkIndex(index).toLocaleLowerCase())) ? 0 : 1}data.answerList.push(obj)})}}handleQuestionContent(match[1], newText, data)} else if (match3) { // 判断题data.questionType 03data.questionContent match3[1] let answer match3[2]for(let i 0; i 2; i) {let obj {answerOrd: ${i 1},answerRight: i 0 ? [对, 正确, √].includes(answer) ? i : false : [错, 错误, ×].includes(answer) ? i : false,answerTitle: i 0 ? 正确 : 错误}data.answerList.push(obj)}} else if (underLineList.length || match2) { // 填空题data.questionType 02let { questionContent, answerList } recognitionPack(newText, underLineList)data.questionContent questionContentdata.answerList answerList} else { // 简答题/论述题 没有匹配其余的直接处理为论述题或简答题// 当前点击编辑选择的题目类型如果不是论述题或简答题就默认设置为简答题data.questionType [04, 06].includes(questionType) ? questionType : 04let newStr // 去掉数字、开头if (/^\d、/.test(newInputText)) {newStr newInputText.replace(/^\d、/, )} else {newStr newInputText}// 一共6种可以解读为答案的内容let resultRegx /(答)|(答案)|(解析)|(分析)|(解答)|(回答)]/g// 给了解析if (resultRegx.test(newInputText)) {// [题干, 第一种, 第二种.....最后一个是根据前面某一种分割出来的答案]如果有解析就是正常的8个项let arr newStr.split(resultRegx)if (arr.length 8) {data.questionContent arr[0].trim()data.questionAnalysis arr[7].trim()} else {data.questionContent newInputTextdata.questionAnalysis }} else {data.questionAnalysis data.questionContent newStr.trim()}}return data }// 序号A~Z-----AA~AZ export const checkIndex (index) {let imn Math.floor((index 1)/26)let remainder (index 1) % 26if(imn 0 || (imn 1 remainder 0)) {// A~Zreturn String.fromCharCode(65 index)}else if((imn 1 || (imn 1 remainder 0)) imn 26){// AA、AB...BA...CA~ZZreturn (String.fromCharCode(65 (remainder ? (imn - 1) : (imn - 2))) String.fromCharCode(65 (remainder ? (remainder - 1) : 25)))} }// 解析答案 export const recognitionResult (inputText) {let result let newText inputText// 一共6种可以解读为答案的内容let resultRegx /(答)|(答案)|(解析)|(分析)|(解答)|(回答)]/g// 给了解析if (resultRegx.test(inputText)) {// [题干, 第一种, 第二种.....最后一个是根据前面某一种分割出来的答案]如果有解析就是正常的8个项let arr inputText.split(resultRegx)newText arr[0].trim()if (arr.length 8) {result arr[7]} else {result }}return { result, newText } }// 以下为填空题识别相关方法// 填空题识别 export const recognitionPack (inputText, underLineList) {let questionContent let answerList []let newStr /^\d、/.test(inputText) ? inputText.replace(/^\d、/, ) : inputText// 这是下划线上有内容if (underLineList.length) {underLineList.map((item, index) {let obj {answerOrd: index 1,answerMoreSelect: item.answerMoreSelect,answerTitle: 第${index 1}空答案,inputVisible: false,inputValue: ,}answerList.push(obj)// 将答案替换成___let end item.underLineStart item.answerLength// 这里加了三个_underLineList中剩余的项的unserLineStart都要处理否则会错位newStr newStr.substring(0, item.underLineStart) ___ newStr.substring(end)// 处理下一个的unserLineStartif (index underLineList.length - 1) {handleCheckUnderStart(index, underLineList)}})questionContent newStr} else { // 这是下划线上没有内容至少三个连续的_才识别成填空题避免部分单词识别错误例如COMMENT_NODE// 找到下划线let underRegx /(_{3})/g// let underRegx /[\_]/glet understrArr newStr.match(underRegx) || []for (let i 0; i understrArr.length; i) {// 将_替换成___let start newStr.indexOf(understrArr[i])let end start understrArr[i].lengthnewStr newStr.substring(0, start) ___ newStr.substring(end)}questionContent newStrlet index 0while(index understrArr.length) {answerList.push({answerOrd: ${index 1},answerMoreSelect: [],answerTitle: 第${index 1}空答案,inputVisible: false,inputValue: })index}}return {questionContent,answerList} }// 判断节点是否有下划线样式 function isLeafWithUnderline(node) {if (node.nodeType Node.TEXT_NODE) {return false}let style window.getComputedStyle(node)// textDecoration含有underline的一定有下划线return style.textDecoration style.textDecoration.includes(underline) }// 递归获取到最深层叶子节点遇到有下划线的节点直接视为叶子节点 function findDeepestNodes(node, deepestNodes []) {// 注释节点if (node.nodeType Node.COMMENT_NODE) { return deepestNodes }// 如果当前节点是文本节点或者具有下划线样式认为是叶子节点if (node.nodeType Node.TEXT_NODE || isLeafWithUnderline(node)) {deepestNodes.push(node)return deepestNodes // 返回当前节点不再深入遍历其子节点}// 遍历当前节点的所有子节点for (let child of node.childNodes) {findDeepestNodes(child, deepestNodes)}return deepestNodes }// 获取下划线列表 export const getUnderlineList (dom, newText) {let allTextNodes findDeepestNodes(dom)let list []let fullText // 找到下划线标签进行数据处理for(let index 0; index allTextNodes.length; index) {let node allTextNodes[index]// 文本节点获取内容和样式是不一样的let style node.nodeType Node.TEXT_NODE ? {} : window.getComputedStyle(node)fullText !node?.innerText ? node.textContent : node.innerText// 去掉数字开头fullText /^\d、/.test(fullText) ? fullText.replace(/^\d、/, ) : fullText// 有下划线的把下划线内容记录下来下划线位置记录下来if (style?.textDecoration style?.textDecoration.includes(underline) node.innerText ! ) {let obj {answerMoreSelect: node.innerText,answerTitle: 第${index 1}空答案,answerLength: node.innerText.length, // 答案长度underLineStart: fullText.length - node.innerText.length }list.push(obj)}}// 处理下划线连在一起但是为u标签时要合并成一个空if (list.length) {for(let i 0; i list.length; i) {// 连续的下划线if (i 0 list[i].underLineStart list[i - 1].underLineStart list[i - 1].answerLength) {list[i - 1] {answerMoreSelect: list[i - 1].answerMoreSelect list[i].answerMoreSelect, // 上一个的文本与当前文本组合answerTitle: 第${i}空答案, // 只留前一个所以下标是前一个的answerLength: list[i - 1].answerLength list[i].answerLength, // 上一个的文本长度与当前文本长度之和underLineStart: list[i - 1].underLineStart // 上一个文本的起始位置就是最终的起始位置}list.splice(i, 1)i--}}}return list }// 获取增加或减少了多少长度 export const getChangeLen (curUnderIndex, underList) {let addLen 0// 遍历当前以及之前的for(let i 0; i curUnderIndex; i) {// 当前下划线文本超出了下划线3个字符的长度替换成3个下划线之后会少了 answerLength-3 的长度后面的都需要往前移动answerLength-3个位置// 当前下划线文本少于下划线3个字符的长度替换成3个下划线之后会多了 3-answerLength 的长度后面的都需要往后移动3-answerLength个位置if (underList[i].answerLength ! 3) {addLen 3 - underList[i].answerLength // 变化的量可能正可能负}}return addLen }// 处理下划线起始位置 export const handleCheckUnderStart (curUnderIndex, underList) {if (curUnderIndex underList.length - 1) return// 获取需要变动的数量let changeLen getChangeLen(curUnderIndex, underList)// 处理当前的后一个即可underList[curUnderIndex 1].underLineStart changeLen }// 处理选择题的题干,获取到答案并更新选项(题干中有多处为答案或者由多处括号,括号里是字母但不一定是答案的情况) export const handleQuestionContent (content, allText, data) {if (!content || !allText) return let successContent // 去掉数字开头let newTextAll allText.replace(/^\d[.、]\s*/, )// 找到传入的题干在所有字符串中的位置let contentIndex newTextAll.indexOf(content)// 截取选项之前的内容比对let regx1 /^(.*?)(?\s*[A-Za-z]\.?[.、])/slet regx2 /^(.*?)(?[A-Za-z](?:(?:\s*\.\s*)|(?:\s*,\s*)|$))/slet matchArr1 newTextAll.match(regx1)let matchArr2 newTextAll.match(regx2)let matchArr []if (matchArr1 matchArr2) { // 两个都匹配比较谁匹配更接近matchArr matchArr1[0].length matchArr2[0].length ? matchArr1 : matchArr2} else if (matchArr1 || matchArr2) { // 有一个不能匹配直接获取能匹配那个matchArr matchArr1 ? matchArr1 : matchArr2} else {matchArr null}// 已有的题干和真正的不同,需要对已有信息进行修改if (matchArr matchArr.length 0 matchArr[0] ! content) {// 选项之前的内容successContent matchArr[0]// 去掉空行successContent successContent.replace(/(\r?\n\s*)/g, \n)let answers data.answerList.map(item { return item.answerTitle })// 从括号中找到真正的答案let answerKeyRegex /[\(]\s*([A-Z])\s*[\)]/glet contentArr successContent.split(answerKeyRegex)let resultContent let successAnswerArr []contentArr.map(item {let regxAnswer /^[A-Za-z]$/g// 仅为大小写字母if (regxAnswer.test(item)) {// 只有一个字母,并且字母在已生成的选项中,说明是其中的一个答案if (item.length 1 answers.includes(item.toLocaleUpperCase())) { // 替换成括号resultContent // 记录出真正的答案,在最后去编辑选项设置选中!successAnswerArr.includes(item.toLocaleUpperCase()) successAnswerArr.push(item.toLocaleUpperCase())} else if (item.length 1) { /*** 多个字母需要判断:* 1.字母有重复说明不是答案,直接还原* 2.字母不重复但是有字母不在已生成的选项中,直接还原* 3.字母不重复并且都在选项中为答案,同时将data中的试题类型修改为多选,选项默认选中项需要更改*/let itemArr item.split().filter(val { return val ! })let newArr [...new Set(JSON.parse(JSON.stringify(itemArr)))]if (itemArr.length ! newArr.length) { // 条件1resultContent ${item}} else {let isInner truefor(let i 0; i newArr.length; i) {newArr[i] newArr[i].toLocaleUpperCase()if (!answers.includes(newArr[i])) { // 条件2resultContent ${item}isInner falsebreak // 退出循环}}// 条件3,记录正确选项if (isInner) {// 替换成括号resultContent // 记录不重复的答案successAnswerArr [...new Set(successAnswerArr.concat(itemArr))]}}} else {// 还原resultContent ${item}}} else {resultContent item}})// 更新题干data.questionContent resultContent// 更新试题类型if (successAnswerArr.length 1) {data.questionType 01} else {data.questionType 00}// 处理选项data.answerList.map((item, index) {// 当前项为答案要默认选中if (successAnswerArr.includes(item.answerTitle)) {item.answerRight data.questionType 00 ? index : 0} else {item.answerRight data.questionType 00 ? false : 1}})} else {data.questionContent content } }这是我简单自定义的一个编辑器其实是一个contenteditable的div对里面内容进行简单处理了之后就可以使用了 templatediv classcustom-editor:style{height: height px}div classcustom-editor-placeholder :style{ display: content ? none : block }{{ placeholder }}/divdiv classcustom-editor-content idcusEditor:contenteditable!disabled/div/div /templatescript setup import { onMounted, ref } from vueconst props defineProps({height: {type: Number,default: 300},disabled: {type: Boolean,default: false},placeholder: {type: String,default: } })let content ref() let customEditor ref(null)const emits defineEmits([change])onMounted(() {customEditor.value document.getElementById(cusEditor)customEditor.value.addEventListener(input, (e) {content.value e.target.innerTextemits(change, customEditor.value.innerText)})// 自定义粘贴去掉图片更改文字颜色匹配系统颜色customEditor.value.addEventListener(paste, async (e) {e.preventDefault()let htmlContent // 尝试从现代API获取HTML内容if (e.clipboardData e.clipboardData.types.includes(text/html)) {htmlContent e.clipboardData.getData(text/html)} else if (e.originalEvent e.originalEvent.clipboardData e.originalEvent.clipboardData.getData) {htmlContent e.originalEvent.clipboardData.getData(text/html)} else {htmlContent (e.clipboardData || window.clipboardData).getData(text)}// 获取粘贴的纯文本便于后面比较避免粘贴内容不全let pasteText (e?.clipboardData || window?.clipboardData)?.getData(text)// 保存当前的选区const selection window.getSelection()const range selection.getRangeAt(0)// 使用DOMParser解析粘贴的HTML内容const parser new DOMParser()const doc parser.parseFromString(htmlContent, text/html)/** 重要* 处理文本节点一定要替换掉font节点* 因为font节点获取内容会包括了css样式比如字体、颜色、大小等等转换成字符串的结果* 无论是innerText还是textContent都是一样的结果严重影响填空题识别*/walkTree(doc.body) // ********重要*********// 直接创建一个div存放现在无法找到又能在同一行又能保留原先样式粘贴进去// 要在原有文字后面直接挨着来需要清除文字样式会导致选择题无法识别let div document.createElement(div)let childNodes doc.body.childNodeschildNodes.forEach(node {if (![Node.ATTRIBUTE_NODE, Node.COMMENT_NODE, Node.DOCUMENT_TYPE_NODE, Node.DOCUMENT_FRAGMENT_NODE].includes(node.nodeType)) {div.appendChild(node)}})// 移除所有的img标签const imgs div.querySelectorAll(img)imgs.forEach(img img.remove())// 更改文字样式匹配系统颜色setBodyTextStyle(div, var(--el-text-color), 12px, transparent)// 粘贴内容不全时进行修正if (pasteText div.innerText ! pasteText) {div.innerText pasteText}// 在原有位置插入处理过的内容range.deleteContents() // 如果要替换选中内容则先删除range.insertNode(div) // 插入编辑器range.collapse(true)selection.removeAllRanges()selection.addRange(range)content.value customEditor.value.innerTextemits(change, customEditor.value.innerText)}) })// 设置文字颜色以及文字大小匹配系统颜色 const setBodyTextStyle (body, color, fontSize, bgc) {// 创建一个递归函数来遍历并设置颜色function setColorRecursively(element) {if (element.nodeType Node.ELEMENT_NODE) {// 如果是元素节点for (let i 0; i element.childNodes.length; i) {setColorRecursively(element.childNodes[i])}// 设置当前元素的文本颜色if (element.style) {element.style.color colorelement.style.fontSize fontSizeelement.style.backgroundColor bgcelement.style.padding 0element.style.margin 0element.style.lineHeight 20 px}} else if (element.nodeType Node.TEXT_NODE) {// 如果是文本节点查找其父元素并设置颜色if (element.parentElement.style) {element.parentElement.style.color colorelement.parentElement.style.fontSize fontSizeelement.parentElement.style.backgroundColor bgcelement.parentElement.style.padding 0element.parentElement.style.margin 0element.parentElement.style.lineHeight 20 px}}}// 从body开始遍历setColorRecursively(body) }// 清理文本节点并转换所有非span元素的文本节点为span比如是font const walkTree (node) {if (node.nodeType Node.TEXT_NODE node.tagName FONT) {var span document.createElement(span)while (node.firstChild) {span.appendChild(node.firstChild)}node.parentNode.replaceChild(span, node)} else if (node.nodeType Node.ELEMENT_NODE) {for (var i 0; i node.childNodes.length; i) {walkTree(node.childNodes[i])}} }const clear () {content.value customEditor.value.innerText emits(change, customEditor.value.innerText) }defineExpose({customEditor,clear }) /scriptstyle langscss scoped .custom-editor {position: relative;width: 100%;padding: 16px;z-index: 10000;.custom-editor-placeholder {position: absolute;top: 16px;left: 16px;color: var(--el-text-color-placeholder);opacity: .5;font-size: 13px;font-size: SourceHanSansCN Regular;z-index: 10001;line-height: 23px;}.custom-editor-content {position: relative;width: 100%;height: 100%;overflow-y: auto;outline: none;border: none;box-shadow: none;z-index: 10002;line-height: 23px;} } span {font-size: 12px;font-family: SourceHanSansCN Regular; } /style组件使用示例 div classtext-titlespan输入区/spandivbxm-buttonsoplain:disabledbtnDisabled || !inputTextclickhandleCleari classbxm-icon-fail btn-icon/i清 空/bxm-buttonbxm-buttontypeprimaryplain:disabledbtnDisabled || !inputTextclickhandleRecognitioni classbxm-icon-switch btn-icon/i识 别/bxm-button/div /div CustomEditor :datainputText refeditor:disabledbtnDisabled:height600stylemargin-top: 16pxplaceholder请将试题粘贴在此处点击识别系统将自动解析题干及选项。change(val) { inputText val } /CustomEditor// 识别 const handleRecognition () {let data recognitionMethod(inputText.value, editor.value.customEditor, props.questionType)formDataText.value.bxmAnswerList JSON.parse(JSON.stringify(data.answerList || []))formDataText.value.bxmQuestionDetail.questionContent data.questionContentformDataText.value.bxmQuestionDetail.questionType data.questionTypeformDataText.value.bxmQuestionDetail.questionAnalysis data.questionAnalysis }const handleClear () {editor.value editor.value.clear() }自己做的试题编辑的组件 !--根据最新ui设计写的试题编辑-- templateel-form classedit-question-box:modelformData:disableddisabled || importLoadingrefruleFormlabel-width100pxsubmit.native.preventdiv classtips one-line v-if[02].includes(formData.bxmQuestionDetail.questionType)i classbxm-icon-info tip-icon/i提示填空用连续三个下划线_表示1个填空题最多设置5个空若一个空有多个参考答案匹配任意一个都算正确。/divel-form-item propbxmQuestionDetail.questionContent:keygetUniqueCode():rules[{ required: true, message: 请填写题干, trigger: blur }]template #labeldiv v-ifcanChangeType !qustionId classquestionContent-custom-label stylewidth: 100%el-dropdown triggerclick sizemini:disableddisabled || importLoadingcommandhandlequestionTypeChange($event, 00)bxm-tag typeprimary plain stylecursor: pointer【{{ title }}】/bxm-tagtemplate #dropdownel-dropdown-menuel-dropdown-item v-foritem in questionTypeList :keyitem.key :commanditem.value{{ item.key }}题/el-dropdown-item/el-dropdown-menu/template/el-dropdown/divtemplate v-else【{{ title }}】/template/templateel-input v-modelformData.bxmQuestionDetail.questionContent typetextarea :rows3 placeholder请输入题干/el-input/el-form-itemel-form-item label【图片】 propfileListdiv classuplod-boxel-uploadrefuploadv-model:file-list:formData.fileListactionaction:multipletrue:auto-uploadfalselist-typepicture:show-file-listfalseaccept.jpeg,.jpg,.png:disableddisabled || importLoading:on-changehandleImageChange:on-previewhandlePictureCardPreview:on-removehandleRemovebxm-button typeprimary :loadingimportLoading :disableddisabled || importLoading iconUpload选择文件/bxm-buttontemplate #tipdiv classel-upload__tip支持上传多个jpeg、jpg、png文件单个文件不超过10M。/div/template/el-upload!-- upload无法回显 自己画一个回显 --ul classimg-boxli v-for(file, index) in formData.fileList:keyindex fileListclassimg-itemimg :srcfile.url altdiv classitem-name clickhandlePictureCardPreview(file)el-icon classitem-name-iconDocument //el-iconspan classitem-name-label{{ file.fileName }}/span/divel-icon v-if!(disabled || importLoading) classitem-close clickhandleRemove(file)Close //el-icon/li/ul/div/el-form-itemdiv classedit-question-content!-- 单选/多选 --template v-if[00, 01].includes(formData.bxmQuestionDetail.questionType)el-form-item v-for(item, index) in formData.bxmAnswerList :keyindex getUniqueCode():propformData.bxmAnswerList.${index}.answerContent:rules[{required: false,validate: (rule, value, callback) handleValidContent(callback, index),trigger: blur}]template #labeldiv classquestion-custom-labelsvg-icon icon-classsort classlabel-icon/svg-iconspan classlabel-title{{ item.answerTitle }}./span/div/templateel-inputv-model.trimitem.answerContentclearableplaceholder请输入选项内容maxlength50show-word-limitstylewidth: 50%; margin-right: 10px;/el-input!-- 单选 --template v-if[00].includes(formData.bxmQuestionDetail.questionType)el-radiov-modelitem.answerRight:labelindexchangechangeAnswerRight($event, index)nbsp;/el-radio/template!-- 多选 --template v-elseel-checkbox v-modelitem.answerRight true-label0 false-label1:disableddisablednbsp;/el-checkbox/templatediv classset-answerspan classset-answer-title v-ifshowResult(item, index)设为答案/span /div!-- 操作按钮 --div classanswer-btn-boxtemplate v-ifindex 0 formData.bxmAnswerList.length 1el-tooltip content上移 placementtopbxm-button iconTop linktypeprimaryclickupAnswer(index)/bxm-button/el-tooltipel-divider directionvertical stylemargin-left: 2px;/el-divider/templatetemplate v-ifindex formData.bxmAnswerList.length - 1 formData.bxmAnswerList.length 1el-tooltip content下移 placementtopbxm-button iconBottom linktypeprimaryclickdownAnswer(index)/bxm-button/el-tooltipel-divider directionvertical stylemargin-left: 2px;/el-divider/templateel-tooltip content删除 placementtopbxm-button iconDelete linktypeprimaryclickdelAnswer(index)/bxm-button/el-tooltip/div/el-form-item/template!-- 填空 --template v-else-if[02].includes(formData.bxmQuestionDetail.questionType)el-form-itemv-for(item, index) in formData.bxmAnswerList :keyindex getUniqueCode():propformData.bxmAnswerList.${index}.answerContent:rules[{required: false,validate: (rule, value, callback) handleValidContent(callback, index),trigger: change}]template #labeldiv classquestion-custom-labelsvg-icon icon-classsort classlabel-icon/svg-iconspan classlabel-title{{ index 1 }}./span/div/templatediv classpack-input-boxel-tagv-for(tag, tagIndex) in item.answerMoreSelect:keytagtypeinfo:closable!disabled:disable-transitionsfalsestylemargin: 2px 4px;closehandleCloseTag(tag, index, tagIndex)el-tooltip v-iftag.length 10 :contenttag placementtop{{ tag.slice(0, 10) }}.../el-tooltiptemplate v-else{{ tag }}/template/el-tagel-inputv-ifitem.inputVisiblev-model.trimitem.inputValue:refsaveTagInput${index}classinput-new-tagstyleheight: 25pxkeyup.enter.nativehandleInputConfirm(index)blurhandleInputConfirm(index)/el-inputel-tooltip v-else content新增 placementtopbxm-buttoniconPlus typeprimarylinkstylemargin-left: 10pxclickshowInput(index)/bxm-button/el-tooltip/divel-tooltip content删除 placementtopbxm-button typeprimary icondelete linkstylemargin-left: 10pxclickdelAnswer02(index)/bxm-button/el-tooltip/el-form-item/template!-- 判断 --template v-else-if[03].includes(formData.bxmQuestionDetail.questionType)el-form-itemel-radio v-modelitem.answerRight v-for(item, index) in formData.bxmAnswerList :keyindex:labelindex stylemargin-left: 16pxchangechangeAnswerRight($event, index){{ item.answerTitle }}el-icon stylemargin-left: 5pxCheck v-ifitem.answerTitle 正确 /Close v-else //el-icon/el-radio/el-form-item/template/div!-- 添加按钮 --bxm-button v-if[00, 01].includes(formData.bxmQuestionDetail.questionType)typeprimarylinkiconPlusclassradio-add-btnclickaddAnswer(formData.bxmAnswerList.length - 1)添加选项/bxm-buttonbxm-button v-if[02].includes(formData.bxmQuestionDetail.questionType)typeprimarylinkiconPlusclassradio-add-btnclickaddAnswer02添加答案/bxm-buttondiv v-if![04, 06].includes(formData.bxmQuestionDetail.questionType) classdash-line/divdiv classedit-question-bottomel-form-item v-if![04, 06].includes(formData.bxmQuestionDetail.questionType) label答案: stylemargin-bottom: 8pxtemplate v-if[00, 01, 03].includes(formData.bxmQuestionDetail.questionType){{ selectedAnswer }}el-icon stylemargin-left: 5px v-ifformData.bxmQuestionDetail.questionType 03Check v-ifselectedAnswer 正确 /Close v-else-ifselectedAnswer 错误 //el-icon/templatetemplate v-elsespan v-for(item, index) in formData.bxmAnswerList :keyindex getUniqueCode()span classp-lr-5{{ index 1 }}./spanspan v-for(val, valIndex) in item.answerMoreSelect :keyvalIndex spanspan classanswer-span p-lr-5{{ val }}/spanspan v-ifvalIndex ! item.answerMoreSelect.length - 1 classp-lr-5//span/span/span/template/el-form-itemel-form-item label解析: propsquestionAnalysis :keygetUniqueCode()el-input v-modelformData.bxmQuestionDetail.questionAnalysis typetextarea :rows8 classquestion-content-inputplaceholder请输入解析/el-input/el-form-item/div/el-form /templatescript setup import { ref, reactive, onMounted, watch, nextTick, computed, onBeforeMount } from vue import { BxmMessage, BxmMessageBox } from bxm-ui3 // 下面几个方法就自己写写吧 import { validateIsNull } from utils/validate import { findItemByValue } from ../../consts/index import { checkIndex } from ../consts/index const props defineProps({questionType: {type: String,default: 00},disabled: {type: Boolean,default: false},data: {type: Object,default: () {return {}}},qustionId: {type: [String, Number],default: },// 是否能够更改试题类型canChangeType: {type: Boolean,default: false} })let formData ref({fileList: [],bxmQuestionDetail: {questBankId: ,questionAnalysis: ,questionContent: ,questionType: ,},bxmAnswerList: [{answerContent: ,answerOrd: 1,answerRight: false,answerTitle: A,questDetailId: }] })let questionTypeList reactive([{value: 00,key: 单选,disabled: false},{value: 01,key: 多选,disabled: false},{value: 02,key: 填空,disabled: false},{value: 03,key: 判断,disabled: false},{value: 04,key: 简答,disabled: false},{value: 06,key: 论述,disabled: false} ]) const ruleForm ref(null)let resultFileList reactive([]) let importLoading ref(false) let dialogImage ref(false) let currentIndex ref(0) let upload ref(null)const emits defineEmits([change, importChange])const showResult computed(() {return (data, index) {// 单选时if (props.questionType 00) {return data.answerRight index} else {return data.answerRight 0 || formData.value.bxmAnswerList[index].answerRight 0}} })const selectedAnswer computed(() {let result if (props.questionType 03) {formData.value.bxmAnswerList.map(item {if (item.answerRight ! false) {result item.answerTitle}})} else if ([00, 01].includes(props.questionType)) {let filterList []if (props.questionType 01) {filterList formData.value.bxmAnswerList.filter(item { return item.answerRight item.answerRight ! 1 }) || []} else {filterList formData.value.bxmAnswerList.filter((item, index) { return item.answerRight index }) || []}result filterList.map(item { return item.answerTitle }).join(、)}return result })const title computed(() {return findItemByValue(questionTypeList, formData.value.bxmQuestionDetail.questionType).key 题 })const handleValidContent (callback, index) {if ([00, 01].includes(props.questionType)) {let curValue formData.value.bxmAnswerList[index].answerContentif (!curValue) {return callback(请填写选项内容)}if (curValue.length 50) {return callback(选项${checkIndex(index)}内容长度超出50请修改)}let list formData.value.bxmAnswerList.filter(item { return item.answerContent curValue })if (list.length 1) {return callback(选项不可重复)}} else if ([02].includes(props.questionType)) {let curAnswer formData.value.bxmAnswerList[index].answerMoreSelectlet list Array.isArray(curAnswer) curAnswer.length ? curAnswer : curAnswer.split(,)let newList list.filter(item { return item formData.value.bxmAnswerList[index].inputValue })if (newList 0) {return callback(同一空答案不可重复)}}return callback() }// 处理数据 const handleFormData (data) {nextTick(() {formData.value.bxmQuestionDetail Object.assign({}, data.bxmQuestionDetail)let bxmAnswers JSON.parse(JSON.stringify(data.bxmAnswerList ? data.bxmAnswerList : data.bxmAnswers))for (const val of bxmAnswers) {val.answerOrd parseInt(val.answerOrd)if ([00, 03].includes(formData.value.bxmQuestionDetail.questionType)) {if (val.answerRight 0 || val.answerRight val.answerOrd - 1) { // 为答案val.answerRight ! val.answerOrd - 1 (val.answerRight val.answerOrd - 1)} else {val.answerRight false}} else if (formData.value.bxmQuestionDetail.questionType 02) {val.answerMoreSelect Array.isArray(val.answerMoreSelect) ? val.answerMoreSelect : val.answerMoreSelect.split(,)val.inputVisible falseval.inputValue // 此处用map更新没有用for实时for(let i 0; i val.answerMoreSelect.length; i) {val.answerMoreSelect[i] val.answerMoreSelect[i].trim()}}// 去除选项、填空答案前后空格if (val.answerContent) {val.answerContent val.answerContent.trim()}}// 判断题如果没有答案加上默认的if (!bxmAnswers.length formData.value.bxmQuestionDetail.questionType 03) {bxmAnswers [{answerOrd: 1,answerRight: false,answerTitle: 正确}, {answerOrd: 2,answerRight: false,answerTitle: 错误}]}formData.value.bxmAnswerList JSON.parse(JSON.stringify(bxmAnswers))// 文件列表处理formData.value.fileList []resultFileList []if (Array.isArray(data.fileList) data.fileList.length) {data.fileList.map(item {item.url window.location.origin / item.filePath;// isOnline: 是否是编辑时后端直接返回的图片formData.value.fileList.push({ ...item, isOnline: true })// 存储数据resultFileList.push({isDelete: false,fileName: item.fileName,filePath: item.filePath,isOnline: true})})}}) }// 类型变化 const handlequestionTypeChange (val, type) {if (val formData.value.bxmQuestionDetail.questionType) { return false }if (type 00) {// 单选/多选相互切换时加是否保留选项提示if ([00, 01].includes(formData.value.bxmQuestionDetail.questionType) [00, 01].includes(val)) {BxmMessageBox.confirm(确认更改试题类型, 提示, {confirmButtonText: 确定,cancelButtonText: 取消,type: warning}).then(() {formData.value.bxmQuestionDetail.questionType valBxmMessageBox.confirm(是否保留选项信息保留时若为多选切换为单选将只保留第一个选中项为答案若不保留将清空选项信息, 提示, {confirmButtonText: 保留选项,cancelButtonText: 清空选项,type: warning}).then(() {let selAnswer formData.value.bxmAnswerList.filter((item, index) { return val 00 ? item.answerRight 0 : item.answerRight index })let selAnswerOrds selAnswer.map(item { return item.answerOrd })formData.value.bxmAnswerList.map((item, index) {// 多选切换为单选if (val 00) {selAnswerOrds selAnswerOrds.length 1 ? [selAnswerOrds[0]] : selAnswerOrdsitem.answerRight selAnswerOrds.includes(item.answerOrd) ? index : false} else { // 单选切换为多选item.answerRight selAnswerOrds.includes(item.answerOrd) ? 0 : 1}})}).catch(() {setAnswerData()})}).catch(() {})} else {BxmMessageBox.confirm(切换试题类型将只保留题干信息是否继续, 提示, {confirmButtonText: 确定,cancelButtonText: 取消,type: warning}).then(() {formData.value.bxmQuestionDetail.questionType valsetAnswerData()}).catch(() {})}} else {formData.value.bxmQuestionDetail.questionType valsetAnswerData()}}// 设置答案数据 const setAnswerData () {// 判断if (formData.value.bxmQuestionDetail.questionType 03) {formData.value.bxmAnswerList [{answerOrd: 1,answerRight: false,answerTitle: 正确}, {answerOrd: 2,answerRight: false,answerTitle: 错误}]} else if (formData.value.bxmQuestionDetail.questionType 02) { // 填空formData.value.bxmAnswerList [{answerOrd: 1,answerMoreSelect: [],answerTitle: 第1空答案,inputVisible: false,inputValue: }]} else if (formData.value.bxmQuestionDetail.questionType 01) { // 多选formData.value.bxmAnswerList [{answerContent: ,answerOrd: 1,answerRight: 1,answerTitle: A,questDetailId: }]} else if (formData.value.bxmQuestionDetail.questionType 00) { // 单选formData.value.bxmAnswerList [{answerContent: ,answerOrd: 1,answerRight: false,answerTitle: A,questDetailId: }]} }watch(() props.questionType, (val) {handlequestionTypeChange(val) }, {immediate: true,deep: true })watch(() props.data, (obj) {handleFormData(Object.assign({}, obj)) }, {immediate: true,deep: true })watch(() importLoading.value, (val) {emits(importChange, val) }, {immediate: true,deep: true })// 处理文件删除 const handleBatchDelFile async (type) {if (!resultFileList.length) { return }let list []if (type 00) { // 点击的取消按钮if (!props.qustionId) { // 新增// 删除全部文件list resultFileList} else { // 编辑// 删除不是后端返回的文件list resultFileList.filter(item { return item.isOnline false })}} else { // 点的确定// 删除用户点过删除的文件list resultFileList.filter(item { return item.isDelete true })}if (list.length) {let params {filePathList: list.map(item { return item.filePath })}await deleteFileList(params).catch(() {})} }// 当前项往下增加一项 const addAnswer (index) {formData.value.bxmAnswerList.splice(index 1, 0, {answerContent: ,answerOrd: ,answerRight: formData.value.bxmQuestionDetail.questionType 00 ? false : 1,answerTitle: ,questDetailId: })for (const index in formData.value.bxmAnswerList) {const val formData.value.bxmAnswerList[index]val.answerTitle checkIndex(parseInt(index))val.answerOrd parseInt(index) 1} }// 将当前项往上提一个 const upAnswer (index) {if (index ! 0) {formData.value.bxmAnswerList[index] formData.value.bxmAnswerList.splice(index - 1, 1, formData.value.bxmAnswerList[index])[0];for (const index in formData.value.bxmAnswerList) {const val formData.value.bxmAnswerList[index]val.answerTitle checkIndex(parseInt(index))val.answerOrd parseInt(index) 1if (formData.value.bxmQuestionDetail.questionType 00 val.answerRight ! false) {val.answerRight parseInt(index)}}} }// 删除当前项 const delAnswer (index) {if (formData.value.bxmAnswerList.length ! 1) {formData.value.bxmAnswerList.splice(index, 1)for (const index in formData.value.bxmAnswerList) {const val formData.value.bxmAnswerList[index]val.answerTitle checkIndex(parseInt(index))val.answerOrd parseInt(index) 1}} }// 将当前项往下降一个 const downAnswer (index) {if (index ! formData.value.bxmAnswerList.length - 1) {formData.value.bxmAnswerList[index] formData.value.bxmAnswerList.splice(index 1, 1, formData.value.bxmAnswerList[index])[0];for (const index in formData.value.bxmAnswerList) {const val formData.value.bxmAnswerList[index]val.answerTitle checkIndex(parseInt(index))val.answerOrd parseInt(index) 1if (formData.value.bxmQuestionDetail.questionType 00 val.answerRight ! false) {val.answerRight parseInt(index)}}} }// 修改答案值 const changeAnswerRight (value, index) {for (const i in formData.value.bxmAnswerList) {formData.value.bxmAnswerList[i].answerRight false // 未选中的存为false保存时改为0选中的改为1}formData.value.bxmAnswerList[index].answerRight index }// 填空题增加一个空位 const addAnswer02 () {if (formData.value.bxmAnswerList.length 5) {formData.value.bxmAnswerList.push({answerMoreSelect: [],inputVisible: false,inputValue: })reSort()} }// 填空题删除一个空位 const delAnswer02 (index) {formData.value.bxmAnswerList.splice(index, 1)reSort() }// 填空题增加或修改后答案重新排序 const reSort () {for (const index in formData.value.bxmAnswerList) {const val formData.value.bxmAnswerList[index]val.answerOrd parseInt(index) 1val.answerTitle 第${parseInt(index) 1}空答案} }// 填空题删除tag const handleCloseTag (tag, index, tagIndex) {// 原先的有问题// formData.value.bxmAnswerList[index].answerMoreSelect.splice(formData.value.bxmAnswerList.indexOf(tag), 1)// 新的formData.value.bxmAnswerList[index].answerMoreSelect.splice(tagIndex, 1) }// 显示新增tag输入框 const showInput (index) {formData.value.bxmAnswerList[index].inputVisible true }// 新增tag const handleInputConfirm (index) {const inputValue formData.value.bxmAnswerList[index].inputValueif (inputValue) {if (formData.value.bxmAnswerList[index].answerMoreSelect.includes(inputValue)) {BxmMessage({type: warning,message: 同一空答案中不能有重复项请修改})return}formData.value.bxmAnswerList[index].answerMoreSelect.push(inputValue)}formData.value.bxmAnswerList[index].inputVisible falseformData.value.bxmAnswerList[index].inputValue }const resetTemp () {formData.value.bxmQuestionDetail {questBankId: props.libraryId,questionAnalysis: ,questionContent: ,questionType: }formData.value.bxmAnswerList [{answerContent: ,answerOrd: 1,answerRight: false,answerTitle: A,questDetailId: }] }// 校验问题 const validateForm async () {let flag await ruleForm.value.validate()if (flag true) {let bxmAnswerListNew JSON.parse(JSON.stringify(formData.value.bxmAnswerList)) // 深拷贝一下防止修改自身时填空题类型的tag报错// 校验题干if (!validateIsNull(formData.value.bxmQuestionDetail.questionContent)) {BxmMessage({type: warning,message: 请填写题干})return false}let answerRightValidate falseif ([00, 01, 03].includes(formData.value.bxmQuestionDetail.questionType)) {// 单选/多选选项重复校验if ([00, 01].includes(formData.value.bxmQuestionDetail.questionType)) {// 选项校验for (let i 0; i bxmAnswerListNew.length; i) {let msg handleValidContent((msg) { return msg }, i)if (msg) {BxmMessage({type: warning,message: msg})return false}}let answerContent [...new Set(bxmAnswerListNew.map(item { return item.answerContent }))]if (answerContent.length bxmAnswerListNew.length) {BxmMessage({type: warning,message: 选项不可重复})return false}}// 校验判断题答案是否选择了答案if (formData.value.bxmQuestionDetail.questionType 03) {let answerRights [...new Set(bxmAnswerListNew.map(item { return item.answerRight }))]if (answerRights.length bxmAnswerListNew.length) {BxmMessage({type: warning,message: 请选择一个答案})return false}}for (const val of bxmAnswerListNew) {if ([00, 01].includes(formData.value.bxmQuestionDetail.questionType) !validateIsNull(val.answerContent)) {BxmMessage({type: warning,message: 请先将选项内容填写完整})return false}if (formData.value.bxmQuestionDetail.questionType 00) {if (val.answerRight false) {val.answerRight 1} else {val.answerRight 0answerRightValidate true}}if (formData.value.bxmQuestionDetail.questionType 03) {if (val.answerRight false) {val.answerRight 1answerRightValidate true} else {val.answerRight 0}}if (formData.value.bxmQuestionDetail.questionType 01 val.answerRight 0) {answerRightValidate true}}if (!answerRightValidate) {BxmMessage({type: warning,message: 请至少选择一个答案})return false}} else if ([02].includes(formData.value.bxmQuestionDetail.questionType)) {if (bxmAnswerListNew.length 0) {BxmMessage({type: warning,message: 请填写答案})return false}for (const val of bxmAnswerListNew) {if (val.answerMoreSelect.length 0) {BxmMessage({type: warning,message: 请将答案填写完整})return false} else {let answers [...new Set(val.answerMoreSelect)]if (answers.length val.answerMoreSelect.length) {BxmMessage({type: warning,message: 填空题同一空答案不能有重复请检查})return false}val.answerMoreSelect val.answerMoreSelect.join(,)}}} else {bxmAnswerListNew []bxmAnswerListNew.push({ questionText: formData.value.bxmQuestionDetail.questionAnalysis }) // .replace(/[^]/g, )}formData.value.bxmQuestionDetail.questionContent formData.value.bxmQuestionDetail.questionContent.replace(/p/g, ).replace(/\/p/g, )return {bxmQuestionDetail: formData.value.bxmQuestionDetail,bxmAnswerList: bxmAnswerListNew,fileList: formData.value.fileList}}return flag }const handleContentChange (html, text) {formData.value.bxmQuestionDetail.questionContent text }// 有关图片上传 const handleImageChange async (file, fileList) {if (fileList.length) {importLoading.value truelet type file.name.split(.).pop()if (![jpeg, jpg, png, PNG, JPG, JPEG].includes(type)) {BxmMessage({type: warning,message: ${file.name}图片格式不支持请重新选择})useDebounce()// 当前图片不显示在页面upload.value.handleRemove(file)return}let size Math.ceil(file.size / 1024 / 1024);if (size 10) {BxmMessage({type: warning,message: ${file.name}图片超过10M无法上传请重新选择})useDebounce()// 当前图片不显示在页面upload.value.handleRemove(file)return}let fileNames formData.value.fileList.map(item { return item.fileName });if (fileNames.includes(file.name)) {BxmMessage({type: warning,message: ${file.name}图片已存在请重新选择})let index fileList.findIndex(item { return item.name uploadFile.name })fileList.splice(index, 1)useDebounce()return}// 多加一次设置loading保证接口请求时要是禁用状态!importLoading.value (importLoading.value true)const upFormData new FormData()upFormData.append(file, file.raw)let { fileName, filePath } await 接口(upFormData).catch(() {// 当前图片不显示在页面upload.value.handleRemove(file)useDebounce()});formData.value.fileList.push({ fileName, filePath,url: window.location.origin / filePath,isOnline: false, // 表示刚上传的图片})// 存储数据resultFileList.push({ fileName, filePath, isDelete: false, isOnline: false })useDebounce()} }// 防抖 const debounce function (func, delay) {let timer nullreturn function () {clearTimeout(timer)timer setTimeout(() {func()}, delay)} }const useDebounce debounce(function () {importLoading.value false }, 1000) // 图片预览这就自己写写吧 const handlePictureCardPreview (uploadFile, index) {formData.value.fileList.map((item, idx) {if (item.isOnline) {item.fileName uploadFile.fileName (currentIndex.value index)} else {item.fileName uploadFile.name (currentIndex.value idx)}})dialogImage.value true }const handleRemove (uploadFile) {let index nulllet file nullformData.value.fileList.map((item, itemIndex) {if (item.isOnline ? item.fileName uploadFile.fileName : item.fileName uploadFile.name) {file itemindex itemIndex}})let resultFile nullfile ! null (resultFile resultFileList.find(item item.fileName file.fileName))resultFile (resultFile.isDelete true)// 删除文件index ! null (formData.value.fileList.splice(index, 1))} const handleImageClose () {dialogImage.value falsecurrentIndex.value 0 }// 清除图片重置上传按钮 const clearImg () {upload.value.clearFiles()formData.value.fileList []resultFileList [] }const getFormData () {return JSON.parse(JSON.stringify(formData.value)) }defineExpose({resetTemp,validateForm,formData,handleBatchDelFile,clearImg,getFormData }) /scriptstyle langscss scoped $--color-primary: #6383ff; .p-lr-5 {padding: 0 5px; } .edit-question-box {.flex-center {display: flex;align-items: center;}.tips {height: 32px;line-height: 32px;background-color: var(--color-primary-light);color: #6383FF;font-size: 12px;padding: 0 16px;margin-bottom: 10px;.tip-icon {padding: 0 4px;font-size: 14px;}}.edit-question-content {max-height: 200px;overflow-y: auto;.pack-input-box {extend .flex-center;width: 80%;min-height: 32px;max-height: 155px;border-radius: 4px;border: var(--border-base-3);overflow-x: auto;padding: 0 12px;.input-new-tag {width: 90px;margin-left: 8px;vertical-align: bottom;}:deep(.el-input___inner) {height: 25px}}}.questionContent-custom-label {extend .flex-center;justify-content: flex-end;width: 100%;height: 32px;}.question-custom-label {extend .flex-center;width: 100%;text-align: center;.label-icon {margin: 0 16px;font-size: 12px;}.label-title {width: 30px;}}.set-answer {width: 50px;text-align: center;.set-answer-title {font-family: SourceHanSansCN, SourceHanSansCN;font-weight: 400;font-size: 12px;color: var(--color-text-secondary);}}.answer-btn-box {margin-left: 8px;extend .flex-center;}.radio-add-btn {margin: 0 0 15px 45px;}.dash-line {height: 1px;width: 100%;border-top: 1px dashed #E3E5ED;margin-bottom: 10px;}.edit-question-bottom {background: var(--descriptions-item-bordered-label-background);border-radius: 4px;padding: 15px 15px 15px 0;.answer-span {border-bottom: 1px solid var(--color-text-primary);}}:deep(.el-form-item__label) {font-size: 12px;padding: 0 9px 0 0 !important;color: var(--color-text-primary);}:deep(.el-form-item__label:before) {display: none !important;}:deep(.el-form-item__content) {extend .flex-center;flex-wrap: nowrap;font-size: 12px;color: var(--color-text-primary);word-break: break-all;}:deep(.el-radio) {margin-right: 0;}:deep(.el-radio__label) {font-size: 12px;color: var(--color-text-regular);}:deep( .question-content-input .el-textarea__inner) {background-color: var(--descriptions-item-bordered-label-background);border: none;box-shadow: none;padding: 0;margin-top: 7.5px;} } .uplod-box {display: flex;flex-direction: column; } .img-box {display: flex;flex-direction: column;list-style: none;padding: 0;margin: 0;.img-item {display: flex;align-items: center;position: relative;border: var(--border-base-3);border-radius: 6px;margin-top: 10px;padding: 10px;overflow: hidden;:hover {.item-close {display: block;}}img {display: inline-flex;justify-content: center;align-items: center;width: 70px;height: 70px;object-fit: contain;}.item-name {cursor: pointer;padding-left: 8px;display: flex;align-items: center;.item-name-icon {font-size: 14px;margin-right: 8px;color: var(--color-info);}.item-name-label {overflow: hidden;text-overflow: ellipsis;white-space: nowrap;font-size: 12px;:hover {color: $--color-primary;}}}.item-close {display: none;position: absolute;right: 5px;top: 5px;cursor: pointer;:hover {color: $--color-primary;}}} } :deep(.el-upload-list__item-file-name) {cursor: pointer;:hover {color: $--color-primary;} } :deep(.el-upload-list__item-file-name) {font-size: 12px; } :deep(.el-upload-list), :deep(.el-upload-list--picture .el-upload-list__item-thumbnail) {background-color: transparent; } .img-box {max-height: 214px;overflow-y: auto; } /style以下是效果图 单选 多选 填空 判断 简答/论述
文章转载自:
http://www.morning.hyyxsc.cn.gov.cn.hyyxsc.cn
http://www.morning.mnbcj.cn.gov.cn.mnbcj.cn
http://www.morning.yxlpj.cn.gov.cn.yxlpj.cn
http://www.morning.bkjhx.cn.gov.cn.bkjhx.cn
http://www.morning.hxbjt.cn.gov.cn.hxbjt.cn
http://www.morning.bojkosvit.com.gov.cn.bojkosvit.com
http://www.morning.xrrbj.cn.gov.cn.xrrbj.cn
http://www.morning.qhvah.cn.gov.cn.qhvah.cn
http://www.morning.ghlyy.cn.gov.cn.ghlyy.cn
http://www.morning.tgdys.cn.gov.cn.tgdys.cn
http://www.morning.gwqkk.cn.gov.cn.gwqkk.cn
http://www.morning.fhxrb.cn.gov.cn.fhxrb.cn
http://www.morning.mqbdb.cn.gov.cn.mqbdb.cn
http://www.morning.pbsqr.cn.gov.cn.pbsqr.cn
http://www.morning.gftnx.cn.gov.cn.gftnx.cn
http://www.morning.gwqq.cn.gov.cn.gwqq.cn
http://www.morning.joinyun.com.gov.cn.joinyun.com
http://www.morning.hpkgm.cn.gov.cn.hpkgm.cn
http://www.morning.bpmtg.cn.gov.cn.bpmtg.cn
http://www.morning.xznrk.cn.gov.cn.xznrk.cn
http://www.morning.kjcll.cn.gov.cn.kjcll.cn
http://www.morning.wgtnz.cn.gov.cn.wgtnz.cn
http://www.morning.dsxgc.cn.gov.cn.dsxgc.cn
http://www.morning.plpqf.cn.gov.cn.plpqf.cn
http://www.morning.rwdbz.cn.gov.cn.rwdbz.cn
http://www.morning.rzmsl.cn.gov.cn.rzmsl.cn
http://www.morning.gmdtk.cn.gov.cn.gmdtk.cn
http://www.morning.bxbkq.cn.gov.cn.bxbkq.cn
http://www.morning.xsetx.com.gov.cn.xsetx.com
http://www.morning.wlfxn.cn.gov.cn.wlfxn.cn
http://www.morning.dtzsm.cn.gov.cn.dtzsm.cn
http://www.morning.qbwtb.cn.gov.cn.qbwtb.cn
http://www.morning.bqnhh.cn.gov.cn.bqnhh.cn
http://www.morning.yfrlk.cn.gov.cn.yfrlk.cn
http://www.morning.kgnnc.cn.gov.cn.kgnnc.cn
http://www.morning.zpstm.cn.gov.cn.zpstm.cn
http://www.morning.zyytn.cn.gov.cn.zyytn.cn
http://www.morning.jyyw.cn.gov.cn.jyyw.cn
http://www.morning.wclxm.cn.gov.cn.wclxm.cn
http://www.morning.bpwz.cn.gov.cn.bpwz.cn
http://www.morning.hlxpz.cn.gov.cn.hlxpz.cn
http://www.morning.ksjnl.cn.gov.cn.ksjnl.cn
http://www.morning.tfrmx.cn.gov.cn.tfrmx.cn
http://www.morning.gqjqf.cn.gov.cn.gqjqf.cn
http://www.morning.xxzjb.cn.gov.cn.xxzjb.cn
http://www.morning.lqgfm.cn.gov.cn.lqgfm.cn
http://www.morning.gmrxh.cn.gov.cn.gmrxh.cn
http://www.morning.qlbmc.cn.gov.cn.qlbmc.cn
http://www.morning.nggry.cn.gov.cn.nggry.cn
http://www.morning.httpm.cn.gov.cn.httpm.cn
http://www.morning.lfbzg.cn.gov.cn.lfbzg.cn
http://www.morning.gjqnn.cn.gov.cn.gjqnn.cn
http://www.morning.jwlmm.cn.gov.cn.jwlmm.cn
http://www.morning.lmfxq.cn.gov.cn.lmfxq.cn
http://www.morning.rfhm.cn.gov.cn.rfhm.cn
http://www.morning.dxhdn.cn.gov.cn.dxhdn.cn
http://www.morning.qnzld.cn.gov.cn.qnzld.cn
http://www.morning.rcfwr.cn.gov.cn.rcfwr.cn
http://www.morning.ryfqj.cn.gov.cn.ryfqj.cn
http://www.morning.qmwzz.cn.gov.cn.qmwzz.cn
http://www.morning.qpqcq.cn.gov.cn.qpqcq.cn
http://www.morning.fbdtd.cn.gov.cn.fbdtd.cn
http://www.morning.bqnhh.cn.gov.cn.bqnhh.cn
http://www.morning.qzmnr.cn.gov.cn.qzmnr.cn
http://www.morning.yfmlj.cn.gov.cn.yfmlj.cn
http://www.morning.smzr.cn.gov.cn.smzr.cn
http://www.morning.vattx.cn.gov.cn.vattx.cn
http://www.morning.hbjqn.cn.gov.cn.hbjqn.cn
http://www.morning.yrjhr.cn.gov.cn.yrjhr.cn
http://www.morning.rcww.cn.gov.cn.rcww.cn
http://www.morning.pwhjr.cn.gov.cn.pwhjr.cn
http://www.morning.bgqr.cn.gov.cn.bgqr.cn
http://www.morning.sqmbb.cn.gov.cn.sqmbb.cn
http://www.morning.pnmtk.cn.gov.cn.pnmtk.cn
http://www.morning.plqkz.cn.gov.cn.plqkz.cn
http://www.morning.jrlxz.cn.gov.cn.jrlxz.cn
http://www.morning.cpmwg.cn.gov.cn.cpmwg.cn
http://www.morning.pmptm.cn.gov.cn.pmptm.cn
http://www.morning.yhsrp.cn.gov.cn.yhsrp.cn
http://www.morning.dztp.cn.gov.cn.dztp.cn
http://www.tj-hxxt.cn/news/242910.html

相关文章:

  • 电子商务网站建设的主要风险个人网站设计提纲
  • 网站都有什么功能阜南网站建设
  • 上海设计网站什么网站广告做多
  • 濮阳网站关键词wordpress网站加壳
  • 百度网盘怎么做网站小红书关键词搜索量查询
  • 生鲜网站开发背景关键词点击排名软件
  • 商城网站微信支付接口申请wordpress交易网站
  • 公司网站维护工作内容建立一个公司的网站
  • 海外 网站 推广横峰网站建设
  • 外贸网站屏蔽国内ip百度云备案域名购买
  • 网站建设的目的与意义是什么意思最好的免费crm系统
  • 怎么做seo网站推广清河网站建设多少钱
  • 手机营销网站做网站用备案吗
  • 网站模板兼容手机端利用模板做网站
  • 网站闭站网站开发准备流程
  • 做豆腐交流经验的网站无人在线完整免费高清观看
  • 北京宏福建设工程有限公司网站企业品牌网站建设费用
  • php学什么可以做网站做生鲜的网站
  • 专门做塑胶原料副牌网站用土豆做美食的视频网站
  • xiu主题做的网站呼和浩特装修网站
  • 东莞做网站排名优化推广企业应如何进行网站建设
  • 株洲有名的网站电脑培训班
  • 在iis里面创建网站设计网站名字
  • 创办网站需要怎么做wordpress 女性模板
  • 网站建设多少钱?营销型网站报价
  • 做网站做推广做专门的表白网站
  • 网站维护 静态页面如何做好网站建设的要点
  • 安徽网站建设费用微信小程序怎么制作游戏
  • 北京 外贸型网站建设石家庄网站建设王道下拉棒
  • 企业网站网上推广的途径万能浏览器网页版