|
@@ -8,77 +8,22 @@
|
|
|
</div>
|
|
|
<div class="content-wrap" v-else>
|
|
|
<Loading :top="200" v-show="dataLoading" type="1"></Loading>
|
|
|
- <div v-if="viewModel === 'type'">
|
|
|
- <div v-for="(type,typeIndex) in typeList">
|
|
|
- <div v-if="groupRes[type]">
|
|
|
- <div>{{ type }}</div>
|
|
|
- <div class="exercise-item" v-for="(item,index) of groupRes[type]" :key="index" @click="onQuestionToggle(index,item.id,$event)" @mouseenter="exerciseMouseover($event)" @mouseleave="exerciseMouseleave($event)">
|
|
|
- <div class="item-tools-wrap">
|
|
|
- <div class="item-tools-t flex-row-center"><Icon type="ios-list-box-outline" />配分</div>
|
|
|
- <div class="item-tools-t flex-row-center" @click.stop="handleToolEdit(item)"><Icon type="ios-brush-outline" />编辑</div>
|
|
|
- <div class="item-tools-t flex-row-center" @click.stop="handleDelete(index)"><Icon type="ios-archive-outline" />删除</div>
|
|
|
- <div class="item-tools-t flex-row-center" v-show="index != 0" @click.stop="handleMoveUp(exerciseList,index)"><Icon type="md-arrow-up" />上移</div>
|
|
|
- <div class="item-tools-t flex-row-center" v-show="index != (exerciseList.length - 1)" @click.stop="handleMoveDown(exerciseList,index)"><Icon type="md-arrow-down" />下移</div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 题干部分 -->
|
|
|
- <div class="item-question" style="pointer-events:none">
|
|
|
- <p>{{ pageSize * (pageNum - 1) + index + 1 }} : <span v-html="item.question"></span></p>
|
|
|
- <span class="item-btn-toggle">
|
|
|
- <Icon :type="collapseList.indexOf(index) > -1 ? 'ios-arrow-dropup' : 'ios-arrow-dropdown'" />
|
|
|
- <!--<Button type="primary">选题</Button>-->
|
|
|
- </span>
|
|
|
- </div>
|
|
|
- <!-- 选项部分 -->
|
|
|
- <div v-for="(option,optionIndex) in item.option" :key="optionIndex" class="item-options" style="pointer-events:none">
|
|
|
- <p class="item-option-content">{{String.fromCharCode(64 + parseInt(optionIndex+1))}} : <span v-html="option.value"></span></p>
|
|
|
- </div>
|
|
|
- <transition name="slide">
|
|
|
- <div v-show="collapseList.indexOf(index) > -1" class="toggle-area">
|
|
|
- <!-- 答案展示部分 -->
|
|
|
- <div class="item-explain" v-show="isShowAnswer">
|
|
|
- <span class="explain-title">【答案】</span>
|
|
|
- <div class="item-explain-details">
|
|
|
- <span v-html="item.answer" v-if="item.type === 'Subjective'"></span>
|
|
|
- <span :class="[ item.type === 'Complete' ? 'item-answer-item':'']" v-for="(answer,index) in item.answer" :key="index" v-else-if="item.type === 'Complete'" v-html="answer"></span>
|
|
|
- <span :class="[ item.type === 'Complete' ? 'item-answer-item':'']" v-for="(answer,index) in item.answer" :key="index" v-else>{{answer}}</span>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <!-- 解析部分 -->
|
|
|
- <div class="item-explain" v-show="isShowAnswer">
|
|
|
- <span class="explain-title">【解析】</span>
|
|
|
- <div class="item-explain-details">
|
|
|
- <span v-html="item.explain || '暂无解析'"></span>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <!-- 知识点部分 -->
|
|
|
- <div class="item-explain" v-show="isShowAnswer">
|
|
|
- <span class="explain-title">【知识点】</span>
|
|
|
- <div class="item-explain-details">
|
|
|
- <span v-html="item.points.length ? item.points : '暂未绑定知识点'"></span>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
|
|
|
- </div>
|
|
|
- </transition>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <div v-else class="list-view">
|
|
|
- <div class="exercise-item" v-for="(item,index) of exerciseList" :key="index" @click="onQuestionToggle(index,item.id,$event)" @mouseenter="exerciseMouseover($event)" @mouseleave="exerciseMouseleave($event)">
|
|
|
+ <div class="list-view" v-for="(typeItem,typeIndex) in groupList">
|
|
|
+ <p v-show="viewModel === 'type'" class="type-name">{{ numberConvertToUppercase(typeIndex + 1) }} : {{ exersicesType[typeItem.type] }} ( {{ typeItem.score }} 分)</p>
|
|
|
+ <div class="exercise-item" v-for="(item,index) of typeItem.list" :key="index" @click="onQuestionToggle(exerciseList.indexOf(item),item.id,$event,typeItem.list)" @mouseenter="exerciseMouseover($event)" @mouseleave="exerciseMouseleave($event)">
|
|
|
<div class="item-tools-wrap">
|
|
|
- <div class="item-tools-t flex-row-center" @click.stop="handleSetScore(item,index)"><Icon type="ios-list-box-outline" />配分</div>
|
|
|
+ <div class="item-tools-t flex-row-center" @click.stop="handleSetScore(item,exerciseList.indexOf(item))"><Icon type="ios-list-box-outline" />配分</div>
|
|
|
<div class="item-tools-t flex-row-center" @click.stop="handleToolEdit(item)"><Icon type="ios-brush-outline" />编辑</div>
|
|
|
- <div class="item-tools-t flex-row-center" @click.stop="handleDelete(index)"><Icon type="ios-archive-outline" />删除</div>
|
|
|
- <div class="item-tools-t flex-row-center" v-show="index != 0" @click.stop="handleMoveUp(exerciseList,index)"><Icon type="md-arrow-up" />上移</div>
|
|
|
- <div class="item-tools-t flex-row-center" v-show="index != (exerciseList.length - 1)" @click.stop="handleMoveDown(exerciseList,index)"><Icon type="md-arrow-down" />下移</div>
|
|
|
+ <div class="item-tools-t flex-row-center" @click.stop="handleDelete(typeItem.list,item,index)"><Icon type="ios-archive-outline" />删除</div>
|
|
|
+ <div class="item-tools-t flex-row-center" v-show="index != 0" @click.stop="handleMoveUp(typeItem.list,index)"><Icon type="md-arrow-up" />上移</div>
|
|
|
+ <div class="item-tools-t flex-row-center" v-show="index != (typeItem.list.length - 1)" @click.stop="handleMoveDown(typeItem.list,index)"><Icon type="md-arrow-down" />下移</div>
|
|
|
</div>
|
|
|
|
|
|
<!-- 题干部分 -->
|
|
|
<div class="item-question" style="pointer-events:none">
|
|
|
- <p>{{ pageSize * (pageNum - 1) + index + 1 }} : <span v-html="item.question"></span></p>
|
|
|
+ <p v-if="viewModel === 'list'">{{pageSize * (pageNum - 1) + exerciseList.indexOf(item) + 1}} : <span v-html="item.question"></span></p>
|
|
|
+ <p v-else>{{ pageSize * (pageNum - 1) + index + 1 }} : <span v-html="item.question"></span></p>
|
|
|
<span class="item-btn-toggle">
|
|
|
<span class="item-score">{{ item.score }} 分</span>
|
|
|
|
|
@@ -91,7 +36,7 @@
|
|
|
<p class="item-option-content">{{String.fromCharCode(64 + parseInt(optionIndex+1))}} : <span v-html="option.value"></span></p>
|
|
|
</div>
|
|
|
<transition name="slide">
|
|
|
- <div v-show="collapseList.indexOf(index) > -1" class="toggle-area">
|
|
|
+ <div v-show="collapseList.indexOf(exerciseList.indexOf(item)) > -1" class="toggle-area">
|
|
|
<!-- 答案展示部分 -->
|
|
|
<div class="item-explain" v-show="isShowAnswer">
|
|
|
<span class="explain-title">【答案】</span>
|
|
@@ -137,10 +82,26 @@
|
|
|
title="题目配分"
|
|
|
@on-ok="onConfirmScore"
|
|
|
>
|
|
|
- <InputNumber :max="curItemScore + surPlusScore" :min="0" v-model="curItemScore" @on-change="onScoreChange"></InputNumber>
|
|
|
+ <InputNumber :max="curItemScore + surPlusScore" :min="0" :step="scoreStep" v-model="curItemScore" @on-change="onScoreChange"></InputNumber>
|
|
|
<p>剩余可分配分数:{{ surPlusScore }}</p>
|
|
|
</Modal>
|
|
|
|
|
|
+ <Modal v-model="typeScoreModel"
|
|
|
+ title="题型配分"
|
|
|
+ footer-hide>
|
|
|
+ <span class="type-score-item">已分配总分 : {{ getTotalScore(groupTypeList) }}</span>
|
|
|
+ <div v-for="item in groupTypeList" class="type-score-item">
|
|
|
+ <span>{{ exersicesType[item.type] }} </span>
|
|
|
+ <span>共 {{ item.list.length }} 道题,总分配:</span>
|
|
|
+ <InputNumber :max="paper.score" :min="0" :step="scoreStep" v-model="item.score"></InputNumber>
|
|
|
+ <span> 分</span>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <Button class="type-score-btn" @click="onConfirmTypeScore" type="info" :disabled="getTotalScore(groupTypeList) > paper.score">确认</Button>
|
|
|
+ <p style="color:red;text-align:center;font-weight:bold;margin-top:10px" v-show="getTotalScore(groupTypeList) > paper.score">配分已超试卷总分,请重新分配!</p>
|
|
|
+
|
|
|
+ </Modal>
|
|
|
+
|
|
|
|
|
|
</div>
|
|
|
</template>
|
|
@@ -148,7 +109,7 @@
|
|
|
<script>
|
|
|
import Loading from '@/common/Loading.vue'
|
|
|
export default {
|
|
|
- props: ['exerciseData','totalScore'],
|
|
|
+ props: ['paper'],
|
|
|
components: {
|
|
|
Loading
|
|
|
},
|
|
@@ -160,13 +121,14 @@
|
|
|
exerciseList: [],
|
|
|
schoolInfo: {},
|
|
|
isShowUploadList: false,
|
|
|
+ typeScoreModel:false,
|
|
|
setPaperInfoModal: false,
|
|
|
exersicesType: {
|
|
|
- Single: '单选',
|
|
|
- Multiple: '多选',
|
|
|
- Judge: '判断',
|
|
|
- Complete: '填空',
|
|
|
- Subjective: '问答',
|
|
|
+ Single: '单选题',
|
|
|
+ Multiple: '多选题',
|
|
|
+ Judge: '判断题',
|
|
|
+ Complete: '填空题',
|
|
|
+ Subjective: '问答题',
|
|
|
Compose: '综合题'
|
|
|
},
|
|
|
exersicesDiff: ['容易', '较易', '一般', '较难', '困难'],
|
|
@@ -183,30 +145,33 @@
|
|
|
subjectList: [],
|
|
|
basketList: [],
|
|
|
originData: [],
|
|
|
- groupRes: {},
|
|
|
+ groupList: [],
|
|
|
+ groupTypeList:[],
|
|
|
typeList: ['Single', 'Multiple', 'Judge', 'Complete', 'Subjective', 'Compose'],
|
|
|
- viewModel:'list',
|
|
|
+ viewModel:'type',
|
|
|
filterParams: {},
|
|
|
surPlusScore: 0,
|
|
|
curItemScore: 0,
|
|
|
curIndex:0,
|
|
|
- lastScore:0,
|
|
|
+ lastScore: 0,
|
|
|
+ scoreStep:0.5,
|
|
|
scoreModal:false
|
|
|
}
|
|
|
},
|
|
|
|
|
|
created() {
|
|
|
- console.log(this.exerciseList)
|
|
|
+ //console.log(this.exerciseList)
|
|
|
},
|
|
|
methods: {
|
|
|
/**
|
|
|
* 根据ID获取试题详细数据
|
|
|
* @param id 试题ID
|
|
|
*/
|
|
|
- getDetailsById(id, index) {
|
|
|
+ getDetailsById(arr, id, index) {
|
|
|
this.$api.newEvaluation.FindExerciseById(id).then(res => {
|
|
|
/* 查询到详细数据则替换掉原数据 */
|
|
|
this.exerciseList.splice(index, 1, res.result.data)
|
|
|
+ arr.splice(index, 1, res.result.data)
|
|
|
})
|
|
|
},
|
|
|
|
|
@@ -215,18 +180,39 @@
|
|
|
* @param index
|
|
|
* @param id
|
|
|
*/
|
|
|
- onQuestionToggle(index, id, e) {
|
|
|
+ onQuestionToggle(index, id, e, arr) {
|
|
|
e.stopPropagation()
|
|
|
let listIndex = this.collapseList.indexOf(index)
|
|
|
if (listIndex > -1) {
|
|
|
this.collapseList.splice(listIndex, 1)
|
|
|
} else {
|
|
|
this.collapseList.push(index)
|
|
|
- if (!this.exerciseList[index].answer.length) this.getDetailsById(id, index)
|
|
|
+ if (!this.exerciseList[index].answer.length) this.getDetailsById(arr, id, index)
|
|
|
this.pageScrollTo(e.target.offsetTop + 60) // content-wrap 距离顶部高度
|
|
|
}
|
|
|
},
|
|
|
|
|
|
+ /**
|
|
|
+ * 数字与中文转换
|
|
|
+ * @param num
|
|
|
+ */
|
|
|
+ numberConvertToUppercase(num) {
|
|
|
+ num = Number(num)
|
|
|
+ var upperCaseNumber = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十', '百', '千', '万', '亿']
|
|
|
+ var length = String(num).length
|
|
|
+ if (length === 1) {
|
|
|
+ return upperCaseNumber[num]
|
|
|
+ } else if (length === 2) {
|
|
|
+ if (num === 10) {
|
|
|
+ return upperCaseNumber[num]
|
|
|
+ } else if (num > 10 && num < 20) {
|
|
|
+ return '十' + upperCaseNumber[String(num).charAt(1)]
|
|
|
+ } else {
|
|
|
+ return upperCaseNumber[String(num).charAt(0)] + '十' + upperCaseNumber[String(num).charAt(1)].replace('零', '')
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
// 分页操作
|
|
|
pageChange(page) {
|
|
|
let start = this.pageSize * (page - 1)
|
|
@@ -288,7 +274,7 @@
|
|
|
* 删除试卷中的单个试题
|
|
|
* @param index
|
|
|
*/
|
|
|
- handleDelete(index) {
|
|
|
+ handleDelete(arr,item,index) {
|
|
|
this.$Modal.confirm({
|
|
|
title: '提示',
|
|
|
content: '<p>确认删除该试题吗?</p>',
|
|
@@ -296,9 +282,10 @@
|
|
|
cancelText: '取消',
|
|
|
onOk: () => {
|
|
|
this.$Message.success('删除成功')
|
|
|
- this.surPlusScore += this.exerciseList[index].score
|
|
|
+ this.surPlusScore += item.score
|
|
|
console.log(this.surPlusScore)
|
|
|
- this.exerciseList.splice(index, 1)
|
|
|
+ arr.splice(index, 1)
|
|
|
+ this.exerciseList.splice(this.exerciseList.indexOf(item), 1)
|
|
|
this.$emit('dataUpdate', this.exerciseList)
|
|
|
}
|
|
|
})
|
|
@@ -322,6 +309,11 @@
|
|
|
},
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
+ * 给单个试题配分
|
|
|
+ * @param item
|
|
|
+ * @param index
|
|
|
+ */
|
|
|
handleSetScore(item, index) {
|
|
|
this.curIndex = index
|
|
|
this.curItemScore = item.score
|
|
@@ -329,41 +321,103 @@
|
|
|
this.scoreModal = true
|
|
|
},
|
|
|
|
|
|
-
|
|
|
+ /**
|
|
|
+ * 配分变化时的剩余分数处理
|
|
|
+ * @param val
|
|
|
+ */
|
|
|
onScoreChange(val) {
|
|
|
this.surPlusScore = this.surPlusScore + this.lastScore - val
|
|
|
this.lastScore = val
|
|
|
|
|
|
},
|
|
|
|
|
|
+ /** 确认单个试题配分 */
|
|
|
onConfirmScore() {
|
|
|
this.$set(this.exerciseList[this.curIndex], 'score', this.curItemScore);
|
|
|
+ },
|
|
|
+
|
|
|
+ /** 按照题型配分 */
|
|
|
+ onConfirmTypeScore() {
|
|
|
+ /** 重新计算剩余分配分数 */
|
|
|
+ this.surPlusScore = this.paper.score - this.groupTypeList.reduce((p, e) => p + e.score, 0)
|
|
|
+ if (this.surPlusScore < 0) {
|
|
|
+ this.$Message.warning("当前配分超过试卷总分,请重新分配!")
|
|
|
+ } else {
|
|
|
+ /* 按照题型配分后平均分配给每个子题 */
|
|
|
+ this.groupTypeList.forEach(item => {
|
|
|
+ item.list.forEach(exercise => {
|
|
|
+ exercise.score = item.score / item.list.length
|
|
|
+ this.exerciseList.filter(item => item.id === exercise.id)[0].score = item.score / item.list.length
|
|
|
+ })
|
|
|
+ })
|
|
|
+ /** 回到题型视图 */
|
|
|
+ this.groupList = this.groupTypeList
|
|
|
+ this.$parent.viewModel = 'type'
|
|
|
+ this.typeScoreModel = false
|
|
|
+ }
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+
|
|
|
+ /** 打开题型配分 */
|
|
|
+ onSetScoreByType() {
|
|
|
+ this.typeScoreModel = true;
|
|
|
+ },
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取题目列表总分
|
|
|
+ * @param arr
|
|
|
+ */
|
|
|
+ getTotalScore(arr) {
|
|
|
+ return arr.reduce((p,e)=>p+e.score,0)
|
|
|
}
|
|
|
|
|
|
- },
|
|
|
- mounted() {
|
|
|
+
|
|
|
},
|
|
|
watch: {
|
|
|
- exerciseData: {
|
|
|
- handler(newValue, oldValue) {
|
|
|
- if (newValue) {
|
|
|
- this.exerciseList = newValue
|
|
|
- this.originData = newValue
|
|
|
- this.totalNum = newValue.length
|
|
|
- this.groupRes = this._.groupBy(newValue, 'type')
|
|
|
+ paper: {
|
|
|
+ handler(newPaper, oldValue) {
|
|
|
+ if (newPaper) {
|
|
|
+
|
|
|
+ let that = this
|
|
|
+ this.groupList = []
|
|
|
+ this.exerciseList = []
|
|
|
+
|
|
|
+ /* 处理试卷内题目按照题型排序 */
|
|
|
+ this.typeList.forEach(item => {
|
|
|
+ this._.mapKeys(this._.groupBy(newPaper.item, 'type'), function (value, key) {
|
|
|
+ if (key === item) { /* 按照题型排序,并且计算每种题型的总分 */
|
|
|
+ that.groupList.push({ type: key, list: value, score : value.reduce((p,e)=>p+e.score,0) })
|
|
|
+ that.exerciseList = that.exerciseList.concat(value)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ });
|
|
|
+
|
|
|
+ this.originData = this.exerciseList
|
|
|
+ this.groupTypeList = this.groupList
|
|
|
+ this.totalNum = newPaper.item.length
|
|
|
+ this.surPlusScore = newPaper.score - newPaper.item.reduce((p,e)=>p+e.score,0);
|
|
|
this.pageScrollTo(0)
|
|
|
this.pageChange(1)
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
-
|
|
|
- totalScore: {
|
|
|
- handler(newValue, oldValue) {
|
|
|
+ viewModel: {
|
|
|
+ handler(newValue) {
|
|
|
if (newValue) {
|
|
|
- this.surPlusScore = newValue - this.exerciseList.reduce((p,e)=>p+e.score,0);
|
|
|
- console.log(this.surPlusScore)
|
|
|
+ if (newValue === 'list') {
|
|
|
+ this.groupList = [{
|
|
|
+ type: 'all',
|
|
|
+ score:this.exerciseList.reduce((p,e)=>p+e.score,0),
|
|
|
+ list: this.exerciseList
|
|
|
+ }]
|
|
|
+ } else {
|
|
|
+ this.groupList = this.groupTypeList
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
+ },
|
|
|
+ immediate:true
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -382,6 +436,12 @@
|
|
|
margin: 20px 0;
|
|
|
}
|
|
|
|
|
|
+ .components-el-container .type-name {
|
|
|
+ font-size:18px;
|
|
|
+ font-weight:bold;
|
|
|
+ margin-top:20px;
|
|
|
+ }
|
|
|
+
|
|
|
.components-el-container .exercise-item {
|
|
|
position:relative;
|
|
|
margin-top:30px;
|
|
@@ -430,6 +490,18 @@
|
|
|
margin:0 3px;
|
|
|
}
|
|
|
|
|
|
+ .type-score-btn {
|
|
|
+ width:80%;
|
|
|
+ margin-left:10%;
|
|
|
+ height:40px;
|
|
|
+ line-height:40px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .type-score-item {
|
|
|
+ margin:20px 10px;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
/*横向垂直水平居中*/
|
|
|
.flex-row-center {
|
|
|
display: flex;
|