Practicechs.vue 55 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524
  1. <!-- -->
  2. <template>
  3. <div v-if="curQue" class="NNPE-ArticleView">
  4. <!-- <a class="ArticleView-full" @click="fullScreen">黑板模式</a> -->
  5. <div
  6. v-if="
  7. ((curQue.mp3_list && curQue.mp3_list.length > 0 && curQue.mp3_list[0].url) ||
  8. config.isHasPY ||
  9. config.isHasEN) &&
  10. curQue.property.mp3_position === 'top'
  11. "
  12. class="aduioLine-box aduioLine-practice-npc"
  13. >
  14. <div class="aduioLine-content">
  15. <template v-if="curQue.mp3_list && curQue.mp3_list.length > 0 && curQue.mp3_list[0].url">
  16. <AudioLine
  17. ref="audioLine"
  18. audio-id="diaPraAudio"
  19. :mp3="curQue.mp3_list[0].url"
  20. :get-cur-time="getCurTime"
  21. :stop-audio="stopAudio"
  22. :width="colLength == 2 ? 175 : isPhone ? 200 : 750"
  23. :is-repeat="isRepeat"
  24. :mp3-source="curQue.mp3_list[0].source"
  25. :ed="ed"
  26. type="audioLine"
  27. :attrib="attrib"
  28. @handleChangeStopAudio="handleChangeStopAudio"
  29. @emptyEd="emptyEd"
  30. />
  31. </template>
  32. </div>
  33. <div class="aduioLine-right">
  34. <!-- <span :class="['Repeat-16', isRepeat ? '' : 'disabled']" @click="changeRepeat"></span> -->
  35. <SvgIcon
  36. v-if="config.isHasPY"
  37. icon-class="repeat-1"
  38. size="16"
  39. :class="['Repeat-16', isRepeat ? '' : 'disabled']"
  40. :style="{ color: isRepeat ? (attrib ? attrib.topic_color : '') : '#DCDFE6', cursor: 'pointer' }"
  41. @click="changeRepeat"
  42. />
  43. <!-- <span
  44. :class="['pinyin-16', config.isShowPY ? '' : 'disabled']"
  45. @click="changePinyin"
  46. v-if="config.isHasPY"
  47. ></span>
  48. <span :class="['EN-16', config.isShowEN ? '' : 'disabled']" @click="changeEN" v-if="config.isHasEN"></span> -->
  49. <SvgIcon
  50. v-if="config.isHasPY"
  51. icon-class="pin-btn"
  52. size="16"
  53. :class="['pinyin-16', config.isShowPY ? '' : 'disabled']"
  54. :style="{ color: config.isShowPY ? (attrib ? attrib.topic_color : '') : '#DCDFE6' }"
  55. @click="changePinyin"
  56. />
  57. <!-- <span :class="['EN-16', config.isShowEN ? '' : 'disabled']" @click="changeEN" v-if="config.isHasEN"></span> -->
  58. <SvgIcon
  59. v-if="config.isHasEN"
  60. icon-class="en-btn"
  61. size="16"
  62. :class="['EN-16', config.isShowEN ? '' : 'disabled']"
  63. :style="{ color: config.isShowEN ? (attrib ? attrib.topic_color : '') : '#DCDFE6' }"
  64. @click="changeEN"
  65. />
  66. </div>
  67. </div>
  68. <template v-if="resObj">
  69. <p v-if="curQue.notice" class="notice" style="padding-top: 24px">
  70. {{ curQue.notice }}
  71. </p>
  72. <div class="NPC-sentences-list">
  73. <div
  74. v-for="(item, index) in resObj.sentList"
  75. :key="'detail' + index"
  76. :class="['NNPE-detail-box', sentIndex == index ? 'active' : '']"
  77. :style="{
  78. backgroundColor: sentIndex == index && attrib ? attrib.assist_color : '',
  79. }"
  80. >
  81. <div
  82. class="NNPE-detail"
  83. @click="
  84. handleChangeTime(
  85. curQue.wordTime && curQue.wordTime[index] && curQue.wordTime[index].bg,
  86. index,
  87. curQue.wordTime && curQue.wordTime[index] && curQue.wordTime[index].ed,
  88. )
  89. "
  90. >
  91. <template v-if="item.sentArr[0].sentIndex == 0">
  92. <RoleChs
  93. :cur-role="item.roleDetail"
  94. :color="
  95. (curQue.wordTime &&
  96. curQue.wordTime[index] &&
  97. curTime >= curQue.wordTime[index].bg &&
  98. curTime <= curQue.wordTime[index].ed) ||
  99. sentIndex == index
  100. ? 'rgba(0,0,0,0.85)'
  101. : 'rgba(0,0,0,0.45)'
  102. "
  103. :type="curQue.property.role_img_type"
  104. />
  105. </template>
  106. <div v-else style="width: 36px; height: 36px"></div>
  107. <div class="sentence-box">
  108. <template v-if="item.sentArr[0].sentIndex == 0">
  109. <!-- <div class="roleDetail" v-if="item.roleDetail.detail && item.roleDetail.detail.wordsList.length > 0">
  110. <span
  111. :class="[
  112. 'pinyin',
  113. (curQue.wordTime &&
  114. curQue.wordTime[index] &&
  115. curTime >= curQue.wordTime[index].bg &&
  116. curTime <= curQue.wordTime[index].ed) ||
  117. sentIndex == index
  118. ? 'color85'
  119. : 'color45',
  120. ]"
  121. >{{ item.roleDetail.detail.wordsList | handlePinyin }}</span
  122. >
  123. <span
  124. :class="[
  125. 'chs',
  126. (curQue.wordTime &&
  127. curQue.wordTime[index] &&
  128. curTime >= curQue.wordTime[index].bg &&
  129. curTime <= curQue.wordTime[index].ed) ||
  130. sentIndex == index
  131. ? 'color85'
  132. : 'color45',
  133. ]"
  134. >{{ item.roleDetail.detail.wordsList | handleChs }}</span
  135. >
  136. </div> -->
  137. <div v-if="item.roleDetail.fullName || item.roleDetail.fullPinyin" class="roleDetail">
  138. <span
  139. :class="[
  140. 'chs',
  141. (curQue.wordTime &&
  142. curQue.wordTime[index] &&
  143. curTime >= curQue.wordTime[index].bg &&
  144. curTime <= curQue.wordTime[index].ed) ||
  145. sentIndex == index
  146. ? 'color85'
  147. : 'color45',
  148. ]"
  149. >{{ item.roleDetail.fullName }}</span
  150. >
  151. <span
  152. :class="[
  153. 'pinyin',
  154. (curQue.wordTime &&
  155. curQue.wordTime[index] &&
  156. curTime >= curQue.wordTime[index].bg &&
  157. curTime <= curQue.wordTime[index].ed) ||
  158. sentIndex == index
  159. ? 'color85'
  160. : 'color45',
  161. ]"
  162. >{{ item.roleDetail.fullPinyin }}</span
  163. >
  164. </div>
  165. </template>
  166. <div class="sentence-box-inner" :style="{ background: item.roleDetail.color.bg }">
  167. <div
  168. v-if="item.enwords && config.isShowEN && curQue.enPosition && curQue.enPosition == 'top'"
  169. :class="['enwords', sentIndex == index ? 'wordBlank' : '']"
  170. >
  171. {{ item.enwords }}
  172. </div>
  173. <div style="overflow: hidden; clear: both"></div>
  174. <div class="NNPE-words-box">
  175. <div
  176. v-for="(pItem, pIndex) in item.sentArr"
  177. :key="'wordsList' + pIndex"
  178. class="NNPE-words"
  179. :class="[
  180. pItem.chs != '“' && pItem.wordIndex == 0 ? 'textLeft' : 'textCenter',
  181. pItem.chs == '“' ? 'textRight' : '',
  182. ]"
  183. >
  184. <template v-if="!pItem.width">
  185. <template v-if="pItem.isShow">
  186. <template
  187. v-if="
  188. (item.sentArr[pIndex + 1] &&
  189. item.sentArr[pIndex + 1].chs &&
  190. chsFhList.indexOf(item.sentArr[pIndex + 1].chs) > -1) ||
  191. (item.sentArr[pIndex + 1] &&
  192. item.sentArr[pIndex + 1].chs &&
  193. item.sentArr[pIndex + 1].chs == '#')
  194. "
  195. >
  196. <span class="NNPE-words-box">
  197. <template v-if="curQue.property.pinyin_position == 'top'">
  198. <span
  199. v-if="config.isShowPY && item.dhaspinyin"
  200. class="NNPE-pinyin"
  201. :class="[
  202. pItem.className ? pItem.className : '',
  203. sentIndex == index ? 'wordBlank' : '',
  204. noFont.indexOf(pItem.pinyin) > -1 ? 'noFont' : '',
  205. ]"
  206. :style="{
  207. fontSize: attrib && attrib.pinyin_size ? attrib.pinyin_size : '14px',
  208. height:
  209. attrib && attrib.pinyin_size
  210. ? attrib.pinyin_size.replace('pt', '') * 1.5 + 'pt'
  211. : '22px',
  212. }"
  213. >{{ NumberList.indexOf(pItem.pinyin) == -1 ? pItem.pinyin : '' }}</span
  214. >
  215. </template>
  216. <span
  217. class="NNPE-chs"
  218. :class="[
  219. pItem.padding && config.isShowPY && item.dhaspinyin ? 'padding' : '',
  220. sentIndex == index ? 'wordBlank' : '',
  221. ]"
  222. >
  223. <template>
  224. <span
  225. v-for="(wItem, wIndex) in pItem.leg"
  226. :key="'ci' + wIndex + pIndex + index"
  227. :class="[
  228. isPlaying &&
  229. pItem.timeList &&
  230. pItem.timeList[wIndex] &&
  231. curTime >= pItem.timeList[wIndex].wordBg &&
  232. curQue.wordTime &&
  233. curQue.wordTime[index] &&
  234. curTime <= curQue.wordTime[index].ed
  235. ? 'active'
  236. : '',
  237. sentIndex == index ? 'wordBlank' : '',
  238. ]"
  239. :style="{
  240. fontFamily: pItem.config.fontFamily,
  241. height:
  242. attrib && attrib.font_size
  243. ? attrib.font_size.replace('pt', '') * 1.4 + 'pt'
  244. : '28px',
  245. fontSize: attrib && attrib.font_size ? attrib.font_size : '20px',
  246. lineHeight:
  247. attrib && attrib.font_size
  248. ? attrib.font_size.replace('pt', '') * 1.4 + 'pt'
  249. : '28px',
  250. display: 'inline-block',
  251. color:
  252. isPlaying &&
  253. pItem.timeList &&
  254. pItem.timeList[wIndex] &&
  255. curTime >= pItem.timeList[wIndex].wordBg &&
  256. curQue.wordTime &&
  257. curQue.wordTime[index] &&
  258. curTime <= curQue.wordTime[index].ed &&
  259. attrib
  260. ? attrib.topic_color
  261. : '',
  262. }"
  263. >{{ NumberList.indexOf(pItem.pinyin) == -1 ? pItem.chs[wIndex] : '' }}</span
  264. >
  265. </template>
  266. </span>
  267. <template v-if="curQue.property.pinyin_position == 'bottom'">
  268. <span
  269. v-if="config.isShowPY && item.dhaspinyin"
  270. class="NNPE-pinyin"
  271. :class="[
  272. pItem.className ? pItem.className : '',
  273. sentIndex == index ? 'wordBlank' : '',
  274. noFont.indexOf(pItem.pinyin) > -1 ? 'noFont' : '',
  275. ]"
  276. :style="{
  277. fontSize: attrib && attrib.pinyin_size ? attrib.pinyin_size : '14px',
  278. height:
  279. attrib && attrib.pinyin_size
  280. ? attrib.pinyin_size.replace('pt', '') * 1.5 + 'pt'
  281. : '22px',
  282. }"
  283. >{{ NumberList.indexOf(pItem.pinyin) == -1 ? pItem.pinyin : '' }}</span
  284. >
  285. </template>
  286. </span>
  287. <span class="NNPE-words-box">
  288. <template v-if="curQue.property.pinyin_position == 'top'">
  289. <span
  290. v-if="config.isShowPY && item.dhaspinyin"
  291. :class="[
  292. 'NNPE-pinyin',
  293. sentIndex == index ? 'wordBlank' : '',
  294. noFont.indexOf(item.sentArr[pIndex + 1].pinyin) > -1 ? 'noFont' : '',
  295. ]"
  296. style="text-align: left"
  297. :style="{
  298. fontSize: attrib && attrib.pinyin_size ? attrib.pinyin_size : '14px',
  299. height:
  300. attrib && attrib.pinyin_size
  301. ? attrib.pinyin_size.replace('pt', '') * 1.5 + 'pt'
  302. : '22px',
  303. }"
  304. >{{
  305. NumberList.indexOf(item.sentArr[pIndex + 1].pinyin) == -1
  306. ? item.sentArr[pIndex + 1].pinyin
  307. : ''
  308. }}</span
  309. >
  310. </template>
  311. <span class="NNPE-chs" style="text-align: left">
  312. <span
  313. :class="[
  314. isPlaying &&
  315. pItem.timeList[pItem.leg - 1] &&
  316. curTime >= pItem.timeList[pItem.leg - 1].wordBg &&
  317. curQue.wordTime &&
  318. curQue.wordTime[index] &&
  319. curTime <= curQue.wordTime[index].ed
  320. ? 'active'
  321. : '',
  322. sentIndex == index ? 'wordBlank' : '',
  323. ]"
  324. :style="{
  325. fontFamily: item.sentArr[pIndex + 1].config.fontFamily,
  326. height:
  327. attrib && attrib.font_size
  328. ? attrib.font_size.replace('pt', '') * 1.4 + 'pt'
  329. : '28px',
  330. fontSize: attrib && attrib.font_size ? attrib.font_size : '20px',
  331. lineHeight:
  332. attrib && attrib.font_size
  333. ? attrib.font_size.replace('pt', '') * 1.4 + 'pt'
  334. : '28px',
  335. display: 'inline-block',
  336. color:
  337. isPlaying &&
  338. pItem.timeList[pItem.leg - 1] &&
  339. curTime >= pItem.timeList[pItem.leg - 1].wordBg &&
  340. curQue.wordTime &&
  341. curQue.wordTime[index] &&
  342. curTime <= curQue.wordTime[index].ed &&
  343. attrib
  344. ? attrib.topic_color
  345. : '',
  346. }"
  347. >
  348. {{
  349. NumberList.indexOf(item.sentArr[pIndex + 1].pinyin) == -1
  350. ? item.sentArr[pIndex + 1].chs
  351. : ''
  352. }}</span
  353. >
  354. </span>
  355. <template v-if="curQue.property.pinyin_position == 'bottom'">
  356. <span
  357. v-if="config.isShowPY && item.dhaspinyin"
  358. :class="[
  359. 'NNPE-pinyin',
  360. sentIndex == index ? 'wordBlank' : '',
  361. noFont.indexOf(item.sentArr[pIndex + 1].pinyin) > -1 ? 'noFont' : '',
  362. ]"
  363. style="text-align: left"
  364. :style="{
  365. fontSize: attrib && attrib.pinyin_size ? attrib.pinyin_size : '14px',
  366. height:
  367. attrib && attrib.pinyin_size
  368. ? attrib.pinyin_size.replace('pt', '') * 1.5 + 'pt'
  369. : '22px',
  370. }"
  371. >{{
  372. NumberList.indexOf(item.sentArr[pIndex + 1].pinyin) == -1
  373. ? item.sentArr[pIndex + 1].pinyin
  374. : ''
  375. }}</span
  376. >
  377. </template>
  378. </span>
  379. <span
  380. v-if="
  381. item.sentArr[pIndex + 2] &&
  382. item.sentArr[pIndex + 2].chs &&
  383. chsFhList.indexOf(item.sentArr[pIndex + 2].chs) > -1
  384. "
  385. class="NNPE-words-box"
  386. >
  387. <template v-if="curQue.property.pinyin_position == 'top'">
  388. <span
  389. v-if="config.isShowPY && item.dhaspinyin"
  390. :class="[
  391. 'NNPE-pinyin',
  392. sentIndex == index ? 'wordBlank' : '',
  393. noFont.indexOf(item.sentArr[pIndex + 2].pinyin) > -1 ? 'noFont' : '',
  394. ]"
  395. style="text-align: left"
  396. :style="{
  397. fontSize: attrib && attrib.pinyin_size ? attrib.pinyin_size : '14px',
  398. height:
  399. attrib && attrib.pinyin_size
  400. ? attrib.pinyin_size.replace('pt', '') * 1.5 + 'pt'
  401. : '22px',
  402. }"
  403. >{{
  404. NumberList.indexOf(item.sentArr[pIndex + 2].pinyin) == -1
  405. ? item.sentArr[pIndex + 2].pinyin
  406. : ''
  407. }}</span
  408. >
  409. </template>
  410. <span class="NNPE-chs" style="text-align: left">
  411. <span
  412. :class="[
  413. isPlaying &&
  414. pItem.timeList[pItem.leg - 1] &&
  415. curTime >= pItem.timeList[pItem.leg - 1].wordBg &&
  416. curQue.wordTime &&
  417. curQue.wordTime[index] &&
  418. curTime <= curQue.wordTime[index].ed
  419. ? 'active'
  420. : '',
  421. sentIndex == index ? 'wordBlank' : '',
  422. ]"
  423. :style="{
  424. fontFamily: item.sentArr[pIndex + 2].config.fontFamily,
  425. height:
  426. attrib && attrib.font_size
  427. ? attrib.font_size.replace('pt', '') * 1.4 + 'pt'
  428. : '28px',
  429. fontSize: attrib && attrib.font_size ? attrib.font_size : '20px',
  430. lineHeight:
  431. attrib && attrib.font_size
  432. ? attrib.font_size.replace('pt', '') * 1.4 + 'pt'
  433. : '28px',
  434. display: 'inline-block',
  435. color:
  436. isPlaying &&
  437. pItem.timeList[pItem.leg - 1] &&
  438. curTime >= pItem.timeList[pItem.leg - 1].wordBg &&
  439. curQue.wordTime &&
  440. curQue.wordTime[index] &&
  441. curTime <= curQue.wordTime[index].ed &&
  442. attrib
  443. ? attrib.topic_color
  444. : '',
  445. }"
  446. >
  447. {{
  448. NumberList.indexOf(item.sentArr[pIndex + 2].pinyin) == -1
  449. ? item.sentArr[pIndex + 2].chs
  450. : ''
  451. }}</span
  452. >
  453. </span>
  454. <template v-if="curQue.property.pinyin_position == 'bottom'">
  455. <span
  456. v-if="config.isShowPY && item.dhaspinyin"
  457. :class="[
  458. 'NNPE-pinyin',
  459. sentIndex == index ? 'wordBlank' : '',
  460. noFont.indexOf(item.sentArr[pIndex + 2].pinyin) > -1 ? 'noFont' : '',
  461. ]"
  462. style="text-align: left"
  463. :style="{
  464. fontSize: attrib && attrib.pinyin_size ? attrib.pinyin_size : '14px',
  465. height:
  466. attrib && attrib.pinyin_size
  467. ? attrib.pinyin_size.replace('pt', '') * 1.5 + 'pt'
  468. : '22px',
  469. }"
  470. >{{
  471. NumberList.indexOf(item.sentArr[pIndex + 2].pinyin) == -1
  472. ? item.sentArr[pIndex + 2].pinyin
  473. : ''
  474. }}</span
  475. >
  476. </template>
  477. </span>
  478. </template>
  479. <template v-else>
  480. <template v-if="curQue.property.pinyin_position == 'top'">
  481. <span
  482. v-if="config.isShowPY && item.dhaspinyin"
  483. class="NNPE-pinyin"
  484. :class="[
  485. pItem.chs != '“' && pItem.padding ? 'padding' : '',
  486. pItem.className ? pItem.className : '',
  487. sentIndex == index ? 'wordBlank' : '',
  488. noFont.indexOf(item.pinyin) > -1 ? 'noFont' : '',
  489. ]"
  490. :style="{
  491. fontSize: attrib && attrib.pinyin_size ? attrib.pinyin_size : '14px',
  492. height:
  493. attrib && attrib.pinyin_size
  494. ? attrib.pinyin_size.replace('pt', '') * 1.5 + 'pt'
  495. : '22px',
  496. }"
  497. >{{ NumberList.indexOf(pItem.pinyin) == -1 ? pItem.pinyin : '' }}</span
  498. >
  499. </template>
  500. <span
  501. v-if="pItem.chs != '#'"
  502. class="NNPE-chs"
  503. :class="[
  504. pItem.chs != '“' && pItem.padding && config.isShowPY && item.dhaspinyin ? 'padding' : '',
  505. sentIndex == index ? 'wordBlank' : '',
  506. ]"
  507. >
  508. <template>
  509. <span
  510. v-for="(wItem, wIndex) in pItem.leg"
  511. :key="'ci' + wIndex + pIndex + index"
  512. :class="[
  513. isPlaying &&
  514. pItem.timeList &&
  515. pItem.timeList[wIndex] &&
  516. curTime >= pItem.timeList[wIndex].wordBg &&
  517. curQue.wordTime &&
  518. curQue.wordTime[index] &&
  519. curTime <= curQue.wordTime[index].ed
  520. ? 'active'
  521. : '',
  522. ]"
  523. :style="{
  524. fontFamily: pItem.config.fontFamily,
  525. height:
  526. attrib && attrib.font_size
  527. ? attrib.font_size.replace('pt', '') * 1.4 + 'pt'
  528. : '28px',
  529. fontSize: attrib && attrib.font_size ? attrib.font_size : '20px',
  530. lineHeight:
  531. attrib && attrib.font_size
  532. ? attrib.font_size.replace('pt', '') * 1.4 + 'pt'
  533. : '28px',
  534. display: 'inline-block',
  535. color:
  536. isPlaying &&
  537. pItem.timeList &&
  538. pItem.timeList[wIndex] &&
  539. curTime >= pItem.timeList[wIndex].wordBg &&
  540. curQue.wordTime &&
  541. curQue.wordTime[index] &&
  542. curTime <= curQue.wordTime[index].ed &&
  543. attrib
  544. ? attrib.topic_color
  545. : '',
  546. }"
  547. >{{ NumberList.indexOf(pItem.chs[wIndex]) == -1 ? pItem.chs[wIndex] : '' }}</span
  548. >
  549. </template>
  550. </span>
  551. <template v-if="curQue.property.pinyin_position == 'bottom'">
  552. <span
  553. v-if="config.isShowPY && item.dhaspinyin"
  554. class="NNPE-pinyin"
  555. :class="[
  556. pItem.chs != '“' && pItem.padding ? 'padding' : '',
  557. pItem.className ? pItem.className : '',
  558. sentIndex == index ? 'wordBlank' : '',
  559. ]"
  560. :style="{
  561. fontSize: attrib && attrib.pinyin_size ? attrib.pinyin_size : '14px',
  562. height:
  563. attrib && attrib.pinyin_size
  564. ? attrib.pinyin_size.replace('pt', '') * 1.5 + 'pt'
  565. : '22px',
  566. }"
  567. >{{ NumberList.indexOf(pItem.pinyin) == -1 ? pItem.pinyin : '' }}</span
  568. >
  569. </template>
  570. </template>
  571. </template>
  572. </template>
  573. <template v-else>
  574. <span
  575. :style="{
  576. height: pItem.height + 'px',
  577. width: pItem.width + 'px',
  578. }"
  579. ></span>
  580. </template>
  581. </div>
  582. </div>
  583. <div style="overflow: hidden; clear: both"></div>
  584. <div
  585. v-if="
  586. item.enwords &&
  587. config.isShowEN &&
  588. (!curQue.enPosition || (curQue.enPosition && curQue.enPosition == 'bottom'))
  589. "
  590. :class="['enwords', sentIndex == index ? 'wordBlank' : '']"
  591. >
  592. {{ item.enwords }}
  593. </div>
  594. <div
  595. v-if="curQue.property.multilingual_position === 'para'"
  596. class="multilingual-para"
  597. :class="[item.isTitle ? 'multilingual-para-center' : '']"
  598. >
  599. {{
  600. multilingualTextList[multilingual] && multilingualTextList[multilingual][index]
  601. ? multilingualTextList[multilingual][index]
  602. : ''
  603. }}
  604. </div>
  605. </div>
  606. </div>
  607. </div>
  608. <div v-show="sentIndex == index" class="Soundrecord-content">
  609. <div class="Soundrecord-content-inner">
  610. <Soundrecord
  611. type="promax"
  612. class="luyin-box"
  613. :TaskModel="TaskModel"
  614. :answer-record-list="
  615. curQue.Bookanswer.practiceModel[index] && curQue.Bookanswer.practiceModel[index].recordList
  616. "
  617. :tm-index="index"
  618. v-if="refresh"
  619. :sent-index="sentIndex"
  620. :attrib="attrib"
  621. @getWavblob="getWavblob"
  622. @handleParentPlay="handleParentPlay"
  623. @sentPause="sentPause"
  624. @handleWav="handleWav"
  625. />
  626. <div v-if="curQue.mp3_list && curQue.mp3_list.length > 0" class="compare-box">
  627. <Audio-compare
  628. :theme-color="attrib ? attrib.topic_color : '#e35454'"
  629. :index="index"
  630. :sent-index="sentIndex"
  631. :url="curQue.mp3_list[0].id"
  632. :bg="curQue.wordTime[index].bg"
  633. :ed="curQue.wordTime[index].ed"
  634. :wavblob="wavblob"
  635. :get-cur-time="getCurTime"
  636. :sent-pause="sentPause"
  637. :is-record="isRecord"
  638. :handle-change-stop-audio="handleChangeStopAudio"
  639. :get-play-status="getPlayStatus"
  640. :attrib="attrib"
  641. />
  642. </div>
  643. </div>
  644. <span class="full-screen-icon" @click="fullScreen">
  645. <svg-icon
  646. icon-class="icon-full"
  647. size="24"
  648. :style="{
  649. color: attrib && attrib.topic_color ? attrib.topic_color : '',
  650. }"
  651. />
  652. </span>
  653. </div>
  654. </div>
  655. <!-- <div class="multilingual" v-for="(items, indexs) in multilingualTextList" :key="indexs">
  656. {{ items }}
  657. </div> -->
  658. </div>
  659. </template>
  660. <template v-for="(items, indexs) in curQue.detail">
  661. <div
  662. v-if="
  663. curQue.property.multilingual_position === 'all' &&
  664. items.multilingualTextList &&
  665. items.multilingualTextList[multilingual] &&
  666. items.multilingualTextList[multilingual].length > 0
  667. "
  668. :key="indexs"
  669. class="multilingual"
  670. >
  671. <div class="multilingual-para" :class="[items.isTitle ? 'multilingual-para-center' : '']">
  672. {{
  673. items.multilingualTextList && items.multilingualTextList[multilingual]
  674. ? items.multilingualTextList[multilingual].join(' ')
  675. : ''
  676. }}
  677. </div>
  678. </div>
  679. </template>
  680. <div
  681. v-if="
  682. ((curQue.mp3_list && curQue.mp3_list.length > 0 && curQue.mp3_list[0].url) ||
  683. config.isHasPY ||
  684. config.isHasEN) &&
  685. curQue.property.mp3_position === 'bottom'
  686. "
  687. class="aduioLine-box aduioLine-practice-npc aduioLine-box-bottom"
  688. >
  689. <div class="aduioLine-content">
  690. <template v-if="curQue.mp3_list && curQue.mp3_list.length > 0 && curQue.mp3_list[0].url">
  691. <AudioLine
  692. ref="audioLine"
  693. audio-id="diaPraAudio"
  694. :mp3="curQue.mp3_list[0].url"
  695. :get-cur-time="getCurTime"
  696. :stop-audio="stopAudio"
  697. :width="colLength == 2 ? 175 : isPhone ? 200 : 750"
  698. :is-repeat="isRepeat"
  699. :mp3-source="curQue.mp3_list[0].source"
  700. :ed="ed"
  701. type="audioLine"
  702. :attrib="attrib"
  703. @handleChangeStopAudio="handleChangeStopAudio"
  704. @emptyEd="emptyEd"
  705. />
  706. </template>
  707. </div>
  708. <div class="aduioLine-right">
  709. <SvgIcon
  710. v-if="config.isHasPY"
  711. icon-class="repeat-1"
  712. size="16"
  713. :class="['Repeat-16', isRepeat ? '' : 'disabled']"
  714. :style="{ color: isRepeat ? (attrib ? attrib.topic_color : '') : '#DCDFE6', cursor: 'pointer' }"
  715. @click="changeRepeat"
  716. />
  717. <!-- <span
  718. :class="['pinyin-16', config.isShowPY ? '' : 'disabled']"
  719. @click="changePinyin"
  720. v-if="config.isHasPY"
  721. ></span>
  722. <span :class="['EN-16', config.isShowEN ? '' : 'disabled']" @click="changeEN" v-if="config.isHasEN"></span> -->
  723. <SvgIcon
  724. v-if="config.isHasPY"
  725. icon-class="pin-btn"
  726. size="16"
  727. :class="['pinyin-16', config.isShowPY ? '' : 'disabled']"
  728. :style="{ color: config.isShowPY ? (attrib ? attrib.topic_color : '') : '#DCDFE6' }"
  729. @click="changePinyin"
  730. />
  731. <!-- <span :class="['EN-16', config.isShowEN ? '' : 'disabled']" @click="changeEN" v-if="config.isHasEN"></span> -->
  732. <SvgIcon
  733. v-if="config.isHasEN"
  734. icon-class="en-btn"
  735. size="16"
  736. :class="['EN-16', config.isShowEN ? '' : 'disabled']"
  737. :style="{ color: config.isShowEN ? (attrib ? attrib.topic_color : '') : '#DCDFE6' }"
  738. @click="changeEN"
  739. />
  740. </div>
  741. </div>
  742. <div :id="'screen-' + mathNum" class="voice-full-screen">
  743. <Voicefullscreen
  744. v-if="isFull && resObj"
  745. :theme-color="attrib ? attrib.topic_color : '#e35454'"
  746. :cur-que="curQue"
  747. :sent-list="resObj.sentList"
  748. :sent-index="sentIndex"
  749. :mp3="curQue.mp3_list && curQue.mp3_list[0] ? curQue.mp3_list[0].id : ''"
  750. :no-font="noFont"
  751. :NNPENewWordList="NNPENewWordList"
  752. :NNPEAnnotationList="NNPEAnnotationList"
  753. :current-tree-i-d="currentTreeID"
  754. :is-full="isFull"
  755. :config="config"
  756. :TaskModel="TaskModel"
  757. :NpcNewWordMp3="NpcNewWordMp3"
  758. :attrib="attrib"
  759. @handleWav="handleWav"
  760. @changePinyin="changePinyin"
  761. @changeEN="changeEN"
  762. @exitFullscreen="exitFullscreen"
  763. @changeIsFull="changeIsFull"
  764. />
  765. </div>
  766. </div>
  767. </template>
  768. <script>
  769. import { timeStrToSen } from '@/utils/transform';
  770. import AudioLine from '../voice_matrix/components/AudioLine.vue';
  771. import Soundrecord from '../../common/SoundRecord.vue'; // 录音模板
  772. import RoleChs from './RoleChs.vue';
  773. import AudioCompare from '../article/components/AudioCompare.vue';
  774. import Voicefullscreen from '../article/Voicefullscreen.vue';
  775. export default {
  776. name: 'ArticleView',
  777. components: {
  778. AudioLine,
  779. Soundrecord,
  780. RoleChs,
  781. AudioCompare,
  782. Voicefullscreen,
  783. },
  784. filters: {
  785. handlePinyin(wordsList) {
  786. let str = '';
  787. wordsList.forEach((item, index) => {
  788. if (index < wordsList.length - 1) {
  789. str += `${item.pinyin} `;
  790. } else {
  791. str += item.pinyin;
  792. }
  793. });
  794. return str;
  795. },
  796. handleChs(wordsList) {
  797. let str = '';
  798. wordsList.forEach((item, index) => {
  799. if (index < wordsList.length - 1) {
  800. str += `${item.chs} `;
  801. } else {
  802. str += item.chs;
  803. }
  804. });
  805. return str;
  806. },
  807. },
  808. props: [
  809. 'curQue',
  810. 'colorBox',
  811. 'noFont',
  812. 'attrib',
  813. 'config',
  814. 'NNPENewWordList',
  815. 'NNPEAnnotationList',
  816. 'currentTreeID',
  817. 'TaskModel',
  818. 'colLength',
  819. 'NpcNewWordMp3',
  820. 'isPhone',
  821. 'multilingual',
  822. ],
  823. data() {
  824. return {
  825. wavblob: null,
  826. resObj: null,
  827. curTime: 0, // 单位s
  828. chsFhList: [',', '。', '”', ':', '》', '?', '!', ';', '、'],
  829. enFhList: [',', '.', ';', '?', '!', ':', '>', '<'],
  830. NumberList: ['①', '②', '③', '④', '⑤', '⑥', '⑦', '⑧', '⑨', '⑩', '⑪', '⑫', '⑬', '⑭', '⑮', '⑯', '⑰', '⑱', '⑲', '⑳'],
  831. stopAudio: false,
  832. sentIndex: 0,
  833. isRepeat: false,
  834. currSent: null, // 当前句子的时间
  835. isRecord: false,
  836. isFull: false,
  837. mathNum: Math.random().toString(36).substr(2),
  838. ed: undefined,
  839. refresh: true,
  840. highWords: null,
  841. highWordsArr: [],
  842. highIndex: 0,
  843. newWordList: [],
  844. multilingualTextList: {},
  845. };
  846. },
  847. computed: {
  848. isPlaying() {
  849. let playing = false;
  850. if (this.$refs.audioLine) {
  851. playing = this.$refs.audioLine.audio.isPlaying;
  852. }
  853. return playing;
  854. },
  855. },
  856. watch: {
  857. sentIndex: {
  858. handler(newVal, oldVal) {
  859. let _this = this;
  860. if (newVal != oldVal) {
  861. let Bookanswer = _this.curQue.Bookanswer;
  862. if (
  863. Bookanswer &&
  864. Bookanswer.practiceModel &&
  865. Bookanswer.practiceModel[newVal] &&
  866. Bookanswer.practiceModel[newVal].recordList &&
  867. Bookanswer.practiceModel[newVal].recordList.length > 0
  868. ) {
  869. _this.wavblob = Bookanswer.practiceModel[newVal].recordList[0].wavData;
  870. } else {
  871. _this.wavblob = '';
  872. }
  873. }
  874. },
  875. deep: true,
  876. },
  877. isFull: {
  878. handler(newVal, oldVal) {
  879. let _this = this;
  880. _this.refresh = false;
  881. if (!newVal) {
  882. _this.$nextTick(() => {
  883. // 重新渲染组件
  884. _this.refresh = true;
  885. });
  886. }
  887. },
  888. deep: true,
  889. },
  890. },
  891. // 生命周期 - 创建完成(可以访问当前this实例)
  892. created() {},
  893. // 生命周期 - 挂载完成(可以访问DOM元素)
  894. mounted() {
  895. if (this.curQue) {
  896. this.handleData();
  897. }
  898. },
  899. beforeCreate() {}, // 生命周期 - 创建之前
  900. beforeMount() {}, // 生命周期 - 挂载之前
  901. beforeUpdate() {}, // 生命周期 - 更新之前
  902. updated() {}, // 生命周期 - 更新之后
  903. beforeDestroy() {}, // 生命周期 - 销毁之前
  904. destroyed() {}, // 生命周期 - 销毁完成
  905. activated() {},
  906. // 方法集合
  907. methods: {
  908. getPlayStatus(val) {
  909. // this.isPlaying = val;
  910. },
  911. pauseAudio() {
  912. let audio = document.getElementsByTagName('audio');
  913. if (audio && audio.length > 0 && window.location.href.indexOf('GCLS-Learn') == -1) {
  914. audio.forEach((item) => {
  915. item.pause();
  916. });
  917. }
  918. },
  919. pauseVideo() {
  920. let video = document.getElementsByTagName('video');
  921. if (video && video.length > 0 && window.location.href.indexOf('GCLS-Learn') == -1) {
  922. video.forEach((item) => {
  923. item.pause();
  924. });
  925. }
  926. },
  927. // 语音全屏
  928. fullScreen(type) {
  929. this.pauseAudio();
  930. this.pauseVideo();
  931. this.isFull = true;
  932. this.goFullscreen();
  933. },
  934. goFullscreen() {
  935. let id = `screen-${this.mathNum}`;
  936. let element = document.getElementById(id);
  937. if (element.requestFullscreen) {
  938. element.requestFullscreen();
  939. } else if (element.msRequestFullscreen) {
  940. element.msRequestFullscreen();
  941. } else if (element.mozRequestFullScreen) {
  942. element.mozRequestFullScreen();
  943. } else if (element.webkitRequestFullscreen) {
  944. element.webkitRequestFullscreen();
  945. }
  946. },
  947. exitFullscreen() {
  948. this.isFull = false;
  949. if (document.exitFullscreen) {
  950. document.exitFullscreen();
  951. } else if (document.msExitFullscreen) {
  952. document.msExitFullscreen();
  953. } else if (document.mozCancelFullScreen) {
  954. document.mozCancelFullScreen();
  955. } else if (document.webkitExitFullscreen) {
  956. document.webkitExitFullscreen();
  957. }
  958. },
  959. changeIsFull() {
  960. this.isFull = false;
  961. },
  962. getWavblob(wavblob) {
  963. this.wavblob = wavblob;
  964. },
  965. sentPause(isRecord) {
  966. this.isRecord = isRecord;
  967. },
  968. getCurTime(curTime) {
  969. let _this = this;
  970. if (_this.isRepeat) {
  971. let time = curTime * 1000;
  972. if (time >= _this.currSent.ed || time <= _this.currSent.bg) {
  973. _this.curTime = _this.currSent.bg;
  974. this.$refs.audioLine.onTimeupdateTime(_this.currSent.bg / 1000, true);
  975. } else {
  976. _this.curTime = curTime * 1000;
  977. }
  978. } else {
  979. _this.curTime = curTime * 1000;
  980. _this.getSentIndex(_this.curTime);
  981. }
  982. },
  983. getSentIndex(curTime) {
  984. for (let i = 0; i < this.curQue.wordTime.length; i++) {
  985. let bg = this.curQue.wordTime[i].bg;
  986. let ed = this.curQue.wordTime[i].ed;
  987. if (curTime >= bg && curTime <= ed) {
  988. this.sentIndex = i;
  989. break;
  990. }
  991. }
  992. },
  993. handleData() {
  994. this.curQue.multilingual.forEach((item) => {
  995. let trans_arr = item.translation.split('\n');
  996. this.$set(this.multilingualTextList, item.type, trans_arr);
  997. });
  998. let resArr = [];
  999. let sentArrTotal = [];
  1000. let curQue = JSON.parse(JSON.stringify(this.curQue));
  1001. let wordTimeList = curQue.wordTime;
  1002. let dhaspinyin = false; // 每段是否有拼音
  1003. curQue.detail.forEach((dItem, dIndex) => {
  1004. dhaspinyin = false;
  1005. let roleDetail = this.getRole(dItem);
  1006. dItem.wordsList.forEach((sItem, sIndex) => {
  1007. let sentArr = [];
  1008. let sentence = dItem.sentences[sIndex];
  1009. sItem.forEach((wItem, wIndex) => {
  1010. let startIndex = wIndex == 0 ? 0 : sentArr[wIndex - 1].startIndex + sentArr[wIndex - 1].chs.length;
  1011. let endIndex = wIndex == 0 ? wItem.chs.length : sentArr[wIndex - 1].endIndex + wItem.chs.length;
  1012. // this.judgePad(sItem, wItem, wIndex);
  1013. this.mergeWordSymbol(wItem);
  1014. let words = '';
  1015. if (this.newWordList.length > 0) {
  1016. if (!this.highWords) {
  1017. this.findLightWord(wItem, wIndex, sentence, sItem);
  1018. words = this.highWords ? this.highWords.words : '';
  1019. } else if (wIndex > this.highWords.endIndex - 1) {
  1020. this.highWords = null;
  1021. this.findLightWord(wItem, wIndex, sentence, sItem);
  1022. words = this.highWords ? this.highWords.words : '';
  1023. } else {
  1024. words = this.highWords ? this.highWords.words : '';
  1025. }
  1026. }
  1027. let obj = {
  1028. paraIndex: dIndex, // 段落索引
  1029. sentIndex: sIndex, // 在段落中句子索引
  1030. wordIndex: wIndex, // 单词的索引
  1031. pinyin:
  1032. curQue.pinyin_type === 'pinyin'
  1033. ? curQue.property.is_first_sentence_first_hz_pinyin_first_char_upper_case === 'true' && wIndex === 0
  1034. ? wItem.pinyin_up
  1035. : wItem.pinyin
  1036. : wItem.pinyin_tone,
  1037. chs: wItem.chs,
  1038. padding: true,
  1039. className: wItem.className,
  1040. isShow: wItem.isShow,
  1041. startIndex,
  1042. endIndex,
  1043. leg: wItem.chs.length,
  1044. timeList: [],
  1045. words,
  1046. config: {
  1047. fontFamily: wItem.fontFamily,
  1048. },
  1049. };
  1050. sentArr.push(obj);
  1051. if (wItem.pinyin) dhaspinyin = true;
  1052. });
  1053. let objs = {
  1054. roleDetail,
  1055. sentArr,
  1056. enwords: dItem.sentencesEn && dItem.sentencesEn[sIndex] && dItem.sentencesEn[sIndex].replace(/\'/g, '’'),
  1057. dhaspinyin,
  1058. };
  1059. sentArrTotal.push(sentArr);
  1060. resArr.push(objs);
  1061. });
  1062. });
  1063. if (wordTimeList && wordTimeList.length > 0) {
  1064. this.mergeWordTime(sentArrTotal, wordTimeList);
  1065. }
  1066. this.resObj = { sentList: resArr };
  1067. },
  1068. // 获取角色
  1069. getRole(dItem) {
  1070. let roleIndex = dItem.roleIndex;
  1071. let resObj = null;
  1072. let roleList = JSON.parse(JSON.stringify(this.curQue.property.role_list));
  1073. for (let i = 0; i < roleList.length; i++) {
  1074. let item = roleList[i];
  1075. if (item.id == roleIndex) {
  1076. resObj = item;
  1077. // resObj.color = this.colorBox[i];
  1078. break;
  1079. }
  1080. }
  1081. return resObj;
  1082. },
  1083. mergeWordTime(resArr, wordTimeList) {
  1084. resArr.forEach((item, index) => {
  1085. let wordsResultList = wordTimeList[index].wordsResultList;
  1086. item.forEach((wItem) => {
  1087. let startIndex = wItem.startIndex;
  1088. let endIndex = wItem.endIndex;
  1089. wItem.timeList = wordsResultList.slice(startIndex, endIndex);
  1090. });
  1091. });
  1092. },
  1093. // 词和标点合一起
  1094. mergeWordSymbol(wItem) {
  1095. if (this.chsFhList.indexOf(wItem.chs) > -1) {
  1096. wItem.isShow = false;
  1097. } else {
  1098. wItem.isShow = true;
  1099. }
  1100. },
  1101. findLightWord(wItem, startIndex, sentence, sItem) {
  1102. let endIndex = 0,
  1103. words = '';
  1104. this.newWordList.forEach((item) => {
  1105. if (item.length == 1) {
  1106. if (item == wItem.chs && !wItem.banLight) {
  1107. words = wItem.chs;
  1108. endIndex = startIndex + 1;
  1109. }
  1110. } else if (item[0] == wItem.chs && sentence.indexOf(item) > -1) {
  1111. let index = null;
  1112. let chsStr = '';
  1113. for (let i = startIndex; i < sItem.length + 1; i++) {
  1114. index = i;
  1115. if (chsStr.length == item.length) {
  1116. break;
  1117. } else {
  1118. chsStr += sItem[i] ? sItem[i].chs : '';
  1119. }
  1120. }
  1121. if (chsStr == item && !wItem.banLight) {
  1122. words = item;
  1123. endIndex = index;
  1124. }
  1125. } else if (wItem.new_word && wItem.new_word == item && !wItem.banLight) {
  1126. words = item;
  1127. endIndex = startIndex + 1;
  1128. }
  1129. });
  1130. if (words) {
  1131. this.highWords = { words, endIndex };
  1132. } else {
  1133. this.highWords = null;
  1134. }
  1135. },
  1136. // 判断是否有padding
  1137. judgePad(sItem, wItem, curIndex) {
  1138. let leg = sItem.length;
  1139. if (curIndex < leg - 1) {
  1140. let nextIndex = curIndex + 1;
  1141. let chs = sItem[nextIndex].chs;
  1142. if (this.chsFhList.indexOf(chs) > -1 || this.chsFhList.indexOf(wItem.chs) > -1) {
  1143. wItem.padding = false;
  1144. } else {
  1145. wItem.padding = true;
  1146. }
  1147. if (this.enFhList.indexOf(wItem.pinyin) > -1) {
  1148. wItem.className = 'textLeft';
  1149. }
  1150. }
  1151. },
  1152. // 转化时间
  1153. handleTimeList(list) {
  1154. let listRes = [];
  1155. list.forEach((item) => {
  1156. let res = timeStrToSen(item);
  1157. listRes.push(res);
  1158. });
  1159. return listRes;
  1160. },
  1161. // 计算总时间
  1162. countWordTime(sentArr) {
  1163. let total = 0;
  1164. sentArr.forEach((item) => {
  1165. total += item.endTime;
  1166. });
  1167. return total;
  1168. },
  1169. // 点击播放某个句子
  1170. handleChangeTime(time, index, ed) {
  1171. let _this = this;
  1172. if (_this.isRepeat) {
  1173. _this.currSent = _this.curQue.wordTime[index];
  1174. }
  1175. _this.sentIndex = index;
  1176. _this.ed = ed;
  1177. if (time) {
  1178. _this.curTime = time;
  1179. _this.$refs.audioLine.onTimeupdateTime(time / 1000, true);
  1180. }
  1181. },
  1182. emptyEd() {
  1183. this.ed = undefined;
  1184. },
  1185. handleWav(list, tmIndex) {
  1186. tmIndex = tmIndex || 0;
  1187. this.curQue.Bookanswer.practiceModel[tmIndex] = {
  1188. recordList: [],
  1189. };
  1190. this.$set(this.curQue.Bookanswer.practiceModel[tmIndex], 'recordList', list);
  1191. },
  1192. // 录音时暂停音频播放
  1193. handleParentPlay() {
  1194. this.stopAudio = true;
  1195. },
  1196. // 音频播放时改变布尔值
  1197. handleChangeStopAudio() {
  1198. this.stopAudio = false;
  1199. },
  1200. // 拼音的显示和隐藏
  1201. changePinyin() {
  1202. if (this.config.isHasPY) {
  1203. this.$emit('changeConfig', 'isShowPY');
  1204. }
  1205. },
  1206. // 英文的显示和隐藏
  1207. changeEN() {
  1208. if (this.config.isHasEN) {
  1209. this.$emit('changeConfig', 'isShowEN');
  1210. }
  1211. },
  1212. // 单句是否重复播放
  1213. changeRepeat() {
  1214. let _this = this;
  1215. _this.isRepeat = !_this.isRepeat;
  1216. this.currSent = _this.curQue.wordTime[_this.sentIndex];
  1217. },
  1218. handleNewword() {
  1219. let NewWordList = [];
  1220. this.NNPENewWordList.forEach((wItem) => {
  1221. // item.forEach((wItem) => {
  1222. if (wItem.new_word) {
  1223. NewWordList.push(wItem.new_word);
  1224. } else if (wItem.detail && wItem.detail.sentence) {
  1225. NewWordList.push(wItem.detail.sentence);
  1226. }
  1227. // });
  1228. });
  1229. this.newWordList = JSON.parse(JSON.stringify(NewWordList));
  1230. },
  1231. }, // 如果页面有keep-alive缓存功能,这个函数会触发
  1232. };
  1233. </script>
  1234. <style lang="scss" scoped>
  1235. //@import url(); 引入公共css类
  1236. .NNPE-ArticleView {
  1237. position: relative;
  1238. width: 100%;
  1239. .ArticleView-full {
  1240. position: absolute;
  1241. top: -44px;
  1242. left: 0;
  1243. z-index: 99999;
  1244. padding-left: 24px;
  1245. font-size: 14px;
  1246. font-weight: bold;
  1247. line-height: 24px;
  1248. color: #000;
  1249. background: url('@/assets/full-screen-red.png') left center no-repeat;
  1250. background-size: 16px 16px;
  1251. }
  1252. .NPC-sentences-list {
  1253. padding: 0 0 24px;
  1254. }
  1255. .multilingual {
  1256. padding: 6px 24px 12px;
  1257. word-break: break-word;
  1258. }
  1259. .aduioLine-content {
  1260. flex: 1;
  1261. }
  1262. .aduioLine-practice-npc {
  1263. display: flex;
  1264. align-items: center;
  1265. justify-content: flex-start;
  1266. .aduioLine-right {
  1267. box-sizing: border-box;
  1268. display: flex;
  1269. align-items: center;
  1270. justify-content: space-between;
  1271. width: 92px;
  1272. height: 40px;
  1273. padding: 0 12px;
  1274. border-left: 1px solid rgba(0, 0, 0, 10%);
  1275. > span {
  1276. width: 16px;
  1277. height: 16px;
  1278. cursor: pointer;
  1279. }
  1280. }
  1281. }
  1282. .NNPE-detail-box {
  1283. &.active {
  1284. background: rgba(0, 0, 0, 6%);
  1285. }
  1286. }
  1287. .enwords {
  1288. padding-left: 3px;
  1289. font-family: 'Helvetica';
  1290. font-size: 14px;
  1291. font-weight: normal;
  1292. line-height: 22px;
  1293. color: rgba(0, 0, 0, 45%);
  1294. word-break: break-word;
  1295. &.wordBlank {
  1296. color: rgba(0, 0, 0, 85%);
  1297. }
  1298. }
  1299. .NNPE-detail {
  1300. box-sizing: border-box;
  1301. display: flex;
  1302. align-items: flex-start;
  1303. justify-content: flex-start;
  1304. width: 100%;
  1305. padding: 8px 24px;
  1306. overflow: hidden;
  1307. clear: both;
  1308. color: rgba(0, 0, 0, 45%);
  1309. .sentence-box {
  1310. padding-left: 8px;
  1311. overflow: hidden;
  1312. clear: both;
  1313. &-inner {
  1314. box-sizing: border-box;
  1315. float: left;
  1316. padding: 8px 12px;
  1317. border: 1px solid rgba(0, 0, 0, 10%);
  1318. border-radius: 8px;
  1319. }
  1320. .roleDetail {
  1321. display: flex;
  1322. align-items: center;
  1323. justify-content: flex-start;
  1324. height: 36px;
  1325. .pinyin {
  1326. margin-left: 4px;
  1327. font-family: 'League';
  1328. font-size: 14px;
  1329. line-height: 22px;
  1330. color: rgba(0, 0, 0, 85%);
  1331. &.noFont {
  1332. font-family: initial;
  1333. }
  1334. }
  1335. .chs {
  1336. font-family: '楷体';
  1337. font-size: 16px;
  1338. line-height: 24px;
  1339. color: rgba(0, 0, 0, 85%);
  1340. }
  1341. .color85 {
  1342. color: rgba(0, 0, 0, 85%);
  1343. }
  1344. .color45 {
  1345. color: rgba(0, 0, 0, 45%);
  1346. }
  1347. }
  1348. }
  1349. .NNPE-words {
  1350. float: left;
  1351. padding-bottom: 5px;
  1352. &-box {
  1353. float: left;
  1354. > span {
  1355. display: block;
  1356. &.NNPE-pinyin {
  1357. height: 20px;
  1358. font-family: 'League';
  1359. font-size: 14px;
  1360. font-weight: normal;
  1361. line-height: 1.5;
  1362. &.noFont {
  1363. font-family: initial;
  1364. }
  1365. &.textLeft {
  1366. text-align: left;
  1367. }
  1368. &.wordBlank {
  1369. color: rgba(0, 0, 0, 85%);
  1370. }
  1371. }
  1372. &.NNPE-chs {
  1373. font-family: '楷体';
  1374. font-size: 20px;
  1375. line-height: 1.4;
  1376. .active {
  1377. color: #de4444;
  1378. }
  1379. &.wordBlank {
  1380. color: rgba(0, 0, 0, 85%);
  1381. }
  1382. }
  1383. // &.padding {
  1384. // padding-right: 6px;
  1385. // }
  1386. }
  1387. }
  1388. &.textLeft {
  1389. text-align: left;
  1390. }
  1391. &.textCenter {
  1392. text-align: center;
  1393. }
  1394. &.textRight {
  1395. text-align: right;
  1396. }
  1397. > span {
  1398. display: block;
  1399. &.NNPE-pinyin {
  1400. height: 20px;
  1401. font-family: 'League';
  1402. font-size: 14px;
  1403. font-weight: normal;
  1404. line-height: 1.5;
  1405. &.noFont {
  1406. font-family: initial;
  1407. }
  1408. &.textLeft {
  1409. text-align: left;
  1410. }
  1411. &.wordBlank {
  1412. color: rgba(0, 0, 0, 85%);
  1413. }
  1414. }
  1415. &.NNPE-chs {
  1416. font-family: '楷体';
  1417. font-size: 20px;
  1418. line-height: 1.4;
  1419. .active {
  1420. color: #de4444;
  1421. }
  1422. &.wordBlank {
  1423. color: rgba(0, 0, 0, 85%);
  1424. }
  1425. }
  1426. &.padding {
  1427. padding: 0 3px;
  1428. }
  1429. }
  1430. }
  1431. }
  1432. .Soundrecord-content {
  1433. display: flex;
  1434. align-items: center;
  1435. justify-content: space-between;
  1436. padding: 0 10px 8px 68px;
  1437. &-inner {
  1438. display: flex;
  1439. align-items: center;
  1440. justify-content: flex-start;
  1441. width: 304px;
  1442. padding: 4px 12px;
  1443. background: #fff;
  1444. border: 1px solid rgba(0, 0, 0, 10%);
  1445. border-radius: 8px;
  1446. .luyin-box {
  1447. width: 280px;
  1448. }
  1449. .compare-box {
  1450. display: flex;
  1451. align-items: center;
  1452. justify-content: center;
  1453. height: 32px;
  1454. }
  1455. }
  1456. .full-screen-icon {
  1457. width: 24px;
  1458. height: 24px;
  1459. cursor: pointer;
  1460. // background: url('@/assets/full-screen-red.png') no-repeat left top;
  1461. // background-size: 100% 100%;
  1462. }
  1463. }
  1464. .voice-full-screen {
  1465. // position: fixed;
  1466. // top: 0;
  1467. // left: 0;
  1468. // z-index: 9999;
  1469. }
  1470. }
  1471. </style>