@zykjcommon/questions 0.0.13 → 0.0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/.env.production +2 -1
  2. package/.env.test +2 -1
  3. package/dist/zykjcommon-questions.common.js +14842 -2485
  4. package/dist/zykjcommon-questions.css +1 -1
  5. package/dist/zykjcommon-questions.umd.js +14843 -2494
  6. package/dist/zykjcommon-questions.umd.min.js +24 -1
  7. package/package.json +2 -2
  8. package/src/App.vue +2 -0
  9. package/src/assets/js/fun.js +23 -2
  10. package/src/assets/js/http.js +1 -1
  11. package/src/assets/scss/questions/index.scss +97 -22
  12. package/src/components/common/IframeComponent.vue +60 -76
  13. package/src/components/common/Loading.vue +9 -31
  14. package/src/components/common/TextAreaEditor.vue +72 -87
  15. package/src/components/exam/QuestionCard.vue +3 -3
  16. package/src/components/questions/QuestionReader.js +4 -4
  17. package/src/components/questions/Question_BriefAnswer.vue +146 -0
  18. package/src/components/questions/Question_FillBlank.vue +151 -0
  19. package/src/components/questions/Question_MultipleChoice.vue +179 -0
  20. package/src/components/questions/Question_Programming.vue +285 -0
  21. package/src/components/questions/Question_Reading.vue +173 -0
  22. package/src/components/questions/Question_SingleChoice.vue +7 -21
  23. package/src/components/questions/buildEntry.js +130 -5
  24. package/src/components/questions/const.js +15 -0
  25. package/src/components/questions/developmentEntry.js +130 -5
  26. package/src/components/questions/entry.js +2 -18
  27. package/src/components/questions/store.js +44 -0
  28. package/src/main.ts +16 -12
  29. package/src/views/exam/Analysis.vue +620 -7
  30. package/src/views/exam/Exam.vue +612 -11
  31. package/vue.config.js +8 -4
