网络安全助手
作品简介
在当今数字化时代,网络安全问题日益突出,从个人隐私泄露到企业数据安全,都需要专业的知识和工具来应对。本作品旨在为用户提供一个便捷的网络安全助手,通过简单的对话或粘贴相关问题,即可获得专业的安全建议和解决方案,简单方便。
技术架构
采用了全后端分离的架构,前端使用 Vue.js,后端使用 Flask 框架,腾讯云的 AI 服务处理自然语言理解与生成。
实现过程
开发环境、开发流程
- 系统:windows 11
- 开发工具:vscode
- 开发环境:node-v23.6.0-win-x64
开发流程
关键技术解析
腾讯云 AI 代码助手在上述过程中的助力
- 理解代码
- 通过腾讯云 AI 代码助手,快速理解代码逻辑和功能。
- 增加标识内容
- 给页面增加了显示的 title,使用腾讯云 AI 代码助手完成的所有内容。
- 增加了点赞确认提示
- 使用腾讯云 AI 助手直接提问,粘贴对应代码完成。
效果展示
使用说明
安装node-v23.6.0-win-x64
启动项目
npm i
npm run dev
- 访问应用
- 访问 http://localhost:3005/ 进行提问即可。
效果展示
演示视频地址:腾讯云AI代码助手-网络安全助手
代码示例
前端部分(Vue.js)
<template>
<h1
style="
text-align: center;
margin-top: 20px;
font-family: 'Arial', sans-serif;
color: #b6ee4b;
background-color: #000000;
padding: 10px 20px;
border-radius: 5px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
"
>
网络安全助手
</h1>
<t-chat
ref="chatRef"
layout="single"
style="height: 600px;
background-color: #d1e9b9;"
:clear-history="chatList.length > 0 && !isStreamLoad"
@clear="clearConfirm"
>
<template v-for="(item, index) in chatList" :key="index">
<t-chat-item
:avatar="item.avatar"
:name="item.name"
:role="item.role"
:datetime="item.datetime"
:content="item.content"
:text-loading="index === 0 && loading"
>
<template v-if="!isStreamLoad" #actions>
<t-chat-action
:is-good="isGood"
:is-bad="isBad"
:content="item.content"
@operation="(type, { e }) => handleOperation(type, { e, index })"
/>
</template>
</t-chat-item>
</template>
<template #footer>
<t-chat-input :stop-disabled="isStreamLoad" @send="inputEnter" @stop="onStop"> </t-chat-input>
</template>
</t-chat>
</template>
<script setup>
import { ref } from 'vue';
const fetchCancel = ref(null);
const loading = ref(false);
const isStreamLoad = ref(false);
const isGood = ref(false);
const isBad = ref(false);
const chatRef = ref(null);
// 滚动到底部
const backBottom = () => {
chatRef.value.scrollToBottom({
behavior: 'smooth',
});
};
// 倒序渲染
const chatList = ref([
{
avatar: 'https://tdesign.gtimg.com/site/chat-avatar.png',
name: '网络安全助手',
datetime: '今天16:38',
content: '我是网络安全助手,有什么可以帮助您?',
role: 'assistant',
},
{
avatar: 'https://www.helloimg.com/i/2025/01/09/677fd84ef02f0.png',
name: 'user',
datetime: '今天21:18',
content: '你是谁',
role: 'user',
},
]);
const clearConfirm = function () {
chatList.value = [];
};
const onStop = function () {
if (fetchCancel.value) {
fetchCancel.value.abort();
loading.value = false;
isStreamLoad.value = false;
}
};
const handleOperation = function (type, options) {
const { index } = options;
if (type === 'good') {
isGood.value = !isGood.value;
isBad.value = false;
} else if (type === 'bad') {
isBad.value = !isBad.value;
isGood.value = false;
} else if (type === 'replay') {
const userQuery = chatList.value[index + 1].content;
inputEnter(userQuery);
}
};
const handleData = async (inputValue) => {
loading.value = true;
isStreamLoad.value = true;
const lastItem = chatList.value[0];
const messages = [{
role: 'user',
content: inputValue,
}];
fetchSSE(messages, {
success(result) {
loading.value = false;
const { data } = result;
lastItem.content += data?.delta?.content;
},
complete(isOk, msg) {
if (!isOk || !lastItem.content) {
lastItem.role = 'error';
lastItem.content = msg;
}
// 控制终止按钮
isStreamLoad.value = false;
loading.value = false;
},
cancel(cancel) {
fetchCancel.value = cancel;
},
});
};
const inputEnter = function (inputValue) {
if (isStreamLoad.value) {
return;
}
if (!inputValue) return;
const params = {
avatar: 'https://www.helloimg.com/i/2025/01/09/677fd84ef02f0.png',
name: 'user',
datetime: new Date().toDateString(),
content: inputValue,
role: 'user',
};
chatList.value.unshift(params);
// 空消息占位
const params2 = {
avatar: 'https://tdesign.gtimg.com/site/chat-avatar.png',
name: '网络安全助手',
datetime: new Date().toDateString(),
content: '',
role: 'assistant',
};
chatList.value.unshift(params2);
handleData(inputValue);
};
// 解析SSE数据
const fetchSSE = async (messages, options) => {
const { success, fail, complete, cancel } = options;
const controller = new AbortController();
const { signal } = controller;
cancel?.(controller);
// your-api-key
const apiKey = 'sk-6R0hq8U7v3bSbT1u41Lp6kPRwAgf9wnW73WgvSC7WUI73eRO';
const responsePromise = fetch('/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer${apiKey ? ` ${apiKey}` : ''}`,
},
body: JSON.stringify({
messages, // 消息列表
model: 'hunyuan-pro', // 模型
stream: true, // 流式
}),
signal,
}).catch((e) => {
const msg = e.toString() || '流式接口异常';
complete?.(false, msg);
return Promise.reject(e); // 确保错误能够被后续的.catch()捕获
});
responsePromise
.then((response) => {
if (!response?.ok) {
complete?.(false, response.statusText);
fail?.();
throw new Error('Request failed'); // 抛出错误以便链式调用中的下一个.catch()处理
}
const reader = response.body.getReader();
const decoder = new TextDecoder();
if (!reader) throw new Error('No reader available');
const bufferArr = [];
let dataText = ''; // 记录数据
const event = { type: null, data: null };
async function processText({ done, value }) {
if (done) {
complete?.(true);
return Promise.resolve();
}
const chunk = decoder.decode(value);
const buffers = chunk.toString().split(/\r?\n/);
bufferArr.push(...buffers);
const i = 0;
while (i < bufferArr.length) {
const line = bufferArr[i];
if (line) {
dataText += line;
const response = line.slice(6);
if (response === '[DONE]') {
event.type = 'finish';
dataText = '';
} else {
const choices = JSON.parse(response.trim())?.choices?.[0];
if (choices.finish_reason === 'stop') {
event.type = 'finish';
dataText = '';
} else {
event.type = 'delta';
event.data = choices;
}
}
}
if (event.type && event.data) {
const jsonData = JSON.parse(JSON.stringify(event));
// debugger;
success(jsonData);
event.type = null;
event.data = null;
}
bufferArr.splice(i, 1);
}
return reader.read().then(processText);
}
return reader.read().then(processText);
})
.catch(() => {
// 处理整个链式调用过程中发生的任何错误
fail?.();
});
};
</script>
希望这个示例对你有所帮助!