index.vue 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891
  1. <!-- eslint-disable vue/no-v-html -->
  2. <template>
  3. <div class="article-preview" :style="getAreaStyle()">
  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="黑板模式" @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. <div :style="{ marginLeft: '40px', cursor: 'pointer' }" title="文本分析" @click="submit">
  19. <svg-icon
  20. icon-class="icon-wbfx"
  21. size="24"
  22. :style="{
  23. color: data.unified_attrib && data.unified_attrib.topic_color ? data.unified_attrib.topic_color : '',
  24. }"
  25. />
  26. </div>
  27. </div>
  28. <div class="right">
  29. <!-- <template v-if="data.property.is_enable_new_word === 'true'">
  30. <el-switch
  31. v-model="showPhrases"
  32. style="display: block"
  33. :active-color="bookInfo.theme_color"
  34. inactive-color="rgba(0,0,0,0.1)"
  35. active-text=""
  36. inactive-text="本课生词"
  37. @change="handleSwitchChange('showPractice', 'showWord')"
  38. />
  39. </template>
  40. <template v-if="data.property.is_enable_read === 'true'">
  41. <el-switch
  42. v-model="showPractice"
  43. style="display: block"
  44. :active-color="bookInfo.theme_color"
  45. inactive-color="rgba(0,0,0,0.1)"
  46. active-text=""
  47. inactive-text="语音练习"
  48. @change="handleSwitchChange('showPhrases', 'showWord')"
  49. />
  50. </template>
  51. <template v-if="data.property.is_enable_word === 'true'">
  52. <el-switch
  53. v-model="showWord"
  54. style="display: block"
  55. :active-color="bookInfo.theme_color"
  56. inactive-color="rgba(0,0,0,0.1)"
  57. active-text=""
  58. inactive-text="取词"
  59. @change="handleSwitchChange('showPhrases', 'showPractice')"
  60. />
  61. </template> -->
  62. <a
  63. v-if="data.property.is_enable_new_word === 'true'"
  64. :style="{
  65. color:
  66. showPhrases && data.unified_attrib && data.unified_attrib.topic_color
  67. ? data.unified_attrib.topic_color
  68. : '',
  69. }"
  70. title="本课生词"
  71. @click="handleSwitchChange('showPractice', 'showWord', 'showPhrases')"
  72. >
  73. <svg-icon icon-class="icon-article-ci" size="24" />
  74. </a>
  75. <a
  76. v-if="data.property.is_enable_read === 'true'"
  77. :style="{
  78. color:
  79. showPractice && data.unified_attrib && data.unified_attrib.topic_color
  80. ? data.unified_attrib.topic_color
  81. : '',
  82. }"
  83. title="语音练习"
  84. @click="handleSwitchChange('showPhrases', 'showWord', 'showPractice')"
  85. >
  86. <svg-icon icon-class="icon-article-practice" size="24" />
  87. </a>
  88. <a
  89. v-if="data.property.is_enable_word === 'true'"
  90. :style="{
  91. color:
  92. showWord && data.unified_attrib && data.unified_attrib.topic_color
  93. ? data.unified_attrib.topic_color
  94. : '',
  95. }"
  96. title="取词模式"
  97. @click="handleSwitchChange('showPhrases', 'showPractice', 'showWord')"
  98. >
  99. <svg-icon icon-class="icon-article-phrase" size="24" />
  100. </a>
  101. </div>
  102. <!-- <div class="setting-fontsize">
  103. <a @click="handleFontsize('-')"
  104. ><img src="@/assets/newImage/common/btn-reduce.png"
  105. /></a>
  106. <img src="@/assets/newImage/common/font-size.png" />
  107. <a @click="handleFontsize('+')"
  108. ><img src="@/assets/newImage/common/btn-increase.png"
  109. /></a>
  110. </div> -->
  111. </div>
  112. <div ref="ArticleViewbody" class="ArticleView-body">
  113. <NormalModelChs
  114. v-if="!showPhrases && !showPractice && !showWord"
  115. :cur-que="data"
  116. :title-fontsize="titleFontsize"
  117. :word-fontsize="wordFontsize"
  118. :body-left="bodyLeft"
  119. :body-width="bodyWidth"
  120. :theme-color="bookInfo.theme_color"
  121. :no-font="noFont"
  122. :config="config"
  123. :NNPEAnnotationList="NNPEAnnotationList"
  124. :col-length="colLength"
  125. :multilingual="showLang && getLang() ? getLang() : ''"
  126. :attrib="data.unified_attrib"
  127. :is-mobile="isMobile"
  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. :theme-color="bookInfo.theme_color"
  137. :no-font="noFont"
  138. :current-tree-i-d="courseware_id"
  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. :attrib="data.unified_attrib"
  147. :is-mobile="isMobile"
  148. @changeConfig="changeConfig"
  149. />
  150. <Practice
  151. v-if="showPractice"
  152. :cur-que="data"
  153. :title-fontsize="titleFontsize"
  154. :word-fontsize="wordFontsize"
  155. :theme-color="bookInfo.theme_color"
  156. :no-font="noFont"
  157. :NNPENewWordList="NNPENewWordList"
  158. :NNPEAnnotationList="NNPEAnnotationList"
  159. :current-tree-i-d="courseware_id"
  160. :config="config"
  161. :TaskModel="isJudgingRightWrong ? 'ANSWER' : ''"
  162. :col-length="colLength"
  163. :NpcNewWordMp3="NpcNewWordMp3"
  164. :is-full="isFull"
  165. :multilingual="showLang && getLang() ? getLang() : ''"
  166. :attrib="data.unified_attrib"
  167. :is-mobile="isMobile"
  168. @changeConfig="changeConfig"
  169. />
  170. <WordModel
  171. v-if="showWord"
  172. :cur-que="data"
  173. :title-fontsize="titleFontsize"
  174. :word-fontsize="wordFontsize"
  175. :body-left="bodyLeft"
  176. :body-width="bodyWidth"
  177. :NNPENewWordList="NNPENewWordList"
  178. :theme-color="bookInfo.theme_color"
  179. :no-font="noFont"
  180. :current-tree-i-d="courseware_id"
  181. :config="config"
  182. :TaskModel="isJudgingRightWrong ? 'ANSWER' : ''"
  183. :col-length="colLength"
  184. :multilingual="showLang && getLang() ? getLang() : ''"
  185. :attrib="data.unified_attrib"
  186. :is-mobile="isMobile"
  187. @changeConfig="changeConfig"
  188. />
  189. </div>
  190. <div :id="'screen-' + mathNum" class="voice-full-screen">
  191. <Voicefullscreen
  192. v-if="isFull && resObj"
  193. :theme-color="bookInfo.theme_color"
  194. :cur-que="data"
  195. :sent-list="resObj.sentList"
  196. :sent-index="0"
  197. :mp3="data.mp3_list && data.mp3_list[0] ? data.mp3_list[0].url : ''"
  198. :no-font="noFont"
  199. :NNPENewWordList="NNPENewWordList"
  200. :NNPEAnnotationList="NNPEAnnotationList"
  201. :current-tree-i-d="courseware_id"
  202. :is-full="isFull"
  203. :config="config"
  204. :TaskModel="isJudgingRightWrong ? 'ANSWER' : ''"
  205. :NpcNewWordMp3="NpcNewWordMp3"
  206. :attrib="data.unified_attrib"
  207. :is-mobile="isMobile"
  208. @handleWav="handleWav"
  209. @changePinyin="changePinyins"
  210. @changeEN="changeENs"
  211. @exitFullscreen="exitFullscreen"
  212. @changeIsFull="changeIsFull"
  213. />
  214. </div>
  215. </div>
  216. <template
  217. v-if="data.new_word_list && data.new_word_list.new_word_list && data.new_word_list.new_word_list.length > 0"
  218. >
  219. <NewWordPreview :new-data="data.new_word_list" :is-mobile="isMobile" />
  220. </template>
  221. <template
  222. v-if="
  223. data.other_word_list && data.other_word_list.new_word_list && data.other_word_list.new_word_list.length > 0
  224. "
  225. >
  226. <NewWordPreview :new-data="data.other_word_list" :is-mobile="isMobile" />
  227. </template>
  228. <template v-if="data.notes_list && data.notes_list.option && data.notes_list.option.length > 0">
  229. <NotesPreview :notes-data="data.notes_list" :is-mobile="isMobile" />
  230. </template>
  231. </div>
  232. </div>
  233. </template>
  234. <script>
  235. import { getArticleData } from '@/views/book/courseware/data/article';
  236. import PreviewMixin from '../common/PreviewMixin';
  237. import PhraseModel from './PhraseModelChs.vue';
  238. import NormalModelChs from './NormalModelChs.vue';
  239. import Practice from './Practicechs.vue'; // 语音练习模式
  240. import WordModel from './WordModelChs.vue'; // 语音练习模式
  241. import Voicefullscreen from './Voicefullscreen.vue';
  242. import { getToken } from '@/utils/auth';
  243. import { GetFileURLMap } from '@/api/app';
  244. import { analysSubmit, getSysConfig } from '@/api/article';
  245. import NewWordPreview from '../new_word/NewWordPreview.vue';
  246. import NotesPreview from '../notes/NotesPreview.vue';
  247. export default {
  248. name: 'ArticlePreview',
  249. components: {
  250. NormalModelChs,
  251. Practice,
  252. WordModel,
  253. PhraseModel,
  254. Voicefullscreen,
  255. NewWordPreview,
  256. NotesPreview,
  257. },
  258. mixins: [PreviewMixin],
  259. inject: ['bookInfo'],
  260. props: ['isMobile'],
  261. data() {
  262. return {
  263. data: getArticleData(),
  264. showPreview: true, // 全文预览
  265. showPhrases: false, // 显示单词和短语
  266. showPractice: false, // 语音练习
  267. showWord: false, // 取词
  268. titleFontsize: 20, // 标题字号初始值
  269. wordFontsize: 16, // 文章内容字号初始值
  270. bodyLeft: 0,
  271. bodyWidth: 0,
  272. noFont: ['~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '/'],
  273. config: {
  274. isShowEN: false,
  275. isHasEN: false,
  276. isShowPY: false,
  277. isHasPY: false,
  278. },
  279. userAnswer: {
  280. normalModel: {
  281. recordList: [],
  282. },
  283. writeModel: {}, // 生词/取词模式
  284. practiceModel: {}, // 练习模式
  285. },
  286. tokenData: getToken(),
  287. mathNum: Math.random().toString(36).substr(2),
  288. isFull: false,
  289. resObj: null,
  290. chsFhList: [',', '。', '”', ':', '》', '?', '!', ';', '、'],
  291. highWords: null,
  292. highWordsArr: [],
  293. highIndex: 0,
  294. newWordList: [],
  295. NNPEAnnotationList: [],
  296. NNPENewWordList: [],
  297. NpcNewWordMp3: [],
  298. colLength: 1,
  299. courseware_id: this.$route.params.id,
  300. multilingualTextList: {},
  301. analyser_url: '',
  302. };
  303. },
  304. computed: {},
  305. watch: {
  306. showLang: {
  307. handler(val) {
  308. if (val) {
  309. this.data.multilingual.forEach((item) => {
  310. let trans_arr = item.translation ? item.translation.split('\n') : [];
  311. this.data.detail.forEach((items) => {
  312. let items_trans_arr = [];
  313. if (!items.hasOwnProperty('multilingualTextList')) {
  314. this.$set(items, 'multilingualTextList', {});
  315. }
  316. if (items.para) {
  317. items_trans_arr = trans_arr.splice(0, items.sentences.length);
  318. }
  319. this.$set(items.multilingualTextList, item.type, items_trans_arr);
  320. });
  321. });
  322. }
  323. },
  324. deep: true,
  325. immediate: true,
  326. },
  327. 'data.content': {
  328. handler(val) {
  329. if (val) {
  330. this.handleData();
  331. let _this = this;
  332. if (!this.isJudgingRightWrong) {
  333. let userAnswer = JSON.parse(JSON.stringify(_this.userAnswer));
  334. _this.$set(this.data, 'Bookanswer', userAnswer);
  335. this.answer.answer_list = this.data.Bookanswer;
  336. }
  337. _this.$nextTick(() => {
  338. _this.bodyLeft = _this.$refs.ArticleViewbody.getBoundingClientRect().left;
  339. });
  340. for (let i = 0; i < this.data.detail.length; i++) {
  341. let enStr = this.data.detail[i].sentencesEn ? this.data.detail[i].sentencesEn.join('') : '';
  342. if (enStr) {
  343. this.config.isShowEN = false;
  344. this.config.isHasEN = true;
  345. }
  346. let pinyin = this.handleObj(this.data.detail[i].wordsList);
  347. if (pinyin && this.isEnable(this.data.property.view_pinyin)) {
  348. this.config.isShowPY = true;
  349. this.config.isHasPY = true;
  350. }
  351. if (enStr && pinyin) {
  352. break;
  353. }
  354. }
  355. }
  356. },
  357. deep: true,
  358. immediate: true,
  359. },
  360. isJudgingRightWrong(val) {
  361. if (!val) return;
  362. this.data.Bookanswer = this.answer.answer_list;
  363. },
  364. },
  365. created() {},
  366. methods: {
  367. changeConfig(obj) {
  368. this.config[obj] = !this.config[obj];
  369. },
  370. changeIsFull() {
  371. this.isFull = false;
  372. },
  373. // 拼音的显示和隐藏
  374. changePinyins() {
  375. if (this.config.isHasPY) {
  376. this.changeConfig('isShowPY');
  377. }
  378. },
  379. // 英文的显示和隐藏
  380. changeENs() {
  381. if (this.config.isHasEN) {
  382. this.changeConfig('isShowEN');
  383. }
  384. },
  385. // 处理字体大小
  386. handleFontsize(symbol) {
  387. if (symbol === '+') {
  388. if (this.wordFontsize < 24) {
  389. this.titleFontsize += 2;
  390. this.wordFontsize += 2;
  391. }
  392. } else if (symbol === '-') {
  393. if (this.wordFontsize > 12) {
  394. this.titleFontsize -= 2;
  395. this.wordFontsize -= 2;
  396. }
  397. }
  398. },
  399. // 切换开关
  400. handleSwitchChange(obj1, obj2, obj3) {
  401. this[obj1] = false;
  402. this[obj2] = false;
  403. this[obj3] = !this[obj3];
  404. this.showPreview = false;
  405. },
  406. handleObj(list) {
  407. let pinyin = '';
  408. list.forEach((item) => {
  409. item.forEach((items) => {
  410. if (items.pinyin) pinyin += items.pinyin;
  411. });
  412. });
  413. return pinyin;
  414. },
  415. submit() {
  416. let access_token =
  417. this.tokenData && this.tokenData.gcls_sys_session_info ? this.tokenData.gcls_sys_session_info.access_token : '';
  418. let loading = this.$loading({
  419. lock: true,
  420. text: 'Loading',
  421. spinner: 'el-icon-loading',
  422. background: 'rgba(0, 0, 0, 0.7)',
  423. });
  424. getSysConfig()
  425. .then((ress) => {
  426. analysSubmit({
  427. app_user_id: '',
  428. text: this.data.content,
  429. })
  430. .then((res) => {
  431. window.open(
  432. `${ress.text_analyser_page_address}GCLS-TC/#/textanalysis/Result?id=${res.record.id}&type=文本分析&AccessToken=${access_token}`,
  433. );
  434. loading.close();
  435. })
  436. .catch((res) => {
  437. loading.close();
  438. });
  439. })
  440. .catch((res) => {
  441. loading.close();
  442. });
  443. },
  444. // 语音全屏
  445. fullScreen() {
  446. this.pauseAudio();
  447. this.pauseVideo();
  448. this.isFull = true;
  449. this.goFullscreen();
  450. },
  451. pauseAudio() {
  452. let audio = document.getElementsByTagName('audio');
  453. if (audio && audio.length > 0 && window.location.href.indexOf('GCLS-Learn') === -1 && audio.forEach) {
  454. audio.forEach((item) => {
  455. item.pause();
  456. });
  457. }
  458. },
  459. pauseVideo() {
  460. let video = document.getElementsByTagName('video');
  461. if (video && video.length > 0 && window.location.href.indexOf('GCLS-Learn') === -1 && video.forEach) {
  462. video.forEach((item) => {
  463. item.pause();
  464. });
  465. }
  466. },
  467. goFullscreen() {
  468. let id = `screen-${this.mathNum}`;
  469. let element = document.getElementById(id);
  470. if (element.requestFullscreen) {
  471. element.requestFullscreen();
  472. } else if (element.msRequestFullscreen) {
  473. element.msRequestFullscreen();
  474. } else if (element.mozRequestFullScreen) {
  475. element.mozRequestFullScreen();
  476. } else if (element.webkitRequestFullscreen) {
  477. element.webkitRequestFullscreen();
  478. }
  479. },
  480. exitFullscreen() {
  481. this.isFull = false;
  482. if (document.exitFullscreen) {
  483. document.exitFullscreen();
  484. } else if (document.msExitFullscreen) {
  485. document.msExitFullscreen();
  486. } else if (document.mozCancelFullScreen) {
  487. document.mozCancelFullScreen();
  488. } else if (document.webkitExitFullscreen) {
  489. document.webkitExitFullscreen();
  490. }
  491. },
  492. handleData() {
  493. if (this.data.new_word_list) {
  494. this.$set(this.data.new_word_list, 'unified_attrib', this.data.unified_attrib);
  495. }
  496. if (this.data.other_word_list) {
  497. this.$set(this.data.other_word_list, 'unified_attrib', this.data.unified_attrib);
  498. }
  499. if (this.data.notes_list) {
  500. this.$set(this.data.notes_list, 'unified_attrib', this.data.unified_attrib);
  501. }
  502. if (this.showLang) {
  503. this.data.multilingual.forEach((item) => {
  504. let trans_arr = item.translation ? item.translation.split('\n') : [];
  505. this.data.detail.forEach((items) => {
  506. let items_trans_arr = [];
  507. if (!items.hasOwnProperty('multilingualTextList')) {
  508. this.$set(items, 'multilingualTextList', {});
  509. }
  510. if (items.para) {
  511. items_trans_arr = trans_arr.splice(0, items.sentences.length);
  512. }
  513. this.$set(items.multilingualTextList, item.type, items_trans_arr);
  514. });
  515. });
  516. }
  517. if (this.data.mp3_list && this.data.mp3_list.length > 0) {
  518. this.data.mp3_list[0].url = this.data.mp3_list[0].temporary_url;
  519. // GetFileURLMap({ file_id_list: [this.data.mp3_list[0].file_id] }).then(({ url_map }) => {
  520. // this.data.mp3_list[0].url = url_map[this.data.mp3_list[0].file_id];
  521. // });
  522. }
  523. this.NNPENewWordList = (
  524. this.data.new_word_list_other_component_input ? this.data.new_word_list_other_component_input : []
  525. )
  526. .concat(
  527. this.data.new_word_list && this.data.new_word_list.new_word_list ? this.data.new_word_list.new_word_list : [],
  528. )
  529. .concat(
  530. this.data.other_word_list && this.data.other_word_list.new_word_list
  531. ? this.data.other_word_list.new_word_list
  532. : [],
  533. );
  534. this.NNPEAnnotationList = this.data.notes_list && this.data.notes_list.option ? this.data.notes_list.option : [];
  535. let resArr = [];
  536. let sentArrTotal = [];
  537. let timeArr = [];
  538. let curQue = JSON.parse(JSON.stringify(this.data));
  539. let wordTimeList = curQue.wordTime;
  540. let dhaspinyin = false; // 每段是否有拼音
  541. let dhaspinyinArr = [];
  542. curQue.detail.forEach((dItem, dIndex) => {
  543. dhaspinyin = false;
  544. dItem.wordsList.forEach((sItem, sIndex) => {
  545. let sentArr = [];
  546. let sentence = dItem.sentences[sIndex];
  547. sItem.forEach((wItem, wIndex) => {
  548. let startIndex = wIndex === 0 ? 0 : sentArr[wIndex - 1].startIndex + sentArr[wIndex - 1].chs.length;
  549. let endIndex = wIndex === 0 ? wItem.chs.length : sentArr[wIndex - 1].endIndex + wItem.chs.length;
  550. // this.judgePad(sItem, wItem, wIndex);
  551. this.mergeWordSymbol(wItem);
  552. let words = '';
  553. if (this.newWordList.length > 0) {
  554. if (!this.highWords) {
  555. this.findLightWord(wItem, wIndex, sentence, sItem);
  556. words = this.highWords ? this.highWords.words : '';
  557. } else if (wIndex > this.highWords.endIndex - 1) {
  558. this.highWords = null;
  559. this.findLightWord(wItem, wIndex, sentence, sItem);
  560. words = this.highWords ? this.highWords.words : '';
  561. } else {
  562. words = this.highWords ? this.highWords.words : '';
  563. }
  564. }
  565. let obj = {
  566. paraIndex: dIndex, // 段落索引
  567. sentIndex: sIndex, // 在段落中句子索引
  568. wordIndex: wIndex, // 单词的索引
  569. pinyin: wItem.pinyin,
  570. chs: wItem.chs,
  571. padding: true,
  572. className: wItem.className,
  573. isShow: wItem.isShow,
  574. startIndex,
  575. endIndex,
  576. leg: wItem.chs.length,
  577. timeList: [],
  578. words,
  579. config: {
  580. fontFamily: wItem.fontFamily,
  581. },
  582. };
  583. sentArr.push(obj);
  584. if (wItem.pinyin) dhaspinyin = true;
  585. });
  586. let objs = {
  587. sentArr,
  588. enwords: dItem.sentencesEn && dItem.sentencesEn[sIndex] && dItem.sentencesEn[sIndex].replace(/'/g, '’'),
  589. };
  590. sentArrTotal.push(sentArr);
  591. resArr.push(objs);
  592. });
  593. timeArr.push(dItem.timeList);
  594. if (this.isEnable(curQue.property.view_pinyin)) {
  595. dhaspinyinArr.push(dhaspinyin);
  596. }
  597. });
  598. if (wordTimeList && wordTimeList.length > 0) {
  599. this.mergeWordTime(sentArrTotal, wordTimeList);
  600. }
  601. let timeList = [];
  602. timeArr.forEach((item) => {
  603. item.forEach((aItem) => {
  604. if (timeList.indexOf(aItem) < 0) {
  605. timeList.push(aItem);
  606. }
  607. });
  608. });
  609. this.resObj = {
  610. sentList: resArr,
  611. timeList,
  612. dhaspinyinArr,
  613. };
  614. },
  615. mergeWordTime(resArr, wordTimeList) {
  616. resArr.forEach((item, index) => {
  617. let wordsResultList = wordTimeList[index].wordsResultList;
  618. item.forEach((wItem) => {
  619. let startIndex = wItem.startIndex;
  620. let endIndex = wItem.endIndex;
  621. wItem.timeList = wordsResultList.slice(startIndex, endIndex);
  622. });
  623. });
  624. },
  625. findLightWord(wItem, startIndex, sentence, sItem) {
  626. let endIndex = 0;
  627. let words = '';
  628. this.newWordList.forEach((item) => {
  629. if (item.length === 1) {
  630. if (item === wItem.chs && !wItem.banLight) {
  631. words = wItem.chs;
  632. endIndex = startIndex + 1;
  633. }
  634. } else if (item[0] === wItem.chs && sentence.indexOf(item) > -1) {
  635. let index = null;
  636. let chsStr = '';
  637. for (let i = startIndex; i < sItem.length + 1; i++) {
  638. index = i;
  639. if (chsStr.length === item.length) {
  640. break;
  641. } else {
  642. chsStr += sItem[i] ? sItem[i].chs : '';
  643. }
  644. }
  645. if (chsStr === item && !wItem.banLight) {
  646. words = item;
  647. endIndex = index;
  648. }
  649. } else if (wItem.new_word && wItem.new_word === item && !wItem.banLight) {
  650. words = item;
  651. endIndex = startIndex + 1;
  652. }
  653. });
  654. if (words) {
  655. this.highWords = { words, endIndex };
  656. } else {
  657. this.highWords = null;
  658. }
  659. },
  660. // 词和标点合一起
  661. mergeWordSymbol(wItem) {
  662. if (this.chsFhList.indexOf(wItem.chs) > -1) {
  663. wItem.isShow = false;
  664. } else {
  665. wItem.isShow = true;
  666. }
  667. },
  668. handleWav(list, tmIndex) {
  669. let _tmIndex = tmIndex || 0;
  670. this.data.Bookanswer.practiceModel[_tmIndex] = {
  671. recordList: [],
  672. };
  673. this.$set(this.data.Bookanswer.practiceModel[_tmIndex], 'recordList', list);
  674. },
  675. handleNewword() {
  676. let NewWordList = [];
  677. this.NNPENewWordList.forEach((wItem) => {
  678. // item.forEach((wItem) => {
  679. if (wItem.new_word) {
  680. NewWordList.push(wItem.new_word);
  681. } else if (wItem.detail && wItem.detail.sentence) {
  682. NewWordList.push(wItem.detail.sentence);
  683. }
  684. // });
  685. });
  686. this.newWordList = JSON.parse(JSON.stringify(NewWordList));
  687. },
  688. },
  689. };
  690. </script>
  691. <style lang="scss" scoped>
  692. @use '@/styles/mixin.scss' as *;
  693. .article-preview {
  694. @include preview-base;
  695. .main {
  696. display: grid;
  697. row-gap: 24px;
  698. align-items: center;
  699. }
  700. .NPC-ArticleView {
  701. width: 100%;
  702. .ArticleView-full {
  703. position: absolute;
  704. top: 0;
  705. left: 0;
  706. z-index: 1;
  707. font-size: 16px;
  708. font-weight: bold;
  709. line-height: 24px;
  710. color: #000;
  711. cursor: pointer;
  712. // background: url('@/assets/full-screen-red.png') left center no-repeat;
  713. // background-size: 20px 20px;
  714. }
  715. .ArticleView-header {
  716. position: relative;
  717. display: flex;
  718. align-items: center;
  719. justify-content: space-between;
  720. height: 24px;
  721. margin-bottom: 16px;
  722. .left {
  723. display: flex;
  724. align-items: center;
  725. justify-content: center;
  726. // padding-left: 24px;
  727. font-size: 16px;
  728. font-weight: bold;
  729. line-height: 24px;
  730. cursor: pointer;
  731. // background: url('@/assets/wbfx-icon.png') left center no-repeat;
  732. // background-size: 20px;
  733. img {
  734. width: 20px;
  735. height: 20px;
  736. margin-right: 4px;
  737. }
  738. }
  739. .right {
  740. display: flex;
  741. gap: 24px;
  742. a {
  743. display: flex;
  744. gap: 4px;
  745. align-items: center;
  746. color: rgba(0, 0, 0, 65%);
  747. cursor: pointer;
  748. }
  749. }
  750. .setting-fontsize {
  751. display: flex;
  752. margin-left: 24px;
  753. a {
  754. box-sizing: border-box;
  755. display: block;
  756. width: 24px;
  757. height: 24px;
  758. border: 1px solid rgba(0, 0, 0, 10%);
  759. border-radius: 4px;
  760. }
  761. img {
  762. width: 100%;
  763. }
  764. > img {
  765. width: 24px;
  766. margin: 0 8px;
  767. }
  768. }
  769. }
  770. .ArticleView-body {
  771. box-sizing: border-box;
  772. background: #fff;
  773. border: 1px solid rgba(0, 0, 0, 10%);
  774. border-radius: 8px;
  775. .aduioLine-box {
  776. width: 100%;
  777. border-bottom: 1px solid rgba(0, 0, 0, 10%);
  778. &-bottom {
  779. border-top: 1px solid rgba(0, 0, 0, 10%);
  780. border-bottom: none;
  781. }
  782. }
  783. }
  784. }
  785. }
  786. </style>
  787. <style lang="scss">
  788. .NPC-ArticleView {
  789. .ArticleView-header {
  790. .el-switch {
  791. margin-left: 24px;
  792. }
  793. .el-switch__core {
  794. width: 44px !important;
  795. height: 24px;
  796. border-radius: 20px;
  797. }
  798. .el-switch__core::after {
  799. top: 3px;
  800. left: 3px;
  801. }
  802. .el-switch.is-checked .el-switch__core::after {
  803. left: 100%;
  804. margin-left: -19px;
  805. }
  806. .el-switch__label {
  807. color: #000;
  808. }
  809. .el-switch__label.is-active {
  810. color: rgba($color: #000, $alpha: 30%);
  811. }
  812. .el-switch__label--left {
  813. margin-right: 8px;
  814. }
  815. }
  816. .pinyin-16 {
  817. cursor: pointer;
  818. // background: url('@/assets/icon/pinyin-16-normal-red.png') no-repeat left top;
  819. // background-size: 100% 100%;
  820. // &.disabled {
  821. // background: url('@/assets/icon/pinyin-16-disable-Black.png') no-repeat left top;
  822. // background-size: 100% 100%;
  823. // }
  824. }
  825. .EN-16 {
  826. cursor: pointer;
  827. // background: url('@/assets/icon/EN-16-normal-red.png') no-repeat left top;
  828. // background-size: 100% 100%;
  829. // &.disabled {
  830. // background: url('@/assets/icon/EN-16-disable-Black.png') no-repeat left top;
  831. // background-size: 100% 100%;
  832. // }
  833. }
  834. }
  835. .ArticleView-body {
  836. .aduioLine-box {
  837. width: 100%;
  838. border-bottom: 1px solid rgba(0, 0, 0, 10%);
  839. &-bottom {
  840. border-top: 1px solid rgba(0, 0, 0, 10%);
  841. border-bottom: none !important;
  842. }
  843. }
  844. .el-slider {
  845. flex: 1;
  846. width: auto !important;
  847. }
  848. }
  849. </style>