Prechádzať zdrojové kódy

教师端英语口语页面

zengyicheng 1 rok pred
rodič
commit
99cb39dac2

BIN
src/assets/icon/englishVoice/add.png


BIN
src/assets/icon/englishVoice/aiImg.png


BIN
src/assets/icon/englishVoice/aiImg1.png


BIN
src/assets/icon/englishVoice/del.png


BIN
src/assets/icon/englishVoice/down.png


BIN
src/assets/icon/englishVoice/edit.png


BIN
src/assets/icon/englishVoice/fChoose.png


BIN
src/assets/icon/englishVoice/isAll.png


BIN
src/assets/icon/englishVoice/noAll.png


BIN
src/assets/icon/englishVoice/noFlie.png


BIN
src/assets/icon/englishVoice/restart.png


BIN
src/assets/icon/englishVoice/right.png


BIN
src/assets/icon/englishVoice/sChoose.png


BIN
src/assets/icon/englishVoice/start_aduio.png


BIN
src/assets/icon/englishVoice/stop_audio.png


BIN
src/assets/icon/englishVoice/up.png


+ 879 - 0
src/components/pages/EnglishVoice new/component/check.vue

@@ -0,0 +1,879 @@
+<template>
+  <div class="checkBox">
+    <div class="c_Box">
+      <div class="check_intro">
+          <img src="../../../../assets/icon/englishVoice/aiImg.png" alt="" />
+      </div>
+      <div class="form_box">
+        <div class="check_item">
+          <div>练习时长:</div>
+          <div class="ctime_right">
+            <div
+              @click="setTime('5', 1)"
+              :class="timeType == 1 ? 'isTime' : ''"
+            >
+              5min
+            </div>
+            <div
+              @click="setTime('10', 2)"
+              :class="timeType == 2 ? 'isTime' : ''"
+            >
+              10min
+            </div>
+            <div
+              @click="setTime('all', 3)"
+              :class="timeType == 3 ? 'isTime' : ''"
+            >
+              不限
+            </div>
+            <div
+              @click="(timeType = 4), (inputShow = true)"
+              :class="timeType == 4 ? 'isTime' : ''"
+            >
+              自定义
+            </div>
+            <div v-if="inputShow && timeType == 4" style="border: none">
+              <el-input
+                v-model="time"
+                placeholder="其他:请输入对话时长,单位min"
+                @change="setTime(time, 4)"
+              ></el-input>
+            </div>
+          </div>
+        </div>
+        <div class="check_item">
+          <div>选择年级:</div>
+          <div>
+            <el-select
+              v-model="checkJson.class"
+              @change="getCheckJson"
+              placeholder="请选择年级"
+            >
+              <el-option
+                v-for="(item, index) in classJuri"
+                :key="index"
+                :label="item.name"
+                :value="item.id"
+              ></el-option>
+            </el-select>
+          </div>
+        </div>
+        <div class="check_item">
+          <div>设置难度:</div>
+          <div class="ctime_right">
+            <div @click="setDType(0)" :class="diffType == 0 ? 'isTime' : ''">
+              简单
+            </div>
+            <div @click="setDType(1)" :class="diffType == 1 ? 'isTime' : ''">
+              一般
+            </div>
+            <div @click="setDType(2)" :class="diffType == 2 ? 'isTime' : ''">
+              困难
+            </div>
+          </div>
+        </div>
+        <div class="check_item" style="position: relative">
+          <div>对话主题:</div>
+          <div class="inputBox">
+            <div class="selectInput" @click="getItem">
+              <div :style="{ color: topicName != '' ? '#000' : '' }">
+                {{ topicName != "" ? topicName : "请选择对话主题" }}
+              </div>
+              <div class="downImg" v-if="isShowSelect == false">
+                <img
+                  src="../../../../assets/icon/englishVoice/down.png"
+                  alt=""
+                />
+              </div>
+              <div class="downImg" v-if="isShowSelect == true">
+                <img src="../../../../assets/icon/englishVoice/up.png" alt="" />
+              </div>
+            </div>
+            <div @click="openAddTalk" class="addNewTalk">
+              <div class="addImg">
+                <img
+                  src="../../../../assets/icon/englishVoice/add.png"
+                  alt=""
+                />
+              </div>
+              <div>新建主题</div>
+            </div>
+          </div>
+
+          <div class="subTalkBox" v-if="isShowSelect">
+            <div class="left">
+              <div
+                v-for="(item, index) in allfType"
+                :key="index"
+                @click="getTypeId(item.id, item.name, 0)"
+                :class="fid == item.id ? 'isCType' : ''"
+              >
+                <el-tooltip
+                  :content="item.name"
+                  popper-class="text_tooltip"
+                  placement="top"
+                  effect="light"
+                >
+                  <div>{{ item.name }}</div>
+                </el-tooltip>
+                <div class="allImg" v-if="fid == item.id">
+                  <img
+                    src="../../../../assets/icon/englishVoice/isAll.png"
+                    alt=""
+                  />
+                </div>
+                <div class="allImg" v-else>
+                  <img
+                    src="../../../../assets/icon/englishVoice/noAll.png"
+                    alt=""
+                  />
+                </div>
+              </div>
+
+              <div @click="fid = '1'" :class="fid == '1' ? 'isCType' : ''">
+                <div>我的话题</div>
+                <div class="allImg" v-if="fid == '1'">
+                  <img
+                    src="../../../../assets/icon/englishVoice/isAll.png"
+                    alt=""
+                  />
+                </div>
+                <div class="allImg" v-else>
+                  <img
+                    src="../../../../assets/icon/englishVoice/noAll.png"
+                    alt=""
+                  />
+                </div>
+              </div>
+            </div>
+            <div
+              class="right"
+              v-if="fid != '' && fid != '1' && englishJson[fid].length > 0"
+            >
+              <div
+                v-for="(item1, index1) in englishJson[fid]"
+                :key="index1"
+                @click="getTypeId(item1.id, item1.name, 1)"
+                :class="sid == item1.id ? 'isCType' : ''"
+              >
+                <el-tooltip
+                  :content="item1.name"
+                  popper-class="text_tooltip"
+                  placement="top"
+                  effect="light"
+                >
+                  <div>{{ item1.name }}</div>
+                </el-tooltip>
+              </div>
+            </div>
+            <div
+              class="right"
+              v-else-if="
+                fid != '' && fid != '1' && englishJson[fid].length == 0
+              "
+              style="
+                display: flex;
+                flex-direction: column;
+                flex-wrap: nowrap;
+                align-items: center;
+                justify-content: center;
+              "
+            >
+              <div class="noFile">
+                <img
+                  src="../../../../assets/icon/englishVoice/noFlie.png"
+                  alt=""
+                />
+              </div>
+              <div style="width: auto; color: #a6a6a6">
+                暂无主题,快去创建吧
+              </div>
+              <div
+                class="goButton"
+                @click="openAddTalk"
+                style="width: auto; height: 20px"
+              >
+                <div>去创建</div>
+                <div class="rightImg">
+                  <img
+                    src="../../../../assets/icon/englishVoice/right.png"
+                    alt=""
+                  />
+                </div>
+              </div>
+            </div>
+            <div class="right" v-if="fid == '1' && mySubTalk.length > 0">
+              <div
+                v-for="(item2, index2) in mySubTalk"
+                :key="index2"
+                @click="getTypeId(item2.id, item2.name, 2)"
+                :class="mytid == item2.id ? 'isCType' : ''"
+              >
+                <el-tooltip
+                  :content="item2.title"
+                  popper-class="text_tooltip"
+                  placement="top"
+                  effect="light"
+                >
+                  <div>{{ item2.title }}</div>
+                </el-tooltip>
+                <div class="rightIcon">
+                  <div
+                    class="editImg"
+                    @click.stop="editMySub(item2.id, item2.title)"
+                  >
+                    <img
+                      src="../../../../assets/icon/englishVoice/edit.png"
+                      alt=""
+                    />
+                  </div>
+                  <div class="delImg" @click.stop="delMySub(item2.id)">
+                    <img
+                      src="../../../../assets/icon/englishVoice/del.png"
+                      alt=""
+                    />
+                  </div>
+                </div>
+              </div>
+            </div>
+            <div
+              class="right"
+              v-else-if="fid == '1' && mySubTalk.length == 0"
+              style="
+                display: flex;
+                flex-direction: column;
+                flex-wrap: nowrap;
+                align-items: center;
+                justify-content: center;
+              "
+            >
+              <div class="noFile">
+                <img
+                  src="../../../../assets/icon/englishVoice/noFlie.png"
+                  alt=""
+                />
+              </div>
+              <div style="width: auto; color: #a6a6a6">
+                暂无主题,快去创建吧
+              </div>
+              <div
+                class="goButton"
+                @click="openAddTalk"
+                style="width: auto; height: 20px"
+              >
+                <div>去创建</div>
+                <div class="rightImg">
+                  <img
+                    src="../../../../assets/icon/englishVoice/right.png"
+                    alt=""
+                  />
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+        <div class="check_item">
+          <div>结果可见:</div>
+          <div class="ctime_right">
+            <div
+              @click="getCShow(true)"
+              :class="checkJson.isShow == true ? 'isTime' : ''"
+            >
+              是
+            </div>
+            <div
+              @click="getCShow(false)"
+              :class="checkJson.isShow == false ? 'isTime' : ''"
+            >
+              否
+            </div>
+          </div>
+        </div>
+        <div class="check_item">
+          <div>评价形式:</div>
+          <div class="ctime_right">
+            <div
+              @click="getCEva(0)"
+              :class="checkJson.eva == 0 ? 'isTime' : ''"
+              style="min-width: 110px"
+            >
+              等级制(A+)
+            </div>
+            <div
+              @click="getCEva(1)"
+              :class="checkJson.eva == 1 ? 'isTime' : ''"
+              style="min-width: 110px"
+            >
+              百分制(100)
+            </div>
+          </div>
+        </div>
+        <div class="check_item">
+          <div>智能评价:</div>
+          <div class="ctime_right1">
+            <el-switch
+              v-model="isAiEva"
+              active-text="一键评价"
+              @change="setAiEva"
+            ></el-switch>
+            <el-checkbox-group v-model="aiEvaChoose" @change="setAiEva">
+              <el-checkbox
+                v-for="item in aiEvaC"
+                :key="item.id"
+                :label="item.id"
+                >{{ item.name }}</el-checkbox
+              >
+            </el-checkbox-group>
+          </div>
+        </div>
+      </div>
+    </div>
+    <addTalk
+      :userid="userid"
+      :oid="oid"
+      :org="org"
+      :allfType="allfType"
+      :addTalkDialogVisible.sync="addTalkDialogVisible"
+    ></addTalk>
+  </div>
+</template>
+
+<script>
+import addTalk from "./component/addTalk.vue";
+export default {
+  components: {
+    addTalk,
+  },
+  props: {
+    checkJson: {
+      type: Object,
+    },
+    diaType: {
+      type: String,
+    },
+    oid: {
+      type: String,
+    },
+    org: {
+      type: String,
+    },
+  },
+  data() {
+    return {
+      isAiEva: false,
+      aiEvaChoose: [],
+      aiEvaC: [
+        { id: "0", name: "评分" },
+        { id: "1", name: "评语" },
+      ],
+      timeType: 0,
+      inputShow: false,
+      time: "",
+      classJuri: [],
+      topicJuri: [],
+      diffType: 0,
+      isShowSelect: false,
+      allfType: [],
+      englishJson: {},
+      fid: "",
+      sid: "",
+      mytid: "",
+      mySubTalk: [],
+      topicName: "",
+      userid: this.$route.query.userid,
+      addTalkDialogVisible: false,
+    };
+  },
+  methods: {
+    setAiEva() {
+      this.checkJson.aiEva.isAiEva = this.isAiEva;
+      this.checkJson.aiEva.aiEvaChoose = this.aiEvaChoose;
+      this.getCheckJson();
+    },
+    setTime(time, t) {
+      if (this.timeType == t) {
+        this.timeType = 0;
+      } else {
+        this.timeType = t;
+      }
+      this.checkJson.time = time;
+      this.getCheckJson();
+    },
+    getTypeId(id, n, t) {
+      if (t == 0) {
+        this.fid = id;
+        this.sid = "";
+        this.topicName = n;
+        this.checkJson.topic = id;
+      } else if (t == 1) {
+        this.sid = id;
+        this.topicName = n;
+        this.checkJson.topic = id;
+      } else {
+        this.mytid = id;
+        this.topicName = n;
+        this.checkJson.topic = id;
+      }
+      this.getCheckJson();
+    },
+    getCShow(boolean) {
+      this.checkJson.isShow = boolean;
+      this.getCheckJson();
+    },
+    getCEva(t) {
+      this.checkJson.eva = t;
+      this.getCheckJson();
+    },
+    setDType(t) {
+      this.diffType = t;
+      this.checkJson.difficulty = t;
+      this.getCheckJson();
+    },
+    getCheckJson() {
+      this.$emit("setCheckJson", this.checkJson);
+      this.$forceUpdate();
+    },
+    //获取班级列表
+    getClass2() {
+      let params = {
+        oid: this.oid,
+      };
+      this.ajax
+        .get(this.$store.state.api + "selectClassBySchool", params)
+        .then((res) => {
+          this.classJuri = res.data[0];
+        })
+        .catch((err) => {
+          console.error(err);
+        });
+    },
+    getItem() {
+      //   this.fid = "";
+      //   this.sid = "";
+      this.isShowSelect = !this.isShowSelect;
+    },
+    getEnglishType() {
+      this.fid = "";
+      this.sid = "";
+      let params = {
+        oid: this.oid,
+        org: this.org,
+      };
+      this.ajax
+        .get(this.$store.state.api + "select_englishVoiceType", params)
+        .then((res) => {
+          var ftype = res.data[0]; //公共父级分类
+          var stype = res.data[1]; //公共子级分类
+          var sctype = res.data[2]; //该学校子级分类
+          var fctype = res.data[3]; //该学校父级分类
+          var fotype = res.data[4]; //组织父级分类
+          var sotype = res.data[5]; //组织子级分类
+          var allfType = [];
+          var allsType = [];
+
+          if (fotype.length == 0 && sotype.length == 0) {
+            if (fctype.length == 0 && sctype.length == 0) {
+              for (var i = 0; i < ftype.length; i++) {
+                allfType.push(ftype[i]);
+              }
+              for (var i = 0; i < stype.length; i++) {
+                allsType.push(stype[[i]]);
+              }
+            } else if (fctype.length == 0 && sctype.length > 0) {
+              for (var i = 0; i < ftype.length; i++) {
+                allfType.push(ftype[i]);
+              }
+              for (var i = 0; i < stype.length; i++) {
+                allsType.push(stype[[i]]);
+              }
+              for (var i = 0; i < sctype.length; i++) {
+                allsType.push(sctype[[i]]);
+              }
+            } else {
+              for (var i = 0; i < fctype.length; i++) {
+                allfType.push(fctype[i]);
+              }
+              for (var i = 0; i < sctype.length; i++) {
+                allsType.push(sctype[[i]]);
+              }
+            }
+          } else {
+            for (var i = 0; i < fotype.length; i++) {
+              allfType.push(fotype[i]);
+            }
+            for (var i = 0; i < sotype.length; i++) {
+              allsType.push(sctysotypepe[[i]]);
+            }
+          }
+
+          var englishJson = {};
+          for (var i = 0; i < allfType.length; i++) {
+            if (!englishJson[allfType[i].id]) {
+              englishJson[allfType[i].id] = [];
+            }
+            for (var j = 0; j < allsType.length; j++) {
+              if (allfType[i].id == allsType[j].pid) {
+                englishJson[allfType[i].id].push(allsType[j]); // 去除公共分类
+              }
+            }
+          }
+          this.allfType = allfType;
+          this.englishJson = englishJson;
+          this.checkJson.allfType = allfType;
+          this.checkJson.englishJson = englishJson;
+          this.getMySubTalk();
+          this.getCheckJson();
+        })
+        .catch((err) => {
+          console.error(err);
+        });
+    },
+    getMySubTalk() {
+      let params = {
+        userid: this.userid,
+      };
+      this.ajax
+        .get(this.$store.state.api + "selectMySubTalk", params)
+        .then((res) => {
+          this.mySubTalk = res.data[0];
+        })
+        .catch((err) => {
+          console.error(err);
+        });
+    },
+    openAddTalk() {
+      this.fid = "";
+      this.sid = "";
+      this.isShowSelect = !this.isShowSelect;
+      this.addTalkDialogVisible = true;
+    },
+    editMySub(id, n) {},
+    delMySub(id) {},
+  },
+  mounted() {
+    this.getClass2();
+    this.getEnglishType();
+  },
+};
+</script>
+
+<style scoped>
+.checkBox {
+  width: 100%;
+  height: calc(100% - 12%);
+}
+.c_Box {
+  width: 50%;
+  margin: 10px auto;
+  display: flex;
+  flex-direction: column;
+  flex-wrap: nowrap;
+  align-items: center;
+}
+.check_intro {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: nowrap;
+  align-items: center;
+  width: 100%;
+  /* height: 120px; */
+  position: relative;
+  border-radius: 10px;
+}
+/* .aiImg {
+  width: 145px;
+  height: 150px;
+  position: absolute;
+  top: -30px;
+  left: 5px;
+} */
+.check_intro > img {
+  width: 100%;
+  height: 100%;
+}
+.intro_text {
+  width: calc(100% - 180px);
+  display: flex;
+  flex-direction: column;
+  flex-wrap: nowrap;
+  align-items: flex-start;
+  position: absolute;
+  left: 170px;
+  font-size: 12px;
+}
+.intro_text > div:first-child {
+  color: #3f87fc;
+  font-size: 22px;
+  font-weight: bold;
+  margin: 0 0 10px 0;
+}
+
+.form_box {
+  width: calc(100% - 40px);
+  display: flex;
+  flex-direction: column;
+  flex-wrap: nowrap;
+  align-items: flex-start;
+  margin: 20px 0 0 0;
+  background: #fff;
+  border-radius: 10px;
+  padding: 20px;
+}
+
+.check_item {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: nowrap;
+  align-items: center;
+  margin: 0 0 20px 0;
+}
+
+.check_item > div:first-child {
+  margin-right: 10px;
+  min-width: 72px;
+  text-align: center;
+}
+
+.ctime_right,
+.ctime_right1 {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: nowrap;
+  align-items: center;
+}
+.ctime_right > div {
+  margin: 0 10px 0 0;
+  border: 1px solid #d3d3d3;
+  border-radius: 5px;
+  min-width: 100px;
+  text-align: center;
+  cursor: pointer;
+  height: 30px;
+  line-height: 30px;
+}
+.form_box > div:first-child > .ctime_right > div:not(:last-child) {
+  border: 1px solid #d3d3d3;
+  border-radius: 5px;
+  min-width: 100px;
+  text-align: center;
+  cursor: pointer;
+  height: 30px;
+  line-height: 30px;
+}
+.ctime_right > div >>> .el-input__inner {
+  height: 32px;
+}
+
+.isTime {
+  background: #e0eafb !important;
+  color: #468afb !important;
+  border: 1px solid #488cfb !important;
+}
+
+.selectInput {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: nowrap;
+  align-items: center;
+  width: 400px;
+  height: 30px;
+  border: 1px solid #dcdfe6;
+  border-radius: 5px;
+  background: #fff;
+  justify-content: space-between;
+  cursor: pointer;
+}
+
+.selectInput:hover {
+  border: 1px solid #75a8fb !important;
+}
+
+.subTalkBox {
+  position: absolute;
+  top: 40px;
+  left: 80px;
+  width: 500px;
+  display: flex;
+  flex-direction: row;
+  flex-wrap: nowrap;
+  align-items: flex-start;
+  z-index: 9;
+}
+
+.subTalkBox > .left,
+.subTalkBox > .right {
+  background: #fff;
+  border: 1px solid #e8e8e8;
+  width: 50%;
+  min-height: 250px;
+  border-radius: 5px;
+  padding: 5px;
+}
+
+.subTalkBox > .right {
+  border-left: none;
+}
+
+.subTalkBox > .left > div,
+.subTalkBox > .right > div {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: nowrap;
+  align-items: center;
+  justify-content: space-between;
+  padding: 5px;
+  cursor: pointer;
+  width: calc(100% - 10px);
+}
+
+.subTalkBox > .left > div > div:first-child,
+.subTalkBox > .right > div > div:first-child {
+  max-width: 160px;
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  word-break: break-word;
+}
+
+.subTalkBox > .left > div:not(:last-child),
+.subTalkBox > .right > div:not(:last-child) {
+  margin: 0 0 5px 0;
+}
+
+.subTalkBox > .left > div > .allImg {
+  width: 12px;
+  height: 12px;
+}
+.subTalkBox > .left > div > .allImg > img {
+  width: 100%;
+  height: 100%;
+}
+.selectInput > div:first-child {
+  color: #c0c4cc;
+  padding: 0 0 0 15px;
+}
+.downImg {
+  width: 20px;
+  height: 20px;
+  margin-right: 10px;
+  transition: opacity 0.5s;
+}
+
+.downImg > img {
+  width: 100%;
+  height: 100%;
+}
+
+.isCType {
+  background: #e0eafb !important;
+  color: #3681fc !important;
+  border-radius: 5px;
+}
+
+.addImg {
+  width: 20px;
+  height: 20px;
+  margin: 0 5px;
+}
+.addImg > img {
+  width: 100%;
+  height: 100%;
+}
+
+.inputBox {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: nowrap;
+  align-items: center;
+}
+
+.addNewTalk {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: nowrap;
+  align-items: center;
+  color: #659efc;
+  border: 1px solid #eff4fc;
+  border-radius: 5px;
+  min-width: 100px;
+  height: 30px;
+  margin: 0 0 0 10px;
+  cursor: pointer;
+}
+
+.goButton {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: nowrap;
+  align-items: center;
+  width: 100px;
+  text-align: center;
+  background: #3681fc;
+  color: #fff;
+  height: 35px;
+  line-height: 35px;
+  justify-content: center;
+  border-radius: 5px;
+  cursor: pointer;
+}
+
+.rightImg {
+  width: 20px;
+  margin-left: 5px;
+  line-height: 15px;
+}
+
+.rightImg > img,
+.noFile > img {
+  width: 100%;
+  height: 100%;
+}
+
+.noFile {
+  width: 70px !important;
+}
+
+.ctime_right1 >>> .el-checkbox-group {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: nowrap;
+  align-items: center;
+  margin: 0 0 0 15px;
+}
+
+.ctime_right1 >>> .el-checkbox {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: nowrap;
+  align-items: center;
+}
+
+.check_item >>> .el-select-dropdown__item:hover {
+  background-color: #e0eafb !important;
+  color: #3983fb !important;
+}
+
+.rightIcon {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: nowrap;
+  align-items: center;
+}
+
+.rightIcon > div:first-child {
+  margin: 0 5px 0 0;
+}
+
+.editImg,
+.delImg {
+  width: 25px;
+  height: 25px;
+  cursor: pointer;
+}
+
+.editImg > img,
+.delImg > img {
+  width: 100%;
+  height: 100%;
+}
+</style>

