|
@@ -1,27 +1,365 @@
|
|
|
<!-- -->
|
|
|
<template>
|
|
|
- <div class="">
|
|
|
- <RoleChs />
|
|
|
+ <div class="NNPE-ArticleView" v-if="curQue">
|
|
|
+ <div
|
|
|
+ class="aduioLine-box"
|
|
|
+ v-if="
|
|
|
+ curQue.mp3_list && curQue.mp3_list.length > 0 && curQue.mp3_list[0].url
|
|
|
+ "
|
|
|
+ >
|
|
|
+ <AudioLine
|
|
|
+ :mp3="curQue.mp3_list[0].url"
|
|
|
+ :getCurTime="getCurTime"
|
|
|
+ ref="audioLine"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <template v-if="resArr.length > 0">
|
|
|
+ <div class="NPC-sentences-list">
|
|
|
+ <div class="NPC-article-empty">
|
|
|
+ <div :class="['empty-left', isHasRemark ? 'hasRemark' : '']"></div>
|
|
|
+ <div class="empty-right"></div>
|
|
|
+ </div>
|
|
|
+ <p class="notice" v-if="curQue.notice">{{ curQue.notice }}</p>
|
|
|
+ <div
|
|
|
+ :class="[
|
|
|
+ 'NNPE-detail',
|
|
|
+ item.isTitle ? 'NNPE-detail-title' : '',
|
|
|
+ item.timeList.length > 0 &&
|
|
|
+ curTime >= item.timeList[0].bg &&
|
|
|
+ curTime <= item.timeList[item.timeList.length - 1].ed
|
|
|
+ ? 'active'
|
|
|
+ : '',
|
|
|
+ ]"
|
|
|
+ v-for="(item, index) in resArr"
|
|
|
+ :key="'detail' + index"
|
|
|
+ >
|
|
|
+ <div :class="['article-content', isHasRemark ? 'hasRemark' : '']">
|
|
|
+ <RoleChs :curRole="item.roleDetail" />
|
|
|
+ <div class="wordsList-box">
|
|
|
+ <img
|
|
|
+ :src="articleImg[index]"
|
|
|
+ v-if="articleImg[0] && index == 0"
|
|
|
+ />
|
|
|
+ <div :style="{ background: item.roleDetail.color.bg }">
|
|
|
+ <div
|
|
|
+ class="NNPE-words"
|
|
|
+ v-for="(pItem, pIndex) in item.wordsList"
|
|
|
+ :key="'wordsList' + pIndex"
|
|
|
+ :class="[pItem.wordIndex == 0 ? 'textLeft' : 'textCenter']"
|
|
|
+ @click="
|
|
|
+ handleChangeTime(
|
|
|
+ item.timeList.length > 0 &&
|
|
|
+ item.timeList[pItem.sentIndex].bg
|
|
|
+ )
|
|
|
+ "
|
|
|
+ >
|
|
|
+ <template v-if="!pItem.width">
|
|
|
+ <template v-if="pItem.isShow">
|
|
|
+ <template
|
|
|
+ v-if="
|
|
|
+ item.wordsList[pIndex + 1].chs &&
|
|
|
+ chsFhList.indexOf(item.wordsList[pIndex + 1].chs) > -1
|
|
|
+ "
|
|
|
+ >
|
|
|
+ <span class="NNPE-words-box">
|
|
|
+ <span
|
|
|
+ v-if="curQue.pyPosition == 'top'"
|
|
|
+ class="NNPE-pinyin"
|
|
|
+ :class="[pItem.className ? pItem.className : '']"
|
|
|
+ >{{ pItem.pinyin }}</span
|
|
|
+ >
|
|
|
+ <span
|
|
|
+ class="NNPE-chs"
|
|
|
+ :class="[
|
|
|
+ item.timeList.length > 0 &&
|
|
|
+ curTime >=
|
|
|
+ item.timeList[pItem.sentIndex].wordsResultList[
|
|
|
+ pItem.wordIndex
|
|
|
+ ].wordBg &&
|
|
|
+ curTime <= item.timeList[pItem.sentIndex].ed
|
|
|
+ ? 'wordActive'
|
|
|
+ : '',
|
|
|
+ ]"
|
|
|
+ >{{ pItem.chs }}</span
|
|
|
+ >
|
|
|
+ <span
|
|
|
+ v-if="curQue.pyPosition == 'bottom'"
|
|
|
+ class="NNPE-pinyin"
|
|
|
+ :class="[pItem.className ? pItem.className : '']"
|
|
|
+ >{{ pItem.pinyin }}</span
|
|
|
+ >
|
|
|
+ </span>
|
|
|
+ <span class="NNPE-words-box">
|
|
|
+ <span
|
|
|
+ v-if="curQue.pyPosition == 'top'"
|
|
|
+ class="NNPE-pinyin"
|
|
|
+ style="text-align: left"
|
|
|
+ >{{ item.wordsList[pIndex + 1].pinyin }}</span
|
|
|
+ >
|
|
|
+ <span
|
|
|
+ class="NNPE-chs"
|
|
|
+ style="text-align: left"
|
|
|
+ :class="[
|
|
|
+ item.timeList.length > 0 &&
|
|
|
+ curTime >=
|
|
|
+ item.timeList[pItem.sentIndex].wordsResultList[
|
|
|
+ pItem.wordIndex
|
|
|
+ ].wordBg &&
|
|
|
+ curTime <= item.timeList[pItem.sentIndex].ed
|
|
|
+ ? 'wordActive'
|
|
|
+ : '',
|
|
|
+ ]"
|
|
|
+ >{{ item.wordsList[pIndex + 1].chs }}</span
|
|
|
+ >
|
|
|
+ <span
|
|
|
+ v-if="curQue.pyPosition == 'bottom'"
|
|
|
+ class="NNPE-pinyin"
|
|
|
+ style="text-align: left"
|
|
|
+ >{{ item.wordsList[pIndex + 1].pinyin }}</span
|
|
|
+ >
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ <template v-else>
|
|
|
+ <span
|
|
|
+ v-if="curQue.pyPosition == 'top'"
|
|
|
+ class="NNPE-pinyin"
|
|
|
+ :class="[
|
|
|
+ pItem.padding ? 'padding' : '',
|
|
|
+ pItem.className ? pItem.className : '',
|
|
|
+ ]"
|
|
|
+ >{{ pItem.pinyin }}</span
|
|
|
+ >
|
|
|
+ <span
|
|
|
+ class="NNPE-chs"
|
|
|
+ :class="[
|
|
|
+ item.timeList.length > 0 &&
|
|
|
+ curTime >=
|
|
|
+ item.timeList[pItem.sentIndex].wordsResultList[
|
|
|
+ pItem.wordIndex
|
|
|
+ ].wordBg &&
|
|
|
+ curTime <= item.timeList[pItem.sentIndex].ed
|
|
|
+ ? 'wordActive'
|
|
|
+ : '',
|
|
|
+ pItem.padding ? 'padding' : '',
|
|
|
+ ]"
|
|
|
+ >{{ pItem.chs }}</span
|
|
|
+ >
|
|
|
+ <span
|
|
|
+ v-if="curQue.pyPosition == 'bottom'"
|
|
|
+ class="NNPE-pinyin"
|
|
|
+ :class="[
|
|
|
+ pItem.padding ? 'padding' : '',
|
|
|
+ pItem.className ? pItem.className : '',
|
|
|
+ ]"
|
|
|
+ >{{ pItem.pinyin }}</span
|
|
|
+ >
|
|
|
+ </template>
|
|
|
+ </template>
|
|
|
+ </template>
|
|
|
+ <template v-else>
|
|
|
+ <span
|
|
|
+ :style="{
|
|
|
+ height: pItem.height + 'px',
|
|
|
+ width: pItem.width + 'px',
|
|
|
+ }"
|
|
|
+ ></span>
|
|
|
+ </template>
|
|
|
+ </div>
|
|
|
+ <div v-if="item.enwords" class="enwords">
|
|
|
+ {{ item.enwords }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <img :src="articleImg[index + 1]" v-if="articleImg[index + 1]" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="remarkBox remark-top" v-if="item.remarkDetail">
|
|
|
+ <RemarkChs :remarkDetail="item.remarkDetail" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="NPC-article-empty NPC-article-empty-bottom">
|
|
|
+ <div :class="['empty-left', isHasRemark ? 'hasRemark' : '']"></div>
|
|
|
+ <div class="empty-right"></div>
|
|
|
+ </div>
|
|
|
+ <div class="dia-article-record">
|
|
|
+ <Soundrecord @handleWav="handleWav" type="promax" class="luyin-box" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
+import { timeStrToSen } from "@/utils/index";
|
|
|
+import AudioLine from "../AudioLine.vue";
|
|
|
import RoleChs from "./RoleChs.vue";
|
|
|
+import RemarkChs from "./RemarkChs.vue";
|
|
|
+import Soundrecord from "../Soundrecord.vue";
|
|
|
export default {
|
|
|
+ name: "DialogueNormalModelChs",
|
|
|
+ props: ["curQue", "colorBox"],
|
|
|
components: {
|
|
|
+ AudioLine,
|
|
|
RoleChs,
|
|
|
+ RemarkChs,
|
|
|
+ Soundrecord,
|
|
|
},
|
|
|
data() {
|
|
|
- return {};
|
|
|
+ return {
|
|
|
+ resArr: [],
|
|
|
+ curTime: 0, //单位s
|
|
|
+ chsFhList: [",", "。", "“", ":", "》", "《", "?", "!", ";"],
|
|
|
+ enFhList: [",", ".", ";", "?", "!", ":", ">", "<"],
|
|
|
+ newWords: ["鱼", "辩礼义"],
|
|
|
+ oldHz: "",
|
|
|
+ hz: "",
|
|
|
+ top: 0,
|
|
|
+ left: 0,
|
|
|
+ articleImg: {}, // 文章图片
|
|
|
+ isHasRemark: false,
|
|
|
+ };
|
|
|
},
|
|
|
computed: {},
|
|
|
watch: {},
|
|
|
//方法集合
|
|
|
- methods: {},
|
|
|
+ methods: {
|
|
|
+ handleWav() {},
|
|
|
+ getCurTime(curTime) {
|
|
|
+ this.curTime = curTime * 1000;
|
|
|
+ },
|
|
|
+ handleData() {
|
|
|
+ let resArr = [];
|
|
|
+ let reg = /_{2,}/g;
|
|
|
+ let leg = this.curQue.detail.length;
|
|
|
+ let curQue = JSON.parse(JSON.stringify(this.curQue));
|
|
|
+ curQue.detail.forEach((dItem, dIndex) => {
|
|
|
+ let roleDetail = this.getRole(dItem);
|
|
|
+ let remarkDetail = dItem.remark;
|
|
|
+ if (remarkDetail && (remarkDetail.chs || remarkDetail.en)) {
|
|
|
+ this.isHasRemark = true;
|
|
|
+ }
|
|
|
+ let paraArr = [];
|
|
|
+ dItem.wordsList.forEach((sItem, sIndex) => {
|
|
|
+ sItem.forEach((wItem, wIndex) => {
|
|
|
+ //this.judgePad(sItem, wItem, wIndex);
|
|
|
+ this.mergeWordSymbol(sItem, wItem, wIndex);
|
|
|
+ let obj = {
|
|
|
+ paraIndex: dIndex, //段落索引
|
|
|
+ sentIndex: sIndex, //在段落中句子索引
|
|
|
+ answer: "",
|
|
|
+ wordIndex: wIndex, //单词的索引
|
|
|
+ pinyin: wItem.pinyin,
|
|
|
+ chs: wItem.chs,
|
|
|
+ isHeng: reg.test(wItem.chs),
|
|
|
+ padding: true, //wItem.padding,
|
|
|
+ className: wItem.className,
|
|
|
+ isShow: wItem.isShow,
|
|
|
+ isNewWord: this.newWords.indexOf(wItem.chs) > -1 ? true : false,
|
|
|
+ };
|
|
|
+ paraArr.push(obj);
|
|
|
+ });
|
|
|
+ });
|
|
|
+ let curSentencesLeg = dItem.sentences.length;
|
|
|
+ let startLeg = dIndex == 0 ? 0 : curQue.detail[dIndex - 1].endLeg;
|
|
|
+ let endLeg = startLeg + curSentencesLeg;
|
|
|
+ dItem.endLeg = endLeg;
|
|
|
+ let timeList = [];
|
|
|
+ if (curQue.wordTime && curQue.wordTime.length > 0) {
|
|
|
+ timeList = curQue.wordTime.slice(startLeg, endLeg);
|
|
|
+ }
|
|
|
+ let enwords =
|
|
|
+ dItem.sentencesEn && dItem.sentencesEn.length > 0
|
|
|
+ ? dItem.sentencesEn.join(" ")
|
|
|
+ : "";
|
|
|
+ let paraObj = {
|
|
|
+ wordsList: paraArr,
|
|
|
+ enwords: enwords,
|
|
|
+ timeList: timeList,
|
|
|
+ roleDetail: roleDetail,
|
|
|
+ remarkDetail: remarkDetail,
|
|
|
+ };
|
|
|
+ resArr.push(paraObj);
|
|
|
+ });
|
|
|
+ this.resArr = resArr;
|
|
|
+ console.log("Normal");
|
|
|
+ console.log(this.resArr);
|
|
|
+
|
|
|
+ // 循环文章图片
|
|
|
+ if (curQue.img_list) {
|
|
|
+ curQue.img_list.forEach((item) => {
|
|
|
+ this.articleImg[item.imgNumber] = item.url;
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+ //词和标点合一起
|
|
|
+ mergeWordSymbol(sItem, wItem, curIndex) {
|
|
|
+ let leg = sItem.length;
|
|
|
+ if (curIndex < leg - 1) {
|
|
|
+ if (this.chsFhList.indexOf(wItem.chs) > -1) {
|
|
|
+ wItem.isShow = false;
|
|
|
+ } else {
|
|
|
+ wItem.isShow = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ //获取角色
|
|
|
+ getRole(dItem) {
|
|
|
+ let roleIndex = dItem.roleIndex;
|
|
|
+ let resObj = null;
|
|
|
+ let roleList = JSON.parse(JSON.stringify(this.curQue.roleList));
|
|
|
+ for (let i = 0; i < roleList.length; i++) {
|
|
|
+ let item = roleList[i];
|
|
|
+ if (item.id == roleIndex) {
|
|
|
+ resObj = item;
|
|
|
+ resObj.color = this.colorBox[i];
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return resObj;
|
|
|
+ },
|
|
|
+ //判断是否有padding
|
|
|
+ judgePad(sItem, wItem, curIndex) {
|
|
|
+ let leg = sItem.length;
|
|
|
+ if (curIndex < leg - 1) {
|
|
|
+ let nextIndex = curIndex + 1;
|
|
|
+ let chs = sItem[nextIndex].chs;
|
|
|
+ if (
|
|
|
+ this.chsFhList.indexOf(chs) > -1 ||
|
|
|
+ this.chsFhList.indexOf(wItem.chs) > -1
|
|
|
+ ) {
|
|
|
+ wItem.padding = false;
|
|
|
+ } else {
|
|
|
+ wItem.padding = true;
|
|
|
+ }
|
|
|
+ if (this.enFhList.indexOf(wItem.pinyin) > -1) {
|
|
|
+ wItem.className = "textLeft";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ //转化时间
|
|
|
+ handleTimeList(list) {
|
|
|
+ let listRes = [];
|
|
|
+ list.forEach((item) => {
|
|
|
+ let res = timeStrToSen(item);
|
|
|
+ listRes.push(res);
|
|
|
+ });
|
|
|
+ return listRes;
|
|
|
+ },
|
|
|
+ //点击播放某个句子
|
|
|
+ handleChangeTime(time) {
|
|
|
+ this.curTime = time;
|
|
|
+ this.$refs.audioLine.onTimeupdateTime(time / 1000);
|
|
|
+ },
|
|
|
+ },
|
|
|
//生命周期 - 创建完成(可以访问当前this实例)
|
|
|
created() {},
|
|
|
//生命周期 - 挂载完成(可以访问DOM元素)
|
|
|
- mounted() {},
|
|
|
+ mounted() {
|
|
|
+ console.log(this.curQue);
|
|
|
+ if (this.curQue) {
|
|
|
+ this.handleData();
|
|
|
+ }
|
|
|
+ },
|
|
|
beforeCreate() {}, //生命周期 - 创建之前
|
|
|
beforeMount() {}, //生命周期 - 挂载之前
|
|
|
beforeUpdate() {}, //生命周期 - 更新之前
|
|
@@ -33,4 +371,197 @@ export default {
|
|
|
</script>
|
|
|
<style lang='scss' scoped>
|
|
|
//@import url(); 引入公共css类
|
|
|
+.NNPE-ArticleView {
|
|
|
+ width: 100%;
|
|
|
+
|
|
|
+ .NPC-sentences-list {
|
|
|
+ .NPC-article-empty {
|
|
|
+ display: flex;
|
|
|
+ justify-content: flex-start;
|
|
|
+ align-items: flex-start;
|
|
|
+ > div {
|
|
|
+ height: 24px;
|
|
|
+ &.empty-left {
|
|
|
+ width: 100%;
|
|
|
+ box-sizing: border-box;
|
|
|
+
|
|
|
+ &.hasRemark {
|
|
|
+ width: 553px;
|
|
|
+ box-sizing: border-box;
|
|
|
+ border-right: 1px rgba(0, 0, 0, 0.1) solid;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ &.empty-right {
|
|
|
+ flex: 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ &-bottom {
|
|
|
+ > div {
|
|
|
+ height: 40px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .dia-article-record {
|
|
|
+ width: 100%;
|
|
|
+ border-top: 1px solid rgba(0, 0, 0, 0.1);
|
|
|
+ .luyin-box {
|
|
|
+ justify-content: start;
|
|
|
+ padding: 8px 12px;
|
|
|
+ height: 40px;
|
|
|
+ width: 280px;
|
|
|
+ justify-content: flex-start;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .NNPE-detail {
|
|
|
+ clear: both;
|
|
|
+ overflow: hidden;
|
|
|
+ display: flex;
|
|
|
+ justify-content: flex-start;
|
|
|
+ align-items: flex-start;
|
|
|
+ &.active {
|
|
|
+ background: rgba(0, 0, 0, 0.06);
|
|
|
+ }
|
|
|
+ .article-content {
|
|
|
+ width: 100%;
|
|
|
+ box-sizing: border-box;
|
|
|
+ padding: 8px 24px 8px 24px;
|
|
|
+ &.hasRemark {
|
|
|
+ width: 553px;
|
|
|
+ border-right: 1px rgba(0, 0, 0, 0.1) solid;
|
|
|
+ padding: 8px 0px 8px 23px;
|
|
|
+ }
|
|
|
+ &.paraLast {
|
|
|
+ padding-bottom: 24px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .NNPE-words {
|
|
|
+ float: left;
|
|
|
+ &-box {
|
|
|
+ float: left;
|
|
|
+ > span {
|
|
|
+ display: block;
|
|
|
+ &.NNPE-pinyin {
|
|
|
+ font-family: "GB-PINYINOK-B";
|
|
|
+ font-weight: normal;
|
|
|
+ font-size: 14px;
|
|
|
+ line-height: 22px;
|
|
|
+ color: #000000;
|
|
|
+ height: 21px;
|
|
|
+ &.textLeft {
|
|
|
+ text-align: left;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ &.NNPE-chs {
|
|
|
+ font-family: "FZJCGFKTK";
|
|
|
+ font-size: 20px;
|
|
|
+ line-height: 28px;
|
|
|
+ color: #000000;
|
|
|
+ &.active {
|
|
|
+ background: rgba(60, 200, 99, 0.2);
|
|
|
+ }
|
|
|
+ &.wordActive {
|
|
|
+ color: #de4444;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ &.padding {
|
|
|
+ padding: 0 3px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ &.textLeft {
|
|
|
+ text-align: left;
|
|
|
+ }
|
|
|
+ &.textCenter {
|
|
|
+ text-align: center;
|
|
|
+ }
|
|
|
+ > span {
|
|
|
+ display: block;
|
|
|
+ &.NNPE-pinyin {
|
|
|
+ font-family: "GB-PINYINOK-B";
|
|
|
+ font-weight: normal;
|
|
|
+ font-size: 14px;
|
|
|
+ line-height: 22px;
|
|
|
+ color: #000000;
|
|
|
+ height: 21px;
|
|
|
+ &.textLeft {
|
|
|
+ text-align: left;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ &.NNPE-chs {
|
|
|
+ font-family: "FZJCGFKTK";
|
|
|
+ font-size: 20px;
|
|
|
+ line-height: 28px;
|
|
|
+ color: #000000;
|
|
|
+ &.active {
|
|
|
+ background: rgba(60, 200, 99, 0.2);
|
|
|
+ }
|
|
|
+ &.wordActive {
|
|
|
+ color: #de4444;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ &.padding {
|
|
|
+ padding: 0 3px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .enwords {
|
|
|
+ font-family: "robot";
|
|
|
+ font-weight: normal;
|
|
|
+ font-size: 14px;
|
|
|
+ line-height: 22px;
|
|
|
+ color: rgba(0, 0, 0, 0.85);
|
|
|
+ }
|
|
|
+ &.NNPE-detail-title {
|
|
|
+ .wordsList-box {
|
|
|
+ > div {
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .index {
|
|
|
+ width: 48px;
|
|
|
+ box-sizing: border-box;
|
|
|
+ padding: 8px;
|
|
|
+ text-align: right;
|
|
|
+ border-right: 1px solid rgba(0, 0, 0, 0.1);
|
|
|
+ b {
|
|
|
+ font-weight: 400;
|
|
|
+ color: #000000;
|
|
|
+ line-height: 1.5;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .wordsList-box {
|
|
|
+ width: 100%;
|
|
|
+ padding: 0px 24px 0px 40px;
|
|
|
+ clear: both;
|
|
|
+ overflow: hidden;
|
|
|
+ > div {
|
|
|
+ float: left;
|
|
|
+ border: 1px solid rgba(0, 0, 0, 0.1);
|
|
|
+ box-sizing: border-box;
|
|
|
+ padding: 8px 12px 8px 12px;
|
|
|
+ border-radius: 8px;
|
|
|
+ }
|
|
|
+ > img {
|
|
|
+ width: 100%;
|
|
|
+ display: block;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .remarkBox {
|
|
|
+ flex: 1;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ &.remark72 {
|
|
|
+ padding-top: 72px;
|
|
|
+ }
|
|
|
+ &.remark-top {
|
|
|
+ padding-top: 44px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
</style>
|