Write.vue 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. <template>
  2. <ModuleBase :type="data.type">
  3. <template #content>
  4. <!-- eslint-disable max-len -->
  5. <div class="write-wrapper">
  6. <template v-if="data.property.content_type === 'con'">
  7. <el-input v-model="data.content" placeholder="输入" type="textarea" @change="handleChangeContent"></el-input>
  8. <span class="tips">输入字或词请一字一行</span>
  9. </template>
  10. <template v-else>
  11. <UploadFile
  12. :courseware-id="courseware_id"
  13. :component-id="id"
  14. :type="'picture'"
  15. :single-size="data.single_size"
  16. :total-size="data.total_size"
  17. :file-list="data.file_list"
  18. :file-id-list="data.file_id_list"
  19. :file-info-list="data.file_info_list"
  20. :label-text="labelText"
  21. :accept-file-type="acceptFileType"
  22. :upload-tip="uploadTip"
  23. :icon-class="iconClass"
  24. @updateFileList="updateFileList"
  25. />
  26. </template>
  27. <template v-if="data.content_list.length > 0">
  28. <el-divider content-position="left">拼音效果</el-divider>
  29. <div class="content-list">
  30. <div
  31. v-for="(item, index) in data.content_list"
  32. :key="index"
  33. title="点击校对拼音"
  34. @click="correctPinyin1(item.con, index)"
  35. >
  36. <span>{{ item.pinyin }}</span>
  37. <b>{{ item.con }}</b>
  38. </div>
  39. </div>
  40. </template>
  41. <CorrectPinyin :visible.sync="visible" :select-content="selectContent" @fillTonePinyin="fillTonePinyin" />
  42. </div>
  43. </template>
  44. </ModuleBase>
  45. </template>
  46. <script>
  47. import ModuleMixin from '../../common/ModuleMixin';
  48. import SoundRecord from '@/views/book/courseware/create/components/question/fill/components/SoundRecord.vue';
  49. import UploadAudio from '@/views/book/courseware/create/components/question/fill/components/UploadAudio.vue';
  50. import UploadFile from '@/views/book/courseware/create/components/base/common/UploadFile.vue';
  51. import { getWriteData } from '@/views/book/courseware/data/write';
  52. import { GetStaticResources } from '@/api/app';
  53. import cnchar from 'cnchar';
  54. import { getRandomNumber } from '@/utils';
  55. import CorrectPinyin from '@/views/book/courseware/create/components/base/common/CorrectPinyin.vue';
  56. export default {
  57. name: 'WritePage',
  58. components: {
  59. SoundRecord,
  60. UploadAudio,
  61. UploadFile,
  62. CorrectPinyin,
  63. },
  64. mixins: [ModuleMixin],
  65. data() {
  66. return {
  67. data: getWriteData(),
  68. labelText: '图片',
  69. acceptFileType: '.png,.jpg',
  70. uploadTip:
  71. 'The size of the uploaded image should not exceed 2MB, the size of the uploaded audio file, pdf file, and excel file should not exceed 20MB, and the size of the uploaded audio file should not exceed 20MB',
  72. iconClass: 'picture',
  73. visible: false,
  74. selectContent: '',
  75. paragraph_index: 0,
  76. };
  77. },
  78. methods: {
  79. // 解析输入内容
  80. handleChangeContent() {
  81. if (this.data.content.trim()) {
  82. let contentArr = this.data.content.split('\n');
  83. let contentList = [];
  84. contentArr.forEach((item, index) => {
  85. if (item.trim()) {
  86. let content_arr = item.trim().split('');
  87. let content_arrs = [];
  88. let content_arr_strokes = [];
  89. content_arr.forEach((itemc) => {
  90. if (itemc.trim()) {
  91. content_arrs.push(itemc.trim());
  92. }
  93. });
  94. content_arrs.forEach((itemc, indexc) => {
  95. content_arr_strokes.push(null);
  96. let MethodName = 'hz_resource_manager-GetHZStrokesContent';
  97. let data = {
  98. hz: itemc,
  99. };
  100. GetStaticResources(MethodName, data).then((res) => {
  101. let obj = {
  102. hz: itemc.trim(),
  103. strokes: res,
  104. };
  105. content_arr_strokes[indexc] = obj;
  106. });
  107. });
  108. contentList.push({
  109. con: item.trim(),
  110. pinyin: cnchar.spell(item.trim(), 'array', 'low', 'tone').join(' '),
  111. audio_file_id: '',
  112. hz_strokes_list: content_arr_strokes,
  113. mark: getRandomNumber(),
  114. });
  115. this.handleMatic(item.trim(), contentList.length - 1);
  116. }
  117. });
  118. this.data.content_list = contentList;
  119. } else {
  120. this.data.content_list = [];
  121. }
  122. },
  123. // 自动生成音频
  124. handleMatic(con, index) {
  125. GetStaticResources('tool-TextToVoiceFile', {
  126. text: con.replace(/<[^>]+>/g, ''),
  127. })
  128. .then(({ status, file_id }) => {
  129. if (status === 1) {
  130. this.data.content_list[index].audio_file_id = file_id;
  131. }
  132. })
  133. .catch(() => {});
  134. },
  135. updateFileList({ file_list, file_id_list, file_info_list }) {
  136. file_list.forEach((item) => {
  137. item.mark = getRandomNumber();
  138. });
  139. this.data.file_list = file_list;
  140. this.data.file_id_list = file_id_list;
  141. this.data.file_info_list = file_info_list;
  142. },
  143. // 校对拼音
  144. correctPinyin1(text, i) {
  145. if (text) {
  146. this.visible = true;
  147. this.selectContent = text;
  148. this.paragraph_index = i;
  149. }
  150. },
  151. // 回填校对后的拼音
  152. fillTonePinyin(tonePinyin) {
  153. this.data.content_list[this.paragraph_index].pinyin = tonePinyin;
  154. let MethodName = 'tool-PinyinToVoiceFile';
  155. let data = {
  156. pinyin: tonePinyin.split(' ').join(','),
  157. };
  158. GetStaticResources(MethodName, data)
  159. .then((res) => {
  160. if (res.status === 1) {
  161. this.data.content_list[this.paragraph_index].audio_file_id = res.file_id;
  162. }
  163. })
  164. .catch(() => {});
  165. },
  166. },
  167. };
  168. </script>
  169. <style lang="scss" scoped>
  170. .write-wrapper {
  171. display: flex;
  172. flex-direction: column;
  173. row-gap: 16px;
  174. align-items: flex-start;
  175. :deep .rich-wrapper {
  176. width: 100%;
  177. }
  178. .tips {
  179. font-size: 12px;
  180. color: #999;
  181. }
  182. .content-list {
  183. display: flex;
  184. flex-wrap: wrap;
  185. gap: 8px 8px;
  186. div {
  187. text-align: center;
  188. cursor: pointer;
  189. span {
  190. font-family: 'League';
  191. }
  192. b {
  193. display: block;
  194. font-family: '楷体';
  195. font-weight: normal;
  196. }
  197. }
  198. }
  199. .auto-matic,
  200. .upload-audio-play {
  201. :deep .upload-wrapper {
  202. margin-top: 0;
  203. }
  204. .audio-wrapper {
  205. :deep .audio-play {
  206. width: 16px;
  207. height: 16px;
  208. color: #000;
  209. background-color: initial;
  210. }
  211. :deep .audio-play.not-url {
  212. color: #a1a1a1;
  213. }
  214. :deep .voice-play {
  215. width: 16px;
  216. height: 16px;
  217. }
  218. }
  219. }
  220. .auto-matic {
  221. display: flex;
  222. flex-shrink: 0;
  223. column-gap: 12px;
  224. align-items: center;
  225. width: 200px;
  226. padding: 5px 12px;
  227. background-color: $fill-color;
  228. border-radius: 2px;
  229. .auto-btn {
  230. font-size: 16px;
  231. font-weight: 400;
  232. line-height: 22px;
  233. color: #1d2129;
  234. cursor: pointer;
  235. }
  236. }
  237. .correct-answer {
  238. display: flex;
  239. flex-wrap: wrap;
  240. gap: 8px;
  241. .el-input {
  242. width: 180px;
  243. :deep &__prefix {
  244. display: flex;
  245. align-items: center;
  246. color: $text-color;
  247. }
  248. }
  249. }
  250. }
  251. </style>