|
@@ -0,0 +1,307 @@
|
|
|
+<!-- -->
|
|
|
+<template>
|
|
|
+ <div class="NNPE-ArticleView" v-if="curQue">
|
|
|
+ <AudioLine
|
|
|
+ :mp3="curQue.mp3_list[0].url"
|
|
|
+ :getCurTime="getCurTime"
|
|
|
+ ref="audioLine"
|
|
|
+ />
|
|
|
+ <template v-if="resObj">
|
|
|
+ <div
|
|
|
+ class="NNPE-detail"
|
|
|
+ v-for="(item, index) in resObj.sentList"
|
|
|
+ :key="'detail' + index"
|
|
|
+ @click="handleChangeTime(resObj.timeList[index])"
|
|
|
+ >
|
|
|
+ <div
|
|
|
+ class="NNPE-words"
|
|
|
+ v-for="(pItem, pIndex) in item"
|
|
|
+ :key="'wordsList' + pIndex"
|
|
|
+ :class="[pItem.wordIndex == 0 ? 'textLeft' : 'textCenter']"
|
|
|
+ >
|
|
|
+ <template v-if="!pItem.width">
|
|
|
+ <span
|
|
|
+ class="NNPE-pinyin"
|
|
|
+ :class="[
|
|
|
+ pItem.padding ? 'padding' : '',
|
|
|
+ pItem.className ? pItem.className : '',
|
|
|
+ ]"
|
|
|
+ >{{ pItem.pinyin }}</span
|
|
|
+ >
|
|
|
+
|
|
|
+ <span
|
|
|
+ class="NNPE-chs"
|
|
|
+ :class="[
|
|
|
+ curTime >= resObj.timeList[index] &&
|
|
|
+ curTime <= resObj.timeList[index + 1] &&
|
|
|
+ curTime >= pItem.startTime
|
|
|
+ ? 'active'
|
|
|
+ : '',
|
|
|
+ pItem.padding ? 'padding' : '',
|
|
|
+ ]"
|
|
|
+ >{{ pItem.chs }}</span
|
|
|
+ >
|
|
|
+ </template>
|
|
|
+ <template v-else>
|
|
|
+ <span
|
|
|
+ :style="{
|
|
|
+ height: pItem.height + 'px',
|
|
|
+ width: pItem.width + 'px',
|
|
|
+ }"
|
|
|
+ ></span>
|
|
|
+ </template>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import { timeStrToSen } from "@/utils/index";
|
|
|
+import AudioLine from "../AudioLine.vue";
|
|
|
+export default {
|
|
|
+ name: "ArticleView",
|
|
|
+ props: ["curQue"],
|
|
|
+ components: {
|
|
|
+ AudioLine,
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ resObj: null,
|
|
|
+ curTime: 0, //单位s
|
|
|
+ chsFhList: [",", "。", "“", ":", "》", "《", "?", "!", ";"],
|
|
|
+ enFhList: [",", ".", ";", "?", "!", ":", ">", "<"],
|
|
|
+ };
|
|
|
+ },
|
|
|
+ computed: {},
|
|
|
+ watch: {},
|
|
|
+ //方法集合
|
|
|
+ methods: {
|
|
|
+ getCurTime(curTime) {
|
|
|
+ this.curTime = curTime;
|
|
|
+ },
|
|
|
+ handleData() {
|
|
|
+ let resArr = [],
|
|
|
+ timeArr = [];
|
|
|
+ let leg = this.curQue.detail.length;
|
|
|
+ let curQue = JSON.parse(JSON.stringify(this.curQue));
|
|
|
+ curQue.detail.forEach((dItem, dIndex) => {
|
|
|
+ let endTime = 0;
|
|
|
+ if (dIndex < leg - 1) {
|
|
|
+ endTime = curQue.detail[dIndex + 1].timeList[0];
|
|
|
+ dItem.timeList.push(endTime);
|
|
|
+ dItem.timeList = this.handleTimeList(dItem.timeList);
|
|
|
+ } else {
|
|
|
+ dItem.timeList = this.handleTimeList(dItem.timeList);
|
|
|
+ endTime = curQue.mp3_list[0].duration;
|
|
|
+ dItem.timeList.push(endTime);
|
|
|
+ }
|
|
|
+
|
|
|
+ dItem.wordsList.forEach((sItem, sIndex) => {
|
|
|
+ let sentArr = [];
|
|
|
+ sItem.forEach((wItem, wIndex) => {
|
|
|
+ let obj = {
|
|
|
+ paraIndex: dIndex, //段落索引
|
|
|
+ sentIndex: sIndex, //在段落中句子索引
|
|
|
+ wordIndex: wIndex, //单词的索引
|
|
|
+ pinyin: wItem.pinyin,
|
|
|
+ chs: wItem.chs,
|
|
|
+ padding: wItem.padding,
|
|
|
+ className: wItem.className,
|
|
|
+ startTime: startTime,
|
|
|
+ endTime: endTime,
|
|
|
+ };
|
|
|
+ sentArr.push(obj);
|
|
|
+ });
|
|
|
+ resArr.push(sentArr);
|
|
|
+ });
|
|
|
+
|
|
|
+ timeArr.push(dItem.timeList);
|
|
|
+ });
|
|
|
+ let timeList = [];
|
|
|
+ timeArr.forEach((item) => {
|
|
|
+ item.forEach((aItem) => {
|
|
|
+ if (timeList.indexOf(aItem) < 0) {
|
|
|
+ timeList.push(aItem);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+ this.resObj = { sentList: resArr, timeList: timeList };
|
|
|
+ console.log(this.resObj);
|
|
|
+ },
|
|
|
+ handleData2() {
|
|
|
+ let resArr = [],
|
|
|
+ timeArr = [];
|
|
|
+ let leg = this.curQue.detail.length;
|
|
|
+ let curQue = JSON.parse(JSON.stringify(this.curQue));
|
|
|
+ curQue.detail.forEach((dItem, dIndex) => {
|
|
|
+ let endTime = 0;
|
|
|
+ if (dIndex < leg - 1) {
|
|
|
+ endTime = curQue.detail[dIndex + 1].timeList[0];
|
|
|
+ dItem.timeList.push(endTime);
|
|
|
+ dItem.timeList = this.handleTimeList(dItem.timeList);
|
|
|
+ } else {
|
|
|
+ dItem.timeList = this.handleTimeList(dItem.timeList);
|
|
|
+ endTime = curQue.mp3_list[0].duration;
|
|
|
+ dItem.timeList.push(endTime);
|
|
|
+ }
|
|
|
+
|
|
|
+ dItem.wordsList.forEach((sItem, sIndex) => {
|
|
|
+ let time_diff = dItem.timeList[sIndex + 1] - dItem.timeList[sIndex];
|
|
|
+ let wordsLeg = dItem.sentences[sIndex].length;
|
|
|
+ let wordTime = time_diff / wordsLeg;
|
|
|
+ // console.log(time_diff, wordsLeg, wordTime);
|
|
|
+ let sentArr = [];
|
|
|
+ sItem.forEach((wItem, wIndex) => {
|
|
|
+ let preTotal = wIndex > 0 ? sentArr[wIndex - 1].endTime : 0;
|
|
|
+ let endTime =
|
|
|
+ wIndex > 0
|
|
|
+ ? wordTime * wItem.chs.length + preTotal
|
|
|
+ : dItem.timeList[sIndex] + wordTime * wItem.chs.length;
|
|
|
+ //console.log("endTime" + endTime);
|
|
|
+ let startTime =
|
|
|
+ wIndex > 0 ? sentArr[wIndex - 1].endTime : dItem.timeList[sIndex];
|
|
|
+ this.judgePad(sItem, wItem, wIndex);
|
|
|
+ let obj = {
|
|
|
+ paraIndex: dIndex, //段落索引
|
|
|
+ sentIndex: sIndex, //在段落中句子索引
|
|
|
+ wordIndex: wIndex, //单词的索引
|
|
|
+ pinyin: wItem.pinyin,
|
|
|
+ chs: wItem.chs,
|
|
|
+ padding: wItem.padding,
|
|
|
+ className: wItem.className,
|
|
|
+ startTime: startTime,
|
|
|
+ endTime: endTime,
|
|
|
+ };
|
|
|
+ sentArr.push(obj);
|
|
|
+ });
|
|
|
+ resArr.push(sentArr);
|
|
|
+ });
|
|
|
+
|
|
|
+ timeArr.push(dItem.timeList);
|
|
|
+ });
|
|
|
+ let timeList = [];
|
|
|
+ timeArr.forEach((item) => {
|
|
|
+ item.forEach((aItem) => {
|
|
|
+ if (timeList.indexOf(aItem) < 0) {
|
|
|
+ timeList.push(aItem);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+ this.resObj = { sentList: resArr, timeList: timeList };
|
|
|
+ console.log(this.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;
|
|
|
+ },
|
|
|
+ //计算总时间
|
|
|
+ countWordTime(sentArr) {
|
|
|
+ let total = 0;
|
|
|
+ sentArr.forEach((item) => {
|
|
|
+ total += item.endTime;
|
|
|
+ });
|
|
|
+ return total;
|
|
|
+ },
|
|
|
+ //点击播放某个句子
|
|
|
+ handleChangeTime(time) {
|
|
|
+ this.curTime = time;
|
|
|
+ this.$refs.audioLine.onTimeupdateTime(time);
|
|
|
+ },
|
|
|
+ },
|
|
|
+ //生命周期 - 创建完成(可以访问当前this实例)
|
|
|
+ created() {},
|
|
|
+ //生命周期 - 挂载完成(可以访问DOM元素)
|
|
|
+ mounted() {
|
|
|
+ console.log(this.curQue);
|
|
|
+ if (this.curQue) {
|
|
|
+ this.handleData();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ beforeCreate() {}, //生命周期 - 创建之前
|
|
|
+ beforeMount() {}, //生命周期 - 挂载之前
|
|
|
+ beforeUpdate() {}, //生命周期 - 更新之前
|
|
|
+ updated() {}, //生命周期 - 更新之后
|
|
|
+ beforeDestroy() {}, //生命周期 - 销毁之前
|
|
|
+ destroyed() {}, //生命周期 - 销毁完成
|
|
|
+ activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发
|
|
|
+};
|
|
|
+</script>
|
|
|
+<style lang='scss' scoped>
|
|
|
+//@import url(); 引入公共css类
|
|
|
+.NNPE-ArticleView {
|
|
|
+ width: 100%;
|
|
|
+ .NNPE-detail {
|
|
|
+ clear: both;
|
|
|
+ overflow: hidden;
|
|
|
+ width: 100%;
|
|
|
+ background: #ffffff;
|
|
|
+ border: 1px solid rgba(0, 0, 0, 0.1);
|
|
|
+ box-sizing: border-box;
|
|
|
+ border-radius: 8px;
|
|
|
+ margin-bottom: 8px;
|
|
|
+ box-sizing: border-box;
|
|
|
+ padding: 8px 16px 0px;
|
|
|
+ .NNPE-words {
|
|
|
+ float: left;
|
|
|
+ padding: 0 0px 8px 0px;
|
|
|
+ &.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: 20px;
|
|
|
+ color: #000000;
|
|
|
+ height: 20px;
|
|
|
+ &.textLeft {
|
|
|
+ text-align: left;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ &.NNPE-chs {
|
|
|
+ font-family: "FZJCGFKTK";
|
|
|
+ font-size: 20px;
|
|
|
+ line-height: 150%;
|
|
|
+ color: #000000;
|
|
|
+ &.active {
|
|
|
+ background: rgba(60, 200, 99, 0.2);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ &.padding {
|
|
|
+ padding-right: 6px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|