组件封装
<template>
</template>
<script>
import CryptoJS from 'crypto-js';
export default {
props: {
modelValue: {
type: Object,
default: {}
}
},
data () {
return {
appId: 'fe9c3cb1',
status: 'init',
ttsWS: null,
totalRes: '',
userInput: '',
};
},
watch: {
modelValue: {
handler (newValue) {
if (newValue.flag) {
this.totalRes = '';
this.connectWebSocket();
}
}
}
},
methods: {
getWebsocketUrl () {
return new Promise((resolve, reject) => {
const apiKey = '????';
const apiSecret = '????';
const url = 'wss://spark-api.xf-yun.com/v1.1/chat';
const host = window.location.host;
const date = new Date().toGMTString();
const algorithm = 'hmac-sha256';
const headers = 'host date request-line';
const signatureOrigin = `host: ${host}\ndate: ${date}\nGET /v1.1/chat HTTP/1.1`;
const signatureSha = CryptoJS.HmacSHA256(signatureOrigin, apiSecret);
const signature = CryptoJS.enc.Base64.stringify(signatureSha);
const authorizationOrigin = `api_key="${apiKey}", algorithm="${algorithm}", headers="${headers}", signature="${signature}"`;
const authorization = window.btoa(authorizationOrigin);
const finalUrl = `${url}?authorization=${authorization}&date=${date}&host=${host}`;
resolve(finalUrl);
});
},
setStatus (status) {
this.status = status;
},
connectWebSocket () {
this.setStatus('ttsing');
this.getWebsocketUrl().then((url) => {
let ttsWS;
if ('WebSocket' in window) {
ttsWS = new WebSocket(url);
} else if ('MozWebSocket' in window) {
ttsWS = new MozWebSocket(url);
} else {
alert('浏览器不支持WebSocket');
return;
}
this.ttsWS = ttsWS;
ttsWS.onopen = (e) => {
this.webSocketSend();
};
ttsWS.onmessage = (e) => {
this.result(e.data);
};
ttsWS.onerror = (e) => {
clearTimeout(this.playTimeout);
this.setStatus('error');
alert('WebSocket报错,请f12查看详情');
console.error(`详情查看:${encodeURI(url.replace('wss:', 'https:'))}`);
};
ttsWS.onclose = (e) => {
this.$emit("update:modelValue", {
flag: !this.modelValue.flag,
text: this.totalRes
})
};
});
},
webSocketSend () {
console.log(this.modelValue);
const params = {
header: {
app_id: this.appId,
uid: '填写你的uid',
},
parameter: {
chat: {
domain: 'general',
temperature: 0.5,
max_tokens: 2048,
},
},
payload: {
message: {
text: [
{ "role": "system", "content": "预设的提问" },
{ "role": "user", "content": this.modelValue.text } //this.modelValue.text 父组件传过来的提问,可以开启上下文对话
],
},
},
};
this.ttsWS.send(JSON.stringify(params));
},
result (resultData) {
let jsonData = JSON.parse(resultData);
this.totalRes += jsonData.payload?.choices.text.map(item => item.content).join("")
if (jsonData.header.code !== 0) {
alert(`提问失败: ${jsonData.header.code}:${jsonData.header.message}`);
console.error(`${jsonData.header.code}:${jsonData.header.message}`);
return;
}
if (jsonData.header.code === 0 && jsonData.header.status === 2) {
this.ttsWS.close();
this.setStatus('init');
}
},
},
};
</script>
组件调用
按钮事件:
<!-- ai逻辑复用 -->
<AiHooks v-model="aiQuestion"></AiHooks>
const aiQuestion = ref() //ai问题
async function getMark () {
loading.value = true;
aiQuestion.value = {
flag: true,
text: 你的提问内容
}
}
监听 aiQuestion 属性
watch(() => aiQuestion.value, (newValue) => {
if (!newValue.flag) {
newValue.text // 回复内容 变量名
...事件
}
})
aiQuestion 改变时调用组件发送请求,并获得回复的内容