MatchingQuestion.vue 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  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. <div v-for="(li, j) in item" :key="li.mark" class="item-cell">
  16. <span v-if="j === 0" class="question-number">
  17. {{ i + 1 }}
  18. </span>
  19. <RichText v-model="li.content" placeholder="输入内容" :inline="true" />
  20. <span v-if="data.property.column_number > j + 1" class="horizontal-line"></span>
  21. <SvgIcon
  22. v-if="data.property.column_number === j + 1"
  23. icon-class="delete"
  24. class="delete pointer"
  25. @click="deleteOption(i)"
  26. />
  27. </div>
  28. </li>
  29. </ul>
  30. </div>
  31. <div class="footer">
  32. <span class="add-option" @click="addOption">
  33. <SvgIcon icon-class="add-circle" size="14" /> <span>增加选项</span>
  34. </span>
  35. </div>
  36. </template>
  37. <template #property>
  38. <el-form :model="data.property">
  39. <el-form-item label="题号">
  40. <el-input v-model="data.property.question_number" />
  41. </el-form-item>
  42. <el-form-item label-width="45px">
  43. <el-radio
  44. v-for="{ value, label } in questionNumberTypeList"
  45. :key="value"
  46. v-model="data.other.question_number_type"
  47. :label="value"
  48. >
  49. {{ label }}
  50. </el-radio>
  51. </el-form-item>
  52. <el-form-item label="题干题号">
  53. <el-select v-model="data.property.stem_question_number_font_size">
  54. <el-option v-for="item in fontSizeList" :key="item" :label="item" :value="item" />
  55. </el-select>
  56. </el-form-item>
  57. <el-form-item label="提示">
  58. <el-radio
  59. v-for="{ value, label } in switchOption"
  60. :key="value"
  61. v-model="data.property.is_enable_description"
  62. :label="value"
  63. >
  64. {{ label }}
  65. </el-radio>
  66. </el-form-item>
  67. <el-form-item label="列数">
  68. <el-radio
  69. v-for="{ value, label } in columnNumberList"
  70. :key="value"
  71. v-model="data.property.column_number"
  72. :label="value"
  73. @input="changeColumnNumber"
  74. >
  75. {{ label }}
  76. </el-radio>
  77. </el-form-item>
  78. <el-form-item label="分值">
  79. <el-radio
  80. v-for="{ value, label } in scoreTypeList"
  81. :key="value"
  82. v-model="data.property.score_type"
  83. :label="value"
  84. >
  85. {{ label }}
  86. </el-radio>
  87. </el-form-item>
  88. <el-form-item label-width="45px">
  89. <el-input-number
  90. v-model="data.property.score"
  91. :min="0"
  92. :step="data.property.score_type === scoreTypeList[0].value ? 1 : 0.1"
  93. />
  94. </el-form-item>
  95. </el-form>
  96. </template>
  97. </QuestionBase>
  98. </template>
  99. <script>
  100. import RichText from '@/components/common/RichText.vue';
  101. import QuestionMixin from '../common/QuestionMixin.js';
  102. import { columnNumberList, getOption, getMatchingDataTemplate } from '@/views/exercise_questions/data/matching';
  103. export default {
  104. name: 'MatchingQuestion',
  105. components: { RichText },
  106. mixins: [QuestionMixin],
  107. data() {
  108. return {
  109. columnNumberList,
  110. data: getMatchingDataTemplate(),
  111. };
  112. },
  113. watch: {
  114. 'data.option_list': {
  115. handler(val) {
  116. if (!val) {
  117. return;
  118. }
  119. this.data.answer.answer_list = val.map((item) => {
  120. return item.map(({ mark }) => mark);
  121. });
  122. },
  123. deep: true,
  124. },
  125. },
  126. methods: {
  127. addOption() {
  128. let newOption = [];
  129. for (let i = 0; i < this.data.property.column_number; i++) {
  130. newOption.push(getOption());
  131. }
  132. this.data.option_list.push(newOption);
  133. },
  134. /**
  135. * 修改列数后,修改选项列表
  136. * @param {Number} val 列数
  137. */
  138. changeColumnNumber(val) {
  139. this.data.option_list = this.data.option_list.map((item) => {
  140. let len = item.length;
  141. if (len > val) {
  142. item.splice(val);
  143. } else if (len < val) {
  144. for (let i = 0; i < val - len; i++) {
  145. item.push(getOption());
  146. }
  147. }
  148. return item;
  149. });
  150. },
  151. },
  152. };
  153. </script>
  154. <style lang="scss" scoped>
  155. .content {
  156. &-item {
  157. .item-cell {
  158. display: flex;
  159. flex: 1;
  160. column-gap: 4px;
  161. align-items: center;
  162. .rich-wrapper {
  163. flex: 1;
  164. min-height: 32px;
  165. background-color: $fill-color;
  166. :deep .rich-text {
  167. &.mce-content-body {
  168. padding-top: 4px;
  169. padding-left: 12px;
  170. }
  171. &:not(.mce-edit-focus) {
  172. p {
  173. margin: 0;
  174. }
  175. }
  176. &.mce-content-body[data-mce-placeholder]:not(.mce-visualblocks)::before {
  177. top: 6px;
  178. left: 12px;
  179. }
  180. }
  181. }
  182. }
  183. }
  184. }
  185. </style>