index.vue 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088
  1. <!-- eslint-disable vue/no-v-html -->
  2. <template>
  3. <div class="article-preview" :style="[getAreaStyle(), getComponentStyle()]">
  4. <SerialNumberPosition v-if="isEnable(data.property.sn_display_mode)" :property="data.property" />
  5. <div class="main">
  6. <div class="NPC-ArticleView NPC-ArticleView-container">
  7. <div class="ArticleView-header">
  8. <a class="ArticleView-full" :title="convertText('黑板模式')" @click="fullScreen">
  9. <svg-icon
  10. icon-class="icon-full"
  11. size="24"
  12. :style="{
  13. color: data.unified_attrib && data.unified_attrib.topic_color ? data.unified_attrib.topic_color : '',
  14. }"
  15. />
  16. </a>
  17. <div>
  18. <!-- v-if="
  19. (tokenData && tokenData.popedom_code_list && tokenData.popedom_code_list.indexOf(2100001) != -1) ||
  20. (tokenData && tokenData.user_type === 'APP')
  21. " -->
  22. <div
  23. class="left"
  24. :style="{ marginLeft: '40px', cursor: 'pointer' }"
  25. :title="convertText('文本分析')"
  26. @click="submit"
  27. >
  28. <!-- <img src="@/assets/wbfx-icon.png" alt="" /> -->
  29. <svg-icon
  30. icon-class="icon-wbfx"
  31. size="24"
  32. :style="{
  33. color: data.unified_attrib && data.unified_attrib.topic_color ? data.unified_attrib.topic_color : '',
  34. }"
  35. />
  36. </div>
  37. </div>
  38. <div class="right">
  39. <!-- <template v-if="data.property.is_enable_new_word === 'true'">
  40. <el-switch
  41. v-model="showPhrases"
  42. style="display: block"
  43. :active-color="bookInfo.theme_color"
  44. inactive-color="rgba(0,0,0,0.1)"
  45. active-text=""
  46. inactive-text="本课生词"
  47. @change="handleSwitchChange('showPractice', 'showWord')"
  48. />
  49. </template>
  50. <template v-if="data.property.is_enable_read === 'true'">
  51. <el-switch
  52. v-model="showPractice"
  53. style="display: block"
  54. :active-color="bookInfo.theme_color"
  55. inactive-color="rgba(0,0,0,0.1)"
  56. active-text=""
  57. inactive-text="语音练习"
  58. @change="handleSwitchChange('showPhrases', 'showWord')"
  59. />
  60. </template>
  61. <template v-if="data.property.is_enable_word === 'true'">
  62. <el-switch
  63. v-model="showWord"
  64. style="display: block"
  65. :active-color="bookInfo.theme_color"
  66. inactive-color="rgba(0,0,0,0.1)"
  67. active-text=""
  68. inactive-text="取词"
  69. @change="handleSwitchChange('showPhrases', 'showPractice')"
  70. />
  71. </template> -->
  72. <a
  73. v-if="data.property.is_enable_new_word === 'true'"
  74. :style="{
  75. color:
  76. showPhrases && data.unified_attrib && data.unified_attrib.topic_color
  77. ? data.unified_attrib.topic_color
  78. : '',
  79. }"
  80. :title="convertText('本课生词')"
  81. @click="handleSwitchChange('showPractice', 'showWord', 'showPhrases')"
  82. >
  83. <svg-icon icon-class="icon-article-ci" size="24" />
  84. </a>
  85. <a
  86. v-if="data.property.is_enable_read === 'true'"
  87. :style="{
  88. color:
  89. showPractice && data.unified_attrib && data.unified_attrib.topic_color
  90. ? data.unified_attrib.topic_color
  91. : '',
  92. }"
  93. :title="convertText('语音练习')"
  94. @click="handleSwitchChange('showPhrases', 'showWord', 'showPractice')"
  95. >
  96. <svg-icon icon-class="icon-article-practice" size="24" />
  97. </a>
  98. <a
  99. v-if="data.property.is_enable_word === 'true'"
  100. :style="{
  101. color:
  102. showWord && data.unified_attrib && data.unified_attrib.topic_color
  103. ? data.unified_attrib.topic_color
  104. : '',
  105. }"
  106. :title="convertText('取词模式')"
  107. @click="handleSwitchChange('showPhrases', 'showPractice', 'showWord')"
  108. >
  109. <svg-icon icon-class="icon-article-phrase" size="24" />
  110. </a>
  111. </div>
  112. </div>
  113. <div ref="ArticleViewbody" class="ArticleView-body">
  114. <NormalModelChs
  115. v-if="!showPhrases && !showPractice && !showWord"
  116. :cur-que="data"
  117. :title-fontsize="titleFontsize"
  118. :word-fontsize="wordFontsize"
  119. :body-left="bodyLeft"
  120. :body-width="bodyWidth"
  121. :attrib="data.unified_attrib"
  122. :is-mobile="isMobile"
  123. :no-font="noFont"
  124. :config="config"
  125. :NNPEAnnotationList="NNPEAnnotationList"
  126. :col-length="colLength"
  127. :multilingual="showLang && getLang() ? getLang() : ''"
  128. @changeConfig="changeConfig"
  129. />
  130. <PhraseModel
  131. v-if="showPhrases"
  132. :cur-que="data"
  133. :title-fontsize="titleFontsize"
  134. :word-fontsize="wordFontsize"
  135. :NNPENewWordList="NNPENewWordList"
  136. :attrib="data.unified_attrib"
  137. :is-mobile="isMobile"
  138. :no-font="noFont"
  139. :body-left="bodyLeft"
  140. :config="config"
  141. :TaskModel="isJudgingRightWrong ? 'ANSWER' : ''"
  142. :NNPEAnnotationList="NNPEAnnotationList"
  143. :col-length="colLength"
  144. :NpcNewWordMp3="NpcNewWordMp3"
  145. :multilingual="showLang && getLang() ? getLang() : ''"
  146. @changeConfig="changeConfig"
  147. />
  148. <Practice
  149. v-if="showPractice"
  150. :cur-que="data"
  151. :title-fontsize="titleFontsize"
  152. :word-fontsize="wordFontsize"
  153. :attrib="data.unified_attrib"
  154. :is-mobile="isMobile"
  155. :no-font="noFont"
  156. :NNPENewWordList="NNPENewWordList"
  157. :NNPEAnnotationList="NNPEAnnotationList"
  158. :config="config"
  159. :TaskModel="isJudgingRightWrong ? 'ANSWER' : ''"
  160. :col-length="colLength"
  161. :NpcNewWordMp3="NpcNewWordMp3"
  162. :is-full="isFull"
  163. :multilingual="showLang && getLang() ? getLang() : ''"
  164. @changeConfig="changeConfig"
  165. />
  166. <WordModel
  167. v-if="showWord"
  168. :cur-que="data"
  169. :title-fontsize="titleFontsize"
  170. :word-fontsize="wordFontsize"
  171. :body-left="bodyLeft"
  172. :body-width="bodyWidth"
  173. :NNPENewWordList="NNPENewWordList"
  174. :attrib="data.unified_attrib"
  175. :is-mobile="isMobile"
  176. :no-font="noFont"
  177. :config="config"
  178. :TaskModel="isJudgingRightWrong ? 'ANSWER' : ''"
  179. :col-length="colLength"
  180. :multilingual="showLang && getLang() ? getLang() : ''"
  181. @changeConfig="changeConfig"
  182. />
  183. </div>
  184. <div :id="'screen-' + mathNum" class="voice-full-screen">
  185. <Voicefullscreen
  186. v-if="isFull && resObj"
  187. :theme-color="bookInfo.theme_color"
  188. :cur-que="data"
  189. :sent-list="resObj.sentList"
  190. :sent-index="0"
  191. :mp3="data.mp3_list && data.mp3_list[0] ? data.mp3_list[0].url : ''"
  192. :no-font="noFont"
  193. :NNPENewWordList="NNPENewWordList"
  194. :NNPEAnnotationList="NNPEAnnotationList"
  195. :is-full="isFull"
  196. :config="config"
  197. :TaskModel="isJudgingRightWrong ? 'ANSWER' : ''"
  198. :NpcNewWordMp3="NpcNewWordMp3"
  199. :attrib="data.unified_attrib"
  200. :is-mobile="isMobile"
  201. @handleWav="handleWav"
  202. @changePinyin="changePinyins"
  203. @changeEN="changeENs"
  204. @exitFullscreen="exitFullscreen"
  205. @changeIsFull="changeIsFull"
  206. />
  207. </div>
  208. </div>
  209. <template
  210. v-if="
  211. data.new_word_list &&
  212. data.new_word_list.new_word_list &&
  213. data.new_word_list.new_word_list.length > 0 &&
  214. data.new_word_list.property.is_show === 'true'
  215. "
  216. >
  217. <NewWordPreview :new-data="data.new_word_list" :is-mobile="isMobile" />
  218. </template>
  219. <template
  220. v-if="
  221. data.other_word_list &&
  222. data.other_word_list.new_word_list &&
  223. data.other_word_list.new_word_list.length > 0 &&
  224. data.other_word_list.property.is_show === 'true'
  225. "
  226. >
  227. <NewWordPreview :new-data="data.other_word_list" :is-mobile="isMobile" />
  228. </template>
  229. <template
  230. v-if="
  231. data.notes_list &&
  232. data.notes_list.option &&
  233. data.notes_list.option.length > 0 &&
  234. data.notes_list.property.is_show === 'true'
  235. "
  236. >
  237. <NotesPreview :notes-data="data.notes_list" :is-mobile="isMobile" />
  238. </template>
  239. </div>
  240. </div>
  241. </template>
  242. <script>
  243. import { getArticleData } from '@/views/book/courseware/data/dialogueArticle';
  244. import PreviewMixin from '../common/PreviewMixin';
  245. import PhraseModel from './PhraseModelChs.vue';
  246. import NormalModelChs from './NormalModelChs.vue';
  247. import Practice from './Practicechs.vue'; // 语音练习模式
  248. import WordModel from './WordModelChs.vue'; // 语音练习模式
  249. import Voicefullscreen from '../article/Voicefullscreen.vue';
  250. import { getToken } from '@/utils/auth';
  251. import { GetFileURLMap } from '@/api/app';
  252. import { analysSubmit, getSysConfig } from '@/api/article';
  253. import NewWordPreview from '../new_word/NewWordPreview.vue';
  254. import NotesPreview from '../notes/NotesPreview.vue';
  255. export default {
  256. name: 'DialogueArticlePreview',
  257. components: {
  258. NormalModelChs,
  259. Practice,
  260. WordModel,
  261. PhraseModel,
  262. Voicefullscreen,
  263. NewWordPreview,
  264. NotesPreview,
  265. },
  266. mixins: [PreviewMixin],
  267. inject: ['bookInfo'],
  268. props: ['isMobile'],
  269. data() {
  270. return {
  271. data: getArticleData(),
  272. showPreview: true, // 全文预览
  273. showPhrases: false, // 显示单词和短语
  274. showPractice: false, // 语音练习
  275. showWord: false, // 取词
  276. titleFontsize: 20, // 标题字号初始值
  277. wordFontsize: 16, // 文章内容字号初始值
  278. bodyLeft: 0,
  279. bodyWidth: 0,
  280. noFont: ['~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '/'],
  281. config: {
  282. isShowEN: false,
  283. isHasEN: false,
  284. isShowPY: false,
  285. isHasPY: false,
  286. },
  287. userAnswer: {
  288. normalModel: {
  289. recordList: [],
  290. },
  291. writeModel: {}, // 生词/取词模式
  292. practiceModel: {}, // 练习模式
  293. wordModel: {
  294. recordList: [],
  295. },
  296. },
  297. tokenData: getToken(),
  298. mathNum: Math.random().toString(36).substr(2),
  299. isFull: false,
  300. resObj: null,
  301. chsFhList: [',', '。', '”', ':', '》', '?', '!', ';', '、'],
  302. highWords: null,
  303. highWordsArr: [],
  304. highIndex: 0,
  305. newWordList: [],
  306. NNPEAnnotationList: [],
  307. NNPENewWordList: [],
  308. NpcNewWordMp3: [],
  309. colLength: 1,
  310. multilingualTextList: {},
  311. analyser_url: '',
  312. };
  313. },
  314. computed: {},
  315. watch: {
  316. showLang: {
  317. handler(val) {
  318. if (val) {
  319. this.data.multilingual.forEach((item) => {
  320. let trans_arr = item.translation ? item.translation.split('\n') : [];
  321. this.data.detail.forEach((items) => {
  322. let items_trans_arr = [];
  323. if (items && !items.hasOwnProperty('multilingualTextList')) {
  324. this.$set(items, 'multilingualTextList', {});
  325. }
  326. if (items.para) {
  327. items_trans_arr = trans_arr.splice(0, items.sentences.length);
  328. }
  329. this.$set(items.multilingualTextList, item.type, items_trans_arr);
  330. });
  331. });
  332. }
  333. },
  334. deep: true,
  335. immediate: true,
  336. },
  337. 'data.detail.length': {
  338. handler(val) {
  339. if (val) {
  340. this.handleData();
  341. let _this = this;
  342. _this.$nextTick(() => {
  343. _this.bodyLeft = _this.$refs.ArticleViewbody.getBoundingClientRect().left;
  344. });
  345. for (let i = 0; i < this.data.detail.length; i++) {
  346. let enStr = this.data.detail[i].sentencesEn ? this.data.detail[i].sentencesEn.join('') : '';
  347. if (enStr) {
  348. this.config.isShowEN = false;
  349. this.config.isHasEN = true;
  350. }
  351. let pinyin = this.handleObj(this.data.detail[i].wordsList);
  352. if (pinyin && this.isEnable(this.data.property.view_pinyin)) {
  353. this.config.isShowPY = true;
  354. this.config.isHasPY = true;
  355. }
  356. if (enStr && pinyin) {
  357. break;
  358. }
  359. }
  360. }
  361. },
  362. deep: true,
  363. immediate: true,
  364. },
  365. isJudgingRightWrong(val) {
  366. if (!val) return;
  367. this.data.Bookanswer = this.answer.answer_list;
  368. },
  369. },
  370. created() {},
  371. methods: {
  372. changeConfig(obj) {
  373. this.config[obj] = !this.config[obj];
  374. },
  375. changeIsFull() {
  376. this.isFull = false;
  377. },
  378. // 拼音的显示和隐藏
  379. changePinyins() {
  380. if (this.config.isHasPY) {
  381. this.changeConfig('isShowPY');
  382. }
  383. },
  384. // 英文的显示和隐藏
  385. changeENs() {
  386. if (this.config.isHasEN) {
  387. this.changeConfig('isShowEN');
  388. }
  389. },
  390. // 处理字体大小
  391. handleFontsize(symbol) {
  392. if (symbol === '+') {
  393. if (this.wordFontsize < 24) {
  394. this.titleFontsize += 2;
  395. this.wordFontsize += 2;
  396. }
  397. } else if (symbol === '-') {
  398. if (this.wordFontsize > 12) {
  399. this.titleFontsize -= 2;
  400. this.wordFontsize -= 2;
  401. }
  402. }
  403. },
  404. // 切换开关
  405. handleSwitchChange(obj1, obj2, obj3) {
  406. this[obj1] = false;
  407. this[obj2] = false;
  408. this[obj3] = !this[obj3];
  409. this.showPreview = false;
  410. },
  411. handleObj(list) {
  412. let pinyin = '';
  413. list.forEach((item) => {
  414. item.forEach((items) => {
  415. if (items.pinyin) pinyin += items.pinyin;
  416. });
  417. });
  418. return pinyin;
  419. },
  420. submit() {
  421. let access_token =
  422. this.tokenData && this.tokenData.gcls_sys_session_info
  423. ? this.tokenData.gcls_sys_session_info.access_token
  424. : this.tokenData && this.tokenData.access_token
  425. ? this.tokenDataaccess_token
  426. : '';
  427. let loading = this.$loading({
  428. lock: true,
  429. text: 'Loading',
  430. spinner: 'el-icon-loading',
  431. background: 'rgba(0, 0, 0, 0.7)',
  432. });
  433. getSysConfig()
  434. .then((ress) => {
  435. let content = '';
  436. this.data.detail.forEach((item) => {
  437. content += `${item.para}\n`;
  438. });
  439. analysSubmit({
  440. app_user_id: '',
  441. text: content,
  442. })
  443. .then((res) => {
  444. window.open(
  445. `${ress.text_analyser_page_address}GCLS-TC/#/textanalysis/Result?id=${res.record.id}&type=文本分析&AccessToken=${access_token}&fromEEP=true`,
  446. );
  447. loading.close();
  448. })
  449. .catch((res) => {
  450. loading.close();
  451. });
  452. })
  453. .catch((res) => {
  454. loading.close();
  455. });
  456. },
  457. // 语音全屏
  458. fullScreen() {
  459. this.pauseAudio();
  460. this.pauseVideo();
  461. this.isFull = true;
  462. // this.goFullscreen();
  463. },
  464. pauseAudio() {
  465. let audio = document.getElementsByTagName('audio');
  466. if (audio && audio.length > 0 && window.location.href.indexOf('GCLS-Learn') === -1 && audio.forEach) {
  467. audio.forEach((item) => {
  468. item.pause();
  469. });
  470. }
  471. },
  472. pauseVideo() {
  473. let video = document.getElementsByTagName('video');
  474. if (video && video.length > 0 && window.location.href.indexOf('GCLS-Learn') === -1 && video.forEach) {
  475. video.forEach((item) => {
  476. item.pause();
  477. });
  478. }
  479. },
  480. goFullscreen() {
  481. let id = `screen-${this.mathNum}`;
  482. let element = document.getElementById(id);
  483. if (element.requestFullscreen) {
  484. element.requestFullscreen();
  485. } else if (element.msRequestFullscreen) {
  486. element.msRequestFullscreen();
  487. } else if (element.mozRequestFullScreen) {
  488. element.mozRequestFullScreen();
  489. } else if (element.webkitRequestFullscreen) {
  490. element.webkitRequestFullscreen();
  491. }
  492. },
  493. exitFullscreen() {
  494. this.isFull = false;
  495. // if (document.exitFullscreen) {
  496. // document.exitFullscreen();
  497. // } else if (document.msExitFullscreen) {
  498. // document.msExitFullscreen();
  499. // } else if (document.mozCancelFullScreen) {
  500. // document.mozCancelFullScreen();
  501. // } else if (document.webkitExitFullscreen) {
  502. // document.webkitExitFullscreen();
  503. // }
  504. },
  505. handleData() {
  506. if (this.data.new_word_list) {
  507. this.$set(this.data.new_word_list, 'unified_attrib', this.data.unified_attrib);
  508. }
  509. if (this.data.other_word_list) {
  510. this.$set(this.data.other_word_list, 'unified_attrib', this.data.unified_attrib);
  511. }
  512. if (this.data.notes_list) {
  513. this.$set(this.data.notes_list, 'unified_attrib', this.data.unified_attrib);
  514. }
  515. if (this.showLang) {
  516. this.data.multilingual.forEach((item) => {
  517. let trans_arr = item.translation ? item.translation.split('\n') : [];
  518. this.data.detail.forEach((items) => {
  519. let items_trans_arr = [];
  520. if (!items.hasOwnProperty('multilingualTextList')) {
  521. this.$set(items, 'multilingualTextList', {});
  522. }
  523. if (items.para) {
  524. items_trans_arr = trans_arr.splice(0, items.sentences.length);
  525. }
  526. this.$set(items.multilingualTextList, item.type, items_trans_arr);
  527. });
  528. });
  529. }
  530. let userAnswer = JSON.parse(JSON.stringify(this.userAnswer));
  531. this.$set(this.data, 'Bookanswer', userAnswer);
  532. if (!this.isJudgingRightWrong) {
  533. this.answer.answer_list = this.data.Bookanswer;
  534. }
  535. if (this.data.mp3_list && this.data.mp3_list.length > 0) {
  536. this.data.mp3_list[0].url = this.data.mp3_list[0].temporary_url;
  537. // GetFileURLMap({ file_id_list: [this.data.mp3_list[0].file_id] }).then(({ url_map }) => {
  538. // this.data.mp3_list[0].url = url_map[this.data.mp3_list[0].file_id];
  539. // });
  540. }
  541. // 处理课文里生词表的音频和时间
  542. if (this.data.new_word_list && this.data.new_word_list.new_word_list) {
  543. if (this.data.new_word_list.audio_data && this.data.new_word_list.audio_data.temporary_url) {
  544. // 如果大音频存在
  545. this.data.new_word_list.new_word_list.forEach((item, index) => {
  546. this.$set(item, 'audio_file_url', this.data.new_word_list.audio_data.temporary_url);
  547. this.$set(
  548. item,
  549. 'audio_begin_time',
  550. this.data.new_word_list.lrc_arr[index] ? this.data.new_word_list.lrc_arr[index].bg : null,
  551. );
  552. this.$set(
  553. item,
  554. 'audio_end_time',
  555. this.data.new_word_list.lrc_arr[index] ? this.data.new_word_list.lrc_arr[index].ed : null,
  556. );
  557. });
  558. } else {
  559. let mp3_list = [];
  560. this.data.new_word_list.new_word_list.forEach((item, index) => {
  561. mp3_list.push(item.mp3_list);
  562. });
  563. GetFileURLMap({ file_id_list: mp3_list }).then(({ url_map }) => {
  564. this.data.new_word_list.new_word_list.forEach((item, index) => {
  565. this.$set(item, 'audio_file_url', url_map[item.mp3_list]);
  566. this.$set(item, 'audio_begin_time', null);
  567. this.$set(item, 'audio_end_time', null);
  568. });
  569. });
  570. }
  571. }
  572. // 处理课文里其他词汇表的音频和时间
  573. if (this.data.other_word_list && this.data.other_word_list.new_word_list) {
  574. if (this.data.other_word_list.audio_data && this.data.other_word_list.audio_data.temporary_url) {
  575. // 如果大音频存在
  576. this.data.other_word_list.new_word_list.forEach((item, index) => {
  577. this.$set(item, 'audio_file_url', this.data.other_word_list.audio_data.temporary_url);
  578. this.$set(
  579. item,
  580. 'audio_begin_time',
  581. this.data.other_word_list.lrc_arr[index] ? this.data.other_word_list.lrc_arr[index].bg : -1,
  582. );
  583. this.$set(
  584. item,
  585. 'audio_end_time',
  586. this.data.other_word_list.lrc_arr[index] ? this.data.other_word_list.lrc_arr[index].ed : -1,
  587. );
  588. });
  589. } else {
  590. let mp3_list = [];
  591. this.data.other_word_list.new_word_list.forEach((item, index) => {
  592. mp3_list.push(item.mp3_list);
  593. });
  594. GetFileURLMap({ file_id_list: mp3_list }).then(({ url_map }) => {
  595. this.data.other_word_list.new_word_list.forEach((item, index) => {
  596. this.$set(item, 'audio_file_url', url_map[item.mp3_list]);
  597. this.$set(item, 'audio_begin_time', null);
  598. this.$set(item, 'audio_end_time', null);
  599. });
  600. });
  601. }
  602. }
  603. if (this.data.new_word_list_other_component_input) {
  604. this.data.new_word_list_other_component_input.forEach((item) => {
  605. if (item.audio_begin_time === -1) {
  606. item.audio_begin_time = null;
  607. item.audio_end_time = null;
  608. }
  609. });
  610. }
  611. this.NNPENewWordList = (
  612. this.data.new_word_list_other_component_input ? this.data.new_word_list_other_component_input : []
  613. )
  614. .concat(
  615. this.data.new_word_list && this.data.new_word_list.new_word_list ? this.data.new_word_list.new_word_list : [],
  616. )
  617. .concat(
  618. this.data.other_word_list && this.data.other_word_list.new_word_list
  619. ? this.data.other_word_list.new_word_list
  620. : [],
  621. );
  622. this.NNPEAnnotationList = this.data.notes_list && this.data.notes_list.option ? this.data.notes_list.option : [];
  623. let resArr = [];
  624. let sentArrTotal = [];
  625. let timeArr = [];
  626. let curQue = JSON.parse(JSON.stringify(this.data));
  627. let wordTimeList = curQue.wordTime;
  628. let dhaspinyin = false; // 每段是否有拼音
  629. let dhaspinyinArr = [];
  630. curQue.detail.forEach((dItem, dIndex) => {
  631. dhaspinyin = false;
  632. dItem.wordsList.forEach((sItem, sIndex) => {
  633. let sentArr = [];
  634. let sentence = dItem.sentences[sIndex];
  635. sItem.forEach((wItem, wIndex) => {
  636. let startIndex = wIndex === 0 ? 0 : sentArr[wIndex - 1].startIndex + sentArr[wIndex - 1].chs.length;
  637. let endIndex = wIndex === 0 ? wItem.chs.length : sentArr[wIndex - 1].endIndex + wItem.chs.length;
  638. // this.judgePad(sItem, wItem, wIndex);
  639. this.mergeWordSymbol(wItem);
  640. let words = '';
  641. if (this.newWordList.length > 0) {
  642. if (!this.highWords) {
  643. this.findLightWord(wItem, wIndex, sentence, sItem);
  644. words = this.highWords ? this.highWords.words : '';
  645. } else if (wIndex > this.highWords.endIndex - 1) {
  646. this.highWords = null;
  647. this.findLightWord(wItem, wIndex, sentence, sItem);
  648. words = this.highWords ? this.highWords.words : '';
  649. } else {
  650. words = this.highWords ? this.highWords.words : '';
  651. }
  652. }
  653. let obj = {
  654. paraIndex: dIndex, // 段落索引
  655. sentIndex: sIndex, // 在段落中句子索引
  656. wordIndex: wIndex, // 单词的索引
  657. pinyin: wItem.pinyin,
  658. chs: wItem.chs,
  659. padding: true,
  660. className: wItem.className,
  661. isShow: wItem.isShow,
  662. startIndex,
  663. endIndex,
  664. leg: wItem.chs.length,
  665. timeList: [],
  666. words,
  667. config: {
  668. fontFamily: wItem.fontFamily,
  669. color: wItem.color,
  670. textDecoration: wItem.textDecoration,
  671. border: wItem.border,
  672. fontWeight: wItem.fontWeight,
  673. },
  674. matchWords: wItem.matchWords,
  675. matchNotes: wItem.matchNotes,
  676. notesColor: wItem.notesColor,
  677. matchNotesObj: wItem.matchNotesObj,
  678. img: wItem.img,
  679. imgPosition: wItem.imgPosition,
  680. };
  681. sentArr.push(obj);
  682. if (wItem.pinyin) dhaspinyin = true;
  683. });
  684. let objs = {
  685. sentArr,
  686. enwords: dItem.sentencesEn && dItem.sentencesEn[sIndex] && dItem.sentencesEn[sIndex].replace(/'/g, '’'),
  687. };
  688. sentArrTotal.push(sentArr);
  689. resArr.push(objs);
  690. });
  691. timeArr.push(dItem.timeList);
  692. if (this.isEnable(curQue.property.view_pinyin)) {
  693. dhaspinyinArr.push(dhaspinyin);
  694. }
  695. });
  696. if (wordTimeList && wordTimeList.length > 0) {
  697. this.mergeWordTime(sentArrTotal, wordTimeList);
  698. }
  699. let timeList = [];
  700. timeArr.forEach((item) => {
  701. item.forEach((aItem) => {
  702. if (timeList.indexOf(aItem) < 0) {
  703. timeList.push(aItem);
  704. }
  705. });
  706. });
  707. this.resObj = {
  708. sentList: resArr,
  709. timeList,
  710. dhaspinyinArr,
  711. };
  712. },
  713. mergeWordTime(resArr, wordTimeList) {
  714. resArr.forEach((item, index) => {
  715. let wordsResultList = wordTimeList[index].wordsResultList;
  716. item.forEach((wItem) => {
  717. let startIndex = wItem.startIndex;
  718. let endIndex = wItem.endIndex;
  719. wItem.timeList = wordsResultList.slice(startIndex, endIndex);
  720. });
  721. });
  722. },
  723. findLightWord(wItem, startIndex, sentence, sItem) {
  724. let endIndex = 0;
  725. let words = '';
  726. this.newWordList.forEach((item) => {
  727. if (item.length === 1) {
  728. if (item === wItem.chs && !wItem.banLight) {
  729. words = wItem.chs;
  730. endIndex = startIndex + 1;
  731. }
  732. } else if (item[0] === wItem.chs && sentence.indexOf(item) > -1) {
  733. let index = null;
  734. let chsStr = '';
  735. for (let i = startIndex; i < sItem.length + 1; i++) {
  736. index = i;
  737. if (chsStr.length === item.length) {
  738. break;
  739. } else {
  740. chsStr += sItem[i] ? sItem[i].chs : '';
  741. }
  742. }
  743. if (chsStr === item && !wItem.banLight) {
  744. words = item;
  745. endIndex = index;
  746. }
  747. } else if (wItem.new_word && wItem.new_word === item && !wItem.banLight) {
  748. words = item;
  749. endIndex = startIndex + 1;
  750. }
  751. });
  752. if (words) {
  753. this.highWords = { words, endIndex };
  754. } else {
  755. this.highWords = null;
  756. }
  757. },
  758. // 词和标点合一起
  759. mergeWordSymbol(wItem) {
  760. if (this.chsFhList.indexOf(wItem.chs) > -1) {
  761. wItem.isShow = false;
  762. } else {
  763. wItem.isShow = true;
  764. }
  765. },
  766. handleWav(list, tmIndex) {
  767. let i = tmIndex || 0;
  768. this.data.Bookanswer.practiceModel[i] = {
  769. recordList: [],
  770. };
  771. this.$set(this.data.Bookanswer.practiceModel[i], 'recordList', list);
  772. },
  773. handleNewword() {
  774. let NewWordList = [];
  775. this.NNPENewWordList.forEach((wItem) => {
  776. // item.forEach((wItem) => {
  777. if (wItem.new_word) {
  778. NewWordList.push(wItem.new_word);
  779. } else if (wItem.detail && wItem.detail.sentence) {
  780. NewWordList.push(wItem.detail.sentence);
  781. }
  782. // });
  783. });
  784. this.newWordList = JSON.parse(JSON.stringify(NewWordList));
  785. },
  786. /**
  787. * 获取无文本内容的数据结构,用于保存为个人模板时的样式模板
  788. */
  789. getNoTextContentData() {
  790. let noTextContentData = JSON.parse(JSON.stringify(this.data));
  791. const resetFieldMap = {
  792. content: '', // 课文内容
  793. mp3_list: [], // 音频列表
  794. detail: [], // 分段分句分词详情
  795. wordTime: [], // 字幕时间
  796. new_word_list: {
  797. title_con: '',
  798. property: {
  799. audio_generation_method: 'upload',
  800. pinyin_position: 'front',
  801. auto_wrap: 'true', // 自动换行
  802. is_has_infor: 'true',
  803. voice_type: '', // 音色
  804. emotion: '', // 风格,情感
  805. speed_ratio: '', // 语速
  806. is_show: 'false',
  807. },
  808. new_word_list: [],
  809. lrc_arr: [], // lrc 文件解析后的数据
  810. // lrc 文件数据
  811. lrc_data: {
  812. name: '',
  813. url: '',
  814. id: '',
  815. file_id: '',
  816. },
  817. // 音频文件数据
  818. audio_data: {
  819. name: '',
  820. media_duration: 0,
  821. temporary_url: '',
  822. url: '',
  823. file_id: '',
  824. },
  825. wordTime: [], // 字幕时间节点
  826. taskId: '',
  827. file_id_list: [], // 文件 id
  828. multilingual: [], // 多语言
  829. }, // 生词列表
  830. other_word_list: {
  831. title_con: '',
  832. property: {
  833. audio_generation_method: 'upload',
  834. pinyin_position: 'front',
  835. auto_wrap: 'true', // 自动换行
  836. is_has_infor: 'true',
  837. voice_type: '', // 音色
  838. emotion: '', // 风格,情感
  839. speed_ratio: '', // 语速
  840. is_show: 'false',
  841. },
  842. new_word_list: [],
  843. lrc_arr: [], // lrc 文件解析后的数据
  844. // lrc 文件数据
  845. lrc_data: {
  846. name: '',
  847. url: '',
  848. id: '',
  849. file_id: '',
  850. },
  851. // 音频文件数据
  852. audio_data: {
  853. name: '',
  854. media_duration: 0,
  855. temporary_url: '',
  856. url: '',
  857. file_id: '',
  858. },
  859. wordTime: [], // 字幕时间节点
  860. taskId: '',
  861. file_id_list: [], // 文件 id
  862. multilingual: [], // 多语言
  863. },
  864. notes_list: {
  865. title_con: '',
  866. option: [],
  867. multilingual: [], // 多语言
  868. file_id_list: [], // 文件 id
  869. property: {
  870. view_pinyin: 'false', // 显示拼音
  871. pinyin_position: 'back', // top bottom
  872. is_first_sentence_first_hz_pinyin_first_char_upper_case: 'true', // 句首大写
  873. is_show: 'false',
  874. },
  875. },
  876. sentence_list_mp: [], // 句子+分词数组
  877. pinyin_type: 'pinyin',
  878. };
  879. Object.assign(noTextContentData, resetFieldMap);
  880. return noTextContentData;
  881. },
  882. },
  883. };
  884. </script>
  885. <style lang="scss" scoped>
  886. @use '@/styles/mixin.scss' as *;
  887. .article-preview {
  888. @include preview-base;
  889. .main {
  890. display: grid;
  891. row-gap: 24px;
  892. // align-items: center;
  893. }
  894. .NPC-ArticleView {
  895. width: 100%;
  896. .ArticleView-full {
  897. position: absolute;
  898. top: 0;
  899. left: 0;
  900. z-index: 1;
  901. font-size: 16px;
  902. font-weight: bold;
  903. line-height: 24px;
  904. color: #000;
  905. cursor: pointer;
  906. // background: url('@/assets/full-screen-red.png') left center no-repeat;
  907. // background-size: 20px 20px;
  908. }
  909. .ArticleView-header {
  910. position: relative;
  911. display: flex;
  912. align-items: center;
  913. justify-content: space-between;
  914. height: 24px;
  915. margin-bottom: 16px;
  916. .left {
  917. display: flex;
  918. align-items: center;
  919. justify-content: center;
  920. // padding-left: 24px;
  921. font-size: 16px;
  922. font-weight: bold;
  923. line-height: 24px;
  924. cursor: pointer;
  925. // background: url('@/assets/wbfx-icon.png') left center no-repeat;
  926. // background-size: 20px;
  927. img {
  928. width: 20px;
  929. height: 20px;
  930. margin-right: 4px;
  931. }
  932. }
  933. .right {
  934. display: flex;
  935. gap: 24px;
  936. a {
  937. display: flex;
  938. gap: 4px;
  939. align-items: center;
  940. color: rgba(0, 0, 0, 65%);
  941. cursor: pointer;
  942. }
  943. }
  944. .setting-fontsize {
  945. display: flex;
  946. margin-left: 24px;
  947. a {
  948. box-sizing: border-box;
  949. display: block;
  950. width: 24px;
  951. height: 24px;
  952. border: 1px solid rgba(0, 0, 0, 10%);
  953. border-radius: 4px;
  954. }
  955. img {
  956. width: 100%;
  957. }
  958. > img {
  959. width: 24px;
  960. margin: 0 8px;
  961. }
  962. }
  963. }
  964. .ArticleView-body {
  965. box-sizing: border-box;
  966. border: 1px solid rgba(0, 0, 0, 10%);
  967. border-radius: 4px;
  968. .aduioLine-box {
  969. width: 100%;
  970. border-bottom: 1px solid rgba(0, 0, 0, 10%);
  971. &-bottom {
  972. border-top: 1px solid rgba(0, 0, 0, 10%);
  973. border-bottom: none;
  974. }
  975. }
  976. }
  977. }
  978. }
  979. </style>
  980. <style lang="scss">
  981. .NPC-ArticleView {
  982. .ArticleView-header {
  983. .el-switch {
  984. margin-left: 24px;
  985. }
  986. .el-switch__core {
  987. width: 44px !important;
  988. height: 24px;
  989. border-radius: 20px;
  990. }
  991. .el-switch__core::after {
  992. top: 3px;
  993. left: 3px;
  994. }
  995. .el-switch.is-checked .el-switch__core::after {
  996. left: 100%;
  997. margin-left: -19px;
  998. }
  999. .el-switch__label {
  1000. color: #000;
  1001. }
  1002. .el-switch__label.is-active {
  1003. color: rgba($color: #000, $alpha: 30%);
  1004. }
  1005. .el-switch__label--left {
  1006. margin-right: 8px;
  1007. }
  1008. }
  1009. .pinyin-16 {
  1010. cursor: pointer;
  1011. // background: url('@/assets/icon/pinyin-16-normal-red.png') no-repeat left top;
  1012. // background-size: 100% 100%;
  1013. // &.disabled {
  1014. // background: url('@/assets/icon/pinyin-16-disable-Black.png') no-repeat left top;
  1015. // background-size: 100% 100%;
  1016. // }
  1017. }
  1018. .EN-16 {
  1019. cursor: pointer;
  1020. // background: url('@/assets/icon/EN-16-normal-red.png') no-repeat left top;
  1021. // background-size: 100% 100%;
  1022. // &.disabled {
  1023. // background: url('@/assets/icon/EN-16-disable-Black.png') no-repeat left top;
  1024. // background-size: 100% 100%;
  1025. // }
  1026. }
  1027. }
  1028. .ArticleView-body {
  1029. .aduioLine-box {
  1030. width: 100%;
  1031. border-bottom: 1px solid rgba(0, 0, 0, 10%);
  1032. &-bottom {
  1033. border-top: 1px solid rgba(0, 0, 0, 10%);
  1034. border-bottom: none;
  1035. }
  1036. }
  1037. .el-slider {
  1038. flex: 1;
  1039. width: auto !important;
  1040. }
  1041. }
  1042. </style>