+ 254 - 0
src/components/pages/EnglishVoice new/component/component/addTalk.vue

@@ -0,0 +1,254 @@
+<template>
+  <el-dialog
+    title="新建主题"
+    :visible.sync="addTalkDialogVisible"
+    :append-to-body="true"
+    width="30%"
+    :before-close="handleClose"
+    class="dialog_diy"
+  >
+    <div class="talkBox">
+      <div class="talkTop">
+        <div>主题名称<span style="color: red">*</span></div>
+        <div>
+          <el-input v-model="title" placeholder="请填写对话主题名称"></el-input>
+        </div>
+      </div>
+      <div class="talkTop">
+        <div>分类</div>
+        <div>
+          <el-select v-model="tid" placeholder="请选择分类">
+            <el-option
+              v-for="(item, index) in allfType"
+              :key="index"
+              :label="item.name"
+              :value="item.id"
+            ></el-option>
+          </el-select>
+        </div>
+      </div>
+      <div class="tips">
+        请在下框中描述您要创建的对话情境,您也可以基于以下内容进行修改。
+      </div>
+      <div class="talkText">
+        <el-input
+          type="textarea"
+          placeholder="请将对话情境设定在【节日活动-节日祝福】这个大场景之下,该任务需包含具体的情境(时间、地点、角色、事件)和对应的任务,该任务具有明确的完成形态,是一个具体的动作,比如「在餐厅点餐点了一份汉堡和薯条」、「知道明天会下午并且需要提前带伞」。
+例如,在【日常对话-询问路线】这个场景中,情境是:放学了(时间)在路边(地点),路边有一位叔叔(角色A),一个小学三年级学生(角色B)想去附近一公里的游乐园玩(事件)。对应的任务是:小学生不知道怎么走,他想询问路边的那位叔叔,搞清楚去游乐园的路线(任务)。"
+          v-model="text"
+          resize="none"
+        >
+        </el-input>
+      </div>
+      <div class="saveBox">
+        <el-switch v-model="isSaveMe" active-text="保存为我的话题"></el-switch>
+        <div>(可以在"我的主题"中修改已保存的主题)</div>
+      </div>
+    </div>
+    <span slot="footer" class="dialog-footer">
+      <!-- <el-button type="primary" @click="confirm(0)">保存到我的话题</el-button> -->
+      <el-button
+        @click="close()"
+        style="background-color: #f0f2f5; color: #7d7e7f"
+        >取消</el-button
+      >
+      <el-button
+        type="primary"
+        @click="confirm"
+        style="background-color: #3681fc; border-color: #3681fc"
+        >确定创建</el-button
+      >
+    </span>
+  </el-dialog>
+</template>
+
+<script>
+export default {
+  props: {
+    addTalkDialogVisible: {
+      type: Boolean,
+      default: false,
+    },
+    oid: {
+      type: String,
+    },
+    org: {
+      type: String,
+    },
+    userid: {
+      type: String,
+    },
+    allfType: {
+      type: Array,
+    },
+  },
+  data() {
+    return {
+      title: "",
+      text: "",
+      tid: "",
+      isSaveMe: false,
+    };
+  },
+  methods: {
+    handleClose(done) {
+      this.close();
+      done();
+    },
+    close() {
+      this.$emit("update:addTalkDialogVisible", false);
+    },
+    confirm() {
+      let params = [
+        {
+          t: this.title,
+          text: this.text,
+          type: this.tid,
+          uid: this.userid,
+          oid: this.oid,
+        },
+      ];
+      this.ajax
+        .post(this.$store.state.api + "addSubTalk", params)
+        .then((res) => {
+          if (this.isSaveMe) {
+            this.addEVType();
+          } else {
+            this.$message({
+              message: "创建成功",
+              type: "success",
+            });
+            this.close();
+          }
+        })
+        .catch((err) => {
+          this.$message.error("创建失败");
+          console.error(err);
+        });
+    },
+    addEVType() {
+      let params = [
+        {
+          t: this.title,
+          type: this.tid,
+          uid: this.userid,
+          oid: this.oid,
+        },
+      ];
+      this.ajax
+        .post(this.$store.state.api + "addEngVType", params)
+        .then((res) => {
+          this.$message({
+            message: "保存成功",
+            type: "success",
+          });
+        })
+        .catch((err) => {
+          this.$message.error("保存失败");
+          console.error(err);
+        });
+    },
+  },
+  watch: {
+    addTalkDialogVisible: {
+      handler: function (newVal, oldVal) {
+        if (newVal) {
+          //   this.setVoiceJson(this.englishVoiceJson);
+        }
+      },
+      deep: true,
+    },
+  },
+};
+</script>
+
+<style scoped>
+.dialog_diy >>> .el-dialog {
+  height: 60%;
+  margin: 20vh auto !important;
+}
+
+.dialog_diy >>> .el-dialog__header {
+  background: #454545 !important;
+  padding: 15px 20px;
+}
+
+.dialog_diy >>> .el-dialog__body {
+  height: calc(100% - 124px);
+  box-sizing: border-box;
+  padding: 0px;
+}
+
+.dialog_diy >>> .el-dialog__title {
+  color: #fff;
+}
+
+.dialog_diy >>> .el-dialog__headerbtn {
+  top: 19px;
+}
+
+.dialog_diy >>> .el-dialog__headerbtn .el-dialog__close {
+  color: #fff;
+}
+
+.dialog_diy >>> .el-dialog__headerbtn .el-dialog__close:hover {
+  color: #fff;
+}
+
+.dialog_diy >>> .el-dialog__body,
+.dialog_diy >>> .el-dialog__footer {
+  background: rgb(rgb(240, 242, 245));
+  overflow: hidden;
+}
+
+.talkBox {
+  padding: 15px 20px;
+  display: flex;
+  flex-direction: column;
+  flex-wrap: nowrap;
+  align-items: flex-start;
+}
+.talkBox > div:not(:first-child) {
+  margin-top: 10px;
+}
+.talkTop {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: nowrap;
+  align-items: center;
+  width: 100%;
+}
+
+.talkTop > div:first-child {
+  min-width: 70px;
+}
+
+.talkTop > div:last-child {
+  width: calc(100% - 70px);
+}
+
+.talkText {
+  width: 100%;
+}
+
+.talkText >>> .el-textarea__inner {
+  min-height: 250px !important;
+}
+
+.tips {
+  font-size: 12px;
+  color: #4f90fc;
+}
+
+.saveBox {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: nowrap;
+  align-items: center;
+}
+
+.saveBox > div:last-child {
+  color: #b3b3b3;
+  font-size: 12px;
+}
+</style>

