guanchunjie 4 years ago
parent
commit
ecafde7a8a
20 changed files with 2519 additions and 83 deletions
  1. 3 0
      src/components/Adult/common/data.js
  2. 163 0
      src/components/Adult/inputModules/DialogueAnswerChs/index.vue
  3. 0 1
      src/components/Adult/inputModules/DialogueArticleChs/components/SegbywordChs.vue
  4. 29 1
      src/components/Adult/inputModules/DialogueArticleChs/index.vue
  5. 92 0
      src/components/Adult/inputModules/DialogueTem/components/ArticleChs.vue
  6. 140 0
      src/components/Adult/inputModules/DialogueTem/components/ClauseresultChs.vue
  7. 87 0
      src/components/Adult/inputModules/DialogueTem/components/CreatetimelistChs.vue
  8. 323 0
      src/components/Adult/inputModules/DialogueTem/components/ParagraphChs.vue
  9. 129 0
      src/components/Adult/inputModules/DialogueTem/components/Pinyin.vue
  10. 196 0
      src/components/Adult/inputModules/DialogueTem/components/RoleChs.vue
  11. 409 0
      src/components/Adult/inputModules/DialogueTem/components/SegbywordChs.vue
  12. 650 0
      src/components/Adult/inputModules/DialogueTem/index.vue
  13. 31 3
      src/components/Adult/preview/DialogueArticleViewChs/NormalModelChs.vue
  14. 30 3
      src/components/Adult/preview/DialogueArticleViewChs/PhraseModelChs.vue
  15. 69 28
      src/components/Adult/preview/DialogueArticleViewChs/Practicechs.vue
  16. 30 3
      src/components/Adult/preview/DialogueArticleViewChs/WordModelChs.vue
  17. 9 0
      src/components/Adult/preview/DialogueArticleViewChs/index.vue
  18. 22 8
      src/components/Adult/preview/WordPhrase.vue
  19. 94 36
      src/components/Adult/preview/components/WordPhraseDetail.vue
  20. 13 0
      src/views/adultInput.vue

+ 3 - 0
src/components/Adult/common/data.js

