|
@@ -0,0 +1,1009 @@
|
|
|
|
+<template>
|
|
|
|
+ <div class="o_box" ref="obox">
|
|
|
|
+ <div class="o_top">
|
|
|
|
+
|
|
|
|
+ </div>
|
|
|
|
+ <div class="o_content">
|
|
|
|
+ <div class="type_box" :style="{ width: oWidth }" v-if="cjson.type !== 'createRole'">
|
|
|
|
+ {{ getType(cjson) }}
|
|
|
|
+ </div>
|
|
|
|
+ <div class="word_box" v-if="cjson.type == 'word' || cjson.type == 'QA'" ref="wb">
|
|
|
|
+ <div class="word_bbox" :style="{ maxHeight: oheight }">
|
|
|
|
+ <img class="word_img" :src="cjson.img" alt="" v-if="cjson.img" @click="previewImg(cjson.img)">
|
|
|
|
+ <div class="word_content" v-html="cjson.content">
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="sentence_box" v-if="cjson.type == 'sentence'" ref="wb">
|
|
|
|
+ <span v-html="cjson.content"></span>
|
|
|
|
+ <div v-if="cjson.img" class="sentence_div">
|
|
|
|
+ <img :src="cjson.img" alt="" @click="previewImg(cjson.img)">
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="word_box" v-if="cjson.type == 'theme'" ref="wb" style="max-height: calc(100% - 95px);">
|
|
|
|
+ <div class="word_bbox" :style="{ maxHeight: oheight }">
|
|
|
|
+ <div class="word_content" v-html="cjson.content"></div>
|
|
|
|
+ <div class="word_content2" v-html="cjson.content2" v-if="cjson.content2"></div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="tips_box" v-if="cjson.type == 'theme' && !isRecord && !LuAudioUrl">提示:准备完成后,点击话筒开始录音</div>
|
|
|
|
+ <div class="time_box" v-if="cjson.type == 'theme' && isRecord">
|
|
|
|
+ <span>倒计时</span>
|
|
|
|
+ <span>{{ Times.min }}:{{ Times.secode }}</span>
|
|
|
|
+ </div>
|
|
|
|
+ <testRole v-if="cjson.type == 'createRole'" :checkJson="answerArray"></testRole>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="o_bottom" v-loading="isloading">
|
|
|
|
+ <div class="star_box" v-if="LuAudioUrl && star > 0">
|
|
|
|
+ <div class="star" v-for="index2 in 5" :key="'star' + index2" :class="{ starA: star >= (index2) }">
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <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 class="audio_index" v-if="!isRecord">
|
|
|
|
+ <div class="audio_index_last" :class="{ disabled: checkType == 0 }" @click="checkIndex('-1')">
|
|
|
|
+ <img src="../../../assets/icon/englishVoice/coin.png" alt="">
|
|
|
|
+ </div>
|
|
|
|
+ <div class="audio_index_content">
|
|
|
|
+ <span>{{ checkType + 1 }}</span>
|
|
|
|
+ <span>/</span>
|
|
|
|
+ <span>{{ checkJson.length }}</span>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="audio_index_next" :class="{ disabled: checkType == (checkJson.length - 1) }"
|
|
|
|
+ @click="checkIndex('1')">
|
|
|
|
+ <img src="../../../assets/icon/englishVoice/coin.png" alt="">
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div v-else class="audio_ing">
|
|
|
|
+ <span>正在录音...</span>
|
|
|
|
+ </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>
|
|
|
|
+ </div>
|
|
|
|
+</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 testRole from "./testRole.vue";
|
|
|
|
+export default {
|
|
|
|
+ components: {
|
|
|
|
+ testRole,
|
|
|
|
+ },
|
|
|
|
+ props: {
|
|
|
|
+ checkJson: {
|
|
|
|
+ type: Array,
|
|
|
|
+ },
|
|
|
|
+ checkType: {
|
|
|
|
+ type: Number,
|
|
|
|
+ },
|
|
|
|
+ work: {
|
|
|
|
+ type: Array
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ data() {
|
|
|
|
+ return {
|
|
|
|
+ cjson: {},
|
|
|
|
+ LuAudioUrl: "",
|
|
|
|
+ isRecord: false,
|
|
|
|
+ isPlayerRecord: false,
|
|
|
|
+ isloading: false,
|
|
|
|
+ oheight: 'auto',
|
|
|
|
+ oWidth: '500px',
|
|
|
|
+ calcTimer: null,
|
|
|
|
+ totalSeconds: 0,
|
|
|
|
+ answerArray: [],
|
|
|
|
+ id: this.guid(),
|
|
|
|
+ star: 0
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ computed: {
|
|
|
|
+ // oheight: function() {
|
|
|
|
+ // // 获取父元素
|
|
|
|
+ // var parentElement = this.$refs['wb'];
|
|
|
|
+
|
|
|
|
+ // // 计算父元素的高度
|
|
|
|
+ // var parentHeight = parentElement.offsetHeight;
|
|
|
|
+ // return parentHeight + 'px'
|
|
|
|
+ // }
|
|
|
|
+ getType() {
|
|
|
|
+ return function (json) {
|
|
|
|
+ if (json.type == 'word') {
|
|
|
|
+ return '单词/词组'
|
|
|
|
+ } else if (json.type == 'QA') {
|
|
|
|
+ return '问答题目'
|
|
|
|
+ } else if (json.type == 'sentence') {
|
|
|
|
+ return '句子/短文'
|
|
|
|
+ } else if (json.type == 'theme') {
|
|
|
|
+ return '主题陈述'
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ },
|
|
|
|
+ Times() {
|
|
|
|
+ let min = this.totalSeconds ? Math.floor(this.totalSeconds / 60) : 0
|
|
|
|
+ let secode = this.totalSeconds ? this.totalSeconds % 60 : 0
|
|
|
|
+ let time = {
|
|
|
|
+ min: min >= 10 ? min : '0' + min,
|
|
|
|
+ secode: secode >= 10 ? secode : '0' + secode
|
|
|
|
+ }
|
|
|
|
+ return time;
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+ watch: {
|
|
|
|
+ checkType: {
|
|
|
|
+ handler: function (newVal, oldVal) {
|
|
|
|
+ this.isloading = false
|
|
|
|
+ this.cjson = JSON.parse(JSON.stringify(this.checkJson[newVal]));
|
|
|
|
+ this.LuAudioUrl = ''
|
|
|
|
+ if (typeof this.work[newVal] == 'string') {
|
|
|
|
+ this.LuAudioUrl = this.work[newVal] ? JSON.parse(JSON.stringify(this.work[newVal])) : ''
|
|
|
|
+ } else if (typeof this.work[newVal] == 'object' && this.cjson.type != 'createRole') {
|
|
|
|
+ this.LuAudioUrl = this.work[newVal].audio ? JSON.parse(JSON.stringify(this.work[newVal].audio)) : ''
|
|
|
|
+ } else if (typeof this.work[newVal] == 'object' && this.cjson.type == 'createRole') {
|
|
|
|
+ var a = Array.isArray(this.work[newVal])
|
|
|
|
+ if (a) {
|
|
|
|
+ this.answerArray = JSON.parse(JSON.stringify(this.work[newVal]))
|
|
|
|
+ } else {
|
|
|
|
+ this.answerArray = []
|
|
|
|
+ this.answerArray.push(
|
|
|
|
+ {
|
|
|
|
+ isY: false,
|
|
|
|
+ content: this.cjson.content3,
|
|
|
|
+ name: this.cjson.content,
|
|
|
|
+ img: this.cjson.img
|
|
|
|
+ }
|
|
|
|
+ )
|
|
|
|
+ }
|
|
|
|
+ this.$emit('setWork', this.answerArray, this.checkType)
|
|
|
|
+ }
|
|
|
|
+ if (!this.work[newVal] && this.cjson.type == 'createRole') {
|
|
|
|
+ var a = Array.isArray(this.work[newVal])
|
|
|
|
+ if (a) {
|
|
|
|
+ this.answerArray = JSON.parse(JSON.stringify(this.work[newVal]))
|
|
|
|
+ } else {
|
|
|
|
+ this.answerArray = []
|
|
|
|
+ this.answerArray.push(
|
|
|
|
+ {
|
|
|
|
+ isY: false,
|
|
|
|
+ content: this.cjson.content3,
|
|
|
|
+ name: this.cjson.content,
|
|
|
|
+ img: this.cjson.img
|
|
|
|
+ }
|
|
|
|
+ )
|
|
|
|
+ }
|
|
|
|
+ this.$emit('setWork', this.answerArray, this.checkType)
|
|
|
|
+ }
|
|
|
|
+ this.star = this.work[newVal] ? (this.work[newVal].score ? JSON.parse(JSON.stringify(this.work[newVal].score)) : 0) : 0
|
|
|
|
+ this.oheight = 'auto'
|
|
|
|
+ this.oWidth = '500px'
|
|
|
|
+ const images = this.$refs['obox'].querySelectorAll('img');
|
|
|
|
+ let loadedCount = 0;
|
|
|
|
+
|
|
|
|
+ // if(images.length){
|
|
|
|
+ // images.forEach((image) => {
|
|
|
|
+ // image.addEventListener('load', () => {
|
|
|
|
+ // loadedCount++;
|
|
|
|
+
|
|
|
|
+ // if (loadedCount === images.length) {
|
|
|
|
+ // this.calculateParentHeight()
|
|
|
|
+ // }
|
|
|
|
+ // });
|
|
|
|
+ // });
|
|
|
|
+ // }else{
|
|
|
|
+ if (this.cjson.type != "createRole") {
|
|
|
|
+ this.calculateParentHeight()
|
|
|
|
+ }
|
|
|
|
+ if (this.cjson.type == "createRole") {
|
|
|
|
+ this.createRole(this.cjson.content2, this.cjson.content)
|
|
|
|
+ }
|
|
|
|
+ // }
|
|
|
|
+
|
|
|
|
+ },
|
|
|
|
+ deep: true,
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+ methods: {
|
|
|
|
+ previewImg(url) {
|
|
|
|
+ this.$hevueImgPreview(url);
|
|
|
|
+ },
|
|
|
|
+ restart() {
|
|
|
|
+ let _this = this
|
|
|
|
+ _this.$confirm("确定重新录音么?", "提示", {
|
|
|
|
+ confirmButtonText: "确定",
|
|
|
|
+ cancelButtonText: "取消",
|
|
|
|
+ type: "warning",
|
|
|
|
+ })
|
|
|
|
+ .then(() => {
|
|
|
|
+ _this.LuAudioUrl = ""
|
|
|
|
+ setTimeout(() => {
|
|
|
|
+ _this.startRecorder()
|
|
|
|
+ }, 500);
|
|
|
|
+ })
|
|
|
|
+ .catch(() => { });
|
|
|
|
+ },
|
|
|
|
+ checkIndex(type) {
|
|
|
|
+ if (type == '1') {
|
|
|
|
+ if (this.checkType == (this.checkJson.length - 1)) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ this.$emit('setType', this.checkType + 1)
|
|
|
|
+ } else {
|
|
|
|
+ if (this.checkType == 0) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ this.$emit('setType', this.checkType - 1)
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ // 开始录音
|
|
|
|
+ startRecorder() {
|
|
|
|
+ let _this = this;
|
|
|
|
+ if (!_this.isRecord) {
|
|
|
|
+ recorder.destroy(); // 销毁录音
|
|
|
|
+ _this.isRecord = true;
|
|
|
|
+ if (this.cjson.type == 'theme') {
|
|
|
|
+ this.setSecodes()
|
|
|
|
+ }
|
|
|
|
+ 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()
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ // 录音播放
|
|
|
|
+ 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 = 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
|
|
|
|
+ let _result = ``;
|
|
|
|
+ iiframe.contentWindow.onRecognizedResult = function (e) {
|
|
|
|
+ console.log('onRecognizedResult', e);
|
|
|
|
+ let privText = e.privText
|
|
|
|
+ _result+=privText;
|
|
|
|
+
|
|
|
|
+ // _this.beforeUpload1(audioFile, 3, privText);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ iiframe.contentWindow.onSessionStopped = function(e){
|
|
|
|
+ console.log("转译完成")
|
|
|
|
+ console.log(e);
|
|
|
|
+ _this.beforeUpload1(audioFile, 3, _result);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ iiframe.contentWindow.doContinuousPronunciationAssessment('', { files: [audioFile] })
|
|
|
|
+ } else if (this.cjson.type == 'createRole') {
|
|
|
|
+ // this.isloading = true
|
|
|
|
+ // this.beforeUpload1(audioFile, 3);
|
|
|
|
+ this.isloading = true
|
|
|
|
+ let _this = this
|
|
|
|
+ let _result = ``;
|
|
|
|
+ iiframe.contentWindow.onRecognizedResult = function (e) {
|
|
|
|
+ console.log('onRecognizedResult', e);
|
|
|
|
+ let privText = e.privText
|
|
|
|
+ _result+=privText;
|
|
|
|
+ // _this.beforeUpload1(audioFile, 3, privText);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ iiframe.contentWindow.onSessionStopped = function(e){
|
|
|
|
+ console.log("转译完成")
|
|
|
|
+ console.log(e);
|
|
|
|
+ _this.beforeUpload1(audioFile, 3, _result);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ iiframe.contentWindow.doContinuousPronunciationAssessment('', { files: [audioFile] })
|
|
|
|
+ } else {
|
|
|
|
+ this.isloading = true
|
|
|
|
+ let _this = this
|
|
|
|
+ let _result = ``;
|
|
|
|
+ let _star = ``;
|
|
|
|
+ iiframe.contentWindow.onRecognizedResult = function (e) {
|
|
|
|
+ console.log('onRecognizedResult', e);
|
|
|
|
+ let privText = e.privText
|
|
|
|
+ _result +=privText;
|
|
|
|
+ _star = JSON.parse(e.privJson).NBest[0].PronunciationAssessment
|
|
|
|
+ console.log(_star)
|
|
|
|
+ // console.log('star', star)
|
|
|
|
+ // e.privText
|
|
|
|
+ // JSON.parse(e.privJson).NBest[0].PronunciationAssessment
|
|
|
|
+
|
|
|
|
+ // _this.beforeUpload1(audioFile, 3, privText, star);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ iiframe.contentWindow.onSessionStopped = function(e){
|
|
|
|
+ console.log("转译完成")
|
|
|
|
+ console.log(e);
|
|
|
|
+ _this.beforeUpload1(audioFile, 3, _result, _star);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ iiframe.contentWindow.doContinuousPronunciationAssessment(this.cjson.content, { files: [audioFile] })
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 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/wav" });
|
|
|
|
+ },
|
|
|
|
+ dataURLtoAudio(blob, filename) {
|
|
|
|
+ return new File([blob], filename, { type: "audio/wav" });
|
|
|
|
+ },
|
|
|
|
+ beforeUpload1(event, type, text, star) {
|
|
|
|
+ var file;
|
|
|
|
+ if (type == 3) {
|
|
|
|
+ file = event;
|
|
|
|
+ } else {
|
|
|
|
+ file = event.target.files[0];
|
|
|
|
+ }
|
|
|
|
+ var credentials = {
|
|
|
|
+ accessKeyId: "AKIATLPEDU37QV5CHLMH",
|
|
|
|
+ secretAccessKey: "Q2SQw37HfolS7yeaR1Ndpy9Jl4E2YZKUuuy2muZR",
|
|
|
|
+ }; //秘钥形式的登录上传
|
|
|
|
+ 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) {
|
|
|
|
+ if (_this.cjson.type != 'createRole') {
|
|
|
|
+ _this.isloading = false
|
|
|
|
+ }
|
|
|
|
+ // _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) {
|
|
|
|
+ if (_this.cjson.type == 'createRole') {
|
|
|
|
+ _this.answerArray.push(
|
|
|
|
+ {
|
|
|
|
+ isY: true,
|
|
|
|
+ content: text,
|
|
|
|
+ voice: data.Location,
|
|
|
|
+ name: '',
|
|
|
|
+ img: ''
|
|
|
|
+ }
|
|
|
|
+ )
|
|
|
|
+ _this.answerCode(text)
|
|
|
|
+ } else {
|
|
|
|
+ _this.LuAudioUrl = data.Location;
|
|
|
|
+ _this.$emit('setWork', _this.LuAudioUrl, _this.checkType, text, star)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ console.log(data.Location);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ calculateParentHeight() {
|
|
|
|
+ this.$nextTick(() => {
|
|
|
|
+ setTimeout(() => {
|
|
|
|
+ // 获取父元素
|
|
|
|
+ var parentElement = this.$refs['wb'];
|
|
|
|
+
|
|
|
|
+ // 计算父元素的高度
|
|
|
|
+ // var parentHeight = parentElement.offsetHeight + 1;
|
|
|
|
+ var parentWidth = parentElement.offsetWidth;
|
|
|
|
+ // this.oheight = parentHeight + 'px'
|
|
|
|
+ this.oWidth = parentWidth + 'px'
|
|
|
|
+ }, 50);
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ setSecodes() {
|
|
|
|
+ this.totalSeconds = this.checkJson[this.checkType].oTime * 60
|
|
|
|
+ // this.totalSeconds = 10
|
|
|
|
+ this.calcTimer = setInterval(() => {
|
|
|
|
+ if (this.totalSeconds > 0) {
|
|
|
|
+ this.totalSeconds--;
|
|
|
|
+ } else {
|
|
|
|
+ clearInterval(this.calcTimer);
|
|
|
|
+ this.calcTimer = null
|
|
|
|
+ this.startRecorder()
|
|
|
|
+ console.log("倒计时结束"); // 输出日志
|
|
|
|
+ }
|
|
|
|
+ }, 1000);
|
|
|
|
+ },
|
|
|
|
+ answerCode(msg) {
|
|
|
|
+ var _this = this;
|
|
|
|
+ if (msg) {
|
|
|
|
+ _this.ajax.post('https://gpt4.cocorobo.cn/assistants_completion_response', {
|
|
|
|
+ uid: _this.id,
|
|
|
|
+ message: msg,
|
|
|
|
+ }).then(function (response) {
|
|
|
|
+ console.log(response);
|
|
|
|
+ _this.answerArray.push(
|
|
|
|
+ {
|
|
|
|
+ isY: false,
|
|
|
|
+ content: response.data.FunctionResponse,
|
|
|
|
+ name: _this.answerArray[0].name,
|
|
|
|
+ img: _this.answerArray[0].img
|
|
|
|
+ }
|
|
|
|
+ )
|
|
|
|
+ console.log(_this.answerArray);
|
|
|
|
+ _this.$forceUpdate()
|
|
|
|
+ _this.isloading = false
|
|
|
|
+ _this.$emit('setWork', _this.answerArray, _this.checkType)
|
|
|
|
+ }).catch(function (error) {
|
|
|
|
+ _this.isloading = false
|
|
|
|
+ console.log(error);
|
|
|
|
+ });
|
|
|
|
+ } else {
|
|
|
|
+ _this.answerArray.push(
|
|
|
|
+ {
|
|
|
|
+ isY: false,
|
|
|
|
+ content: "抱歉,您刚刚没有成功录入内容,请再说一遍!",
|
|
|
|
+ name: _this.answerArray[0].name,
|
|
|
|
+ img: _this.answerArray[0].img
|
|
|
|
+ }
|
|
|
|
+ )
|
|
|
|
+ _this.isloading = false
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ 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.id,
|
|
|
|
+ instructions: content,
|
|
|
|
+ assistantName: name
|
|
|
|
+ }).then(function (response) {
|
|
|
|
+ console.log(response);
|
|
|
|
+ }).catch(function (error) {
|
|
|
|
+ console.log(error);
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ beforeDestroy() {
|
|
|
|
+ if (!this.isRecord) {
|
|
|
|
+ } else {
|
|
|
|
+ if (this.calcTimer) {
|
|
|
|
+ clearInterval(this.calcTimer)
|
|
|
|
+ this.calcTimer = null;
|
|
|
|
+ }
|
|
|
|
+ recorder.stop(); // 结束录音
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ mounted() {
|
|
|
|
+
|
|
|
|
+ this.cjson = JSON.parse(JSON.stringify(this.checkJson[this.checkType]));
|
|
|
|
+ this.LuAudioUrl = ''
|
|
|
|
+ if (typeof this.work[this.checkType] == 'string') {
|
|
|
|
+ this.LuAudioUrl = this.work[this.checkType] ? JSON.parse(JSON.stringify(this.work[this.checkType])) : ''
|
|
|
|
+ } else if (typeof this.work[this.checkType] == 'object' && this.cjson.type != 'createRole') {
|
|
|
|
+ this.LuAudioUrl = this.work[this.checkType].audio ? JSON.parse(JSON.stringify(this.work[this.checkType].audio)) : ''
|
|
|
|
+ } else if (typeof this.work[this.checkType] == 'object' && this.cjson.type == 'createRole') {
|
|
|
|
+ var a = Array.isArray(this.work[this.checkType])
|
|
|
|
+ if (a) {
|
|
|
|
+ this.answerArray = JSON.parse(JSON.stringify(this.work[this.checkType]))
|
|
|
|
+ } else {
|
|
|
|
+ this.answerArray = []
|
|
|
|
+ this.answerArray.push(
|
|
|
|
+ {
|
|
|
|
+ isY: false,
|
|
|
|
+ content: this.cjson.content3,
|
|
|
|
+ name: this.cjson.content,
|
|
|
|
+ img: this.cjson.img
|
|
|
|
+ }
|
|
|
|
+ )
|
|
|
|
+ }
|
|
|
|
+ this.$emit('setWork', this.answerArray, this.checkType)
|
|
|
|
+ }
|
|
|
|
+ if (!this.work[this.checkType] && this.cjson.type == 'createRole') {
|
|
|
|
+ var a = Array.isArray(this.work[this.checkType])
|
|
|
|
+ if (a) {
|
|
|
|
+ this.answerArray = JSON.parse(JSON.stringify(this.work[this.checkType]))
|
|
|
|
+ } else {
|
|
|
|
+ this.answerArray = []
|
|
|
|
+ this.answerArray.push(
|
|
|
|
+ {
|
|
|
|
+ isY: false,
|
|
|
|
+ content: this.cjson.content3,
|
|
|
|
+ name: this.cjson.content,
|
|
|
|
+ img: this.cjson.img
|
|
|
|
+ }
|
|
|
|
+ )
|
|
|
|
+ }
|
|
|
|
+ this.$emit('setWork', this.answerArray, this.checkType)
|
|
|
|
+ }
|
|
|
|
+ this.star = this.work[this.checkType] ? (this.work[this.checkType].score ? JSON.parse(JSON.stringify(this.work[this.checkType].score)) : 0) : 0
|
|
|
|
+
|
|
|
|
+ if (this.cjson.type != "createRole") {
|
|
|
|
+ this.calculateParentHeight()
|
|
|
|
+ }
|
|
|
|
+ if (this.cjson.type == "createRole") {
|
|
|
|
+ this.createRole(this.cjson.content2, this.cjson.content)
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+}
|
|
|
|
+</script>
|
|
|
|
+
|
|
|
|
+<style scoped>
|
|
|
|
+.o_box {
|
|
|
|
+ width: 100%;
|
|
|
|
+ height: 100%;
|
|
|
|
+ background-image: url('../../../assets/icon/env_background.png');
|
|
|
|
+ background-size: cover;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.o_top {
|
|
|
|
+ height: 65px;
|
|
|
|
+ position: absolute;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.o_content {
|
|
|
|
+ height: calc(100% - 210px);
|
|
|
|
+ display: flex;
|
|
|
|
+ align-items: center;
|
|
|
|
+ justify-content: center;
|
|
|
|
+ overflow: hidden;
|
|
|
|
+ flex-direction: column;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.o_bottom {
|
|
|
|
+ height: 210px;
|
|
|
|
+ display: flex;
|
|
|
|
+ flex-direction: column;
|
|
|
|
+ align-items: center;
|
|
|
|
+ justify-content: center;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.word_box {
|
|
|
|
+ min-width: 500px;
|
|
|
|
+ max-width: 70%;
|
|
|
|
+ background: #fff;
|
|
|
|
+ border-radius: 10px;
|
|
|
|
+ position: relative;
|
|
|
|
+ /* max-height: calc(100% - 40px); */
|
|
|
|
+ max-height: calc(100% - 70px);
|
|
|
|
+ /* overflow: auto; */
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.tips_box {
|
|
|
|
+ margin-top: 30px;
|
|
|
|
+ color: #727272;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.word_box>.word_bbox {
|
|
|
|
+ width: 100%;
|
|
|
|
+ position: relative;
|
|
|
|
+ z-index: 999;
|
|
|
|
+ max-height: 100%;
|
|
|
|
+ overflow: auto;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.sentence_box {
|
|
|
|
+ background: #e0e0e04d;
|
|
|
|
+ min-width: 500px;
|
|
|
|
+ max-width: 70%;
|
|
|
|
+ border-radius: 15px;
|
|
|
|
+ /* max-height: 100%; */
|
|
|
|
+ overflow: auto;
|
|
|
|
+ padding: 15px;
|
|
|
|
+ font-size: 16px;
|
|
|
|
+ color: #000;
|
|
|
|
+ line-height: 20px;
|
|
|
|
+ word-break: break-word;
|
|
|
|
+ white-space: pre-line;
|
|
|
|
+ max-height: calc(100% - 80px);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.word_box::before {
|
|
|
|
+ content: '';
|
|
|
|
+ position: absolute;
|
|
|
|
+ width: 100%;
|
|
|
|
+ height: 100%;
|
|
|
|
+ display: block;
|
|
|
|
+ box-shadow: 0 0 4px 4px #1d39830d;
|
|
|
|
+ border-radius: 10px;
|
|
|
|
+ z-index: 2;
|
|
|
|
+ background: #fff;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.word_box::after {
|
|
|
|
+ content: '';
|
|
|
|
+ position: absolute;
|
|
|
|
+ width: 100%;
|
|
|
|
+ height: 100%;
|
|
|
|
+ background: #fff;
|
|
|
|
+ display: block;
|
|
|
|
+ box-shadow: 0 0 4px 4px #1d39830d;
|
|
|
|
+ border-radius: 10px;
|
|
|
|
+ z-index: 1;
|
|
|
|
+ top: 15px;
|
|
|
|
+ left: 15px;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.word_box>.word_bbox>.word_img {
|
|
|
|
+ width: calc(100% - 30px);
|
|
|
|
+ max-height: 300px;
|
|
|
|
+ z-index: 999;
|
|
|
|
+ position: relative;
|
|
|
|
+ margin: 15px auto;
|
|
|
|
+ display: block;
|
|
|
|
+ border-radius: 10px;
|
|
|
|
+ cursor: pointer;
|
|
|
|
+ object-fit: contain;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+.word_box>.word_bbox>.word_content {
|
|
|
|
+ position: relative;
|
|
|
|
+ z-index: 999;
|
|
|
|
+ text-align: center;
|
|
|
|
+ font-size: 36px;
|
|
|
|
+ margin: 15px;
|
|
|
|
+ font-weight: bold;
|
|
|
|
+ color: #000;
|
|
|
|
+ width: calc(100% - 30px);
|
|
|
|
+ word-break: break-word;
|
|
|
|
+ white-space: pre-line;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.word_box>.word_bbox>.word_content2 {
|
|
|
|
+ position: relative;
|
|
|
|
+ z-index: 999;
|
|
|
|
+ text-align: left;
|
|
|
|
+ font-size: 16px;
|
|
|
|
+ margin: 15px;
|
|
|
|
+ color: #727272;
|
|
|
|
+ width: calc(100% - 30px);
|
|
|
|
+ word-break: break-word;
|
|
|
|
+ white-space: pre-line;
|
|
|
|
+ /* margin-top: 10px; */
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+.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;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.o_bottom .audio_index {
|
|
|
|
+ display: flex;
|
|
|
|
+ align-items: center;
|
|
|
|
+ justify-content: center;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+.audio_index_last,
|
|
|
|
+.audio_index_next {
|
|
|
|
+ height: 40px;
|
|
|
|
+ width: 40px;
|
|
|
|
+ background: #3681fc;
|
|
|
|
+ border-radius: 50%;
|
|
|
|
+ display: flex;
|
|
|
|
+ align-items: center;
|
|
|
|
+ justify-content: center;
|
|
|
|
+ cursor: pointer;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.audio_index_last>img,
|
|
|
|
+.audio_index_next>img {
|
|
|
|
+ width: 15px;
|
|
|
|
+ height: auto;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.audio_index_last.disabled,
|
|
|
|
+.audio_index_next.disabled {
|
|
|
|
+ opacity: .6;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.audio_index_last>img {
|
|
|
|
+ transform: rotate(180deg);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.audio_index_last {
|
|
|
|
+ margin-right: 20px;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.audio_index_content {
|
|
|
|
+ color: #000;
|
|
|
|
+ font-size: 16px;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.audio_index_next {
|
|
|
|
+ margin-left: 20px;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+.audio_ing {
|
|
|
|
+ color: #EE3E3E;
|
|
|
|
+ margin-top: 25px;
|
|
|
|
+ font-size: 12px;
|
|
|
|
+ display: flex;
|
|
|
|
+ align-items: center;
|
|
|
|
+ justify-content: center;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.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;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.time_box {
|
|
|
|
+ display: flex;
|
|
|
|
+ flex-direction: column;
|
|
|
|
+ align-items: center;
|
|
|
|
+ justify-content: center;
|
|
|
|
+ margin-top: 25px;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.time_box>span:nth-child(1) {
|
|
|
|
+ color: #727272;
|
|
|
|
+ font-size: 16px;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.time_box>span:nth-child(2) {
|
|
|
|
+ /* margin-top: 10px; */
|
|
|
|
+ font-size: 32px;
|
|
|
|
+ color: #3581FC;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.type_box {
|
|
|
|
+ min-width: 500px;
|
|
|
|
+ width: 70%;
|
|
|
|
+ text-align: right;
|
|
|
|
+ color: #a5a5a5;
|
|
|
|
+ margin-bottom: 10px;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.sentence_div {
|
|
|
|
+ width: 100%;
|
|
|
|
+ overflow: hidden;
|
|
|
|
+ margin-top: 10px;
|
|
|
|
+ display: flex;
|
|
|
|
+ justify-content: flex-end;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.sentence_div>img {
|
|
|
|
+ width: 60px;
|
|
|
|
+ height: 60px;
|
|
|
|
+ object-fit: cover;
|
|
|
|
+ cursor: pointer;
|
|
|
|
+ border-radius: 4px
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.star_box {
|
|
|
|
+ display: flex;
|
|
|
|
+ align-items: center;
|
|
|
|
+ margin-bottom: 10px
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.star_box>.star {
|
|
|
|
+ width: 25px;
|
|
|
|
+ height: 25px;
|
|
|
|
+ display: block;
|
|
|
|
+ background-image: url('../../../assets/icon/englishVoice/star-no.png');
|
|
|
|
+ background-size: 100% 100%;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.star_box>.star+.star {
|
|
|
|
+ margin-left: 5px;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.star_box>.starA {
|
|
|
|
+ background-image: url('../../../assets/icon/englishVoice/star.png');
|
|
|
|
+}
|
|
|
|
+</style>
|