lsc 1 year ago
parent
commit
c050393235

+ 1 - 1
dist/index.html

@@ -25,7 +25,7 @@
       height: 100%;
       width: 100%;
       background: #e6eaf0;
-    }</style><link href=./static/css/app.c04754490d1b81c6c0757a2b67ec85b0.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=./static/js/manifest.3512a67a6213c2df4180.js></script><script type=text/javascript src=./static/js/vendor.b01159b52abeac4e6216.js></script><script type=text/javascript src=./static/js/app.dac999cd38590a3d21d3.js></script></body></html><script>function stopSafari() {
+    }</style><link href=./static/css/app.8b9d4587f0c1dfa52e9f1cf74160550d.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=./static/js/manifest.3512a67a6213c2df4180.js></script><script type=text/javascript src=./static/js/vendor.f4313154be2b51e16fef.js></script><script type=text/javascript src=./static/js/app.e904d93e9a46dc9d5b5a.js></script></body></html><script>function stopSafari() {
     //阻止safari浏览器双击放大功能
     let lastTouchEnd = 0  //更新手指弹起的时间
     document.documentElement.addEventListener("touchstart", function (event) {

File diff suppressed because it is too large
+ 0 - 0
dist/static/css/app.8b9d4587f0c1dfa52e9f1cf74160550d.css


File diff suppressed because it is too large
+ 0 - 0
dist/static/css/app.8b9d4587f0c1dfa52e9f1cf74160550d.css.map


File diff suppressed because it is too large
+ 0 - 0
dist/static/css/app.c04754490d1b81c6c0757a2b67ec85b0.css


File diff suppressed because it is too large
+ 0 - 0
dist/static/css/app.c04754490d1b81c6c0757a2b67ec85b0.css.map


File diff suppressed because it is too large
+ 0 - 0
dist/static/js/app.e904d93e9a46dc9d5b5a.js


File diff suppressed because it is too large
+ 0 - 0
dist/static/js/app.e904d93e9a46dc9d5b5a.js.map


File diff suppressed because it is too large
+ 0 - 0
dist/static/js/manifest.3512a67a6213c2df4180.js.map


File diff suppressed because it is too large
+ 0 - 0
dist/static/js/vendor.f4313154be2b51e16fef.js


File diff suppressed because it is too large
+ 0 - 0
dist/static/js/vendor.f4313154be2b51e16fef.js.map


+ 1 - 0
package.json

@@ -38,6 +38,7 @@
     "v-viewer": "^1.6.4",
     "vant": "^2.12.10",
     "vue": "^2.5.2",
+    "vue-audio-better": "^3.0.1",
     "vue-cookies": "^1.7.4",
     "vue-pdf": "^4.2.0",
     "vue-router": "^3.0.1",

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


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


+ 1 - 1
src/common/axios.config.js

@@ -21,7 +21,7 @@ axios.interceptors.request.use((config) => {
     // } else if (config.method === 'post') {
     //     config.data = qs.stringify(config.data)//序列化post 参数
     // }
-    if(config.url === 'https://gpt.cocorobo.cn/search_image' || config.url === 'https://gpt.cocorobo.cn/chat') {
+    if(config.url === 'https://gpt.cocorobo.cn/search_image' || config.url === 'https://gpt.cocorobo.cn/chat' || config.url === 'https://gpt4.cocorobo.cn/create_free_assistants' || config.url === 'https://gpt4.cocorobo.cn/assistants_completion_response') {
         config.data = config.data//序列化post 参数
     } else if (config.data && config.data[0].post == '1' && config.method === 'post') {
         config.data = 'mode=' + (Object.values(config.data[0]).join(','))//序列化post 参数

+ 1 - 0
src/common/tools.js

@@ -32,6 +32,7 @@ export const tools = {
     67: { name: "分子结构" },
     68: { name: "时间轴" },
     69: { name: "英语写作" },
+    70: { name: "英语口语" },
     25: { name: "目标管理" },
     26: { name: "课程设计" },
     62: { name: "交互视频" }

+ 21 - 12
src/components/pages/EnglishVoice/component/check.vue

@@ -63,20 +63,20 @@ export default {
                         }
                     ]
                 },
-                // {
-                //     name:'对话',
-                //     open: false,
-                //     children:[
-                //         {
-                //             icon:icon_check_addUser,
-                //             name:'创建角色',
-                //             type:'createRole'
-                //         }
-                //     ]
-                // },
+                {
+                    name:'对话',
+                    open: true,
+                    children:[
+                        {
+                            icon:icon_check_addUser,
+                            name:'创建角色',
+                            type:'createRole'
+                        }
+                    ]
+                },
                 {
                     name:'主题陈述',
-                    open: false,
+                    open: true,
                     children:[
                         {
                             icon:icon_check_theme,
@@ -126,6 +126,15 @@ export default {
                     rTime: 1,   //准备时间
                     oTime: 1,   //演讲时间
                 })
+            }else if(item.type == 'createRole'){
+                this.checkArray.push({
+                    type:'createRole',
+                    title:'', 
+                    img:'',
+                    content:'' ,  //人名
+                    content2:'',   //角色定义
+                    content3:'',   //角色问候
+                })
             }
             this.$forceUpdate()
             this.$emit('setJson', this.checkArray)

+ 292 - 0
src/components/pages/EnglishVoice/component/component/createRole.vue

@@ -0,0 +1,292 @@
+<template>
+    <div class="o_box">
+        <div class="o_content">
+            <span>角色名字</span>
+            <textarea v-autoHeight="38" rows="1" class="binfo_input binfo_textarea" cols v-model="checkJson.content"
+                placeholder="创建角色" @change="setJson"></textarea>
+        </div>
+        <div class="o_content">
+            <span>添加图片</span>
+            <div class="o_uploadbox_img" v-if="checkJson.img">
+                <div class="pic_mask">
+                    <span @click="checkImg(checkJson.img)">查看</span>
+                    <span @click="deleteImg()">删除</span>
+                </div>
+                <img :src="checkJson.img" alt="">
+            </div>
+            <div class="o_uploadbox" v-if="!checkJson.img" @click="getImg()">智能获取</div>
+            <div class="o_uploadbox" style="padding: 0 6px;" @click="addImg($event)" v-if="!checkJson.img">
+                <span class="icon_pic"></span>
+                <input type="file" accept="image/*" style="display: none" @change="beforeUpload($event)" />
+            </div>
+        </div>
+        <div class="o_content">
+            <span>角色定义</span>
+            <textarea v-autoHeight="38" rows="1" class="binfo_input binfo_textarea" cols v-model="checkJson.content2"
+                placeholder="请输入对改角色的定义" @change="setJson"></textarea>
+        </div>
+        <div class="o_content">
+            <span>角色问候</span>
+            <textarea v-autoHeight="38" rows="1" class="binfo_input binfo_textarea" cols v-model="checkJson.content3"
+                placeholder="请输入对改角色的问候话语" @change="setJson"></textarea>
+        </div>
+        <div class="o_content">
+            <span></span>
+            <button class="c_pub_button_add" @click="openTest">角色测试</button>
+        </div>
+        <div v-if="proVisible" class="mask">
+            <div class="progressBox">
+                <div class="lbox">
+                    <img src="../../../../../assets/loading.gif" />上传中,请稍后
+                </div>
+                <div style="margin-bottom: 10px">
+                    <span>{{
+                        isFinishSize
+                    }}M</span>
+                    /
+                    <span>{{
+                        isAllSize
+                    }}M</span>
+                </div>
+                <el-progress :text-inside="true" :stroke-width="20" :percentage="progress
+                    ? progress
+                    : 0
+                    " style="width: 80%"></el-progress>
+            </div>
+        </div>
+        <gpt-img :sysPicVisible.sync="sysPicVisible" :value="checkJson.content" @setImg="setImg"></gpt-img>
+    </div>
+</template>
+
+<script>
+import minxin from './minxins/minxin';
+export default {
+    mixins: [minxin],
+    props: {
+        cjson: {
+            type: Object,
+        },
+    },
+    data() {
+        return {
+            checkJson: {}
+        }
+    },
+    methods: {
+        setJson() {
+            this.$emit('setJson', this.checkJson)
+        },
+        setImg(url) {
+            this.checkJson.img = url
+            this.$emit('setJson', this.checkJson)
+        },
+        openTest(){
+            this.$emit('openTest', this.checkJson)
+        }
+    },
+    watch: {
+        cjson: {
+            handler: function (newVal, oldVal) {
+                this.checkJson = this.depthCopy(newVal);
+            },
+            deep: true,
+        },
+        imgUrl: {
+            handler: function (newVal, oldVal) {
+                this.checkJson.img = newVal
+                this.$forceUpdate()
+                this.$emit('setJson', this.checkJson)
+            },
+            deep: true,
+        },
+    },
+    mounted() {
+        this.checkJson = this.depthCopy(this.cjson);
+    }
+}
+</script>
+
+<style scoped>
+.o_box {
+    width: 100%;
+    box-sizing: border-box;
+    padding: 12px 16px 12px 48px;
+    background: #f5f6f7;
+    position: relative;
+}
+
+.binfo_input {
+    width: 100%;
+    margin: 0;
+    padding: 8px;
+    display: block;
+    min-width: 0;
+    outline: none;
+    box-sizing: border-box;
+    background: none;
+    border: none;
+    border-radius: 4px;
+    background: #fff;
+    font-size: 16px;
+    resize: none;
+    font-family: 'Microsoft YaHei';
+    min-height: 38px;
+    /* border: 1px solid #3682fc00; */
+    border: 1.5px solid #CAD1DC;
+}
+
+.binfo_textarea {
+    border: 1.5px solid #CAD1DC;
+    font-size: 14px;
+    resize: none;
+    /* background: #f6f6f6; */
+    font-family: 'Microsoft YaHei';
+}
+
+.binfo_input:focus-visible {
+    border: 1.5px solid #3681FC !important;
+}
+
+.o_content {
+    display: flex;
+    color: #000;
+    font-size: 14px;
+}
+
+.o_content+.o_content {
+    margin-top: 10px;
+}
+
+.o_content>span {
+    min-width: 57px;
+    margin-right: 12px;
+    line-height: 38px;
+}
+
+.o_uploadbox {
+    height: 32px;
+    padding: 0 8px;
+    background: #eee;
+    line-height: 32px;
+    margin-top: 3px;
+    font-size: 14px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    cursor: pointer;
+}
+
+.o_uploadbox+.o_uploadbox {
+    margin-left: 12px;
+}
+
+.icon_pic {
+    width: 20px;
+    height: 20px;
+    background-image: url('../../../../../assets/icon/englishVoice/icon_picture.png');
+    background-size: 100% 100%;
+    display: block;
+}
+
+.mask {
+    background-color: rgb(0 0 0 / 30%);
+    /* position: fixed; */
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    z-index: 90;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+}
+
+.progressBox {
+    width: 300px;
+    height: 150px;
+    background: #fff;
+    border-radius: 10px;
+    box-shadow: 0 0 6px 1px #bfbfbf;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    flex-direction: column;
+    position: relative;
+    color: #6c6c6c;
+}
+
+.progressBox>>>.el-progress-bar__outer {
+    background-color: #d1dfff !important;
+}
+
+.progressBox .lbox {
+    height: 50px;
+    font-size: 19px;
+    display: flex;
+    align-items: center;
+    color: #747474;
+}
+
+.progressBox .lbox img {
+    width: 40px;
+    margin-right: 20px;
+}
+
+.closeCss {
+    position: absolute;
+    top: 8px;
+    right: 8px;
+    cursor: pointer;
+    width: 20px;
+    height: 20px;
+}
+
+.closeCss>img {
+    width: 100%;
+    height: 100%;
+}
+
+
+.o_uploadbox_img {
+    width: 100px;
+    height: 100px;
+    border-radius: 5px;
+    position: relative;
+    overflow: hidden;
+}
+
+.o_uploadbox_img>img {
+    width: 100%;
+    height: 100%;
+    object-fit: cover;
+}
+
+.o_uploadbox_img:hover .pic_mask {
+    display: flex;
+}
+
+.pic_mask {
+    position: absolute;
+    width: 100%;
+    height: 100%;
+    background: rgba(0, 0, 0, .3);
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+    top: 0;
+    left: 0;
+    color: #458dff;
+    display: none;
+    border-radius: 5px;
+}
+
+.pic_mask>span {
+    cursor: pointer;
+    font-size: 14px;
+    color: #fff;
+}
+
+.pic_mask>span+span {
+    margin-top: 10px;
+}</style>

+ 4 - 0
src/components/pages/EnglishVoice/component/component/gptImg.vue

@@ -59,6 +59,10 @@ export default {
         },
         searchImage() {
             var _this = this;
+            if (_this.searchImageValue == "") {
+                _this.$message.error("请输入关键词");
+                return
+            }
             _this.imageList = []
             _this.imageloading = true
             _this.ajax.post('https://gpt.cocorobo.cn/search_image', {

+ 495 - 0
src/components/pages/EnglishVoice/component/component/testRole.vue

@@ -0,0 +1,495 @@
+<template>
+    <el-dialog title="对话测试" width="400px" :visible.sync="dataDialog" :append-to-body="true" :before-close="handleClose"
+        class="dialog_diy">
+        <div v-loading="isloading">
+            <div class="dialog_content">
+                <div class="dialog" v-for="(item, index) in answerArray" :key="index" :class="{ dialog_right: item.isY }">
+                    <div class="d_img">
+                        <img :src="item.img ? item.img : require('../../../../../assets/icon/englishVoice/icon_portal.png')"
+                            alt="">
+                    </div>
+                    <div class="d_content">
+                        <div class="d_name" v-if="item.name">{{ item.name }}</div>
+                        <div class="d_voice" v-if="item.voice">
+                            <mini-audio :audio-source="item.voice" class="audio_class"></mini-audio>
+                        </div>
+                        <div class="d_log" v-if="item.content">{{ item.content }}</div>
+                    </div>
+                </div>
+            </div>
+            <div class="dialog_answer">
+                <span v-if="isRecord">正在录音中,再次点击话筒停止录音...</span>
+                <img @click="startRecorder" src="../../../../../assets/icon/englishVoice/icon_voice.png" alt="">
+            </div>
+            <iframe allow="camera *; microphone *;display-capture;midi;encrypted-media;"
+                src="https://beta.cloud.cocorobo.cn/browser/public/index.html" ref="iiframe"></iframe>
+        </div>
+    </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---------------')
+};
+export default {
+    components: {
+    },
+    props: {
+        dataDialog: {
+            type: Boolean,
+            default: false
+        },
+        checkJson: {
+            type: Object,
+        }
+    },
+    data() {
+        return {
+            json: [],
+            answerArray: [],
+            isRecord: false,
+            isPlayerRecord: false,
+            isloading: false,
+        };
+    },
+    methods: {
+        handleClose(done) {
+            this.close();
+            done();
+        },
+        close() {
+            this.$emit("update:dataDialog", false);
+        },
+        close2() {
+            this.$emit("update:dataDialog", false);
+        },
+        confirm() {
+            this.close2();
+        },
+        setVoiceJson(val) {
+            let a = JSON.parse(JSON.stringify(val));
+            this.json = a;
+            this.answerArray = []
+            this.answerArray.push(
+                {
+                    isY: false,
+                    content: a.content3,
+                    name: a.content,
+                    img: a.img
+                }
+            )
+            // let iiframe = this.$refs['iiframe']
+            // .doPronunciationAssessmentOnceAsync()
+            // console.log(iiframe);
+            // this.answerArray.push(
+            //     {
+            //         isY: true,
+            //         content: a.content3,
+            //         name: a.content,
+            //     }
+            // )
+            this.createRole(a.content2, a.content)
+        },
+        answerCode(msg) {
+            var _this = this;
+            _this.ajax.post('https://gpt4.cocorobo.cn/assistants_completion_response', {
+                uid: _this.guid(),
+                message: msg,
+            }).then(function (response) {
+                console.log(response);
+                _this.answerArray.push(
+                    {
+                        isY: false,
+                        content: response.FunctionResponse,
+                        name: _this.answerArray[0].name,
+                        img: _this.answerArray[0].img
+                    }
+                )
+                _this.isloading = false
+            }).catch(function (error) {
+                _this.isloading = false
+                console.log(error);
+            });
+        },
+        // 开始录音
+        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}`);
+                    }
+                );
+
+            } else {
+                _this.isRecord = false;
+                recorder.stop(); // 结束录音
+                this.getMp3Data()
+            }
+        },
+
+        // 录音播放
+        playRecorder() {
+            if (!recorder.fileSize) {
+                return;
+            }
+            if (!this.isPlayerRecord) {
+                this.isPlayerRecord = true;
+                recorder.play();
+            } else {
+                this.isPlayerRecord = false;
+                recorder.stopPlay(); // 停止录音播放
+            }
+            recorder.onplayend = () => {
+                this.isPlayerRecord = false;
+                console.log("onplayend");
+            };
+        },
+
+        /**
+         * 文件格式转换 wav-map3
+         * */
+        getMp3Data() {
+            if (!recorder.fileSize) {
+                this.$message.error("请录音后在上传语音");
+                return;
+            }
+            const mp3Blob = this.convertToMp3(recorder.getWAV());
+            let audioFile = this.dataURLtoAudio(mp3Blob, "mp3");
+            console.log(audioFile);
+            let iiframe = this.$refs['iiframe']
+            iiframe.contentWindow.doPronunciationAssessmentOnceAsync('', { files: [audioFile] })
+            this.isloading = true
+            let _this = this
+            iiframe.contentWindow.onRecognizedResult = function (e) {
+                console.log('onRecognizedResult', e);
+                let privText = e.privText
+                // e.privText 
+                // JSON.parse(e.privJson).NBest[0].PronunciationAssessment
+
+                _this.beforeUpload1(audioFile, 3, privText);
+            }
+            // recorder.download(mp3Blob, "recorder", "mp3");
+        },
+        convertToMp3(wavDataView) {
+            // 获取wav头信息
+            const wav = lamejs.WavHeader.readHeader(wavDataView); // 此处其实可以不用去读wav头信息,毕竟有对应的config配置
+            const { channels, sampleRate } = wav;
+            const mp3enc = new lamejs.Mp3Encoder(channels, sampleRate, 128);
+            // 获取左右通道数据
+            const result = recorder.getChannelData();
+            const buffer = [];
+            const leftData =
+                result.left &&
+                new Int16Array(result.left.buffer, 0, result.left.byteLength / 2);
+            const rightData =
+                result.right &&
+                new Int16Array(result.right.buffer, 0, result.right.byteLength / 2);
+            const remaining = leftData.length + (rightData ? rightData.length : 0);
+            const maxSamples = 1152;
+            for (let i = 0; i < remaining; i += maxSamples) {
+                const left = leftData.subarray(i, i + maxSamples);
+                let right = null;
+                let mp3buf = null;
+                if (channels === 2) {
+                    right = rightData.subarray(i, i + maxSamples);
+                    mp3buf = mp3enc.encodeBuffer(left, right);
+                } else {
+                    mp3buf = mp3enc.encodeBuffer(left);
+                }
+                if (mp3buf.length > 0) {
+                    buffer.push(mp3buf);
+                }
+            }
+
+            const enc = mp3enc.flush();
+            if (enc.length > 0) {
+                buffer.push(enc);
+            }
+            return new Blob(buffer, { type: "audio/mp3" });
+        },
+        dataURLtoAudio(blob, filename) {
+            return new File([blob], filename, { type: "audio/mp3" });
+        },
+        beforeUpload1(event, type, privText) {
+            var file;
+            if (type == 3) {
+                file = event;
+            } else {
+                file = event.target.files[0];
+            }
+            var credentials = {
+                accessKeyId: "AKIATLPEDU37QV5CHLMH",
+                secretAccessKey: "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",
+            }; //秘钥形式的登录上传
+            window.AWS.config.update(credentials);
+            window.AWS.config.region = "cn-northwest-1"; //设置区域
+
+            var bucket = new window.AWS.S3({ params: { Bucket: "ccrb" } }); //选择桶
+            var _this = this;
+
+            if (file) {
+                var params = {
+                    Key:
+                        file.name.split(".")[0] +
+                        new Date().getTime() +
+                        "." +
+                        file.name.split(".")[file.name.split(".").length - 1],
+                    ContentType: file.type,
+                    Body: file,
+                    "Access-Control-Allow-Credentials": "*",
+                    ACL: "public-read",
+                }; //key可以设置为桶的相抵路径,Body为文件, ACL最好要设置
+                var options = {
+                    partSize: 2048 * 1024 * 1024,
+                    queueSize: 2,
+                    leavePartsOnError: true,
+                };
+                bucket
+                    .upload(params, options)
+                    .on("httpUploadProgress", function (evt) {
+                        //这里可以写进度条
+                        // console.log("Uploaded : " + parseInt((evt.loaded * 80) / evt.total) + '%');
+                        // _this.progress = parseInt((evt.loaded * 80) / evt.total);
+                    })
+                    .send(function (err, data) {
+                        // _this.progress = 100;
+                        if (err) {
+                            // var a = _this.$refs.upload1.uploadFiles;
+                            // a.splice(a.length - 1, a.length);
+                            _this.$message.error("上传失败");
+                        } else {
+                            if (type == 3) {
+                                // _this.LuAudioUrl = data.Location;
+                                _this.answerArray.push(
+                                    {
+                                        isY: true,
+                                        content: privText,
+                                        voice: data.Location,
+                                        name: '',
+                                        img: ''
+                                    }
+                                )
+                                _this.answerCode(privText)
+                            }
+                            console.log(data.Location);
+                        }
+                    });
+            }
+        },
+        guid() {
+            var _num,
+                i,
+                _guid = "";
+            for (i = 0; i < 32; i++) {
+                _guid += Math.floor(Math.random() * 16).toString(16); //随机0  - 16 的数字 转变为16进制的字符串
+                _num = Math.floor((i - 7) / 4); //计算 (i-7)除4
+                if (_num > -1 && _num < 4 && i == 7 + 4 * _num) {
+                    //会使guid中间加 "-"   形式为xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+                    _guid += "-";
+                }
+            }
+            return _guid;
+        },
+        createRole(content, name) {
+            var _this = this;
+            _this.ajax.post('https://gpt4.cocorobo.cn/create_free_assistants', {
+                filename: [],
+                url: [],
+                uid: _this.guid(),
+                instructions: content,
+                assistantName: name
+            }).then(function (response) {
+                console.log(response);
+            }).catch(function (error) {
+                console.log(error);
+            });
+        }
+    },
+    watch: {
+        dataDialog: {
+            handler: function (newVal, oldVal) {
+                if (newVal) {
+                    this.setVoiceJson(this.checkJson);
+                }
+            },
+            deep: true
+        }
+    },
+    mounted() {
+        this.setVoiceJson(this.checkJson);
+    }
+};
+</script>
+    
+<style scoped>
+.dialog_diy>>>.el-dialog {
+    /* width: 100%; */
+    /* max-width: 1000px; */
+    /* height: 100%; */
+    /* margin: 0vh auto !important; */
+}
+
+.dialog_diy>>>.el-dialog__header {
+    background: #454545 !important;
+    padding: 15px;
+}
+
+.dialog_diy>>>.el-dialog__body {
+    /* height: calc(100% - 54px); */
+    box-sizing: border-box;
+    padding: 15px;
+}
+
+.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: #f0f4fa;
+    overflow: hidden;
+}
+
+
+.dialog_content {
+    height: 500px;
+    background: #fff;
+    width: 100%;
+    padding: 10px;
+    box-sizing: border-box;
+    border-radius: 4px;
+    overflow: auto;
+}
+
+.dialog_answer {
+    height: 45px;
+    background: #fff;
+    width: 100%;
+    padding: 10px;
+    box-sizing: border-box;
+    margin-top: 10px;
+    display: flex;
+    align-items: center;
+    border-radius: 4px;
+}
+
+.dialog_answer>img {
+    height: 100%;
+    margin-left: auto;
+    cursor: pointer;
+}
+
+
+.dialog {
+    display: flex;
+}
+
+.dialog+.dialog {
+    margin-top: 15px;
+}
+
+.dialog_right {
+    flex-direction: row-reverse;
+}
+
+.dialog>.d_img {
+    width: 35px;
+    height: 35px;
+    min-width: 35px;
+    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 {
+    width: 100%;
+}
+
+.dialog>.d_content>.d_name {
+    color: #7C7C7C;
+    font-size: 12px;
+    margin-bottom: 5px;
+}
+
+.dialog_right>.d_content>.d_name {
+    text-align: right;
+}
+
+.dialog>.d_content>.d_log {
+    color: #000;
+    font-size: 14px;
+    padding: 5px;
+    background: #d9e7fe;
+}
+
+.dialog>.d_content>.d_voice {
+    width: 100%;
+}
+
+.audio_class {
+    background: #3680fb !important;
+    margin: 0 !important;
+    width: 100% !important;
+    box-sizing: border-box !important;
+}
+
+.audio_b>>>.vueAudioBetter span:before {
+    color: #fff;
+}
+
+.audio_class>>>.slider .process {
+    background: #000;
+}
+
+.audio_b>>>.vueAudioBetter .iconfont:active {
+    position: unset !important;
+}
+</style>
+    

+ 23 - 4
src/components/pages/EnglishVoice/component/order.vue

@@ -10,9 +10,10 @@
           <span class="drag" v-if="editType == 2"></span>
           <span class="order" v-else>{{ index + 1 }}、</span>
           <span class="icon"
-            :class="{ icon_word: item.type == 'word', icon_sentence: item.type == 'sentence', icon_QA: item.type == 'QA', icon_theme: item.type == 'theme' }"></span>
+            :class="{ icon_word: item.type == 'word', icon_sentence: item.type == 'sentence', icon_QA: item.type == 'QA', icon_theme: item.type == 'theme', icon_createRole: item.type == 'createRole' }"></span>
           <span class="title">{{ getTitle(item) }}</span>
           <div class="edit_btn">
+            <button class="c_pub_button_add" @click.stop="openTest(item)" style="margin-right: 15px;" v-if="editType == 2 && item.type == 'createRole' && checkType != index">角色测试</button>
             <div class="pic" v-if="editType == 2 && item.img && checkType != index">
               <div class="pic_mask">
                 <span class="delete" @click.stop="deleteImg(index)"></span>
@@ -28,9 +29,11 @@
           <sentence :cjson="item" v-if="item.type == 'sentence'" @setJson="setJson"></sentence>
           <word :cjson="item" v-if="item.type == 'word'" @setJson="setJson"></word>
           <theme :cjson="item" v-if="item.type == 'theme'" @setJson="setJson"></theme>
+          <createRole :cjson="item" v-if="item.type == 'createRole'" @setJson="setJson" @openTest="openTest"></createRole>
         </div>
       </div>
     </div>
+    <testRole :dataDialog.sync="dataDialog" :checkJson="Json"></testRole>
   </div>
 </template>
 
@@ -40,13 +43,17 @@ import qa from './component/qa2.vue'
 import sentence from './component/sentence.vue'
 import word from './component/word.vue'
 import theme from './component/theme.vue'
+import createRole from './component/createRole.vue'
+import testRole from './component/testRole.vue'
 export default {
   mixins: [minxin],
   components: {
     qa,
     sentence,
     word,
-    theme
+    theme,
+    createRole,
+    testRole
   },
   props: {
     checkJson: {
@@ -62,7 +69,9 @@ export default {
   },
   data() {
     return {
-      checkArray: []
+      checkArray: [],
+      dataDialog: false,
+      Json: {}
     }
   },
   computed: {
@@ -91,7 +100,9 @@ export default {
           return '问题'
         } else if(item.type == 'theme' && !item.content){
           return '主题陈述'
-        }else{
+        } else if(item.type == 'createRole' && !item.content){
+          return '角色对话'
+        } else{
           return item.content
         }
       }
@@ -143,6 +154,10 @@ export default {
           this.$forceUpdate()
           this.$emit('setJson', this.checkArray)
         })
+    },
+    openTest(json){
+      this.dataDialog = true
+      this.Json = json
     }
   },
   mounted() {
@@ -249,6 +264,10 @@ export default {
   background-image: url('../../../../assets/icon/englishVoice/icon_check_theme.png');
 }
 
+.o_child_title>.icon.icon_createRole {
+  background-image: url('../../../../assets/icon/englishVoice/icon_check_addUser.png');
+}
+
 .o_child_title>.edit_btn {
   margin-left: auto;
   display: flex;

+ 2 - 1
src/main.js

@@ -20,11 +20,12 @@ import Clipboard from "clipboard";
 import hevueImgPreview from './components/tools/hevue-img-preview'
 import './assets/css/button.css'
 import './assets/css/dialog.css'
+import VueAudio from 'vue-audio-better'
 
 const echarts = require('echarts');
 
 //
-Vue.use(VideoPlayer).use(VueCookies).use(Viewer).use(hevueImgPreview, {
+Vue.use(VideoPlayer).use(VueAudio).use(VueCookies).use(Viewer).use(hevueImgPreview, {
     clickMaskCLose: true
 })
 Vue.config.productionTip = false

Some files were not shown because too many files changed in this diff