<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>
 

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