@@ -0,0 +1,146 @@
1
+ <template>
2
+ <div class="zykjcommon-question">
3
+ <div v-if="!isSub" class="question-type">{{questionInfo.questionIndex}}、{{questionInfo.hint ? questionInfo.hint : questionInfo.question_type_str}}<span v-if="questionInfo.score!=='null'"><!--({{questionInfo.score}}分)--></span>
4
+ <span class="score fr" v-if="mode==='analysis'">得分:{{questionInfo.answerMap ? questionInfo.answerMap.user_score : '-'}}分</span>
5
+ </div>
6
+ <div class="question-box">
7
+ <!-- <div class="question-stem">{{questionInfo.hint}}</div>-->
8
+ <div class="editor-content" v-html="questionInfo.htmlContent"></div>
9
+
10
+ <!-- <div class="editor-tit">样例输入</div>
11
+ <div class="editor-output" style="margin-bottom: 0.3rem">
12
+ 哇哈哈哈哈哈
13
+ </div>
14
+ <div class="editor-tit">样例输出</div>-->
15
+ <TextAreaEditor @getTextareaStr="getTextareaStr"
16
+ :disabled="mode === 'review'"
17
+ v-if="mode === 'exam' || mode === 'review'"
18
+ :value="textareaStr"
19
+ :placeHolder="'请在此输入答案'"></TextAreaEditor>
20
+ <div class="editor-output" style="margin-bottom: 0.3rem;" v-if="mode === 'analysis'">
21
+ <div class="editor-tit">【你的答案】:</div>
22
+ <div class="output-main" v-html="answerMap.subjective_answer">
23
+ </div>
24
+ </div>
25
+ <div ></div>
26
+ <div class="question-analysis" v-if="mode === 'analysis'">
27
+ <div class="triangle-top"></div>
28
+ <div class="question-analysis-item">
29
+ <span class="txt">【正确答案】:</span>
30
+ <div class="txt-box" v-html="analyCorrectAnswer"></div>
31
+ </div>
32
+ <div class="question-analysis-item" v-if="questionInfo.analysis">
33
+ <span class="txt">【本题解析】:</span>
34
+ <div class="txt-box">
35
+ <span class="analysis-txt" v-html="questionInfo.analysisHtmlContent"></span>
36
+ </div>
37
+ </div>
38
+ </div>
39
+ </div>
40
+ <!--
41
+ 兼容性写法,两个都写
42
+ vue2支持.sync
43
+ vue3支持v-model:
44
+ :visible.sync="visible"
45
+ v-model:visible="visible"
46
+ -->
47
+ <MediaLooker :visible.sync="visible"
48
+ v-model:visible="visible"
49
+ v-if="visible"
50
+ :mediaCount="curMediaCount"
51
+ :mediaLookerList="mediaLookerList"></MediaLooker>
52
+ </div>
53
+ </template>
54
+ <script>
55
+
56
+ import {commonData,doMediaLookerSome} from './mixin'
57
+ import MediaLooker from '../common/MediaLooker.vue'
58
+ import TextAreaEditor from '../common/TextAreaEditor.vue'
59
+ export default {
60
+ name: 'Question_BriefAnswer',
61
+ props: {
62
+ isSub:{
63
+ type: Boolean,
64
+ default: false
65
+ },
66
+ questionInfo: {
67
+ type: Object,
68
+ default: {}
69
+ },
70
+ bus: {
71
+ type: Object,
72
+ default: {}
73
+ },
74
+ mode: {
75
+ type: String,
76
+ default: 'exam'
77
+ }
78
+ },
79
+ mounted() {
80
+ doMediaLookerSome(this)
81
+ },
82
+ data() {
83
+ return {
84
+ textareaHtml:'',
85
+ textareaStr:'',
86
+ analyCorrectAnswer:'',
87
+ answerMap:{},
88
+ ...JSON.parse(commonData)
89
+ };
90
+ },
91
+ watch: {
92
+ questionInfo:{
93
+ handler(nv,ov){
94
+ if(nv){
95
+ this.answerMap = nv.answerMap
96
+ if(this.questionInfo.answerMap){
97
+ if(this.mode === 'analysis'){
98
+ this.analyCorrectAnswer = this.questionInfo.correct_subjective_answer
99
+ }
100
+ let subjective_answer = this.questionInfo.answerMap.subjective_answer
101
+ if(subjective_answer!==undefined && subjective_answer!==null && subjective_answer!==''){
102
+ //带br的转成纯字符串
103
+ this.textareaStr = subjective_answer.replace(/<br>/img,'\n')
104
+ }
105
+ }
106
+ }
107
+ },
108
+ immediate:true
109
+ }
110
+ },
111
+ computed:{
112
+ },
113
+ methods: {
114
+ getAnswer(){
115
+ let subjective_answer = this.textareaHtml
116
+ return {subjective_answer}
117
+ },
118
+ isAnswered(){
119
+ let brReg = /<br>/img
120
+ let spaceReg = /\s+/img
121
+ let str = this.textareaHtml.replace(brReg,'')
122
+ str = str.replace(spaceReg,'')
123
+ let answerd = str.length > 0
124
+ return answerd
125
+ },
126
+ isCorrect(){
127
+ let correct = this.questionInfo.answerMap.is_correct === '1' ? true : false
128
+ return correct
129
+ },
130
+ getTextareaStr(str){
131
+ let reg = /\n/ig
132
+ this.textareaHtml = str.replace(reg, '<br>')
133
+ let answered = this.isAnswered()
134
+ this.$emit('getIsAnswered',answered)
135
+ this.mode === 'exam' && this.bus.$emit('questionCardChange',{
136
+ questionIndex:this.questionInfo.questionIndex - 1,
137
+ answered
138
+ })
139
+ }
140
+ },
141
+ components:{
142
+ TextAreaEditor,
143
+ MediaLooker
144
+ }
145
+ };
146
+ </script>
@@ -0,0 +1,151 @@
1
+ <template>
2
+ <div class="zykjcommon-question">
3
+ <div class="question-type" v-if="!isSub">{{questionInfo.questionIndex}}、{{questionInfo.hint ? questionInfo.hint :questionInfo.question_type_str}}<span v-if="questionInfo.score!=='null'"><!--({{questionInfo.score}}分)--></span>
4
+ <span class="score fr" v-if="mode==='analysis'">得分:{{questionInfo.answerMap ? questionInfo.answerMap.user_score : '-'}}分</span>
5
+ </div>
6
+ <div class="question-box">
7
+ <div class="editor-content"
8
+ style="line-height: 40px;"
9
+ v-if="questionInfo.htmlContent" v-html="questionInfo.htmlContent"></div>
10
+
11
+ </div>
12
+ <!--
13
+ 兼容性写法,两个都写
14
+ vue2支持.sync
15
+ vue3支持v-model:
16
+ :visible.sync="visible"
17
+ v-model:visible="visible"
18
+ -->
19
+ <MediaLooker :visible.sync="visible"
20
+ v-model:visible="visible"
21
+ v-if="visible"
22
+ :mediaCount="curMediaCount"
23
+ :mediaLookerList="mediaLookerList"></MediaLooker>
24
+ </div>
25
+ </template>
26
+ <script>
27
+
28
+ import {commonData,doMediaLookerSome} from './mixin'
29
+ import MediaLooker from '../common/MediaLooker.vue'
30
+ let filerRegs = [
31
+ {reg:/&lt;/ig,val:'<'},
32
+ {reg:/&gt;/ig,val:'>'}
33
+ ]
34
+ export default {
35
+ name: 'Question_FillBlank',
36
+ props: {
37
+ bus: {
38
+ type: Object,
39
+ default: {}
40
+ },
41
+ isSub:{
42
+ type: Boolean,
43
+ default: false
44
+ },
45
+ orderIndex:{
46
+ type: Number,
47
+ default: 0
48
+ },
49
+ questionInfo: {
50
+ type: Object,
51
+ default: {}
52
+ },
53
+ mode: {
54
+ type: String,
55
+ default: 'exam'
56
+ }
57
+ },
58
+ mounted() {
59
+ let self = this
60
+ doMediaLookerSome(this)
61
+ this.$watch('questionInfo',(nv)=>{
62
+ if(nv){
63
+ this.answerMap = nv.answerMap
64
+ let fillBlank = jQuery(this.$el).find('.fill-blank')
65
+ fillBlank.replaceWith(jQuery(`<span class="fill-blank" contenteditable="${self.mode==='exam'?'true':'false'}">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>`))
66
+ jQuery(this.$el).find('.fill-blank').bind('input',function(e){
67
+ let ipt = jQuery(e.target)
68
+ let iptValue = ipt.html()
69
+ iptValue = self.getIptValue(iptValue)
70
+ if(iptValue.length <= 0){
71
+ ipt.html('&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;')
72
+ }
73
+ let answered = self.isAnswered()
74
+ self.$emit('getIsAnswered',answered)
75
+ self.mode === 'exam' && self.bus.$emit('questionCardChange',{
76
+ questionIndex:self.questionInfo.questionIndex - 1,
77
+ answered
78
+ })
79
+ })
80
+ if(nv.answerMap){
81
+ if(this.mode === 'analysis'){
82
+ this.analyCorrectAnswer = this.questionInfo.correct_gap_data
83
+ }
84
+ let gap_data = nv.answerMap.gap_data
85
+ jQuery(this.$el).find('.fill-blank').each((index,item)=>{
86
+ let val = gap_data[index]
87
+ if(val){
88
+ filerRegs.forEach((filterItem)=>{
89
+ let reg = filterItem.reg
90
+ if(reg.test(val)){
91
+ let replaceVal = filterItem.val
92
+ val = val.replace(reg,replaceVal)
93
+ }
94
+ })
95
+ jQuery(item).text(val)
96
+ this.mode === 'exam' && this.bus.$emit('questionCardChange',{
97
+ questionIndex:self.questionInfo.questionIndex - 1,
98
+ answered:true
99
+ })
100
+ }
101
+ })
102
+ }
103
+
104
+ let answered = self.isAnswered()
105
+ self.$emit('getIsAnswered',answered)
106
+ }
107
+ },{
108
+ immediate:true
109
+ })
110
+ },
111
+ data() {
112
+ return {
113
+ analyCorrectAnswer:'',
114
+ answerMap:{},
115
+ ...JSON.parse(commonData)
116
+ };
117
+ },
118
+ watch: {},
119
+ computed:{
120
+ },
121
+ methods: {
122
+ getAnswer(){
123
+ let fillBlank = jQuery(this.$el).find('.fill-blank')
124
+ let gap_data = []
125
+ fillBlank.each((index,item)=>{
126
+ let iptValue = jQuery(item).html()
127
+ iptValue = this.getIptValue(iptValue)
128
+ gap_data.push(iptValue)
129
+ })
130
+ return {gap_data}
131
+ },
132
+ isAnswered(){
133
+ let answerResult = this.getAnswer().gap_data
134
+ let answered = answerResult.some((item)=>{
135
+ return item !== ''
136
+ })
137
+ return answered
138
+ },
139
+ isCorrect(){
140
+ let correct = this.questionInfo.answerMap.is_correct === '1' ? true : false
141
+ return correct
142
+ },
143
+ getIptValue(str){
144
+ return str.replace(/&nbsp;/ig,'').replace(/^\s+/ig,'').replace(/\s+$/ig,'')
145
+ }
146
+ },
147
+ components:{
148
+ MediaLooker
149
+ }
150
+ };
151
+ </script>
@@ -0,0 +1,179 @@
1
+ <template>
2
+ <div class="zykjcommon-question">
3
+ <div class="question-type" v-if="!isSub">{{questionInfo.questionIndex}}、{{questionInfo.hint ? questionInfo.hint : questionInfo.question_type_str}}<span v-if="questionInfo.score!=='null'"><!--({{questionInfo.score}}分)--></span>
4
+ <span class="score fr" v-if="mode==='analysis'">得分:{{questionInfo.answerMap ? questionInfo.answerMap.user_score : '-'}}分</span>
5
+ </div>
6
+ <div class="question-box">
7
+ <!-- <div class="question-stem" v-if="!isSub">{{questionInfo.hint}}</div>-->
8
+ <div class="question-stem" v-if="isSub"><span v-if="questionInfo.hint">{{questionInfo.questionIndex2}}、</span>{{questionInfo.hint}}</div>
9
+ <div class="editor-content" v-if="!isSub" v-html="questionInfo.htmlContent"></div>
10
+ <div class="editor-content" style="display: flex" v-if="isSub">
11
+ <span v-if="!questionInfo.hint">{{questionInfo.questionIndex2}}、</span><div style="display: inline-block;flex:1;" v-html="questionInfo.htmlContent"></div>
12
+ </div>
13
+ <div class="question-option-list">
14
+ <div class="question-option" v-for="(item,index) in exam_options_data">
15
+ <div class="checkbox-box" :class="{'checked':checkboxList.indexOf(item.index) > -1}">
16
+ <input type="checkbox"
17
+ :disabled="mode === 'analysis' || mode === 'review'"
18
+ v-model="checkboxList"
19
+ :id="'checkbox-'+questionInfo.questionIndex+'-'+index"
20
+ class="checkbox"
21
+ :value="item.index">
22
+ <div class="checkbox-bg"></div>
23
+ </div>
24
+ <div class="label-box">
25
+ <label :for="'checkbox-'+questionInfo.questionIndex+'-'+index">
26
+ <span>{{item.enIndex}}.<span v-if="item.data.file_type == 0">{{item.data.option_content}}</span></span>
27
+ <div class="img-box" v-if="item.data.file_type != 0">
28
+ <img :src="item.data.file_url">
29
+ </div>
30
+ </label>
31
+ </div>
32
+ </div>
33
+ <div class="question-analysis" v-if="mode === 'analysis'">
34
+ <div class="triangle-top"></div>
35
+ <div class="question-analysis-item">
36
+ <span class="txt">【你的回答】:</span>
37
+ <div class="txt-box">
38
+ <span :class="{'wrong':questionInfo.answerMap.is_correct !== '1','right':questionInfo.answerMap.is_correct === '1'}">{{questionInfo.answerMap.is_correct !== '1'?'错误':'正确'}}</span>
39
+ </div>
40
+ </div>
41
+ <div class="question-analysis-item">
42
+ <span class="txt">【正确答案】:</span>
43
+ <div class="txt-box">
44
+ <span>{{analyCorrectAnswer}}</span>
45
+ </div>
46
+ </div>
47
+ <div class="question-analysis-item" v-if="questionInfo.analysis">
48
+ <span class="txt">【本题解析】:</span>
49
+ <div class="txt-box">
50
+ <span class="analysis-txt" v-html="questionInfo.analysisHtmlContent"></span>
51
+ </div>
52
+ </div>
53
+ </div>
54
+ </div>
55
+ </div>
56
+ <!--
57
+ 兼容性写法,两个都写
58
+ vue2支持.sync
59
+ vue3支持v-model:
60
+ :visible.sync="visible"
61
+ v-model:visible="visible"
62
+ -->
63
+ <MediaLooker :visible.sync="visible"
64
+ v-model:visible="visible"
65
+ v-if="visible"
66
+ :mediaCount="curMediaCount"
67
+ :mediaLookerList="mediaLookerList"></MediaLooker>
68
+ </div>
69
+ </template>
70
+ <script>
71
+
72
+ import {commonData,doMediaLookerSome} from './mixin'
73
+ import MediaLooker from '../common/MediaLooker.vue'
74
+ import fun from "../../assets/js/fun";
75
+
76
+ export default {
77
+ name: 'Question_MultipleChoice',
78
+ props: {
79
+ isSub:{
80
+ type: Boolean,
81
+ default: false
82
+ },
83
+ orderIndex:{
84
+ type: Number,
85
+ default: 0
86
+ },
87
+ questionInfo: {
88
+ type: Object,
89
+ default: {}
90
+ },
91
+ bus: {
92
+ type: Object,
93
+ default: {}
94
+ },
95
+ mode: {
96
+ type: String,
97
+ default: 'exam'
98
+ }
99
+ },
100
+ mounted() {
101
+ doMediaLookerSome(this)
102
+ this.$watch('checkboxList',(nv)=>{
103
+ let self = this
104
+ let isSub = this.isSub
105
+ let answered = this.isAnswered()
106
+ this.$emit('getIsAnswered',answered)
107
+ if(!isSub){
108
+ this.mode === 'exam' && this.bus.$emit('questionCardChange',{
109
+ questionIndex:this.questionInfo.questionIndex - 1,
110
+ answered
111
+ })
112
+ }else{
113
+ this.mode === 'exam' && this.bus.$emit('optionChange')
114
+ this.mode === 'exam' && this.$emit('optionChange', {orderIndex:this.orderIndex,isAnswered:self.isAnswered()})
115
+ }
116
+ },{
117
+ immediate:true
118
+ })
119
+ },
120
+ data() {
121
+ return {
122
+ checkboxList:[],
123
+ analyCorrectAnswer:'',
124
+ exam_options_data:[],
125
+ answerMap:{},
126
+ ...JSON.parse(commonData)
127
+ };
128
+ },
129
+ watch: {
130
+ questionInfo:{
131
+ handler(nv,ov){
132
+ if(nv){
133
+ this.exam_options_data = nv.exam_options_data
134
+ this.answerMap = nv.answerMap
135
+ //回显答案
136
+ if(nv.answerMap){
137
+ if(this.mode === 'analysis'){
138
+ this.analyCorrectAnswer = this.getCorrectStr(this.questionInfo.correct_multiple_index_set)
139
+ }
140
+ let multiple_index_set = this.questionInfo.answerMap.multiple_index_set
141
+ if(multiple_index_set && multiple_index_set.length){
142
+ this.checkboxList = JSON.parse(JSON.stringify(multiple_index_set))
143
+ // analysis的时候在这里标记tab已读,因为改变的时候限定了exam了
144
+ this.$emit('optionChange', {orderIndex:this.orderIndex,isAnswered:this.isAnswered()})
145
+ }
146
+ }
147
+ }
148
+ },
149
+ immediate:true
150
+ }
151
+ },
152
+ computed:{
153
+ },
154
+ methods: {
155
+ getAnswer(){
156
+ let self = this
157
+ return {multiple_index_set:self.checkboxList}
158
+ },
159
+ isAnswered(){
160
+ let answerd = this.checkboxList.length !== 0
161
+ return answerd
162
+ },
163
+ isCorrect(){
164
+ let correct = this.questionInfo.answerMap.is_correct === '1' ? true : false
165
+ return correct
166
+ },
167
+ getCorrectStr(correct_multiple_index_set){
168
+ let str = ''
169
+ correct_multiple_index_set.forEach((item,index)=>{
170
+ str += `${fun.indexToEnIndex(item)}${index === correct_multiple_index_set.length -1?'':'、'}`
171
+ })
172
+ return str
173
+ }
174
+ },
175
+ components:{
176
+ MediaLooker
177
+ }
178
+ };
179
+ </script>