1、准备工作
1)、进入以下平台进行注册,登录后,点击红框处
2)、点击个人免费包(会弹出实名认证,先进行实名认证)
3)、认证后,会进入以下界面,先添加应用
4)、添加应用
5)、选择套餐,提交订单
6)、返回主页,点击控制台,找到自己的应用,点击进入应用
7)、进入应用后找到自己的APPID、APISecret、APIKey。
2、先看效果
3、前端完整代码
★★★注意★★★:个人只是写了前端代码,聊天记录刷新后就没有了。
<template><a-layout style="max-width: 800px; margin: auto"><a-layout-content:style="{border: '3px solid #4fc3f7',borderRadius: '8px',boxShadow: '0 8px 16px rgba(0, 0, 0, 0.3)',overflow: 'hidden',}"><h2 style="margin-bottom: 20px; text-align: center; color: #4fc3f7">Chat Record</h2><div class="divider"></div><div class="chat-messages" ref="chatMessages"><!-- 聊天记录显示区域Q --><div v-if="dialogueHistory.length === 0" class="no-data-message">暂无数据</div><divv-for="message in dialogueHistory":key="message.id"class="message-container"><!-- 修改部分 --><div:class="[message.type === 'question'? 'user-name-aline': 'robot-name-aline',]"><div>{{ message.name }}:</div></div><div class="divider"></div><div:class="[message.type === 'question' ? 'user-message' : 'bot-message',message.isCode ? 'code-message' : '',]"style="position: relative"><template v-if="message.isCode"><!-- 使用 extractCodeAndLanguage 函数 --><prev-html="highlightCode(extractCodeAndLanguage(message.text).code)"style="background-color: #f0f0f0;padding: 15px;box-shadow: #999999;border-radius: 5px;margin: 0;"></pre></template><template v-else>{{ message.text }}</template><!-- 添加复制按钮 --><buttonv-if="message.isCode"@click="copyCode(message.text)"class="copy-button"style="position: absolute;top: 7px;right: 7px;cursor: pointer;border: none;background: transparent;color: #3498db;">Copy</button></div><!-- 结束修改部分 --></div></div><div class="user-input-container"><!-- 用户输入框 --><a-inputv-model="inputVal"@pressEnter="sendMsg"placeholder="请输入消息..."style="flex-grow: 1;padding: 8px;border: 1px solid #3498db;border-radius: 5px;margin-right: 10px;"/><!-- 发送按钮 --><a-button type="primary" @click="sendMsg" style="cursor: pointer">发送</a-button></div></a-layout-content></a-layout>
</template>
<script setup>
import { ref } from "vue";
import * as base64 from "base-64";
import CryptoJs from "crypto-js";
import hljs from "highlight.js/lib/core";
import "highlight.js/styles/default.css"; // 选择适合你项目的样式// 导入你需要的语言支持
import javascript from "highlight.js/lib/languages/javascript";
import css from "highlight.js/lib/languages/css";
import html from "highlight.js/lib/languages/xml";
import ClipboardJS from "clipboard";// 注册语言支持
hljs.registerLanguage("javascript", javascript);
hljs.registerLanguage("css", css);
hljs.registerLanguage("html", html);
const requestObj = {APPID: "填你自己的",APISecret: "填你自己的",APIKey: "填你自己的",Uid: "0",sparkResult: "",
};const inputVal = ref("");
const result = ref("");
const dialogueHistory = ref([]);const isCopyButtonClicked = ref(false);// 检测回复是否为代码
const isCode = (text) => {// 简单的检测逻辑,您可以根据需要进行调整return text.startsWith("```") && text.endsWith("```");
};// 获取鉴权 URL
const getWebsocketUrl = async () => {return new Promise((resolve, reject) => {const url = "wss://spark-api.xf-yun.com/v3.1/chat";const host = "spark-api.xf-yun.com";const apiKeyName = "api_key";const date = new Date().toGMTString();const algorithm = "hmac-sha256";const headers = "host date request-line";const signatureOrigin = `host: ${host}\ndate: ${date}\nGET /v3.1/chat HTTP/1.1`;const signatureSha = CryptoJs.HmacSHA256(signatureOrigin,requestObj.APISecret);const signature = CryptoJs.enc.Base64.stringify(signatureSha);const authorizationOrigin = `${apiKeyName}="${requestObj.APIKey}", algorithm="${algorithm}", headers="${headers}", signature="${signature}"`;const authorization = base64.encode(authorizationOrigin);// 将空格编码resolve(`${url}?authorization=${authorization}&date=${encodeURI(date)}&host=${host}`);});
};// 发送消息
const sendMsg = async () => {const myUrl = await getWebsocketUrl();const socket = new WebSocket(myUrl);socket.onopen = (event) => {// 发送消息的逻辑// 发送消息const params = {header: {app_id: requestObj.APPID,uid: "redrun",},parameter: {chat: {domain: "generalv3",temperature: 0.5,max_tokens: 1024,},},payload: {message: {text: [{ role: "user", content: inputVal.value }],},},};dialogueHistory.value.push({type: "question",name: "我",text: inputVal.value,// timestamp: getTimestamp(),});socket.send(JSON.stringify(params));};socket.onmessage = (event) => {const data = JSON.parse(event.data);if (data.header.code !== 0) {console.error("Error:", data.header.code, data.header.message);socket.close();return;}// 累积所有接收到的消息if (data.payload.choices.text) {// 连接新接收到的消息片段const newMessage = data.payload.choices.text[0].content;if (dialogueHistory.value.length > 0 &&dialogueHistory.value[dialogueHistory.value.length - 1].type ==="answer") {// 连接新接收到的消息片段到最后一个回答dialogueHistory.value[dialogueHistory.value.length - 1].text +=newMessage;} else {// 添加新的回答dialogueHistory.value.push({type: "answer",name: "智能助手",text: newMessage,// timestamp: getTimestamp(),});}// 如果回复是代码,添加相应的标记和样式if (isCode(newMessage)) {dialogueHistory.value[dialogueHistory.value.length - 1].isCode = true;}}// 如果对话完成或者发生错误,则关闭 socketif (data.header.status === 2 || data.header.code !== 0) {setTimeout(() => {socket.close();}, 1000);}};socket.onclose = (event) => {inputVal.value = "";};socket.onerror = (event) => {console.error("WebSocket error:", event);};
};
// 移除代码块的标记和语言标识符
const extractCodeAndLanguage = (text) => {if (isCode(text)) {const lines = text.split("\n");const language = lines[0].substring(3).trim();const code = lines.slice(1, -1).join("\n");return { language, code };}return { language: null, code: text };
};
// 高亮代码的方法
const highlightCode = (code) => {// 判断是否包含代码标识符if (code.startsWith("```") && code.endsWith("```")) {// 去掉头尾的```标识符code = code.slice(3, -3);}const highlighted = hljs.highlightAuto(code);return highlighted.value;
};
//
// // 获取当前时间戳
// const getTimestamp = () => {
// return Math.floor(new Date().getTime() / 1000);
// };
//
// // 格式化时间戳为可读的时间格式
// const formatTimestamp = (timestamp) => {
// const date = new Date(timestamp * 1000);
// const hours = date.getHours();
// const minutes = "0" + date.getMinutes();
// return `${hours}:${minutes.substr(-2)}`;
// };
const copyCode = (code) => {// 使用 clipboard.js 复制文本到剪贴板const parentButton = document.querySelector(".message-container button");// 获取处理后的代码,如果是代码块,提取其中的代码const processedCode =code.startsWith("```") && code.endsWith("```")? extractCodeAndLanguage(code).code: code;// 获取按钮元素const copyButton = document.querySelector(".copy-button");// 按钮初始文本const initialButtonText = copyButton.innerText;// 修改按钮文本为勾copyButton.innerText = "✔ Copied";// 3秒后将按钮文本还原setTimeout(() => {copyButton.innerText = initialButtonText;}, 3000);if (parentButton && parentButton.parentNode) {const clipboard = new ClipboardJS(parentButton, {text: function () {return processedCode;},});clipboard.on("success", function (e) {console.log("Text copied to clipboard:", e.text);clipboard.destroy(); // 销毁 clipboard 实例,防止重复绑定});clipboard.on("error", function (e) {console.error("Unable to copy text to clipboard:", e.action);clipboard.destroy(); // 销毁 clipboard 实例,防止重复绑定});} else {console.error("Parent button or its parent node is null or undefined.");}
};
</script><style scoped>
#ChatRobotView {max-width: 800px;margin: auto;
}.chat-container {border: 1px solid #ccc;border-radius: 8px;overflow: hidden;
}.chat-messages {padding: 10px;max-height: 400px;overflow-y: auto;
}.message {margin-bottom: 10px;
}.user-message {background-color: #3498db;color: #ffffff;padding: 10px;border-radius: 5px;align-self: flex-end;
}.bot-message {background-color: #e0e0e0;color: #000000;padding: 10px;border-radius: 5px;align-self: flex-start;
}.user-input-container {display: flex;justify-content: space-between;align-items: center;padding: 10px;border-top: 1px solid #ddd;
}.user-input-container input {flex-grow: 1;padding: 8px;border: 1px solid #ddd;border-radius: 5px;margin-right: 10px;
}.user-input-container button {background-color: #4caf50;color: #fff;border: none;padding: 8px 16px;border-radius: 5px;cursor: pointer;
}.message-container {display: flex;flex-direction: column;margin-bottom: 10px;
}.message-info {font-size: 12px;color: #888;margin-bottom: 5px;
}.user-name-aline {align-self: flex-end;margin-bottom: 5px;
}.robot-name-aline {align-self: flex-start;margin-bottom: 5px;
}.no-data-message {font-size: large;color: #8c8c8c;height: 200px;display: flex;align-items: center;justify-content: center;
}.message-container button.copy-button:active {background-color: #4caf50; /* 按下时的背景色 */color: #fff;
}.divider {width: 100%;height: 1px;background-color: #4fc3f7;margin: 5px 0;
}
</style>