VoiceMatrix.vue 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858
  1. <template>
  2. <div v-if="curQue" class="voice-matrix">
  3. <div class="voice-matrix-audio">
  4. <div v-if="curQue.voiceMatrix.isAudioNumber" class="audio-number">
  5. <span
  6. :class="[
  7. themeColor.length === 0 || themeColor === 'red'
  8. ? 'serial-number'
  9. : `serial-number-${themeColor}`
  10. ]"
  11. >
  12. {{ curQue.voiceMatrix.audioSerialNumber }}
  13. </span>
  14. </div>
  15. <div v-show="hasSelectedCell" class="audio-simple">
  16. <img :src="playing ? voicePlaySrc : voicePauseSrc" @click="playAudio">
  17. </div>
  18. <audio-line
  19. v-show="!hasSelectedCell"
  20. ref="audioLine"
  21. :mp3="mp3Url"
  22. :get-cur-time="getCurTime"
  23. :stop-audio="stopAudio"
  24. @handleChangeStopAudio="handleChangeStopAudio"
  25. @playChange="playChange"
  26. />
  27. </div>
  28. <!-- 语音矩阵 -->
  29. <div class="voice-matrix-container">
  30. <div
  31. v-if="curQue.voiceMatrix.matrix.length > 0"
  32. class="matrix"
  33. :style="{
  34. 'grid-template': `40px repeat(${curQue.voiceMatrix.matrix.length}, auto) 1fr / 40px repeat(${curQue.voiceMatrix.matrix[0].length}, auto) 1fr`
  35. }"
  36. @mouseleave="clearSelectCell"
  37. >
  38. <!-- 顶部单元格 -->
  39. <div class="matrix-top" @mouseenter="clearSelectCell" />
  40. <template v-for="(row, i) in curQue.voiceMatrix.matrix[0]">
  41. <div
  42. :key="`top-${i}`"
  43. :class="[
  44. 'matrix-top',
  45. curQue.voiceMatrix.columnSelection && (selectColumn === i ||
  46. (selectedLine.type === 'column' && selectedLine.index === i))
  47. ? 'read'
  48. : ''
  49. ]"
  50. @mouseenter="checkboxMouseenter(selectColumn === i, 'column')"
  51. >
  52. <span
  53. v-if="row.type !== 'connection' && curQue.voiceMatrix.columnSelection"
  54. v-show="
  55. selectColumn === i ||
  56. (selectedLine.type === 'column' && selectedLine.index === i)
  57. "
  58. :class="[
  59. `matrix-checkbox-row-${themeColor}`,
  60. selectedLine.type === 'column' && selectedLine.index === i
  61. ? 'active'
  62. : ''
  63. ]"
  64. @click="selectRowOrColumn(i, 'column')"
  65. />
  66. </div>
  67. </template>
  68. <div class="matrix-top" @mouseenter="clearSelectCell" />
  69. <!-- 主矩阵 -->
  70. <template v-for="(row, i) in curQue.voiceMatrix.matrix">
  71. <div
  72. :key="`start-${i}`"
  73. :class="[
  74. 'column-wrapper',
  75. curQue.voiceMatrix.rowSelection && (selectRow === i ||
  76. (selectedLine.type === 'row' && selectedLine.index === i))
  77. ? 'read'
  78. : ''
  79. ]"
  80. @mouseenter="checkboxMouseenter(selectRow === i, 'row')"
  81. >
  82. <span
  83. v-if="curQue.voiceMatrix.rowSelection"
  84. v-show="
  85. selectRow === i ||
  86. (selectedLine.type === 'row' && selectedLine.index === i)
  87. "
  88. :class="[
  89. `matrix-checkbox-column-${themeColor}`,
  90. selectedLine.type === 'row' && selectedLine.index === i
  91. ? 'active'
  92. : ''
  93. ]"
  94. @click="selectRowOrColumn(i, 'row')"
  95. />
  96. </div>
  97. <!-- 单元格 -->
  98. <template v-for="(column, j) in row">
  99. <div
  100. :key="`wrapper-${i}-${j}`"
  101. :class="[
  102. 'column-wrapper',
  103. (curQue.voiceMatrix.rowSelection && selectRow === i) ||
  104. (curQue.voiceMatrix.columnSelection && selectColumn === j) ||
  105. (curQue.voiceMatrix.columnSelection && selectedLine.type === 'column' && selectedLine.index === j) ||
  106. (curQue.voiceMatrix.rowSelection && selectedLine.type === 'row' && selectedLine.index === i)
  107. ? 'read'
  108. : '',
  109. (i === 0 && curQue.voiceMatrix.firstLineHighlight) || (j === row.length - 1 && curQue.voiceMatrix.lastColumnHighlight)
  110. ? `highlight-${themeColor}`
  111. : ''
  112. ]"
  113. @mouseenter="matrixCellMouseenter(i, j, column.type)"
  114. >
  115. <!-- 文本 -->
  116. <div
  117. v-if="column.type === 'text'"
  118. :key="`column-${i}-${j}`"
  119. :class="[
  120. column.text.length === 0 ? 'space' : `column-${themeColor}`,
  121. (selectCell.row === i && selectCell.column === j) ||
  122. (selectedLine.type === 'column' &&
  123. selectedLine.index === j) ||
  124. (selectedLine.type === 'row' && selectedLine.index === i)
  125. ? 'selected'
  126. : '',
  127. column.lrc_data.begin_time / 1000 <= curTime &&
  128. (curTime < column.lrc_data.end_time / 1000 ||
  129. column.lrc_data.end_time === -1)
  130. ? 'playing'
  131. : '',
  132. column.isTitle ? 'title' : ''
  133. ]"
  134. @click="matrixCellClick(i, j)"
  135. >
  136. <span>{{ column.text }}</span>
  137. </div>
  138. <!-- 连接线 -->
  139. <div
  140. v-else-if="column.type === 'connection'"
  141. :key="`column-${i}-${j}`"
  142. :class="[
  143. 'connection',
  144. i === 0 && curQue.voiceMatrix.firstLineHighlight
  145. ? `highlight-bc-${themeColor}`
  146. : ''
  147. ]"
  148. />
  149. <!-- 分词 -->
  150. <div
  151. v-else-if="column.type === 'SentenceSegwordChs'"
  152. :key="`column-${i}-${j}`"
  153. :class="[
  154. `sentence-${themeColor}`,
  155. (selectCell.row === i && selectCell.column === j) ||
  156. (selectedLine.type === 'column' &&
  157. selectedLine.index === j) ||
  158. (selectedLine.type === 'row' && selectedLine.index === i)
  159. ? 'selected'
  160. : '',
  161. column.lrc_data.begin_time / 1000 <= curTime &&
  162. (curTime < column.lrc_data.end_time / 1000 ||
  163. column.lrc_data.end_time === -1)
  164. ? 'playing'
  165. : '',
  166. column.isTitle ? 'title' : ''
  167. ]"
  168. :style="{
  169. 'grid-template-columns': `repeat(${column.sentence_data.wordsList.length}, auto)`
  170. }"
  171. @click="matrixCellClick(i, j)"
  172. >
  173. <template v-for="(word, w) in column.sentence_data.wordsList">
  174. <span
  175. v-if="column.sentence_data.pyPosition === 'top'"
  176. :key="`pinyin-${w}`"
  177. class="pinyin"
  178. >
  179. {{ word.pinyin }}
  180. </span>
  181. <span v-else :key="`chs-${w}`" class="chs">
  182. {{ word.chs }}
  183. </span>
  184. </template>
  185. <template v-for="(word, w) in column.sentence_data.wordsList">
  186. <span
  187. v-if="column.sentence_data.pyPosition === 'top'"
  188. :key="`chs-${w}`"
  189. class="chs"
  190. >
  191. {{ word.chs }}
  192. </span>
  193. <span v-else :key="`pinyin-${w}`" class="pinyin">
  194. {{ word.pinyin }}
  195. </span>
  196. </template>
  197. </div>
  198. </div>
  199. </template>
  200. <div
  201. :key="`end-${i}`"
  202. :class="[
  203. curQue.voiceMatrix.rowSelection && (selectRow === i ||
  204. (selectedLine.type === 'row' && selectedLine.index === i))
  205. ? 'read'
  206. : ''
  207. ]"
  208. @mouseenter="clearSelectCell"
  209. />
  210. </template>
  211. <!-- 底部格子 -->
  212. <div class="matrix-bottom" @mouseenter="clearSelectCell" />
  213. <template v-for="(row, i) in curQue.voiceMatrix.matrix[0]">
  214. <div
  215. :key="`bottom-${i}`"
  216. :class="[
  217. 'matrix-bottom',
  218. curQue.voiceMatrix.columnSelection && (selectColumn === i ||
  219. (selectedLine.type === 'column' && selectedLine.index === i))
  220. ? 'read'
  221. : ''
  222. ]"
  223. @mouseenter="clearSelectCell"
  224. />
  225. </template>
  226. <div class="matrix-bottom" @mouseenter="clearSelectCell" />
  227. </div>
  228. </div>
  229. <soundrecord
  230. type="promax"
  231. class="luyin-box"
  232. :file-name="fileName"
  233. @handleWav="handleWav"
  234. />
  235. </div>
  236. </template>
  237. <script>
  238. import AudioLine from "./AudioLine.vue";
  239. import Soundrecord from "./Soundrecord.vue";
  240. export default {
  241. components: {
  242. AudioLine,
  243. Soundrecord
  244. },
  245. props: ["curQue", "themeColor"],
  246. data() {
  247. return {
  248. curTime: 0,
  249. playing: false,
  250. stopAudio: true,
  251. unWatch: null,
  252. lrcArray: [],
  253. // voicePauseSrc: require("../../../assets/common/icon-voice-red.png"),
  254. // voicePlaySrc: require("../../../assets/common/icon-voice-red-play.png"),
  255. fileName: "",
  256. // 底色行、列
  257. selectRow: -1,
  258. selectColumn: -1,
  259. // 行、列选中
  260. selectedLine: {
  261. type: "",
  262. index: 0
  263. },
  264. // 点击选中
  265. selectCell: {
  266. row: -1,
  267. column: -1
  268. }
  269. };
  270. },
  271. computed: {
  272. mp3Url() {
  273. let mp3_list = this.curQue.mp3_list[0];
  274. if (mp3_list === undefined) return "";
  275. return mp3_list.url.match(/^\[FID##/)
  276. ? mp3_list.temporary_url
  277. : mp3_list.url;
  278. },
  279. hasSelectedCell() {
  280. let { type, index } = this.selectedLine;
  281. let { row, column } = this.selectCell;
  282. return (type.length > 0 && index >= 0) || (row >= 0 && column >= 0);
  283. },
  284. voicePauseSrc() {
  285. let themeColor = this.themeColor;
  286. if (themeColor.length === 0 || themeColor === "red") {
  287. return require("../../../assets/NPC/play-red.png");
  288. }
  289. return require(`../../../assets/NPC/play-${themeColor}.png`);
  290. },
  291. voicePlaySrc() {
  292. let themeColor = this.themeColor;
  293. if (themeColor.length === 0 || themeColor === "red") {
  294. return require("../../../assets/NPC/icon-voice-play-red.png");
  295. }
  296. return require(`../../../assets/NPC/icon-voice-play-${themeColor}.png`);
  297. }
  298. },
  299. watch: {
  300. hasSelectedCell() {
  301. this.handleParentPlay();
  302. }
  303. },
  304. methods: {
  305. // 鼠标移入移出
  306. matrixCellMouseenter(i, j, type) {
  307. if (type === "connection") {
  308. this.selectRow = -1;
  309. this.selectColumn = -1;
  310. } else {
  311. this.selectRow = i;
  312. this.selectColumn = j;
  313. }
  314. },
  315. clearSelectCell() {
  316. this.selectRow = -1;
  317. this.selectColumn = -1;
  318. },
  319. matrixCellClick(row, column) {
  320. if (this.playing) this.handleParentPlay();
  321. if (row === this.selectCell.row && column === this.selectCell.column) {
  322. this.selectCell = { row: -1, column: -1 };
  323. return;
  324. }
  325. this.selectedLine = { type: "", index: -1 };
  326. this.selectCell = { row, column };
  327. // 设置录音文件名
  328. let { type, text, sentence_data } = this.curQue.voiceMatrix.matrix[row][
  329. column
  330. ];
  331. this.fileName = `${type === "text" ? text : ""}${
  332. type === "SentenceSegwordChs" ? sentence_data.sentence : ""
  333. }`;
  334. if (!this.hasSelectedCell) this.handleParentPlay();
  335. },
  336. checkboxMouseenter(isSelected, type) {
  337. if (!isSelected) return this.clearSelectCell();
  338. if (type === "row") this.selectColumn = -1;
  339. if (type === "column") this.selectRow = -1;
  340. },
  341. // 选中行、列
  342. selectRowOrColumn(index, type) {
  343. this.handleParentPlay();
  344. this.lrcArray = [];
  345. this.selectCell = { row: -1, column: -1 };
  346. if (this.unWatch) this.unWatch();
  347. if (
  348. this.selectedLine.type === type &&
  349. this.selectedLine.index === index
  350. ) {
  351. this.selectedLine = { type: "", index: -1 };
  352. return;
  353. }
  354. this.selectedLine = { type, index };
  355. this.fileName = `第 ${index + 1} ${type === "row" ? "行" : "列"}`;
  356. },
  357. playAudio() {
  358. if (!this.hasSelectedCell) return;
  359. if (this.playing) return this.handleParentPlay();
  360. if (this.lrcArray.length > 0) return this.$refs.audioLine.PlayAudio();
  361. this.lrcArray = [];
  362. let { type, index } = this.selectedLine;
  363. if (type.length > 0 && index >= 0 && type === "row") {
  364. this.curQue.voiceMatrix.matrix[index].forEach(item => {
  365. if (
  366. item.type === "SentenceSegwordChs" ||
  367. (item.type === "text" && item.text.length > 0)
  368. ) {
  369. this.lrcArray.push(item.lrc_data);
  370. }
  371. });
  372. if (this.lrcArray.length > 0) this.lrcPlay(this.lrcArray[0], 0);
  373. return;
  374. }
  375. if (type.length > 0 && index >= 0 && type === "column") {
  376. this.curQue.voiceMatrix.matrix.forEach(item => {
  377. let data = item[index];
  378. if (
  379. data.type === "SentenceSegwordChs" ||
  380. (data.type === "text" && data.text.length > 0)
  381. ) {
  382. this.lrcArray.push(data.lrc_data);
  383. }
  384. });
  385. if (this.lrcArray.length > 0) this.lrcPlay(this.lrcArray[0], 0);
  386. return;
  387. }
  388. let { row, column } = this.selectCell;
  389. if (row >= 0 && column >= 0) {
  390. this.handleChangeTime(
  391. this.curQue.voiceMatrix.matrix[row][column].lrc_data
  392. );
  393. }
  394. },
  395. lrcPlay({ begin_time, end_time }, index) {
  396. this.handleParentPlay();
  397. this.$nextTick(() => {
  398. this.$refs.audioLine.onTimeupdateTime(begin_time / 1000);
  399. this.$refs.audioLine.PlayAudio();
  400. if (end_time === -1) return;
  401. let end = end_time / 1000 - 0.01;
  402. this.unWatch = this.$watch("curTime", val => {
  403. if (val >= end) {
  404. if (!this.hasSelectedCell) return this.unWatch();
  405. this.handleParentPlay();
  406. this.$refs.audioLine.onTimeupdateTime(end);
  407. this.unWatch();
  408. let i = index + 1;
  409. if (i < this.lrcArray.length) {
  410. this.lrcPlay(this.lrcArray[i], i);
  411. } else {
  412. this.lrcArray = [];
  413. }
  414. }
  415. });
  416. });
  417. },
  418. playChange(playing) {
  419. this.playing = playing;
  420. },
  421. // 暂停音频播放
  422. handleParentPlay() {
  423. this.stopAudio = true;
  424. },
  425. // 音频播放时改变布尔值
  426. handleChangeStopAudio() {
  427. this.stopAudio = false;
  428. },
  429. getCurTime(curTime) {
  430. this.curTime = curTime;
  431. },
  432. handleWav(data) {
  433. console.log(data);
  434. },
  435. handleChangeTime({ begin_time, end_time }) {
  436. if (this.unWatch) this.unWatch();
  437. this.handleParentPlay();
  438. this.$nextTick(() => {
  439. this.$refs.audioLine.onTimeupdateTime(begin_time / 1000);
  440. this.$refs.audioLine.PlayAudio();
  441. // 监听是否已到结束时间,为了选中效果 - 0.01
  442. if (end_time === -1) return;
  443. let end = end_time / 1000 - 0.01;
  444. this.unWatch = this.$watch("curTime", val => {
  445. if (val >= end) {
  446. this.handleParentPlay();
  447. this.$refs.audioLine.onTimeupdateTime(end);
  448. this.unWatch();
  449. this.unWatch = null;
  450. }
  451. });
  452. });
  453. }
  454. }
  455. };
  456. </script>
  457. <style lang="scss" scoped>
  458. $select-color: #de4444;
  459. $border-color: #e6e6e6;
  460. $select-color-green: #24b99e;
  461. $select-color-green-bc: rgba(36, 185, 158, 0.25);
  462. $select-color-green-hover: #3dd4b8;
  463. $select-color-green-active: #1fa189;
  464. $select-color-brown: #bd8865;
  465. $select-color-brown-bc: rgba(189, 136, 101, 0.25);
  466. $select-color-brown-hover: #d6a687;
  467. $select-color-brown-active: #a37557;
  468. .voice-matrix {
  469. height: 100%;
  470. width: 100%;
  471. margin-bottom: 16px;
  472. color: #262626;
  473. &-audio {
  474. display: flex;
  475. height: 42px;
  476. border: 1px solid $border-color;
  477. border-radius: 8px 8px 0 0;
  478. .audio-number {
  479. padding: 11px 0 0 12px;
  480. %serial-number,
  481. .serial-number {
  482. display: inline-block;
  483. width: 16px;
  484. height: 16px;
  485. text-align: center;
  486. line-height: 16px;
  487. font-size: 12px;
  488. background-color: $select-color;
  489. font-family: "robot";
  490. color: #fff;
  491. border-radius: 50%;
  492. }
  493. .serial-number-green {
  494. @extend %serial-number;
  495. background-color: $select-color-green;
  496. }
  497. .serial-number-brown {
  498. @extend %serial-number;
  499. background-color: $select-color-brown;
  500. }
  501. }
  502. .audio-simple {
  503. line-height: 46px;
  504. height: 100%;
  505. img {
  506. cursor: pointer;
  507. width: 16px;
  508. margin-left: 12px;
  509. }
  510. }
  511. }
  512. // 语音矩阵
  513. &-container {
  514. height: calc(100% - 80px);
  515. background-color: #f5f5f5;
  516. border-left: 1px solid $border-color;
  517. border-right: 1px solid $border-color;
  518. .matrix {
  519. display: inline-grid;
  520. width: 100%;
  521. height: 100%;
  522. .matrix-top,
  523. .matrix-bottom {
  524. min-height: 40px;
  525. }
  526. %matrix-checkbox {
  527. position: relative;
  528. top: calc(50% - 5px);
  529. display: block;
  530. width: 14px;
  531. height: 14px;
  532. border: 1.5px solid #b0b0b0;
  533. border-radius: 4px;
  534. margin: 0 auto;
  535. cursor: pointer;
  536. &.active {
  537. border-color: $select-color;
  538. &::after {
  539. box-sizing: content-box;
  540. content: "";
  541. border: 1px solid $select-color;
  542. border-left: 0;
  543. border-top: 0;
  544. height: 7px;
  545. left: 4px;
  546. position: absolute;
  547. width: 3px;
  548. transform: rotate(45deg) scaleY(1);
  549. transition: transform 0.15s ease-in 0.05s;
  550. transform-origin: center;
  551. }
  552. }
  553. }
  554. .matrix-checkbox-row-,
  555. .matrix-checkbox-row-red {
  556. @extend %matrix-checkbox;
  557. }
  558. .matrix-checkbox-row-green {
  559. @extend %matrix-checkbox;
  560. &.active {
  561. border-color: $select-color-green-active;
  562. &::after {
  563. border-color: $select-color-green-active;
  564. }
  565. }
  566. }
  567. .matrix-checkbox-row-brown {
  568. @extend %matrix-checkbox;
  569. &.active {
  570. border-color: $select-color-brown-active;
  571. &::after {
  572. border-color: $select-color-brown-active;
  573. }
  574. }
  575. }
  576. %matrix-checkbox-column,
  577. .matrix-checkbox-column-,
  578. .matrix-checkbox-column-red {
  579. @extend %matrix-checkbox;
  580. top: calc(50% - 7px);
  581. right: -2px;
  582. }
  583. .matrix-checkbox-column-green {
  584. @extend %matrix-checkbox-column;
  585. &.active {
  586. border-color: $select-color-green-active;
  587. &::after {
  588. border-color: $select-color-green-active;
  589. }
  590. }
  591. }
  592. .matrix-checkbox-column-brown {
  593. @extend %matrix-checkbox-column;
  594. &.active {
  595. border-color: $select-color-brown-active;
  596. &::after {
  597. border-color: $select-color-brown-active;
  598. }
  599. }
  600. }
  601. .read {
  602. background-color: #eaeaea;
  603. }
  604. .highlight-,
  605. .highlight-red {
  606. color: $select-color;
  607. }
  608. .highlight-green {
  609. color: $select-color-green;
  610. }
  611. .highlight-brown {
  612. color: $select-color-brown;
  613. }
  614. .column-wrapper {
  615. padding: 4px;
  616. %column {
  617. width: 100%;
  618. height: 100%;
  619. padding: 7px 16px;
  620. min-height: 32px;
  621. background-color: #fff;
  622. border: 1px solid $border-color;
  623. border-radius: 8px;
  624. transition: 0.2s;
  625. cursor: pointer;
  626. &:hover {
  627. border-color: #8c8c8c;
  628. }
  629. &.selected {
  630. color: $select-color;
  631. border-color: $select-color;
  632. }
  633. &.playing {
  634. background-color: #fee;
  635. }
  636. &.title {
  637. background-color: transparent;
  638. border-color: transparent;
  639. }
  640. }
  641. %column-red,
  642. .column-,
  643. .column-red {
  644. @extend %column;
  645. position: relative;
  646. font-family: "GB-PINYINOK-B", "FZJCGFKTK";
  647. &::before {
  648. display: inline-block;
  649. content: "";
  650. height: 100%;
  651. vertical-align: middle;
  652. }
  653. }
  654. .column-green {
  655. @extend %column-red;
  656. &.selected {
  657. color: $select-color-green;
  658. border-color: $select-color-green;
  659. }
  660. &.playing {
  661. background-color: $select-color-green-bc;
  662. }
  663. }
  664. .column-brown {
  665. @extend %column-red;
  666. &.selected {
  667. color: $select-color-brown;
  668. border-color: $select-color-brown;
  669. }
  670. &.playing {
  671. background-color: $select-color-brown-bc;
  672. }
  673. }
  674. %sentence,
  675. .sentence-,
  676. .sentence-red {
  677. @extend %column;
  678. display: inline-grid;
  679. column-gap: 8px;
  680. justify-items: center;
  681. justify-content: start;
  682. .pinyin {
  683. font-family: "GB-PINYINOK-B";
  684. font-size: 14px;
  685. line-height: 22px;
  686. }
  687. .chs {
  688. font-family: "FZJCGFKTK";
  689. font-size: 16px;
  690. line-height: 24px;
  691. }
  692. }
  693. .sentence-green {
  694. @extend %sentence;
  695. &.selected {
  696. color: $select-color-green;
  697. border-color: $select-color-green;
  698. }
  699. &.playing {
  700. background-color: $select-color-green-hover;
  701. }
  702. }
  703. .sentence-brown {
  704. @extend %sentence;
  705. &.selected {
  706. color: $select-color-brown;
  707. border-color: $select-color-brown;
  708. }
  709. &.playing {
  710. background-color: $select-color-brown-hover;
  711. }
  712. }
  713. .connection {
  714. position: relative;
  715. top: calc(50% - 1px);
  716. height: 2px;
  717. width: 16px;
  718. margin: 0 -4px;
  719. border-radius: 4px;
  720. background-color: #252525;
  721. &.highlight-bc-,
  722. &.highlight-bc-red {
  723. background-color: $select-color;
  724. }
  725. &.highlight-bc-green {
  726. background-color: $select-color-green;
  727. }
  728. &.highlight-bc-brown {
  729. background-color: $select-color-brown;
  730. }
  731. }
  732. }
  733. }
  734. .matrix-audio {
  735. width: 228px;
  736. height: 40px;
  737. padding: 4px 4px 4px 16px;
  738. margin: 24px 24px 0 0;
  739. background-color: #fff;
  740. border: 1px solid $border-color;
  741. border-radius: 8px;
  742. }
  743. }
  744. .luyin-box {
  745. padding: 8px 16px;
  746. height: 40px;
  747. border: 1px solid $border-color;
  748. border-radius: 0 0 8px 8px;
  749. }
  750. }
  751. </style>
  752. <style lang="scss" scoped>
  753. .NNPE-tableList-tr-last{
  754. .voice-matrix{
  755. margin-bottom: 0;
  756. }
  757. }
  758. </style>
  759. <style lang="scss">
  760. .voice-matrix {
  761. &-audio {
  762. .audioLine {
  763. border-radius: 8px 8px 0 0 !important;
  764. }
  765. .el-slider {
  766. width: 100% !important;
  767. }
  768. }
  769. }
  770. </style>