Select.vue 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. <template>
  2. <ModuleBase :type="data.type">
  3. <template #content>
  4. <ul class="option-list">
  5. <li v-for="(item, i) in data.option_list" :key="item.mark" class="option-item">
  6. <span class="serial-number">{{ convertNumberToLetter(i) }}.</span>
  7. <div class="option-contnet">
  8. <span :class="['checkbox', { active: isAnswer(item.mark) }]" @click="selectAnswer(item.mark)">
  9. <SvgIcon icon-class="check-mark" width="10" height="7" />
  10. </span>
  11. <RichText v-model="item.content" placeholder="输入内容" :inline="true" :height="32" />
  12. </div>
  13. <span class="multilingual" @click="openMultilingual(i)">
  14. <SvgIcon icon-class="multilingual" class-name="multilingual" width="12" height="12" />
  15. </span>
  16. <span class="delete" @click="deleteOption">
  17. <SvgIcon icon-class="delete-2" width="12" height="12" />
  18. </span>
  19. </li>
  20. </ul>
  21. <div class="add">
  22. <SvgIcon icon-class="add-circle" width="14" height="14" />
  23. <span class="add-button" @click="addOption">增加选项</span>
  24. </div>
  25. <el-divider v-if="isEnable(data.property.view_pinyin)" content-position="left">拼音效果</el-divider>
  26. <PinyinText
  27. v-for="(item, i) in data.option_list"
  28. v-show="isEnable(data.property.view_pinyin)"
  29. :key="i"
  30. ref="PinyinText"
  31. :paragraph-list="item.paragraph_list"
  32. :pinyin-position="data.property.pinyin_position"
  33. @fillCorrectPinyin="fillCorrectPinyin($event, i)"
  34. />
  35. <MultilingualFill
  36. v-if="curSelectIndex !== -1"
  37. :visible.sync="multilingualVisible"
  38. :text="data.option_list[curSelectIndex].content"
  39. :translations="data.option_list[curSelectIndex].multilingual"
  40. @SubmitTranslation="handleMultilingualTranslation"
  41. />
  42. </template>
  43. </ModuleBase>
  44. </template>
  45. <script>
  46. import ModuleMixin from '../../common/ModuleMixin';
  47. import PinyinText from '@/components/PinyinText.vue';
  48. import { getSelectData, getOption, arrangeTypeList } from '@/views/book/courseware/data/select';
  49. export default {
  50. name: 'SelectPage',
  51. components: {
  52. PinyinText,
  53. },
  54. mixins: [ModuleMixin],
  55. data() {
  56. return {
  57. data: getSelectData(),
  58. curSelectIndex: -1,
  59. };
  60. },
  61. watch: {
  62. 'data.property.arrange_type': 'handlerMindMap',
  63. 'data.answer.answer_list': 'handlerMindMap',
  64. 'data.property': {
  65. handler({ view_pinyin }) {
  66. if (!this.isEnable(view_pinyin)) {
  67. this.data.option_list.forEach((item) => {
  68. item.paragraph_list = [];
  69. item.paragraph_list_parameter = {
  70. text: '',
  71. pinyin_proofread_word_list: [],
  72. };
  73. });
  74. return;
  75. }
  76. if (this.data.option_list.length > 0 && this.data.option_list[0].paragraph_list.length > 0) return;
  77. this.data.option_list.forEach((item, i) => {
  78. const text = item.content.replace(/<[^>]+>/g, '');
  79. if (!text) return;
  80. item.paragraph_list_parameter.text = text;
  81. this.createParsedTextInfoPinyin(text, i);
  82. });
  83. },
  84. deep: true,
  85. },
  86. },
  87. methods: {
  88. // 将数字转换为小写字母
  89. convertNumberToLetter(number) {
  90. return String.fromCharCode(97 + number);
  91. },
  92. /**
  93. * @description 判断是否为答案
  94. * @param {string} mark 选项标记
  95. */
  96. isAnswer(mark) {
  97. return this.data.answer.answer_list.includes(mark);
  98. },
  99. /**
  100. * @description 选择答案
  101. * @param {string} mark 选项标记
  102. */
  103. selectAnswer(mark) {
  104. const index = this.data.answer.answer_list.indexOf(mark);
  105. if (index === -1) {
  106. this.data.answer.answer_list.push(mark);
  107. } else {
  108. this.data.answer.answer_list.splice(index, 1);
  109. }
  110. },
  111. /**
  112. * @description 添加选项
  113. */
  114. addOption() {
  115. this.data.option_list.push(getOption());
  116. },
  117. /**
  118. * @description 删除选项
  119. * @param {number} index 选项索引
  120. */
  121. deleteOption(index) {
  122. this.data.option_list.splice(index, 1);
  123. },
  124. handlerMindMap() {
  125. const direction = this.data.property.arrange_type === arrangeTypeList[0].value ? '横排' : '竖排';
  126. const select = this.data.answer.answer_list.length > 1 ? '多选' : '单选';
  127. this.data.mind_map.node_list = [{ name: `${direction}${select}选择题` }];
  128. },
  129. openMultilingual(i) {
  130. this.curSelectIndex = i;
  131. this.multilingualVisible = true;
  132. },
  133. handleMultilingualTranslation(translations) {
  134. this.$set(this.data.option_list[this.curSelectIndex], 'multilingual', translations);
  135. },
  136. },
  137. };
  138. </script>
  139. <style lang="scss" scoped>
  140. .option-list {
  141. display: flex;
  142. flex-direction: column;
  143. row-gap: 8px;
  144. .option-item {
  145. display: flex;
  146. column-gap: 8px;
  147. align-items: center;
  148. min-height: 36px;
  149. .serial-number {
  150. width: 40px;
  151. height: 36px;
  152. padding: 4px 8px;
  153. color: $text-color;
  154. background-color: $fill-color;
  155. border-radius: 2px;
  156. }
  157. .option-contnet {
  158. display: flex;
  159. flex: 1;
  160. column-gap: 6px;
  161. align-items: center;
  162. padding: 0 12px;
  163. overflow: hidden;
  164. background-color: $fill-color;
  165. .checkbox {
  166. display: flex;
  167. align-items: center;
  168. justify-content: center;
  169. width: 16px;
  170. height: 16px;
  171. cursor: pointer;
  172. background-color: #fff;
  173. border: 1px solid #dcdfe6;
  174. border-radius: 2px;
  175. .svg-icon {
  176. display: none;
  177. }
  178. &.active {
  179. color: #fff;
  180. background-color: #000;
  181. .svg-icon {
  182. display: block;
  183. }
  184. }
  185. }
  186. }
  187. .delete,
  188. .multilingual {
  189. margin-left: 8px;
  190. cursor: pointer;
  191. }
  192. }
  193. }
  194. .add {
  195. display: flex;
  196. column-gap: 6px;
  197. align-items: center;
  198. justify-content: center;
  199. margin-top: 12px;
  200. .svg-icon {
  201. cursor: pointer;
  202. }
  203. .add-button {
  204. font-size: 14px;
  205. color: $main-color;
  206. cursor: pointer;
  207. }
  208. }
  209. </style>