|
@@ -8,11 +8,13 @@
|
|
|
<div class="titBarLeft">
|
|
|
<div
|
|
|
@click="cutBar(index)"
|
|
|
- :class="barNum == index ? 'titBarBorder' : ''"
|
|
|
+ :class="pageStatus == index ? 'titBarBorder' : ''"
|
|
|
v-for="(i, index) in titBarList"
|
|
|
:key="index + 'a'"
|
|
|
>
|
|
|
- <img :src="barNum == index ? i.ico : i.ico1" alt="" />{{ i.title }}
|
|
|
+ <img :src="pageStatus == index ? i.ico : i.ico1" alt="" />{{
|
|
|
+ i.title
|
|
|
+ }}
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="titBarRig">
|
|
@@ -23,18 +25,21 @@
|
|
|
<div class="ca-top">
|
|
|
<!-- 开始页面 -->
|
|
|
<startPage
|
|
|
- v-show="barNum == 0 && !TapeNum"
|
|
|
- @startTape="judge = 1"
|
|
|
+ v-show="showIndexPage"
|
|
|
+ @startTape="recordedStart"
|
|
|
@uploadTape="uploadRecording"
|
|
|
/>
|
|
|
- <!-- 实时转录 -->
|
|
|
- <transcription v-show="barNum == 1" :data="transcriptionData" />
|
|
|
- <!-- 上传录音页 -->
|
|
|
- <tape :chatData="chatList" v-show="barNum == 0 && TapeNum" />
|
|
|
+ <!-- 原文速递 -->
|
|
|
+ <transcription
|
|
|
+ v-show="pageStatus == 1 && !showIndexPage"
|
|
|
+ :data="transcriptionData"
|
|
|
+ />
|
|
|
+ <!-- ai对话 -->
|
|
|
+ <tape ref="tapeRef" :aiNameList="aiNameList" :chatData="chatList" v-show="pageStatus == 0 && !showIndexPage" />
|
|
|
<!-- <div class="t-t-m-Item" v-show="cardStatus==1"> -->
|
|
|
<iframe
|
|
|
ref="viframe"
|
|
|
- v-if="barNum == 2"
|
|
|
+ v-if="pageStatus == 2 && !showIndexPage"
|
|
|
style="width: 100%; height: 100%; border: none"
|
|
|
:src="
|
|
|
'https://view.officeapps.live.com/op/view.aspx?src=' +
|
|
@@ -47,11 +52,11 @@
|
|
|
<div class="ca-b-operation">
|
|
|
<div class="ca-b-o-header">
|
|
|
<div class="ca-b-o-h-left">
|
|
|
- <div class="ca-b-o-h-l-select" @click.stop="changeAnalysis()">
|
|
|
+ <!-- <div class="ca-b-o-h-l-select" @click.stop="changeAnalysis()">
|
|
|
<span class="ca-b-o-h-l-s-icon el-icon-collection"></span>
|
|
|
<div class="ca-b-o-h-s-l-text">课堂观察</div>
|
|
|
<span class="ca-b-o-h-s-l-icon2 el-icon-caret-top"></span>
|
|
|
- </div>
|
|
|
+ </div> -->
|
|
|
|
|
|
<div class="ca-b-o-h-l-select" style="color: #3681fc">
|
|
|
<div
|
|
@@ -71,7 +76,6 @@
|
|
|
v-for="(i, index) in languageList"
|
|
|
:key="index + 'lag'"
|
|
|
:class="i.label == languageRadio ? 'radioBg' : ''"
|
|
|
- @click.stop="changeLanguage"
|
|
|
v-model.number="languageRadio"
|
|
|
:label.Num="i.label"
|
|
|
>{{ i.lang }}</el-radio
|
|
@@ -88,13 +92,26 @@
|
|
|
<div class="ca-b-o-h-right">
|
|
|
<div class="ca-b-o-h-r-radio">
|
|
|
<div
|
|
|
- :class="TapeNum == index ? 'TapeCss' : ''"
|
|
|
+ :class="
|
|
|
+ (index == 0 && showIndexPage) ||
|
|
|
+ (index == 1 && !showIndexPage)
|
|
|
+ ? 'TapeCss'
|
|
|
+ : ''
|
|
|
+ "
|
|
|
class="tapeSty"
|
|
|
@click="cutTape(index)"
|
|
|
v-for="(i, index) in tapeList"
|
|
|
:key="index + 'b'"
|
|
|
>
|
|
|
- <img :src="TapeNum == index ? i.ico : i.ico1" alt="" />
|
|
|
+ <img
|
|
|
+ :src="
|
|
|
+ (index == 0 && showIndexPage) ||
|
|
|
+ (index == 1 && !showIndexPage)
|
|
|
+ ? i.ico
|
|
|
+ : i.ico1
|
|
|
+ "
|
|
|
+ alt=""
|
|
|
+ />
|
|
|
</div>
|
|
|
|
|
|
<!-- <span @click.stop="changeContinuousDialogue(!continuousDialogue)"
|
|
@@ -109,16 +126,16 @@
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div v-show="!judge" class="ca-b-o-main">
|
|
|
+ <div class="ca-b-o-main">
|
|
|
<div
|
|
|
class="ca-b-o-m-tape"
|
|
|
- v-show="TapeNum == 0 && startTape == 0"
|
|
|
- @click.stop="judge = 1"
|
|
|
+ v-show="controlsStatus == 0"
|
|
|
+ @click.stop="recordedStart()"
|
|
|
>
|
|
|
<span class="el-icon-microphone"></span>
|
|
|
<div class="ca-b-o-m-t-text">点击开始录音</div>
|
|
|
</div>
|
|
|
- <div class="ca-b-o-m-tapeTwo" v-show="TapeNum == 0 && startTape == 1">
|
|
|
+ <div class="ca-b-o-m-tapeTwo" v-show="controlsStatus == 2">
|
|
|
<mini-audio
|
|
|
:audio-source="audioUrl"
|
|
|
class="audio_class"
|
|
@@ -133,7 +150,7 @@
|
|
|
justify-content: center;
|
|
|
align-items: center;
|
|
|
"
|
|
|
- @click="judge = 1"
|
|
|
+ @click="recordedStart()"
|
|
|
>
|
|
|
<img
|
|
|
style="width: 10px; height: 16px"
|
|
@@ -142,54 +159,76 @@
|
|
|
/>
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div
|
|
|
- class="ca-b-o-m-inputAre"
|
|
|
- v-show="TapeNum == 1 && startTape == 0"
|
|
|
- >
|
|
|
+ <div class="ca-b-o-m-inputAre" v-show="controlsStatus == 3">
|
|
|
<div class="ca-b-o-m-left">
|
|
|
<textarea
|
|
|
id="myTextarea"
|
|
|
+ ref="textareaRef"
|
|
|
min-rows="1"
|
|
|
max-rows="5"
|
|
|
- :value="textareaValue"
|
|
|
- placeholder="在此输入您想了解的内容,输入“/”可获取提示语,shift+enter换行"
|
|
|
+ v-model="textareaValue"
|
|
|
+ placeholder="在此输入您想了解的内容"
|
|
|
autosize="none"
|
|
|
+ @input="textareaChange"
|
|
|
+ @change="textareaChange"
|
|
|
></textarea>
|
|
|
</div>
|
|
|
<div class="ca-b-o-m-right">
|
|
|
<span @click.stop="tapeSubmit()"></span>
|
|
|
- <div :class="sendBtnDsiable ? 'ca-b-o-m-r-dsiableBtn' : ''">
|
|
|
+ <!-- <div :class="sendBtnDsiable ? 'ca-b-o-m-r-dsiableBtn' : ''">
|
|
|
发送
|
|
|
- </div>
|
|
|
+ </div> -->
|
|
|
+ <el-button :disabled="textareaValue.trim().length==0" type="primary" size="mini" @click="send()">发送</el-button>
|
|
|
</div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
- <div class="ca-b-o-m-inputAreImg" v-show="judge">
|
|
|
- <img
|
|
|
- style="height: 120%"
|
|
|
- src="@/assets/icon/classroomObservation/tapetime.png"
|
|
|
- alt=""
|
|
|
- />
|
|
|
- <div
|
|
|
- style="width: 100px; display: flex; justify-content: space-between"
|
|
|
- >
|
|
|
- <div class="lyStart" @click="(judge = 0), (startTape = 1)">
|
|
|
+ <div class="ca-b-o-m-TapeArea" v-show="controlsStatus == 1">
|
|
|
+ <div class="ca-b-o-m-i-left">
|
|
|
<img
|
|
|
- style="width: 12px; height: 12px"
|
|
|
- src="@/assets/icon/classroomObservation/lyStart.png"
|
|
|
+ style="height: 120%"
|
|
|
+ src="@/assets/icon/classroomObservation/isTape.png"
|
|
|
alt=""
|
|
|
/>
|
|
|
+ <div>
|
|
|
+ <div v-if="recordedForm.status == 1" style="color:#EE3E3E">录音中...</div>
|
|
|
+ <div v-if="recordedForm.status == 2" style="color:#6b798e">已暂停...</div>
|
|
|
+ <span>{{ recordedForm.time }}</span>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
-
|
|
|
- <div class="lyStart" @click="(judge = 0), (startTape = 1)">
|
|
|
- <img
|
|
|
- style="width: 12px; height: 12px"
|
|
|
- src="@/assets/icon/classroomObservation/lyStop.png"
|
|
|
- alt=""
|
|
|
- />
|
|
|
+ <!-- <img
|
|
|
+ style="height: 120%"
|
|
|
+ src="@/assets/icon/classroomObservation/tapetime.png"
|
|
|
+ alt=""
|
|
|
+ /> -->
|
|
|
+ <div
|
|
|
+ style="
|
|
|
+ width: 100px;
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ "
|
|
|
+ >
|
|
|
+ <div class="lyStart" @click="stopRecorded()">
|
|
|
+ <img
|
|
|
+ style="width: 12px; height: 12px"
|
|
|
+ src="@/assets/icon/classroomObservation/lyStart.png"
|
|
|
+ alt=""
|
|
|
+ v-if="recordedForm.status == 1"
|
|
|
+ />
|
|
|
+ <img
|
|
|
+ style="width: 12px; height: 12px"
|
|
|
+ src="@/assets/icon/classroomObservation/start.png"
|
|
|
+ alt=""
|
|
|
+ v-if="recordedForm.status == 2"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div class="lyStart" @click="finishRecorded()">
|
|
|
+ <img
|
|
|
+ style="width: 12px; height: 12px"
|
|
|
+ src="@/assets/icon/classroomObservation/lyStop.png"
|
|
|
+ alt=""
|
|
|
+ />
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
- <!-- <div class="ca-b-o-m-left">
|
|
|
+ <!-- <div class="ca-b-o-m-left">
|
|
|
<textarea :value="textareaValue" autosize="none"></textarea>
|
|
|
</div>
|
|
|
<div class="ca-b-o-m-right">
|
|
@@ -198,6 +237,7 @@
|
|
|
发送
|
|
|
</div>
|
|
|
</div> -->
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
@@ -209,6 +249,26 @@ import startPage from "./startPage.vue";
|
|
|
import transcription from "./transcription.vue";
|
|
|
import tape from "./tape.vue";
|
|
|
|
|
|
+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---------------')
|
|
|
+// };
|
|
|
+
|
|
|
// 自定义指令,用于处理点击外部区域的事件
|
|
|
const clickOutside = {
|
|
|
bind(el, binding) {
|
|
@@ -229,16 +289,16 @@ const clickOutside = {
|
|
|
},
|
|
|
};
|
|
|
export default {
|
|
|
- emits:["updateFileId"],
|
|
|
+ emits: ["updateFileId"],
|
|
|
props: {
|
|
|
tid: {
|
|
|
type: String,
|
|
|
- require:true,
|
|
|
+ require: true,
|
|
|
},
|
|
|
fileIdid: {
|
|
|
type: String,
|
|
|
- default: ''
|
|
|
- }
|
|
|
+ default: "",
|
|
|
+ },
|
|
|
},
|
|
|
components: {
|
|
|
startPage,
|
|
@@ -250,24 +310,27 @@ export default {
|
|
|
},
|
|
|
data() {
|
|
|
return {
|
|
|
- continuousDialogue: true,
|
|
|
- mainBtnStatus: 0, //0--录音 1--输入
|
|
|
- pageStatus: 0, //0--初始页面 1--实时转录 2--上传录音页
|
|
|
+ // continuousDialogue: true,
|
|
|
+ controlsStatus: 0, //0--点击开始录音 1--录音中 2--录音完毕预览 3--文字输入
|
|
|
+ pageStatus: 0, //0--ai对话 1--原文文稿 2--转录文稿
|
|
|
+ showIndexPage: true, //是否显示初始页面
|
|
|
languageRadio: 1, //设置选择语言
|
|
|
- languageShow: 0, //控制显示
|
|
|
- // 判断0录音与1打字切换
|
|
|
- TapeNum: 0,
|
|
|
- startTape: 0,
|
|
|
- loading:false,
|
|
|
- judge: 0,
|
|
|
+ languageShow: false, //控制显示
|
|
|
+ loading: false,
|
|
|
textareaValue: "",
|
|
|
- barNum: 0,
|
|
|
+ recordedForm: {
|
|
|
+ time: "00:00:00", //时间
|
|
|
+ status: 0, //0--未录音 1--正在录音 2--暂停 3--录音结束
|
|
|
+ },
|
|
|
+ aiNameList:[
|
|
|
+ {index:0,name:"ai助手"},
|
|
|
+ {index:1,name:"ABC模型"},
|
|
|
+ {index:2,name:'5EX模型'}
|
|
|
+ ],
|
|
|
audioUrl:
|
|
|
"https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/%E8%A7%A3%E5%86%B3%E5%9E%83%E5%9C%BE%E9%97%AE%E9%A2%981713172672090.m4a",
|
|
|
-
|
|
|
fileUrl:
|
|
|
"https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/%E8%BD%AC%E5%BD%95%E6%96%87%E7%A8%BF1713172600896.xlsx",
|
|
|
-
|
|
|
// 设置list
|
|
|
languageList: [
|
|
|
{ label: 1, lang: "普通话" },
|
|
@@ -350,12 +413,6 @@ export default {
|
|
|
直接填埋这种方法会占用大量土地,而且还会污染土地,焚烧发电这种方法会会污_
|
|
|
`,
|
|
|
},
|
|
|
- /* [
|
|
|
- {
|
|
|
- time:'00:01'k,
|
|
|
- content:''
|
|
|
- }
|
|
|
- ]*/
|
|
|
chatList: [
|
|
|
{
|
|
|
role: "ai",
|
|
@@ -407,20 +464,20 @@ Markdown表格Markdown表格Markdown表格Markdown表格Markdown表格Markdown
|
|
|
return true;
|
|
|
},
|
|
|
},
|
|
|
+ watch: {},
|
|
|
methods: {
|
|
|
handleBlur(event) {
|
|
|
// console.log("点击其它区域啦", event);
|
|
|
this.languageShow = !this.languageShow;
|
|
|
},
|
|
|
- handShow() {},
|
|
|
// 上传录音
|
|
|
uploadRecording() {
|
|
|
let input = document.createElement("input");
|
|
|
input.type = "file";
|
|
|
- input.accept = "*";
|
|
|
+ input.accept = "audio/*, .txt, .pdf, .xlsx";
|
|
|
input.click();
|
|
|
input.onchange = () => {
|
|
|
- this.loading= true;
|
|
|
+ this.loading = true;
|
|
|
let file = input.files[0];
|
|
|
var credentials = {
|
|
|
accessKeyId: "AKIATLPEDU37QV5CHLMH",
|
|
@@ -460,30 +517,47 @@ Markdown表格Markdown表格Markdown表格Markdown表格Markdown表格Markdown
|
|
|
_this.$message.error("上传失败");
|
|
|
_this.loading = false;
|
|
|
} else {
|
|
|
- _this.ajax.put("https://gpt4.cocorobo.cn/upload_file_knowledge",{url: data.Location}).then(res=>{
|
|
|
- let _data = res.data.FunctionResponse;
|
|
|
- if(_data.result && _data.result.id){
|
|
|
- _this.$emit("updateFileId", _data.result.id)
|
|
|
- let pram2 = {
|
|
|
- id: _this.fileIdid,
|
|
|
- json_data: JSON.stringify({file_ids:_data.result.id}),
|
|
|
- // json_data: JSON.stringify({file_ids:'file-r5phg4I2oFqly4WpW7oOOTnA'}),
|
|
|
- };
|
|
|
- _this.ajax
|
|
|
- .post(
|
|
|
- "https://gpt4.cocorobo.cn/update_classroom_observation",
|
|
|
- pram2
|
|
|
- )
|
|
|
- }else{
|
|
|
- _this.$message.error("上传失败")
|
|
|
- }
|
|
|
+ // 判断是不是音频文件
|
|
|
+ const audioRegex = /\.(mp3|wav|ogg|flac|m4a)$/i;
|
|
|
+ if (audioRegex.test(data.Location)) {
|
|
|
+ _this.controlsStatus = 2;
|
|
|
+ _this.showIndexPage = false;
|
|
|
+ _this.pageStatus = 1;
|
|
|
+ _this.audioUrl = data.Location;
|
|
|
_this.loading = false;
|
|
|
- // this.$emit("updateFileId", data.Location)
|
|
|
- }).catch(e=>{
|
|
|
- _this.loading = false;
|
|
|
- _this.$message.error("上传失败")
|
|
|
- })
|
|
|
-
|
|
|
+ } else {
|
|
|
+ _this.ajax
|
|
|
+ .put("https://gpt4.cocorobo.cn/upload_file_knowledge", {
|
|
|
+ url: data.Location,
|
|
|
+ })
|
|
|
+ .then((res) => {
|
|
|
+ let _data = res.data.FunctionResponse;
|
|
|
+ if (_data.result && _data.result.id) {
|
|
|
+ _this.$emit("updateFileId", _data.result.id);
|
|
|
+ let pram2 = {
|
|
|
+ id: _this.fileIdid,
|
|
|
+ json_data: JSON.stringify({
|
|
|
+ file_ids: _data.result.id,
|
|
|
+ }),
|
|
|
+ // json_data: JSON.stringify({file_ids:'file-r5phg4I2oFqly4WpW7oOOTnA'}),
|
|
|
+ };
|
|
|
+ _this.ajax.post(
|
|
|
+ "https://gpt4.cocorobo.cn/update_classroom_observation",
|
|
|
+ pram2
|
|
|
+ );
|
|
|
+ } else {
|
|
|
+ _this.$message.error("上传失败");
|
|
|
+ }
|
|
|
+ _this.loading = false;
|
|
|
+ // this.$emit("updateFileId", data.Location)
|
|
|
+ })
|
|
|
+ .catch((e) => {
|
|
|
+ _this.loading = false;
|
|
|
+ _this.$message.error("上传失败");
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // console.log(data.Location)
|
|
|
}
|
|
|
});
|
|
|
}
|
|
@@ -492,32 +566,297 @@ Markdown表格Markdown表格Markdown表格Markdown表格Markdown表格Markdown
|
|
|
// this.barNum = 4;
|
|
|
},
|
|
|
cutBar(val) {
|
|
|
- this.barNum = val;
|
|
|
+ this.pageStatus = val;
|
|
|
+ if (this.pageStatus == 0) {
|
|
|
+ //ai对话
|
|
|
+ this.controlsStatus = 3;
|
|
|
+ } else if (this.pageStatus == 1 || this.pageStatus == 2) {
|
|
|
+ // 原文速览&&转录文稿
|
|
|
+ this.controlsStatus = 2;
|
|
|
+ }
|
|
|
+ this.showIndexPage = false;
|
|
|
},
|
|
|
cutTape(val) {
|
|
|
- this.TapeNum = val * 1;
|
|
|
- this.judge = 0;
|
|
|
- this.startTape = 0;
|
|
|
- if (val == 1) {
|
|
|
- this.barNum = 0;
|
|
|
+ if (val == 0) {
|
|
|
+ this.showIndexPage = true;
|
|
|
+ this.controlsStatus = 0;
|
|
|
+ } else if (val == 1) {
|
|
|
+ if (this.pageStatus == 0) {
|
|
|
+ //ai对话
|
|
|
+ this.controlsStatus = 3;
|
|
|
+ } else if (this.pageStatus == 1 || this.pageStatus == 2) {
|
|
|
+ // 原文速览&&转录文稿
|
|
|
+ this.controlsStatus = 2;
|
|
|
+ }
|
|
|
+ this.showIndexPage = false;
|
|
|
}
|
|
|
},
|
|
|
- // 切换语言
|
|
|
- changeLanguage() {
|
|
|
- this.$message.info("切换语言");
|
|
|
+ recordedStart() {
|
|
|
+ // 开始录音
|
|
|
+ if (this.controlsStatus != 1 && this.recordedForm.status == 0) {
|
|
|
+ recorder.initRecorder(); //初始化录音
|
|
|
+ recorder.destroy(); // 销毁录音
|
|
|
+ // 开始录音
|
|
|
+ recorder.start().then(
|
|
|
+ () => {
|
|
|
+ this.controlsStatus = 1;
|
|
|
+ this.recordedForm.status = 1;
|
|
|
+ recorder.onprogress = this.updateRecordedTime;
|
|
|
+ this.$message.success("录音已开始");
|
|
|
+ },
|
|
|
+ (error) => {
|
|
|
+ this.controlsStatus = 0;
|
|
|
+ this.recordedForm.status = 0;
|
|
|
+ // _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 ([1, 2].includes(this.recordedForm.status)) {
|
|
|
+ this.controlsStatus = 1;
|
|
|
+ this.$message.info("还在录音中");
|
|
|
+ } else if ([3].includes(this.recordedForm.status)) {
|
|
|
+ this.$confirm("再次录音会顶替掉之前的录音,您确定吗", "提醒", {
|
|
|
+ confirmButtonText: "确定",
|
|
|
+ cancelButtonText: "取消",
|
|
|
+ type: "warning",
|
|
|
+ })
|
|
|
+ .then(() => {
|
|
|
+ this.recordedForm.status = 0;
|
|
|
+ recorder.initRecorder(); //初始化录音
|
|
|
+ recorder.destroy(); // 销毁录音
|
|
|
+ this.recordedStart();
|
|
|
+ })
|
|
|
+ .catch((_) => {
|
|
|
+ console.log("不顶替");
|
|
|
+ });
|
|
|
+ }
|
|
|
+ // this.controlsStatus = 1;
|
|
|
},
|
|
|
- //切换观察
|
|
|
- changeAnalysis() {
|
|
|
- this.$message.info("切换观察");
|
|
|
+ updateRecordedTime({duration}) {
|
|
|
+ // 更新currentTime,将秒数转换为时分秒格式
|
|
|
+ let hours = Math.floor(duration / 3600);
|
|
|
+ let minutes = Math.floor((duration % 3600) / 60);
|
|
|
+ let seconds = Math.floor(duration % 60);
|
|
|
+ this.recordedForm.time = `${hours.toString().padStart(2, "0")}:${minutes
|
|
|
+ .toString()
|
|
|
+ .padStart(2, "0")}:${seconds.toString().padStart(2, "0")}`;
|
|
|
},
|
|
|
+ //切换观察
|
|
|
+ // changeAnalysis() {
|
|
|
+ // this.$message.info("切换观察");
|
|
|
+ // },
|
|
|
// 切换连续对话
|
|
|
changeContinuousDialogue(newValue) {
|
|
|
this.continuousDialogue = newValue;
|
|
|
},
|
|
|
- //点击开始录音
|
|
|
+ // 点击发送旁的录音
|
|
|
tapeSubmit() {
|
|
|
- this.mainBtnStatus = 0;
|
|
|
- this.pageStatus = 1;
|
|
|
+ // this.$message.info("发送旁的录音");
|
|
|
+ // this.mainBtnStatus = 0;
|
|
|
+ // this.pageStatus = 1;
|
|
|
+ // this.TapeNum = 0;
|
|
|
+ },
|
|
|
+ async finishRecorded() {
|
|
|
+ this.loading = true;
|
|
|
+ recorder.stop();
|
|
|
+ this.$message.success("已结束录音");
|
|
|
+
|
|
|
+ let file = this.convertToMp3(recorder.getWAV());
|
|
|
+ file.lastModifiedDate = new Date();
|
|
|
+ file.name = "recordedFile.mp3";
|
|
|
+ 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) + '%');
|
|
|
+ })
|
|
|
+ .send(function (err, data) {
|
|
|
+ if (err) {
|
|
|
+ _this.$message.error("上传失败");
|
|
|
+ _this.loading = false;
|
|
|
+ } else {
|
|
|
+ // 判断是不是音频文件
|
|
|
+ // 更改录音文件
|
|
|
+ _this.audioUrl = data.Location;
|
|
|
+ _this.controlsStatus = 2;
|
|
|
+ _this.pageStatus = 1;
|
|
|
+ _this.recordedForm.status = 3;
|
|
|
+ _this.showIndexPage = false;
|
|
|
+ _this.loading = false;
|
|
|
+ // const audioRegex = /\.(mp3|wav|ogg|flac|m4a)$/i;
|
|
|
+ // if (audioRegex.test(data.Location)) {
|
|
|
+ // _this.controlsStatus = 2;
|
|
|
+ // _this.showIndexPage = false;
|
|
|
+ // _this.pageStatus = 1;
|
|
|
+ // _this.audioUrl = data.Location;
|
|
|
+ // _this.loading = false;
|
|
|
+ // } else {
|
|
|
+ // _this.ajax
|
|
|
+ // .put("https://gpt4.cocorobo.cn/upload_file_knowledge", {
|
|
|
+ // url: data.Location,
|
|
|
+ // })
|
|
|
+ // .then((res) => {
|
|
|
+ // let _data = res.data.FunctionResponse;
|
|
|
+ // if (_data.result && _data.result.id) {
|
|
|
+ // _this.$emit("updateFileId", _data.result.id);
|
|
|
+ // let pram2 = {
|
|
|
+ // id: _this.fileIdid,
|
|
|
+ // json_data: JSON.stringify({
|
|
|
+ // file_ids: _data.result.id,
|
|
|
+ // }),
|
|
|
+ // // json_data: JSON.stringify({file_ids:'file-r5phg4I2oFqly4WpW7oOOTnA'}),
|
|
|
+ // };
|
|
|
+ // _this.ajax.post(
|
|
|
+ // "https://gpt4.cocorobo.cn/update_classroom_observation",
|
|
|
+ // pram2
|
|
|
+ // );
|
|
|
+ // } else {
|
|
|
+ // _this.$message.error("上传失败");
|
|
|
+ // }
|
|
|
+ // _this.loading = false;
|
|
|
+ // // this.$emit("updateFileId", data.Location)
|
|
|
+ // })
|
|
|
+ // .catch((e) => {
|
|
|
+ // _this.loading = false;
|
|
|
+ // _this.$message.error("上传失败");
|
|
|
+ // });
|
|
|
+ // }
|
|
|
+
|
|
|
+ // console.log(data.Location)
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ // recorder.download(mp3Blob, "recorder", "mp3");
|
|
|
+ // let wavBlob = await recorder.getWAVBlob()
|
|
|
+ // const reader = new FileReader();
|
|
|
+ //将blob转未ArrayBuffer
|
|
|
+ // reader.onload = () => {
|
|
|
+ // const audioData = reader.result; // 获取 WAV blob 数据
|
|
|
+ // const samples = new Int16Array(audioData); // 转换为 Int16Array
|
|
|
+ // // 创建一个mp3编码器
|
|
|
+ // const mp3Encoder = new lamejs.Mp3Encoder(1, 44100, 128);
|
|
|
+ // // 将录音数据编码为MP3
|
|
|
+ // const mp3Data = mp3Encoder.encodeBuffer(samples);
|
|
|
+ // // 创建一个Blob包含MP3数据
|
|
|
+ // const mp3Blob = new Blob([mp3Data], { type: "audio/mp3" });
|
|
|
+ // console.log(`MP3文件:${mp3Blob}`);
|
|
|
+ // this.loading = false;
|
|
|
+ // recorder.initRecorder(); // 初始化录音
|
|
|
+ // recorder.destroy(); // 销毁录音
|
|
|
+ // };
|
|
|
+ // reader.readAsArrayBuffer(blob);
|
|
|
+ },
|
|
|
+ stopRecorded() {
|
|
|
+ if (!recorder.ispause) {
|
|
|
+ recorder.pause();
|
|
|
+ this.recordedForm.status = 2;
|
|
|
+ this.$message.warning("已暂停录音");
|
|
|
+ } else {
|
|
|
+ recorder.resume();
|
|
|
+ this.recordedForm.status = 1;
|
|
|
+ this.$message.success("已继续录音");
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 发送消息
|
|
|
+ send(){
|
|
|
+ if(this.textareaValue.trim().length<=0)return this.$message.info(`请输入内容`);
|
|
|
+
|
|
|
+ this.chatList.push({
|
|
|
+ role: "user",
|
|
|
+ name: "我",
|
|
|
+ create_at: new Date().toLocaleString().replace(/\//ig,'-'),
|
|
|
+ content: `${this.textareaValue}`,
|
|
|
+ },)
|
|
|
+
|
|
|
+ this.textareaValue = "";
|
|
|
+ this.chatList.push({
|
|
|
+ role: "ai",
|
|
|
+ name: "AI助手",
|
|
|
+ create_at: new Date().toLocaleString().replace(/\//ig,'-'),
|
|
|
+ content:`您好呀,我有什么可以帮助您的吗`,
|
|
|
+ },)
|
|
|
+
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.$refs.textareaRef.style.height = '50px'
|
|
|
+ this.$refs.tapeRef.$el.querySelector('.t-chartArea').scrollTop = this.$refs.tapeRef.$el.querySelector('.t-chartArea').scrollHeight;
|
|
|
+ });;
|
|
|
+ },
|
|
|
+ textareaChange(){
|
|
|
+ this.$refs.textareaRef.style.height = '50px'
|
|
|
+ this.$refs.textareaRef.style.height = this.$refs.textareaRef.scrollHeight+"px"
|
|
|
+ },
|
|
|
+
|
|
|
+ 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" });
|
|
|
},
|
|
|
},
|
|
|
};
|
|
@@ -648,6 +987,7 @@ Markdown表格Markdown表格Markdown表格Markdown表格Markdown表格Markdown
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
justify-content: flex-end;
|
|
|
+ position: relative;
|
|
|
}
|
|
|
.ca-b-o-header {
|
|
|
width: 100%;
|
|
@@ -765,9 +1105,8 @@ Markdown表格Markdown表格Markdown表格Markdown表格Markdown表格Markdown
|
|
|
|
|
|
margin-top: 5px;
|
|
|
border-radius: 16px;
|
|
|
- background-color: white;
|
|
|
- box-shadow: 0 5px 10px 10px #e6eaeb;
|
|
|
transition: 0.3s;
|
|
|
+ position: relative;
|
|
|
}
|
|
|
|
|
|
.ca-b-o-main:hover {
|
|
@@ -783,6 +1122,9 @@ Markdown表格Markdown表格Markdown表格Markdown表格Markdown表格Markdown
|
|
|
align-items: center;
|
|
|
font-size: 20px;
|
|
|
color: #3681fc;
|
|
|
+ border-radius: 16px;
|
|
|
+ background-color: white;
|
|
|
+ box-shadow: 0 5px 10px 10px #e6eaeb;
|
|
|
transition: 0.3s;
|
|
|
}
|
|
|
.ca-b-o-m-tapeTwo {
|
|
@@ -796,6 +1138,9 @@ Markdown表格Markdown表格Markdown表格Markdown表格Markdown表格Markdown
|
|
|
color: #3681fc;
|
|
|
box-sizing: border-box;
|
|
|
padding: 0 20px;
|
|
|
+ border-radius: 16px;
|
|
|
+ background-color: white;
|
|
|
+ box-shadow: 0 5px 10px 10px #e6eaeb;
|
|
|
transition: 0.3s;
|
|
|
}
|
|
|
.ca-b-o-m-tapeTwo >>> .vueAudioBetter {
|
|
@@ -812,49 +1157,85 @@ Markdown表格Markdown表格Markdown表格Markdown表格Markdown表格Markdown
|
|
|
|
|
|
.ca-b-o-m-inputAre {
|
|
|
width: 100%;
|
|
|
- height: 100%;
|
|
|
+ min-height: 100%;
|
|
|
+ height: auto;
|
|
|
display: flex;
|
|
|
- align-items: center;
|
|
|
+ align-items: flex-end;
|
|
|
+ border-radius: 16px;
|
|
|
+ background-color: white;
|
|
|
+ box-shadow: 0 5px 10px 10px #e6eaeb;
|
|
|
+ transition: 0.3s;
|
|
|
+ position: absolute;
|
|
|
+ bottom: 0;
|
|
|
}
|
|
|
|
|
|
-.ca-b-o-m-inputAreImg {
|
|
|
+.ca-b-o-m-TapeArea{
|
|
|
width: 100%;
|
|
|
- height: 64px;
|
|
|
+ height: 100%;
|
|
|
display: flex;
|
|
|
- margin-top: 5px;
|
|
|
justify-content: space-between;
|
|
|
+ border-radius: 16px;
|
|
|
background-color: #f0f2f5;
|
|
|
+ box-shadow: 0 5px 10px 10px #e6eaeb;
|
|
|
+ transition: 0.3s;
|
|
|
+ align-items: center;
|
|
|
+ padding-right: 20px;
|
|
|
+ box-sizing: border-box;
|
|
|
+}
|
|
|
+
|
|
|
+.ca-b-o-m-i-left {
|
|
|
+ display: flex;
|
|
|
align-items: center;
|
|
|
}
|
|
|
-.ca-b-o-m-inputAreImg > img {
|
|
|
- height: 100%;
|
|
|
+
|
|
|
+.ca-b-o-m-i-left > div > div {
|
|
|
+ color: #ee3e3e;
|
|
|
+ font-weight: bold;
|
|
|
+}
|
|
|
+
|
|
|
+.ca-b-o-m-i-left > div > span {
|
|
|
+ font-size: 14px;
|
|
|
+ margin-top: 5px;
|
|
|
+}
|
|
|
+
|
|
|
+.ca-b-o-m-i-left > img {
|
|
|
+ margin-left: 10px;
|
|
|
+ border-radius: 50%;
|
|
|
+ margin-right: 20px;
|
|
|
}
|
|
|
|
|
|
.ca-b-o-m-left {
|
|
|
flex: 1;
|
|
|
- height: 100%;
|
|
|
+ height: auto;
|
|
|
+ min-height: 64px;
|
|
|
display: flex;
|
|
|
/* justify-content: center; */
|
|
|
align-items: center;
|
|
|
box-sizing: border-box;
|
|
|
- padding: 0 20px;
|
|
|
+ padding-left: 20px;
|
|
|
}
|
|
|
|
|
|
.ca-b-o-m-left > textarea {
|
|
|
resize: none;
|
|
|
- height: 80%;
|
|
|
- width: 98%;
|
|
|
+ min-height: 50px;
|
|
|
+ margin: 7px 0;
|
|
|
+ max-height: 500px;
|
|
|
+ width: 100%;
|
|
|
font-size: 18px;
|
|
|
border: none;
|
|
|
outline: none;
|
|
|
+ resize: none;
|
|
|
+ overflow: auto;
|
|
|
}
|
|
|
.ca-b-o-m-right {
|
|
|
- width: 150px;
|
|
|
- height: 100%;
|
|
|
+ width: 100px;
|
|
|
+ min-width: 80px;
|
|
|
+ height: 64px;
|
|
|
+ max-height: 64px;
|
|
|
display: flex;
|
|
|
justify-content: center;
|
|
|
align-items: center;
|
|
|
- /* background-color: red; */
|
|
|
+ margin-right: 10px;
|
|
|
}
|
|
|
|
|
|
#myTextarea::-webkit-input-placeholder {
|