index.vue 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011
  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 { analysSubmit, getSysConfig } from '@/api/article';
  252. import NewWordPreview from '../new_word/NewWordPreview.vue';
  253. import NotesPreview from '../notes/NotesPreview.vue';
  254. export default {
  255. name: 'DialogueArticlePreview',
  256. components: {
  257. NormalModelChs,
  258. Practice,
  259. WordModel,
  260. PhraseModel,
  261. Voicefullscreen,
  262. NewWordPreview,
  263. NotesPreview,
  264. },
  265. mixins: [PreviewMixin],
  266. inject: ['bookInfo'],
  267. props: ['isMobile'],
  268. data() {
  269. return {
  270. data: getArticleData(),
  271. showPreview: true, // 全文预览
  272. showPhrases: false, // 显示单词和短语
  273. showPractice: false, // 语音练习
  274. showWord: false, // 取词
  275. titleFontsize: 20, // 标题字号初始值
  276. wordFontsize: 16, // 文章内容字号初始值
  277. bodyLeft: 0,
  278. bodyWidth: 0,
  279. noFont: ['~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '/'],
  280. config: {
  281. isShowEN: false,
  282. isHasEN: false,
  283. isShowPY: false,
  284. isHasPY: false,
  285. },
  286. userAnswer: {
  287. normalModel: {
  288. recordList: [],
  289. },
  290. writeModel: {}, // 生词/取词模式
  291. practiceModel: {}, // 练习模式
  292. wordModel: {
  293. recordList: [],
  294. },
  295. },
  296. tokenData: getToken(),
  297. mathNum: Math.random().toString(36).substr(2),
  298. isFull: false,
  299. resObj: null,
  300. chsFhList: [',', '。', '”', ':', '》', '?', '!', ';', '、'],
  301. highWords: null,
  302. highWordsArr: [],
  303. highIndex: 0,
  304. newWordList: [],
  305. NNPEAnnotationList: [],
  306. NNPENewWordList: [],
  307. NpcNewWordMp3: [],
  308. colLength: 1,
  309. multilingualTextList: {},
  310. analyser_url: '',
  311. };
  312. },
  313. computed: {},
  314. watch: {
  315. showLang: {
  316. handler(val) {
  317. if (val) {
  318. this.data.multilingual.forEach((item) => {
  319. let trans_arr = item.translation ? item.translation.split('\n') : [];
  320. this.data.detail.forEach((items) => {
  321. let items_trans_arr = [];
  322. if (items && !items.hasOwnProperty('multilingualTextList')) {
  323. this.$set(items, 'multilingualTextList', {});
  324. }
  325. if (items.para) {
  326. items_trans_arr = trans_arr.splice(0, items.sentences.length);
  327. }
  328. this.$set(items.multilingualTextList, item.type, items_trans_arr);
  329. });
  330. });
  331. }
  332. },
  333. deep: true,
  334. immediate: true,
  335. },
  336. 'data.detail.length': {
  337. handler(val) {
  338. if (val) {
  339. this.handleData();
  340. let _this = this;
  341. _this.$nextTick(() => {
  342. _this.bodyLeft = _this.$refs.ArticleViewbody.getBoundingClientRect().left;
  343. });
  344. for (let i = 0; i < this.data.detail.length; i++) {
  345. let enStr = this.data.detail[i].sentencesEn ? this.data.detail[i].sentencesEn.join('') : '';
  346. if (enStr) {
  347. this.config.isShowEN = false;
  348. this.config.isHasEN = true;
  349. }
  350. let pinyin = this.handleObj(this.data.detail[i].wordsList);
  351. if (pinyin && this.isEnable(this.data.property.view_pinyin)) {
  352. this.config.isShowPY = true;
  353. this.config.isHasPY = true;
  354. }
  355. if (enStr && pinyin) {
  356. break;
  357. }
  358. }
  359. }
  360. },
  361. deep: true,
  362. immediate: true,
  363. },
  364. isJudgingRightWrong(val) {
  365. if (!val) return;
  366. this.data.Bookanswer = this.answer.answer_list;
  367. },
  368. },
  369. created() {},
  370. methods: {
  371. changeConfig(obj) {
  372. this.config[obj] = !this.config[obj];
  373. },
  374. changeIsFull() {
  375. this.isFull = false;
  376. },
  377. // 拼音的显示和隐藏
  378. changePinyins() {
  379. if (this.config.isHasPY) {
  380. this.changeConfig('isShowPY');
  381. }
  382. },
  383. // 英文的显示和隐藏
  384. changeENs() {
  385. if (this.config.isHasEN) {
  386. this.changeConfig('isShowEN');
  387. }
  388. },
  389. // 处理字体大小
  390. handleFontsize(symbol) {
  391. if (symbol === '+') {
  392. if (this.wordFontsize < 24) {
  393. this.titleFontsize += 2;
  394. this.wordFontsize += 2;
  395. }
  396. } else if (symbol === '-') {
  397. if (this.wordFontsize > 12) {
  398. this.titleFontsize -= 2;
  399. this.wordFontsize -= 2;
  400. }
  401. }
  402. },
  403. // 切换开关
  404. handleSwitchChange(obj1, obj2, obj3) {
  405. this[obj1] = false;
  406. this[obj2] = false;
  407. this[obj3] = !this[obj3];
  408. this.showPreview = false;
  409. },
  410. handleObj(list) {
  411. let pinyin = '';
  412. list.forEach((item) => {
  413. item.forEach((items) => {
  414. if (items.pinyin) pinyin += items.pinyin;
  415. });
  416. });
  417. return pinyin;
  418. },
  419. submit() {
  420. let access_token =
  421. this.tokenData && this.tokenData.gcls_sys_session_info ? this.tokenData.gcls_sys_session_info.access_token : '';
  422. let loading = this.$loading({
  423. lock: true,
  424. text: 'Loading',
  425. spinner: 'el-icon-loading',
  426. background: 'rgba(0, 0, 0, 0.7)',
  427. });
  428. getSysConfig()
  429. .then((ress) => {
  430. let content = '';
  431. this.data.detail.forEach((item) => {
  432. content += `${item.para}\n`;
  433. });
  434. analysSubmit({
  435. app_user_id: '',
  436. text: content,
  437. })
  438. .then((res) => {
  439. window.open(
  440. `${ress.text_analyser_page_address}GCLS-TC/#/textanalysis/Result?id=${res.record.id}&type=文本分析&AccessToken=${access_token}&fromEEP=true`,
  441. );
  442. loading.close();
  443. })
  444. .catch((res) => {
  445. loading.close();
  446. });
  447. })
  448. .catch((res) => {
  449. loading.close();
  450. });
  451. },
  452. // 语音全屏
  453. fullScreen() {
  454. this.pauseAudio();
  455. this.pauseVideo();
  456. this.isFull = true;
  457. // this.goFullscreen();
  458. },
  459. pauseAudio() {
  460. let audio = document.getElementsByTagName('audio');
  461. if (audio && audio.length > 0 && window.location.href.indexOf('GCLS-Learn') === -1 && audio.forEach) {
  462. audio.forEach((item) => {
  463. item.pause();
  464. });
  465. }
  466. },
  467. pauseVideo() {
  468. let video = document.getElementsByTagName('video');
  469. if (video && video.length > 0 && window.location.href.indexOf('GCLS-Learn') === -1 && video.forEach) {
  470. video.forEach((item) => {
  471. item.pause();
  472. });
  473. }
  474. },
  475. goFullscreen() {
  476. let id = `screen-${this.mathNum}`;
  477. let element = document.getElementById(id);
  478. if (element.requestFullscreen) {
  479. element.requestFullscreen();
  480. } else if (element.msRequestFullscreen) {
  481. element.msRequestFullscreen();
  482. } else if (element.mozRequestFullScreen) {
  483. element.mozRequestFullScreen();
  484. } else if (element.webkitRequestFullscreen) {
  485. element.webkitRequestFullscreen();
  486. }
  487. },
  488. exitFullscreen() {
  489. this.isFull = false;
  490. // if (document.exitFullscreen) {
  491. // document.exitFullscreen();
  492. // } else if (document.msExitFullscreen) {
  493. // document.msExitFullscreen();
  494. // } else if (document.mozCancelFullScreen) {
  495. // document.mozCancelFullScreen();
  496. // } else if (document.webkitExitFullscreen) {
  497. // document.webkitExitFullscreen();
  498. // }
  499. },
  500. handleData() {
  501. if (this.data.new_word_list) {
  502. this.$set(this.data.new_word_list, 'unified_attrib', this.data.unified_attrib);
  503. }
  504. if (this.data.other_word_list) {
  505. this.$set(this.data.other_word_list, 'unified_attrib', this.data.unified_attrib);
  506. }
  507. if (this.data.notes_list) {
  508. this.$set(this.data.notes_list, 'unified_attrib', this.data.unified_attrib);
  509. }
  510. if (this.showLang) {
  511. this.data.multilingual.forEach((item) => {
  512. let trans_arr = item.translation ? item.translation.split('\n') : [];
  513. this.data.detail.forEach((items) => {
  514. let items_trans_arr = [];
  515. if (!items.hasOwnProperty('multilingualTextList')) {
  516. this.$set(items, 'multilingualTextList', {});
  517. }
  518. if (items.para) {
  519. items_trans_arr = trans_arr.splice(0, items.sentences.length);
  520. }
  521. this.$set(items.multilingualTextList, item.type, items_trans_arr);
  522. });
  523. });
  524. }
  525. let userAnswer = JSON.parse(JSON.stringify(this.userAnswer));
  526. this.$set(this.data, 'Bookanswer', userAnswer);
  527. if (!this.isJudgingRightWrong) {
  528. this.answer.answer_list = this.data.Bookanswer;
  529. }
  530. if (this.data.mp3_list && this.data.mp3_list.length > 0) {
  531. this.data.mp3_list[0].url = this.data.mp3_list[0].temporary_url;
  532. // GetFileURLMap({ file_id_list: [this.data.mp3_list[0].file_id] }).then(({ url_map }) => {
  533. // this.data.mp3_list[0].url = url_map[this.data.mp3_list[0].file_id];
  534. // });
  535. }
  536. this.NNPENewWordList = (
  537. this.data.new_word_list_other_component_input ? this.data.new_word_list_other_component_input : []
  538. )
  539. .concat(
  540. this.data.new_word_list && this.data.new_word_list.new_word_list ? this.data.new_word_list.new_word_list : [],
  541. )
  542. .concat(
  543. this.data.other_word_list && this.data.other_word_list.new_word_list
  544. ? this.data.other_word_list.new_word_list
  545. : [],
  546. );
  547. this.NNPEAnnotationList = this.data.notes_list && this.data.notes_list.option ? this.data.notes_list.option : [];
  548. let resArr = [];
  549. let sentArrTotal = [];
  550. let timeArr = [];
  551. let curQue = JSON.parse(JSON.stringify(this.data));
  552. let wordTimeList = curQue.wordTime;
  553. let dhaspinyin = false; // 每段是否有拼音
  554. let dhaspinyinArr = [];
  555. curQue.detail.forEach((dItem, dIndex) => {
  556. dhaspinyin = false;
  557. dItem.wordsList.forEach((sItem, sIndex) => {
  558. let sentArr = [];
  559. let sentence = dItem.sentences[sIndex];
  560. sItem.forEach((wItem, wIndex) => {
  561. let startIndex = wIndex === 0 ? 0 : sentArr[wIndex - 1].startIndex + sentArr[wIndex - 1].chs.length;
  562. let endIndex = wIndex === 0 ? wItem.chs.length : sentArr[wIndex - 1].endIndex + wItem.chs.length;
  563. // this.judgePad(sItem, wItem, wIndex);
  564. this.mergeWordSymbol(wItem);
  565. let words = '';
  566. if (this.newWordList.length > 0) {
  567. if (!this.highWords) {
  568. this.findLightWord(wItem, wIndex, sentence, sItem);
  569. words = this.highWords ? this.highWords.words : '';
  570. } else if (wIndex > this.highWords.endIndex - 1) {
  571. this.highWords = null;
  572. this.findLightWord(wItem, wIndex, sentence, sItem);
  573. words = this.highWords ? this.highWords.words : '';
  574. } else {
  575. words = this.highWords ? this.highWords.words : '';
  576. }
  577. }
  578. let obj = {
  579. paraIndex: dIndex, // 段落索引
  580. sentIndex: sIndex, // 在段落中句子索引
  581. wordIndex: wIndex, // 单词的索引
  582. pinyin: wItem.pinyin,
  583. chs: wItem.chs,
  584. padding: true,
  585. className: wItem.className,
  586. isShow: wItem.isShow,
  587. startIndex,
  588. endIndex,
  589. leg: wItem.chs.length,
  590. timeList: [],
  591. words,
  592. config: {
  593. fontFamily: wItem.fontFamily,
  594. color: wItem.color,
  595. textDecoration: wItem.textDecoration,
  596. border: wItem.border,
  597. fontWeight: wItem.fontWeight,
  598. },
  599. matchWords: wItem.matchWords,
  600. matchNotes: wItem.matchNotes,
  601. notesColor: wItem.notesColor,
  602. matchNotesObj: wItem.matchNotesObj,
  603. img: wItem.img,
  604. imgPosition: wItem.imgPosition,
  605. };
  606. sentArr.push(obj);
  607. if (wItem.pinyin) dhaspinyin = true;
  608. });
  609. let objs = {
  610. sentArr,
  611. enwords: dItem.sentencesEn && dItem.sentencesEn[sIndex] && dItem.sentencesEn[sIndex].replace(/'/g, '’'),
  612. };
  613. sentArrTotal.push(sentArr);
  614. resArr.push(objs);
  615. });
  616. timeArr.push(dItem.timeList);
  617. if (this.isEnable(curQue.property.view_pinyin)) {
  618. dhaspinyinArr.push(dhaspinyin);
  619. }
  620. });
  621. if (wordTimeList && wordTimeList.length > 0) {
  622. this.mergeWordTime(sentArrTotal, wordTimeList);
  623. }
  624. let timeList = [];
  625. timeArr.forEach((item) => {
  626. item.forEach((aItem) => {
  627. if (timeList.indexOf(aItem) < 0) {
  628. timeList.push(aItem);
  629. }
  630. });
  631. });
  632. this.resObj = {
  633. sentList: resArr,
  634. timeList,
  635. dhaspinyinArr,
  636. };
  637. },
  638. mergeWordTime(resArr, wordTimeList) {
  639. resArr.forEach((item, index) => {
  640. let wordsResultList = wordTimeList[index].wordsResultList;
  641. item.forEach((wItem) => {
  642. let startIndex = wItem.startIndex;
  643. let endIndex = wItem.endIndex;
  644. wItem.timeList = wordsResultList.slice(startIndex, endIndex);
  645. });
  646. });
  647. },
  648. findLightWord(wItem, startIndex, sentence, sItem) {
  649. let endIndex = 0;
  650. let words = '';
  651. this.newWordList.forEach((item) => {
  652. if (item.length === 1) {
  653. if (item === wItem.chs && !wItem.banLight) {
  654. words = wItem.chs;
  655. endIndex = startIndex + 1;
  656. }
  657. } else if (item[0] === wItem.chs && sentence.indexOf(item) > -1) {
  658. let index = null;
  659. let chsStr = '';
  660. for (let i = startIndex; i < sItem.length + 1; i++) {
  661. index = i;
  662. if (chsStr.length === item.length) {
  663. break;
  664. } else {
  665. chsStr += sItem[i] ? sItem[i].chs : '';
  666. }
  667. }
  668. if (chsStr === item && !wItem.banLight) {
  669. words = item;
  670. endIndex = index;
  671. }
  672. } else if (wItem.new_word && wItem.new_word === item && !wItem.banLight) {
  673. words = item;
  674. endIndex = startIndex + 1;
  675. }
  676. });
  677. if (words) {
  678. this.highWords = { words, endIndex };
  679. } else {
  680. this.highWords = null;
  681. }
  682. },
  683. // 词和标点合一起
  684. mergeWordSymbol(wItem) {
  685. if (this.chsFhList.indexOf(wItem.chs) > -1) {
  686. wItem.isShow = false;
  687. } else {
  688. wItem.isShow = true;
  689. }
  690. },
  691. handleWav(list, tmIndex) {
  692. let i = tmIndex || 0;
  693. this.data.Bookanswer.practiceModel[i] = {
  694. recordList: [],
  695. };
  696. this.$set(this.data.Bookanswer.practiceModel[i], 'recordList', list);
  697. },
  698. handleNewword() {
  699. let NewWordList = [];
  700. this.NNPENewWordList.forEach((wItem) => {
  701. // item.forEach((wItem) => {
  702. if (wItem.new_word) {
  703. NewWordList.push(wItem.new_word);
  704. } else if (wItem.detail && wItem.detail.sentence) {
  705. NewWordList.push(wItem.detail.sentence);
  706. }
  707. // });
  708. });
  709. this.newWordList = JSON.parse(JSON.stringify(NewWordList));
  710. },
  711. /**
  712. * 获取无文本内容的数据结构,用于保存为个人模板时的样式模板
  713. */
  714. getNoTextContentData() {
  715. let noTextContentData = JSON.parse(JSON.stringify(this.data));
  716. const resetFieldMap = {
  717. content: '', // 课文内容
  718. mp3_list: [], // 音频列表
  719. detail: [], // 分段分句分词详情
  720. wordTime: [], // 字幕时间
  721. new_word_list: {
  722. title_con: '',
  723. property: {
  724. audio_generation_method: 'upload',
  725. pinyin_position: 'front',
  726. auto_wrap: 'true', // 自动换行
  727. is_has_infor: 'true',
  728. voice_type: '', // 音色
  729. emotion: '', // 风格,情感
  730. speed_ratio: '', // 语速
  731. is_show: 'false',
  732. },
  733. new_word_list: [],
  734. lrc_arr: [], // lrc 文件解析后的数据
  735. // lrc 文件数据
  736. lrc_data: {
  737. name: '',
  738. url: '',
  739. id: '',
  740. file_id: '',
  741. },
  742. // 音频文件数据
  743. audio_data: {
  744. name: '',
  745. media_duration: 0,
  746. temporary_url: '',
  747. url: '',
  748. file_id: '',
  749. },
  750. wordTime: [], // 字幕时间节点
  751. taskId: '',
  752. file_id_list: [], // 文件 id
  753. multilingual: [], // 多语言
  754. }, // 生词列表
  755. other_word_list: {
  756. title_con: '',
  757. property: {
  758. audio_generation_method: 'upload',
  759. pinyin_position: 'front',
  760. auto_wrap: 'true', // 自动换行
  761. is_has_infor: 'true',
  762. voice_type: '', // 音色
  763. emotion: '', // 风格,情感
  764. speed_ratio: '', // 语速
  765. is_show: 'false',
  766. },
  767. new_word_list: [],
  768. lrc_arr: [], // lrc 文件解析后的数据
  769. // lrc 文件数据
  770. lrc_data: {
  771. name: '',
  772. url: '',
  773. id: '',
  774. file_id: '',
  775. },
  776. // 音频文件数据
  777. audio_data: {
  778. name: '',
  779. media_duration: 0,
  780. temporary_url: '',
  781. url: '',
  782. file_id: '',
  783. },
  784. wordTime: [], // 字幕时间节点
  785. taskId: '',
  786. file_id_list: [], // 文件 id
  787. multilingual: [], // 多语言
  788. },
  789. notes_list: {
  790. title_con: '',
  791. option: [],
  792. multilingual: [], // 多语言
  793. file_id_list: [], // 文件 id
  794. property: {
  795. view_pinyin: 'false', // 显示拼音
  796. pinyin_position: 'back', // top bottom
  797. is_first_sentence_first_hz_pinyin_first_char_upper_case: 'true', // 句首大写
  798. is_show: 'false',
  799. },
  800. },
  801. sentence_list_mp: [], // 句子+分词数组
  802. pinyin_type: 'pinyin',
  803. };
  804. Object.assign(noTextContentData, resetFieldMap);
  805. return noTextContentData;
  806. },
  807. },
  808. };
  809. </script>
  810. <style lang="scss" scoped>
  811. @use '@/styles/mixin.scss' as *;
  812. .article-preview {
  813. @include preview-base;
  814. .main {
  815. display: grid;
  816. row-gap: 24px;
  817. align-items: center;
  818. }
  819. .NPC-ArticleView {
  820. width: 100%;
  821. .ArticleView-full {
  822. position: absolute;
  823. top: 0;
  824. left: 0;
  825. z-index: 1;
  826. font-size: 16px;
  827. font-weight: bold;
  828. line-height: 24px;
  829. color: #000;
  830. cursor: pointer;
  831. // background: url('@/assets/full-screen-red.png') left center no-repeat;
  832. // background-size: 20px 20px;
  833. }
  834. .ArticleView-header {
  835. position: relative;
  836. display: flex;
  837. align-items: center;
  838. justify-content: space-between;
  839. height: 24px;
  840. margin-bottom: 16px;
  841. .left {
  842. display: flex;
  843. align-items: center;
  844. justify-content: center;
  845. // padding-left: 24px;
  846. font-size: 16px;
  847. font-weight: bold;
  848. line-height: 24px;
  849. cursor: pointer;
  850. // background: url('@/assets/wbfx-icon.png') left center no-repeat;
  851. // background-size: 20px;
  852. img {
  853. width: 20px;
  854. height: 20px;
  855. margin-right: 4px;
  856. }
  857. }
  858. .right {
  859. display: flex;
  860. gap: 24px;
  861. a {
  862. display: flex;
  863. gap: 4px;
  864. align-items: center;
  865. color: rgba(0, 0, 0, 65%);
  866. cursor: pointer;
  867. }
  868. }
  869. .setting-fontsize {
  870. display: flex;
  871. margin-left: 24px;
  872. a {
  873. box-sizing: border-box;
  874. display: block;
  875. width: 24px;
  876. height: 24px;
  877. border: 1px solid rgba(0, 0, 0, 10%);
  878. border-radius: 4px;
  879. }
  880. img {
  881. width: 100%;
  882. }
  883. > img {
  884. width: 24px;
  885. margin: 0 8px;
  886. }
  887. }
  888. }
  889. .ArticleView-body {
  890. box-sizing: border-box;
  891. border: 1px solid rgba(0, 0, 0, 10%);
  892. border-radius: 4px;
  893. .aduioLine-box {
  894. width: 100%;
  895. border-bottom: 1px solid rgba(0, 0, 0, 10%);
  896. &-bottom {
  897. border-top: 1px solid rgba(0, 0, 0, 10%);
  898. border-bottom: none;
  899. }
  900. }
  901. }
  902. }
  903. }
  904. </style>
  905. <style lang="scss">
  906. .NPC-ArticleView {
  907. .ArticleView-header {
  908. .el-switch {
  909. margin-left: 24px;
  910. }
  911. .el-switch__core {
  912. width: 44px !important;
  913. height: 24px;
  914. border-radius: 20px;
  915. }
  916. .el-switch__core::after {
  917. top: 3px;
  918. left: 3px;
  919. }
  920. .el-switch.is-checked .el-switch__core::after {
  921. left: 100%;
  922. margin-left: -19px;
  923. }
  924. .el-switch__label {
  925. color: #000;
  926. }
  927. .el-switch__label.is-active {
  928. color: rgba($color: #000, $alpha: 30%);
  929. }
  930. .el-switch__label--left {
  931. margin-right: 8px;
  932. }
  933. }
  934. .pinyin-16 {
  935. cursor: pointer;
  936. // background: url('@/assets/icon/pinyin-16-normal-red.png') no-repeat left top;
  937. // background-size: 100% 100%;
  938. // &.disabled {
  939. // background: url('@/assets/icon/pinyin-16-disable-Black.png') no-repeat left top;
  940. // background-size: 100% 100%;
  941. // }
  942. }
  943. .EN-16 {
  944. cursor: pointer;
  945. // background: url('@/assets/icon/EN-16-normal-red.png') no-repeat left top;
  946. // background-size: 100% 100%;
  947. // &.disabled {
  948. // background: url('@/assets/icon/EN-16-disable-Black.png') no-repeat left top;
  949. // background-size: 100% 100%;
  950. // }
  951. }
  952. }
  953. .ArticleView-body {
  954. .aduioLine-box {
  955. width: 100%;
  956. border-bottom: 1px solid rgba(0, 0, 0, 10%);
  957. &-bottom {
  958. border-top: 1px solid rgba(0, 0, 0, 10%);
  959. border-bottom: none;
  960. }
  961. }
  962. .el-slider {
  963. flex: 1;
  964. width: auto !important;
  965. }
  966. }
  967. </style>