Voicefullscreen.vue 85 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560
  1. <!-- -->
  2. <template>
  3. <div
  4. v-if="sentList"
  5. :class="['voicefull', bgIndex == 0 ? 'bg1' : 'bg2', isLandscape ? 'voicefull-scape' : '']"
  6. :style="{
  7. paddingRight: isLandscape ? '100px' : '',
  8. }"
  9. >
  10. <div class="voicefull-bottom" @mouseover="setTopShow(true)" @mouseleave="setTopShow(false)">
  11. <div :class="[isTopShow || isPhone ? 'voicefull-bottom-show' : 'voicefull-bottom-hidden']">
  12. <div :class="['bottom-left', TaskModel == 'ANSWER' ? 'bottom-left-margin' : '']"></div>
  13. <div :class="['page-count', bgIndex == 0 ? 'page-count-white' : 'page-count-green']">
  14. {{ curSentIndex + 1 }}/{{ sentList.length }}
  15. </div>
  16. </div>
  17. </div>
  18. <div v-if="item" class="voicefull-content">
  19. <div class="vc-box">
  20. <div
  21. :class="[
  22. 'vc-left vc-left-grey',
  23. isShowLeft && bgIndex == 0 ? 'vc-left-black' : '',
  24. isShowLeft && bgIndex == 1 ? 'vc-left-white' : '',
  25. curSentIndex == 0 ? 'hidden' : '',
  26. ]"
  27. @click="prevSentence"
  28. ></div>
  29. </div>
  30. <div class="vc-main">
  31. <div class="NNPE-words-box">
  32. <div style="overflow: hidden; clear: both"></div>
  33. <div
  34. v-if="enwords && config.isShowEN && curQue.enPosition && curQue.enPosition == 'top'"
  35. :class="['enwords', bgIndex == 1 ? 'enwords-green' : '']"
  36. :style="{ fontSize: enSize + 'px' }"
  37. >
  38. {{ convertText(enwords) }}
  39. </div>
  40. <div
  41. v-for="(pItem, pIndex) in item"
  42. :key="'wordsList' + pIndex"
  43. class="NNPE-words"
  44. :class="[
  45. pItem.chs != '“' && pItem.wordIndex == 0 ? 'textLeft' : 'textCenter',
  46. pItem.chs == '“' ? 'textRight' : '',
  47. ]"
  48. @dblclick="showWordDetail($event, pItem)"
  49. @click="playWord(pItem)"
  50. >
  51. <template>
  52. <template v-if="!pItem.width">
  53. <template v-if="pItem.isShow">
  54. <span
  55. v-if="
  56. item[pIndex - 1] &&
  57. item[pIndex - 1].chs &&
  58. firstFhlist.indexOf(item[pIndex - 1].chs) > -1 &&
  59. item[pIndex - 2] &&
  60. item[pIndex - 2].chs &&
  61. firstFhlist.indexOf(item[pIndex - 2].chs) > -1
  62. "
  63. class="NNPE-words-box"
  64. >
  65. <template v-if="curQue.property.pinyin_position == 'top'">
  66. <span
  67. v-if="config.isShowPY"
  68. :class="[
  69. 'NNPE-pinyin',
  70. noFont.indexOf(item[pIndex - 2].pinyin) > -1 ? 'noFont' : '',
  71. bgIndex == 1 ? 'font-white' : '',
  72. ]"
  73. :style="{
  74. fontSize: pySize + 'px',
  75. textAlign: left,
  76. height: pySize * 1.25 + 'px',
  77. }"
  78. >{{ NumberList.indexOf(item[pIndex - 2].pinyin) == -1 ? item[pIndex - 2].pinyin : '' }}</span
  79. >
  80. </template>
  81. <span
  82. :class="['NNPE-chs', curQue.property.pinyin_position == 'top' ? 'bottom' : '']"
  83. :style="{
  84. fontSize: hzSize + 'px',
  85. textAlign: left,
  86. height: hzSize * 1.17 + 'px',
  87. }"
  88. >
  89. <span
  90. :class="[
  91. pItem.timeList[0] &&
  92. curTime >= pItem.timeList[0].wordBg &&
  93. curQue.wordTime &&
  94. curQue.wordTime[curSentIndex] &&
  95. curTime <= curQue.wordTime[curSentIndex].ed
  96. ? bgIndex == 0
  97. ? 'active'
  98. : 'active-yellow'
  99. : '',
  100. bgIndex == 1 ? 'font-white' : '',
  101. newWordList.indexOf(item[pIndex - 2].chs) > -1 && !isPlaying ? 'newActive' : '',
  102. item[pIndex - 2].words && !isPlaying ? 'newActive' : '',
  103. ]"
  104. :style="{
  105. fontSize: hzSize + 'px',
  106. fontFamily:
  107. item[pIndex - 2].config && item[pIndex - 2].config.fontFamily
  108. ? item[pIndex - 2].config.fontFamily
  109. : '',
  110. textDecoration:
  111. item[pIndex - 2].config && item[pIndex - 2].config.textDecoration
  112. ? item[pIndex - 2].config.textDecoration
  113. : '',
  114. borderBottom:
  115. item[pIndex - 2].config && item[pIndex - 2].config.border === 'dotted' ? '1px dotted' : '',
  116. fontWeight:
  117. item[pIndex - 2].config && item[pIndex - 2].config.fontWeight
  118. ? item[pIndex - 2].config.fontWeight
  119. : '',
  120. color:
  121. item[pIndex - 2].config && item[pIndex - 2].config.color
  122. ? item[pIndex - 2].config.color
  123. : '',
  124. height: hzSize * 1.17 + 'px',
  125. display: 'inline-block',
  126. width: item[pIndex - 2].chs.trim() === '' ? '10px' : '',
  127. }"
  128. >{{ convertText(item[pIndex - 2].chs) }}</span
  129. >
  130. <img
  131. v-if="
  132. item[pIndex - 2].img &&
  133. item[pIndex - 2].img.length > 0 &&
  134. item[pIndex - 2].imgPosition === 'after'
  135. "
  136. :src="item[pIndex - 2].img[0].file_url"
  137. :style="{
  138. width: hzSize + 'px',
  139. height: hzSize + 'px',
  140. }"
  141. />
  142. </span>
  143. <template v-if="curQue.property.pinyin_position == 'bottom'">
  144. <span
  145. v-if="config.isShowPY"
  146. :class="[
  147. 'NNPE-pinyin',
  148. noFont.indexOf(item[pIndex - 2].pinyin) > -1 ? 'noFont' : '',
  149. bgIndex == 1 ? 'font-white' : '',
  150. 'bottom',
  151. ]"
  152. :style="{
  153. fontSize: pySize + 'px',
  154. textAlign: left,
  155. height: pySize * 1.25 + 'px',
  156. }"
  157. >{{ NumberList.indexOf(item[pIndex - 2].pinyin) == -1 ? item[pIndex - 2].pinyin : '' }}</span
  158. >
  159. </template>
  160. </span>
  161. <span
  162. v-if="item[pIndex - 1] && item[pIndex - 1].chs && firstFhlist.indexOf(item[pIndex - 1].chs) > -1"
  163. class="NNPE-words-box"
  164. >
  165. <template v-if="curQue.property.pinyin_position == 'top'">
  166. <span
  167. v-if="config.isShowPY"
  168. :class="[
  169. 'NNPE-pinyin',
  170. noFont.indexOf(item[pIndex - 1].pinyin) > -1 ? 'noFont' : '',
  171. bgIndex == 1 ? 'font-white' : '',
  172. ]"
  173. :style="{
  174. fontSize: pySize + 'px',
  175. textAlign: left,
  176. height: pySize * 1.25 + 'px',
  177. }"
  178. >{{ NumberList.indexOf(item[pIndex - 1].pinyin) == -1 ? item[pIndex - 1].pinyin : '' }}</span
  179. >
  180. </template>
  181. <span
  182. :class="['NNPE-chs', curQue.property.pinyin_position == 'top' ? 'bottom' : '']"
  183. :style="{
  184. fontSize: hzSize + 'px',
  185. textAlign: left,
  186. height: hzSize * 1.17 + 'px',
  187. }"
  188. >
  189. <span
  190. :class="[
  191. pItem.timeList[0] &&
  192. curTime >= pItem.timeList[0].wordBg &&
  193. curQue.wordTime &&
  194. curQue.wordTime[curSentIndex] &&
  195. curTime <= curQue.wordTime[curSentIndex].ed
  196. ? bgIndex == 0
  197. ? 'active'
  198. : 'active-yellow'
  199. : '',
  200. bgIndex == 1 ? 'font-white' : '',
  201. newWordList.indexOf(item[pIndex - 1].chs) > -1 && !isPlaying ? 'newActive' : '',
  202. item[pIndex - 1].words && !isPlaying ? 'newActive' : '',
  203. ]"
  204. :style="{
  205. fontSize: hzSize + 'px',
  206. fontFamily:
  207. item[pIndex - 1].config && item[pIndex - 1].config.fontFamily
  208. ? item[pIndex - 1].config.fontFamily
  209. : '',
  210. textDecoration:
  211. item[pIndex - 1].config && item[pIndex - 1].config.textDecoration
  212. ? item[pIndex + 1].config.textDecoration
  213. : '',
  214. borderBottom:
  215. item[pIndex - 1].config && item[pIndex - 1].config.border === 'dotted' ? '1px dotted' : '',
  216. fontWeight:
  217. item[pIndex - 1].config && item[pIndex - 1].config.fontWeight
  218. ? item[pIndex - 1].config.fontWeight
  219. : '',
  220. color:
  221. item[pIndex - 1].config && item[pIndex - 1].config.color
  222. ? item[pIndex - 1].config.color
  223. : '',
  224. height: hzSize * 1.17 + 'px',
  225. display: 'inline-block',
  226. width: item[pIndex - 1].chs.trim() === '' ? '10px' : '',
  227. }"
  228. >{{ convertText(item[pIndex - 1].chs) }}</span
  229. >
  230. <img
  231. v-if="
  232. item[pIndex - 1].img &&
  233. item[pIndex - 1].img.length > 0 &&
  234. item[pIndex - 1].imgPosition === 'after'
  235. "
  236. :src="item[pIndex - 1].img[0].file_url"
  237. :style="{
  238. width: hzSize + 'px',
  239. height: hzSize + 'px',
  240. }"
  241. />
  242. </span>
  243. <template v-if="curQue.property.pinyin_position == 'bottom'">
  244. <span
  245. v-if="config.isShowPY"
  246. :class="[
  247. 'NNPE-pinyin',
  248. noFont.indexOf(item[pIndex - 1].pinyin) > -1 ? 'noFont' : '',
  249. bgIndex == 1 ? 'font-white' : '',
  250. 'bottom',
  251. ]"
  252. :style="{
  253. fontSize: pySize + 'px',
  254. textAlign: left,
  255. height: pySize * 1.25 + 'px',
  256. }"
  257. >{{ NumberList.indexOf(item[pIndex - 1].pinyin) == -1 ? item[pIndex - 1].pinyin : '' }}</span
  258. >
  259. </template>
  260. </span>
  261. <template
  262. v-if="item[pIndex + 1] && item[pIndex + 1].chs && chsFhList.indexOf(item[pIndex + 1].chs) > -1"
  263. >
  264. <span class="NNPE-words-box">
  265. <template v-if="curQue.property.pinyin_position == 'top'">
  266. <span
  267. v-if="config.isShowPY"
  268. class="NNPE-pinyin"
  269. :class="[
  270. pItem.className ? pItem.className : '',
  271. noFont.indexOf(pItem.pinyin) > -1 ? 'noFont' : '',
  272. bgIndex == 1 ? 'font-white' : '',
  273. ]"
  274. :style="{
  275. fontSize: pySize + 'px',
  276. height: pySize * 1.25 + 'px',
  277. }"
  278. >{{ NumberList.indexOf(pItem.pinyin) == -1 ? pItem.pinyin : '' }}</span
  279. >
  280. </template>
  281. <span
  282. class="NNPE-chs"
  283. :class="[
  284. pItem.padding && config.isShowPY ? 'padding' : '',
  285. curQue.property.pinyin_position == 'top' ? 'bottom' : '',
  286. ]"
  287. :style="{
  288. height: hzSize * 1.17 + 'px',
  289. }"
  290. >
  291. <template>
  292. <span
  293. v-for="(wItem, wIndex) in pItem.leg"
  294. :key="'ci' + wIndex + pIndex"
  295. :class="[
  296. pItem.timeList &&
  297. pItem.timeList[wIndex] &&
  298. curTime >= pItem.timeList[wIndex].wordBg &&
  299. curQue.wordTime &&
  300. curQue.wordTime[curSentIndex] &&
  301. curTime <= curQue.wordTime[curSentIndex].ed
  302. ? bgIndex == 0
  303. ? 'active'
  304. : 'active-yellow'
  305. : '',
  306. bgIndex == 1 ? 'font-white' : '',
  307. bgIndex == 0 && wordIndex == pItem.wordIndex ? 'wordActive' : '',
  308. bgIndex == 1 && wordIndex == pItem.wordIndex ? 'wordActive-blue' : '',
  309. newWordList.indexOf(pItem.chs) > -1 && !isPlaying ? 'newActive' : '',
  310. pItem.words && !isPlaying ? 'newActive' : '',
  311. ]"
  312. :style="{
  313. fontSize: hzSize + 'px',
  314. fontFamily: pItem.config && pItem.config.fontFamily ? pItem.config.fontFamily : '',
  315. textDecoration:
  316. pItem.config && pItem.config.textDecoration ? pItem.config.textDecoration : '',
  317. borderBottom: pItem.config && pItem.config.border === 'dotted' ? '1px dotted' : '',
  318. fontWeight: pItem.config && pItem.config.fontWeight ? pItem.config.fontWeight : '',
  319. color: pItem.config && pItem.config.color ? pItem.config.color : '',
  320. height: hzSize * 1.17 + 'px',
  321. display: 'inline-block',
  322. width: pItem.chs[wIndex].trim() === '' ? '10px' : '',
  323. }"
  324. >{{ convertText(pItem.chs[wIndex]) }}</span
  325. >
  326. </template>
  327. <img
  328. v-if="pItem.img && pItem.img.length > 0 && pItem.imgPosition === 'after'"
  329. :src="pItem.img[0].file_url"
  330. :style="{
  331. width: hzSize + 'px',
  332. height: hzSize + 'px',
  333. }"
  334. />
  335. </span>
  336. <template v-if="curQue.property.pinyin_position == 'bottom'">
  337. <span
  338. v-if="config.isShowPY"
  339. class="NNPE-pinyin bottom"
  340. :class="[
  341. pItem.className ? pItem.className : '',
  342. noFont.indexOf(pItem.pinyin) > -1 ? 'noFont' : '',
  343. bgIndex == 1 ? 'font-white' : '',
  344. ]"
  345. :style="{
  346. fontSize: pySize + 'px',
  347. height: pySize * 1.25 + 'px',
  348. }"
  349. >{{ NumberList.indexOf(pItem.pinyin) == -1 ? pItem.pinyin : '' }}</span
  350. >
  351. </template>
  352. </span>
  353. <span class="NNPE-words-box">
  354. <template v-if="curQue.property.pinyin_position == 'top'">
  355. <span
  356. v-if="config.isShowPY"
  357. :class="[
  358. 'NNPE-pinyin',
  359. noFont.indexOf(item[pIndex + 1].pinyin) > -1 ? 'noFont' : '',
  360. bgIndex == 1 ? 'font-white' : '',
  361. ]"
  362. :style="{
  363. fontSize: pySize + 'px',
  364. textAlign: left,
  365. height: pySize * 1.25 + 'px',
  366. }"
  367. >{{ NumberList.indexOf(item[pIndex + 1].pinyin) == -1 ? item[pIndex + 1].pinyin : '' }}</span
  368. >
  369. </template>
  370. <span
  371. :class="['NNPE-chs', curQue.property.pinyin_position == 'top' ? 'bottom' : '']"
  372. :style="{
  373. fontSize: hzSize + 'px',
  374. textAlign: left,
  375. height: hzSize * 1.17 + 'px',
  376. }"
  377. >
  378. <span
  379. :class="[
  380. pItem.timeList[pItem.leg - 1] &&
  381. curTime >= pItem.timeList[pItem.leg - 1].wordBg &&
  382. curQue.wordTime &&
  383. curQue.wordTime[curSentIndex] &&
  384. curTime <= curQue.wordTime[curSentIndex].ed
  385. ? bgIndex == 0
  386. ? 'active'
  387. : 'active-yellow'
  388. : '',
  389. bgIndex == 1 ? 'font-white' : '',
  390. newWordList.indexOf(item[pIndex + 1].chs) > -1 && !isPlaying ? 'newActive' : '',
  391. item[pIndex + 1].words && !isPlaying ? 'newActive' : '',
  392. ]"
  393. :style="{
  394. fontSize: hzSize + 'px',
  395. fontFamily:
  396. item[pIndex + 1].config && item[pIndex + 1].config.fontFamily
  397. ? item[pIndex + 1].config.fontFamily
  398. : '',
  399. textDecoration:
  400. item[pIndex + 1].config && item[pIndex + 1].config.textDecoration
  401. ? item[pIndex + 1].config.textDecoration
  402. : '',
  403. borderBottom:
  404. item[pIndex + 1].config && item[pIndex + 1].config.border === 'dotted'
  405. ? '1px dotted'
  406. : '',
  407. fontWeight:
  408. item[pIndex + 1].config && item[pIndex + 1].config.fontWeight
  409. ? item[pIndex + 1].config.fontWeight
  410. : '',
  411. color:
  412. item[pIndex + 1].config && item[pIndex + 1].config.color
  413. ? item[pIndex + 1].config.color
  414. : '',
  415. height: hzSize * 1.17 + 'px',
  416. display: 'inline-block',
  417. width: item[pIndex + 1].chs.trim() === '' ? '10px' : '',
  418. }"
  419. >{{ convertText(item[pIndex + 1].chs) }}</span
  420. >
  421. <img
  422. v-if="
  423. item[pIndex + 1].img &&
  424. item[pIndex + 1].img.length > 0 &&
  425. item[pIndex + 1].imgPosition === 'after'
  426. "
  427. :src="item[pIndex + 1].img[0].file_url"
  428. :style="{
  429. width: hzSize + 'px',
  430. height: hzSize + 'px',
  431. }"
  432. />
  433. </span>
  434. <template v-if="curQue.property.pinyin_position == 'bottom'">
  435. <span
  436. v-if="config.isShowPY"
  437. :class="[
  438. 'NNPE-pinyin',
  439. noFont.indexOf(item[pIndex + 1].pinyin) > -1 ? 'noFont' : '',
  440. bgIndex == 1 ? 'font-white' : '',
  441. 'bottom',
  442. ]"
  443. :style="{
  444. fontSize: pySize + 'px',
  445. textAlign: left,
  446. height: pySize * 1.25 + 'px',
  447. }"
  448. >{{ NumberList.indexOf(item[pIndex + 1].pinyin) == -1 ? item[pIndex + 1].pinyin : '' }}</span
  449. >
  450. </template>
  451. </span>
  452. <span
  453. v-if="item[pIndex + 2] && item[pIndex + 2].chs && chsFhList.indexOf(item[pIndex + 2].chs) > -1"
  454. class="NNPE-words-box"
  455. >
  456. <template v-if="curQue.property.pinyin_position == 'top'">
  457. <span
  458. v-if="config.isShowPY"
  459. :class="[
  460. 'NNPE-pinyin',
  461. noFont.indexOf(item[pIndex + 2].pinyin) > -1 ? 'noFont' : '',
  462. bgIndex == 1 ? 'font-white' : '',
  463. ]"
  464. :style="{
  465. fontSize: pySize + 'px',
  466. textAlign: left,
  467. height: pySize * 1.25 + 'px',
  468. }"
  469. >{{ NumberList.indexOf(item[pIndex + 2].pinyin) == -1 ? item[pIndex + 2].pinyin : '' }}</span
  470. >
  471. </template>
  472. <span
  473. :class="['NNPE-chs', curQue.property.pinyin_position == 'top' ? 'bottom' : '']"
  474. :style="{
  475. fontSize: hzSize + 'px',
  476. textAlign: left,
  477. height: hzSize * 1.17 + 'px',
  478. }"
  479. >
  480. <span
  481. :class="[
  482. pItem.timeList[pItem.leg - 1] &&
  483. curTime >= pItem.timeList[pItem.leg - 1].wordBg &&
  484. curQue.wordTime &&
  485. curQue.wordTime[curSentIndex] &&
  486. curTime <= curQue.wordTime[curSentIndex].ed
  487. ? bgIndex == 0
  488. ? 'active'
  489. : 'active-yellow'
  490. : '',
  491. bgIndex == 1 ? 'font-white' : '',
  492. newWordList.indexOf(item[pIndex + 2].chs) > -1 && !isPlaying ? 'newActive' : '',
  493. item[pIndex + 2].words && !isPlaying ? 'newActive' : '',
  494. ]"
  495. :style="{
  496. fontSize: hzSize + 'px',
  497. fontFamily:
  498. item[pIndex + 2].config && item[pIndex + 2].config.fontFamily
  499. ? item[pIndex + 2].config.fontFamily
  500. : '',
  501. textDecoration:
  502. item[pIndex + 2].config && item[pIndex + 2].config.textDecoration
  503. ? item[pIndex + 2].config.textDecoration
  504. : '',
  505. borderBottom:
  506. item[pIndex + 2].config && item[pIndex + 2].config.border === 'dotted'
  507. ? '1px dotted'
  508. : '',
  509. fontWeight:
  510. item[pIndex + 2].config && item[pIndex + 2].config.fontWeight
  511. ? item[pIndex + 2].config.fontWeight
  512. : '',
  513. color:
  514. item[pIndex + 2].config && item[pIndex + 2].config.color
  515. ? item[pIndex + 2].config.color
  516. : '',
  517. height: hzSize * 1.17 + 'px',
  518. display: 'inline-block',
  519. width: item[pIndex + 2].chs.trim() === '' ? '10px' : '',
  520. }"
  521. >{{ convertText(item[pIndex + 2].chs) }}</span
  522. >
  523. <img
  524. v-if="
  525. item[pIndex + 2].img &&
  526. item[pIndex + 2].img.length > 0 &&
  527. item[pIndex + 2].imgPosition === 'after'
  528. "
  529. :src="item[pIndex + 2].img[0].file_url"
  530. :style="{
  531. width: hzSize + 'px',
  532. height: hzSize + 'px',
  533. }"
  534. />
  535. </span>
  536. <template v-if="curQue.property.pinyin_position == 'bottom'">
  537. <span
  538. v-if="config.isShowPY"
  539. :class="[
  540. 'NNPE-pinyin',
  541. noFont.indexOf(item[pIndex + 2].pinyin) > -1 ? 'noFont' : '',
  542. bgIndex == 1 ? 'font-white' : '',
  543. 'bottom',
  544. ]"
  545. :style="{
  546. fontSize: pySize + 'px',
  547. textAlign: left,
  548. height: pySize * 1.25 + 'px',
  549. }"
  550. >{{ NumberList.indexOf(item[pIndex + 2].pinyin) == -1 ? item[pIndex + 2].pinyin : '' }}</span
  551. >
  552. </template>
  553. </span>
  554. <span
  555. v-if="
  556. item[pIndex + 2] &&
  557. item[pIndex + 2].chs &&
  558. chsFhList.indexOf(item[pIndex + 2].chs) > -1 &&
  559. item[pIndex + 3] &&
  560. item[pIndex + 3].chs &&
  561. chsFhList.indexOf(item[pIndex + 3].chs) > -1
  562. "
  563. class="NNPE-words-box"
  564. >
  565. <template v-if="curQue.property.pinyin_position == 'top'">
  566. <span
  567. v-if="config.isShowPY"
  568. :class="[
  569. 'NNPE-pinyin',
  570. noFont.indexOf(item[pIndex + 3].pinyin) > -1 ? 'noFont' : '',
  571. bgIndex == 1 ? 'font-white' : '',
  572. ]"
  573. :style="{
  574. fontSize: pySize + 'px',
  575. textAlign: left,
  576. height: pySize * 1.25 + 'px',
  577. }"
  578. >{{ NumberList.indexOf(item[pIndex + 3].pinyin) == -1 ? item[pIndex + 3].pinyin : '' }}</span
  579. >
  580. </template>
  581. <span
  582. :class="['NNPE-chs', curQue.property.pinyin_position == 'top' ? 'bottom' : '']"
  583. :style="{
  584. fontSize: hzSize + 'px',
  585. textAlign: left,
  586. height: hzSize * 1.17 + 'px',
  587. }"
  588. >
  589. <span
  590. :class="[
  591. pItem.timeList[pItem.leg - 1] &&
  592. curTime >= pItem.timeList[pItem.leg - 1].wordBg &&
  593. curQue.wordTime &&
  594. curQue.wordTime[curSentIndex] &&
  595. curTime <= curQue.wordTime[curSentIndex].ed
  596. ? bgIndex == 0
  597. ? 'active'
  598. : 'active-yellow'
  599. : '',
  600. bgIndex == 1 ? 'font-white' : '',
  601. newWordList.indexOf(item[pIndex + 3].chs) > -1 && !isPlaying ? 'newActive' : '',
  602. item[pIndex + 3].words && !isPlaying ? 'newActive' : '',
  603. ]"
  604. :style="{
  605. fontSize: hzSize + 'px',
  606. fontFamily:
  607. item[pIndex + 3].config && item[pIndex + 3].config.fontFamily
  608. ? item[pIndex + 3].config.fontFamily
  609. : '',
  610. textDecoration:
  611. item[pIndex + 3].config && item[pIndex + 3].config.textDecoration
  612. ? item[pIndex + 3].config.textDecoration
  613. : '',
  614. borderBottom:
  615. item[pIndex + 3].config && item[pIndex + 3].config.border === 'dotted'
  616. ? '1px dotted'
  617. : '',
  618. fontWeight:
  619. item[pIndex + 3].config && item[pIndex + 3].config.fontWeight
  620. ? item[pIndex + 3].config.fontWeight
  621. : '',
  622. color:
  623. item[pIndex + 3].config && item[pIndex + 3].config.color
  624. ? item[pIndex + 3].config.color
  625. : '',
  626. height: hzSize * 1.17 + 'px',
  627. display: 'inline-block',
  628. width: item[pIndex + 3].chs.trim() === '' ? '10px' : '',
  629. }"
  630. >{{ convertText(item[pIndex + 3].chs) }}</span
  631. >
  632. <img
  633. v-if="
  634. item[pIndex + 3].img &&
  635. item[pIndex + 3].img.length > 0 &&
  636. item[pIndex + 3].imgPosition === 'after'
  637. "
  638. :src="item[pIndex + 3].img[0].file_url"
  639. :style="{
  640. width: hzSize + 'px',
  641. height: hzSize + 'px',
  642. }"
  643. />
  644. </span>
  645. <template v-if="curQue.property.pinyin_position == 'bottom'">
  646. <span
  647. v-if="config.isShowPY"
  648. :class="[
  649. 'NNPE-pinyin',
  650. noFont.indexOf(item[pIndex + 3].pinyin) > -1 ? 'noFont' : '',
  651. bgIndex == 1 ? 'font-white' : '',
  652. 'bottom',
  653. ]"
  654. :style="{
  655. fontSize: pySize + 'px',
  656. textAlign: left,
  657. height: pySize * 1.25 + 'px',
  658. }"
  659. >{{ NumberList.indexOf(item[pIndex + 3].pinyin) == -1 ? item[pIndex + 3].pinyin : '' }}</span
  660. >
  661. </template>
  662. </span>
  663. </template>
  664. <template v-else>
  665. <span class="NNPE-words-box">
  666. <template v-if="curQue.property.pinyin_position == 'top'">
  667. <span
  668. v-if="config.isShowPY"
  669. class="NNPE-pinyin"
  670. :class="[
  671. pItem.chs != '“' && pItem.padding ? 'padding' : '',
  672. pItem.className ? pItem.className : '',
  673. noFont.indexOf(pItem.pinyin) > -1 ? 'noFont' : '',
  674. bgIndex == 1 ? 'font-white' : '',
  675. ]"
  676. :style="{
  677. fontSize: pySize + 'px',
  678. height: pySize * 1.25 + 'px',
  679. }"
  680. >{{ NumberList.indexOf(pItem.pinyin) == -1 ? pItem.pinyin : '' }}</span
  681. >
  682. </template>
  683. <span
  684. v-if="pItem.chs != '#'"
  685. class="NNPE-chs"
  686. :class="[
  687. pItem.chs != '“' && pItem.padding && config.isShowPY ? 'padding' : '',
  688. curQue.property.pinyin_position == 'top' ? 'bottom' : '',
  689. ]"
  690. :style="{
  691. height: hzSize * 1.17 + 'px',
  692. }"
  693. >
  694. <template v-for="(wItem, wIndex) in pItem.leg">
  695. <span
  696. :key="'ci' + wIndex + pIndex + curSentIndex"
  697. :class="[
  698. pItem.timeList &&
  699. pItem.timeList[wIndex] &&
  700. curTime >= pItem.timeList[wIndex].wordBg &&
  701. curQue.wordTime &&
  702. curQue.wordTime[curSentIndex] &&
  703. curTime <= curQue.wordTime[curSentIndex].ed
  704. ? bgIndex == 0
  705. ? 'active'
  706. : 'active-yellow'
  707. : '',
  708. bgIndex == 1 ? 'font-white' : '',
  709. bgIndex == 0 && wordIndex == pItem.wordIndex ? 'wordActive' : '',
  710. bgIndex == 1 && wordIndex == pItem.wordIndex ? 'wordActive-blue' : '',
  711. newWordList.indexOf(pItem.chs) > -1 && !isPlaying ? 'newActive' : '',
  712. pItem.words && !isPlaying ? 'newActive' : '',
  713. ]"
  714. :style="{
  715. fontSize: hzSize + 'px',
  716. fontFamily: pItem.config && pItem.config.fontFamily ? pItem.config.fontFamily : '',
  717. textDecoration:
  718. pItem.config && pItem.config.textDecoration ? pItem.config.textDecoration : '',
  719. borderBottom: pItem.config && pItem.config.border === 'dotted' ? '1px dotted' : '',
  720. fontWeight: pItem.config && pItem.config.fontWeight ? pItem.config.fontWeight : '',
  721. color: pItem.config && pItem.config.color ? pItem.config.color : '',
  722. height: hzSize * 1.17 + 'px',
  723. display: 'inline-block',
  724. width: pItem.chs[wIndex].trim() === '' ? '10px' : '',
  725. }"
  726. >{{ convertText(pItem.chs[wIndex]) }}</span
  727. >
  728. </template>
  729. <img
  730. v-if="pItem.img && pItem.img.length > 0 && pItem.imgPosition === 'after'"
  731. :src="pItem.img[0].file_url"
  732. :style="{
  733. width: hzSize + 'px',
  734. height: hzSize + 'px',
  735. }"
  736. />
  737. </span>
  738. <template v-if="curQue.property.pinyin_position == 'bottom'">
  739. <span
  740. v-if="config.isShowPY"
  741. class="NNPE-pinyin bottom"
  742. :class="[
  743. pItem.chs != '“' && pItem.padding ? 'padding' : '',
  744. pItem.className ? pItem.className : '',
  745. bgIndex == 1 ? 'font-white' : '',
  746. ]"
  747. :style="{
  748. fontSize: pySize + 'px',
  749. height: pySize * 1.25 + 'px',
  750. }"
  751. >{{ NumberList.indexOf(pItem.pinyin) == -1 ? pItem.pinyin : '' }}</span
  752. >
  753. </template>
  754. </span>
  755. </template>
  756. </template>
  757. </template>
  758. <template v-else>
  759. <span
  760. :style="{
  761. height: pItem.height + 'px',
  762. width: pItem.width + 'px',
  763. }"
  764. ></span>
  765. </template>
  766. </template>
  767. </div>
  768. </div>
  769. <div style="overflow: hidden; clear: both"></div>
  770. <div
  771. v-if="
  772. enwords && config.isShowEN && (!curQue.enPosition || (curQue.enPosition && curQue.enPosition == 'bottom'))
  773. "
  774. :class="['enwords', bgIndex == 1 ? 'enwords-green' : '']"
  775. :style="{ fontSize: enSize + 'px' }"
  776. >
  777. {{ convertText(enwords) }}
  778. </div>
  779. </div>
  780. <div class="vc-box-right">
  781. <div
  782. :class="[
  783. 'vc-left vc-right-grey',
  784. isShowRight && bgIndex == 0 ? 'vc-right-black' : '',
  785. isShowRight && bgIndex == 1 ? 'vc-right-white' : '',
  786. curSentIndex == sentList.length - 1 ? 'hidden' : '',
  787. ]"
  788. @click="nextSentence"
  789. ></div>
  790. </div>
  791. </div>
  792. <div class="voicefull-top" @mouseover="setBottomShow(true)" @mouseleave="setBottomShow(false)">
  793. <div :class="[isBottomShow || isPhone ? 'voicefull-top-show' : 'voicefull-top-hidden']">
  794. <div class="top-left">
  795. <div :class="['select-bg', bgIndex == 1 ? 'select-bg-blue' : '']">
  796. <div :class="['bg-green-box', bgIndex == 1 ? 'active' : '']">
  797. <span :class="['bg-green', bgIndex == 1 ? 'active' : '']" @click="changeBg(1)"></span>
  798. </div>
  799. <div :class="['bg-white-box', bgIndex == 0 ? 'active' : '']">
  800. <span :class="['bg-white', bgIndex == 0 ? 'active' : '']" @click="changeBg(0)"></span>
  801. </div>
  802. </div>
  803. <div :class="['set-fontSize', bgIndex == 1 ? 'set-fontSize-green' : '']">
  804. <template v-if="hzSize >= 34">
  805. <span
  806. :class="['font-jian-black', bgIndex == 1 ? 'font-jian-yellow' : '']"
  807. @click="setFontSize('-')"
  808. ></span>
  809. </template>
  810. <template v-else>
  811. <span
  812. :class="['font-jian-black', bgIndex == 1 ? 'font-jian-yellow-disabled' : 'font-jian-white-disabled']"
  813. ></span>
  814. </template>
  815. <span :class="['font-img-black', bgIndex == 1 ? 'font-img-yellow' : '']"></span>
  816. <template v-if="hzSize <= 76">
  817. <span :class="['font-jia-black', bgIndex == 1 ? 'font-jia-yellow' : '']" @click="setFontSize('+')"></span>
  818. </template>
  819. <template v-else>
  820. <span
  821. :class="['font-jia-black', bgIndex == 1 ? 'font-jia-yellow-disabled' : 'font-jia-white-disabled']"
  822. ></span>
  823. </template>
  824. </div>
  825. <div
  826. :class="['op-btn', bgIndex == 1 ? 'op-btn-green' : '']"
  827. :title="convertText('键盘控制开启后,可用方向键控制翻页,空格键播放暂停,回车键录音')"
  828. @click="changeStatus('isKeyboard')"
  829. >
  830. <span
  831. :class="[
  832. 'keyboard-icon',
  833. !isKeyboard ? 'disabled' : '',
  834. isKeyboard && bgIndex == 1 ? 'keyboard-icon-yellow' : '',
  835. ]"
  836. ></span>
  837. </div>
  838. </div>
  839. <div class="top-middle">
  840. <template v-if="mp3">
  841. <AudioLineSentence
  842. :key="'sent' + curSentIndex"
  843. ref="audioLineSent"
  844. :mp3="mp3"
  845. :get-cur-time="getCurTime"
  846. :audio-id="'artPraAudioId' + curSentIndex"
  847. :stop-audio="stopAudio"
  848. :width="120"
  849. :hide-slider="true"
  850. :bg="bg"
  851. :ed="ed"
  852. :cur-time="curTime"
  853. :max-time="maxTime"
  854. :bg-index="bgIndex"
  855. :is-repeat="isRepeat"
  856. :is-auto="isAuto"
  857. @playChange="playChange"
  858. @rollSentence="rollSentence"
  859. />
  860. </template>
  861. <div :class="['op-btn', bgIndex == 1 ? 'op-btn-green' : '']" @click="setStatus">
  862. <span
  863. :class="[
  864. 'repeat-icon',
  865. !isRepeat && !isAuto ? 'disabled' : '',
  866. !isRepeat && isAuto ? 'auto-icon' : '',
  867. isRepeat && bgIndex == 1 ? 'repeat-icon-yellow' : '',
  868. !isRepeat && isAuto && bgIndex == 1 ? 'auto-icon-yellow' : '',
  869. ]"
  870. ></span>
  871. </div>
  872. <div :class="['op-btn', bgIndex == 1 ? 'op-btn-green' : '']" @click="changePinyin">
  873. <span
  874. :class="[
  875. 'pinyin-icon',
  876. !config.isShowPY ? 'disabled' : '',
  877. config.isShowPY && bgIndex == 1 ? 'pinyin-icon-yellow' : '',
  878. ]"
  879. ></span>
  880. </div>
  881. <div :class="['op-btn', bgIndex == 1 ? 'op-btn-green' : '']" @click="changeEN">
  882. <span
  883. :class="[
  884. 'en-icon',
  885. !enwords ? 'disabled' : '',
  886. !config.isShowEN ? 'disabled' : '',
  887. config.isShowEN && bgIndex == 1 ? 'en-icon-yellow' : '',
  888. ]"
  889. ></span>
  890. </div>
  891. <!-- <div
  892. :class="['op-btn', bgIndex == 1 ? 'op-btn-green' : '']"
  893. title="点击收藏后可在“个人中心”-“我的收藏”查看"
  894. @click="handleColl"
  895. >
  896. <span
  897. :class="[
  898. 'coll-icon',
  899. !isCollArr[curSentIndex] ? 'disabled' : '',
  900. isCollArr[curSentIndex] && bgIndex == 1 ? 'coll-icon-yellow' : '',
  901. ]"
  902. ></span>
  903. </div> -->
  904. </div>
  905. <div :class="['op-btn', bgIndex == 1 ? 'op-btn-green' : '']" @click="exitFullScreen">
  906. <span :class="['close-icon', bgIndex == 1 ? 'close-icon-white' : '']"></span>
  907. </div>
  908. </div>
  909. </div>
  910. <template v-if="isShow">
  911. <div ref="wordcard" class="NNPE-wordDetail" :style="{ left: left + 'px' }">
  912. <Wordcard
  913. :word="word"
  914. :change-word-card="changeWordCard"
  915. :theme-color="themeColor"
  916. :current-tree-i-d="currentTreeID"
  917. :mp3-url="wordPlayMp3"
  918. :bg="wordbgs"
  919. :ed="wordeds"
  920. :attrib="attrib"
  921. :is-mobile="isMobile"
  922. :is-full="true"
  923. :page-from="isPhone ? 'fullscreen' : ''"
  924. />
  925. </div>
  926. </template>
  927. <div v-if="isWordPlay || isNewWordPlay" class="word-play-audio">
  928. <AudioLineSentence
  929. ref="audioLineWord"
  930. :mp3="isWordPlay ? NpcNewWordMp3 : isNewWordPlay ? wordPlayMp3 : ''"
  931. :get-cur-time="getCurWordTime"
  932. :audio-id="'artPraAudioId' + curSentIndex + wordIndex"
  933. :stop-audio="stopAudio"
  934. :width="120"
  935. :hide-slider="false"
  936. :bg="wordbg"
  937. :ed="worded"
  938. :max-time="wordMaxTime"
  939. :bg-index="bgIndex"
  940. :is-repeat="isRepeat"
  941. :word-play="true"
  942. @changePlayStatus="changePlayStatus"
  943. />
  944. </div>
  945. <template v-if="isNoteShow">
  946. <div
  947. ref="notecard"
  948. class="NNPE-wordDetail"
  949. :style="{
  950. marginLeft: windowWidth > 642 ? '-321px' : '0px',
  951. left: windowWidth > 642 ? '' : '0px',
  952. width: isMobile ? '100%' : '',
  953. }"
  954. >
  955. <Notecard :item="curNoteCon" :change-card="changeCard" :attrib="attrib" :is-mobile="isMobile" />
  956. </div>
  957. </template>
  958. </div>
  959. </template>
  960. <script>
  961. import AudioLineSentence from './components/AudioLineSentence.vue';
  962. import Wordcard from './components/Wordcard.vue';
  963. import Notecard from './components/Notecard.vue'; // 注释
  964. import { LearnWebSI } from '@/api/app';
  965. export default {
  966. name: 'VoiceFullScreen',
  967. components: {
  968. AudioLineSentence,
  969. Wordcard,
  970. Notecard,
  971. },
  972. inject: ['convertText'],
  973. props: [
  974. 'sentList',
  975. 'sentIndex',
  976. 'mp3',
  977. 'wordTimeList',
  978. 'curQue',
  979. 'noFont',
  980. 'themeColor',
  981. 'NNPENewWordList',
  982. 'NNPEAnnotationList',
  983. 'currentTreeID',
  984. 'config',
  985. 'TaskModel',
  986. 'NpcNewWordMp3',
  987. 'attrib',
  988. 'isMobile',
  989. ],
  990. data() {
  991. return {
  992. pySize: 32,
  993. hzSize: 48,
  994. enSize: 24,
  995. bgIndex: 1,
  996. maxTime: 0,
  997. item: null,
  998. bg: 0,
  999. ed: 0,
  1000. isRepeat: false,
  1001. NumberList: ['①', '②', '③', '④', '⑤', '⑥', '⑦', '⑧', '⑨', '⑩', '⑪', '⑫', '⑬', '⑭', '⑮', '⑯', '⑰', '⑱', '⑲', '⑳'],
  1002. chsFhList: [',', '。', '”', ':', '》', '?', '!', ';', '#', '、', '’', ')', '〕', '〕〕', '〉'],
  1003. enFhList: [',', '.', ';', '?', '!', ':', '>', '<'],
  1004. firstFhlist: ['(', '“', '‘', '〔', '〔〔', '〈', '《'],
  1005. curTime: 0,
  1006. wavblob: null,
  1007. stopAudio: false,
  1008. isRecord: false,
  1009. isShowCompare: false,
  1010. isShowRight: true,
  1011. isShowLeft: true,
  1012. curSentIndex: 0,
  1013. oldHz: '',
  1014. hz: '',
  1015. clientY: 0,
  1016. top: 0,
  1017. left: 0,
  1018. newWordList: [],
  1019. pinyin: '',
  1020. wordIndex: -1,
  1021. isShow: false,
  1022. wordbg: 0,
  1023. worded: 0,
  1024. wordbgs: 0,
  1025. wordeds: 0,
  1026. wordMaxTime: 0,
  1027. isWordPlay: false,
  1028. isNewWordPlay: false,
  1029. curWordTime: 0,
  1030. isPlaying: false,
  1031. isAuto: false,
  1032. key: 'isRepeat',
  1033. isKeyboard: true,
  1034. isTopShow: false,
  1035. isBottomShow: false,
  1036. isRecording: false,
  1037. recordPlaying: false,
  1038. isCollArr: [],
  1039. enwords: '',
  1040. screenHeight: 0,
  1041. wordPlayMp3: '',
  1042. curNoteCon: null,
  1043. isNoteShow: false,
  1044. oldNoteNum: '',
  1045. windowWidth: window.innerWidth,
  1046. isLandscape: window.innerWidth < window.innerHeight, // 手机是否为竖屏
  1047. isPhone: false,
  1048. };
  1049. },
  1050. computed: {
  1051. // isPlaying: function () {
  1052. // let playing = false;
  1053. // if (this.$refs.audioLineSent) {
  1054. // playing = this.$refs.audioLineSent.audio.isPlaying;
  1055. // }
  1056. // console.log(playing);
  1057. // return playing;
  1058. // },
  1059. },
  1060. watch: {
  1061. isRecording: {
  1062. handler(newVal) {
  1063. if (newVal) {
  1064. this.isBottomShow = newVal;
  1065. }
  1066. },
  1067. deep: true,
  1068. },
  1069. recordPlaying: {
  1070. handler(newVal) {
  1071. if (newVal) {
  1072. this.isBottomShow = newVal;
  1073. }
  1074. },
  1075. deep: true,
  1076. },
  1077. sentIndex: {
  1078. handler(newVal) {
  1079. this.curSentIndex = newVal;
  1080. this.getSentence();
  1081. },
  1082. deep: true,
  1083. },
  1084. hz: {
  1085. handler(val) {
  1086. if (val) {
  1087. this.handleNewWords(val);
  1088. }
  1089. },
  1090. // 深度观察监听
  1091. deep: true,
  1092. },
  1093. isShow: {
  1094. handler(val) {
  1095. if (val) {
  1096. setTimeout(() => {
  1097. this.cardHeight = this.$refs.wordcard.offsetHeight;
  1098. if (this.screenHeight - this.clientY > this.cardHeight) {
  1099. this.top = this.clientY + 20;
  1100. } else {
  1101. this.top = this.clientY - this.cardHeight - 30;
  1102. }
  1103. }, 50);
  1104. }
  1105. },
  1106. // 深度观察监听
  1107. deep: true,
  1108. },
  1109. isNoteShow: {
  1110. handler(val) {
  1111. if (val) {
  1112. setTimeout(() => {
  1113. this.cardHeight = this.$refs.notecard.offsetHeight;
  1114. if (this.screenHeight - this.clientY > this.cardHeight) {
  1115. this.top = this.clientY + 20;
  1116. } else {
  1117. this.top = this.clientY - this.cardHeight - 30;
  1118. }
  1119. }, 50);
  1120. }
  1121. },
  1122. // 深度观察监听
  1123. deep: true,
  1124. },
  1125. },
  1126. // 生命周期 - 创建完成(可以访问当前this实例)
  1127. created() {
  1128. const regExp = /Android|webOS|iPhone|BlackBerry|IEMobile|Opera Mini/i;
  1129. this.isPhone = regExp.test(navigator.userAgent) && window.innerWidth < 860;
  1130. },
  1131. // 生命周期 - 挂载完成(可以访问DOM元素)
  1132. mounted() {
  1133. window.addEventListener('resize', this.getScreenHeight);
  1134. this.getScreenHeight();
  1135. document.addEventListener('keyup', (e) => {
  1136. if (this.isKeyboard) {
  1137. if (e.keyCode === 32) {
  1138. // 空格
  1139. this.$nextTick(() => {
  1140. if (this.$refs.audioLineSent) {
  1141. this.$refs.audioLineSent.PlayAudio();
  1142. }
  1143. });
  1144. } else if (e.keyCode === 38) {
  1145. this.prevSentence();
  1146. } else if (e.keyCode === 40) {
  1147. this.nextSentence();
  1148. } else if (e.keyCode === 13) {
  1149. } else if (event.key === 'Escape' || event.key === 'Esc' || event.keyCode === 27) {
  1150. this.exitFullScreen();
  1151. }
  1152. }
  1153. });
  1154. if (this.NNPENewWordList) {
  1155. this.handleNewword();
  1156. }
  1157. this.curSentIndex = this.sentIndex;
  1158. this.getSentence();
  1159. document.addEventListener('fullscreenchange', () => {
  1160. let isFullscreen =
  1161. document.fullscreenElement ||
  1162. document.mozFullScreenElement ||
  1163. document.webkitFullscreenElement ||
  1164. document.fullScreen ||
  1165. document.mozFullScreen ||
  1166. document.webkitIsFullScreen;
  1167. if (!isFullscreen) {
  1168. this.changeFullScreen();
  1169. }
  1170. });
  1171. document.addEventListener('mozfullscreenchange', () => {
  1172. let isFullscreen =
  1173. document.fullscreenElement ||
  1174. document.mozFullScreenElement ||
  1175. document.webkitFullscreenElement ||
  1176. document.fullScreen ||
  1177. document.mozFullScreen ||
  1178. document.webkitIsFullScreen;
  1179. if (!isFullscreen) {
  1180. this.changeFullScreen();
  1181. }
  1182. });
  1183. document.addEventListener('webkitfullscreenchange', () => {
  1184. let isFullscreen =
  1185. document.fullscreenElement ||
  1186. document.mozFullScreenElement ||
  1187. document.webkitFullscreenElement ||
  1188. document.fullScreen ||
  1189. document.mozFullScreen ||
  1190. document.webkitIsFullScreen;
  1191. if (!isFullscreen) {
  1192. this.changeFullScreen();
  1193. }
  1194. });
  1195. document.addEventListener('msfullscreenchange', () => {
  1196. let isFullscreen =
  1197. document.fullscreenElement ||
  1198. document.mozFullScreenElement ||
  1199. document.webkitFullscreenElement ||
  1200. document.fullScreen ||
  1201. document.mozFullScreen ||
  1202. document.webkitIsFullScreen;
  1203. if (!isFullscreen) {
  1204. this.changeFullScreen();
  1205. }
  1206. });
  1207. },
  1208. beforeCreate() {}, // 生命周期 - 创建之前
  1209. beforeMount() {}, // 生命周期 - 挂载之前
  1210. beforeUpdate() {}, // 生命周期 - 更新之前
  1211. updated() {}, // 生命周期 - 更新之后
  1212. beforeDestroy() {
  1213. window.removeEventListener('resize', this.getScreenHeight);
  1214. }, // 生命周期 - 销毁之前
  1215. destroyed() {}, // 生命周期 - 销毁完成
  1216. activated() {},
  1217. // 方法集合
  1218. methods: {
  1219. setTopShow(bool) {
  1220. this.isTopShow = bool;
  1221. },
  1222. setBottomShow(bool) {
  1223. if (!this.recordPlaying && !this.isRecording) {
  1224. this.isBottomShow = bool;
  1225. }
  1226. },
  1227. getPlayStatus(bool) {
  1228. this.recordPlaying = bool;
  1229. },
  1230. setFontSize(type) {
  1231. if (type === '-') {
  1232. if (this.hzSize >= 34) {
  1233. this.hzSize -= 4;
  1234. }
  1235. }
  1236. if (type === '+') {
  1237. if (this.hzSize <= 76) {
  1238. this.hzSize += 4;
  1239. }
  1240. }
  1241. this.pySize = parseInt(this.hzSize / 1.5);
  1242. this.enSize = parseInt(this.hzSize / 2);
  1243. },
  1244. playChange(bool) {
  1245. this.isPlaying = bool;
  1246. },
  1247. handleColl() {
  1248. if (this.isCollArr[this.curSentIndex]) {
  1249. this.cancleColl();
  1250. } else {
  1251. this.addColl();
  1252. }
  1253. },
  1254. // 添加收藏
  1255. addColl() {
  1256. let Bookdetail = sessionStorage.getItem('Bookdetail');
  1257. // if (Bookdetail) {
  1258. Bookdetail = JSON.parse(Bookdetail);
  1259. let MethodName = 'order-collection_manager-AddMyCollection';
  1260. let text = '';
  1261. this.item.forEach((item) => {
  1262. if (item.chs !== '#') {
  1263. text += item.chs;
  1264. }
  1265. });
  1266. let sentence_json = {
  1267. item: JSON.stringify(this.item),
  1268. bg: this.bg,
  1269. ed: this.ed,
  1270. mp3: this.mp3,
  1271. pyPosition: this.curQue.property.pinyin_position,
  1272. };
  1273. let data = {
  1274. goods_id: this.currentTreeID,
  1275. goods_type: 502,
  1276. goods_name: Bookdetail.name,
  1277. goods_person_name_desc: Bookdetail.author ? Bookdetail.author : '',
  1278. goods_picture_id: Bookdetail.picture_id ? Bookdetail.picture_id : '',
  1279. goods_price: Bookdetail.price,
  1280. sentence: {
  1281. sentence_text: text,
  1282. sentence_json: JSON.stringify(sentence_json),
  1283. },
  1284. };
  1285. LearnWebSI(MethodName, data).then((res) => {
  1286. this.$set(this.isCollArr, this.curSentIndex, true);
  1287. this.$message.success('收藏成功!');
  1288. });
  1289. // } else {
  1290. // this.$message.warning('权限不足!');
  1291. // }
  1292. },
  1293. // 取消收藏
  1294. cancleColl() {
  1295. let text = '';
  1296. this.item.forEach((item) => {
  1297. if (item.chs !== '#') {
  1298. text += item.chs;
  1299. }
  1300. });
  1301. let MethodName = 'order-collection_manager-CancelMyGoodsCollection_WS';
  1302. let data = {
  1303. goods_type: 502,
  1304. goods_list: [
  1305. {
  1306. goods_id: this.currentTreeID, // 课件的id
  1307. sentence_text: text,
  1308. },
  1309. ],
  1310. };
  1311. LearnWebSI(MethodName, data).then((res) => {
  1312. this.$set(this.isCollArr, this.curSentIndex, false);
  1313. this.$message.success('取消成功!');
  1314. });
  1315. },
  1316. // 检查收藏状态
  1317. checkCollStatus() {
  1318. let text = '';
  1319. this.item.forEach((item) => {
  1320. if (item.chs !== '#') {
  1321. text += item.chs;
  1322. }
  1323. });
  1324. let MethodName = 'order-collection_manager-CheckMyGoodsCollectionStatus';
  1325. let data = {
  1326. goods_type: 502,
  1327. goods_id: this.currentTreeID, // 课件的id
  1328. sentence_text: text,
  1329. };
  1330. LearnWebSI(MethodName, data).then((res) => {
  1331. let collFlag = res.is_collection === 'true';
  1332. this.$set(this.isCollArr, this.curSentIndex, collFlag);
  1333. });
  1334. },
  1335. showPrevNext(bool, key) {
  1336. this[key] = bool;
  1337. },
  1338. prevSentence() {
  1339. if (this.curSentIndex === 0) {
  1340. // this.$message.warning("已经是第一个句子了");
  1341. return;
  1342. }
  1343. this.curSentIndex -= 1;
  1344. this.getSentence();
  1345. if (this.isAuto) {
  1346. this.curTime = this.bg;
  1347. this.$refs.audioLineSent.onTimeupdateTime(this.bg / 1000);
  1348. }
  1349. },
  1350. nextSentence() {
  1351. if (this.curSentIndex === this.sentList.length - 1) {
  1352. // this.$message.warning("已经是最后一个句子了");
  1353. return;
  1354. }
  1355. this.curSentIndex += 1;
  1356. this.getSentence();
  1357. },
  1358. rollSentence() {
  1359. if (this.curSentIndex === this.sentList.length - 1) {
  1360. this.curSentIndex = 0;
  1361. } else {
  1362. this.curSentIndex += 1;
  1363. }
  1364. this.getSentence();
  1365. },
  1366. changeStatus(key) {
  1367. if (key === 'config.isShowEN') {
  1368. if (this.enwords) {
  1369. this[key] = !this[key];
  1370. }
  1371. } else {
  1372. this[key] = !this[key];
  1373. }
  1374. },
  1375. changePinyin() {
  1376. this.$emit('changePinyin');
  1377. },
  1378. changeEN() {
  1379. this.$emit('changeEN');
  1380. },
  1381. setStatus() {
  1382. if (this.key === 'isRepeat') {
  1383. if (this.isRepeat) {
  1384. this.isRepeat = false;
  1385. this.isAuto = true;
  1386. this.key = 'isAuto';
  1387. } else {
  1388. this.isRepeat = true;
  1389. this.key = 'isRepeat';
  1390. }
  1391. } else if (this.key === 'isAuto') {
  1392. if (this.isAuto) {
  1393. this.isRepeat = false;
  1394. this.isAuto = false;
  1395. this.key = 'isRepeat';
  1396. }
  1397. }
  1398. },
  1399. getRerordStatus(bool) {
  1400. this.isShowCompare = bool;
  1401. },
  1402. getMicrophoneStatus(bool) {
  1403. this.isRecording = bool;
  1404. },
  1405. getWavblob(wavblob) {
  1406. this.wavblob = wavblob;
  1407. },
  1408. sentPause(isRecord) {
  1409. this.isRecord = isRecord;
  1410. },
  1411. getCurTime(curTime) {
  1412. if (this.isRepeat) {
  1413. let time = curTime * 1000;
  1414. if (time > this.ed || time < this.bg) {
  1415. this.curTime = this.bg;
  1416. this.$refs.audioLineSent.onTimeupdateTime(this.bg / 1000);
  1417. } else {
  1418. this.curTime = curTime * 1000;
  1419. }
  1420. } else if (this.isAuto) {
  1421. let time = curTime * 1000;
  1422. if (time > this.ed) {
  1423. this.rollSentence();
  1424. this.curTime = this.bg;
  1425. this.$refs.audioLineSent.onTimeupdateTime(this.bg / 1000);
  1426. } else {
  1427. this.curTime = curTime * 1000;
  1428. }
  1429. } else {
  1430. this.curTime = curTime * 1000;
  1431. }
  1432. },
  1433. getCurCompareTime(curTime) {
  1434. this.curTime = curTime * 1000;
  1435. },
  1436. getCurWordTime(curTime) {
  1437. this.curWordTime = curTime * 1000;
  1438. },
  1439. changeBg(bgIndex) {
  1440. this.bgIndex = bgIndex;
  1441. },
  1442. getSentence() {
  1443. this.isShowCompare =
  1444. this.curQue.Bookanswer.practiceModel[this.curSentIndex] &&
  1445. this.curQue.Bookanswer.practiceModel[this.curSentIndex].recordList &&
  1446. this.curQue.Bookanswer.practiceModel[this.curSentIndex].recordList.length > 0;
  1447. this.pauseAudio();
  1448. this.isPlaying = false;
  1449. let item = JSON.parse(JSON.stringify(this.sentList[this.curSentIndex]));
  1450. if (item.sentArr) {
  1451. this.item = item.sentArr;
  1452. this.enwords = item.enwords;
  1453. } else {
  1454. this.item = item;
  1455. }
  1456. this.item.forEach((wItem, wIndex) => {
  1457. this.mergeWordSymbol(wItem);
  1458. wItem.isShow = wItem.isShow;
  1459. });
  1460. this.sentList.forEach((item) => {
  1461. this.isCollArr.push(false);
  1462. });
  1463. this.bg =
  1464. this.curQue.wordTime && this.curQue.wordTime[this.curSentIndex]
  1465. ? this.curQue.wordTime[this.curSentIndex].bg
  1466. : 0;
  1467. this.ed =
  1468. this.curQue.wordTime && this.curQue.wordTime[this.curSentIndex]
  1469. ? this.curQue.wordTime[this.curSentIndex].ed
  1470. : 0;
  1471. let maxTime = (this.ed - this.bg) / 1000;
  1472. if (maxTime < 1) {
  1473. this.maxTime = 1;
  1474. } else {
  1475. this.maxTime = maxTime;
  1476. }
  1477. // this.checkCollStatus();
  1478. },
  1479. // 词和标点合一起
  1480. mergeWordSymbol(wItem) {
  1481. if (
  1482. this.chsFhList.indexOf(wItem.chs) > -1 ||
  1483. this.NumberList.indexOf(wItem.chs) > -1 ||
  1484. this.firstFhlist.indexOf(wItem.chs) > -1
  1485. ) {
  1486. wItem.isShow = false;
  1487. } else {
  1488. wItem.isShow = true;
  1489. }
  1490. },
  1491. pauseAudio() {
  1492. let audio = document.getElementsByTagName('audio');
  1493. if (audio && audio.length > 0 && window.location.href.indexOf('GCLS-Learn') === -1 && audio.forEach) {
  1494. audio.forEach((item) => {
  1495. item.pause();
  1496. });
  1497. }
  1498. },
  1499. exitFullScreen() {
  1500. this.pauseAudio();
  1501. this.$emit('exitFullscreen');
  1502. },
  1503. changeFullScreen() {
  1504. this.pauseAudio();
  1505. this.$emit('changeIsFull');
  1506. },
  1507. handleWav(list, tmIndex) {
  1508. let _tmIndex = tmIndex || 0;
  1509. this.$emit('handleWav', list, _tmIndex);
  1510. },
  1511. // 录音时暂停音频播放
  1512. handleParentPlay() {
  1513. this.stopAudio = true;
  1514. },
  1515. // 音频播放时改变布尔值
  1516. handleChangeStopAudio() {
  1517. this.stopAudio = false;
  1518. },
  1519. // 播放音频
  1520. // playWord(item) {
  1521. //
  1522. // if (this.newWordList.indexOf(item.chs) > -1 || item.words) {
  1523. // this.pauseAudio();
  1524. // this.isWordPlay = false;
  1525. // this.wordIndex = item.wordIndex;
  1526. // setTimeout(() => {
  1527. // let leg = item.timeList.length;
  1528. // this.wordbg = item.timeList[0].wordBg;
  1529. // this.worded = item.timeList[leg - 1].wordEd;
  1530. // let wordMaxTime = (this.worded - this.wordbg) / 1000;
  1531. // if (wordMaxTime < 1) {
  1532. // this.wordMaxTime = 1;
  1533. // } else {
  1534. // this.wordMaxTime = wordMaxTime;
  1535. // }
  1536. // this.isWordPlay = true;
  1537. // }, 50);
  1538. // }
  1539. // },
  1540. playWord(item) {
  1541. if (this.newWordList.indexOf(item.chs) > -1 || item.words) {
  1542. this.pauseAudio();
  1543. this.isNewWordPlay = false;
  1544. let new_word = item.words ? item.words : item.chs;
  1545. this.NNPENewWordList.forEach((itemn) => {
  1546. // items.forEach((itemn) => {
  1547. if (itemn.new_word === new_word) {
  1548. this.wordbg = itemn.audio_begin_time || itemn.bg;
  1549. this.worded = itemn.audio_end_time || itemn.ed;
  1550. this.wordPlayMp3 = itemn.newWordMp3 || itemn.audio_file_url;
  1551. }
  1552. // });
  1553. });
  1554. setTimeout(() => {
  1555. this.isNewWordPlay = true;
  1556. }, 50);
  1557. }
  1558. },
  1559. changePlayStatus() {
  1560. this.isWordPlay = false;
  1561. this.isNewWordPlay = false;
  1562. this.wordIndex = -1;
  1563. },
  1564. showWordDetail(e, item) {
  1565. let noteIndex = '';
  1566. if (this.TaskModel === 'ANSWER') {
  1567. return;
  1568. }
  1569. if (
  1570. this.chsFhList.indexOf(item.chs) > -1 ||
  1571. /^[a-zA-Z0-9]/.test(item.chs) ||
  1572. this.firstFhlist.indexOf(item.chs) > -1
  1573. ) {
  1574. return;
  1575. }
  1576. if (this.NumberList.indexOf(item.chs) > -1) {
  1577. for (let i = 0; i < this.NumberList.length; i++) {
  1578. if (this.NumberList[i] === item.chs) {
  1579. noteIndex = `${String(i)}`;
  1580. break;
  1581. }
  1582. }
  1583. this.showNoteDetail(e, noteIndex);
  1584. } else if (item.matchNotes) {
  1585. // 关联了注释
  1586. if (this.NNPEAnnotationList && this.NNPEAnnotationList.length > 0) {
  1587. this.NNPEAnnotationList.forEach((items, indexs) => {
  1588. let textContent = items.con.replace(/<[^>]*>?/gm, '');
  1589. if (textContent === item.matchNotes.trim()) {
  1590. noteIndex = `${String(indexs)}`;
  1591. this.showNoteDetail(e, noteIndex);
  1592. }
  1593. });
  1594. }
  1595. } else if (this.newWordList.indexOf(item.chs) > -1 || this.newWordList.indexOf(item.words) > -1) {
  1596. if (this.oldHz !== item.chs) {
  1597. this.isShow = false;
  1598. setTimeout(() => {
  1599. this.hz = item.words ? item.words : item.chs;
  1600. this.pinyin = item.pinyin;
  1601. this.wordIndex = item.wordIndex;
  1602. }, 50);
  1603. }
  1604. this.clientY = e.clientY;
  1605. let new_word = item.words ? item.words : item.chs;
  1606. this.wordPlayMp3 = '';
  1607. this.NNPENewWordList.forEach((itemn) => {
  1608. // items.forEach((itemn) => {
  1609. if (itemn.new_word === new_word) {
  1610. this.wordbgs = itemn.audio_begin_time || itemn.bg;
  1611. this.wordeds = itemn.audio_end_time || itemn.ed;
  1612. this.wordPlayMp3 = itemn.newWordMp3 || itemn.audio_file_url;
  1613. }
  1614. // });
  1615. });
  1616. let left = e.clientX;
  1617. let width = 0;
  1618. if (item.chs.length === 1 || item.chs.length === 2) {
  1619. width = 304;
  1620. } else if (item.chs.length === 3 || item.chs.length === 4) {
  1621. width = 432;
  1622. } else if (item.chs.length > 3) {
  1623. width = 560;
  1624. }
  1625. // if (left - this.bodyLeft > this.contentWidth / 2) {
  1626. // this.left = left - width + 10;
  1627. // } else {
  1628. this.left = left - width / 2;
  1629. // }
  1630. } else if (item.matchWords && this.newWordList.indexOf(item.matchWords) > -1) {
  1631. // 关联了生词
  1632. if (this.oldHz !== item.matchWords) {
  1633. this.isShow = false;
  1634. setTimeout(() => {
  1635. this.hz = item.matchWords;
  1636. this.pinyin = item.pinyin;
  1637. this.wordIndex = item.wordIndex;
  1638. }, 50);
  1639. }
  1640. this.clientY = e.clientY;
  1641. let new_word = item.matchWords;
  1642. this.wordPlayMp3 = '';
  1643. this.NNPENewWordList.forEach((itemn) => {
  1644. // items.forEach((itemn) => {
  1645. if (itemn.new_word === new_word) {
  1646. this.wordbgs = itemn.audio_begin_time || itemn.bg;
  1647. this.wordeds = itemn.audio_end_time || itemn.ed;
  1648. this.wordPlayMp3 = itemn.newWordMp3 || itemn.audio_file_url;
  1649. }
  1650. // });
  1651. });
  1652. let left = e.clientX;
  1653. let width = 0;
  1654. if (item.matchWords.length === 1 || item.matchWords.length === 2) {
  1655. width = 304;
  1656. } else if (item.matchWords.length === 3 || item.matchWords.length === 4) {
  1657. width = 432;
  1658. } else if (item.matchWords.length > 3) {
  1659. width = 560;
  1660. }
  1661. this.left = left - width / 2;
  1662. } else {
  1663. if (this.oldHz !== item.chs) {
  1664. this.isShow = false;
  1665. setTimeout(() => {
  1666. this.hz = item.words ? item.words : item.chs;
  1667. this.pinyin = item.pinyin;
  1668. this.wordIndex = item.wordIndex;
  1669. }, 50);
  1670. }
  1671. this.clientY = e.clientY;
  1672. let new_word = item.words ? item.words : item.chs;
  1673. this.wordPlayMp3 = '';
  1674. this.wordbgs = '';
  1675. this.wordeds = '';
  1676. this.wordPlayMp3 = '';
  1677. let left = e.clientX;
  1678. let width = 0;
  1679. if (item.chs.length === 1 || item.chs.length === 2) {
  1680. width = 304;
  1681. } else if (item.chs.length === 3 || item.chs.length === 4) {
  1682. width = 432;
  1683. } else if (item.chs.length > 3) {
  1684. width = 560;
  1685. }
  1686. this.left = left - width / 2;
  1687. }
  1688. },
  1689. showNoteDetail(e, noteNum) {
  1690. if (this.oldNoteNum !== noteNum) {
  1691. this.isNoteShow = false;
  1692. setTimeout(() => {
  1693. this.noteNum = noteNum;
  1694. this.handleNote(noteNum);
  1695. }, 50);
  1696. }
  1697. this.clientY = e.clientY;
  1698. let left = e.clientX;
  1699. let width = 642;
  1700. if (left - this.bodyLeft > this.contentWidth / 2) {
  1701. this.left = left - width + 10;
  1702. } else if (left - 200 > 500) {
  1703. this.left = 500;
  1704. } else {
  1705. this.left = left - 200;
  1706. }
  1707. },
  1708. changeWordCard(isShow) {
  1709. this.isShow = isShow;
  1710. this.oldHz = '';
  1711. this.hz = '';
  1712. this.wordIndex = -1;
  1713. },
  1714. // 处理分词数据
  1715. handleNewWords(val) {
  1716. this.isShow = true;
  1717. this.word = null;
  1718. if (this.newWordList.indexOf(val) > -1) {
  1719. for (let i = 0; i < this.NNPENewWordList.length; i++) {
  1720. let pItem = this.NNPENewWordList[i];
  1721. if (pItem.new_word.trim() === val.trim()) {
  1722. let wordlist = val.split('');
  1723. this.word = { list: wordlist, detail: pItem };
  1724. break;
  1725. }
  1726. }
  1727. } else {
  1728. let wordlist = val.split('');
  1729. let option = {
  1730. definition_list: [],
  1731. mp3_list: [],
  1732. new_word: val,
  1733. pinyin: this.pinyin,
  1734. };
  1735. this.word = { list: wordlist, detail: option };
  1736. }
  1737. this.oldHz = val;
  1738. },
  1739. handleNewword() {
  1740. let NewWordList = [];
  1741. this.NNPENewWordList.forEach((wItem) => {
  1742. // item.forEach((wItem) => {
  1743. NewWordList.push(wItem.new_word);
  1744. // });
  1745. });
  1746. this.newWordList = JSON.parse(JSON.stringify(NewWordList));
  1747. },
  1748. getScreenHeight() {
  1749. this.screenHeight = window.innerHeight;
  1750. },
  1751. // 处理注释数据
  1752. handleNote(val) {
  1753. this.isNoteShow = true;
  1754. this.oldNoteNum = val;
  1755. let noteIndex = Number(val);
  1756. if (this.NNPEAnnotationList && this.NNPEAnnotationList.length > 0) {
  1757. this.curNoteCon = this.NNPEAnnotationList[noteIndex] ? this.NNPEAnnotationList[noteIndex] : null;
  1758. }
  1759. },
  1760. changeCard(isShow) {
  1761. this.isNoteShow = isShow;
  1762. this.oldNoteNum = '';
  1763. this.noteNum = '';
  1764. },
  1765. }, // 如果页面有keep-alive缓存功能,这个函数会触发
  1766. };
  1767. </script>
  1768. <style lang="scss" scoped>
  1769. .voicefull {
  1770. position: fixed;
  1771. top: 0;
  1772. left: 0;
  1773. z-index: 99999;
  1774. display: flex;
  1775. flex-direction: column;
  1776. width: 100%;
  1777. height: 100vh;
  1778. padding-top: env(safe-area-inset-top);
  1779. padding-bottom: env(safe-area-inset-bottom);
  1780. overflow: hidden;
  1781. &-scape {
  1782. display: flex;
  1783. flex-direction: column;
  1784. width: 100vh;
  1785. height: 100vw;
  1786. margin-left: 100vw;
  1787. transform: rotate(90deg);
  1788. transform-origin: 0% 0%;
  1789. .vc-main {
  1790. max-height: calc(100vw - 132px) !important;
  1791. }
  1792. .op-btn {
  1793. margin-left: 16px !important;
  1794. }
  1795. }
  1796. .NNPE-wordDetail {
  1797. position: fixed;
  1798. top: 50%;
  1799. z-index: 9999;
  1800. margin-top: -196px;
  1801. // box-shadow: 0 4px 16px rgba(0, 0, 0, 15%);
  1802. }
  1803. &.bg1 {
  1804. background: #fff;
  1805. }
  1806. &.bg2 {
  1807. background: linear-gradient(180deg, #274533 0%, #385f45 100%);
  1808. .NNPE-words > span.NNPE-chs .newActive,
  1809. .NNPE-words-box > span.NNPE-chs .newActive {
  1810. color: #ffc600 !important;
  1811. }
  1812. }
  1813. &-top {
  1814. box-sizing: border-box;
  1815. width: 100%;
  1816. height: 136px;
  1817. padding: 0 40px;
  1818. .voicefull-top-hidden {
  1819. display: flex;
  1820. align-items: center;
  1821. justify-content: space-between;
  1822. width: 100%;
  1823. height: 136px;
  1824. visibility: hidden;
  1825. }
  1826. .voicefull-top-show {
  1827. display: flex;
  1828. align-items: center;
  1829. justify-content: space-between;
  1830. width: 100%;
  1831. height: 136px;
  1832. visibility: visible;
  1833. }
  1834. .top-left {
  1835. display: flex;
  1836. align-items: center;
  1837. justify-content: flex-start;
  1838. }
  1839. .select-bg {
  1840. box-sizing: border-box;
  1841. display: flex;
  1842. align-items: center;
  1843. justify-content: space-between;
  1844. justify-content: center;
  1845. width: 96px;
  1846. height: 56px;
  1847. margin-right: 32px;
  1848. border: 1px solid rgba(0, 0, 0, 10%);
  1849. border-radius: 40px;
  1850. &.select-bg-blue {
  1851. background: rgba(255, 255, 255, 10%);
  1852. border: 1px solid rgba(0, 0, 0, 10%);
  1853. }
  1854. > div {
  1855. display: flex;
  1856. align-items: center;
  1857. justify-content: center;
  1858. width: 36px;
  1859. height: 36px;
  1860. border-radius: 100%;
  1861. &.bg-white-box {
  1862. margin-right: 4px;
  1863. background: 0 0;
  1864. &.active {
  1865. background: #de4444;
  1866. }
  1867. }
  1868. &.bg-green-box {
  1869. background: #fff;
  1870. &.active {
  1871. background: #ffc600;
  1872. }
  1873. }
  1874. > span {
  1875. box-sizing: border-box;
  1876. width: 24px;
  1877. height: 24px;
  1878. cursor: pointer;
  1879. border-radius: 100%;
  1880. &.bg-white {
  1881. background: #fff;
  1882. }
  1883. &.bg-green {
  1884. background: linear-gradient(180deg, #274533 0%, #385f45 100%);
  1885. }
  1886. }
  1887. }
  1888. }
  1889. .set-fontSize {
  1890. display: flex;
  1891. align-items: center;
  1892. justify-content: center;
  1893. height: 56px;
  1894. padding: 0 20px;
  1895. background: #fff;
  1896. border: 1px solid rgba(0, 0, 0, 10%);
  1897. border-radius: 40px;
  1898. &-green {
  1899. background: rgba(255, 255, 255, 10%);
  1900. border: 1px solid rgba(0, 0, 0, 10%);
  1901. }
  1902. > span {
  1903. width: 24px;
  1904. height: 24px;
  1905. margin: 0 4px;
  1906. &.font-jian {
  1907. &-black {
  1908. cursor: pointer;
  1909. background: url('@/assets/jian-black.png') no-repeat left top;
  1910. background-size: 100% 100%;
  1911. }
  1912. &-yellow {
  1913. cursor: pointer;
  1914. background: url('@/assets/jian-white.png') no-repeat left top;
  1915. background-size: 100% 100%;
  1916. }
  1917. &-white-disabled {
  1918. cursor: pointer;
  1919. background: url('@/assets/jian-white-disabled.png') no-repeat left top;
  1920. background-size: 100% 100%;
  1921. }
  1922. &-yellow-disabled {
  1923. cursor: pointer;
  1924. background: url('@/assets/jian-yellow-disabled.png') no-repeat left top;
  1925. background-size: 100% 100%;
  1926. }
  1927. }
  1928. &.font-img {
  1929. &-black {
  1930. background: url('@/assets/fontSize-black.png') no-repeat left top;
  1931. background-size: 100% 100%;
  1932. }
  1933. &-yellow {
  1934. background: url('@/assets/fontSize-white.png') no-repeat left top;
  1935. background-size: 100% 100%;
  1936. }
  1937. }
  1938. &.font-jia {
  1939. &-black {
  1940. cursor: pointer;
  1941. background: url('@/assets/jia-black.png') no-repeat left top;
  1942. background-size: 100% 100%;
  1943. }
  1944. &-yellow {
  1945. cursor: pointer;
  1946. background: url('@/assets/jia-white.png') no-repeat left top;
  1947. background-size: 100% 100%;
  1948. }
  1949. &-white-disabled {
  1950. cursor: pointer;
  1951. background: url('@/assets/jia-white-disabled.png') no-repeat left top;
  1952. background-size: 100% 100%;
  1953. }
  1954. &-yellow-disabled {
  1955. cursor: pointer;
  1956. background: url('@/assets/jia-yellow-disabled.png') no-repeat left top;
  1957. background-size: 100% 100%;
  1958. }
  1959. }
  1960. }
  1961. }
  1962. .top-middle {
  1963. display: flex;
  1964. align-items: center;
  1965. justify-content: center;
  1966. .audio-box {
  1967. display: flex;
  1968. align-items: center;
  1969. justify-content: center;
  1970. width: 56px;
  1971. height: 56px;
  1972. background: #fff;
  1973. border: 1px solid rgba(0, 0, 0, 10%);
  1974. border-radius: 40px;
  1975. &-green {
  1976. background: rgba(255, 255, 255, 10%);
  1977. border: 1px solid rgba(0, 0, 0, 10%);
  1978. }
  1979. }
  1980. }
  1981. }
  1982. .op-btn {
  1983. box-sizing: border-box;
  1984. display: flex;
  1985. flex-shrink: 0;
  1986. align-items: center;
  1987. justify-content: center;
  1988. width: 56px;
  1989. height: 56px;
  1990. margin-left: 32px;
  1991. cursor: pointer;
  1992. background: #fff;
  1993. border: 1px solid rgba(0, 0, 0, 10%);
  1994. border-radius: 100%;
  1995. &-green {
  1996. background: rgba(255, 255, 255, 10%);
  1997. border: 1px solid rgba(0, 0, 0, 10%);
  1998. }
  1999. &.close-btn {
  2000. background: #274533;
  2001. border: 1px solid rgba(0, 0, 0, 10%);
  2002. }
  2003. > span {
  2004. width: 24px;
  2005. height: 24px;
  2006. &.close-icon {
  2007. background: url('@/assets/icon/cross-24-normal-black.png') no-repeat left top;
  2008. background-size: 100% 100%;
  2009. &-white {
  2010. background: url('@/assets/icon/cross-24-normal-white.png') no-repeat left top;
  2011. background-size: 100% 100%;
  2012. }
  2013. }
  2014. }
  2015. }
  2016. .repeat-icon {
  2017. background: url('@/assets/icon/Repeat-24-normal-red.png') no-repeat left top;
  2018. background-size: 100% 100%;
  2019. &.disabled {
  2020. background: url('@/assets/icon/Repeat-24-disable-Black.png') no-repeat left top;
  2021. background-size: 100% 100%;
  2022. }
  2023. &-yellow {
  2024. background: url('@/assets/icon/Repeat-24-normal-yellow.png') no-repeat left top;
  2025. background-size: 100% 100%;
  2026. }
  2027. &.auto-icon {
  2028. background: url('@/assets/icon/Auto-24-next-red.png') no-repeat left top;
  2029. background-size: 100% 100%;
  2030. &-yellow {
  2031. background: url('@/assets/icon/Auto-24-next-yellow.png') no-repeat left top;
  2032. background-size: 100% 100%;
  2033. }
  2034. }
  2035. }
  2036. .pinyin-icon {
  2037. background: url('@/assets/icon/pinyin-24-normal-red.png') no-repeat left top;
  2038. background-size: 100% 100%;
  2039. &.disabled {
  2040. background: url('@/assets/icon/pinyin-24-disable-Black.png') no-repeat left top;
  2041. background-size: 100% 100%;
  2042. }
  2043. &-yellow {
  2044. background: url('@/assets/icon/pinyin-24-normal-yellow.png') no-repeat left top;
  2045. background-size: 100% 100%;
  2046. }
  2047. }
  2048. .en-icon {
  2049. background: url('@/assets/icon/EN-24-normal-Red.png') no-repeat left top;
  2050. background-size: 100% 100%;
  2051. &.disabled {
  2052. background: url('@/assets/icon/EN-24-disable-Black.png') no-repeat left top;
  2053. background-size: 100% 100%;
  2054. }
  2055. &-yellow {
  2056. background: url('@/assets/icon/EN-24-normal-yellow.png') no-repeat left top;
  2057. background-size: 100% 100%;
  2058. }
  2059. }
  2060. .coll-icon {
  2061. background: url('@/assets/icon/bookmarkfill-24-normal-red.png') no-repeat left top;
  2062. background-size: 100% 100%;
  2063. &.disabled {
  2064. background: url('@/assets/icon/bookmarkfill-24-disable-Black.png') no-repeat left top;
  2065. background-size: 100% 100%;
  2066. }
  2067. &-yellow {
  2068. background: url('@/assets/icon/bookmarkfill-24-normal-yellow.png') no-repeat left top;
  2069. background-size: 100% 100%;
  2070. }
  2071. }
  2072. .keyboard-icon {
  2073. background: url('@/assets/icon/enter-24-keyboard-red.png') no-repeat left top;
  2074. background-size: 100% 100%;
  2075. &.disabled {
  2076. background: url('@/assets/icon/enter-24-keyboard-disable-Black.png') no-repeat left top;
  2077. background-size: 100% 100%;
  2078. }
  2079. &-yellow {
  2080. background: url('@/assets/icon/enter-24-keyboard-yellow.png') no-repeat left top;
  2081. background-size: 100% 100%;
  2082. }
  2083. }
  2084. &-content {
  2085. box-sizing: border-box;
  2086. display: flex;
  2087. flex: 1;
  2088. align-items: center;
  2089. width: 100%;
  2090. .vc-box {
  2091. padding: 0 8px 0 36px;
  2092. &-right {
  2093. padding: 0 36px 0 8px;
  2094. }
  2095. }
  2096. .vc-left {
  2097. width: 64px;
  2098. height: 64px;
  2099. cursor: pointer;
  2100. &-grey {
  2101. background: url('@/assets/left-grey.png') no-repeat left top;
  2102. background-size: 100% 100%;
  2103. }
  2104. &-black {
  2105. background: url('@/assets/left-black.png') no-repeat left top;
  2106. background-size: 100% 100%;
  2107. }
  2108. &-white {
  2109. background: url('@/assets/left-white.png') no-repeat left top;
  2110. background-size: 100% 100%;
  2111. }
  2112. &.hidden {
  2113. visibility: hidden;
  2114. }
  2115. }
  2116. .vc-right {
  2117. width: 64px;
  2118. height: 64px;
  2119. cursor: pointer;
  2120. &-grey {
  2121. background: url('@/assets/right-grey.png') no-repeat left top;
  2122. background-size: 100% 100%;
  2123. }
  2124. &-black {
  2125. background: url('@/assets/right-black.png') no-repeat left top;
  2126. background-size: 100% 100%;
  2127. }
  2128. &-white {
  2129. background: url('@/assets/right-white.png') no-repeat left top;
  2130. background-size: 100% 100%;
  2131. }
  2132. }
  2133. .vc-main {
  2134. width: fit-content;
  2135. padding: 0 67px;
  2136. margin: 0 auto;
  2137. .enwords {
  2138. padding: 0 3px;
  2139. margin-top: 24px;
  2140. font-family: 'Helvetica';
  2141. font-size: 24px;
  2142. line-height: 32px;
  2143. color: rgba(0, 0, 0, 45%);
  2144. word-break: break-word;
  2145. &-green {
  2146. color: rgba(255, 255, 255, 65%);
  2147. }
  2148. }
  2149. }
  2150. .NNPE-words {
  2151. float: left;
  2152. user-select: none;
  2153. &-box {
  2154. float: left;
  2155. > span {
  2156. display: block;
  2157. &.NNPE-pinyin {
  2158. box-sizing: border-box;
  2159. font-family: 'League';
  2160. font-size: 32px;
  2161. font-weight: normal;
  2162. line-height: 1.25;
  2163. color: rgba(0, 0, 0, 85%);
  2164. &.bottom {
  2165. padding-bottom: 16px;
  2166. }
  2167. &.noFont {
  2168. font-family: initial;
  2169. }
  2170. &.textLeft {
  2171. text-align: left;
  2172. }
  2173. &.font-white {
  2174. color: #fff !important;
  2175. }
  2176. &.wordBlank {
  2177. color: rgba(0, 0, 0, 85%);
  2178. }
  2179. }
  2180. &.NNPE-chs {
  2181. display: flex;
  2182. flex-flow: wrap; // 兼容不是汉字的内容
  2183. font-family: '楷体';
  2184. font-size: 48px;
  2185. line-height: 1.17;
  2186. color: rgba(0, 0, 0, 85%);
  2187. &.bottom {
  2188. padding-bottom: 16px;
  2189. }
  2190. .font-white {
  2191. color: #fff !important;
  2192. }
  2193. .active {
  2194. color: #de4444 !important;
  2195. &-yellow {
  2196. color: #ffc600 !important;
  2197. }
  2198. }
  2199. .wordActive {
  2200. color: #de4444 !important;
  2201. }
  2202. .wordActive-blue {
  2203. color: #ffc600 !important;
  2204. }
  2205. .newActive {
  2206. color: #de4444 !important;
  2207. }
  2208. }
  2209. // &.padding {
  2210. // padding-right: 6px;
  2211. // }
  2212. }
  2213. }
  2214. &.textLeft {
  2215. text-align: left;
  2216. }
  2217. &.textCenter {
  2218. text-align: center;
  2219. }
  2220. &.textRight {
  2221. text-align: right;
  2222. }
  2223. > span {
  2224. display: block;
  2225. &.NNPE-pinyin {
  2226. box-sizing: border-box;
  2227. font-family: 'League';
  2228. font-size: 32px;
  2229. font-weight: normal;
  2230. line-height: 1.25;
  2231. color: rgba(0, 0, 0, 85%);
  2232. &.bottom {
  2233. padding-bottom: 16px;
  2234. }
  2235. &.font-white {
  2236. color: #fff !important;
  2237. }
  2238. &.noFont {
  2239. font-family: initial;
  2240. }
  2241. &.textLeft {
  2242. text-align: left;
  2243. }
  2244. &.wordBlank {
  2245. color: rgba(0, 0, 0, 85%);
  2246. }
  2247. }
  2248. &.NNPE-chs {
  2249. display: flex;
  2250. flex-flow: wrap; // 兼容不是汉字的内容
  2251. font-family: '楷体';
  2252. font-size: 48px;
  2253. line-height: 1.17;
  2254. color: rgba(0, 0, 0, 85%);
  2255. &.bottom {
  2256. padding-bottom: 16px;
  2257. }
  2258. .font-white {
  2259. color: #fff !important;
  2260. }
  2261. .active {
  2262. color: #de4444 !important;
  2263. &-yellow {
  2264. color: #ffc600 !important;
  2265. }
  2266. }
  2267. .wordActive {
  2268. color: #de4444 !important;
  2269. }
  2270. .wordActive-blue {
  2271. color: #ffc600 !important;
  2272. }
  2273. .newActive {
  2274. color: #de4444 !important;
  2275. }
  2276. }
  2277. &.padding {
  2278. padding-right: 3px;
  2279. padding-left: 3px;
  2280. }
  2281. }
  2282. }
  2283. }
  2284. &-bottom {
  2285. box-sizing: border-box;
  2286. display: flex;
  2287. align-items: center;
  2288. justify-content: space-between;
  2289. width: 100%;
  2290. height: 136px;
  2291. padding-right: 40px;
  2292. .voicefull-bottom-show {
  2293. display: flex;
  2294. align-items: center;
  2295. justify-content: space-between;
  2296. width: 100%;
  2297. height: 136px;
  2298. visibility: visible;
  2299. }
  2300. .voicefull-bottom-hidden {
  2301. display: flex;
  2302. align-items: center;
  2303. justify-content: space-between;
  2304. width: 100%;
  2305. height: 136px;
  2306. visibility: hidden;
  2307. }
  2308. .bottom-left {
  2309. display: flex;
  2310. align-items: center;
  2311. justify-content: flex-start;
  2312. &-margin {
  2313. margin-left: 40px;
  2314. }
  2315. .compare-box {
  2316. box-sizing: border-box;
  2317. height: 56px;
  2318. padding: 16px;
  2319. border: 1px solid rgba(0, 0, 0, 10%);
  2320. border-left: 0 solid rgba(0, 0, 0, 10%);
  2321. border-radius: 0 40px 40px 0;
  2322. &-white {
  2323. background: rgba(255, 255, 255, 10%);
  2324. border: 1px solid rgba(0, 0, 0, 10%);
  2325. border-left: 0;
  2326. }
  2327. &-answer {
  2328. border-radius: 40px;
  2329. }
  2330. }
  2331. }
  2332. .page-count {
  2333. box-sizing: border-box;
  2334. min-width: 60px;
  2335. padding: 8px;
  2336. font-family: 'robot';
  2337. font-size: 16px;
  2338. line-height: 24px;
  2339. color: #000;
  2340. text-align: center;
  2341. background: #fff;
  2342. border-radius: 8px;
  2343. &-green {
  2344. color: #fff;
  2345. background: rgba(255, 255, 255, 20%);
  2346. }
  2347. }
  2348. }
  2349. }
  2350. .word-play-audio {
  2351. position: absolute;
  2352. left: -1000px;
  2353. }
  2354. .NNPE-wordDetail {
  2355. position: fixed;
  2356. top: 50%;
  2357. left: 50%;
  2358. z-index: 116;
  2359. max-width: 100%;
  2360. margin-top: -196px;
  2361. overflow: auto;
  2362. // box-shadow: 0 4px 16px rgba(0, 0, 0, 15%);
  2363. // width: 260px;
  2364. // height: 200px;
  2365. // background: #cc0;
  2366. }
  2367. </style>
  2368. <style lang="scss">
  2369. .NPC-Big-Book-preview-green {
  2370. .bg1 {
  2371. .repeat-icon {
  2372. background: url('@/assets/icon/Repeat-24-normal-Green.png') no-repeat left top;
  2373. background-size: 100% 100%;
  2374. }
  2375. .pinyin-icon {
  2376. background: url('@/assets/icon/pinyin-24-normal-green.png') no-repeat left top;
  2377. background-size: 100% 100%;
  2378. }
  2379. .en-icon {
  2380. background: url('@/assets/icon/EN-24-normal-Green.png') no-repeat left top;
  2381. background-size: 100% 100%;
  2382. }
  2383. .coll-icon {
  2384. background: url('@/assets/icon/bookmarkfill-24-normal-green.png') no-repeat left top;
  2385. background-size: 100% 100%;
  2386. }
  2387. }
  2388. }
  2389. .NPC-Big-Book-preview-brown {
  2390. .bg1 {
  2391. .repeat-icon {
  2392. background: url('@/assets/icon/Repeat-24-normal-Brown.png') no-repeat left top;
  2393. background-size: 100% 100%;
  2394. }
  2395. .pinyin-icon {
  2396. background: url('@/assets/icon/pinyin-24-normal-brown.png') no-repeat left top;
  2397. background-size: 100% 100%;
  2398. }
  2399. .en-icon {
  2400. background: url('@/assets/icon/EN-24-normal-Brown.png') no-repeat left top;
  2401. background-size: 100% 100%;
  2402. }
  2403. .coll-icon {
  2404. background: url('@/assets/icon/bookmarkfill-24-normal-brown.png') no-repeat left top;
  2405. background-size: 100% 100%;
  2406. }
  2407. }
  2408. }
  2409. </style>