@@ -18,6 +18,9 @@ let fnData = [{
   name: "注释",
 
 }, {
+  type: "dialogue_answer_chs",
+  name: "对话题模板"
+}, {
   type: "sentence_chs",
   name: "句子模板",
   list: [{

+ 163 - 0
src/components/Adult/inputModules/DialogueAnswerChs/index.vue

@@ -0,0 +1,163 @@
+<!--  -->
+<template>
+  <div class="dia-ans-choice" v-if="curQue">
+    <div class="adult-book-input-item">
+      <span class="adult-book-lable">标题:</span>           
+      <el-input
+        style="width: 300px"
+        placeholder="请输入标题"
+        v-model="curQue.title"
+        @blur="onBlur(curQue, 'title')"
+        class="adult-book-input"
+        :autosize="{ minRows: 2 }"
+      ></el-input>
+    </div>
+    <div class="NPC-Book-model">
+      <span class="adult-book-input-lable">拼音位置:</span>
+      <el-radio-group v-model="curQue.pyPosition">
+        <el-radio :label="'top'">字上面</el-radio>
+        <el-radio :label="'bottom'">字下面</el-radio>
+      </el-radio-group>
+    </div>
+    <div class="adult-book-input">
+      <div
+        class="dialogue-list"
+        v-for="(item, index) in curQue.list"
+        :key="'list' + index"
+      >
+        <span>{{ index + 1 }}</span>
+        <span class="editDialogue" @click="editDialogue(index)"
+          >编辑此对话</span
+        >
+      </div>
+
+      <el-button type="primary" @click="addDialogue">添加对话</el-button>
+    </div>
+    <div class="dialogWindow" title="提示" v-show="dialogVisible">
+      <div class="inner">
+        <DialogueTem :curQue="curQue.list[listIndex]" />
+        <span slot="footer" class="dialog-footer">
+          <el-button @click="dialogVisible = false">取 消</el-button>
+          <el-button type="primary" @click="dialogVisible = false"
+            >确 定</el-button
+          >
+        </span>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import DialogueTem from "../DialogueTem";
+export default {
+  components: {
+    DialogueTem,
+  },
+  props: ["curQue", "changeCurQue"],
+  data() {
+    return {
+      dialogVisible: false,
+      listIndex: 0,
+      data_structure: {
+        title: "",
+        type: "dialogue_answer_chs",
+        name: "对话题",
+        model: 1,
+        pyPosition: "top", //top 拼音在上面;bottom 拼音在下面
+        list: [
+          {
+            number: "",
+            notice: "", //文章提示信息
+            mp3_list: [],
+            img_list: [],
+            article: "",
+            roleList: [],
+            detail: [],
+            wordTime: [],
+            taskId: "",
+          },
+        ],
+      },
+    };
+  },
+  computed: {},
+  watch: {},
+  //方法集合
+  methods: {
+    onBlur(item, field) {
+      item[field] = item[field] ? item[field].trim() : "";
+    },
+    editDialogue(index) {
+      this.listIndex = index;
+      this.dialogVisible = true;
+    },
+    addDialogue() {
+      let obj = JSON.parse(JSON.stringify(this.data_structure.list[0]));
+      this.curQue.list.push(obj);
+    },
+    initCurQueData() {
+      let res_data = JSON.parse(JSON.stringify(this.data_structure));
+      this.changeCurQue(res_data);
+    },
+  },
+  //生命周期 - 创建完成(可以访问当前this实例)
+  created() {},
+  //生命周期 - 挂载完成(可以访问DOM元素)
+  mounted() {
+    console.log("文章保存");
+    console.log(this.curQue);
+    if (this.curQue) {
+      if (this.curQue.detail && this.curQue.detail.length > 0) {
+        if (this.curQue.detail[0].para) {
+          this.isPara = true;
+        }
+        if (this.curQue.detail[0].sentences.length > 0) {
+          this.isClause = true;
+        }
+        if (this.curQue.detail[0].seg_words.length > 0) {
+          this.isByWord = true;
+        }
+      }
+    } else {
+      this.initCurQueData();
+    }
+  },
+  beforeCreate() {}, //生命周期 - 创建之前
+  beforeMount() {}, //生命周期 - 挂载之前
+  beforeUpdate() {}, //生命周期 - 更新之前
+  updated() {}, //生命周期 - 更新之后
+  beforeDestroy() {}, //生命周期 - 销毁之前
+  destroyed() {}, //生命周期 - 销毁完成
+  activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发
+};
+</script>
+<style lang='scss' scoped>
+//@import url(); 引入公共css类
+.editDialogue {
+  width: 200px;
+  height: 40px;
+  text-align: center;
+  line-height: 40px;
+}
+.dialogWindow {
+  position: fixed;
+  left: 0;
+  top: 0;
+  z-index: 3000;
+  background: rgba(0, 0, 0, 0.6);
+  width: 100%;
+  min-height: 100vh;
+  z-index: 1000;
+  box-sizing: border-box;
+  padding: 20px;
+  > .inner {
+    background: #fff;
+    width: 1000px;
+    height: 860px;
+    overflow-y: auto;
+    margin: 0 auto;
+    box-sizing: border-box;
+    padding: 20px 32px;
+  }
+}
+</style>

+ 0 - 1
src/components/Adult/inputModules/DialogueArticleChs/components/SegbywordChs.vue

@@ -233,7 +233,6 @@ export default {
       this.proofParaIndex = index;
       this.sentIndex = sentIndex;
       this.paraCon = item;
-      this.paraCon.sentencesEn = sentencesEn;
       this.wordsListLeg = this.paraCon.sentences.length;
     },
     checkEn(str) {

+ 29 - 1
src/components/Adult/inputModules/DialogueArticleChs/index.vue

@@ -5,6 +5,16 @@
     v-if="curQue"
     v-loading="loading"
   >
+    <div class="adult-book-input-item">
+      <span class="adult-book-lable">序号:</span>           
+      <el-input
+        style="width: 300px"
+        placeholder="请输入序号"
+        v-model="curQue.title"
+        @blur="onBlur(curQue, 'number')"
+        class="adult-book-input"
+      ></el-input>
+    </div>
     <div class="Big-Book-img">
       <UploadArt
         :change-fill-id="changeImage"
@@ -51,6 +61,17 @@
         :handleMp3Base64="handleChange"
       />
     </div>
+    <div class="adult-book-input-item">
+      <span class="adult-book-lable">文章提示:</span>
+      <el-input
+        class="adult-book-input"
+        type="textarea"
+        :autosize="{ minRows: 2 }"
+        placeholder="请输入文章提示"
+        v-model="curQue.notice"
+        @blur="onBlur(curQue, 'notice')"
+      ></el-input>
+    </div>
     <div class="NPC-Book-role">
       <ul class="adult-book-input-role" v-if="curQue.roleList.length > 0">
         <li
@@ -181,7 +202,7 @@ import Createtimelist from "./components/CreatetimelistChs.vue";
 import RoleChs from "./components/RoleChs.vue";
 
 export default {
-  name: "ArticleTemChs",
+  name: "DialogueAnswerChs",
   components: {
     Upload,
     UploadArt,
@@ -241,6 +262,7 @@ export default {
         name: "课文",
         model: 1,
         pyPosition: "top", //top 拼音在上面;bottom 拼音在下面
+        notice: "", //文章提示信息
         mp3_list: [],
         img_list: [],
         article: "",
@@ -256,6 +278,9 @@ export default {
   watch: {},
   //方法集合
   methods: {
+    onBlur(item, field) {
+      item[field] = item[field] ? item[field].trim() : "";
+    },
     changeMp3(fileList) {
       const articleImgList = JSON.parse(JSON.stringify(fileList));
       const articleImgRes = [];
@@ -491,6 +516,9 @@ export default {
       if (!this.curQue.taskId) {
         this.curQue.taskId = "";
       }
+      if (!this.curQue.notice) {
+        this.curQue.notice = "";
+      }
       if (this.curQue.detail && this.curQue.detail.length > 0) {
         if (this.curQue.detail[0].para) {
           this.isPara = true;

+ 92 - 0
src/components/Adult/inputModules/DialogueTem/components/ArticleChs.vue

@@ -0,0 +1,92 @@
+<!--  -->
+<template>
+  <div class="NPC-Dialogue-article" v-if="curQue">
+    <span class="adult-book-lable-bottom">文章:</span>
+    <el-input
+      class="adult-book-input-800"
+      type="textarea"
+      :autosize="{ minRows: 10 }"
+      placeholder="请输入文章"
+      v-model="curQue.article"
+      @blur="onBlur(curQue, 'article')"
+    ></el-input>
+    <div style="margin-top: 10px">
+      <el-button type="primary" size="small" @click="createPara"
+        >生成段落</el-button
+      >
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  components: {},
+  props: ["curQue", "changeIsPara"],
+  data() {
+    return {
+      detailItem: {
+        roleIndex: "",
+        paraIndex: 0,
+        para: "",
+        sentences: [],
+        segList: [],
+        seg_words: [],
+        wordsList: [],
+        timeList: [],
+        isTitle: false,
+        sentencesEn: [],
+      },
+    };
+  },
+  computed: {},
+  watch: {},
+  //方法集合
+  methods: {
+    onBlur(item, field) {
+      item[field] = item[field] ? item[field].trim() : "";
+    },
+    createPara() {
+      let paraArr = this.curQue.article.split(/\n+/g);
+
+      this.$set(this.curQue, "detail", []);
+      for (let i = 0; i < paraArr.length; i++) {
+        let con = paraArr[i];
+        let detailItem = JSON.parse(JSON.stringify(this.detailItem));
+        detailItem.para = con;
+        detailItem.paraIndex = i;
+        this.curQue.detail.push(detailItem);
+        // if (this.curQue.detail.length == 0) {
+        //   detailItem.para = con;
+        //   detailItem.paraIndex = i;
+        //   this.curQue.detail.push(detailItem);
+        // } else {
+        //   if (!(this.curQue.detail[i] && this.curQue.detail[i].para == con)) {
+        //     this.$set(this.curQue.detail[i], "para", con);
+        //   }
+        // }
+      }
+      this.changeIsPara();
+      this.$message.success("生成成功");
+    },
+  },
+  //生命周期 - 创建完成(可以访问当前this实例)
+  created() {},
+  //生命周期 - 挂载完成(可以访问DOM元素)
+  mounted() {},
+  beforeCreate() {}, //生命周期 - 创建之前
+  beforeMount() {}, //生命周期 - 挂载之前
+  beforeUpdate() {}, //生命周期 - 更新之前
+  updated() {}, //生命周期 - 更新之后
+  beforeDestroy() {}, //生命周期 - 销毁之前
+  destroyed() {}, //生命周期 - 销毁完成
+  activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发
+};
+</script>
+<style lang='scss' scoped>
+//@import url(); 引入公共css类
+.NPC-Dialogue-article {
+  .NPC-Dialogue-input {
+    margin: 20px 0;
+  }
+}
+</style>

+ 140 - 0
src/components/Adult/inputModules/DialogueTem/components/ClauseresultChs.vue

@@ -0,0 +1,140 @@
+<!-- 分句组件 -->
+<template>
+  <div class="Big-Book-Maxwidth">
+    <div class="Big-Book-con-top">
+      <span class="adult-book-lable-bottom">分句结果:</span>
+    </div>
+    <div
+      class="NPC-sentence-list"
+      v-for="(item, index) in para_list"
+      :key="'sent_list' + index"
+    >
+      <template v-if="item.para">
+        <el-input
+          class="adult-book-input-800"
+          type="textarea"
+          :autosize="{ minRows: 3 }"
+          placeholder="请输入内容"
+          v-model="item.para"
+          :readonly="item.isReadonly"
+          @change="handleChange(item.para, index)"
+          @blur="onBlur(item, 'para')"
+        ></el-input>
+        <el-button
+          v-if="item.isReadonly"
+          type="danger"
+          size="small"
+          @click="editClause(item)"
+          >编辑</el-button
+        >
+        <el-button v-else type="primary" size="small" @click="sureClause(index)"
+          >生词分词</el-button
+        >
+      </template>
+    </div>
+    <!-- <el-button type="primary" size="small" @click="oneClickResult"
+      >一键生成分词</el-button
+    > -->
+  </div>
+</template>
+
+<script>
+export default {
+  name: "Clauseresult",
+  components: {},
+  props: ["curQue", "segByWord"],
+  data() {
+    return {
+      para_list: [],
+      paraIndex: "",
+    };
+  },
+  computed: {},
+  watch: {
+    "curQue.detail": {
+      handler: function (newVal, oldVal) {
+        this.handleSentence(JSON.parse(JSON.stringify(newVal)));
+      },
+      deep: true,
+    },
+  },
+  //方法集合
+  methods: {
+    onBlur(item, field) {
+      item[field] = item[field] ? item[field].trim() : "";
+    },
+    //把句子拼成段落
+    handleSentence(detail) {
+      let paraList = [];
+      detail.forEach((item) => {
+        let para = item.sentences.join("\n");
+        let obj = {
+          para: para,
+          isReadonly: false,
+        };
+        paraList.push(obj);
+      });
+      this.para_list = paraList;
+      if (this.paraIndex !== "") {
+        this.para_list[this.paraIndex].isReadonly = true;
+      }
+    },
+    //input内容变化
+    handleChange(value, index) {
+      let _this = this;
+      let sentArr = value.split("\n");
+      this.$set(_this.curQue.detail[index], "sentences", sentArr);
+    },
+    sureClause(index) {
+      debugger;
+      let _this = this;
+      let para_list = JSON.parse(JSON.stringify(_this.para_list));
+      let paraStr = para_list[index].para.replace(/\n/g, "");
+      let orgPara = _this.curQue.detail[index].para;
+      if (paraStr != orgPara) {
+        this.$message.warning("跟上面的段落内容不一致,请检查!");
+        return;
+      }
+      this.paraIndex = index;
+      let sentArr = _this.para_list[index].para.split("\n");
+      _this.$set(_this.curQue.detail[index], "sentences", sentArr);
+      _this.segByWord(_this.curQue.detail[index].sentences, index);
+    },
+    editClause(item) {
+      item.isReadonly = false;
+    },
+    saveClause(item, index) {
+      let _this = this;
+      item.isReadonly = true;
+      let sentArr = item.para.split("\n");
+      _this.$set(_this.curQue.detail[index], "sentences", sentArr);
+    },
+    oneClickResult() {},
+  },
+  //生命周期 - 创建完成(可以访问当前this实例)
+  created() {},
+  //生命周期 - 挂载完成(可以访问DOM元素)
+  mounted() {
+    console.log("====分句====");
+    console.log(this.curQue);
+    let detail = JSON.parse(JSON.stringify(this.curQue.detail));
+    this.handleSentence(detail);
+  },
+  beforeCreate() {}, //生命周期 - 创建之前
+  beforeMount() {}, //生命周期 - 挂载之前
+  beforeUpdate() {}, //生命周期 - 更新之前
+  updated() {}, //生命周期 - 更新之后
+  beforeDestroy() {}, //生命周期 - 销毁之前
+  destroyed() {}, //生命周期 - 销毁完成
+  activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发
+};
+</script>
+<style lang='scss' scoped>
+//@import url(); 引入公共css类
+.NPC-sentence-list {
+  display: flex;
+  justify-content: flex-start;
+  align-items: flex-end;
+  margin-bottom: 10px;
+}
+</style>

+ 87 - 0
src/components/Adult/inputModules/DialogueTem/components/CreatetimelistChs.vue

@@ -0,0 +1,87 @@
+<!-- 分句组件 -->
+<template>
+  <div class="Big-Book-Maxwidth">
+    <div
+      class="NPC-sentence-list"
+      v-for="(item, index) in detail"
+      :key="'detail' + index"
+    >
+      <span class="Big-Book-left-text">第{{ index + 1 }}段落</span>
+      <el-input
+        type="textarea"
+        :autosize="{ minRows: 3 }"
+        placeholder="请输入内容"
+        v-model="item.time_str"
+        @blur="onBlur(item, 'time_str')"
+      ></el-input>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "Createtimelist",
+  components: {},
+  props: ["curQue", "segByWord"],
+  data() {
+    return {
+      detail: [],
+    };
+  },
+  computed: {},
+  watch: {
+    // "curQue.sentences": {
+    //   handler: function (newVal, oldVal) {
+    //     this.handleSentence(JSON.parse(JSON.stringify(newVal)));
+    //   },
+    //   deep: true,
+    // },
+  },
+  //方法集合
+  methods: {
+    onBlur(item, field) {
+      item[field] = item[field] ? item[field].trim() : "";
+    },
+    //把句子拼成段落
+    handleSentence(detail) {
+      detail.forEach((deItem) => {
+        if (deItem.timeList.length > 0) {
+          let time_Arr = [];
+          deItem.timeList.forEach((tItem, tIndex) => {
+            time_Arr.push("[" + tItem + "]" + deItem.sentences[tIndex]);
+          });
+          deItem.time_str = time_Arr.join("\n");
+        } else {
+          deItem.time_str = "";
+        }
+      });
+      this.detail = detail;
+    },
+  },
+  //生命周期 - 创建完成(可以访问当前this实例)
+  created() {},
+  //生命周期 - 挂载完成(可以访问DOM元素)
+  mounted() {
+    console.log("====分句lrc文件====");
+    console.log(this.curQue);
+    let detail = JSON.parse(JSON.stringify(this.curQue.detail));
+    this.handleSentence(detail);
+  },
+  beforeCreate() {}, //生命周期 - 创建之前
+  beforeMount() {}, //生命周期 - 挂载之前
+  beforeUpdate() {}, //生命周期 - 更新之前
+  updated() {}, //生命周期 - 更新之后
+  beforeDestroy() {}, //生命周期 - 销毁之前
+  destroyed() {}, //生命周期 - 销毁完成
+  activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发
+};
+</script>
+<style lang='scss' scoped>
+//@import url(); 引入公共css类
+.NPC-sentence-list {
+  display: flex;
+  justify-content: flex-start;
+  align-items: flex-end;
+  margin-bottom: 10px;
+}
+</style>

+ 323 - 0
src/components/Adult/inputModules/DialogueTem/components/ParagraphChs.vue

@@ -0,0 +1,323 @@
+<!--分句组件-->
+<template>
+  <div class="Big-Book-Maxwidth">
+    <div class="Big-Book-con">
+      <div class="Big-Book-con-top">
+        <span class="Big-Book-left-text">文章段落:</span>
+        <el-button type="text" size="small" @click="editPara" v-if="readonly"
+          >编辑段落</el-button
+        >
+      </div>
+      <div
+        class="NPC-para-list"
+        v-for="(item, index) in curQue.detail"
+        :key="'para' + index"
+      >
+        <span class="NPC-para-number">{{ index + 1 }}.</span>
+        <el-select
+          v-model="item.roleIndex"
+          placeholder="请选择角色"
+          style="width:120px;margin-right:10px;font-size;12px;"
+        >
+          <el-option
+            v-for="(rItem, rIndex) in roleList"
+            :key="'role' + index + rIndex"
+            :label="rItem.label"
+            :value="rItem.id"
+          >
+          </el-option>
+        </el-select>
+        <el-input
+          style="width: 500px"
+          type="textarea"
+          :autosize="{ minRows: 3 }"
+          placeholder="请输入内容"
+          v-model="item.para"
+          @blur="onBlur(item, 'para')"
+          :readonly="readonly"
+        ></el-input>
+        <el-button
+          size="small"
+          type="warning"
+          @click="addRemark(item, index)"
+          >{{ item.remark ? "修改备注" : "添加备注" }}</el-button
+        >
+        <img
+          @click="deleteOption(index)"
+          class="close"
+          src="../../../../../assets/adult/del-close.png"
+          alt=""
+          v-if="!readonly"
+        />
+      </div>
+      <el-button type="primary" size="small" @click="sureSegResult"
+        >确定分句</el-button
+      >
+    </div>
+    <el-dialog title="标注" :visible.sync="remarkVisible" width="50%">
+      <div class="remark" v-if="remark">
+        <div class="adult-book-input-item">
+          <span class="adult-book-lable">中文:</span>
+          <el-input
+            class="adult-book-input"
+            type="textarea"
+            :autosize="{ minRows: 2 }"
+            placeholder="请输入中文"
+            v-model="remark.chs"
+            @blur="onBlur(remark, 'chs')"
+          ></el-input>
+        </div>
+        <div class="adult-book-input-item">
+          <span class="adult-book-lable">英文:</span>
+          <el-input
+            class="adult-book-input"
+            type="textarea"
+            :autosize="{ minRows: 2 }"
+            placeholder="请输入英文"
+            v-model="remark.en"
+            @blur="onBlur(remark, 'en')"
+          ></el-input>
+        </div>
+      </div>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="remarkVisible = false">取 消</el-button>
+        <el-button type="primary" @click="saveRemark">保 存</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import "@/utils/pinyin_dict_withtone";
+import "@/utils/pinyinUtil";
+export default {
+  components: {},
+  props: ["curQue", "sureSeg", "isClause", "changeIsClause"],
+  data() {
+    return {
+      imgNumber: 10,
+      mp3Number: 10,
+      fileCon: {
+        img_list: [],
+        mp3_list: [],
+      },
+      readonly: false,
+      roleList: [],
+      remarkVisible: false,
+      remark: null,
+      paraIndex: 0,
+    };
+  },
+  computed: {},
+  watch: {
+    isClause(newVal, oldVal) {
+      this.readonly = newVal;
+    },
+    "curQue.roleList": {
+      handler: function (newVal, oldVal) {
+        if (newVal.length > 0) {
+          this.initRoleList();
+        }
+      },
+      deep: true,
+    },
+  },
+  //方法集合
+  methods: {
+    onBlur(item, field) {
+      item[field] = item[field] ? item[field].trim() : "";
+    },
+    onBlurIndex(index, field) {
+      let res = this.curQue[field][index].trim();
+      this.$set(this.curQue[field], index, res);
+    },
+    sureSegResult() {
+      let _this = this;
+      _this.readonly = true;
+      _this.sureSeg();
+    },
+    initRoleList() {
+      let roleList = JSON.parse(JSON.stringify(this.curQue.roleList));
+      roleList = roleList.map((item) => {
+        if (item.detail.fullName) {
+          item.label = item.detail.fullName;
+        } else if (item.role) {
+          item.label = item.role;
+        } else if (item.img_list.length > 0) {
+          item.label = "头像" + (item.id + 1);
+        }
+        return item;
+      });
+      this.roleList = roleList;
+      console.log(this.roleList);
+    },
+    // 点击生成拼音
+    getPinyin(item) {
+      console.log(12356);
+      let bool = false;
+      let value = "";
+      if (item.con == "") {
+        this.$message.info("请先输入内容,再生成拼音");
+        bool = true;
+      } else {
+        value = item.con;
+      }
+      if (bool) {
+        return;
+      }
+      let result = pinyinUtil.getPinyin(value);
+      item.pinyin = result;
+    },
+
+    deleteOption(index) {
+      if (index == 0) {
+        this.$message.warning("不能全部删除");
+        return;
+      }
+      this.curQue.detail.splice(index, 1);
+    },
+    addOption() {
+      let leg = this.curQue.detail.length;
+      let last = this.curQue.detail[leg - 1].para;
+      if (!last) {
+        this.$message.warning("数据不能全是空");
+        return;
+      }
+      let obj = {
+        paraIndex: leg,
+        para: "",
+        sentences: [],
+        segList: [],
+        seg_words: [],
+        wordsList: [],
+        timeList: [],
+      };
+      this.curQue.detail.push(obj);
+    },
+    editPara() {
+      this.$confirm("此操作需要重新校对分句分词, 是否继续?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+      })
+        .then(() => {
+          this.readonly = false;
+          this.changeIsClause(this.readonly);
+        })
+        .catch(() => {});
+    },
+    addRemark(item, index) {
+      this.paraIndex = index;
+      if (!item.remark) {
+        item.remark = {
+          chs: "",
+          en: "",
+        };
+      }
+      this.remark = JSON.parse(JSON.stringify(item.remark));
+      console.log(this.remark);
+      this.remarkVisible = true;
+    },
+    saveRemark() {
+      let _this = this;
+      _this.curQue.detail[_this.paraIndex].remark = JSON.parse(
+        JSON.stringify(this.remark)
+      );
+      this.remarkVisible = false;
+      console.log(_this.curQue.detail);
+    },
+  },
+  //生命周期 - 创建完成(可以访问当前this实例)
+  created() {},
+  //生命周期 - 挂载完成(可以访问DOM元素)
+  mounted() {
+    this.readonly = this.isClause;
+    if (this.curQue) {
+      this.initRoleList();
+    }
+  },
+  beforeCreate() {}, //生命周期 - 创建之前
+  beforeMount() {}, //生命周期 - 挂载之前
+  beforeUpdate() {}, //生命周期 - 更新之前
+  updated() {}, //生命周期 - 更新之后
+  beforeDestroy() {}, //生命周期 - 销毁之前
+  destroyed() {}, //生命周期 - 销毁完成
+  activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发
+};
+</script>
+<style lang='scss' scoped>
+//@import url(); 引入公共css类
+.Big-Book-Maxwidth {
+  .Big-Book-content {
+    &.m {
+      display: flex;
+      justify-content: flex-start;
+      align-items: flex-start;
+    }
+
+    .Big-Book-title {
+      font-size: 16px;
+      line-height: 40px;
+      color: #000;
+      margin-right: 15px;
+    }
+    .Big-Book-main {
+      > div {
+        margin-bottom: 10px;
+        &.Big-Book-pinyin {
+          display: flex;
+          justify-content: flex-start;
+          align-items: center;
+        }
+      }
+    }
+  }
+  .NPC-para-list {
+    display: flex;
+    justify-content: flex-start;
+    align-items: flex-start;
+    margin-bottom: 10px;
+    .NPC-para-number {
+      width: 28px;
+      margin-right: 5px;
+      text-align: right;
+    }
+  }
+  .close {
+    width: 24px;
+    cursor: pointer;
+  }
+  .NPC-footer-btn {
+    display: flex;
+    justify-content: flex-start;
+    align-items: flex-start;
+  }
+  .sureSegbtn {
+    width: 120px;
+    padding: 0 15px;
+    height: 40px;
+    color: #fff;
+    background-color: #409eff;
+    border-color: #409eff;
+    box-sizing: border-box;
+    border-radius: 4px;
+    text-align: center;
+    line-height: 40px;
+    cursor: pointer;
+    margin-right: 16px;
+  }
+  .addoption {
+    width: 120px;
+    padding: 0 15px;
+    height: 40px;
+    background: #f3f3f3;
+    border: 1px dashed rgba(0, 0, 0, 0.15);
+    box-sizing: border-box;
+    border-radius: 4px;
+    text-align: center;
+    line-height: 40px;
+    cursor: pointer;
+    margin-right: 16px;
+  }
+}
+</style>

+ 129 - 0
src/components/Adult/inputModules/DialogueTem/components/Pinyin.vue

@@ -0,0 +1,129 @@
+<!--  -->
+<template>
+  <div class="NPC-words-box" v-if="wordsList">
+    <span class="Big-Book-left-text">校对拼音:</span>
+    <div class="NPC-proof-pinyin">
+      <div class="NPC-words-list">
+        <el-table :data="wordsList" border style="width: 400px">
+          <el-table-column prop="chs" label="词" width="180"> </el-table-column>
+          <el-table-column label="拼音" width="220">
+            <template slot-scope="scope">
+              <el-input
+                v-model="scope.row.pinyin"
+                placeholder="请输入拼音"
+                @blur="onBlur(scope.row, 'pinyin')"
+              ></el-input>
+            </template>
+          </el-table-column>
+        </el-table>
+        <div></div>
+      </div>
+      <div class="yunmu">
+        <span>点击可复制</span>
+        <table border="1" class="yunmu-table">
+          <tr v-for="(item, index) in tableData" :key="'tableData' + index">
+            <td
+              v-for="(tdItem, tdIndex) in item"
+              :key="'pinyin' + index + tdIndex"
+              :id="'pinyin' + index + tdIndex"
+              @click="CopyToClipboard('pinyin' + index + tdIndex)"
+            >
+              {{ tdItem }}
+            </td>
+          </tr>
+        </table>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  components: {},
+  props: ["wordsList"],
+  data() {
+    return {
+      tableData: [
+        ["ā", "á", "ǎ", "à"],
+        ["ō", "ó", "ǒ", "ò"],
+        ["ē", "é", "ě", "è"],
+        ["ī", "í", "ǐ", "ì"],
+        ["ū", "ú", "ǔ", "ù"],
+        ["ǖ", "ǘ", "ǚ", "ǜ"],
+        ["Ā", "Á", "Â", "À"],
+        ["Ō", "Ó", "Ô", "Ò"],
+        ["Ē", "É", "Ê", "È"],
+        ["Ī", "Í", "Î", "Ì"],
+        ["Ū", "Ú", "Û", "Ù"],
+      ],
+    };
+  },
+  computed: {},
+  watch: {},
+  //方法集合
+  methods: {
+    onBlur(item, field) {
+      item[field] = item[field] ? item[field].trim() : "";
+      item[field] = item[field].replace(/\s+/g, "");
+    },
+    CopyToClipboard(element) {
+      var doc = document,
+        text = doc.getElementById(element),
+        range,
+        selection;
+      if (doc.body.createTextRange) {
+        range = doc.body.createTextRange();
+        range.moveToElementText(text);
+        range.select();
+      } else if (window.getSelection) {
+        selection = window.getSelection();
+        range = doc.createRange();
+        range.selectNodeContents(text);
+        selection.removeAllRanges();
+        selection.addRange(range);
+      }
+      document.execCommand("copy");
+      this.$message({
+        message: "复制成功",
+        type: "success",
+      });
+      window.getSelection().removeAllRanges();
+    },
+  },
+  //生命周期 - 创建完成(可以访问当前this实例)
+  created() {},
+  //生命周期 - 挂载完成(可以访问DOM元素)
+  mounted() {},
+  beforeCreate() {}, //生命周期 - 创建之前
+  beforeMount() {}, //生命周期 - 挂载之前
+  beforeUpdate() {}, //生命周期 - 更新之前
+  updated() {}, //生命周期 - 更新之后
+  beforeDestroy() {}, //生命周期 - 销毁之前
+  destroyed() {}, //生命周期 - 销毁完成
+  activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发
+};
+</script>
+<style lang='scss' scoped>
+//@import url(); 引入公共css类
+.NPC-words-box {
+  position: relative;
+  .NPC-proof-pinyin {
+    display: flex;
+    justify-content: flex-start;
+  }
+  .yunmu {
+    margin-left: 36px;
+    &-table {
+      width: 260px;
+      > tr {
+        td {
+          cursor: pointer;
+          text-align: center;
+          font-size: 16px;
+          height: 26px;
+        }
+      }
+    }
+  }
+}
+</style>

+ 196 - 0
src/components/Adult/inputModules/DialogueTem/components/RoleChs.vue

@@ -0,0 +1,196 @@
+<!--  -->
+<template>
+  <div class="NPC-da-role">
+    <div class="adult-book-input-item NPC-da-role-flex">
+      <span class="adult-book-lable">角色:</span>
+      <el-input
+        style="width: 110px"
+        class="NPC-role-input"
+        placeholder="请输入角色"
+        v-model="curRole.role"
+        @change="changeRole"
+        @blur="onBlur(curRole, 'role')"
+      ></el-input>
+      <span style="margin-right: 10px">或</span>
+      <Upload
+        type="image"
+        :changeFillId="changeImage"
+        :datafileList="fileCon.img_list"
+        :filleNumber="imgNumber"
+        :uploadType="'image'"
+      />
+    </div>
+    <div class="adult-book-input-item">
+      <span class="adult-book-lable">姓名:</span>
+      <el-input
+        class="NPC-role-input"
+        placeholder="请输入内容"
+        v-model="curRole.detail.fullName"
+        @blur="onBlur(curRole.detail, 'fullName')"
+      ></el-input>
+      <el-button type="danger" @click="segWord(curRole.detail.fullName)"
+        >分词</el-button
+      >
+    </div>
+    <div class="adult-book-input-item">
+      <span class="adult-book-lable">分词结果:</span>
+      <el-input
+        class="NPC-role-input"
+        placeholder="请输入分词结果"
+        v-model="curRole.detail.seg_words"
+        @change="handleChange"
+        @blur="onBlur(curRole.detail, 'seg_words')"
+      ></el-input>
+      <el-button type="danger" @click="_createPinyin">生成拼音</el-button>
+    </div>
+    <div
+      v-if="
+        curRole &&
+        curRole.detail.wordsList &&
+        curRole.detail.wordsList.length > 0
+      "
+    >
+      <Pinyin :wordsList="curRole.detail.wordsList" />
+    </div>
+  </div>
+</template>
+
+<script>
+import Upload from "../../../common/Upload.vue";
+import Pinyin from "./Pinyin.vue";
+const Base64 = require("js-base64").Base64;
+import { segSentences, BatchSegContent, createPinyin } from "@/api/ajax";
+export default {
+  name: "role",
+  components: {
+    Upload,
+    Pinyin,
+  },
+  props: ["curRole", "Upload"],
+  data() {
+    return {
+      fileCon: {
+        mp3_list: [],
+        img_list: [],
+      },
+      imgNumber: 1,
+      loading: false,
+    };
+  },
+  computed: {},
+  watch: {},
+  //方法集合
+  methods: {
+    onBlur(item, field) {
+      item[field] = item[field] ? item[field].trim() : "";
+    },
+    changeRole(val) {
+      if (val && this.curRole.img_list.length > 0) {
+        this.curRole.img_list.splice(0, 1);
+      }
+    },
+    handleChange(val) {
+      this.curRole.detail.seg_words = val.replace(/\s+/g, " ");
+      let arr = this.curRole.detail.seg_words.split(/\s+/);
+      this.$set(this.curRole.detail, "segList", arr);
+    },
+    //生成分词
+    segWord(sentence) {
+      if (!sentence) {
+        this.$message.warning("姓名不能为空");
+        return;
+      }
+      let sentences = [sentence];
+      this.loading = true;
+      let textList = [];
+      sentences.forEach((item) => {
+        let str = Base64.encode(item);
+        textList.push(str);
+      });
+      let data = {
+        textList: textList,
+      };
+      BatchSegContent(data).then((res) => {
+        this.loading = false;
+        let list = res.data.result.list;
+        this.$set(this.curRole.detail, "segList", list);
+        let seg_words = list.join(" ");
+        this.$set(this.curRole.detail, "seg_words", seg_words);
+      });
+    },
+    //生成拼音
+    _createPinyin() {
+      let res_str = this.curRole.detail.seg_words.replace(/\s+/g, "");
+      let org_sent = this.curRole.detail.fullName;
+      if (res_str.trim() != org_sent.trim()) {
+        this.$message.warning("跟原句不一致,请检查是否误删除或新增其他内容");
+        return;
+      }
+      let textListList = [];
+      let segArr = JSON.parse(JSON.stringify(this.curRole.detail.segList));
+      segArr.forEach((item) => {
+        let str = Base64.encode(item);
+        textListList.push(str);
+      });
+      let data = {
+        textListList: [textListList],
+      };
+      createPinyin(data).then((res) => {
+        let wordsList = res.data.result[0];
+        this.$set(this.curRole.detail, "wordsList", wordsList);
+      });
+    },
+    changeImage(fileList) {
+      const articleImgList = JSON.parse(JSON.stringify(fileList));
+      const articleImgRes = [];
+      articleImgList.forEach((item) => {
+        if (item.response) {
+          const obj = {
+            name: item.name,
+            url: item.response.file_info_list[0].file_url,
+            id: "[FID##" + item.response.file_info_list[0].file_id + "##FID]",
+          };
+          articleImgRes.push(obj);
+        }
+      });
+      //this.articleImgList = articleImgRes;
+      this.curRole.img_list = JSON.parse(JSON.stringify(articleImgRes));
+      this.curRole.role = "";
+    },
+  },
+  //生命周期 - 创建完成(可以访问当前this实例)
+  created() {},
+  //生命周期 - 挂载完成(可以访问DOM元素)
+  mounted() {
+    if (this.curRole) {
+      this.fileCon.img_list = this.curRole.img_list;
+    }
+  },
+  beforeCreate() {}, //生命周期 - 创建之前
+  beforeMount() {}, //生命周期 - 挂载之前
+  beforeUpdate() {}, //生命周期 - 更新之前
+  updated() {}, //生命周期 - 更新之后
+  beforeDestroy() {}, //生命周期 - 销毁之前
+  destroyed() {}, //生命周期 - 销毁完成
+  activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发
+};
+</script>
+<style lang='scss' scoped>
+//@import url(); 引入公共css类
+.NPC-da-role {
+  width: 100%;
+  &-flex {
+    display: flex;
+    justify-content: flex-start;
+    align-items: center;
+  }
+}
+</style>
+<style lang="scss">
+.NPC-da-role {
+  .NPC-role-input {
+    width: 300px;
+    margin-right: 10px;
+  }
+}
+</style>

+ 409 - 0
src/components/Adult/inputModules/DialogueTem/components/SegbywordChs.vue

@@ -0,0 +1,409 @@
+<!-- 分句组件 -->
+<template>
+  <div class="Big-Book-Maxwidth">
+    <div class="Big-Book-con-top">
+      <span class="Big-Book-left-text">分词结果:</span>
+    </div>
+    <div
+      class="NPC-para-list"
+      v-for="(item, index) in wordsSegList"
+      :key="'sent_list' + index"
+    >
+      <div class="NPC-header">
+        <span>第{{ index + 1 }}段落</span>
+        <span class="open"></span>
+      </div>
+      <div
+        class="NPC-sentence-list"
+        v-for="(wordItem, sentIndex) in item.seg_words"
+        :key="sentIndex"
+      >
+        <el-input
+          type="textarea"
+          :autosize="{ minRows: 1 }"
+          placeholder="请输入内容"
+          v-model="wordItem.sent_str"
+          :readonly="!wordItem.isReadonly"
+          @change="handleChange"
+        ></el-input>
+        <el-button
+          type="danger"
+          size="small"
+          @click="proofSegWords(item, index, sentIndex)"
+          >校对</el-button
+        >
+      </div>
+    </div>
+
+    <el-dialog
+      title="校对分词"
+      :visible.sync="proofVisible"
+      width="60%"
+      :close-on-click-modal="false"
+      top="10px"
+    >
+      <span class="dialog-top-btn">
+        <el-button size="mini" v-if="sentIndex > 0" @click="prevSent"
+          >上一个</el-button
+        >
+        <el-button
+          size="mini"
+          v-if="sentIndex < wordsListLeg - 1"
+          @click="nextSent"
+          >下一个</el-button
+        >
+      </span>
+      <div class="NPC-words" v-if="paraCon">
+        <div class="NPC-words-box">
+          <span class="Big-Book-left-text">原句:</span>
+          <el-input
+            type="textarea"
+            :autosize="{ minRows: 1 }"
+            placeholder="请输入内容"
+            v-model="paraCon.sentences[sentIndex]"
+            :readonly="true"
+          ></el-input>
+        </div>
+        <div class="NPC-words-box" v-if="paraCon.sentencesEn">
+          <span class="Big-Book-left-text">翻译:</span>
+          <el-input
+            type="textarea"
+            :autosize="{ minRows: 1 }"
+            placeholder="请输入翻译"
+            v-model="paraCon.sentencesEn[sentIndex]"
+          ></el-input>
+        </div>
+        <div class="NPC-words-box">
+          <span class="Big-Book-left-text">分词:</span>
+          <el-input
+            type="textarea"
+            :autosize="{ minRows: 1 }"
+            placeholder="请输入内容"
+            v-model="paraCon.seg_words[sentIndex].sent_str"
+            @click="handleChangeWords"
+            @blur="onBlurIndex(sentIndex, 'seg_words')"
+          ></el-input>
+          <div class="NPC-gPinyin">
+            <el-button type="danger" size="small" @click="_createPinyin"
+              >确定生成拼音</el-button
+            >
+          </div>
+        </div>
+        <template>
+          <div class="NPC-words-box">
+            <span class="Big-Book-left-text">校对拼音:</span>
+            <div class="NPC-words-list">
+              <el-table
+                :data="paraCon.wordsList[sentIndex]"
+                border
+                style="width: 400px"
+              >
+                <el-table-column prop="chs" label="词" width="180">
+                </el-table-column>
+                <el-table-column label="拼音" width="220">
+                  <template slot-scope="scope">
+                    <el-input
+                      v-model="scope.row.pinyin"
+                      placeholder="请输入拼音"
+                      @blur="onBlur(scope.row, 'pinyin')"
+                    ></el-input>
+                  </template>
+                </el-table-column>
+              </el-table>
+              <div></div>
+            </div>
+            <div class="yunmu">
+              <span>点击可复制</span>
+              <table border="1" class="yunmu-table">
+                <tr
+                  v-for="(item, index) in tableData"
+                  :key="'tableData' + index"
+                >
+                  <td
+                    v-for="(tdItem, tdIndex) in item"
+                    :key="'td' + index + tdIndex"
+                    :id="'td' + index + tdIndex"
+                    @click="CopyToClipboard('td' + index + tdIndex)"
+                  >
+                    {{ tdItem }}
+                  </td>
+                </tr>
+              </table>
+            </div>
+          </div>
+          <span slot="footer" class="dialog-footer">
+            <el-button type="primary" @click="save">保存</el-button>
+          </span>
+        </template>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+              
+
+<script>
+import { createPinyin } from "@/api/ajax";
+import { Base64 } from "js-base64";
+export default {
+  name: "SegbywordChs",
+  components: {},
+  props: ["curQue", "paraIndex", "createPinyin", "segList"],
+  data() {
+    return {
+      proofParaIndex: 0, //校对句子所属的段落
+      wordsSegList: [],
+      proofVisible: false,
+      paraCon: null, //段落句子,校对分词和拼音
+      sentIndex: 0,
+      tableData: [
+        ["ā", "á", "ǎ", "à"],
+        ["ō", "ó", "ǒ", "ò"],
+        ["ē", "é", "ě", "è"],
+        ["ī", "í", "ǐ", "ì"],
+        ["ū", "ú", "ǔ", "ù"],
+        ["ǖ", "ǘ", "ǚ", "ǜ"],
+        ["Ā", "Á", "Â", "À"],
+        ["Ō", "Ó", "Ô", "Ò"],
+        ["Ē", "É", "Ê", "È"],
+        ["Ī", "Í", "Î", "Ì"],
+        ["Ū", "Ú", "Û", "Ù"],
+      ],
+      wordsListLeg: 0,
+    };
+  },
+  computed: {},
+  watch: {
+    segList: {
+      handler: function (newVal, oldVal) {
+        if (newVal != oldVal) {
+          this.getParaSegWordsResult();
+        }
+      },
+      deep: true,
+    },
+  },
+  //方法集合
+  methods: {
+    onBlur(item, field) {
+      item[field] = item[field] ? item[field].trim() : "";
+    },
+    onBlurIndex(index, field) {
+      let res = this.paraCon[field][index].sent_str.trim();
+      this.$set(this.paraCon[field][index], "sent_str", res);
+    },
+    //获取段落中句子分词结果
+    getParaSegWordsResult() {
+      let detail = this.curQue.detail;
+      for (let i = 0; i < detail.length; i++) {
+        if (detail[i].paraIndex == this.paraIndex) {
+          detail[i].seg_words = this.handleWordsList(detail[i].segList);
+        }
+      }
+      this.wordsSegList = detail;
+    },
+    handleWordsList(list) {
+      let seg_words = [];
+      list.forEach((item, index) => {
+        let sent_str = item.join(" ");
+        let obj = {
+          sent_str: sent_str,
+          isReadonly: false,
+        };
+        seg_words.push(obj);
+      });
+      return seg_words;
+    },
+    sureSegWords() {},
+    //input内容变化
+    handleChange(value) {
+      // console.log(value);
+      // let arr = value.split("\n");
+      // console.log(arr);
+    },
+    //改变分词的划分
+    handleChangeWords(value) {},
+    //判断是不是汉语
+    checkCh(str) {
+      var RegExp = new RegExp("[\\u4E00-\\u9FFF]", "g");
+      return RegExp.test(str);
+    },
+    //校对分词
+    proofSegWords(item, index, sentIndex) {
+      this.proofVisible = true;
+      this.proofParaIndex = index;
+      this.sentIndex = sentIndex;
+      this.paraCon = item;
+      this.wordsListLeg = this.paraCon.sentences.length;
+    },
+    checkEn(str) {
+      var RegExp = /^[a-zA-Z]+$/;
+      return RegExp.test(str);
+    },
+    //生成拼音
+    _createPinyin() {
+      let sentIndex = this.sentIndex;
+      let sent_arr = this.paraCon.seg_words[sentIndex].sent_str.split(/\s+/);
+      let res_str = "";
+      sent_arr.forEach((item) => {
+        if (item) {
+          let bool = this.checkEn(item);
+          if (bool) {
+            res_str += item.trim() + " ";
+          } else if (item == "(") {
+            res_str += " " + item.trim() + " ";
+          } else if (item == ")") {
+            res_str += " " + item.trim() + " ";
+          } else {
+            res_str += item.trim();
+          }
+        }
+      });
+      res_str = res_str.replace(/\s+/g, " ");
+      let org_sent = this.paraCon.sentences[sentIndex];
+      if (res_str.trim() != org_sent.trim()) {
+        this.$message.warning("跟原句不一致,请检查是否误删除或新增其他内容");
+        return;
+      }
+      let textListList = [];
+      let arr = this.paraCon.seg_words[sentIndex].sent_str.split(/\s+/);
+      this.$set(this.paraCon.segList, sentIndex, arr);
+      let segArr = this.paraCon.segList[sentIndex];
+      segArr.forEach((item) => {
+        let str = Base64.encode(item);
+        textListList.push(str);
+      });
+      let data = {
+        textListList: [textListList],
+      };
+      createPinyin(data).then((res) => {
+        let wordsList = res.data.result[0];
+        this.$set(this.paraCon.wordsList, sentIndex, wordsList);
+      });
+    },
+    CopyToClipboard(element) {
+      var doc = document,
+        text = doc.getElementById(element),
+        range,
+        selection;
+      if (doc.body.createTextRange) {
+        range = doc.body.createTextRange();
+        range.moveToElementText(text);
+        range.select();
+      } else if (window.getSelection) {
+        selection = window.getSelection();
+        range = doc.createRange();
+        range.selectNodeContents(text);
+        selection.removeAllRanges();
+        selection.addRange(range);
+      }
+      document.execCommand("copy");
+      this.$message({
+        message: "复制成功",
+        type: "success",
+      });
+      window.getSelection().removeAllRanges();
+    },
+    save() {
+      let _this = this;
+      let paraCon = JSON.parse(JSON.stringify(this.paraCon));
+      _this.$set(_this.curQue.detail, _this.proofParaIndex, paraCon);
+      _this.$message.success("保存成功");
+    },
+    //上一句
+    prevSent() {
+      if (this.paraCon.wordsList.length <= 0) {
+        this.$message.warning("请生成拼音");
+        return;
+      }
+      this.save();
+      this.sentIndex -= 1;
+    },
+    //下一句
+    nextSent() {
+      if (this.paraCon.wordsList.length <= 0) {
+        this.$message.warning("请生成拼音");
+        return;
+      }
+      this.save();
+      this.sentIndex += 1;
+      //this.paraCon = this.curQue.detail[this.sentIndex];
+    },
+    beforeClose() {},
+  },
+  //生命周期 - 创建完成(可以访问当前this实例)
+  created() {},
+  //生命周期 - 挂载完成(可以访问DOM元素)
+  mounted() {
+    console.log("====分词结果====");
+    console.log(this.curQue.detail);
+    this.getParaSegWordsResult();
+  },
+  beforeCreate() {}, //生命周期 - 创建之前
+  beforeMount() {}, //生命周期 - 挂载之前
+  beforeUpdate() {}, //生命周期 - 更新之前
+  updated() {}, //生命周期 - 更新之后
+  beforeDestroy() {}, //生命周期 - 销毁之前
+  destroyed() {}, //生命周期 - 销毁完成
+  activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发
+};
+</script>
+<style lang='scss' scoped>
+//@import url(); 引入公共css类
+.NPC-para-list {
+  border: 1px #cccccc solid;
+  margin-bottom: 10px;
+  .NPC-header {
+    height: 40px;
+    width: 100%;
+    box-sizing: border-box;
+    padding: 0 20px;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    background: #ccc;
+    margin-bottom: 10px;
+  }
+  .NPC-sentence-list {
+    width: 100%;
+    box-sizing: border-box;
+    padding: 0px 15px 10px 15px;
+    display: flex;
+    justify-content: flex-start;
+    align-items: flex-start;
+  }
+}
+.NPC-words-box {
+  position: relative;
+  margin-bottom: 10px;
+}
+.NPC-words-list {
+  height: 400px;
+  overflow-y: scroll;
+}
+.dialog-top-btn {
+  width: 100%;
+  display: flex;
+  justify-content: flex-end;
+  align-items: center;
+  margin-bottom: 15px;
+}
+.NPC-gPinyin {
+  margin-top: 10px;
+}
+.yunmu {
+  position: absolute;
+  left: 460px;
+  top: 80px;
+  &-table {
+    width: 260px;
+    > tr {
+      td {
+        cursor: pointer;
+        text-align: center;
+        font-size: 16px;
+        height: 26px;
+      }
+    }
+  }
+}
+</style>

+ 650 - 0
src/components/Adult/inputModules/DialogueTem/index.vue

@@ -0,0 +1,650 @@
+<!--  -->
+<template>
+  <div
+    class="NPC-Book-Article Big-Book-Maxwidth"
+    v-if="curQue"
+    v-loading="loading"
+  >
+    <div class="Big-Book-img">
+      <UploadArt
+        :change-fill-id="changeImage"
+        :datafile-list="fileCon.img_list"
+        upload-type="image"
+        class="article_pdf"
+        :filleNumber="imageNumber"
+      />
+      <ul
+        class="uploadArt_list"
+        v-if="curQue.img_list && curQue.img_list.length > 0"
+      >
+        <li
+          v-for="(artItem, artIndex) in curQue.img_list"
+          :key="'articleImgList' + artIndex"
+        >
+          <img :src="artItem.url" style="width: 26px" />
+          <span class="art_name">{{ artItem.name }}</span>
+          <p>
+            图片放到第<el-input
+              class="imgNumber"
+              type="number"
+              v-model="artItem.imgNumber"
+              size="mini"
+              @input="forceUpdate"
+            ></el-input
+            >段落的后面
+          </p>
+          <img
+            src="@/assets/adult/del-close.png"
+            class="del-close"
+            @click="delImage(artIndex)"
+          />
+        </li>
+      </ul>
+    </div>
+    <div class="Big-Book-mp3">
+      <Upload
+        type="mp3"
+        :changeFillId="changeMp3"
+        :datafileList="fileCon.mp3_list"
+        :filleNumber="mp3Number"
+        :uploadType="'mp3'"
+        :handleMp3Base64="handleChange"
+      />
+    </div>
+    <div class="adult-book-input-item">
+      <span class="adult-book-lable">文章提示:</span>
+      <el-input
+        class="adult-book-input"
+        type="textarea"
+        :autosize="{ minRows: 2 }"
+        placeholder="请输入文章提示"
+        v-model="curQue.notice"
+        @blur="onBlur(curQue, 'notice')"
+      ></el-input>
+    </div>
+    <div class="NPC-Book-role">
+      <ul class="adult-book-input-role" v-if="curQue.roleList.length > 0">
+        <li
+          v-for="(rItem, rIndex) in curQue.roleList"
+          :key="'roleList' + rIndex"
+        >
+          <div class="rItem" @click="editRole(rItem)">
+            <span v-if="rItem.role" class="adult-book-input-roleText">{{
+              rItem.role
+            }}</span>
+            <img
+              v-else
+              :src="rItem.img_list[0] && rItem.img_list[0].url"
+              class="adult-book-input-roleImg"
+            />
+            <template v-if="rItem.detail.wordsList.length > 0">
+              <span class="pinyin">{{
+                rItem.detail.wordsList | handlePinyin
+              }}</span>
+              <span class="chs">{{ rItem.detail.wordsList | handleChs }}</span>
+            </template>
+          </div>
+          <i class="el-icon-circle-close" @click="delRole(rIndex)"></i>
+        </li>
+      </ul>
+      <el-button type="primary" @click="addRole">添加角色</el-button>
+    </div>
+    <div class="NPC-Book-article">
+      <ArticleChs
+        :curQue="curQue"
+        :isPara="isPara"
+        :changeIsPara="changeIsPara"
+      />
+    </div>
+    <div class="NPC-Book-Paragraph" v-if="isPara">
+      <Paragraph :curQue="curQue" :isClause="isClause" :sureSeg="sureSeg" />
+    </div>
+    <!---上传rlc文件-->
+    <!-- <div class="NPC-Book-Paragraph" v-if="isClause">
+      <el-button
+        type="warning"
+        size="small"
+        @click="uploadLRC"
+        v-if="curQue.detail[0].timeList.length == 0"
+        >上传lrc文件</el-button
+      >
+      <div v-else class="lrc-box">
+        <span>已有字幕时间节点</span>
+        <el-button type="text" @click="editTimeList">去编辑</el-button>
+      </div>
+    </div> -->
+
+    <!---分句-->
+    <div class="NPC-Book-Paragraph" v-if="isClause">
+      <Clauseresult :curQue="curQue" :segByWord="segByWord" />
+    </div>
+    <div class="lrc-box">
+      <div
+        v-if="this.curQue.wordTime && this.curQue.wordTime.length > 0"
+        class="lrc-box"
+      >
+        <span>已有字幕时间节点</span>
+        <el-button type="text" @click="againWordTime">重新生成</el-button>
+      </div>
+      <template v-else>
+        <el-button v-if="!isWordTime" size="medium" @click="createWordTime"
+          >自动生成字幕节点</el-button
+        >
+        <p v-else>字幕节点生成中...请等待</p>
+      </template>
+    </div>
+    <!---分词-->
+    <div class="NPC-Book-Word" v-if="isByWord">
+      <Segbyword :curQue="curQue" :paraIndex="paraIndex" :segList="segList" />
+    </div>
+    <el-dialog title="段落分句字幕打点" :visible.sync="cTVisible" width="30%">
+      <Createtimelist ref="createtimelist" :curQue="curQue" />
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="cTVisible = false">取 消</el-button>
+        <el-button type="primary" @click="saveTimeList">保 存</el-button>
+      </span>
+    </el-dialog>
+    <el-dialog
+      :title="roleStatus == 1 ? '添加角色' : '编辑角色'"
+      :visible.sync="roleVisible"
+      :modal="false"
+      width="60%"
+    >
+      <template v-if="roleStatus == 1">
+        <RoleChs
+          ref="createRolelist"
+          :curRole="curQue.roleList[curQue.roleList.length - 1]"
+        />
+      </template>
+      <template v-else>
+        <RoleChs ref="createRolelist" :curRole="curRole" />
+      </template>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="roleVisible = false">取 消</el-button>
+        <el-button type="primary" @click="saveRoleList">保 存</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import {
+  segSentences,
+  BatchSegContent,
+  createPinyin,
+  prepareTranscribe,
+  getWordTime,
+} from "@/api/ajax";
+const Base64 = require("js-base64").Base64;
+import Upload from "../../common/Upload.vue";
+import UploadArt from "../../common/UploadArt.vue";
+import ArticleChs from "./components/ArticleChs.vue";
+import Paragraph from "./components/ParagraphChs.vue";
+import Clauseresult from "./components/ClauseresultChs.vue";
+import Segbyword from "./components/SegbywordChs.vue";
+import Createtimelist from "./components/CreatetimelistChs.vue";
+import RoleChs from "./components/RoleChs.vue";
+
+export default {
+  name: "ArticleTemChs",
+  components: {
+    Upload,
+    UploadArt,
+    ArticleChs,
+    Paragraph,
+    Clauseresult,
+    Segbyword,
+    Createtimelist,
+    RoleChs,
+  },
+  props: ["curQue", "changeCurQue", "tmIndex"],
+  filters: {
+    handlePinyin(wordsList) {
+      let str = "";
+      wordsList.forEach((item, index) => {
+        if (index < wordsList.length - 1) {
+          str += item.pinyin + " ";
+        } else {
+          str += item.pinyin;
+        }
+      });
+      return str;
+    },
+    handleChs(wordsList) {
+      let str = "";
+      wordsList.forEach((item, index) => {
+        if (index < wordsList.length - 1) {
+          str += item.chs + " ";
+        } else {
+          str += item.chs;
+        }
+      });
+      return str;
+    },
+  },
+  data() {
+    return {
+      imageNumber: 1000,
+      mp3Number: 1,
+      fileCon: {
+        img_list: [],
+        mp3_list: [],
+      },
+      isPara: false,
+      isClause: false,
+      isByWord: false,
+      paraIndex: 0, //段落索引
+      cTVisible: false,
+      roleVisible: false,
+      roleStatus: 1, //1添加;2是编辑
+      curRole: null,
+      loading: false,
+      segList: null,
+      isWordTime: false,
+    };
+  },
+  computed: {},
+  watch: {
+    curQue: {
+      handler: function (newVal, oldVal) {
+        this.isPara = false;
+        this.isClause = false;
+        this.isByWord = false;
+        this.paraIndex = 0; //段落索引
+        this.roleStatus = 1; //1添加;2是编辑
+        this.curRole = null;
+        this.loading = false;
+        this.segList = null;
+        this.isWordTime = false;
+        this.initData();
+      },
+      deep: true,
+    },
+  },
+  //方法集合
+  methods: {
+    onBlur(item, field) {
+      item[field] = item[field] ? item[field].trim() : "";
+    },
+    changeMp3(fileList) {
+      const articleImgList = JSON.parse(JSON.stringify(fileList));
+      const articleImgRes = [];
+      articleImgList.forEach((item) => {
+        if (item.response) {
+          const obj = {
+            name: item.name,
+            duration: item.response.file_info_list[0].media_duration,
+            url: item.response.file_info_list[0].file_url,
+            id: "[FID##" + item.response.file_info_list[0].file_id + "##FID]",
+
+            media_duration: item.response.file_info_list[0].media_duration, //音频时长
+          };
+          articleImgRes.push(obj);
+        }
+      });
+      this.curQue.mp3_list = JSON.parse(JSON.stringify(articleImgRes));
+    },
+
+    changeImage(file) {
+      console.log(file);
+      if (file.response) {
+        const obj = {
+          name: file.name,
+          url: file.response.file_info_list[0].file_url,
+          id: "[FID##" + item.response.file_info_list[0].file_id + "##FID]",
+          imgNumber: 0,
+        };
+        this.curQue.img_list.push(obj);
+        this.$forceUpdate();
+      }
+    },
+    forceUpdate() {
+      this.$forceUpdate();
+    },
+    delImage(index) {
+      this.curQue.img_list.splice(index, 1);
+      this.fileCon.img_list.splice(index, 1);
+    },
+    //添加角色
+    addRole() {
+      this.roleVisible = true;
+      console.log(this.roleVisible);
+      this.roleStatus = 1;
+      let id = Math.random().toString(36).substr(2);
+      let roleCon = {
+        id: id,
+        role: "",
+        img_list: [],
+        detail: {
+          fullName: "",
+          seg_words: "",
+          wordsList: [],
+        },
+      };
+      this.curQue.roleList.push(JSON.parse(JSON.stringify(roleCon)));
+    },
+    //保存角色
+    saveRoleList() {
+      this.roleVisible = false;
+      this.$message.success("保存成功!");
+      console.log(this.curQue);
+    },
+    //删除角色
+    delRole(index) {
+      this.curQue.roleList.splice(index, 1);
+    },
+    //点击角色
+    editRole(item) {
+      this.roleVisible = true;
+      this.roleStatus = 2;
+      this.curRole = item;
+    },
+    changeIsPara() {
+      this.isPara = true;
+    },
+    //生成分句
+    sureSeg() {
+      let detail = JSON.parse(JSON.stringify(this.curQue.detail));
+      let leg = detail.length;
+      let flag = false;
+      for (let i = 0; i < leg; i++) {
+        if (!detail[i].para) {
+          flag = true;
+          break;
+        }
+      }
+      if (!flag) {
+        let textList = [];
+        detail.forEach((item) => {
+          let str = Base64.encode(item.para);
+          textList.push(str);
+        });
+        this.loading = true;
+        let data = {
+          textList: textList,
+        };
+        segSentences(data).then((res) => {
+          this.loading = false;
+          let result = res.data.result;
+          result.forEach((item, index) => {
+            this.$set(this.curQue.detail[index], "sentences", item);
+            for (let i = 0; i < item.length; i++) {
+              this.curQue.detail[index].sentencesEn.push("");
+            }
+          });
+          this.isClause = true;
+        });
+      } else {
+        this.$message.warning("段落不能为空");
+      }
+    },
+    changeIsClause(isClause) {
+      this.isClause = isClause;
+    },
+    //生成分词
+    segByWord(sentences, paraIndex) {
+      console.log(sentences);
+      this.loading = true;
+      let textList = [];
+      sentences.forEach((item) => {
+        let str = Base64.encode(item);
+        textList.push(str);
+      });
+      let data = {
+        textList: textList,
+      };
+      BatchSegContent(data).then((res) => {
+        this.loading = false;
+        let list = res.data.result.list;
+        this.$set(this.curQue.detail[paraIndex], "segList", list);
+        console.log(this.curQue);
+        this.segList = list;
+        this.isByWord = true;
+        this.paraIndex = paraIndex;
+      });
+    },
+    // 上传音频文件
+    handleChange(file, fileList) {
+      let _this = this;
+      _this.getBase64(file.raw).then((res) => {
+        let base_res = res.split("base64,");
+        let data = {
+          fileName: file.raw.name,
+          speechBase64: base_res[1],
+        };
+        prepareTranscribe(data).then((res) => {
+          _this.$set(_this.curQue, "taskId", res.data.taskId);
+        });
+      });
+    },
+    getBase64(file) {
+      return new Promise(function (resolve, reject) {
+        let reader = new FileReader();
+        let imgResult = "";
+        reader.readAsDataURL(file);
+        reader.onload = function () {
+          imgResult = reader.result;
+        };
+        reader.onerror = function (error) {
+          reject(error);
+        };
+        reader.onloadend = function () {
+          resolve(imgResult);
+        };
+      });
+    },
+    createWordTime() {
+      if (this.curQue.taskId) {
+        let verseList = [];
+        this.curQue.detail.forEach((item) => {
+          verseList = verseList.concat(item.sentences);
+        });
+        if (verseList.length > 0) {
+          this.isWordTime = true;
+          let data = {
+            taskId: this.curQue.taskId,
+            verseList: JSON.stringify(verseList),
+          };
+          getWordTime(data).then((res) => {
+            this.curQue.wordTime = res.data.result;
+            this.isWordTime = false;
+          });
+        }
+      } else {
+        this.$message.warning("请先上传音频");
+      }
+    },
+    againWordTime() {
+      this.isWordTime = false;
+      this.$set(this.curQue, "wordTime", []);
+    },
+    uploadLRC() {
+      this.cTVisible = true;
+    },
+    //保存字幕节点
+    saveTimeList() {
+      this.cTVisible = false;
+      let detail = JSON.parse(JSON.stringify(this.$refs.createtimelist.detail));
+      let detailRes = detail.map((item) => {
+        let timeList = item.time_str.split("\n");
+        item.timeList = this.handleTimeReg(timeList);
+        return item;
+      });
+      this.curQue.detail = JSON.parse(JSON.stringify(detailRes));
+      console.log(this.curQue.detail);
+    },
+
+    handleTimeReg(list) {
+      list = list.map((item) => {
+        let regArr = item.split("]");
+        let reg = regArr[0];
+        item = reg.replace("[", "");
+        return item;
+      });
+      return list;
+    },
+    //点击字幕节点
+    editTimeList() {
+      this.cTVisible = true;
+    },
+    initData() {
+      console.log("对话答题保存");
+      console.log(this.curQue);
+      if (this.curQue) {
+        if (this.curQue.detail && this.curQue.detail.length > 0) {
+          if (this.curQue.detail[0].para) {
+            this.isPara = true;
+          }
+          if (this.curQue.detail[0].sentences.length > 0) {
+            this.isClause = true;
+          }
+          if (this.curQue.detail[0].seg_words.length > 0) {
+            this.isByWord = true;
+          }
+        }
+        if (!this.curQue.img_list) {
+          this.curQue.img_list = [];
+        }
+        if (!this.curQue.mp3_list) {
+          this.curQue.mp3_list = [];
+        }
+        this.fileCon.img_list = JSON.parse(
+          JSON.stringify(this.curQue.img_list)
+        );
+        this.fileCon.mp3_list = JSON.parse(
+          JSON.stringify(this.curQue.mp3_list)
+        );
+      }
+    },
+  },
+  //生命周期 - 创建完成(可以访问当前this实例)
+  created() {},
+  //生命周期 - 挂载完成(可以访问DOM元素)
+  mounted() {
+    this.initData();
+  },
+  beforeCreate() {}, //生命周期 - 创建之前
+  beforeMount() {}, //生命周期 - 挂载之前
+  beforeUpdate() {}, //生命周期 - 更新之前
+  updated() {}, //生命周期 - 更新之后
+  beforeDestroy() {}, //生命周期 - 销毁之前
+  destroyed() {}, //生命周期 - 销毁完成
+  activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发
+};
+</script>
+<style lang='scss' scoped>
+//@import url(); 引入公共css类
+p {
+  margin: 0;
+  padding: 0;
+}
+.adult-book-input-role {
+  clear: both;
+  overflow: hidden;
+
+  > li {
+    float: left;
+    display: flex;
+    justify-content: flex-start;
+    align-items: center;
+    padding: 4px 8px;
+    border: 1px #a7a7a7 solid;
+    border-radius: 8px;
+    margin: 0 10px 10px 0px;
+    .rItem {
+      display: flex;
+      justify-content: flex-start;
+      align-items: center;
+
+      .adult-book-input {
+        &-roleText {
+          width: 40px;
+          height: 40px;
+          background: #a7a7a7;
+          border-radius: 100%;
+          text-align: center;
+          line-height: 40px;
+        }
+        &-roleImg {
+          width: 40px;
+          height: 40px;
+        }
+      }
+      .pinyin {
+        font-family: "GB-PINYINOK-B";
+        font-size: 14px;
+        line-height: 22px;
+        color: rgba(0, 0, 0, 0.85);
+        margin-right: 8px;
+        margin-left: 8px;
+      }
+      .chs {
+        font-family: "FZJCGFKTK";
+        font-size: 16px;
+        line-height: 24px;
+        color: #000000;
+        margin-right: 16px;
+      }
+    }
+    > i {
+      cursor: pointer;
+    }
+  }
+}
+.uploadArt_list {
+  border: 1px #ccc solid;
+  border-bottom: 0;
+  margin-top: 10px;
+  > li {
+    display: flex;
+    justify-content: flex-start;
+    align-items: center;
+    border-bottom: 1px #ccc solid;
+
+    > span {
+      width: 320px;
+      word-wrap: break-word;
+      font-size: 14px;
+      color: rgb(112, 110, 110);
+      border-right: 1px #ccc solid;
+      padding: 5px 10px;
+    }
+    > p {
+      flex: 1;
+      padding: 5px 10px;
+    }
+    .imgNumber {
+      width: 80px;
+    }
+    .del-close {
+      width: 24px;
+      height: 24px;
+      cursor: pointer;
+      margin-right: 10px;
+    }
+  }
+}
+.NPC-Book-Article {
+  > div {
+    margin-bottom: 20px;
+  }
+}
+.NPC-Book-model {
+  display: flex;
+  justify-content: flex-start;
+  align-items: center;
+
+  > span {
+    margin: 0;
+  }
+}
+.lrc-box {
+  display: flex;
+  justify-content: flex-start;
+  align-items: center;
+  > span {
+    font-size: 14px;
+    margin-right: 16px;
+  }
+}
+</style>

+ 31 - 3
src/components/Adult/preview/DialogueArticleViewChs/NormalModelChs.vue

@@ -19,6 +19,7 @@
           <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',
@@ -62,6 +63,7 @@
                       >
                         <span class="NNPE-words-box">
                           <span
+                            v-if="curQue.pyPosition == 'top'"
                             class="NNPE-pinyin"
                             :class="[pItem.className ? pItem.className : '']"
                             >{{ pItem.pinyin }}</span
@@ -80,11 +82,20 @@
                             ]"
                             >{{ 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 class="NNPE-pinyin" style="text-align: left">{{
-                            item.wordsList[pIndex + 1].pinyin
-                          }}</span>
+                          <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"
@@ -100,10 +111,17 @@
                             ]"
                             >{{ 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' : '',
@@ -126,6 +144,15 @@
                           ]"
                           >{{ 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>
@@ -345,6 +372,7 @@ export default {
 //@import url(); 引入公共css类
 .NNPE-ArticleView {
   width: 100%;
+
   .NPC-sentences-list {
     .NPC-article-empty {
       display: flex;

+ 30 - 3
src/components/Adult/preview/DialogueArticleViewChs/PhraseModelChs.vue

@@ -19,6 +19,7 @@
           <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' : '']"
           v-for="(item, index) in resArr"
@@ -49,6 +50,7 @@
                       >
                         <span class="NNPE-words-box">
                           <span
+                            v-if="curQue.pyPosition == 'top'"
                             class="NNPE-pinyin"
                             :class="[pItem.className ? pItem.className : '']"
                             >{{ pItem.pinyin }}</span
@@ -62,18 +64,34 @@
                             ]"
                             >{{ 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 class="NNPE-pinyin" style="text-align: left">{{
-                            item.wordsList[pIndex + 1].pinyin
-                          }}</span>
+                          <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">{{
                             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' : '',
@@ -91,6 +109,15 @@
                           ]"
                           >{{ 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>

+ 69 - 28
src/components/Adult/preview/DialogueArticleViewChs/Practicechs.vue

@@ -31,6 +31,7 @@
     </div>
 
     <template v-if="resObj">
+      <p class="notice" v-if="curQue.notice">{{ curQue.notice }}</p>
       <div class="NPC-sentences-list">
         <div
           :class="['NNPE-detail-box', sentIndex == index ? 'active' : '']"
@@ -74,15 +75,17 @@
                           "
                         >
                           <span class="NNPE-words-box">
-                            <span
-                              v-if="isShowPY"
-                              class="NNPE-pinyin"
-                              :class="[
-                                pItem.className ? pItem.className : '',
-                                sentIndex == index ? 'wordBlank' : '',
-                              ]"
-                              >{{ pItem.pinyin }}</span
-                            >
+                            <template v-if="curQue.pyPosition == 'top'">
+                              <span
+                                v-if="isShowPY"
+                                class="NNPE-pinyin"
+                                :class="[
+                                  pItem.className ? pItem.className : '',
+                                  sentIndex == index ? 'wordBlank' : '',
+                                ]"
+                                >{{ pItem.pinyin }}</span
+                              >
+                            </template>
                             <span
                               class="NNPE-chs"
                               :class="[
@@ -110,17 +113,30 @@
                                 >
                               </template>
                             </span>
+                            <template v-if="curQue.pyPosition == 'bottom'">
+                              <span
+                                v-if="isShowPY"
+                                class="NNPE-pinyin"
+                                :class="[
+                                  pItem.className ? pItem.className : '',
+                                  sentIndex == index ? 'wordBlank' : '',
+                                ]"
+                                >{{ pItem.pinyin }}</span
+                              >
+                            </template>
                           </span>
                           <span class="NNPE-words-box">
-                            <span
-                              v-if="isShowPY"
-                              :class="[
-                                'NNPE-pinyin',
-                                sentIndex == index ? 'wordBlank' : '',
-                              ]"
-                              style="text-align: left"
-                              >{{ item.sentArr[pIndex + 1].pinyin }}</span
-                            >
+                            <template v-if="curQue.pyPosition == 'top'">
+                              <span
+                                v-if="isShowPY"
+                                :class="[
+                                  'NNPE-pinyin',
+                                  sentIndex == index ? 'wordBlank' : '',
+                                ]"
+                                style="text-align: left"
+                                >{{ item.sentArr[pIndex + 1].pinyin }}</span
+                              >
+                            </template>
                             <span class="NNPE-chs" style="text-align: left">
                               <span
                                 :class="[
@@ -136,19 +152,32 @@
                                 {{ item.sentArr[pIndex + 1].chs }}</span
                               >
                             </span>
+                            <template v-if="curQue.pyPosition == 'bottom'">
+                              <span
+                                v-if="isShowPY"
+                                :class="[
+                                  'NNPE-pinyin',
+                                  sentIndex == index ? 'wordBlank' : '',
+                                ]"
+                                style="text-align: left"
+                                >{{ item.sentArr[pIndex + 1].pinyin }}</span
+                              >
+                            </template>
                           </span>
                         </template>
                         <template v-else>
-                          <span
-                            v-if="isShowPY"
-                            class="NNPE-pinyin"
-                            :class="[
-                              pItem.padding ? 'padding' : '',
-                              pItem.className ? pItem.className : '',
-                              sentIndex == index ? 'wordBlank' : '',
-                            ]"
-                            >{{ pItem.pinyin }}</span
-                          >
+                          <template v-if="curQue.pyPosition == 'top'">
+                            <span
+                              v-if="isShowPY"
+                              class="NNPE-pinyin"
+                              :class="[
+                                pItem.padding ? 'padding' : '',
+                                pItem.className ? pItem.className : '',
+                                sentIndex == index ? 'wordBlank' : '',
+                              ]"
+                              >{{ pItem.pinyin }}</span
+                            >
+                          </template>
                           <span
                             class="NNPE-chs"
                             :class="[
@@ -173,6 +202,18 @@
                               >
                             </template>
                           </span>
+                          <template v-if="curQue.pyPosition == 'bottom'">
+                            <span
+                              v-if="isShowPY"
+                              class="NNPE-pinyin"
+                              :class="[
+                                pItem.padding ? 'padding' : '',
+                                pItem.className ? pItem.className : '',
+                                sentIndex == index ? 'wordBlank' : '',
+                              ]"
+                              >{{ pItem.pinyin }}</span
+                            >
+                          </template>
                         </template>
                       </template>
                     </template>

+ 30 - 3
src/components/Adult/preview/DialogueArticleViewChs/WordModelChs.vue

@@ -19,6 +19,7 @@
           <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' : '']"
           v-for="(item, index) in resArr"
@@ -49,6 +50,7 @@
                       >
                         <span class="NNPE-words-box">
                           <span
+                            v-if="curQue.pyPosition == 'top'"
                             class="NNPE-pinyin"
                             :class="[pItem.className ? pItem.className : '']"
                             >{{ pItem.pinyin }}</span
@@ -65,18 +67,34 @@
                             ]"
                             >{{ 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 class="NNPE-pinyin" style="text-align: left">{{
-                            item.wordsList[pIndex + 1].pinyin
-                          }}</span>
+                          <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">{{
                             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' : '',
@@ -96,6 +114,15 @@
                           ]"
                           >{{ 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>

+ 9 - 0
src/components/Adult/preview/DialogueArticleViewChs/index.vue

@@ -218,6 +218,15 @@ export default {
 </style>
 <style lang="scss">
 .NPC-ArticleView {
+  .notice {
+    font-weight: normal;
+    font-size: 14px;
+    line-height: 150%;
+    margin-bottom: 16px;
+    color: #000000;
+    padding: 0 24px;
+    margin-bottom: 8px;
+  }
   .ArticleView-header {
     .el-switch {
       margin-left: 24px;

+ 22 - 8
src/components/Adult/preview/WordPhrase.vue

@@ -101,6 +101,8 @@
         :changeDetailIndex="changeDetailIndex"
         :closeWord="closeWordShow"
         :detailIndex="detailIndex"
+        :getWordLiju="getWordLiju"
+        :optionRes="optionRes"
       />
     </div>
   </div>
@@ -128,6 +130,7 @@ export default {
       playClass: "",
       mp3_index: -1,
       playWord: null,
+      optionRes: [],
     };
   },
   //计算属性 类似于data概念
@@ -162,16 +165,17 @@ export default {
       }
     },
     // 打开单词详情
-    showDetail(item, index) {
+    showDetail(item) {
       this.data = null;
       this.data = item;
       console.log(this.data);
       this.detailShow = true;
-      this.detailIndex = index;
+      this.detailIndex = item.sIndex;
       this.getWordLiju(item.new_word);
     },
     // 获取生词的例句
     getWordLiju(val) {
+      console.log(this.data);
       this.data.list1 = [];
       this.data.list2 = [];
       this.data.list3 = [];
@@ -247,24 +251,25 @@ export default {
     lasspanetail(val) {
       this.detailIndex = val;
       this.data = null;
-      this.data = this.curQue.option[this.detailIndex];
+      this.data = this.optionRes[this.detailIndex];
       this.getWordLiju(this.data.new_word);
     },
     // 下一个单词详情
     nexspanetail(val) {
       this.detailIndex = val;
       this.data = null;
-      this.data = this.curQue.option[this.detailIndex];
+      this.data = this.optionRes[this.detailIndex];
       this.getWordLiju(this.data.new_word);
     },
     changeDetailIndex(val) {
+      debugger;
       if (val == "last") {
         this.detailIndex--;
       } else {
         this.detailIndex++;
       }
       this.data = null;
-      this.data = this.curQue.option[this.detailIndex];
+      this.data = this.optionRes[this.detailIndex];
     },
     playNewwords() {
       let _this = this;
@@ -310,16 +315,22 @@ export default {
   //生命周期 - 创建完成(可以访问当前this实例)
   created() {
     console.log(this.curQue);
+
     if (this.curQue.type == "NewWord_chs") {
+      let optionRes = [];
       this.curQue.option.forEach((item, index) => {
+        optionRes = optionRes.concat(item);
         item.index = index + 1;
         item.forEach((sItem, sIndex) => {
+          sItem.sIndex =
+            index == 0 ? sIndex : sIndex + this.curQue.option[index - 1].length;
           sItem.def_str =
             sItem.definition_list.length > 0
               ? sItem.definition_list.join(";")
               : "";
         });
       });
+      this.optionRes = JSON.parse(JSON.stringify(optionRes));
     }
     console.log(this.curQue);
   },
@@ -434,7 +445,8 @@ export default {
       }
       .NPC-word-tab-common {
         padding-left: 8px;
-        width: 112px;
+        width: 120px;
+        box-sizing: border-box;
       }
       .NPC-word-tab-pinyin {
         font-family: "GB-PINYINOK-B";
@@ -446,12 +458,14 @@ export default {
       }
       .NPC-word-tab-cixing {
         font-family: "robot";
-        width: 40px;
+        width: 48px;
+        box-sizing: border-box;
       }
       .NPC-word-tab-def {
-        width: 284px;
+        width: 296px;
         font-family: "robot";
         word-break: break-word;
+        box-sizing: border-box;
       }
     }
   }

+ 94 - 36
src/components/Adult/preview/components/WordPhraseDetail.vue

@@ -1,7 +1,7 @@
 <template>
   <div
     v-if="height"
-    class="Module"
+    class="Module wordDetailChs"
     :style="{
       height: height,
       maxHeight: height,
@@ -37,13 +37,23 @@
           </div>
         </div>
         <div class="wordDetail">
-          <div class="Strockplay">
-            <Strockplayredline
-              :Book_text="data.new_word"
-              :playStorkes="true"
-              :targetDiv="'bwcHanziIntp' + detailIndex"
-              :wordNum="data.new_word.length"
-            />
+          <div class="bwc-Strockplay" v-if="isShow">
+            <div
+              class="strockplay"
+              v-for="(conItem, conindex) in data.new_word"
+              :key="'new_word_' + conindex"
+            >
+              <Strockplayredline
+                :Book_text="conItem"
+                :playStorkes="true"
+                :targetDiv="'bwcHanziIntp' + detailIndex + conindex"
+                :wordNum="data.new_word.length"
+              />
+              <div
+                class="bwc-line"
+                v-if="conindex < data.new_word.length - 1"
+              ></div>
+            </div>
           </div>
           <div class="wordInfor">
             <div class="yinpin">
@@ -59,7 +69,7 @@
             </p>
           </div>
         </div>
-        <div class="zhedie">
+        <div class="zhedie-white">
           <div v-if="data.list1.length > 0">
             <el-collapse v-model="wordShow">
               <el-collapse-item name="1">
@@ -224,6 +234,8 @@ export default {
     "closeWord",
     "detailIndex",
     "notshowNext",
+    "getWordLiju",
+    "optionRes",
   ],
   data() {
     //这里存放数据
@@ -232,12 +244,25 @@ export default {
       margintop: "",
       wordShow: "",
       list1: [],
+      isShow: false,
+      old_word: "",
     };
   },
   //计算属性 类似于data概念
   computed: {},
   //监控data中数据变化
-  watch: {},
+  watch: {
+    data: {
+      handler: function (val, oldVal) {
+        const _this = this;
+        if (val) {
+          _this.initData();
+        }
+      },
+      // 深度观察监听
+      deep: true,
+    },
+  },
   //方法集合
   methods: {
     playAudio() {},
@@ -255,12 +280,17 @@ export default {
     },
     // 下一个单词详情
     nextDetail() {
-      if (this.detailIndex == this.curQue.option.length - 1) {
+      if (this.detailIndex == this.optionRes.length - 1) {
         this.$message.warning("当前已经是最后一个了 ");
         return;
       }
-      this.changeDetailIndex("next");
-      this.getWordLiju();
+      if (this.old_word != this.data.new_word) {
+        this.isShow = false;
+        setTimeout(() => {
+          this.changeDetailIndex("next");
+          this.getWordLiju();
+        }, 50);
+      }
     },
     handleExample(list) {
       list.map((item, index) => {
@@ -276,27 +306,32 @@ export default {
         return item;
       });
     },
+    initData() {
+      if (this.curQue) {
+        this.isShow = true;
+        if (this.data.list1 && this.data.list1.length > 0) {
+          this.handleExample(this.data.list1);
+        }
+        if (this.data.list2 && this.data.list2.length > 0) {
+          this.handleExample(this.data.list2);
+        }
+        this.old_word = this.optionRes.new_word;
+      }
+      let Fathernode = document.getElementsByClassName(
+        "NNPE-Big-Book-preview"
+      )[0];
+      if (Fathernode) {
+        //   this.height = Fathernode.clientHeight + "px";
+        this.height = window.innerHeight + "px";
+        this.margintop = "-" + window.innerHeight / 2 + "px";
+      }
+    },
   },
   //生命周期 - 创建完成(可以访问当前this实例)
   created() {},
   //生命周期 - 挂载完成(可以访问DOM元素)
   mounted() {
-    if (this.curQue) {
-      if (this.data.list1 && this.data.list1.length > 0) {
-        this.handleExample(this.data.list1);
-      }
-      if (this.data.list2 && this.data.list2.length > 0) {
-        this.handleExample(this.data.list2);
-      }
-    }
-    let Fathernode = document.getElementsByClassName(
-      "NNPE-Big-Book-preview"
-    )[0];
-    if (Fathernode) {
-      //   this.height = Fathernode.clientHeight + "px";
-      this.height = window.innerHeight + "px";
-      this.margintop = "-" + window.innerHeight / 2 + "px";
-    }
+    this.initData();
   },
   //生命周期-创建之前
   beforeCreated() {},
@@ -366,12 +401,36 @@ export default {
       display: flex;
       justify-content: flex-start;
       align-items: flex-start;
-      .Strockplay {
-        box-sizing: border-box;
-        border: 2px solid #ff5757;
+      .bwc-Strockplay {
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        min-width: 130px;
+        height: 130px;
+        margin-bottom: 16px;
+        border: 2px solid #de4444;
         border-radius: 8px;
+        box-sizing: border-box;
         overflow: hidden;
         margin-right: 37px;
+        .strockplay {
+          display: flex;
+          justify-content: center;
+          align-items: center;
+          position: relative;
+          .collect-icon {
+            width: 16px;
+            position: absolute;
+            right: 4px;
+            bottom: 4px;
+            cursor: pointer;
+          }
+        }
+        .bwc-line {
+          width: 2px;
+          height: 128px;
+          background: #de4444;
+        }
       }
       .wordInfor {
         .yinpin {
@@ -407,7 +466,7 @@ export default {
         color: #000000;
       }
     }
-    .zhedie {
+    .zhedie-white {
       width: 100%;
       margin: 0 auto;
       > div {
@@ -453,7 +512,6 @@ export default {
           display: flex;
 
           > :nth-child(1) {
-            width: 28px;
             text-align: right;
             margin-right: 6px;
             line-height: 24px;
@@ -550,8 +608,8 @@ export default {
 }
 </style>
 <style lang="scss">
-.adult-book-NPC {
-  .zhedie {
+.wordDetailChs {
+  .zhedie-white {
     .el-collapse-item__header {
       height: 40px;
       background: #fff;

+ 13 - 0
src/views/adultInput.vue

@@ -136,6 +136,17 @@
                         <!-- <ArticleView :curQue="topicIitem.que" /> -->
                       </template>
                     </template>
+                    <template v-if="topicIitem.type == 'dialogue_answer_chs'">
+                      <template v-if="topicIitem.is_edit">
+                        <DialogueAnswerChs
+                          :curQue="topicIitem.data"
+                          :changeCurQue="changeCurQue"
+                        />
+                      </template>
+                      <template v-else>
+                        <!-- <ArticleView :curQue="topicIitem.que" /> -->
+                      </template>
+                    </template>
                     <template v-if="topicIitem.type == 'NewWord_chs'">
                       <template v-if="topicIitem.is_edit">
                         <Neword
@@ -358,6 +369,7 @@ import Sentence from "@/components/Adult/inputModules/Sentence.vue";
 import Sudoku from "@/components/Adult/inputModules/Sudoku.vue";
 import ToneSelect from "@/components/Adult/inputModules/ToneSelect.vue";
 import NumberCombination from "@/components/Adult/inputModules/NumberCombination.vue";
+import DialogueAnswerChs from "@/components/Adult/inputModules/DialogueAnswerChs";
 
 import Textdes from "@/components/Adult/inputModules/Textdes.vue";
 import Record from "@/components/Adult/inputModules/Record.vue";
@@ -424,6 +436,7 @@ export default {
     Sudoku,
     NumberCombination,
     ToneSelect,
+    DialogueAnswerChs,
   },
   data() {
     return {