PracticeModel.vue 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482
  1. <!-- -->
  2. <template>
  3. <div class="NNPE-ArticleView" v-if="articleInfo">
  4. <template
  5. v-if="
  6. resArr &&
  7. resArr.wordsList &&
  8. resArr.wordsList[0] &&
  9. resArr.wordsList[0][0] &&
  10. resArr.wordsList[0][0].hasOwnProperty('pno') &&
  11. resArr.wordsList[0][0].pno === 0
  12. "
  13. >
  14. <h2 :class="['NNPE-words']">
  15. <span
  16. v-for="(itemR, indexR) in resArr.wordsList[0]"
  17. :key="indexR"
  18. :style="{
  19. color: colorObj.titleColor,
  20. fontSize: titleFontsize + 'px',
  21. lineHeight: titleFontsize + 8 + 'px',
  22. marginRight: '10px',
  23. fontWeight: '700',
  24. }"
  25. :class="[
  26. itemR.tokens[9] === '' ? 'marginRight' : '',
  27. itemR.marginRight ? 'marginSingleRight' : '',
  28. ]"
  29. >
  30. <template v-if="itemR.isShow">
  31. <span
  32. class="NNPE-chs"
  33. :class="[
  34. itemR.type,
  35. itemR.tokens[9] === '' ? 'marginRight' : '',
  36. itemR.highIndex ? 'fontWeight' : '',
  37. itemR.marginRight ? 'marginSingleRight' : '',
  38. ]"
  39. >{{ itemR.tokens[2] }}</span
  40. >
  41. <span
  42. class="NNPE-chs NNPE-chs-both"
  43. v-if="
  44. resArr.wordsList[0][indexR + 1] &&
  45. resArr.wordsList[0][indexR + 1].tokens[2] &&
  46. enFhList.indexOf(resArr.wordsList[0][indexR + 1].tokens[2]) > -1
  47. "
  48. :class="[
  49. resArr.wordsList[0][indexR + 1].type,
  50. resArr.wordsList[0][indexR + 1].tokens[8] === ''
  51. ? 'marginLeft'
  52. : '',
  53. resArr.wordsList[0][indexR + 1].highIndex ? 'fontWeight' : '',
  54. resArr.wordsList[0][indexR + 1].marginRight
  55. ? 'marginSingleRight'
  56. : '',
  57. ]"
  58. >{{ resArr.wordsList[0][indexR + 1].tokens[2] }}</span
  59. >
  60. </template>
  61. <!-- {{itemR.tokens[2]}} -->
  62. </span>
  63. </h2>
  64. </template>
  65. <h2 v-else>
  66. <span
  67. :style="{
  68. color: colorObj.titleColor,
  69. fontSize: titleFontsize + 'px',
  70. lineHeight: titleFontsize + 8 + 'px',
  71. marginRight: '10px',
  72. fontWeight: '700',
  73. cursor: 'pointer',
  74. }"
  75. >{{ articleInfo.art_title }}</span
  76. >
  77. </h2>
  78. <h6
  79. class="nnpe-article-author"
  80. :style="{
  81. color: colorObj.sourceColor,
  82. fontSize: '14px',
  83. lineHeight: '22px',
  84. fontWeight: '400',
  85. }"
  86. >
  87. {{
  88. articleInfo.art_author +
  89. " · " +
  90. articleInfo.study_phase_name +
  91. "版 · 第 " +
  92. articleInfo.iss_no +
  93. " 期 · " +
  94. articleInfo.release_date +
  95. " · " +
  96. articleInfo.chn_item +
  97. (articleInfo.page_no_in_pub ? " · P" + articleInfo.page_no_in_pub : "")
  98. }}
  99. </h6>
  100. <div class="audio-box">
  101. <div
  102. class="aduioLine-content aduioLine-box"
  103. v-if="articleInfo.art_sound_url"
  104. :style="{
  105. background: colorObj.audiobg,
  106. borderColor: colorObj.audioBorder,
  107. }"
  108. >
  109. <AudioLine
  110. audioId="artNormalAudio"
  111. :mp3="articleInfo.art_sound_url"
  112. :getCurTime="getCurTime"
  113. ref="audioLine"
  114. :mp3Source="'tts'"
  115. type="audioLine"
  116. :ed="ed"
  117. :showEd="showEd"
  118. @emptyEd="emptyEd"
  119. :colorObj="colorObj"
  120. />
  121. <svg-icon
  122. icon-class="icon-wrapper"
  123. class="wrapper"
  124. @click="fullScreen"
  125. :style="{ color: colorObj.audioBtnColor }"
  126. ></svg-icon>
  127. </div>
  128. </div>
  129. <template v-if="resArr.wordsList && resArr.wordsList.length > 0">
  130. <div class="table-box" :class="['table-box-' + colorObj.type]">
  131. <div
  132. :class="['NNPE-detail']"
  133. v-for="(item, index) in resArr.wordsList"
  134. :key="'detail' + index"
  135. >
  136. <a
  137. class="history-btn"
  138. v-if="
  139. resArr.timeList[index] &&
  140. resArr.timeList[index] &&
  141. curTime >= resArr.timeList[index].s &&
  142. curTime <= resArr.timeList[index].e
  143. "
  144. @click="lookHistory(index)"
  145. >历史记录</a
  146. >
  147. <b
  148. class="para-index"
  149. :style="{
  150. fontSize: wordFontsize + 'px',
  151. color:
  152. resArr.timeList[index] &&
  153. resArr.timeList[index] &&
  154. curTime >= resArr.timeList[index].s &&
  155. curTime <= resArr.timeList[index].e
  156. ? colorObj.type === 'white'
  157. ? '#2F3742'
  158. : colorObj.type === 'darkGreen'
  159. ? '#299772'
  160. : colorObj.type === 'armyGreen'
  161. ? '#30A47D'
  162. : '#5373E7'
  163. : colorObj.type === 'white'
  164. ? '#D0D3D9'
  165. : colorObj.type === 'darkGreen'
  166. ? '#7A8983'
  167. : colorObj.type === 'armyGreen'
  168. ? '#6B7C74'
  169. : '#737781',
  170. }"
  171. >{{ index + 1 }}</b
  172. >
  173. <div class="wordsList-box">
  174. <div class="nnpe-sentence-box">
  175. <div v-for="(pItem, pIndex) in item" :key="'wordsList' + pIndex">
  176. <template v-if="pItem.isShow">
  177. <div
  178. :class="[
  179. 'NNPE-words',
  180. isPlaying &&
  181. resArr.timeList[index] &&
  182. resArr.timeList[index] &&
  183. curTime >= resArr.timeList[index].s &&
  184. curTime <= resArr.timeList[index].e
  185. ? 'sentActive'
  186. : '',
  187. pItem.pno == paraIndex && pItem.sno == sentIndex
  188. ? 'overActive'
  189. : '',
  190. ]"
  191. @click="
  192. handleChangeTime(
  193. resArr.timeList[index] &&
  194. resArr.timeList[index] &&
  195. resArr.timeList[index].s
  196. )
  197. "
  198. @mouseover="handleMouseover(pItem)"
  199. @mouseleave="handleMouseleave"
  200. >
  201. <span
  202. class="NNPE-chs"
  203. :class="[
  204. isPlaying &&
  205. resArr.timeList[index] &&
  206. resArr.timeList[index] &&
  207. resArr.timeList[index].e &&
  208. resArr.timeList[index].tokens &&
  209. resArr.timeList[index].tokens[pItem.wIndex] &&
  210. curTime >=
  211. resArr.timeList[index].tokens[pItem.wIndex].s &&
  212. curTime <= resArr.timeList[index].e
  213. ? 'wordActive'
  214. : '',
  215. pItem.tokens[9] === '' ? 'marginRight' : '',
  216. pItem.marginRight ? 'marginSingleRight' : '',
  217. ]"
  218. :style="{
  219. fontSize: wordFontsize + 'px',
  220. color:
  221. isPlaying &&
  222. resArr.timeList[index] &&
  223. resArr.timeList[index] &&
  224. resArr.timeList[index].tokens[pItem.wIndex] &&
  225. curTime >=
  226. resArr.timeList[index].tokens[pItem.wIndex].s &&
  227. curTime <=
  228. resArr.timeList[index].tokens[pItem.wIndex].e
  229. ? colorObj.statisticValue
  230. : resArr.timeList[index] &&
  231. resArr.timeList[index] &&
  232. curTime >= resArr.timeList[index].s &&
  233. curTime <= resArr.timeList[index].e
  234. ? colorObj.contentColor
  235. : colorObj.type === 'white'
  236. ? '#D0D3D9'
  237. : colorObj.type === 'darkGreen'
  238. ? '#7A8983'
  239. : colorObj.type === 'darkBlue'
  240. ? '#737781'
  241. : '#6B7C74',
  242. }"
  243. >{{ pItem.tokens[2] }}</span
  244. >
  245. <span
  246. class="NNPE-chs NNPE-chs-both"
  247. v-if="
  248. item[pIndex + 1] &&
  249. item[pIndex + 1].tokens[2] &&
  250. enFhList.indexOf(item[pIndex + 1].tokens[2]) > -1
  251. "
  252. :class="[
  253. isPlaying &&
  254. resArr.timeList[index] &&
  255. resArr.timeList[index] &&
  256. resArr.timeList[index].tokens[pItem.wIndex] &&
  257. curTime >=
  258. resArr.timeList[index].tokens[pItem.wIndex].s &&
  259. curTime <= resArr.timeList[index].e
  260. ? 'wordActive'
  261. : '',
  262. item[pIndex + 1].tokens[8] === '' ? 'marginLeft' : '',
  263. item[pIndex + 1].marginRight ? 'marginSingleRight' : '',
  264. ]"
  265. :style="{
  266. fontSize: wordFontsize + 'px',
  267. color:
  268. isPlaying &&
  269. resArr.timeList[index] &&
  270. resArr.timeList[index] &&
  271. resArr.timeList[index].tokens[pItem.wIndex] &&
  272. curTime >=
  273. resArr.timeList[index].tokens[pItem.wIndex].s &&
  274. curTime <=
  275. resArr.timeList[index].tokens[pItem.wIndex].e
  276. ? colorObj.statisticValue
  277. : resArr.timeList[index] &&
  278. resArr.timeList[index] &&
  279. curTime >= resArr.timeList[index].s &&
  280. curTime <= resArr.timeList[index].e
  281. ? colorObj.contentColor
  282. : colorObj.type === 'white'
  283. ? '#D0D3D9'
  284. : colorObj.type === 'darkGreen'
  285. ? '#7A8983'
  286. : colorObj.type === 'darkBlue'
  287. ? '#737781'
  288. : '#6B7C74',
  289. }"
  290. >{{ item[pIndex + 1].tokens[2] }}</span
  291. >
  292. </div>
  293. </template>
  294. </div>
  295. </div>
  296. </div>
  297. <div
  298. class="score-box"
  299. v-if="
  300. activeSentId === articleInfo.art_corpus_data.sentList[index].id &&
  301. score !== null
  302. "
  303. >
  304. <div class="score">
  305. <span>朗读评分</span>
  306. <b :style="wordStyle()">{{ score }}</b>
  307. </div>
  308. <a @click="lookMoreInfo">查看详细</a>
  309. </div>
  310. </div>
  311. <div class="operate-box" :style="{ background: colorObj.contentBg }">
  312. <div
  313. class="operate-box-inner"
  314. :style="{ background: colorObj.contentInnerBg }"
  315. >
  316. <div class="operate-box-inner-content">
  317. <div class="operate-item" @click="changePlaySent('-')">
  318. <svg-icon
  319. icon-class="Go-start"
  320. :style="{
  321. color:
  322. colorObj.type === 'white' || colorObj.type === 'darkGreen'
  323. ? '#000'
  324. : '#fff',
  325. }"
  326. ></svg-icon>
  327. <span
  328. :style="{
  329. color: colorObj.type === 'armyGreen' ? '#7C8983' : '',
  330. }"
  331. >上一句</span
  332. >
  333. </div>
  334. <div class="operate-item" @click="compare">
  335. <svg-icon
  336. icon-class="Type-drive"
  337. :style="{
  338. color:
  339. colorObj.type === 'white' || colorObj.type === 'darkGreen'
  340. ? '#000'
  341. : '#fff',
  342. }"
  343. ></svg-icon>
  344. <span
  345. :style="{
  346. color: colorObj.type === 'armyGreen' ? '#7C8983' : '',
  347. }"
  348. >听对比</span
  349. >
  350. </div>
  351. <div class="operate-item">
  352. <b
  353. class="luyin-btn"
  354. v-if="!microphoneStatus"
  355. @click="microphone"
  356. >
  357. <svg-icon
  358. icon-class="Voice-luyin"
  359. :style="{ color: '#fff' }"
  360. ></svg-icon>
  361. </b>
  362. <img
  363. class="luyin-gif"
  364. @click="microphone"
  365. v-else
  366. src="../../../assets/voice-gif.png"
  367. />
  368. <span
  369. v-if="microphoneStatus"
  370. class="record-time"
  371. :style="{ color: '#F2555A', fontWeight: '600' }"
  372. >{{ handleDateTime(recordtime) }}</span
  373. >
  374. <span
  375. v-else
  376. :style="{
  377. color: colorObj.type === 'armyGreen' ? '#7C8983' : '',
  378. }"
  379. >点击录音</span
  380. >
  381. </div>
  382. <div
  383. class="operate-item"
  384. @click="
  385. playmicrophone(
  386. selectIndex || selectIndex == 0
  387. ? recordList[selectIndex].toltime
  388. : ''
  389. )
  390. "
  391. >
  392. <svg-icon
  393. icon-class="Headphone-sound"
  394. :style="{
  395. color:
  396. colorObj.type === 'white' || colorObj.type === 'darkGreen'
  397. ? '#000'
  398. : '#fff',
  399. }"
  400. ></svg-icon>
  401. <span
  402. :style="{
  403. color: colorObj.type === 'armyGreen' ? '#7C8983' : '',
  404. }"
  405. >我读的</span
  406. >
  407. </div>
  408. <div class="operate-item" @click="changePlaySent('+')">
  409. <svg-icon
  410. icon-class="Go-end"
  411. :style="{
  412. color:
  413. colorObj.type === 'white' || colorObj.type === 'darkGreen'
  414. ? '#000'
  415. : '#fff',
  416. }"
  417. ></svg-icon>
  418. <span
  419. :style="{
  420. color: colorObj.type === 'armyGreen' ? '#7C8983' : '',
  421. }"
  422. >下一句</span
  423. >
  424. </div>
  425. </div>
  426. </div>
  427. </div>
  428. </div>
  429. </template>
  430. <!-- <img src="../../../assets/article-img.png" style="max-width:100%;margin:24px 0;" /> -->
  431. <div class="clear-box">
  432. <h5>词汇标记设置</h5>
  433. <div class="item">
  434. <span>跟读</span>
  435. <el-switch
  436. v-model="repeatAfter"
  437. active-color="#175DFF"
  438. inactive-color="#D0D3D9"
  439. key="sent-repeatAfter"
  440. >
  441. </el-switch>
  442. </div>
  443. <div class="item">
  444. <span>单句模式</span>
  445. <el-switch
  446. v-model="singleModel"
  447. active-color="#175DFF"
  448. inactive-color="#D0D3D9"
  449. key="sent-singleModel"
  450. @change="mutualExclusive('singleModel', 'autoNextSent')"
  451. >
  452. </el-switch>
  453. </div>
  454. <div class="item">
  455. <span>自动下一句</span>
  456. <el-switch
  457. v-model="autoNextSent"
  458. active-color="#175DFF"
  459. inactive-color="#D0D3D9"
  460. key="sent-autoNextSent"
  461. @change="mutualExclusive('autoNextSent', 'singleModel')"
  462. >
  463. </el-switch>
  464. </div>
  465. </div>
  466. <el-dialog
  467. :visible.sync="historyFlag"
  468. :show-close="false"
  469. :close-on-click-modal="false"
  470. width="680px"
  471. :modal="false"
  472. class="login-dialog"
  473. v-if="historyFlag"
  474. >
  475. <history-record-list
  476. :list="historySentRecordList"
  477. :sentData="resArr.wordsList[playSentIndex]"
  478. :timeData="resArr.timeList[playSentIndex]"
  479. :mp3Url="articleInfo.art_sound_url"
  480. @closeHistory="closeHistory"
  481. :colorObj="colorObj"
  482. :wordFontsize="wordFontsize"
  483. @handleChangeTime="handleChangeTime"
  484. @returnCurrentTime="returnCurrentTime"
  485. :parentCurtimt="curTime"
  486. :parentPlay="Playing"
  487. v-loading="historyLoading"
  488. ></history-record-list>
  489. </el-dialog>
  490. <div class="voice-full-screen" :id="'screen-' + mathNum">
  491. <Voicefullscreen
  492. v-if="isFull"
  493. :curQue="articleInfo"
  494. :likeWord="likeWord"
  495. :sentIndex="playSentIndex === -1 ? 0 : playSentIndex"
  496. :mp3="articleInfo.art_sound_url"
  497. :likeSentencelist="likeSentencelist"
  498. @exitFullscreen="exitFullscreen"
  499. @changeIsFull="changeIsFull"
  500. />
  501. </div>
  502. <el-dialog
  503. :visible.sync="recordsScoreInfoFlag"
  504. :show-close="false"
  505. :close-on-click-modal="false"
  506. width="680px"
  507. :modal="false"
  508. class="login-dialog"
  509. v-if="recordsScoreInfoFlag"
  510. >
  511. <RecordsScoreInfo
  512. :sentData="resArr.wordsList[playSentIndex]"
  513. :scoreAllInfo="scoreInfo"
  514. @closeScoreInfo="closeScoreInfo"
  515. :wordFontsize="wordFontsize"
  516. ></RecordsScoreInfo>
  517. </el-dialog>
  518. </div>
  519. </template>
  520. <script>
  521. import AudioLine from "@/components/common/AudioLine.vue";
  522. import HistoryRecordList from "./HistoryRecordList.vue";
  523. import Recorder from "js-audio-recorder"; // 录音插件
  524. import { getLogin } from "@/api/ajax";
  525. import Voicefullscreen from "./Voicefullscreen.vue";
  526. import RecordsScoreInfo from "./RecordsScoreInfo.vue";
  527. export default {
  528. name: "ArticleView",
  529. props: [
  530. "titleFontsize",
  531. "wordFontsize",
  532. "colorObj",
  533. "articleType",
  534. "articleInfo",
  535. "likeSentencelist",
  536. "likeWord",
  537. "articleImg",
  538. ],
  539. components: {
  540. AudioLine,
  541. HistoryRecordList,
  542. Voicefullscreen,
  543. RecordsScoreInfo,
  544. },
  545. data() {
  546. return {
  547. resArr: [],
  548. curTime: 0, //单位s
  549. enFhList: [
  550. ",",
  551. ".",
  552. ";",
  553. "?",
  554. "!",
  555. ":",
  556. ">",
  557. "<",
  558. "'",
  559. "’",
  560. "n't",
  561. "n’t",
  562. "n’ts",
  563. "n‘t",
  564. "'t",
  565. "’t",
  566. "‘t",
  567. "'s",
  568. "’s",
  569. "‘s",
  570. "'m",
  571. "’m",
  572. "‘m",
  573. "'re",
  574. "’re",
  575. "‘re",
  576. "'d",
  577. "’d",
  578. "‘d",
  579. "'ve",
  580. "’ve",
  581. "‘ve",
  582. ")",
  583. "'ll",
  584. "’ll",
  585. "‘ll",
  586. "”",
  587. ],
  588. paraIndex: -1, //段落索引
  589. sentIndex: -1, // 句子索引
  590. repeatAfter: false,
  591. singleModel: false,
  592. autoNextSent: false,
  593. recorder: new Recorder({
  594. sampleBits: 16, // 采样位数,支持 8 或 16,默认是16
  595. sampleRate: 16000, // 采样率,支持 11025、16000、22050、24000、44100、48000,根据浏览器默认值,我的chrome是48000
  596. numChannels: 1, // 声道,支持 1 或 2, 默认是1
  597. }),
  598. microphoneStatus: false,
  599. hasMicro: "", // 录音后的样式class
  600. wavblob: null,
  601. audio: new window.Audio(),
  602. audioc: new window.Audio(), // 对比
  603. recordList: [], // 录音文件数组
  604. recordtime: 0, // 录音时长
  605. timer: null, // 计时器
  606. recordFile: 1, // 录音文件名
  607. selectIndex: null, // 选中的录音索引
  608. oldIndex: null, // 存储播放录音索引
  609. playtime: 0, // 播放时间
  610. isPlayings: false,
  611. playSentIndex: -1, // 播放的句子索引
  612. historyFlag: false, // 历史记录弹窗
  613. historySentRecordList: [], // 单句历史录音list
  614. ed: undefined,
  615. showEd: false, //是否看ed的值
  616. historyLoading: false,
  617. timeC: null,
  618. isCompare: false,
  619. isFull: false,
  620. mathNum: Math.random().toString(36).substr(2),
  621. score: null,
  622. activeSentId: "",
  623. recordsScoreInfoFlag: false,
  624. scoreInfo: null,
  625. };
  626. },
  627. computed: {
  628. isPlaying: function () {
  629. let playing = false;
  630. if (this.$refs.audioLine) {
  631. playing = this.$refs.audioLine.audio.isPlaying;
  632. }
  633. return playing;
  634. },
  635. Playing: function () {
  636. let playing = false;
  637. if (this.$refs.audioLine) {
  638. playing = this.$refs.audioLine.audio.playing;
  639. }
  640. return playing;
  641. },
  642. wordStyle() {
  643. return function () {
  644. let color = "";
  645. if (this.score < 60) {
  646. color = "#F2555A";
  647. } else if (60 <= this.score && this.score < 80) {
  648. color = "#929CA8";
  649. } else if (80 <= this.score && this.score < 90) {
  650. color = "#0081F1";
  651. } else if (this.score >= 90) {
  652. color = "#1CCDA7";
  653. }
  654. return {
  655. color: color,
  656. };
  657. };
  658. },
  659. },
  660. watch: {},
  661. //方法集合
  662. methods: {
  663. changePlaySent(type) {
  664. this.audio.pause();
  665. this.audioc.pause();
  666. if (type === "-") {
  667. if (this.playSentIndex > 0) {
  668. this.playSentIndex--;
  669. } else {
  670. this.playSentIndex = 0;
  671. }
  672. } else {
  673. if (this.playSentIndex < this.resArr.wordsList.length - 1) {
  674. this.playSentIndex++;
  675. } else {
  676. this.playSentIndex = 0;
  677. }
  678. }
  679. this.handleChangeTime(
  680. this.resArr.timeList[this.playSentIndex]
  681. ? this.resArr.timeList[this.playSentIndex].s
  682. : null
  683. );
  684. },
  685. getCurTime(curTime) {
  686. if (this.isCompare) {
  687. let time = curTime * 1000;
  688. if (
  689. time >= this.resArr.timeList[this.playSentIndex].e ||
  690. time <= this.resArr.timeList[this.playSentIndex].s
  691. ) {
  692. // this.curTime = this.resArr.timeList[this.playSentIndex].s;
  693. // this.$refs.audioLine.onTimeupdateTime(_this.currSent.bg / 1000, true);
  694. } else {
  695. this.curTime = curTime * 1000;
  696. }
  697. } else if (
  698. this.singleModel &&
  699. this.playSentIndex > -1 &&
  700. !this.repeatAfter
  701. ) {
  702. let time = curTime * 1000;
  703. if (
  704. time >= this.resArr.timeList[this.playSentIndex].e ||
  705. time <= this.resArr.timeList[this.playSentIndex].s
  706. ) {
  707. // this.curTime = this.resArr.timeList[this.playSentIndex].s;
  708. // this.$refs.audioLine.onTimeupdateTime(
  709. // this.resArr.timeList[this.playSentIndex].s / 1000,
  710. // true
  711. // );
  712. this.$refs.audioLine.StopAudio();
  713. } else {
  714. this.curTime = curTime * 1000;
  715. }
  716. } else if (
  717. (this.singleModel || this.autoNextSent) &&
  718. this.playSentIndex > -1 &&
  719. this.repeatAfter
  720. ) {
  721. let time = curTime * 1000;
  722. this.curTime = curTime * 1000;
  723. // for(let i=0; i<this.resArr.timeList.length;i++){
  724. // if(this.curTime>this.resArr.timeList[i].s&&this.curTime<=this.resArr.timeList[i].e){
  725. // this.playSentIndex = i
  726. // break
  727. // }
  728. // }
  729. // if (time >= this.resArr.timeList[this.playSentIndex].s || time <= this.resArr.timeList[this.playSentIndex].e) {
  730. // this.curTime = this.resArr.timeList[this.playSentIndex].s;
  731. if (this.playSentIndex === 0)
  732. this.ed = this.resArr.timeList[this.playSentIndex].e;
  733. this.showEd = true;
  734. // this.$refs.audioLine.onTimeupdateTime(this.resArr.timeList[this.playSentIndex].s / 1000, true);
  735. // }
  736. } else {
  737. this.curTime = curTime * 1000;
  738. for (let i = 0; i < this.resArr.timeList.length; i++) {
  739. if (
  740. this.curTime >= this.resArr.timeList[i].s &&
  741. this.curTime < this.resArr.timeList[i].e
  742. ) {
  743. this.playSentIndex = i;
  744. break;
  745. }
  746. }
  747. }
  748. },
  749. returnCurrentTime() {
  750. return this.curTime;
  751. },
  752. handleData() {
  753. let resArr = {
  754. wordsList: [],
  755. timeList: [],
  756. };
  757. let articleInfo = JSON.parse(JSON.stringify(this.articleInfo));
  758. articleInfo.art_corpus_data.sentList.forEach((item, index) => {
  759. let wordlist = [];
  760. item.tokens.forEach((items, indexs) => {
  761. let obj = {
  762. sent_id: item.id,
  763. sno: item.sno - 1,
  764. pno: item.pno,
  765. text: item.text,
  766. tokens: items,
  767. wIndex: indexs,
  768. isShow: this.enFhList.indexOf(items[2]) == -1,
  769. marginRight: indexs === item.tokens.length - 1,
  770. };
  771. wordlist.push(obj);
  772. });
  773. resArr.wordsList.push(wordlist);
  774. if (
  775. articleInfo.art_sound_srt_data &&
  776. articleInfo.art_sound_srt_data.sents &&
  777. articleInfo.art_sound_srt_data.sents[index]
  778. ) {
  779. resArr.timeList.push(articleInfo.art_sound_srt_data.sents[index]);
  780. }
  781. });
  782. this.resArr = resArr;
  783. },
  784. handleChangeTime(time, ed, flag, type) {
  785. this.audio.pause();
  786. this.audioc.pause();
  787. if (flag) {
  788. this.$refs.audioLine.PlayAudio();
  789. } else {
  790. if (time >= 0) {
  791. this.curTime = time;
  792. for (let i = 0; i < this.resArr.timeList.length; i++) {
  793. if (
  794. this.curTime >= this.resArr.timeList[i].s &&
  795. this.curTime < this.resArr.timeList[i].e
  796. ) {
  797. this.playSentIndex = i;
  798. break;
  799. }
  800. }
  801. if (ed) {
  802. this.ed = ed;
  803. } else if (
  804. (this.singleModel || this.autoNextSent) &&
  805. this.playSentIndex > -1 &&
  806. this.repeatAfter
  807. ) {
  808. this.ed = this.resArr.timeList[this.playSentIndex].e;
  809. } else {
  810. this.ed = undefined;
  811. }
  812. if (this.$refs.audioLine)
  813. this.$refs.audioLine.onTimeupdateTime(time / 1000, true);
  814. }
  815. }
  816. },
  817. emptyEd(flag) {
  818. this.ed = undefined;
  819. if (flag) {
  820. this.showEd = false;
  821. if (!this.microphoneStatus) {
  822. // this.microphone();
  823. }
  824. }
  825. },
  826. //经过每个词,高亮句子
  827. handleMouseover(pItem) {
  828. this.paraIndex = pItem.pno;
  829. this.sentIndex = pItem.sno;
  830. },
  831. handleMouseleave() {
  832. this.paraIndex = -1;
  833. this.sentIndex = -1;
  834. },
  835. mutualExclusive(val, val1) {
  836. if (this[val]) {
  837. this[val1] = false;
  838. }
  839. },
  840. // 开始录音
  841. microphone() {
  842. let _this = this;
  843. this.score = null;
  844. this.scoreInfo = null;
  845. this.audio.pause();
  846. this.audioc.pause();
  847. if (_this.$refs.audioLine && _this.$refs.audioLine.audio.playing) {
  848. _this.$refs.audioLine.PlayAudio();
  849. }
  850. if (!this.microphoneStatus) {
  851. _this.hasMicro = "";
  852. // _this.$emit("getWavblob", null);
  853. // this.$emit("getSelectData", { type: "" });
  854. // 开始录音
  855. this.recorder.start();
  856. this.microphoneStatus = true;
  857. this.recordtime = 0;
  858. this.isPlayings = false;
  859. clearInterval(_this.timer);
  860. _this.timer = setInterval(() => {
  861. _this.recordtime++;
  862. }, 1000);
  863. this.$emit("handleParentPlay");
  864. let obj = {
  865. name: _this.fileName
  866. ? _this.fileName + _this.recordFile
  867. : "Recording " + _this.recordFile,
  868. id: _this.recordFile + Math.round(Math.random() * 10),
  869. };
  870. if (this.selectData) obj.selectData = this.selectData;
  871. _this.recordList.push(obj);
  872. _this.recordFile++;
  873. _this.selectIndex = _this.recordList.length - 1;
  874. } else {
  875. this.hasMicro = "normal";
  876. this.recorder.stop();
  877. clearInterval(_this.timer);
  878. let toltime = Math.ceil(this.recorder.duration); // 录音总时长
  879. let fileSize = this.recorder.fileSize; // 录音总大小
  880. // 录音结束,获取取录音数据
  881. let wav = this.recorder.getWAVBlob(); // 获取 WAV 数据
  882. // this.wavblob = wav;
  883. this.microphoneStatus = false;
  884. let reader = new window.FileReader();
  885. reader.readAsDataURL(wav);
  886. reader.onloadend = () => {
  887. _this.recordList[_this.selectIndex].wavData = reader.result;
  888. _this.recordList[_this.selectIndex].toltime = Math.floor(toltime);
  889. _this.recordList[_this.selectIndex].fileSize = fileSize;
  890. _this.wavblob = _this.recordList[_this.selectIndex].wavData;
  891. _this.$emit("getWavblob", _this.wavblob);
  892. _this.$emit(
  893. "handleWav",
  894. JSON.parse(JSON.stringify(_this.recordList)),
  895. _this.tmIndex
  896. );
  897. if (this.recordList[this.selectIndex].selectData) {
  898. this.$emit(
  899. "getSelectData",
  900. this.recordList[this.selectIndex].selectData
  901. );
  902. }
  903. this.addRecord(reader.result, toltime);
  904. };
  905. }
  906. _this.$emit(
  907. "getRerordStatus",
  908. !_this.microphoneStatus && _this.recordList.length > 0
  909. );
  910. _this.$emit("getMicrophoneStatus", _this.microphoneStatus);
  911. },
  912. playmicrophone(totalTimes) {
  913. this.audioc.pause();
  914. if (this.hasMicro) {
  915. this.isPlayings = true;
  916. if (this.selectIndex || this.selectIndex == 0) {
  917. let totalTime = totalTimes;
  918. let _this = this;
  919. if (!this.audio.paused) {
  920. this.audio.pause();
  921. clearInterval(_this.timer);
  922. } else if (this.audio.paused && _this.oldIndex == _this.selectIndex) {
  923. _this.audio.play();
  924. if (_this.recordtime == 0) {
  925. _this.recordtime = totalTimes;
  926. _this.playtime = 0;
  927. }
  928. _this.timer = setInterval(() => {
  929. if (_this.playtime < totalTime) {
  930. _this.playtime++;
  931. _this.recordtime = totalTime - _this.playtime;
  932. } else {
  933. clearInterval(_this.timer);
  934. }
  935. }, 1000);
  936. } else {
  937. _this.audio.pause();
  938. _this.audio.load();
  939. _this.audio.src = _this.wavblob;
  940. _this.oldIndex = _this.selectIndex;
  941. _this.audio.play();
  942. _this.playtime = 0;
  943. _this.recordtime = totalTime;
  944. clearInterval(_this.timer);
  945. _this.timer = setInterval(() => {
  946. if (_this.playtime < totalTime) {
  947. _this.playtime++;
  948. _this.recordtime = totalTime - _this.playtime;
  949. } else {
  950. clearInterval(_this.timer);
  951. }
  952. }, 1000);
  953. }
  954. }
  955. }
  956. },
  957. // 格式化录音时长
  958. handleDateTime(time) {
  959. if (parseInt(time / 60) < 10) {
  960. time =
  961. ("0" + parseInt(time / 60)).substring(
  962. ("0" + parseInt(time / 60)).length - 2
  963. ) +
  964. ":" +
  965. ("0" + (time % 60)).substring(("0" + (time % 60)).length - 2);
  966. } else {
  967. time =
  968. parseInt(time / 60) +
  969. ":" +
  970. ("0" + (time % 60)).substring(("0" + (time % 60)).length - 2);
  971. }
  972. return time;
  973. },
  974. // 点击历史记录按钮
  975. lookHistory(index) {
  976. this.historyFlag = true;
  977. this.historyLoading = true;
  978. this.audio.pause();
  979. this.audioc.pause();
  980. if (this.microphoneStatus) {
  981. this.microphone();
  982. }
  983. if (this.$refs.audioLine.audio.playing) {
  984. this.$refs.audioLine.PlayAudio();
  985. }
  986. this.playSentIndex = index;
  987. let MethodName = "/PaperServer/Client/UserSentRec/RecListInUserSent";
  988. let data = {
  989. sent_id: this.articleInfo.art_corpus_data.sentList[index].id,
  990. got_rec_data_flag: false,
  991. };
  992. getLogin(MethodName, data)
  993. .then((res) => {
  994. if (res.status === 1) {
  995. this.historySentRecordList = res.data.all;
  996. this.historyLoading = false;
  997. }
  998. })
  999. .catch(() => {
  1000. this.historyLoading = false;
  1001. });
  1002. },
  1003. closeHistory() {
  1004. this.historyFlag = false;
  1005. },
  1006. // 保存录音
  1007. addRecord(wav, toltime) {
  1008. if (this.playSentIndex === -1) {
  1009. return;
  1010. }
  1011. this.activeSentId =
  1012. this.articleInfo.art_corpus_data.sentList[this.playSentIndex].id;
  1013. let MethodName = "/PaperServer/Client/UserSentRec/AddUserSentRec";
  1014. let data = {
  1015. sent_id:
  1016. this.articleInfo.art_corpus_data.sentList[this.playSentIndex].id,
  1017. rec_sound_data: wav,
  1018. toltime: toltime,
  1019. };
  1020. getLogin(MethodName, data).then((res) => {
  1021. this.score = JSON.parse(
  1022. res.data.current.rec_rate_info
  1023. ).score_result.average_score;
  1024. this.scoreInfo = res.data;
  1025. if (this.repeatAfter) {
  1026. if (
  1027. this.autoNextSent &&
  1028. this.resArr.timeList[this.playSentIndex + 1]
  1029. ) {
  1030. // this.playSentIndex = this.playSentIndex+1
  1031. this.ed = this.resArr.timeList[this.playSentIndex + 1].e;
  1032. this.handleChangeTime(
  1033. this.resArr.timeList[this.playSentIndex + 1].s
  1034. );
  1035. }
  1036. }
  1037. });
  1038. },
  1039. // 对比
  1040. compare() {
  1041. let _this = this;
  1042. _this.isCompare = true;
  1043. // let curTime = _this.resArr.timeList[_this.playSentIndex].s
  1044. // for(let i=0; i<this.resArr.timeList.length;i++){
  1045. // if(curTime>this.resArr.timeList[i].s&&curTime<=this.resArr.timeList[i].e){
  1046. // this.playSentIndex = i
  1047. // break
  1048. // }
  1049. // }
  1050. let playSentIndex = JSON.parse(JSON.stringify(_this.playSentIndex));
  1051. if (playSentIndex === -1) {
  1052. this.$message.warning("请先选择要对比的句子");
  1053. return;
  1054. }
  1055. if (!this.wavblob) {
  1056. this.$message.warning("请先录音");
  1057. return;
  1058. }
  1059. this.audio.pause();
  1060. if (!this.audioc.paused) {
  1061. this.audioc.pause();
  1062. } else {
  1063. _this.audioc.pause();
  1064. _this.audioc.load();
  1065. if (_this.resArr.timeList[playSentIndex]) {
  1066. _this.handleChangeTime(
  1067. _this.resArr.timeList[playSentIndex].s,
  1068. _this.resArr.timeList[playSentIndex].e
  1069. );
  1070. }
  1071. _this.timeC = setInterval(() => {
  1072. if (_this.curTime >= _this.resArr.timeList[playSentIndex].e - 250) {
  1073. _this.curTime = _this.resArr.timeList[playSentIndex].s;
  1074. clearInterval(_this.timeC);
  1075. _this.playWavdata();
  1076. }
  1077. }, 500);
  1078. }
  1079. },
  1080. playWavdata() {
  1081. let _this = this;
  1082. _this.audioc.src = _this.wavblob;
  1083. _this.audioc.play();
  1084. _this.audioc.addEventListener("ended", function () {
  1085. _this.isCompare = false;
  1086. });
  1087. },
  1088. pauseAudio() {
  1089. let audio = document.getElementsByTagName("audio");
  1090. audio.forEach((item) => {
  1091. item.pause();
  1092. });
  1093. },
  1094. pauseVideo() {
  1095. let video = document.getElementsByTagName("video");
  1096. video.forEach((item) => {
  1097. item.pause();
  1098. });
  1099. },
  1100. //语音全屏
  1101. fullScreen() {
  1102. this.pauseAudio();
  1103. this.pauseVideo();
  1104. this.isFull = true;
  1105. this.goFullscreen();
  1106. },
  1107. goFullscreen() {
  1108. let id = "screen-" + this.mathNum;
  1109. var element = document.getElementById(id);
  1110. if (element.requestFullscreen) {
  1111. element.requestFullscreen();
  1112. } else if (element.msRequestFullscreen) {
  1113. element.msRequestFullscreen();
  1114. } else if (element.mozRequestFullScreen) {
  1115. element.mozRequestFullScreen();
  1116. } else if (element.webkitRequestFullscreen) {
  1117. element.webkitRequestFullscreen();
  1118. }
  1119. },
  1120. exitFullscreen() {
  1121. this.isFull = false;
  1122. if (document.exitFullscreen) {
  1123. document.exitFullscreen();
  1124. } else if (document.msExitFullscreen) {
  1125. document.msExitFullscreen();
  1126. } else if (document.mozCancelFullScreen) {
  1127. document.mozCancelFullScreen();
  1128. } else if (document.webkitExitFullscreen) {
  1129. document.webkitExitFullscreen();
  1130. }
  1131. },
  1132. changeIsFull() {
  1133. this.isFull = false;
  1134. },
  1135. lookMoreInfo() {
  1136. this.recordsScoreInfoFlag = true;
  1137. },
  1138. closeScoreInfo() {
  1139. this.recordsScoreInfoFlag = false;
  1140. },
  1141. },
  1142. //生命周期 - 创建完成(可以访问当前this实例)
  1143. created() {},
  1144. //生命周期 - 挂载完成(可以访问DOM元素)
  1145. mounted() {
  1146. if (this.articleInfo) {
  1147. this.handleData();
  1148. }
  1149. },
  1150. beforeCreate() {}, //生命周期 - 创建之前
  1151. beforeMount() {}, //生命周期 - 挂载之前
  1152. beforeUpdate() {}, //生命周期 - 更新之前
  1153. updated() {}, //生命周期 - 更新之后
  1154. beforeDestroy() {
  1155. clearInterval(this.timeC);
  1156. }, //生命周期 - 销毁之前
  1157. destroyed() {}, //生命周期 - 销毁完成
  1158. activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发
  1159. };
  1160. </script>
  1161. <style lang="scss" scoped>
  1162. //@import url(); 引入公共css类
  1163. .NNPE-ArticleView {
  1164. width: 100%;
  1165. .nnpe-article-author {
  1166. margin: 24px 0;
  1167. }
  1168. h2 {
  1169. display: flex;
  1170. flex-flow: wrap;
  1171. &.sentActive {
  1172. background: rgba(24, 144, 255, 0.1);
  1173. }
  1174. &.overActive {
  1175. background: rgba(0, 0, 0, 0.06);
  1176. }
  1177. .wordActive {
  1178. color: #175dff;
  1179. }
  1180. }
  1181. .table-box {
  1182. padding-top: 20px;
  1183. padding-bottom: 64px;
  1184. // background: #f7f7f7;
  1185. // border-top: 1px solid rgba(0, 0, 0, 0.1);
  1186. :last-child {
  1187. :last-child.wordsList-box {
  1188. padding-bottom: 40px;
  1189. }
  1190. }
  1191. .wordsList-box {
  1192. flex: 1;
  1193. padding: 20px 0;
  1194. .nnpe-sentence-box {
  1195. display: flex;
  1196. flex-flow: wrap;
  1197. }
  1198. > img {
  1199. max-width: 50%;
  1200. display: block;
  1201. padding: 16px 0;
  1202. margin: 0 auto;
  1203. }
  1204. }
  1205. }
  1206. .NNPE-detail {
  1207. clear: both;
  1208. // overflow: hidden;
  1209. display: flex;
  1210. position: relative;
  1211. .history-btn {
  1212. position: absolute;
  1213. left: -110px;
  1214. top: 50%;
  1215. margin-top: -16px;
  1216. z-index: 1;
  1217. padding: 5px 16px;
  1218. border-radius: 2px;
  1219. background: #f2f3f5;
  1220. color: #4e5969;
  1221. font-size: 14px;
  1222. line-height: 22px;
  1223. cursor: pointer;
  1224. }
  1225. .score-box {
  1226. position: absolute;
  1227. right: -110px;
  1228. top: 50%;
  1229. margin-top: -55px;
  1230. z-index: 1;
  1231. padding: 8px;
  1232. border-radius: 4px;
  1233. background: #f2f3f5;
  1234. color: #4e5969;
  1235. font-size: 14px;
  1236. line-height: 22px;
  1237. border: 1px solid rgba(0, 0, 0, 0.08);
  1238. width: 96px;
  1239. text-align: center;
  1240. .score {
  1241. border-radius: 4px;
  1242. background: #fff;
  1243. text-align: center;
  1244. padding: 8px 12px;
  1245. color: #929ca8;
  1246. font-size: 12px;
  1247. font-weight: 400;
  1248. line-height: 20px;
  1249. b {
  1250. font-size: 20px;
  1251. line-height: 28px;
  1252. }
  1253. }
  1254. a {
  1255. color: #929ca8;
  1256. font-size: 14px;
  1257. line-height: 22px;
  1258. margin-top: 8px;
  1259. }
  1260. }
  1261. .para-index {
  1262. color: #d0d3d9;
  1263. font-size: 18px;
  1264. font-weight: 700;
  1265. line-height: 26px;
  1266. padding-top: 20px;
  1267. width: 40px;
  1268. flex-shrink: 0;
  1269. &-active {
  1270. color: #2f3742;
  1271. }
  1272. }
  1273. .NNPE-words {
  1274. float: left;
  1275. padding: 0;
  1276. &.noPadding {
  1277. padding: 0;
  1278. }
  1279. &.sentActive {
  1280. background: rgba(24, 144, 255, 0.1);
  1281. }
  1282. &.overActive {
  1283. background: rgba(0, 0, 0, 0.06);
  1284. }
  1285. &.textLeft {
  1286. text-align: left;
  1287. }
  1288. &.textCenter {
  1289. text-align: center;
  1290. }
  1291. > span {
  1292. float: left;
  1293. cursor: pointer;
  1294. &.NNPE-chs {
  1295. // font-size: 24px;
  1296. font-family: "Smartisan";
  1297. line-height: 150%;
  1298. color: #000000;
  1299. padding: 0 3px;
  1300. &.wordActive {
  1301. color: #175dff;
  1302. }
  1303. &.marginRight {
  1304. padding-right: 0;
  1305. }
  1306. &.marginLeft {
  1307. padding-left: 0;
  1308. }
  1309. &.marginSingleRight {
  1310. padding-right: 3px;
  1311. }
  1312. }
  1313. &.padding {
  1314. padding: 0 3px;
  1315. cursor: pointer;
  1316. }
  1317. }
  1318. }
  1319. }
  1320. .operate-box {
  1321. position: fixed;
  1322. border-top: 1px solid #ebebeb;
  1323. height: 192px;
  1324. width: 1000px;
  1325. background: #f2f3f5;
  1326. left: 50%;
  1327. bottom: 0;
  1328. margin-left: -500px;
  1329. padding-bottom: 24px;
  1330. z-index: 1;
  1331. &-inner {
  1332. padding-top: 40px;
  1333. height: 144px;
  1334. &-content {
  1335. width: 680px;
  1336. margin: 0 auto;
  1337. display: flex;
  1338. justify-content: space-between;
  1339. }
  1340. .operate-item {
  1341. text-align: center;
  1342. cursor: pointer;
  1343. .luyin-btn {
  1344. display: block;
  1345. width: 64px;
  1346. height: 64px;
  1347. padding: 10px;
  1348. border-radius: 60px;
  1349. background: #f2555a;
  1350. box-shadow: 0px 8px 10px -5px rgba(0, 0, 0, 0.08),
  1351. 0px 16px 24px 2px rgba(0, 0, 0, 0.04),
  1352. 0px 6px 30px 5px rgba(0, 0, 0, 0.05);
  1353. }
  1354. .luyin-gif {
  1355. display: block;
  1356. width: 64px;
  1357. height: 64px;
  1358. border-radius: 60px;
  1359. box-shadow: 0px 8px 10px -5px rgba(0, 0, 0, 0.08),
  1360. 0px 16px 24px 2px rgba(0, 0, 0, 0.04),
  1361. 0px 6px 30px 5px rgba(0, 0, 0, 0.05);
  1362. }
  1363. .svg-icon {
  1364. display: block;
  1365. width: 44px;
  1366. height: 44px;
  1367. margin: 0 auto;
  1368. padding: 6px;
  1369. }
  1370. span {
  1371. color: #929ca8;
  1372. font-size: 12px;
  1373. font-weight: 400;
  1374. line-height: 20px;
  1375. }
  1376. }
  1377. }
  1378. }
  1379. .table-box-white {
  1380. .wordActive {
  1381. color: #3459d2 !important;
  1382. }
  1383. .sentActive {
  1384. background: #d9e2fc !important;
  1385. }
  1386. }
  1387. .table-box-darkGreen {
  1388. .wordActive {
  1389. color: #299772 !important;
  1390. }
  1391. .sentActive {
  1392. background: #ecefed !important;
  1393. }
  1394. }
  1395. .table-box-darkBlue {
  1396. .wordActive {
  1397. color: #5373e7 !important;
  1398. }
  1399. .sentActive {
  1400. background: #1c2129 !important;
  1401. }
  1402. }
  1403. .table-box-armyGreen {
  1404. .wordActive {
  1405. color: #30a47d !important;
  1406. }
  1407. .sentActive {
  1408. background: #2a2f2c !important;
  1409. }
  1410. }
  1411. }
  1412. .audio-box {
  1413. display: flex;
  1414. align-items: center;
  1415. justify-content: space-between;
  1416. }
  1417. .aduioLine-box {
  1418. width: 516px;
  1419. height: 48px;
  1420. background: #ffffff;
  1421. border: 1px solid #ebebeb;
  1422. border-radius: 30px;
  1423. display: flex;
  1424. align-items: center;
  1425. padding: 8px 24px;
  1426. .wrapper {
  1427. width: 24px;
  1428. height: 24px;
  1429. flex-shrink: 0;
  1430. color: #175dff;
  1431. margin-left: 8px;
  1432. }
  1433. .Audio {
  1434. width: 430px;
  1435. }
  1436. }
  1437. .clear-box {
  1438. right: calc((100% - 1000px) / 2 - 172px);
  1439. position: fixed;
  1440. top: 510px;
  1441. overflow: auto;
  1442. width: 152px;
  1443. padding: 8px;
  1444. border-radius: 8px;
  1445. border: 1px solid #ebebeb;
  1446. background: #fff;
  1447. box-shadow: 0px 5px 5px -3px rgba(0, 0, 0, 0.1),
  1448. 0px 4px 6px 1px rgba(0, 0, 0, 0.06), 0px 3px 6px 2px rgba(0, 0, 0, 0.05);
  1449. margin-top: 24px;
  1450. h5 {
  1451. margin: 0;
  1452. color: rgba(0, 0, 0, 0.4);
  1453. font-size: 14px;
  1454. font-weight: 400;
  1455. line-height: 22px;
  1456. }
  1457. .item {
  1458. display: flex;
  1459. align-items: center;
  1460. justify-content: space-between;
  1461. margin-top: 4px;
  1462. border-radius: 4px;
  1463. background: #f2f3f5;
  1464. padding: 4px 8px;
  1465. color: #2f3742;
  1466. font-size: 14px;
  1467. font-weight: 400;
  1468. line-height: 22px;
  1469. cursor: pointer;
  1470. &.red-item {
  1471. color: #f53f3f;
  1472. }
  1473. }
  1474. }
  1475. </style>