right.vue 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018
  1. <template>
  2. <div class="o_box" ref="obox">
  3. <div class="o_top">
  4. </div>
  5. <div class="o_content">
  6. <div class="type_box" :style="{ width: oWidth }" v-if="cjson.type !== 'createRole'">
  7. {{ getType(cjson) }}
  8. </div>
  9. <div class="word_box" v-if="cjson.type == 'word' || cjson.type == 'QA'" ref="wb">
  10. <div class="word_bbox" :style="{ maxHeight: oheight }">
  11. <img class="word_img" :src="cjson.img" alt="" v-if="cjson.img" @click="previewImg(cjson.img)">
  12. <div class="word_content" v-html="cjson.content">
  13. </div>
  14. </div>
  15. </div>
  16. <div class="sentence_box" v-if="cjson.type == 'sentence'" ref="wb">
  17. <span v-html="cjson.content"></span>
  18. <div v-if="cjson.img" class="sentence_div">
  19. <img :src="cjson.img" alt="" @click="previewImg(cjson.img)">
  20. </div>
  21. </div>
  22. <div class="word_box" v-if="cjson.type == 'theme'" ref="wb" style="max-height: calc(100% - 95px);">
  23. <div class="word_bbox" :style="{ maxHeight: oheight }">
  24. <div class="word_content" v-html="cjson.content"></div>
  25. <div class="word_content2" v-html="cjson.content2" v-if="cjson.content2"></div>
  26. </div>
  27. </div>
  28. <div class="tips_box" v-if="cjson.type == 'theme' && !isRecord && !LuAudioUrl">提示:准备完成后,点击话筒开始录音</div>
  29. <div class="time_box" v-if="cjson.type == 'theme' && isRecord">
  30. <span>倒计时</span>
  31. <span>{{ Times.min }}:{{ Times.secode }}</span>
  32. </div>
  33. <testRole v-if="cjson.type == 'createRole'" :checkJson="answerArray"></testRole>
  34. </div>
  35. <div class="o_bottom" v-loading="isloading">
  36. <div class="star_box" v-if="LuAudioUrl && star > 0">
  37. <div class="star" v-for="index2 in 5" :key="'star' + index2" :class="{ starA: star >= (index2) }">
  38. </div>
  39. </div>
  40. <div class="audio" v-if="!LuAudioUrl">
  41. <img v-if="!isRecord" src="../../../assets/icon/englishVoice/start_aduio.png" alt="" @click="startRecorder">
  42. <img v-else src="../../../assets/icon/englishVoice/stop_audio.png" alt="" @click="startRecorder">
  43. </div>
  44. <div class="audio_word" v-if="!LuAudioUrl">
  45. <span v-if="!isRecord">点击话筒开始录音</span>
  46. <span v-else>点击话筒结束录音</span>
  47. </div>
  48. <div v-if="LuAudioUrl" class="audio_b">
  49. <mini-audio :audio-source="LuAudioUrl" class="audio_class"></mini-audio>
  50. </div>
  51. <div v-if="LuAudioUrl" class="audio_rerecord" @click="restart()">
  52. <span>录音</span>
  53. </div>
  54. <div class="audio_index" v-if="!isRecord">
  55. <div class="audio_index_last" :class="{ disabled: checkType == 0 }" @click="checkIndex('-1')">
  56. <img src="../../../assets/icon/englishVoice/coin.png" alt="">
  57. </div>
  58. <div class="audio_index_content">
  59. <span>{{ checkType + 1 }}</span>
  60. <span>/</span>
  61. <span>{{ checkJson.length }}</span>
  62. </div>
  63. <div class="audio_index_next" :class="{ disabled: checkType == (checkJson.length - 1) }"
  64. @click="checkIndex('1')">
  65. <img src="../../../assets/icon/englishVoice/coin.png" alt="">
  66. </div>
  67. </div>
  68. <div v-else class="audio_ing">
  69. <span>正在录音...</span>
  70. </div>
  71. </div>
  72. <iframe allow="camera *; microphone *;display-capture;midi;encrypted-media;"
  73. :src="iframeSrc" ref="iiframe" v-show="false"></iframe>
  74. </div>
  75. </template>
  76. <script>
  77. import Recorder from "js-audio-recorder";
  78. const lamejs = require("lamejs");
  79. const recorder = new Recorder({
  80. sampleBits: 16, // 采样位数,支持 8 或 16,默认是16
  81. sampleRate: 48000, // 采样率,支持 11025、16000、22050、24000、44100、48000,根据浏览器默认值,我的chrome是48000
  82. numChannels: 1, // 声道,支持 1 或 2, 默认是1
  83. // compiling: false,(0.x版本中生效,1.x增加中) // 是否边录边转换,默认是false
  84. });
  85. // 绑定事件-打印的是当前录音数据
  86. recorder.onprogress = function (params) {
  87. // console.log('--------------START---------------')
  88. // console.log('录音时长(秒)', params.duration);
  89. // console.log('录音大小(字节)', params.fileSize);
  90. // console.log('录音音量百分比(%)', params.vol);
  91. // console.log('当前录音的总数据([DataView, DataView...])', params.data);
  92. // console.log('--------------END---------------')
  93. };
  94. import testRole from "./testRole.vue";
  95. export default {
  96. components: {
  97. testRole,
  98. },
  99. props: {
  100. checkJson: {
  101. type: Array,
  102. },
  103. checkType: {
  104. type: Number,
  105. },
  106. work: {
  107. type: Array
  108. }
  109. },
  110. data() {
  111. return {
  112. cjson: {},
  113. LuAudioUrl: "",
  114. isRecord: false,
  115. isPlayerRecord: false,
  116. isloading: false,
  117. oheight: 'auto',
  118. oWidth: '500px',
  119. calcTimer: null,
  120. totalSeconds: 0,
  121. answerArray: [],
  122. id: this.guid(),
  123. star: 0
  124. }
  125. },
  126. computed: {
  127. // oheight: function() {
  128. // // 获取父元素
  129. // var parentElement = this.$refs['wb'];
  130. // // 计算父元素的高度
  131. // var parentHeight = parentElement.offsetHeight;
  132. // return parentHeight + 'px'
  133. // }
  134. getType() {
  135. return function (json) {
  136. if (json.type == 'word') {
  137. return '单词/词组'
  138. } else if (json.type == 'QA') {
  139. return '问答题目'
  140. } else if (json.type == 'sentence') {
  141. return '句子/短文'
  142. } else if (json.type == 'theme') {
  143. return '主题陈述'
  144. }
  145. };
  146. },
  147. Times() {
  148. let min = this.totalSeconds ? Math.floor(this.totalSeconds / 60) : 0
  149. let secode = this.totalSeconds ? this.totalSeconds % 60 : 0
  150. let time = {
  151. min: min >= 10 ? min : '0' + min,
  152. secode: secode >= 10 ? secode : '0' + secode
  153. }
  154. return time;
  155. },
  156. iframeSrc() {
  157. if(this.$region == 'hk') {
  158. return `https://cloud.cocorobo.hk/browser/public/index.html`;
  159. } else if(this.$region == 'com') {
  160. return `https://cloud.cocorobo.com/browser/public/index.html`;
  161. } else {
  162. return `https://beta.cloud.cocorobo.cn/browser/public/index.html`;
  163. }
  164. },
  165. },
  166. watch: {
  167. checkType: {
  168. handler: function (newVal, oldVal) {
  169. this.isloading = false
  170. this.cjson = JSON.parse(JSON.stringify(this.checkJson[newVal]));
  171. this.LuAudioUrl = ''
  172. if (typeof this.work[newVal] == 'string') {
  173. this.LuAudioUrl = this.work[newVal] ? JSON.parse(JSON.stringify(this.work[newVal])) : ''
  174. } else if (typeof this.work[newVal] == 'object' && this.cjson.type != 'createRole') {
  175. this.LuAudioUrl = this.work[newVal].audio ? JSON.parse(JSON.stringify(this.work[newVal].audio)) : ''
  176. } else if (typeof this.work[newVal] == 'object' && this.cjson.type == 'createRole') {
  177. var a = Array.isArray(this.work[newVal])
  178. if (a) {
  179. this.answerArray = JSON.parse(JSON.stringify(this.work[newVal]))
  180. } else {
  181. this.answerArray = []
  182. this.answerArray.push(
  183. {
  184. isY: false,
  185. content: this.cjson.content3,
  186. name: this.cjson.content,
  187. img: this.cjson.img
  188. }
  189. )
  190. }
  191. this.$emit('setWork', this.answerArray, this.checkType)
  192. }
  193. if (!this.work[newVal] && this.cjson.type == 'createRole') {
  194. var a = Array.isArray(this.work[newVal])
  195. if (a) {
  196. this.answerArray = JSON.parse(JSON.stringify(this.work[newVal]))
  197. } else {
  198. this.answerArray = []
  199. this.answerArray.push(
  200. {
  201. isY: false,
  202. content: this.cjson.content3,
  203. name: this.cjson.content,
  204. img: this.cjson.img
  205. }
  206. )
  207. }
  208. this.$emit('setWork', this.answerArray, this.checkType)
  209. }
  210. this.star = this.work[newVal] ? (this.work[newVal].score ? JSON.parse(JSON.stringify(this.work[newVal].score)) : 0) : 0
  211. this.oheight = 'auto'
  212. this.oWidth = '500px'
  213. const images = this.$refs['obox'].querySelectorAll('img');
  214. let loadedCount = 0;
  215. // if(images.length){
  216. // images.forEach((image) => {
  217. // image.addEventListener('load', () => {
  218. // loadedCount++;
  219. // if (loadedCount === images.length) {
  220. // this.calculateParentHeight()
  221. // }
  222. // });
  223. // });
  224. // }else{
  225. if (this.cjson.type != "createRole") {
  226. this.calculateParentHeight()
  227. }
  228. if (this.cjson.type == "createRole") {
  229. this.createRole(this.cjson.content2, this.cjson.content)
  230. }
  231. // }
  232. },
  233. deep: true,
  234. },
  235. },
  236. methods: {
  237. previewImg(url) {
  238. this.$hevueImgPreview(url);
  239. },
  240. restart() {
  241. let _this = this
  242. _this.$confirm("确定重新录音么?", "提示", {
  243. confirmButtonText: "确定",
  244. cancelButtonText: "取消",
  245. type: "warning",
  246. })
  247. .then(() => {
  248. _this.LuAudioUrl = ""
  249. setTimeout(() => {
  250. _this.startRecorder()
  251. }, 500);
  252. })
  253. .catch(() => { });
  254. },
  255. checkIndex(type) {
  256. if (type == '1') {
  257. if (this.checkType == (this.checkJson.length - 1)) {
  258. return;
  259. }
  260. this.$emit('setType', this.checkType + 1)
  261. } else {
  262. if (this.checkType == 0) {
  263. return;
  264. }
  265. this.$emit('setType', this.checkType - 1)
  266. }
  267. },
  268. // 开始录音
  269. startRecorder() {
  270. let _this = this;
  271. if (!_this.isRecord) {
  272. recorder.destroy(); // 销毁录音
  273. _this.isRecord = true;
  274. if (this.cjson.type == 'theme') {
  275. this.setSecodes()
  276. }
  277. recorder.start().then(
  278. () => { },
  279. (error) => {
  280. _this.isRecord = false;
  281. // _this.$message.error(`${error.name} : ${error.message}`);
  282. _this.$message.error(`没有找到可使用的麦克风,或者您没有允许此网页使用麦克风`);
  283. // 出错了
  284. console.log(`${error.name} : ${error.message}`);
  285. if (_this.calcTimer) {
  286. clearInterval(_this.calcTimer)
  287. _this.calcTimer = null;
  288. }
  289. }
  290. );
  291. } else {
  292. if (_this.calcTimer) {
  293. clearInterval(_this.calcTimer)
  294. _this.calcTimer = null;
  295. }
  296. _this.isRecord = false;
  297. recorder.stop(); // 结束录音
  298. this.getMp3Data()
  299. }
  300. },
  301. // 录音播放
  302. playRecorder() {
  303. if (!recorder.fileSize) {
  304. return;
  305. }
  306. if (!this.isPlayerRecord) {
  307. this.isPlayerRecord = true;
  308. recorder.play();
  309. } else {
  310. this.isPlayerRecord = false;
  311. recorder.stopPlay(); // 停止录音播放
  312. }
  313. recorder.onplayend = () => {
  314. this.isPlayerRecord = false;
  315. console.log("onplayend");
  316. };
  317. },
  318. /**
  319. * 文件格式转换 wav-map3
  320. * */
  321. getMp3Data() {
  322. if (!recorder.fileSize) {
  323. this.$message.error("请录音后在上传语音");
  324. return;
  325. }
  326. const mp3Blob = recorder.getWAVBlob();
  327. // const mp3Blob = this.convertToMp3(recorder.getWAV());
  328. let audioFile = this.dataURLtoAudio(mp3Blob, "wav");
  329. console.log(audioFile);
  330. let iiframe = this.$refs['iiframe']
  331. // this.isloading = true
  332. // this.beforeUpload1(audioFile, 3);
  333. // return;
  334. if (this.cjson.type == 'theme' || this.cjson.type == 'QA') {
  335. this.isloading = true
  336. let _this = this
  337. let _result = ``;
  338. iiframe.contentWindow.onRecognizedResult = function (e) {
  339. console.log('onRecognizedResult', e);
  340. let privText = e.privText
  341. _result+=privText;
  342. // _this.beforeUpload1(audioFile, 3, privText);
  343. }
  344. iiframe.contentWindow.onSessionStopped = function(e){
  345. console.log("转译完成")
  346. console.log(e);
  347. _this.beforeUpload1(audioFile, 3, _result);
  348. }
  349. iiframe.contentWindow.doContinuousPronunciationAssessment('', { files: [audioFile] })
  350. } else if (this.cjson.type == 'createRole') {
  351. // this.isloading = true
  352. // this.beforeUpload1(audioFile, 3);
  353. this.isloading = true
  354. let _this = this
  355. let _result = ``;
  356. iiframe.contentWindow.onRecognizedResult = function (e) {
  357. console.log('onRecognizedResult', e);
  358. let privText = e.privText
  359. _result+=privText;
  360. // _this.beforeUpload1(audioFile, 3, privText);
  361. }
  362. iiframe.contentWindow.onSessionStopped = function(e){
  363. console.log("转译完成")
  364. console.log(e);
  365. _this.beforeUpload1(audioFile, 3, _result);
  366. }
  367. iiframe.contentWindow.doContinuousPronunciationAssessment('', { files: [audioFile] })
  368. } else {
  369. this.isloading = true
  370. let _this = this
  371. let _result = ``;
  372. let _star = ``;
  373. iiframe.contentWindow.onRecognizedResult = function (e) {
  374. console.log('onRecognizedResult', e);
  375. let privText = e.privText
  376. _result +=privText;
  377. _star = JSON.parse(e.privJson).NBest[0].PronunciationAssessment
  378. console.log(_star)
  379. // console.log('star', star)
  380. // e.privText
  381. // JSON.parse(e.privJson).NBest[0].PronunciationAssessment
  382. // _this.beforeUpload1(audioFile, 3, privText, star);
  383. }
  384. iiframe.contentWindow.onSessionStopped = function(e){
  385. console.log("转译完成")
  386. console.log(e);
  387. _this.beforeUpload1(audioFile, 3, _result, _star);
  388. }
  389. iiframe.contentWindow.doContinuousPronunciationAssessment(this.cjson.content, { files: [audioFile] })
  390. }
  391. // recorder.download(mp3Blob, "recorder", "mp3");
  392. },
  393. convertToMp3(wavDataView) {
  394. // 获取wav头信息
  395. const wav = lamejs.WavHeader.readHeader(wavDataView); // 此处其实可以不用去读wav头信息,毕竟有对应的config配置
  396. const { channels, sampleRate } = wav;
  397. const mp3enc = new lamejs.Mp3Encoder(channels, sampleRate, 128);
  398. // 获取左右通道数据
  399. const result = recorder.getChannelData();
  400. const buffer = [];
  401. const leftData =
  402. result.left &&
  403. new Int16Array(result.left.buffer, 0, result.left.byteLength / 2);
  404. const rightData =
  405. result.right &&
  406. new Int16Array(result.right.buffer, 0, result.right.byteLength / 2);
  407. const remaining = leftData.length + (rightData ? rightData.length : 0);
  408. const maxSamples = 1152;
  409. for (let i = 0; i < remaining; i += maxSamples) {
  410. const left = leftData.subarray(i, i + maxSamples);
  411. let right = null;
  412. let mp3buf = null;
  413. if (channels === 2) {
  414. right = rightData.subarray(i, i + maxSamples);
  415. mp3buf = mp3enc.encodeBuffer(left, right);
  416. } else {
  417. mp3buf = mp3enc.encodeBuffer(left);
  418. }
  419. if (mp3buf.length > 0) {
  420. buffer.push(mp3buf);
  421. }
  422. }
  423. const enc = mp3enc.flush();
  424. if (enc.length > 0) {
  425. buffer.push(enc);
  426. }
  427. return new Blob(buffer, { type: "audio/wav" });
  428. },
  429. dataURLtoAudio(blob, filename) {
  430. return new File([blob], filename, { type: "audio/wav" });
  431. },
  432. beforeUpload1(event, type, text, star) {
  433. var file;
  434. if (type == 3) {
  435. file = event;
  436. } else {
  437. file = event.target.files[0];
  438. }
  439. var credentials = {
  440. accessKeyId: "AKIATLPEDU37QV5CHLMH",
  441. secretAccessKey: "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",
  442. }; //秘钥形式的登录上传
  443. window.AWS.config.update(credentials);
  444. window.AWS.config.region = "cn-northwest-1"; //设置区域
  445. var bucket = new window.AWS.S3({ params: { Bucket: "ccrb" } }); //选择桶
  446. var _this = this;
  447. if (file) {
  448. var params = {
  449. Key:
  450. file.name.split(".")[0] +
  451. new Date().getTime() +
  452. "." +
  453. file.name.split(".")[file.name.split(".").length - 1],
  454. ContentType: file.type,
  455. Body: file,
  456. "Access-Control-Allow-Credentials": "*",
  457. ACL: "public-read",
  458. }; //key可以设置为桶的相抵路径,Body为文件, ACL最好要设置
  459. var options = {
  460. partSize: 2048 * 1024 * 1024,
  461. queueSize: 2,
  462. leavePartsOnError: true,
  463. };
  464. bucket
  465. .upload(params, options)
  466. .on("httpUploadProgress", function (evt) {
  467. //这里可以写进度条
  468. // console.log("Uploaded : " + parseInt((evt.loaded * 80) / evt.total) + '%');
  469. // _this.progress = parseInt((evt.loaded * 80) / evt.total);
  470. })
  471. .send(function (err, data) {
  472. if (_this.cjson.type != 'createRole') {
  473. _this.isloading = false
  474. }
  475. // _this.progress = 100;
  476. if (err) {
  477. var a = _this.$refs.upload1.uploadFiles;
  478. a.splice(a.length - 1, a.length);
  479. _this.$message.error("上传失败");
  480. } else {
  481. if (type == 3) {
  482. if (_this.cjson.type == 'createRole') {
  483. _this.answerArray.push(
  484. {
  485. isY: true,
  486. content: text,
  487. voice: data.Location,
  488. name: '',
  489. img: ''
  490. }
  491. )
  492. _this.answerCode(text)
  493. } else {
  494. _this.LuAudioUrl = data.Location;
  495. _this.$emit('setWork', _this.LuAudioUrl, _this.checkType, text, star)
  496. }
  497. }
  498. console.log(data.Location);
  499. }
  500. });
  501. }
  502. },
  503. calculateParentHeight() {
  504. this.$nextTick(() => {
  505. setTimeout(() => {
  506. // 获取父元素
  507. var parentElement = this.$refs['wb'];
  508. // 计算父元素的高度
  509. // var parentHeight = parentElement.offsetHeight + 1;
  510. var parentWidth = parentElement.offsetWidth;
  511. // this.oheight = parentHeight + 'px'
  512. this.oWidth = parentWidth + 'px'
  513. }, 50);
  514. });
  515. },
  516. setSecodes() {
  517. this.totalSeconds = this.checkJson[this.checkType].oTime * 60
  518. // this.totalSeconds = 10
  519. this.calcTimer = setInterval(() => {
  520. if (this.totalSeconds > 0) {
  521. this.totalSeconds--;
  522. } else {
  523. clearInterval(this.calcTimer);
  524. this.calcTimer = null
  525. this.startRecorder()
  526. console.log("倒计时结束"); // 输出日志
  527. }
  528. }, 1000);
  529. },
  530. answerCode(msg) {
  531. var _this = this;
  532. if (msg) {
  533. _this.ajax.post('https://gpt4.cocorobo.cn/assistants_completion_response', {
  534. uid: _this.id,
  535. message: msg,
  536. }).then(function (response) {
  537. console.log(response);
  538. _this.answerArray.push(
  539. {
  540. isY: false,
  541. content: response.data.FunctionResponse,
  542. name: _this.answerArray[0].name,
  543. img: _this.answerArray[0].img
  544. }
  545. )
  546. console.log(_this.answerArray);
  547. _this.$forceUpdate()
  548. _this.isloading = false
  549. _this.$emit('setWork', _this.answerArray, _this.checkType)
  550. }).catch(function (error) {
  551. _this.isloading = false
  552. console.log(error);
  553. });
  554. } else {
  555. _this.answerArray.push(
  556. {
  557. isY: false,
  558. content: "抱歉,您刚刚没有成功录入内容,请再说一遍!",
  559. name: _this.answerArray[0].name,
  560. img: _this.answerArray[0].img
  561. }
  562. )
  563. _this.isloading = false
  564. }
  565. },
  566. guid() {
  567. var _num,
  568. i,
  569. _guid = "";
  570. for (i = 0; i < 32; i++) {
  571. _guid += Math.floor(Math.random() * 16).toString(16); //随机0 - 16 的数字 转变为16进制的字符串
  572. _num = Math.floor((i - 7) / 4); //计算 (i-7)除4
  573. if (_num > -1 && _num < 4 && i == 7 + 4 * _num) {
  574. //会使guid中间加 "-" 形式为xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  575. _guid += "-";
  576. }
  577. }
  578. return _guid;
  579. },
  580. createRole(content, name) {
  581. var _this = this;
  582. _this.ajax.post('https://gpt4.cocorobo.cn/create_free_assistants', {
  583. fileName: [],
  584. url: [],
  585. uid: _this.id,
  586. instructions: content,
  587. assistantName: name
  588. }).then(function (response) {
  589. console.log(response);
  590. }).catch(function (error) {
  591. console.log(error);
  592. });
  593. }
  594. },
  595. beforeDestroy() {
  596. if (!this.isRecord) {
  597. } else {
  598. if (this.calcTimer) {
  599. clearInterval(this.calcTimer)
  600. this.calcTimer = null;
  601. }
  602. recorder.stop(); // 结束录音
  603. }
  604. },
  605. mounted() {
  606. this.cjson = JSON.parse(JSON.stringify(this.checkJson[this.checkType]));
  607. this.LuAudioUrl = ''
  608. if (typeof this.work[this.checkType] == 'string') {
  609. this.LuAudioUrl = this.work[this.checkType] ? JSON.parse(JSON.stringify(this.work[this.checkType])) : ''
  610. } else if (typeof this.work[this.checkType] == 'object' && this.cjson.type != 'createRole') {
  611. this.LuAudioUrl = this.work[this.checkType].audio ? JSON.parse(JSON.stringify(this.work[this.checkType].audio)) : ''
  612. } else if (typeof this.work[this.checkType] == 'object' && this.cjson.type == 'createRole') {
  613. var a = Array.isArray(this.work[this.checkType])
  614. if (a) {
  615. this.answerArray = JSON.parse(JSON.stringify(this.work[this.checkType]))
  616. } else {
  617. this.answerArray = []
  618. this.answerArray.push(
  619. {
  620. isY: false,
  621. content: this.cjson.content3,
  622. name: this.cjson.content,
  623. img: this.cjson.img
  624. }
  625. )
  626. }
  627. this.$emit('setWork', this.answerArray, this.checkType)
  628. }
  629. if (!this.work[this.checkType] && this.cjson.type == 'createRole') {
  630. var a = Array.isArray(this.work[this.checkType])
  631. if (a) {
  632. this.answerArray = JSON.parse(JSON.stringify(this.work[this.checkType]))
  633. } else {
  634. this.answerArray = []
  635. this.answerArray.push(
  636. {
  637. isY: false,
  638. content: this.cjson.content3,
  639. name: this.cjson.content,
  640. img: this.cjson.img
  641. }
  642. )
  643. }
  644. this.$emit('setWork', this.answerArray, this.checkType)
  645. }
  646. this.star = this.work[this.checkType] ? (this.work[this.checkType].score ? JSON.parse(JSON.stringify(this.work[this.checkType].score)) : 0) : 0
  647. if (this.cjson.type != "createRole") {
  648. this.calculateParentHeight()
  649. }
  650. if (this.cjson.type == "createRole") {
  651. this.createRole(this.cjson.content2, this.cjson.content)
  652. }
  653. },
  654. }
  655. </script>
  656. <style scoped>
  657. .o_box {
  658. width: 100%;
  659. height: 100%;
  660. background-image: url('../../../assets/icon/env_background.png');
  661. background-size: cover;
  662. }
  663. .o_top {
  664. height: 65px;
  665. position: absolute;
  666. }
  667. .o_content {
  668. height: calc(100% - 210px);
  669. display: flex;
  670. align-items: center;
  671. justify-content: center;
  672. overflow: hidden;
  673. flex-direction: column;
  674. }
  675. .o_bottom {
  676. height: 210px;
  677. display: flex;
  678. flex-direction: column;
  679. align-items: center;
  680. justify-content: center;
  681. }
  682. .word_box {
  683. min-width: 500px;
  684. max-width: 70%;
  685. background: #fff;
  686. border-radius: 10px;
  687. position: relative;
  688. /* max-height: calc(100% - 40px); */
  689. max-height: calc(100% - 70px);
  690. /* overflow: auto; */
  691. }
  692. .tips_box {
  693. margin-top: 30px;
  694. color: #727272;
  695. }
  696. .word_box>.word_bbox {
  697. width: 100%;
  698. position: relative;
  699. z-index: 999;
  700. max-height: 100%;
  701. overflow: auto;
  702. }
  703. .sentence_box {
  704. background: #e0e0e04d;
  705. min-width: 500px;
  706. max-width: 70%;
  707. border-radius: 15px;
  708. /* max-height: 100%; */
  709. overflow: auto;
  710. padding: 15px;
  711. font-size: 16px;
  712. color: #000;
  713. line-height: 20px;
  714. word-break: break-word;
  715. white-space: pre-line;
  716. max-height: calc(100% - 80px);
  717. }
  718. .word_box::before {
  719. content: '';
  720. position: absolute;
  721. width: 100%;
  722. height: 100%;
  723. display: block;
  724. box-shadow: 0 0 4px 4px #1d39830d;
  725. border-radius: 10px;
  726. z-index: 2;
  727. background: #fff;
  728. }
  729. .word_box::after {
  730. content: '';
  731. position: absolute;
  732. width: 100%;
  733. height: 100%;
  734. background: #fff;
  735. display: block;
  736. box-shadow: 0 0 4px 4px #1d39830d;
  737. border-radius: 10px;
  738. z-index: 1;
  739. top: 15px;
  740. left: 15px;
  741. }
  742. .word_box>.word_bbox>.word_img {
  743. width: calc(100% - 30px);
  744. max-height: 300px;
  745. z-index: 999;
  746. position: relative;
  747. margin: 15px auto;
  748. display: block;
  749. border-radius: 10px;
  750. cursor: pointer;
  751. object-fit: contain;
  752. }
  753. .word_box>.word_bbox>.word_content {
  754. position: relative;
  755. z-index: 999;
  756. text-align: center;
  757. font-size: 36px;
  758. margin: 15px;
  759. font-weight: bold;
  760. color: #000;
  761. width: calc(100% - 30px);
  762. word-break: break-word;
  763. white-space: pre-line;
  764. }
  765. .word_box>.word_bbox>.word_content2 {
  766. position: relative;
  767. z-index: 999;
  768. text-align: left;
  769. font-size: 16px;
  770. margin: 15px;
  771. color: #727272;
  772. width: calc(100% - 30px);
  773. word-break: break-word;
  774. white-space: pre-line;
  775. /* margin-top: 10px; */
  776. }
  777. .o_bottom .audio {
  778. display: flex;
  779. align-items: center;
  780. justify-content: center;
  781. }
  782. .o_bottom .audio>img {
  783. width: 75px;
  784. height: 75px;
  785. cursor: pointer;
  786. }
  787. .o_bottom .audio_word {
  788. display: flex;
  789. align-items: center;
  790. justify-content: center;
  791. color: #00000099;
  792. font-size: 16px;
  793. margin: 10px 0 8px;
  794. }
  795. .o_bottom .audio_index {
  796. display: flex;
  797. align-items: center;
  798. justify-content: center;
  799. }
  800. .audio_index_last,
  801. .audio_index_next {
  802. height: 40px;
  803. width: 40px;
  804. background: #3681fc;
  805. border-radius: 50%;
  806. display: flex;
  807. align-items: center;
  808. justify-content: center;
  809. cursor: pointer;
  810. }
  811. .audio_index_last>img,
  812. .audio_index_next>img {
  813. width: 15px;
  814. height: auto;
  815. }
  816. .audio_index_last.disabled,
  817. .audio_index_next.disabled {
  818. opacity: .6;
  819. }
  820. .audio_index_last>img {
  821. transform: rotate(180deg);
  822. }
  823. .audio_index_last {
  824. margin-right: 20px;
  825. }
  826. .audio_index_content {
  827. color: #000;
  828. font-size: 16px;
  829. }
  830. .audio_index_next {
  831. margin-left: 20px;
  832. }
  833. .audio_ing {
  834. color: #EE3E3E;
  835. margin-top: 25px;
  836. font-size: 12px;
  837. display: flex;
  838. align-items: center;
  839. justify-content: center;
  840. }
  841. .audio_b {
  842. display: flex;
  843. align-items: center;
  844. justify-content: center;
  845. margin-bottom: 15px;
  846. }
  847. .audio_rerecord {
  848. display: flex;
  849. align-items: center;
  850. justify-content: center;
  851. margin-bottom: 15px;
  852. }
  853. .audio_rerecord>span {
  854. display: flex;
  855. border: 1px solid #3981FA;
  856. align-items: center;
  857. color: #3981FA;
  858. padding: 5px 10px;
  859. border-radius: 5px;
  860. cursor: pointer;
  861. }
  862. .audio_rerecord>span::before {
  863. content: '';
  864. width: 15px;
  865. height: 15px;
  866. background: url('../../../assets/icon/englishVoice/restart.png');
  867. display: block;
  868. background-size: 100% 100%;
  869. margin-right: 5px;
  870. }
  871. .audio_class {
  872. background: #3680fb !important;
  873. margin: 0 !important;
  874. }
  875. .audio_b>>>.vueAudioBetter span:before {
  876. color: #fff;
  877. }
  878. .audio_class>>>.slider .process {
  879. background: #000;
  880. }
  881. .audio_b>>>.vueAudioBetter .iconfont:active {
  882. position: unset !important;
  883. }
  884. .time_box {
  885. display: flex;
  886. flex-direction: column;
  887. align-items: center;
  888. justify-content: center;
  889. margin-top: 25px;
  890. }
  891. .time_box>span:nth-child(1) {
  892. color: #727272;
  893. font-size: 16px;
  894. }
  895. .time_box>span:nth-child(2) {
  896. /* margin-top: 10px; */
  897. font-size: 32px;
  898. color: #3581FC;
  899. }
  900. .type_box {
  901. min-width: 500px;
  902. width: 70%;
  903. text-align: right;
  904. color: #a5a5a5;
  905. margin-bottom: 10px;
  906. }
  907. .sentence_div {
  908. width: 100%;
  909. overflow: hidden;
  910. margin-top: 10px;
  911. display: flex;
  912. justify-content: flex-end;
  913. }
  914. .sentence_div>img {
  915. width: 60px;
  916. height: 60px;
  917. object-fit: cover;
  918. cursor: pointer;
  919. border-radius: 4px
  920. }
  921. .star_box {
  922. display: flex;
  923. align-items: center;
  924. margin-bottom: 10px
  925. }
  926. .star_box>.star {
  927. width: 25px;
  928. height: 25px;
  929. display: block;
  930. background-image: url('../../../assets/icon/englishVoice/star-no.png');
  931. background-size: 100% 100%;
  932. }
  933. .star_box>.star+.star {
  934. margin-left: 5px;
  935. }
  936. .star_box>.starA {
  937. background-image: url('../../../assets/icon/englishVoice/star.png');
  938. }
  939. </style>