WordModelChs.vue 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327
  1. <!-- -->
  2. <template>
  3. <div class="NNPE-ArticleView" v-if="curQue">
  4. <div
  5. class="aduioLine-box aduioLine-practice-npc"
  6. v-if="
  7. (curQue.mp3_list && curQue.mp3_list.length > 0 && curQue.mp3_list[0].url) || config.isHasPY || config.isHasEN
  8. "
  9. >
  10. <div class="aduioLine-content">
  11. <template v-if="curQue.mp3_list && curQue.mp3_list.length > 0 && curQue.mp3_list[0].url">
  12. <AudioLine
  13. audioId="artPhraseAudio"
  14. :mp3="curQue.mp3_list[0].url"
  15. :getCurTime="getCurTime"
  16. :mp3Source="curQue.mp3_list[0].source"
  17. :width="colLength == 2 ? 200 : 700"
  18. ref="audioLine"
  19. />
  20. </template>
  21. </div>
  22. <div class="aduioLine-right">
  23. <!-- <span
  24. :class="['pinyin-16', config.isShowPY ? '' : 'disabled']"
  25. @click="changePinyin"
  26. v-if="config.isHasPY"
  27. ></span>
  28. <span :class="['EN-16', config.isShowEN ? '' : 'disabled']" @click="changeEN" v-if="config.isHasEN"></span> -->
  29. <SvgIcon
  30. icon-class="PinYin"
  31. size="16"
  32. :class="['pinyin-16', config.isShowPY ? '' : 'disabled']"
  33. @click="changePinyin"
  34. v-if="config.isHasPY"
  35. :style="{ color: themeColor }"
  36. />
  37. <SvgIcon
  38. icon-class="PinYin"
  39. size="16"
  40. :class="['EN-16', config.isShowEN ? '' : 'disabled']"
  41. @click="changeEN"
  42. v-if="config.isHasEN"
  43. :style="{ color: themeColor }"
  44. />
  45. </div>
  46. </div>
  47. <template v-if="!config.isHasEN || (config.isHasEN && !config.isShowEN)">
  48. <template v-if="resArr.length > 0">
  49. <div class="NPC-sentences-list">
  50. <div
  51. :class="['NNPE-detail', item.isTitle ? 'NNPE-detail-title' : '']"
  52. v-for="(item, index) in resArr"
  53. :key="'detail' + index"
  54. >
  55. <div
  56. class="wordsList-box"
  57. :class="[
  58. curQue.detail[index].paragraphAttr
  59. ? 'wordsList-box-' + curQue.detail[index].paragraphAttr.paragraphAlign
  60. : '',
  61. ]"
  62. >
  63. <img :src="articleImg[index]" v-if="articleImg[0] && index == 0" />
  64. <div>
  65. <div
  66. class="NNPE-words"
  67. v-for="(pItem, pIndex) in item.wordsList"
  68. :key="'wordsList' + pIndex"
  69. :class="[
  70. pItem.chs != '“' && pItem.wordIndex == 0 ? 'textLeft' : 'textCenter',
  71. pItem.chs == '“' ? 'textRight' : '',
  72. ]"
  73. >
  74. <template v-if="!pItem.width">
  75. <template v-if="pItem.isShow">
  76. <template
  77. v-if="
  78. item.wordsList[pIndex + 1] &&
  79. item.wordsList[pIndex + 1].chs &&
  80. chsFhList.indexOf(item.wordsList[pIndex + 1].chs) > -1
  81. "
  82. >
  83. <span class="NNPE-words-box" @click="showWordDetail($event, pItem)">
  84. <span
  85. v-if="curQue.property.pinyin_position == 'top' && config.isShowPY && item.dhaspinyin"
  86. class="NNPE-pinyin"
  87. :class="[pItem.className ? pItem.className : '']"
  88. >{{ pItem.pinyin }}</span
  89. >
  90. <span
  91. class="NNPE-chs"
  92. :class="[
  93. item.timeList &&
  94. item.timeList[pItem.sentIndex] &&
  95. curTime >= item.timeList[pItem.sentIndex].bg &&
  96. curTime <= item.timeList[pItem.sentIndex].ed &&
  97. curTime
  98. ? 'active'
  99. : '',
  100. paraIndex == pItem.paraIndex &&
  101. sentIndex == pItem.sentIndex &&
  102. wordIndex == pItem.wordIndex
  103. ? 'wordActive'
  104. : '',
  105. ]"
  106. :style="{
  107. fontFamily: pItem.config.fontFamily,
  108. height: '28px',
  109. display: 'inline-block',
  110. }"
  111. >{{ NumberList.indexOf(pItem.pinyin) == -1 ? pItem.chs : '' }}</span
  112. >
  113. <span
  114. v-if="curQue.property.pinyin_position == 'bottom' && config.isShowPY && item.dhaspinyin"
  115. class="NNPE-pinyin"
  116. :class="[pItem.className ? pItem.className : '']"
  117. >{{ pItem.pinyin }}</span
  118. >
  119. </span>
  120. <span class="NNPE-words-box" @click="showWordDetail($event, item.wordsList[pIndex + 1])">
  121. <span
  122. v-if="curQue.property.pinyin_position == 'top' && config.isShowPY && item.dhaspinyin"
  123. class="NNPE-pinyin"
  124. style="text-align: left"
  125. >{{ item.wordsList[pIndex + 1].pinyin }}</span
  126. >
  127. <span
  128. class="NNPE-chs"
  129. style="text-align: left"
  130. :class="[
  131. item.timeList &&
  132. item.timeList[pItem.sentIndex] &&
  133. curTime >= item.timeList[pItem.sentIndex].bg &&
  134. curTime <= item.timeList[pItem.sentIndex].ed &&
  135. curTime
  136. ? 'active'
  137. : '',
  138. ]"
  139. :style="{
  140. fontFamily: item.wordsList[pIndex + 1].config.fontFamily,
  141. height: '28px',
  142. display: 'inline-block',
  143. }"
  144. >{{
  145. NumberList.indexOf(item.wordsList[pIndex + 1].pinyin) == -1
  146. ? item.wordsList[pIndex + 1].chs
  147. : ''
  148. }}</span
  149. >
  150. <span
  151. v-if="curQue.property.pinyin_position == 'bottom' && config.isShowPY && item.dhaspinyin"
  152. class="NNPE-pinyin"
  153. style="text-align: left"
  154. >{{ item.wordsList[pIndex + 1].pinyin }}</span
  155. >
  156. </span>
  157. <span
  158. class="NNPE-words-box"
  159. v-if="
  160. item.wordsList[pIndex + 2] &&
  161. item.wordsList[pIndex + 2].chs &&
  162. chsFhList.indexOf(item.wordsList[pIndex + 2].chs) > -1
  163. "
  164. @click="showWordDetail($event, item.wordsList[pIndex + 2])"
  165. >
  166. <span
  167. v-if="curQue.property.pinyin_position == 'top' && config.isShowPY && item.dhaspinyin"
  168. :class="[
  169. 'NNPE-pinyin',
  170. noFont.indexOf(item.wordsList[pIndex + 2].pinyin) > -1 ? 'noFont' : '',
  171. ]"
  172. style="text-align: left"
  173. >{{ item.wordsList[pIndex + 2].pinyin }}</span
  174. >
  175. <span
  176. class="NNPE-chs"
  177. style="text-align: left"
  178. :class="[
  179. item.timeList &&
  180. item.timeList[pItem.sentIndex] &&
  181. curTime >= item.timeList[pItem.sentIndex].bg &&
  182. curTime <= item.timeList[pItem.sentIndex].ed &&
  183. curTime
  184. ? 'active'
  185. : '',
  186. pItem.paraIndex == paraIndex && pItem.sentIndex == sentIndex ? 'overActive' : '',
  187. pItem.chstimeList &&
  188. pItem.chstimeList[pItem.leg - 1] &&
  189. curTime >= pItem.chstimeList[pItem.leg - 1].wordBg &&
  190. curQue.wordTime &&
  191. curTime <= item.timeList[pItem.sentIndex].ed
  192. ? 'wordActive'
  193. : '',
  194. ]"
  195. :style="{
  196. fontFamily: item.wordsList[pIndex + 2].config.fontFamily,
  197. height: '28px',
  198. display: 'inline-block',
  199. }"
  200. >{{
  201. NumberList.indexOf(item.wordsList[pIndex + 2].pinyin) == -1
  202. ? item.wordsList[pIndex + 2].chs
  203. : ''
  204. }}</span
  205. >
  206. <span
  207. v-if="curQue.property.pinyin_position == 'bottom' && config.isShowPY && item.dhaspinyin"
  208. :class="[
  209. 'NNPE-pinyin',
  210. noFont.indexOf(item.wordsList[pIndex + 2].pinyin) > -1 ? 'noFont' : '',
  211. ]"
  212. style="text-align: left"
  213. >{{ item.wordsList[pIndex + 2].pinyin }}</span
  214. >
  215. </span>
  216. </template>
  217. <template v-else>
  218. <span
  219. v-if="curQue.property.pinyin_position == 'top' && config.isShowPY && item.dhaspinyin"
  220. class="NNPE-pinyin"
  221. :class="[
  222. pItem.chs != '“' && pItem.padding ? 'padding' : '',
  223. pItem.className ? pItem.className : '',
  224. ]"
  225. >{{ pItem.pinyin }}</span
  226. >
  227. <span
  228. class="NNPE-chs"
  229. :class="[
  230. item.timeList &&
  231. item.timeList[pItem.sentIndex] &&
  232. curTime >= item.timeList[pItem.sentIndex].bg &&
  233. curTime <= item.timeList[pItem.sentIndex].ed &&
  234. curTime
  235. ? 'active'
  236. : '',
  237. pItem.chs != '“' && pItem.padding && config.isShowPY ? 'padding' : '',
  238. ]"
  239. :style="{
  240. fontFamily: pItem.config.fontFamily,
  241. height: '28px',
  242. display: 'inline-block',
  243. }"
  244. @click="showWordDetail($event, pItem)"
  245. >{{ NumberList.indexOf(pItem.pinyin) == -1 ? pItem.chs : '' }}</span
  246. >
  247. <span
  248. v-if="curQue.property.pinyin_position == 'bottom' && config.isShowPY && item.dhaspinyin"
  249. class="NNPE-pinyin"
  250. :class="[
  251. pItem.chs != '“' && pItem.padding ? 'padding' : '',
  252. pItem.className ? pItem.className : '',
  253. ]"
  254. >{{ pItem.pinyin }}</span
  255. >
  256. </template>
  257. </template>
  258. </template>
  259. <template v-else>
  260. <span
  261. :style="{
  262. height: pItem.height + 'px',
  263. width: pItem.width + 'px',
  264. }"
  265. ></span>
  266. </template>
  267. </div>
  268. </div>
  269. <img :src="articleImg[index + 1]" v-if="articleImg[index + 1]" />
  270. </div>
  271. </div>
  272. </div>
  273. </template>
  274. </template>
  275. <template v-else>
  276. <template v-if="resObj">
  277. <!-- -->
  278. <div class="NPC-sentences-list">
  279. <div
  280. :class="['NNPE-detail-box', sentIndex == index ? 'active' : '']"
  281. v-for="(item, index) in resObj.sentList"
  282. :key="'detail' + index"
  283. >
  284. <div :class="['NNPE-details']">
  285. <div
  286. v-if="item.enwords && config.isShowEN && curQue.enPosition && curQue.enPosition == 'top'"
  287. :class="['enwords', sentIndex == index ? 'wordBlank' : '']"
  288. >
  289. {{ item.enwords }}
  290. </div>
  291. <div style="overflow: hidden; clear: both"></div>
  292. <div
  293. class="NNPE-words"
  294. v-for="(pItem, pIndex) in item.sentArr"
  295. :key="'wordsList' + pIndex"
  296. :class="[
  297. pItem.chs != '“' && pItem.wordIndex == 0 ? 'textLeft' : 'textCenter',
  298. pItem.chs == '“' ? 'textRight' : '',
  299. ]"
  300. >
  301. <template v-if="!pItem.width">
  302. <template v-if="pItem.isShow">
  303. <template
  304. v-if="
  305. item.sentArr[pIndex + 1] &&
  306. item.sentArr[pIndex + 1].chs &&
  307. chsFhList.indexOf(item.sentArr[pIndex + 1].chs) > -1
  308. "
  309. >
  310. <span class="NNPE-words-box" @click="showWordDetail($event, pItem)">
  311. <template v-if="curQue.property.pinyin_position == 'top'">
  312. <span
  313. v-if="config.isShowPY"
  314. class="NNPE-pinyin"
  315. :class="[
  316. pItem.className ? pItem.className : '',
  317. sentIndex == index ? 'wordBlank' : '',
  318. noFont.indexOf(pItem.pinyin) > -1 ? 'noFont' : '',
  319. ]"
  320. >{{ pItem.pinyin }}</span
  321. >
  322. </template>
  323. <span
  324. class="NNPE-chs"
  325. :class="[
  326. pItem.padding && config.isShowPY ? 'padding' : '',
  327. sentIndex == index ? 'wordBlank' : '',
  328. ]"
  329. >
  330. <template>
  331. <span
  332. v-for="(wItem, wIndex) in pItem.leg"
  333. :key="'ci' + wIndex + pIndex + index"
  334. :class="[]"
  335. :style="{
  336. fontFamily: pItem.config.fontFamily,
  337. height: '28px',
  338. display: 'inline-block',
  339. }"
  340. >{{ NumberList.indexOf(pItem.pinyin) == -1 ? pItem.chs[wIndex] : '' }}</span
  341. >
  342. </template>
  343. </span>
  344. <template v-if="curQue.property.pinyin_position == 'bottom'">
  345. <span
  346. v-if="config.isShowPY"
  347. class="NNPE-pinyin"
  348. :class="[
  349. pItem.className ? pItem.className : '',
  350. sentIndex == index ? 'wordBlank' : '',
  351. noFont.indexOf(pItem.pinyin) > -1 ? 'noFont' : '',
  352. ]"
  353. >{{ pItem.pinyin }}</span
  354. >
  355. </template>
  356. </span>
  357. <span class="NNPE-words-box" @click="showWordDetail($event, item.sentArr[pIndex + 1])">
  358. <template v-if="curQue.property.pinyin_position == 'top'">
  359. <span
  360. v-if="config.isShowPY"
  361. :class="[
  362. 'NNPE-pinyin',
  363. sentIndex == index ? 'wordBlank' : '',
  364. noFont.indexOf(item.sentArr[pIndex + 1].pinyin) > -1 ? 'noFont' : '',
  365. ]"
  366. style="text-align: left"
  367. >{{ item.sentArr[pIndex + 1].pinyin }}</span
  368. >
  369. </template>
  370. <span class="NNPE-chs" style="text-align: left">
  371. <span
  372. :class="[]"
  373. :style="{
  374. fontFamily: item.sentArr[pIndex + 1].config.fontFamily,
  375. height: '28px',
  376. display: 'inline-block',
  377. }"
  378. >
  379. {{
  380. NumberList.indexOf(item.sentArr[pIndex + 1].pinyin) == -1
  381. ? item.sentArr[pIndex + 1].chs
  382. : ''
  383. }}</span
  384. >
  385. </span>
  386. <template v-if="curQue.property.pinyin_position == 'bottom'">
  387. <span
  388. v-if="config.isShowPY"
  389. :class="[
  390. 'NNPE-pinyin',
  391. sentIndex == index ? 'wordBlank' : '',
  392. noFont.indexOf(item.sentArr[pIndex + 1].pinyin) > -1 ? 'noFont' : '',
  393. ]"
  394. style="text-align: left"
  395. >{{ item.sentArr[pIndex + 1].pinyin }}</span
  396. >
  397. </template>
  398. </span>
  399. <span
  400. class="NNPE-words-box"
  401. v-if="
  402. item.sentArr[pIndex + 2] &&
  403. item.sentArr[pIndex + 2].chs &&
  404. chsFhList.indexOf(item.sentArr[pIndex + 2].chs) > -1
  405. "
  406. @click="showWordDetail($event, item.sentArr[pIndex + 2])"
  407. >
  408. <template v-if="curQue.property.pinyin_position == 'top'">
  409. <span
  410. v-if="config.isShowPY"
  411. :class="[
  412. 'NNPE-pinyin',
  413. sentIndex == index ? 'wordBlank' : '',
  414. noFont.indexOf(item.sentArr[pIndex + 2].pinyin) > -1 ? 'noFont' : '',
  415. ]"
  416. style="text-align: left"
  417. >{{ item.sentArr[pIndex + 2].pinyin }}</span
  418. >
  419. </template>
  420. <span class="NNPE-chs" style="text-align: left">
  421. <span
  422. :class="[]"
  423. :style="{
  424. fontFamily: item.sentArr[pIndex + 2].config.fontFamily,
  425. height: '28px',
  426. display: 'inline-block',
  427. }"
  428. >
  429. {{
  430. NumberList.indexOf(item.sentArr[pIndex + 2].pinyin) == -1
  431. ? item.sentArr[pIndex + 2].chs
  432. : ''
  433. }}</span
  434. >
  435. </span>
  436. <template v-if="curQue.property.pinyin_position == 'bottom'">
  437. <span
  438. v-if="config.isShowPY"
  439. :class="[
  440. 'NNPE-pinyin',
  441. sentIndex == index ? 'wordBlank' : '',
  442. noFont.indexOf(item.sentArr[pIndex + 2].pinyin) > -1 ? 'noFont' : '',
  443. ]"
  444. style="text-align: left"
  445. >{{ item.sentArr[pIndex + 2].pinyin }}</span
  446. >
  447. </template>
  448. </span>
  449. </template>
  450. <template v-else>
  451. <template v-if="curQue.property.pinyin_position == 'top'">
  452. <span
  453. v-if="config.isShowPY"
  454. class="NNPE-pinyin"
  455. :class="[
  456. pItem.chs != '“' && pItem.padding ? 'padding' : '',
  457. pItem.className ? pItem.className : '',
  458. sentIndex == index ? 'wordBlank' : '',
  459. noFont.indexOf(pItem.pinyin) > -1 ? 'noFont' : '',
  460. ]"
  461. >{{ pItem.pinyin }}</span
  462. >
  463. </template>
  464. <span
  465. class="NNPE-chs"
  466. :class="[
  467. pItem.chs != '“' && pItem.padding && config.isShowPY ? 'padding' : '',
  468. sentIndex == index ? 'wordBlank' : '',
  469. ]"
  470. >
  471. <template>
  472. <span
  473. v-for="(wItem, wIndex) in pItem.leg"
  474. :key="'ci' + wIndex + pIndex + index"
  475. :class="[]"
  476. :style="{
  477. fontFamily: pItem.config.fontFamily,
  478. height: '28px',
  479. display: 'inline-block',
  480. }"
  481. >{{ NumberList.indexOf(pItem.pinyin) == -1 ? pItem.chs[wIndex] : '' }}</span
  482. >
  483. </template>
  484. </span>
  485. <template v-if="curQue.property.pinyin_position == 'bottom'">
  486. <span
  487. v-if="config.isShowPY"
  488. class="NNPE-pinyin"
  489. :class="[
  490. pItem.chs != '“' && pItem.padding ? 'padding' : '',
  491. pItem.className ? pItem.className : '',
  492. sentIndex == index ? 'wordBlank' : '',
  493. noFont.indexOf(pItem.pinyin) > -1 ? 'noFont' : '',
  494. ]"
  495. >{{ pItem.pinyin }}</span
  496. >
  497. </template>
  498. </template>
  499. </template>
  500. </template>
  501. <template v-else>
  502. <span
  503. :style="{
  504. height: pItem.height + 'px',
  505. width: pItem.width + 'px',
  506. }"
  507. ></span>
  508. </template>
  509. </div>
  510. <div style="overflow: hidden; clear: both"></div>
  511. <div
  512. v-if="
  513. item.enwords &&
  514. config.isShowEN &&
  515. (!curQue.enPosition || (curQue.enPosition && curQue.enPosition == 'bottom'))
  516. "
  517. :class="['enwords', sentIndex == index ? 'wordBlank' : '']"
  518. >
  519. {{ item.enwords }}
  520. </div>
  521. </div>
  522. </div>
  523. </div>
  524. </template>
  525. </template>
  526. <template v-if="isShow">
  527. <div
  528. ref="wordcard"
  529. class="NNPE-wordDetail"
  530. :style="{
  531. marginLeft:
  532. word.detail.new_word.length === 1
  533. ? '-152px'
  534. : windowWidth > word.detail.new_word.length * 126 + 48
  535. ? '-' + (word.detail.new_word.length * 63 + 24) + 'px'
  536. : '0px',
  537. left: windowWidth > word.detail.new_word.length * 126 + 48 ? '' : '0px',
  538. }"
  539. >
  540. <Wordcard
  541. :word="word"
  542. :changeWordCard="changeWordCard"
  543. :themeColor="themeColor"
  544. :currentTreeID="currentTreeID"
  545. :TaskModel="TaskModel"
  546. :writeList="curQue.Bookanswer.writeModel"
  547. @changeCurQue="changeCurQue"
  548. />
  549. </div>
  550. </template>
  551. </div>
  552. </template>
  553. <script>
  554. import AudioLine from '../voice_matrix/components/AudioLine.vue';
  555. import Wordcard from './components/Wordcard.vue'; // 卡片
  556. import $ from 'jquery';
  557. export default {
  558. name: 'WordModelChs',
  559. props: [
  560. 'curQue',
  561. 'bodyLeft',
  562. 'NNPENewWordList',
  563. 'themeColor',
  564. 'currentTreeID',
  565. 'config',
  566. 'TaskModel',
  567. 'colLength',
  568. 'noFont',
  569. ],
  570. components: {
  571. AudioLine,
  572. Wordcard,
  573. },
  574. data() {
  575. return {
  576. resArr: [],
  577. resObj: null,
  578. curTime: 0, //单位s
  579. chsFhList: [',', '。', '”', ':', '》', '?', '!', ';', '、', '……'],
  580. enFhList: [',', '.', ';', '?', '!', ':', '>', '<'],
  581. NumberList: ['①', '②', '③', '④', '⑤', '⑥', '⑦', '⑧', '⑨', '⑩', '⑪', '⑫', '⑬', '⑭', '⑮', '⑯', '⑰', '⑱', '⑲', '⑳'],
  582. newWords: ['鱼', '辩礼义'],
  583. isShow: false,
  584. hz: '',
  585. oldHz: '',
  586. pinyin: '',
  587. word: null,
  588. clientY: 0,
  589. top: 0,
  590. left: 0,
  591. contentWidth: 732,
  592. articleImg: {}, // 文章图片
  593. paraIndex: -1,
  594. sentIndex: -1,
  595. wordIndex: -1,
  596. screenHeight: 0,
  597. cardHeight: 0,
  598. windowWidth: window.innerWidth,
  599. };
  600. },
  601. computed: {},
  602. watch: {
  603. hz: {
  604. handler: function (val, oldVal) {
  605. let _this = this;
  606. if (val) {
  607. if (_this.NumberList.indexOf(val) > -1) {
  608. return;
  609. }
  610. _this.handleNewWords(val, _this.top, _this.left);
  611. }
  612. },
  613. // 深度观察监听
  614. deep: true,
  615. },
  616. isShow: {
  617. handler: function (val, oldVal) {
  618. let _this = this;
  619. if (val) {
  620. setTimeout(() => {
  621. _this.cardHeight = _this.$refs.wordcard.offsetHeight;
  622. // if (_this.screenHeight - _this.clientY > _this.cardHeight) {
  623. // _this.top = _this.clientY + 20;
  624. // } else {
  625. // _this.top = _this.clientY - _this.cardHeight - 30;
  626. // }
  627. }, 0);
  628. }
  629. },
  630. // 深度观察监听
  631. deep: true,
  632. },
  633. },
  634. //方法集合
  635. methods: {
  636. //拼音的显示和隐藏
  637. changePinyin() {
  638. if (this.config.isHasPY) {
  639. this.$emit('changeConfig', 'isShowPY');
  640. }
  641. },
  642. // 英文的显示和隐藏
  643. changeEN() {
  644. if (this.config.isHasEN) {
  645. this.$emit('changeConfig', 'isShowEN');
  646. }
  647. },
  648. getCurTime(curTime) {
  649. this.curTime = curTime * 1000;
  650. this.getSentIndex(this.curTime);
  651. },
  652. getSentIndex(curTime) {
  653. for (let i = 0; i < this.curQue.wordTime.length; i++) {
  654. let bg = this.curQue.wordTime[i].bg;
  655. let ed = this.curQue.wordTime[i].ed;
  656. if (curTime >= bg && curTime <= ed) {
  657. this.sentIndex = i;
  658. break;
  659. }
  660. }
  661. },
  662. handleData() {
  663. let resArr = [];
  664. let leg = this.curQue.detail.length;
  665. let curQue = JSON.parse(JSON.stringify(this.curQue));
  666. let dhaspinyin = false; // 每段是否有拼音
  667. curQue.detail.forEach((dItem, dIndex) => {
  668. dhaspinyin = false;
  669. let paraArr = [];
  670. if (!dItem.isTitle) {
  671. paraArr = [
  672. {
  673. pinyin: '',
  674. chs: '',
  675. width: 20,
  676. height: 20,
  677. },
  678. {
  679. width: 20,
  680. height: 20,
  681. pinyin: '',
  682. chs: '',
  683. },
  684. ];
  685. }
  686. dItem.wordsList.forEach((sItem, sIndex) => {
  687. sItem.forEach((wItem, wIndex) => {
  688. //this.judgePad(sItem, wItem, wIndex);
  689. this.mergeWordSymbol(sItem, wItem, wIndex);
  690. let obj = {
  691. paraIndex: dIndex, //段落索引
  692. sentIndex: sIndex, //在段落中句子索引
  693. wordIndex: wIndex, //单词的索引
  694. pinyin:
  695. curQue.pinyin_type === 'pinyin'
  696. ? curQue.property.is_enable_sentence_case && wIndex === 0
  697. ? wItem.pinyin_up
  698. : wItem.pinyin
  699. : wItem.pinyin_tone,
  700. chs: wItem.chs,
  701. padding: true,
  702. className: wItem.className,
  703. isShow: wItem.isShow,
  704. isNewWord: this.newWords.indexOf(wItem.chs) > -1 ? true : false,
  705. config: {
  706. fontFamily: wItem.fontFamily,
  707. },
  708. };
  709. paraArr.push(obj);
  710. if (wItem.pinyin) dhaspinyin = true;
  711. });
  712. });
  713. let curSentencesLeg = dItem.sentences.length;
  714. let startLeg = dIndex == 0 ? 0 : curQue.detail[dIndex - 1].endLeg;
  715. let endLeg = startLeg + curSentencesLeg;
  716. dItem.endLeg = endLeg;
  717. let timeList = curQue.wordTime.slice(startLeg, endLeg);
  718. let paraObj = {
  719. wordsList: paraArr,
  720. timeList: timeList,
  721. dhaspinyin: dhaspinyin,
  722. isTitle: dItem.isTitle,
  723. };
  724. resArr.push(paraObj);
  725. });
  726. this.resArr = resArr;
  727. // 循环文章图片
  728. if (curQue.img_list) {
  729. curQue.img_list.forEach((item) => {
  730. this.articleImg[item.imgNumber] = item.id;
  731. });
  732. }
  733. let resArrs = [],
  734. sentArrTotal = [],
  735. timeArr = [];
  736. let wordTimeList = curQue.wordTime;
  737. curQue.detail.forEach((dItem, dIndex) => {
  738. dItem.wordsList.forEach((sItem, sIndex) => {
  739. let sentArr = [];
  740. sItem.forEach((wItem, wIndex) => {
  741. let startIndex = wIndex == 0 ? 0 : sentArr[wIndex - 1].startIndex + sentArr[wIndex - 1].chs.length;
  742. let endIndex = wIndex == 0 ? wItem.chs.length : sentArr[wIndex - 1].endIndex + wItem.chs.length;
  743. // this.judgePad(sItem, wItem, wIndex);
  744. this.mergeWordSymbol(wItem);
  745. let obj = {
  746. paraIndex: dIndex, //段落索引
  747. sentIndex: sIndex, //在段落中句子索引
  748. wordIndex: wIndex, //单词的索引
  749. pinyin:
  750. curQue.pinyin_type === 'pinyin'
  751. ? curQue.property.is_enable_sentence_case && wIndex === 0
  752. ? wItem.pinyin_up
  753. : wItem.pinyin
  754. : wItem.pinyin_tone,
  755. chs: wItem.chs,
  756. padding: true,
  757. className: wItem.className,
  758. isShow: wItem.isShow,
  759. startIndex: startIndex,
  760. endIndex: endIndex,
  761. leg: wItem.chs.length,
  762. timeList: [],
  763. };
  764. sentArr.push(obj);
  765. });
  766. let objs = {
  767. sentArr: sentArr,
  768. enwords: dItem.sentencesEn && dItem.sentencesEn[sIndex] && dItem.sentencesEn[sIndex].replace(/\'/g, '’'),
  769. };
  770. sentArrTotal.push(sentArr);
  771. resArrs.push(objs);
  772. });
  773. timeArr.push(dItem.timeList);
  774. });
  775. if (wordTimeList && wordTimeList.length > 0) {
  776. this.mergeWordTime(sentArrTotal, wordTimeList);
  777. }
  778. let timeList = [];
  779. timeArr.forEach((item) => {
  780. item.forEach((aItem) => {
  781. if (timeList.indexOf(aItem) < 0) {
  782. timeList.push(aItem);
  783. }
  784. });
  785. });
  786. this.resObj = { sentList: resArrs, timeList: timeList };
  787. },
  788. mergeWordTime(resArr, wordTimeList) {
  789. resArr.forEach((item, index) => {
  790. let wordsResultList = wordTimeList[index].wordsResultList;
  791. item.forEach((wItem) => {
  792. let startIndex = wItem.startIndex;
  793. let endIndex = wItem.endIndex;
  794. wItem.timeList = wordsResultList.slice(startIndex, endIndex);
  795. });
  796. });
  797. },
  798. //词和标点合一起
  799. mergeWordSymbol(sItem, wItem, curIndex) {
  800. let leg = sItem.length;
  801. if (wItem && wItem.chs) {
  802. if (this.chsFhList.indexOf(wItem.chs) > -1) {
  803. wItem.isShow = false;
  804. } else {
  805. wItem.isShow = true;
  806. }
  807. }
  808. },
  809. mergeWordSymbols(wItem) {
  810. if (this.chsFhList.indexOf(wItem.chs) > -1 || this.NumberList.indexOf(wItem.chs) > -1) {
  811. wItem.isShow = false;
  812. } else {
  813. wItem.isShow = true;
  814. }
  815. },
  816. //判断是否有padding
  817. judgePad(sItem, wItem, curIndex) {
  818. let leg = sItem.length;
  819. if (curIndex < leg - 1) {
  820. let nextIndex = curIndex + 1;
  821. let chs = sItem[nextIndex].chs;
  822. if (this.chsFhList.indexOf(chs) > -1 || this.chsFhList.indexOf(wItem.chs) > -1) {
  823. wItem.padding = false;
  824. } else {
  825. wItem.padding = true;
  826. }
  827. if (this.enFhList.indexOf(wItem.pinyin) > -1) {
  828. wItem.className = 'textLeft';
  829. }
  830. }
  831. },
  832. //转化时间
  833. handleTimeList(list) {
  834. let listRes = [];
  835. list.forEach((item) => {
  836. let res = timeStrToSen(item);
  837. listRes.push(res);
  838. });
  839. return listRes;
  840. },
  841. //分:秒转秒
  842. timeStrToSen(time) {
  843. if (!time) {
  844. return -1;
  845. }
  846. var pos = time.indexOf(':');
  847. var min = 0,
  848. sec = 0;
  849. if (pos > 0) {
  850. min = parseInt(time.substring(0, pos));
  851. sec = parseFloat(time.substring(pos + 1));
  852. }
  853. return min * 60 + sec;
  854. },
  855. //点击播放某个句子
  856. handleChangeTime(time) {
  857. this.curTime = time;
  858. this.$refs.audioLine.onTimeupdateTime(time / 1000);
  859. },
  860. showWordDetail(e, item) {
  861. let _this = this;
  862. if (
  863. this.chsFhList.indexOf(item.chs) > -1 ||
  864. item.chs == '“' ||
  865. item.chs == '(' ||
  866. /^[a-zA-Z0-9]/.test(item.chs)
  867. ) {
  868. return false;
  869. }
  870. if (_this.oldHz != item.chs) {
  871. this.isShow = false;
  872. setTimeout(() => {
  873. _this.hz = item.chs;
  874. _this.pinyin = item.pinyin;
  875. _this.paraIndex = item.paraIndex;
  876. _this.sentIndex = item.sentIndex;
  877. _this.wordIndex = item.wordIndex;
  878. }, 50);
  879. }
  880. _this.clientY = e.clientY;
  881. let left = e.clientX;
  882. let width = 0;
  883. if (item.chs.length == 1 || item.chs.length == 2) {
  884. width = 304;
  885. } else if (item.chs.length == 3 || item.chs.length == 4) {
  886. width = 432;
  887. } else if (item.chs.length > 3) {
  888. width = 560;
  889. }
  890. if (left - this.bodyLeft > this.contentWidth / 2) {
  891. _this.left = left - width + 30;
  892. } else {
  893. _this.left = left - 30;
  894. }
  895. },
  896. changeWordCard(isShow) {
  897. let _this = this;
  898. _this.isShow = isShow;
  899. _this.oldHz = '';
  900. _this.hz = '';
  901. _this.paraIndex = -1;
  902. _this.sentIndex = -1;
  903. _this.wordIndex = -1;
  904. },
  905. // 处理分词数据
  906. handleNewWords(val) {
  907. this.isShow = true;
  908. this.word = null;
  909. let wordlist = val.split('');
  910. let option = {
  911. definition_list: [],
  912. mp3_list: [],
  913. new_word: val,
  914. pinyin: this.pinyin,
  915. };
  916. this.word = { list: wordlist, detail: option };
  917. this.oldHz = val;
  918. },
  919. getScreenHeight() {
  920. this.screenHeight = window.innerHeight;
  921. },
  922. changeCurQue(answer) {
  923. if (answer) {
  924. let writeModel = this.curQue.Bookanswer.writeModel;
  925. let hz = answer.hz;
  926. if (writeModel.hasOwnProperty(hz)) {
  927. writeModel[hz].push(answer);
  928. } else {
  929. writeModel[hz] = [answer];
  930. }
  931. }
  932. },
  933. },
  934. //生命周期 - 创建完成(可以访问当前this实例)
  935. created() {},
  936. //生命周期 - 挂载完成(可以访问DOM元素)
  937. mounted() {
  938. if (this.curQue) {
  939. this.handleData();
  940. }
  941. $(window).resize(() => {
  942. this.getScreenHeight();
  943. });
  944. this.getScreenHeight();
  945. },
  946. beforeCreate() {}, //生命周期 - 创建之前
  947. beforeMount() {}, //生命周期 - 挂载之前
  948. beforeUpdate() {}, //生命周期 - 更新之前
  949. updated() {}, //生命周期 - 更新之后
  950. beforeDestroy() {
  951. this.isShow = false;
  952. }, //生命周期 - 销毁之前
  953. destroyed() {}, //生命周期 - 销毁完成
  954. activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发
  955. };
  956. </script>
  957. <style lang="scss" scoped>
  958. //@import url(); 引入公共css类
  959. .NNPE-ArticleView {
  960. width: 100%;
  961. .aduioLine-practice-npc {
  962. display: flex;
  963. align-items: center;
  964. justify-content: flex-start;
  965. .aduioLine-content {
  966. flex: 1;
  967. }
  968. .aduioLine-right {
  969. box-sizing: border-box;
  970. display: flex;
  971. align-items: center;
  972. justify-content: space-between;
  973. width: 69px;
  974. height: 40px;
  975. padding: 0 12px;
  976. border-left: 1px solid rgba(0, 0, 0, 10%);
  977. > span {
  978. width: 16px;
  979. height: 16px;
  980. cursor: pointer;
  981. }
  982. }
  983. }
  984. .NPC-sentences-list {
  985. padding: 24px 0;
  986. }
  987. .NNPE-detail {
  988. overflow: hidden;
  989. clear: both;
  990. color: rgba(0, 0, 0, 85%);
  991. .NNPE-words {
  992. float: left;
  993. &-box {
  994. float: left;
  995. > span {
  996. display: block;
  997. &.NNPE-pinyin {
  998. height: 22px;
  999. font-family: 'GB-PINYINOK-B';
  1000. font-size: 14px;
  1001. font-weight: normal;
  1002. line-height: 22px;
  1003. &.noFont {
  1004. font-family: initial;
  1005. }
  1006. &.textLeft {
  1007. text-align: left;
  1008. }
  1009. }
  1010. &.NNPE-chs {
  1011. font-family: '楷体';
  1012. font-size: 20px;
  1013. line-height: 28px;
  1014. &.active {
  1015. background: rgba(36, 185, 158, 15%);
  1016. }
  1017. // &.wordActive {
  1018. // color: #de4444;
  1019. // }
  1020. }
  1021. &.padding {
  1022. padding: 0 3px;
  1023. }
  1024. }
  1025. }
  1026. &.textLeft {
  1027. text-align: left;
  1028. }
  1029. &.textCenter {
  1030. text-align: center;
  1031. }
  1032. &.textRight {
  1033. text-align: right;
  1034. }
  1035. > span {
  1036. display: block;
  1037. &.NNPE-pinyin {
  1038. height: 22px;
  1039. font-family: 'GB-PINYINOK-B';
  1040. font-size: 14px;
  1041. font-weight: normal;
  1042. line-height: 22px;
  1043. &.noFont {
  1044. font-family: initial;
  1045. }
  1046. &.textLeft {
  1047. text-align: left;
  1048. }
  1049. }
  1050. &.NNPE-chs {
  1051. font-family: '楷体';
  1052. font-size: 20px;
  1053. line-height: 28px;
  1054. &.active {
  1055. background: rgba(36, 185, 158, 15%);
  1056. }
  1057. // &.wordActive {
  1058. // color: #de4444;
  1059. // }
  1060. }
  1061. &.padding {
  1062. padding: 0 3px;
  1063. }
  1064. }
  1065. }
  1066. &.NNPE-detail-title {
  1067. .wordsList-box {
  1068. > div {
  1069. display: flex;
  1070. flex-flow: wrap;
  1071. justify-content: center;
  1072. width: 100%;
  1073. }
  1074. }
  1075. }
  1076. .index {
  1077. box-sizing: border-box;
  1078. width: 48px;
  1079. padding: 8px;
  1080. text-align: right;
  1081. border-right: 1px solid rgba(0, 0, 0, 10%);
  1082. b {
  1083. font-weight: 400;
  1084. line-height: 1.5;
  1085. color: #000;
  1086. }
  1087. }
  1088. .wordsList-box {
  1089. display: flex;
  1090. width: 100%;
  1091. padding: 6px 24px 12px;
  1092. &-left {
  1093. justify-content: flex-start;
  1094. }
  1095. &-center {
  1096. justify-content: center;
  1097. }
  1098. &-right {
  1099. justify-content: flex-end;
  1100. }
  1101. > div {
  1102. overflow: hidden;
  1103. clear: both;
  1104. }
  1105. > img {
  1106. display: block;
  1107. max-width: 100%;
  1108. margin: 0 auto;
  1109. }
  1110. }
  1111. }
  1112. }
  1113. .NNPE-wordDetail {
  1114. position: fixed;
  1115. top: 50%;
  1116. left: 50%;
  1117. z-index: 116;
  1118. max-width: 100%;
  1119. margin-top: -196px;
  1120. overflow: auto;
  1121. // width: 260px;
  1122. // height: 200px;
  1123. // background: #cc0;
  1124. }
  1125. .NNPE-detail-box {
  1126. box-sizing: border-box;
  1127. width: 100%;
  1128. padding: 8px 24px;
  1129. margin-bottom: 8px;
  1130. &.active {
  1131. background: rgba(222, 68, 68, 15%);
  1132. }
  1133. }
  1134. .NNPE-details {
  1135. overflow: hidden;
  1136. clear: both;
  1137. .NNPE-words {
  1138. float: left;
  1139. &-box {
  1140. float: left;
  1141. > span {
  1142. display: block;
  1143. &.NNPE-pinyin {
  1144. height: 20px;
  1145. font-family: 'GB-PINYINOK-B';
  1146. font-size: 14px;
  1147. font-weight: normal;
  1148. line-height: 20px;
  1149. color: rgba(0, 0, 0, 85%);
  1150. &.noFont {
  1151. font-family: initial;
  1152. }
  1153. &.textLeft {
  1154. text-align: left;
  1155. }
  1156. &.wordBlank {
  1157. color: rgba(0, 0, 0, 85%);
  1158. }
  1159. }
  1160. &.NNPE-chs {
  1161. font-family: '楷体';
  1162. font-size: 20px;
  1163. line-height: 28px;
  1164. color: rgba(0, 0, 0, 85%);
  1165. .active {
  1166. color: #de4444;
  1167. }
  1168. &.wordBlank {
  1169. color: rgba(0, 0, 0, 85%);
  1170. }
  1171. }
  1172. // &.padding {
  1173. // padding-right: 6px;
  1174. // }
  1175. }
  1176. }
  1177. &.textLeft {
  1178. text-align: left;
  1179. }
  1180. &.textCenter {
  1181. text-align: center;
  1182. }
  1183. &.textRight {
  1184. text-align: right;
  1185. }
  1186. > span {
  1187. display: block;
  1188. &.NNPE-pinyin {
  1189. height: 20px;
  1190. font-family: 'GB-PINYINOK-B';
  1191. font-size: 14px;
  1192. font-weight: normal;
  1193. line-height: 20px;
  1194. color: rgba(0, 0, 0, 85%);
  1195. &.noFont {
  1196. font-family: initial;
  1197. }
  1198. &.textLeft {
  1199. text-align: left;
  1200. }
  1201. &.wordBlank {
  1202. color: rgba(0, 0, 0, 85%);
  1203. }
  1204. }
  1205. &.NNPE-chs {
  1206. font-family: '楷体';
  1207. font-size: 20px;
  1208. line-height: 28px;
  1209. color: rgba(0, 0, 0, 85%);
  1210. .active {
  1211. color: #de4444;
  1212. }
  1213. &.wordBlank {
  1214. color: rgba(0, 0, 0, 85%);
  1215. }
  1216. }
  1217. &.padding {
  1218. padding: 0 3px;
  1219. }
  1220. }
  1221. }
  1222. }
  1223. .enwords {
  1224. padding-left: 3px;
  1225. font-family: 'Helvetica';
  1226. font-size: 14px;
  1227. font-weight: normal;
  1228. line-height: 22px;
  1229. color: rgba(0, 0, 0, 85%);
  1230. word-break: break-word;
  1231. &.wordBlank {
  1232. color: rgba(0, 0, 0, 85%);
  1233. }
  1234. }
  1235. .NPC-Big-Book-preview-green {
  1236. .NNPE-ArticleView {
  1237. .NNPE-detail-box {
  1238. &.active {
  1239. background: rgba(36, 185, 158, 15%);
  1240. }
  1241. }
  1242. }
  1243. }
  1244. .NPC-Big-Book-preview-brown {
  1245. .NNPE-ArticleView {
  1246. .NNPE-detail-box {
  1247. &.active {
  1248. background: rgba(189, 136, 101, 15%);
  1249. }
  1250. }
  1251. }
  1252. }
  1253. </style>