+ 18 - 0
src/components/pages/EnglishVoice new/component/component/report.vue

@@ -0,0 +1,18 @@
+<template>
+  <div class="reportBox"></div>
+</template>
+
+<script>
+export default {};
+</script>
+
+<style scoped>
+.reportBox {
+  background: #fff;
+  width: 800px;
+  height: 300px;
+  position: absolute;
+  bottom: -320px;
+  right: 45px;
+}
+</style>

+ 707 - 0
src/components/pages/EnglishVoice new/component/talkPreview.vue

@@ -0,0 +1,707 @@
+<template>
+  <el-dialog
+    title="对话预览"
+    :visible.sync="talkPreviewDialog"
+    :append-to-body="true"
+    width="100%"
+    :before-close="handleClose"
+    class="dialog_diy"
+  >
+    <div class="o_content">
+      <div class="d_box">
+        <div class="dialog">
+          <div class="d_img">
+            <img
+              :src="
+                require('../../../../assets/icon/englishVoice/icon_portal.png')
+              "
+              alt=""
+            />
+          </div>
+          <div class="d_content_message">
+            <div>Hello,以下是我们这次口语练习的要求:</div>
+            <div class="d_name" v-if="answerArray.time">
+              练习时长:{{
+                answerArray.time == "all" ? "不限时" : answerArray.time + "min"
+              }}
+            </div>
+            <div class="d_name" v-if="answerArray.difficulty">
+              设置难度:{{
+                answerArray.difficulty == 0
+                  ? "简单"
+                  : answerArray.difficulty == 1
+                  ? "一般"
+                  : "困难"
+              }}
+            </div>
+            <div
+              class="d_name"
+              v-if="fName && sName"
+              style="
+                display: flex;
+                flex-direction: row;
+                flex-wrap: nowrap;
+                align-items: center;
+                width: 100%;
+              "
+            >
+              <div style="min-width: 60px">对话主题:</div>
+              <div style="width: calc(100% - 80px)">
+                {{ fName - sName }}
+              </div>
+            </div>
+            <div class="gotoTalk">我已了解,开始对话</div>
+            <div class="nowTime">{{ currentTime }}</div>
+          </div>
+        </div>
+        <div class="dialog">
+          <div class="d_img">
+            <img
+              :src="
+                require('../../../../assets/icon/englishVoice/icon_portal.png')
+              "
+              alt=""
+            />
+          </div>
+          <div class="d_content">
+            <div class="d_voice">
+              <mini-audio
+                :audio-source="voice"
+                class="audio_class"
+              ></mini-audio>
+            </div>
+            <div class="d_log">
+              {{ content }}
+            </div>
+          </div>
+          <div class="nowTime" style="margin: 0 0 0 50px">
+            {{ currentTime }}
+          </div>
+        </div>
+        <div class="dialog dialog_right">
+          <div class="d_img">
+            <img
+              :src="
+                require('../../../../assets/icon/englishVoice/icon_portal.png')
+              "
+              alt=""
+            />
+          </div>
+          <div class="d_content">
+            <div class="d_voice">
+              <mini-audio
+                :audio-source="voice"
+                class="audio_class"
+              ></mini-audio>
+            </div>
+            <div class="d_log2">
+              {{ content }}
+            </div>
+          </div>
+          <report v-if="lookReport"></report>
+          <div @click="lookReport = true" class="reportButton" :style="{bottom:lookReport ? '-360px' : '-35px'}">查看报告</div>
+          <div class="nowTime" style="margin: 0 50px 0 0; bottom: -60px" :style="{bottom:lookReport ? '-390px' : '-60px'}">
+            {{ currentTime }}
+          </div>
+        </div>
+      </div>
+    </div>
+    <div class="o_bottom" v-loading="isloading">
+      <div class="audio" v-if="!LuAudioUrl">
+        <img
+          v-if="!isRecord"
+          src="../../../../assets/icon/englishVoice/start_aduio.png"
+          alt=""
+          @click="startRecorder"
+        />
+        <img
+          v-else
+          src="../../../../assets/icon/englishVoice/stop_audio.png"
+          alt=""
+          @click="startRecorder"
+        />
+      </div>
+      <div class="audio_word" v-if="!LuAudioUrl">
+        <span v-if="!isRecord">点击话筒开始录音</span>
+        <span v-else>点击话筒结束录音</span>
+      </div>
+      <div v-if="LuAudioUrl" class="audio_b">
+        <mini-audio :audio-source="LuAudioUrl" class="audio_class"></mini-audio>
+      </div>
+      <div v-if="LuAudioUrl" class="audio_rerecord" @click="restart()">
+        <span>录音</span>
+      </div>
+      <!-- <div v-else class="audio_ing">
+        <span>正在录音...</span>
+      </div> -->
+      <div class="checkFooter">
+        <div>上一步</div>
+        <div style="background: #3681fc; color: #fff; border: none">
+          确认创建
+        </div>
+      </div>
+    </div>
+    <iframe
+      allow="camera *; microphone *;display-capture;midi;encrypted-media;"
+      src="https://beta.cloud.cocorobo.cn/browser/public/index.html"
+      ref="iiframe"
+      v-show="false"
+    ></iframe>
+  </el-dialog>
+</template>
+
+<script>
+import Recorder from "js-audio-recorder";
+const lamejs = require("lamejs");
+
+const recorder = new Recorder({
+  sampleBits: 16, // 采样位数,支持 8 或 16,默认是16
+  sampleRate: 48000, // 采样率,支持 11025、16000、22050、24000、44100、48000,根据浏览器默认值,我的chrome是48000
+  numChannels: 1, // 声道,支持 1 或 2, 默认是1
+  // compiling: false,(0.x版本中生效,1.x增加中) // 是否边录边转换,默认是false
+});
+
+// 绑定事件-打印的是当前录音数据
+recorder.onprogress = function (params) {
+  // console.log('--------------START---------------')
+  // console.log('录音时长(秒)', params.duration);
+  // console.log('录音大小(字节)', params.fileSize);
+  // console.log('录音音量百分比(%)', params.vol);
+  // console.log('当前录音的总数据([DataView, DataView...])', params.data);
+  // console.log('--------------END---------------')
+};
+import report from "./component/report.vue";
+export default {
+  components: {
+    report,
+  },
+  props: {
+    talkPreviewDialog: {
+      type: Boolean,
+      default: false,
+    },
+    oid: {
+      type: String,
+    },
+    org: {
+      type: String,
+    },
+    checkJson: {
+      type: Object,
+    },
+  },
+  data() {
+    return {
+      answerArray: [],
+      fName: "",
+      sName: "",
+      currentTime: "",
+      isloading: false,
+      LuAudioUrl: "",
+      isRecord: false,
+      calcTimer: null,
+      totalSeconds: 0,
+      voice: "",
+      lookReport: false,
+      content:
+        "Read the following text aloud.A Car Accident I saw a car accident this morning. A boy wanted to cross the road but he did not look carefully. He just ran out into the road. A car was coming and the driver stopped at once. Luckily, the boy was not hurt. However, there was a bus behind the car. It could not stop and hit the back of the car. Someone called the police and they arrived quickly.",
+    };
+  },
+  methods: {
+    handleClose(done) {
+      this.close();
+      done();
+    },
+    close() {
+      this.$emit("update:talkPreviewDialog", false);
+    },
+    setVoiceJson(val) {
+      let a = JSON.parse(JSON.stringify(val));
+      for (var i = 0; i < a.allfType.length; i++) {
+        for (var j = 0; j < a.englishJson[a.allfType[i].id].length; j++) {
+          if (a.englishJson[a.allfType[i].id][j].id == a.topic) {
+            this.fName = a.allfType[i].name;
+            this.sName = a.englishJson[a.allfType[i].id][j].name;
+          }
+        }
+      }
+      this.answerArray = a;
+      this.$forceUpdate();
+    },
+    formatDate(date) {
+      const year = date.getFullYear();
+      const month = (date.getMonth() + 1).toString().padStart(2, "0");
+      const day = date.getDate().toString().padStart(2, "0");
+      const hours = date.getHours().toString().padStart(2, "0");
+      const minutes = date.getMinutes().toString().padStart(2, "0");
+      const seconds = date.getSeconds().toString().padStart(2, "0");
+
+      return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
+    },
+    restart() {
+      let _this = this;
+      _this
+        .$confirm("确定重新录音么?", "提示", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning",
+        })
+        .then(() => {
+          _this.LuAudioUrl = "";
+          setTimeout(() => {
+            _this.startRecorder();
+          }, 500);
+        })
+        .catch(() => {});
+    },
+    // 开始录音
+    startRecorder() {
+      let _this = this;
+      if (!_this.isRecord) {
+        recorder.destroy(); // 销毁录音
+        _this.isRecord = true;
+        recorder.start().then(
+          () => {},
+          (error) => {
+            _this.isRecord = false;
+            // _this.$message.error(`${error.name} : ${error.message}`);
+            _this.$message.error(
+              `没有找到可使用的麦克风,或者您没有允许此网页使用麦克风`
+            );
+            // 出错了
+            console.log(`${error.name} : ${error.message}`);
+            if (_this.calcTimer) {
+              clearInterval(_this.calcTimer);
+              _this.calcTimer = null;
+            }
+          }
+        );
+      } else {
+        if (_this.calcTimer) {
+          clearInterval(_this.calcTimer);
+          _this.calcTimer = null;
+        }
+        _this.isRecord = false;
+        recorder.stop(); // 结束录音
+        this.getMp3Data();
+      }
+    },
+    getMp3Data() {
+      if (!recorder.fileSize) {
+        this.$message.error("请录音后在上传语音");
+        return;
+      }
+
+      const mp3Blob = recorder.getWAVBlob();
+      // const mp3Blob = this.convertToMp3(recorder.getWAV());
+      let audioFile = this.dataURLtoAudio(mp3Blob, "wav");
+      console.log(audioFile);
+      let iiframe = this.$refs["iiframe"];
+
+      // this.isloading = true
+      //   this.beforeUpload1(audioFile, 3);
+      //   return;
+      // if (this.cjson.type == 'theme' || this.cjson.type == 'QA') {
+      //   this.isloading = true
+      //   let _this = this
+      //   iiframe.contentWindow.onRecognizedResult = function (e) {
+      //     console.log('onRecognizedResult', e);
+      //     let privText = e.privText
+      //     _this.beforeUpload1(audioFile, 3, privText);
+      //   }
+
+      //   iiframe.contentWindow.doContinuousPronunciationAssessment('', { files: [audioFile] })
+      // } else if (this.cjson.type == 'createRole') {
+      //   // this.isloading = true
+      //   // this.beforeUpload1(audioFile, 3);
+      //   this.isloading = true
+      //   let _this = this
+      //   iiframe.contentWindow.onRecognizedResult = function (e) {
+      //     console.log('onRecognizedResult', e);
+      //     let privText = e.privText
+      //     _this.beforeUpload1(audioFile, 3, privText);
+      //   }
+
+      //   iiframe.contentWindow.doContinuousPronunciationAssessment('', { files: [audioFile] })
+      // } else {
+      this.isloading = true;
+      let _this = this;
+      iiframe.contentWindow.onRecognizedResult = function (e) {
+        console.log("onRecognizedResult", e);
+        let privText = e.privText;
+        let star = JSON.parse(e.privJson).NBest[0].PronunciationAssessment;
+        console.log("star", star);
+        // e.privText
+        // JSON.parse(e.privJson).NBest[0].PronunciationAssessment
+
+        // _this.beforeUpload1(audioFile, 3, privText, star);
+      };
+      iiframe.contentWindow.doContinuousPronunciationAssessment("", {
+        files: [audioFile],
+      });
+      // }
+
+      // recorder.download(mp3Blob, "recorder", "mp3");
+    },
+  },
+  watch: {
+    talkPreviewDialog: {
+      handler: function (newVal, oldVal) {
+        if (newVal) {
+          this.setVoiceJson(this.checkJson);
+        }
+      },
+      deep: true,
+    },
+  },
+  created() {
+    this.currentTime = this.formatDate(new Date());
+  },
+  mounted() {
+    this.setVoiceJson(this.checkJson);
+  },
+};
+</script>
+
+<style scoped>
+.dialog_diy >>> .el-dialog {
+  height: 100%;
+  margin: 0vh auto !important;
+}
+
+.dialog_diy >>> .el-dialog__header {
+  background: #454545 !important;
+  padding: 15px 20px;
+}
+
+.dialog_diy >>> .el-dialog__body {
+  height: calc(100% - 124px);
+  box-sizing: border-box;
+  padding: 0px;
+}
+
+.dialog_diy >>> .el-dialog__title {
+  color: #fff;
+}
+
+.dialog_diy >>> .el-dialog__headerbtn {
+  top: 19px;
+}
+
+.dialog_diy >>> .el-dialog__headerbtn .el-dialog__close {
+  color: #fff;
+}
+
+.dialog_diy >>> .el-dialog__headerbtn .el-dialog__close:hover {
+  color: #fff;
+}
+
+.dialog_diy >>> .el-dialog__body,
+.dialog_diy >>> .el-dialog__footer {
+  background: rgb(rgb(240, 242, 245));
+  overflow: hidden;
+}
+
+.o_content {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  flex-direction: column;
+  height: calc(100% - 210px);
+  overflow: hidden;
+}
+
+.d_box {
+  width: 100%;
+  height: 100%;
+  padding: 25px 50px;
+  -webkit-box-sizing: border-box;
+  box-sizing: border-box;
+  overflow: auto;
+}
+
+.dialog {
+  display: flex;
+  position: relative;
+}
+
+.dialog + .dialog {
+  margin-top: 40px;
+}
+
+.dialog_right {
+  flex-direction: row-reverse;
+}
+
+.dialog > .d_img {
+  width: 40px;
+  height: 40px;
+  min-width: 40px;
+  overflow: hidden;
+  border-radius: 50%;
+  margin-right: 5px;
+}
+
+.dialog > .d_img > img {
+  width: 100%;
+  height: 100%;
+  object-fit: cover;
+}
+
+.dialog_right > .d_img {
+  margin-right: 0;
+  margin-left: 5px;
+}
+
+.dialog > .d_content,
+.dialog > .d_content_message {
+  width: 100%;
+}
+.dialog > .d_content_message {
+  display: flex;
+  width: 300px;
+  background: #f6f9ff;
+  flex-direction: column;
+  flex-wrap: nowrap;
+  align-items: flex-start;
+  border-radius: 10px;
+  margin: 0 0 0 10px;
+  position: relative;
+}
+.dialog > .d_content_message > div {
+  padding: 5px;
+}
+.nowTime {
+  position: absolute;
+  bottom: -30px;
+  color: #9c9d9f;
+  font-size: 12px;
+}
+.dialog_right > .d_content,
+.dialog_right > .d_content_message {
+  display: flex;
+  flex-direction: column;
+  align-items: flex-end;
+}
+
+.dialog > .d_content > .d_name,
+.dialog > .d_content_message > .d_name {
+  color: #7c7c7c;
+  font-size: 12px;
+  margin-bottom: 5px;
+}
+
+.dialog_right > .d_content > .d_name,
+.dialog_right > .d_content_message > .d_name {
+  text-align: right;
+}
+
+.dialog > .d_content > .d_log,
+.dialog > .d_content_message > .d_log {
+  color: #000;
+  font-size: 16px;
+  background: #fff;
+  width: 100%;
+  max-width: 800px;
+  border: 2px solid #e05d63;
+  border-radius: 40px;
+  line-height: 26px;
+  padding: 20px 35px;
+  box-sizing: border-box;
+  position: relative;
+  margin: 10px 0 0 0;
+}
+
+.dialog > .d_content > .d_log::before,
+.dialog > .d_content_message > .d_log::before {
+  content: "";
+  width: calc(100% - 20px);
+  height: calc(100% - 20px);
+  position: absolute;
+  border: 1px dashed #e05d63;
+  box-sizing: border-box;
+  top: 50%;
+  left: 50%;
+  border-radius: 30px;
+  transform: translate(-50%, -50%);
+}
+
+.dialog > .d_content > .d_log2,
+.dialog > .d_content_message > .d_log2 {
+  color: #000;
+  font-size: 14px;
+  background: #fff;
+  width: 100%;
+  max-width: 800px;
+  border: 1px dashed #0f94ce;
+  border-radius: 5px;
+  line-height: 26px;
+  padding: 10px;
+  box-sizing: border-box;
+  position: relative;
+  margin-top: 10px;
+}
+
+.dialog > .d_content > .d_voice,
+.dialog > .d_content_message > .d_voice {
+  width: 100%;
+  max-width: 600px;
+}
+
+.audio_class {
+  background: #3680fb !important;
+  margin: 0 !important;
+  width: 100% !important;
+  box-sizing: border-box !important;
+}
+
+.d_voice >>> .vueAudioBetter span:before {
+  color: #fff;
+}
+
+.audio_class >>> .slider .process {
+  background: #000;
+}
+
+.d_voice >>> .vueAudioBetter .iconfont:active {
+  position: unset !important;
+}
+
+.o_bottom {
+  height: 210px;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+}
+
+.o_bottom .audio {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.o_bottom .audio > img {
+  width: 75px;
+  height: 75px;
+  cursor: pointer;
+}
+
+.o_bottom .audio_word {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  color: #00000099;
+  font-size: 16px;
+  margin: 10px 0 8px;
+}
+
+.audio_b {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  margin-bottom: 15px;
+}
+
+.audio_rerecord {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  margin-bottom: 15px;
+}
+
+.audio_rerecord > span {
+  display: flex;
+  border: 1px solid #3981fa;
+  align-items: center;
+  color: #3981fa;
+  padding: 5px 10px;
+  border-radius: 5px;
+  cursor: pointer;
+}
+
+.audio_rerecord > span::before {
+  content: "";
+  width: 15px;
+  height: 15px;
+  background: url("../../../../assets/icon/englishVoice/restart.png");
+  display: block;
+  background-size: 100% 100%;
+  margin-right: 5px;
+}
+
+.audio_class {
+  background: #3680fb !important;
+  margin: 0 !important;
+}
+
+.audio_b >>> .vueAudioBetter span:before {
+  color: #fff;
+}
+
+.audio_class >>> .slider .process {
+  background: #000;
+}
+
+.audio_b >>> .vueAudioBetter .iconfont:active {
+  position: unset !important;
+}
+
+.audio_ing {
+  color: #ee3e3e;
+  margin-top: 25px;
+  font-size: 12px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.gotoTalk {
+  margin: 0 5px 10px 5px;
+  background: #3681fc;
+  color: #fff;
+  text-align: center;
+  width: calc(100% - 20px);
+  height: 30px;
+  line-height: 30px;
+  padding: 0 !important;
+  border-radius: 5px;
+  cursor: pointer;
+}
+
+.checkFooter {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: nowrap;
+  align-items: center;
+  justify-content: flex-end;
+}
+.checkFooter > div {
+  min-width: 100px;
+  width: 100px;
+  text-align: center;
+  border-radius: 5px;
+  background: #ffffff;
+  color: #3681fc;
+  border: 1px solid #3681fc;
+  height: 35px;
+  line-height: 35px;
+  margin-right: 10px;
+  font-size: 12px;
+  cursor: pointer;
+}
+
+.reportButton {
+  position: absolute;
+  bottom: -35px;
+  right: 50px;
+  background: #16c267;
+  color: #fff;
+  width: 70px;
+  height: 25px;
+  text-align: center;
+  line-height: 25px;
+  cursor: pointer;
+  border-radius: 5px;
+}
+</style>

+ 332 - 0
src/components/pages/EnglishVoice new/index.vue

@@ -0,0 +1,332 @@
+<template>
+  <el-dialog
+    title="英语口语"
+    :visible.sync="EnglishVoiceDialog"
+    :append-to-body="true"
+    width="100%"
+    :before-close="handleClose"
+    class="dialog_diy"
+  >
+    <div class="engBox" v-if="diaType == '0'">
+      <div
+        class="leftBox"
+        :class="boxClick == '0' ? 'clickBox leftBox' : 'leftBox'"
+        @click="boxClick = '0'"
+      >
+        <div class="fChoose">
+          <img src="../../../assets/icon/englishVoice/fChoose.png" alt="" />
+        </div>
+        <div>自然交流场景</div>
+        <div>
+          自然交流场景说明自然交流场景说明自然交流场景说明自然交流场景说(最多展示两行)
+        </div>
+        <div class="goButton" @click="diaType = '1'" v-if="boxClick == '0'">
+          <div>去创建</div>
+          <div class="right">
+            <img src="../../../assets/icon/englishVoice/right.png" alt="" />
+          </div>
+        </div>
+      </div>
+      <div
+        class="rightBox"
+        :class="boxClick == '1' ? 'clickBox rightBox' : 'rightBox'"
+        @click="boxClick = '1'"
+      >
+        <div class="sChoose">
+          <img src="../../../assets/icon/englishVoice/sChoose.png" alt="" />
+        </div>
+        <div>口语题目场景</div>
+        <div>
+          口语题目场景说明口语题目场景说明口语题目场景说明口语题目场景说明(最多展示两行)
+        </div>
+        <div class="goButton" @click="diaType = '1'" v-if="boxClick == '1'">
+          <div>去创建</div>
+          <div class="right">
+            <img src="../../../assets/icon/englishVoice/right.png" alt="" />
+          </div>
+        </div>
+      </div>
+    </div>
+    <check
+      :checkJson="checkJson"
+      @setCheckJson="setCheckJson"
+      :diaType="diaType"
+      :oid="oid"
+      :org="org"
+      v-if="diaType == '1'"
+    ></check>
+    <talkPreview
+      :talkPreviewDialog.sync="talkPreviewDialog"
+      :checkJson="checkJson"
+      :oid="oid"
+      :org="org"
+    ></talkPreview>
+    <span slot="footer" class="dialog-footer" v-if="diaType == '0'">
+      <el-button type="primary" @click="close()">确 认</el-button>
+      <el-button @click="close()">关 闭</el-button>
+    </span>
+    <span
+      slot="footer"
+      class="dialog-footer checkFooter"
+      v-if="diaType == '1' || talkPreviewDialog"
+    >
+      <div @click="diaType = '0'">上一步</div>
+      <div @click="talkPreview">对话预览</div>
+      <div
+        @click="confirm()"
+        style="background: #3681fc; color: #fff; border: none"
+      >
+        确认上传
+      </div>
+    </span>
+  </el-dialog>
+</template>
+
+<script>
+import check from "./component/check";
+import talkPreview from "./component/talkPreview.vue";
+export default {
+  components: {
+    check,
+    talkPreview,
+  },
+  props: {
+    EnglishVoiceDialog: {
+      type: Boolean,
+      default: false,
+    },
+    oid: {
+      type: String,
+    },
+    org: {
+      type: String,
+    },
+    englishVoiceJson: {
+      type: Object,
+    },
+  },
+  data() {
+    return {
+      checkJson: {
+        time: "",
+        class: "",
+        difficulty: 0,
+        topic: "",
+        isShow: false,
+        eva: 0,
+        aiEva: {
+          isAiEva: false,
+          aiEvaChoose: [],
+        },
+        allfType: [],
+        englishJson: {},
+      },
+      diaType: "0",
+      boxClick: "0",
+      talkPreviewDialog: false,
+    };
+  },
+  methods: {
+    handleClose(done) {
+      this.close();
+      done();
+    },
+    close() {
+      this.diaType = "0";
+      this.$emit("update:EnglishVoiceDialog", false);
+    },
+    setCheckJson(checkJson) {
+      this.checkJson = checkJson;
+    },
+    confirm() {
+      this.$emit(
+        "setEnglishVoiceJson",
+        JSON.parse(JSON.stringify(this.checkJson))
+      );
+      this.close();
+    },
+    talkPreview() {
+      if (this.checkJson.time == "") {
+        this.$message.error("请选择练习时长!");
+        return;
+      } else if (this.checkJson.class == "") {
+        this.$message.error("请选择年级!");
+        return;
+      } else if (this.checkJson.topic == "") {
+        this.$message.error("请选择话题!");
+        return;
+      }
+      this.talkPreviewDialog = true;
+    },
+  },
+  watch: {
+    EnglishVoiceDialog: {
+      handler: function (newVal, oldVal) {
+        if (newVal) {
+          //   this.setVoiceJson(this.englishVoiceJson);
+          this.checkJson = JSON.parse(JSON.stringify(this.englishVoiceJson));
+        }
+      },
+      deep: true,
+    },
+  },
+  mounted() {
+    // this.setVoiceJson(this.englishVoiceJson);
+  },
+};
+</script>
+
+<style scoped>
+.dialog_diy >>> .el-dialog {
+  background: #f0f2f5;
+  height: 100%;
+  margin: 0vh auto !important;
+}
+
+.dialog_diy >>> .el-dialog__header {
+  background: #454545 !important;
+  padding: 15px 20px;
+}
+
+.dialog_diy >>> .el-dialog__body {
+  height: calc(100% - 124px);
+  box-sizing: border-box;
+  padding: 0px;
+}
+
+.dialog_diy >>> .el-dialog__title {
+  color: #fff;
+}
+
+.dialog_diy >>> .el-dialog__headerbtn {
+  top: 19px;
+}
+
+.dialog_diy >>> .el-dialog__headerbtn .el-dialog__close {
+  color: #fff;
+}
+
+.dialog_diy >>> .el-dialog__headerbtn .el-dialog__close:hover {
+  color: #fff;
+}
+
+.dialog_diy >>> .el-dialog__body,
+.dialog_diy >>> .el-dialog__footer {
+  background: #f0f2f5;
+  overflow: hidden;
+}
+
+.engBox {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  flex-direction: row;
+  flex-wrap: nowrap;
+  align-items: center;
+  justify-content: center;
+}
+
+.leftBox,
+.rightBox {
+  display: flex;
+  flex-direction: column;
+  flex-wrap: nowrap;
+  align-items: center;
+  width: 400px;
+  padding: 20px;
+  background: #fff;
+  border-radius: 5px;
+  cursor: pointer;
+  position: relative;
+}
+
+.clickBox {
+  border: 2px solid #78aafc;
+  box-shadow: 0px 1px 10px 2px #e0e0e0;
+}
+
+.leftBox {
+  margin: 0 50px 0 0;
+}
+
+.leftBox > div:nth-child(2),
+.rightBox > div:nth-child(2) {
+  font-weight: bold;
+  font-size: 20px;
+  margin: 10px 0;
+}
+
+.leftBox > div:nth-child(3),
+.rightBox > div:nth-child(3) {
+  text-align: center;
+}
+
+.fChoose,
+.sChoose {
+  width: 300px;
+  height: 250px;
+  cursor: pointer;
+}
+
+.fChoose > img,
+.sChoose > img {
+  width: 100%;
+  height: 100%;
+  object-fit: cover;
+}
+
+.checkFooter {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: nowrap;
+  align-items: center;
+  justify-content: flex-end;
+}
+.checkFooter > div {
+  min-width: 100px;
+  width: 100px;
+  text-align: center;
+  border-radius: 5px;
+  background: #ffffff;
+  color: #3681fc;
+  border: 1px solid #3681fc;
+  height: 35px;
+  line-height: 35px;
+  margin-right: 10px;
+  font-size: 12px;
+  cursor: pointer;
+}
+.checkFooter > div:first-child {
+  background: #f0f2f5 !important;
+  color: #000 !important;
+}
+
+.goButton {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: nowrap;
+  align-items: center;
+  position: absolute;
+  bottom: -70px;
+  width: 100px;
+  text-align: center;
+  background: #3681fc;
+  color: #fff;
+  height: 35px;
+  line-height: 35px;
+  justify-content: center;
+  border-radius: 5px;
+  cursor: pointer;
+}
+
+.right {
+  width: 20px;
+  margin-left: 5px;
+  line-height: 15px;
+}
+
+.right > img {
+  width: 100%;
+  height: 100%;
+}
+</style>

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 637 - 218
src/components/pages/addCourse.vue


Niektoré súbory nie sú zobrazené, pretože je v týchto rozdielových dátach zmenené mnoho súborov