SelectQuestion.vue 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. <!-- 选择题 -->
  2. <template>
  3. <QuestionBase>
  4. <template #content>
  5. <div class="stem">
  6. <el-input
  7. v-if="data.property.stem_type === stemTypeList[0].value"
  8. v-model="data.stem"
  9. rows="3"
  10. resize="none"
  11. type="textarea"
  12. placeholder="输入题干"
  13. />
  14. <RichText v-if="data.property.stem_type === stemTypeList[1].value" v-model="data.stem" placeholder="输入题干" />
  15. <el-input
  16. v-show="isEnable(data.property.is_enable_description)"
  17. v-model="data.description"
  18. rows="3"
  19. resize="none"
  20. type="textarea"
  21. placeholder="输入描述"
  22. />
  23. <UploadAudio
  24. v-show="isEnable(data.property.is_enable_listening)"
  25. :file-id="data.file_id_list?.[0]"
  26. @upload="upload"
  27. @deleteFile="deleteFile"
  28. />
  29. </div>
  30. <div class="content">
  31. <ul>
  32. <li v-for="(item, i) in data.option_list" :key="i" class="content-item">
  33. <span class="question-number" title="双击切换序号类型" @dblclick="changeOptionType(data)">
  34. {{ computedQuestionNumber(i, data.option_number_show_mode) }}
  35. </span>
  36. <div class="option-content">
  37. <span :class="['checkbox', { active: isAnswer(item.mark) }]" @click="selectAnswer(item.mark)"></span>
  38. <RichText v-model="item.content" placeholder="输入内容" :inline="true" />
  39. </div>
  40. <SvgIcon icon-class="delete" class="delete pointer" @click="deleteOption(i)" />
  41. </li>
  42. </ul>
  43. </div>
  44. <div class="footer">
  45. <span class="add-option" @click="addOption">
  46. <SvgIcon icon-class="add-circle" size="14" /> <span>增加选项</span>
  47. </span>
  48. </div>
  49. </template>
  50. <template #property>
  51. <el-form :model="data.property">
  52. <el-form-item label="题干">
  53. <el-radio
  54. v-for="{ value, label } in stemTypeList"
  55. :key="value"
  56. v-model="data.property.stem_type"
  57. :label="value"
  58. >
  59. {{ label }}
  60. </el-radio>
  61. </el-form-item>
  62. <el-form-item label="题号">
  63. <el-input v-model="data.property.question_number" />
  64. </el-form-item>
  65. <el-form-item label-width="45px">
  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 selectTypeList"
  88. :key="value"
  89. v-model="data.property.select_type"
  90. :label="value"
  91. @input="changeSelectType"
  92. >
  93. {{ label }}
  94. </el-radio>
  95. </el-form-item>
  96. <!-- TODO 选项细分 -->
  97. <!-- <el-form-item label="选项细分">
  98. <el-radio
  99. v-for="{ value, label } in switchOption"
  100. :key="value"
  101. v-model="data.property.is_option_subdivision"
  102. :label="value"
  103. @input="changeSelectType"
  104. >
  105. {{ label }}
  106. </el-radio>
  107. </el-form-item>
  108. <el-form-item label-width="72px">
  109. <el-input-number
  110. v-model="data.property.option_number"
  111. :min="2"
  112. :max="5"
  113. :step="1"
  114. :disabled="!isEnable(data.property.is_option_subdivision)"
  115. />
  116. </el-form-item> -->
  117. <el-form-item label="听力">
  118. <el-radio
  119. v-for="{ value, label } in switchOption"
  120. :key="value"
  121. v-model="data.property.is_enable_listening"
  122. :label="value"
  123. >
  124. {{ label }}
  125. </el-radio>
  126. </el-form-item>
  127. <el-form-item label="分值">
  128. <el-radio
  129. v-for="{ value, label } in scoreTypeList"
  130. :key="value"
  131. v-model="data.property.score_type"
  132. :label="value"
  133. :disabled="scoreTypeList[1].value === value && data.property.select_type === selectTypeList[0].value"
  134. >
  135. {{ label }}
  136. </el-radio>
  137. </el-form-item>
  138. <el-form-item label-width="45px">
  139. <el-input-number
  140. v-model="data.property.score"
  141. :min="0"
  142. :step="data.property.score_type === scoreTypeList[0].value ? 1 : 0.1"
  143. />
  144. </el-form-item>
  145. </el-form>
  146. </template>
  147. </QuestionBase>
  148. </template>
  149. <script>
  150. import UploadAudio from '../common/UploadAudio.vue';
  151. import QuestionMixin from '../common/QuestionMixin.js';
  152. import { selectTypeList, scoreTypeList, changeOptionType } from '@/views/exercise_questions/data/common';
  153. import { getSelectData, getOption } from '@/views/exercise_questions/data/select';
  154. export default {
  155. name: 'SelectQuestion',
  156. components: {
  157. UploadAudio,
  158. },
  159. mixins: [QuestionMixin],
  160. data() {
  161. return {
  162. selectTypeList,
  163. changeOptionType,
  164. data: getSelectData(),
  165. };
  166. },
  167. methods: {
  168. /**
  169. * 智能识别
  170. * @param {String} text 识别数据
  171. */
  172. recognition(text) {
  173. let arr = text
  174. .split(/[\r\n]/)
  175. .map((item) => item.trim())
  176. .filter((item) => item);
  177. if (arr.length > 0) {
  178. this.data.stem = arr[0];
  179. this.data.option_list = arr.slice(1).map((content) => getOption(content));
  180. }
  181. },
  182. changeSelectType(val) {
  183. if (val === selectTypeList[0].value && this.data.answer.answer_list.length > 1) {
  184. this.data.answer.answer_list = [this.data.answer.answer_list[0]];
  185. }
  186. // 当多选题切换到单选题时,分值类型切换为总分
  187. if (val === selectTypeList[0].value && this.data.property.score_type === scoreTypeList[1].value) {
  188. this.data.property.score_type = scoreTypeList[0].value;
  189. }
  190. },
  191. isAnswer(mark) {
  192. return this.data.answer.answer_list.includes(mark);
  193. },
  194. selectAnswer(mark) {
  195. let index = this.data.answer.answer_list.indexOf(mark);
  196. if (this.data.property.select_type === selectTypeList[0].value) {
  197. this.data.answer.answer_list = [mark];
  198. }
  199. if (this.data.property.select_type === selectTypeList[1].value) {
  200. if (index === -1) {
  201. this.data.answer.answer_list.push(mark);
  202. } else {
  203. this.data.answer.answer_list.splice(index, 1);
  204. }
  205. }
  206. },
  207. addOption() {
  208. this.data.option_list.push(getOption());
  209. },
  210. },
  211. };
  212. </script>
  213. <style lang="scss" scoped>
  214. .content {
  215. .option-content {
  216. .checkbox {
  217. display: inline-flex;
  218. align-items: center;
  219. justify-content: center;
  220. width: 16px;
  221. height: 16px;
  222. margin-right: 8px;
  223. cursor: pointer;
  224. border: 1px solid #333;
  225. border-radius: 50%;
  226. &.active {
  227. &::before {
  228. display: inline-block;
  229. width: 6px;
  230. height: 6px;
  231. content: '';
  232. background-color: #333;
  233. border-radius: 50%;
  234. }
  235. }
  236. }
  237. }
  238. }
  239. </style>