JudgeQuestion.vue 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. <template>
  2. <QuestionBase>
  3. <template #content>
  4. <div class="stem">
  5. <RichText v-model="data.stem" :font-size="18" placeholder="输入题干" />
  6. <RichText
  7. v-if="isEnable(data.property.is_enable_description)"
  8. v-model="data.description"
  9. placeholder="输入提示"
  10. />
  11. </div>
  12. <div class="content">
  13. <ul>
  14. <li v-for="(item, i) in data.option_list" :key="i" class="content-item">
  15. <el-input v-if="isEnable(isEnableManualModify)" v-model="item.custom_number" class="manual-modify" />
  16. <span v-else class="question-number" title="双击切换序号类型" @dblclick="changeOptionType(data)">
  17. {{ computedQuestionNumber(i, data.option_number_show_mode) }}
  18. </span>
  19. <div class="option-content">
  20. <RichText v-model="item.content" placeholder="输入内容" :inline="true" />
  21. </div>
  22. <div class="option-type">
  23. <div
  24. v-for="option_type in data.property.option_type_list"
  25. :key="option_type"
  26. :class="[
  27. 'option-type-item',
  28. {
  29. active: data.answer.answer_list.find(
  30. (li) => li.mark === item.mark && li.option_type === option_type,
  31. ),
  32. },
  33. ]"
  34. @click="selectOptionAnswer(option_type, item.mark)"
  35. >
  36. <SvgIcon
  37. v-if="option_type === option_type_list[0].value"
  38. icon-class="check-mark"
  39. width="10"
  40. height="7"
  41. />
  42. <SvgIcon v-if="option_type === option_type_list[1].value" icon-class="cross" size="8" />
  43. <SvgIcon v-if="option_type === option_type_list[2].value" icon-class="circle" size="10" />
  44. </div>
  45. </div>
  46. <SvgIcon icon-class="delete" class="delete pointer" @click="deleteOption(i)" />
  47. </li>
  48. </ul>
  49. </div>
  50. <div class="footer">
  51. <span class="add-option" @click="addOption">
  52. <SvgIcon icon-class="add-circle" size="14" /> <span>增加选项</span>
  53. </span>
  54. </div>
  55. <div v-if="isEnable(data.property.is_enable_analysis)" class="analysis">
  56. <div class="analysis-title">解析:</div>
  57. <RichText v-model="data.analysis" :is-border="true" :font-size="14" placeholder="输入解析" />
  58. </div>
  59. </template>
  60. <template #property>
  61. <el-form :model="data.property" label-width="72px" label-position="left">
  62. <el-form-item label="题号">
  63. <el-input v-model="data.property.question_number" />
  64. </el-form-item>
  65. <el-form-item>
  66. <el-radio
  67. v-for="{ value, label } in questionNumberTypeList"
  68. :key="value"
  69. v-model="data.other.question_number_type"
  70. :label="value"
  71. >
  72. {{ label }}
  73. </el-radio>
  74. </el-form-item>
  75. <el-form-item label="提示">
  76. <el-radio
  77. v-for="{ value, label } in switchOption"
  78. :key="value"
  79. v-model="data.property.is_enable_description"
  80. :label="value"
  81. >
  82. {{ label }}
  83. </el-radio>
  84. </el-form-item>
  85. <el-form-item label="解析">
  86. <el-radio
  87. v-for="{ value, label } in switchOption"
  88. :key="value"
  89. v-model="data.property.is_enable_analysis"
  90. :label="value"
  91. >
  92. {{ label }}
  93. </el-radio>
  94. </el-form-item>
  95. <el-form-item label="题干题号">
  96. <el-select v-model="data.property.stem_question_number_font_size">
  97. <el-option v-for="item in fontSizeList" :key="item" :label="item" :value="item" />
  98. </el-select>
  99. </el-form-item>
  100. <el-form-item label="选项题号">
  101. <el-select v-model="data.property.option_question_number_font_size">
  102. <el-option v-for="item in fontSizeList" :key="item" :label="item" :value="item" />
  103. </el-select>
  104. </el-form-item>
  105. <el-form-item label="选项">
  106. <el-checkbox-group v-model="optionTypeList">
  107. <el-checkbox v-for="{ label, value } in option_type_list" :key="value" :label="label" />
  108. </el-checkbox-group>
  109. </el-form-item>
  110. <el-form-item label="分值">
  111. <el-radio
  112. v-for="{ value, label } in scoreTypeList"
  113. :key="value"
  114. v-model="data.property.score_type"
  115. :label="value"
  116. >
  117. {{ label }}
  118. </el-radio>
  119. </el-form-item>
  120. <el-form-item>
  121. <el-input-number
  122. v-model="data.property.score"
  123. :min="0"
  124. :step="data.property.score_type === scoreTypeList[0].value ? 1 : 0.1"
  125. />
  126. </el-form-item>
  127. </el-form>
  128. </template>
  129. </QuestionBase>
  130. </template>
  131. <script>
  132. import QuestionMixin from '../common/QuestionMixin.js';
  133. import { changeOptionType } from '@/views/exercise_questions/data/common';
  134. import {
  135. getJudgeData,
  136. option_type_list,
  137. option_type_value_list,
  138. getOption,
  139. analysisRecognitionJudgeData,
  140. } from '@/views/exercise_questions/data/judge';
  141. export default {
  142. name: 'JudgeQuestion',
  143. mixins: [QuestionMixin],
  144. props: {
  145. isEnableManualModify: {
  146. type: String,
  147. default: 'false',
  148. },
  149. },
  150. data() {
  151. return {
  152. option_type_list,
  153. changeOptionType,
  154. data: getJudgeData(),
  155. };
  156. },
  157. computed: {
  158. optionTypeList: {
  159. get() {
  160. if (!this.data.property.option_type_list) {
  161. return [];
  162. }
  163. return this.data.property.option_type_list
  164. .map((item) => {
  165. let type = this.option_type_list.find(({ value }) => value === item);
  166. return type ? type.label : '';
  167. })
  168. .filter((word) => word && word.length > 0);
  169. },
  170. set(val) {
  171. this.data.property.option_type_list = val
  172. .map((item) => {
  173. let type = this.option_type_list.find(({ label }) => label === item);
  174. return type ? type.value : '';
  175. })
  176. .filter((word) => word && word.length > 0)
  177. .sort((a, b) => option_type_value_list.indexOf(a) - option_type_value_list.indexOf(b));
  178. },
  179. },
  180. },
  181. watch: {
  182. isEnableManualModify: {
  183. handler(val) {
  184. if (val === 'false') return;
  185. this.data.option_list = this.data.option_list.map((item, i) => {
  186. return { ...item, custom_number: `${i + 1}` };
  187. });
  188. },
  189. },
  190. },
  191. methods: {
  192. addOption() {
  193. this.data.option_list.push(getOption());
  194. },
  195. /**
  196. * 智能识别
  197. * @param {String} text 识别数据
  198. */
  199. recognition(text) {
  200. let arr = this.recognitionCommon(text);
  201. let obj = analysisRecognitionJudgeData(arr);
  202. this.recognitionCommonSetObj(obj);
  203. this.data.answer.answer_list = [];
  204. },
  205. /**
  206. * 选择选项答案
  207. * @param {String} option_type 选项类型
  208. * @param {String} mark 选项标记
  209. */
  210. selectOptionAnswer(option_type, mark) {
  211. const index = this.data.answer.answer_list.findIndex((item) => item.mark === mark);
  212. if (index === -1) {
  213. this.data.answer.answer_list.push({ option_type, mark });
  214. } else {
  215. this.data.answer.answer_list[index].option_type = option_type;
  216. }
  217. },
  218. },
  219. };
  220. </script>
  221. <style lang="scss" scoped>
  222. .content {
  223. &-item {
  224. .manual-modify {
  225. width: 55px;
  226. :deep .el-input__inner {
  227. height: 36px;
  228. }
  229. }
  230. .option-type {
  231. display: flex;
  232. column-gap: 8px;
  233. align-items: center;
  234. height: 32px;
  235. padding: 8px 16px;
  236. background-color: $fill-color;
  237. &-item {
  238. display: flex;
  239. align-items: center;
  240. justify-content: center;
  241. width: 16px;
  242. height: 16px;
  243. color: $font-light-color;
  244. cursor: pointer;
  245. background-color: #d7d7d7;
  246. border-radius: 2px;
  247. &.active {
  248. color: #fff;
  249. background-color: $main-color;
  250. }
  251. }
  252. }
  253. }
  254. }
  255. </style>