开箱即用deepseek-vue3+ts版本
</div></div></div></div></div><el-select<el-option/></div></div></div>
<template>
<div class="ds-wrap">
<ul class="menu">
<li
v-for="list in menuArr"
:key="list.id"
@click="dsBtnClick()">
<SvgIcon :name="list.img" width="15" height="15" ></SvgIcon>
{{ list.name }}
</li>
</ul>
<div class="content">
<!-- <Summarize :loading="loading" :content="content"/> -->
<div class="advanced-chat-container">
<div>
<!-- ����ָʾ�� -->
<div class="ds-loading-wrap" v-if="loading">
<div class="loading-indicator">
<div class="spinner"></div>
<span>�������ɻش�...</span>
</div>
</div>
<div class="ds-content" v-else ref="dsContentRef">
<div v-html="md.render(markedContent)"></div>
</div>
</div>
</div>
<div class="ds-button">
<div class="ds-select-wrap">
<SvgIcon name="ds-ms" width="15" height="15" class="dsms-svg"></SvgIcon>
<el-select
v-model="moduleName"
style="width: 220px"
>
<el-option
v-for="item in moduleArr"
:key="item.moduleName"
:label="item.moduleName"
:value="item.moduleName"
/>
</el-select>
</div>
<SvgIcon name="copy" width="35px" height="35px" class="curxB" @click="copyBtn"></SvgIcon>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { notice } from '@/utils/messageUtils';
import MarkdownIt from 'markdown-it';
import hljs from 'highlight.js';
import { DeepSeek } from '@/store/module/API_DS'
const DeepSeekStore = DeepSeek();
const dsContentRef = ref<any>('');
const md = new MarkdownIt({
html: true,
linkify: true,
typographer: true,
xhtmlPut: false,
breaks: false,
langProfix: 'language-',
quotes:'���� ����',
highlight: function (str:any, lang:any) {
if(lang && hljs.getLanguage(lang)) {
try {
return hljs.highlight(str, { language: lang }).value
} catch(_) {}
}
return ''
}
})
const loading = ref(false)
const menuArr = ref([
{ img: 'ds-zj', name: '�����ܽ�', id: 0},
{ img: 'ds-faq', name: '���ܶԻ�', id: 1},
])
const moduleName = ref(import.meta.env.VITE_MODULE);
const moduleArr = ref([
{
id: '0', moduleName: 'deepseek-0.2'
},
{
id: '1', moduleName: 'deepseek-0.3'
}
])
const dsContent = ref(``);
const markedContent = ref<any>(``)
const getAxiosInit = async(data:string) => {
let dataObj = {
"callerno": data
}
const params:any = await DeepSeekStore.queryAssistChatListFn(dataObj)
console.log(params)
if(params.success) {
dsContent.value = params.data
loading.value = true;
getAxios_zj()
} else {
notice().wran('��ʾ', params.message, 'error')
}
}
const dsBtnClick = () => {
if((window as any).top.customInfo.ani) {
let data = (window as any).top.customInfo.ani
getAxiosInit(data)
} else {
notice().wran('��ʾ', 'û�м�¼�������', 'error');
}
}
const getAxios_zj = async() => {
if(dsContent.value == '') {
notice().wran('��ʾ', '���������ݣ�', 'error');
return true;
}
contentInit()
}
const AbortControllers = ref<any>()
const contentInit = async() => {
markedContent.value = '';
AbortControllers.value = new AbortController() as any
let data1 = '������һ�ݿͻ�����ϯ���������ݣ�';
let data2 = '�����Ͽͻ��Ự�����ܽ��һ�λ���';
let data3 = dsContent.value
const response:any = await fetch(`${import.meta.env.VITE_LOAD_URL}${import.meta.env.VITE_CHAT}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
"model": `${import.meta.env.VITE_MODULE}`,
"messages": [
{
"role": "user",
"content": `${data1}${data3}${data2}`
}
],
"stream": true
}),
});
const reader = response.body.getReader();
const decoder = new TextDecoder();
let done = false;
while (!done) {
const { value, done: streamDone } = await reader.read();
done = streamDone;
let tep_mesg:any = ''
console.log(value)
if(value) {
const chunk = decoder.decode(value, {stream: true});
const lines = (tep_mesg + chunk).split('\n');
tep_mesg = lines.pop() || "";
for(const line of lines) {
const message = parseStreamLine(line)
appendToMessage(message)
}
}
}
}
const parseStreamLine = (line:any) => {
try {
const dataString = line.replace(/^data: /, '');
if(!dataString) return "";
const data = JSON.parse(dataString);
return data.choices[0].delta.content || '';
// return data.message.content || '';
} catch {
if(line == "data: [DONE]") return ""
else return null
}
}
const appendToMessage = (message:any) => {
console.log(message)
if (message == '\u003cthink\u003e') {
markedContent.value += "<div class='think'>"
} else if (message == '\u003c/think\u003e') {
markedContent.value += "</div>"
} else {
markedContent.value += message;
}
if(loading.value){
loading.value = false;
}
if(dsContentRef.value) {
const container = dsContentRef.value;
container.scrollTo({
top: container.scrollHeight,
behavior: 'smooth'
})
}
}
const copyBtn = (_node:any) => {
const htmlContent = dsContentRef.value.innerHTML;
// ʹ���������think��ǩ��ע��Ƕ�����ƣ�
const cleanText = htmlContent
.replace(/<div[\s\S]*?<\/div>/gi, '') // �Ƴ�think��ǩ������
.replace(/<[^>]+>/g, '') // �Ƴ�����HTML��ǩ
.replace(/\s+/g, ' ') // �ϲ��ո�
.trim();
copyToClipboard(cleanText);
}
const copyToClipboard = async(text:any) => {
try {
await navigator.clipboard.writeText(text)
notice().wran('��ʾ', '���Ƴɹ�', 'success')
} catch(err) {
notice().wran('��ʾ', '����ʧ��', 'error')
}
}
</script>
<style lang="scss">
.think {
color: rgba(0, 188, 212, 0.88);
border-radius: 5px;
// display: none;
}
.ds-wrap {
margin: 5px auto;
border-radius: 5px;
padding: 10px;
.menu {
width: 100%;
display: flex;
font-size: 14px;
li {
height: 33px;
line-height: 33px;
text-align: center;
cursor: pointer;
display: flex;
align-items: center;
background-color: #f5f6fa;
border-radius: 12px;
box-sizing: border-box;
flex-direction: row;
justify-content: center;
margin-right: 8px;
padding: 8.5px 12px;
svg {
margin: 0 5px;
}
}
}
.content {
margin: 5px 0;margin: 5px 0;
border-radius: 10px;
border: 1px solid #b6adff;
padding: 10px;
height: 88vh;
position: relative;
}
.el-select__placeholder {
padding-left: 25px
}
.ds-button {
display: flex;
flex-wrap: nowrap;
align-items: center;
position: absolute;
bottom: 5px;
.curxB {
margin: 0 10px;
cursor: pointer;
}
.ds-select-wrap {
position: relative;
height: 35px;
}
.dsms-svg {
position: absolute;
left: 0;
z-index: 999;
top: 10px;
left: 10px;
}
}
}
.advanced-chat-container {
width: 100%;
}
.ds-content {
width: 100%;
padding: 10px 12px;
margin-bottom: 45px;
line-height: 22px;
height: 80vh;
overflow: auto;
padding: 12px;
text-indent: 2em;
}
.loading-indicator {
display: flex;
align-items: center;
font-size: 12px;
gap: 8px;
color: #666;
padding: 12px;
.spinner {
width: 12px;
height: 12px;
border: 2px solid #ddd;
border-top-color: #007bff;
border-radius: 50%;
animation: spin 1s linear infinite;
}
}
@keyframes spin {
to {
transform: rotate(360deg)
}
}
</style>
更多推荐

所有评论(0)