From ed6f781fbe1dd5297a54d61ba50b5d609bb1b639 Mon Sep 17 00:00:00 2001
From: king <18310653075@163.com>
Date: 星期四, 20 三月 2025 10:31:59 +0800
Subject: [PATCH] Merge branch 'positec' into dms

---
 src/views/mkai/index.jsx |  312 +++++++++++++++++++++++++++------------------------
 1 files changed, 167 insertions(+), 145 deletions(-)

diff --git a/src/views/mkai/index.jsx b/src/views/mkai/index.jsx
index 05fddfb..aff559b 100644
--- a/src/views/mkai/index.jsx
+++ b/src/views/mkai/index.jsx
@@ -4,6 +4,7 @@
 import { LoadingOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons'
 // import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'
 // import { dark } from 'react-syntax-highlighter/dist/esm/styles/prism'
+import { fetchEventSource } from '@microsoft/fetch-event-source'
 import moment from 'moment'
 
 import Api from '@/api'
@@ -180,46 +181,13 @@
     message.success('澶嶅埗鎴愬姛銆�')
   }
 
-  // eslint-disable-next-line
-  // let html = marked(item.content, {
-  //   highlight: (code, language) => {
-  //   // 閫氳繃鏃堕棿鎴崇敓鎴愬敮涓�鏍囪瘑
-  //   const codeIndex = parseInt(Date.now() + "") + Math.floor(Math.random() * 10000000)
-  //   // 鏍煎紡鍖栫涓�琛屾槸鍙充晶language鍜� 鈥滃鍒垛�� 鎸夐挳锛�
-  //   let html = ` 
-  //     <div class=${styles["code-block-header"]}>
-  //       <span>${language}</span>
-  //       <span id='copy-btn'data-clipboard-action="copy" data-clipboard-target="#copy${codeIndex}">澶嶅埗浠g爜</span>
-  //     </div>
-  //   `
-    
-  //   //浠g爜閮ㄥ垎
-  //   if (code) {
-  //     try {
-  //     // 浣跨敤 highlight.js 瀵逛唬鐮佽繘琛岄珮浜樉绀�
-  //       const preCode = hljs.highlightAuto(code).value;
-  //       // 灏嗕唬鐮佸寘瑁瑰湪 textarea 涓紝鐢变簬闃叉textarea娓叉煋鍑虹幇闂锛岃繖閲屽皢 "<" 鐢� "&lt;" 浠f浛锛屼笉褰卞搷澶嶅埗鍔熻兘
-  //       return `<pre class='${styles["hljs-customer"]} hljs'>
-  //           <code>${preCode}</code>
-  //       </pre>
-  //       <textarea style="position: absolute;top: -9999px;left: -9999px;z-index: -9999;" id="copy${codeIndex}">${code.replace(/<\/textarea>/g,"&lt;/textarea>")}</textarea>`;
-  //     } catch (error) {
-
-  //       }
-  //     }
-  //   }
-  // })
-  // <SyntaxHighlighter language="javascript" style={dark}>
-  //   {item.content}
-  // </SyntaxHighlighter>
-
   return (
     <div className="assist-wrap" {...restProps}>
       <DeepSeekLogo/>
-      {item.type === 'deepseek-reasoner' ? <div className="top-level">
+      <div className="top-level">
         <DeepSeekIcon />
         {item.loading ? '鎬濊�冧腑...' : '宸叉繁搴︽�濊��'}
-      </div> : null}
+      </div>
       {item.loading ? <LoadingOutlined /> : null}
       <div dangerouslySetInnerHTML={{ __html: item.content }}></div>
       {item.oriText ? <MkCopy onClick={copy}/> : null}
@@ -233,8 +201,9 @@
     UserID: '',
     LoginUID: '',
     textInput: '',
-    type: 'deepseek-reasoner', // deepseek-chat deepseek-reasoner
+    type: 'DeepSeek-R1-Distill-Qwen-32B', // deepseek-chat deepseek-reasoner
     currentChat: {id: '', list: [], title: ''},
+    dpChat: null,
     chats: []
   }
 
@@ -380,7 +349,7 @@
             id: cell.id,
             content: _content,
             oriText: content,
-            type: cell.typecharone || '',
+            type: 'deepseek-reasoner',
             role
           }
         })
@@ -390,14 +359,14 @@
     })
   }
 
-  changeType = () => {
-    const { type } = this.state
+  // changeType = () => {
+  //   const { type } = this.state
 
-    this.setState({type: type === 'deepseek-reasoner' ? 'deepseek-chat' : 'deepseek-reasoner'})
-  }
+  //   this.setState({type: type === 'deepseek-reasoner' ? 'deepseek-chat' : 'deepseek-reasoner'})
+  // }
 
   submit = () => {
-    const { textInput, currentChat, UserID, LoginUID, loading, type } = this.state
+    const { textInput, currentChat, loading, type /*, UserID, LoginUID*/ } = this.state
 
     let val = textInput.replace(/\t+|\v+/g, '').replace(/^\s+|\s+$/g, '')
 
@@ -406,122 +375,174 @@
     let node = document.getElementById('mk-input')
     node && node.blur()
 
-    let isNew = false
+    // let isNew = false
+    const that = this
     let chat = fromJS(currentChat).toJS()
 
-    if (!chat.id) {
-      chat.id = Utils.getuuid()
-      isNew = true
-    }
-
     chat.list.push({ role: 'user', content: val, id: Utils.getuuid() })
-    chat.list.push({ role: 'assistant', content: '', type: type, loading: true, id: Utils.getuuid() })
 
     if (!chat.title) {
       chat.title = val.substr(0, 32)
     }
     chat.loading = true
 
-    this.setState({textInput: '', currentChat: chat})
+    let reschat = { role: 'assistant', content: '', type: type, loading: true, id: Utils.getuuid() }
 
-    let list = []
-    chat.list.forEach(item => {
-      if (!item.loading) {
-        list.push({
-          role: item.role,
-          content: item.oriText || item.content
-        })
-      }
-    })
+    this.setState({textInput: '', currentChat: fromJS(chat).toJS(), dpChat: reschat})
 
-    Api.directRequest({
-      url: burl + '/chat/completions',
-      method: 'post',
-      headers: { 'Content-Type': 'application/json' },
-      data: {
-        model: type,
-        messages: list,
-        stream: false
-      }
-    }).then(res => {
-      let _chat = fromJS(chat).toJS()
+    // let list = []
+    // chat.list.forEach(item => {
+    //   if (!item.loading) {
+    //     list.push({
+    //       role: item.role,
+    //       content: item.oriText || item.content
+    //     })
+    //   }
+    // })
 
-      delete _chat.loading
-      _chat.list.pop()
+    // const ctrlAbout = new AbortController()
+    // const { signal } = ctrlAbout
+    let contents = []
+    let timer = setInterval(() => {
+      if (contents.length) {
+        let _cont = contents.shift()
 
-      let _val = '鏈嶅姟鍣ㄧ箒蹇欙紝璇风◢鍚庡啀璇曘��'
-      let _html = _val
-      let tokens_count = 0
-      if (res.success && res.choices && res.choices[0]) {
-        _val = res.choices[0].message.content
-        _html = this.getAssistVal(_val)
-      } else if (!res.success && res.rawStatusCode === 400 && res.message && /This\s*model's\s*maximum\s*context\s*length/.test(res.message)) {
-        _html = `褰撳墠瀵硅瘽宸茶秴鍑�${type === 'deepseek-reasoner' ? '娣卞害鎬濊�冪殑' : ''}鏈�澶ч暱搴﹂檺鍒讹紝寮�鍚竴涓柊瀵硅瘽缁х画鎬濊�冨惂~`
-        _val = _html
-      }
-
-      if (res.usage && res.usage.total_tokens) {
-        tokens_count = res.usage.total_tokens
-      }
-
-      _chat.list = _chat.list.map(item => {
-        delete item.loading
-        delete item.step
-        return item
-      })
-
-      _chat.list.push({ role: 'assistant', content: _html, oriText: _val, type: type, step: true, id: Utils.getuuid() })
-
-      this.setState({currentChat: _chat})
-
-      Api.genericInterface({
-        func: 's_deepseek_ai',
-        rduri: burl + '/webapi/dostars',
-        file_url: '',
-        userid: UserID,
-        LoginUID: LoginUID,
-        u_id: sessionStorage.getItem('UserID'),
-        content: window.btoa(window.encodeURIComponent(_val)),
-        title: window.btoa(window.encodeURIComponent(chat.title)),
-        data_type: 'reply',
-        tokens_count: tokens_count,
-        version: type,
-        ID: chat.id
-      }).then(r => {
-        if (!r.status) {
-          notification.error({
-            top: 92,
-            message: r.message,
-            duration: 10
-          })
-        } else if (isNew) {
-          this.getList()
+        if (_cont === '[CLOSE]') {
+          clearInterval(timer)
+          chat.list.push(reschat)
+          that.setState({dpChat: null, currentChat: chat, loading: false})
+        } else {
+          reschat.content += _cont
+    
+          if (_cont === '</think>') {
+            delete reschat.loading
+          }
+  
+          that.setState({dpChat: reschat})
         }
-      })
-    })
+      }
+    }, 30)
 
-    Api.genericInterface({
-      func: 's_deepseek_ai',
-      rduri: burl + '/webapi/dostars',
-      file_url: '',
-      userid: UserID,
-      LoginUID: LoginUID,
-      u_id: sessionStorage.getItem('UserID'),
-      content: window.btoa(window.encodeURIComponent(val)),
-      title: window.btoa(window.encodeURIComponent(chat.title)),
-      data_type: 'request',
-      version: type,
-      tokens_count: 0,
-      ID: chat.id
-    }).then(result => {
-      if (!result.status) {
-        notification.error({
-          top: 92,
-          message: result.message,
-          duration: 10
-        })
+    fetchEventSource(burl + '/chat', {
+      mode: 'cors',
+      method: 'POST',
+      headers: {
+        'Content-Type': 'application/json',
+        'Accept': 'text/event-stream'
+      },
+      body: JSON.stringify({
+        chat_session_id: chat.id || '',
+        model: type,
+        prompt: val,
+        stream: true
+      }),
+      onmessage(event) {
+        if (event.data) {
+          if (event.data === '[CLOSE]') {
+            contents.push(event.data)
+          } else {
+            let data = JSON.parse(event.data)
+            if (!chat.id && data.id) {
+              chat.id = data.id
+            }
+            contents.push(data.content)
+          }
+        }
+      },
+      onclose() {},
+      onerror(error) {
+        console.info(error)
       }
     })
+
+    // Api.directRequest({
+    //   url: burl + '/chat/completions',
+    //   method: 'post',
+    //   headers: { 'Content-Type': 'application/json' },
+    //   data: {
+    //     model: type,
+    //     messages: list,
+    //     stream: false
+    //   }
+    // }).then(res => {
+    //   let _chat = fromJS(chat).toJS()
+
+    //   delete _chat.loading
+    //   _chat.list.pop()
+
+    //   let _val = '鏈嶅姟鍣ㄧ箒蹇欙紝璇风◢鍚庡啀璇曘��'
+    //   let _html = _val
+    //   let tokens_count = 0
+    //   if (res.success && res.choices && res.choices[0]) {
+    //     _val = res.choices[0].message.content
+    //     _html = this.getAssistVal(_val)
+    //   } else if (!res.success && res.rawStatusCode === 400 && res.message && /This\s*model's\s*maximum\s*context\s*length/.test(res.message)) {
+    //     _html = `褰撳墠瀵硅瘽宸茶秴鍑�${type === 'deepseek-reasoner' ? '娣卞害鎬濊�冪殑' : ''}鏈�澶ч暱搴﹂檺鍒讹紝寮�鍚竴涓柊瀵硅瘽缁х画鎬濊�冨惂~`
+    //     _val = _html
+    //   }
+
+    //   if (res.usage && res.usage.total_tokens) {
+    //     tokens_count = res.usage.total_tokens
+    //   }
+
+    //   _chat.list = _chat.list.map(item => {
+    //     delete item.loading
+    //     delete item.step
+    //     return item
+    //   })
+
+    //   _chat.list.push({ role: 'assistant', content: _html, oriText: _val, type: type, step: true, id: Utils.getuuid() })
+
+    //   this.setState({currentChat: _chat})
+
+    //   Api.genericInterface({
+    //     func: 's_deepseek_ai',
+    //     rduri: burl + '/webapi/dostars',
+    //     file_url: '',
+    //     userid: UserID,
+    //     LoginUID: LoginUID,
+    //     u_id: sessionStorage.getItem('UserID'),
+    //     content: window.btoa(window.encodeURIComponent(_val)),
+    //     title: window.btoa(window.encodeURIComponent(chat.title)),
+    //     data_type: 'reply',
+    //     tokens_count: tokens_count,
+    //     version: type,
+    //     ID: chat.id
+    //   }).then(r => {
+    //     if (!r.status) {
+    //       notification.error({
+    //         top: 92,
+    //         message: r.message,
+    //         duration: 10
+    //       })
+    //     } else if (isNew) {
+    //       this.getList()
+    //     }
+    //   })
+    // })
+
+    // Api.genericInterface({
+    //   func: 's_deepseek_ai',
+    //   rduri: burl + '/webapi/dostars',
+    //   file_url: '',
+    //   userid: UserID,
+    //   LoginUID: LoginUID,
+    //   u_id: sessionStorage.getItem('UserID'),
+    //   content: window.btoa(window.encodeURIComponent(val)),
+    //   title: window.btoa(window.encodeURIComponent(chat.title)),
+    //   data_type: 'request',
+    //   version: type,
+    //   tokens_count: 0,
+    //   ID: chat.id
+    // }).then(result => {
+    //   if (!result.status) {
+    //     notification.error({
+    //       top: 92,
+    //       message: result.message,
+    //       duration: 10
+    //     })
+    //   }
+    // })
   }
 
   getAssistVal = (val) => {
@@ -595,10 +616,10 @@
   }
 
   render () {
-    const { loading, textInput, type, currentChat, chats } = this.state
+    const { loading, textInput, currentChat, chats, dpChat } = this.state
 
     let able = textInput && !/^\s+$/.test(textInput)
-    let empty = !currentChat.id
+    let empty = currentChat.list.length === 0
 
     return (
       <div className="mk-deepseek-wrap">
@@ -643,6 +664,7 @@
                     return <UserChat key={item.id} item={item}/>
                   }
                 })}
+                {dpChat ? <DpChat key='chat' item={dpChat}/> : null}
               </div> : null}
               {!empty ? <div className="chat-reset">
                 <div className="wrap" onClick={this.newContent}>
@@ -657,7 +679,7 @@
                       <TextArea id="mk-input" value={textInput} autoSize={{minRows: 2, maxRows: 12}} placeholder="缁� DeepSeek 鍙戦�佹秷鎭� " onChange={this.changeVal} onPressEnter={this.submit}/>
                     </div>
                     <div className="ec4f5d61">
-                      {type === 'deepseek-chat' ? <Tooltip placement="left" title="璋冪敤鏂版ā鍨� DeekSeek-R1锛岃В鍐虫帹鐞嗛棶棰�">
+                      {/* {type === 'deepseek-chat' ? <Tooltip placement="left" title="璋冪敤鏂版ā鍨� DeekSeek-R1锛岃В鍐虫帹鐞嗛棶棰�">
                         <div className="ds-button" onClick={this.changeType}>
                           <DeepSeekIcon/>
                           <span className="text">娣卞害鎬濊�� (R1)</span>
@@ -665,7 +687,7 @@
                       </Tooltip> : <div className="ds-button active" onClick={this.changeType}>
                         <DeepSeekIcon/>
                         <span className="text">娣卞害鎬濊�� (R1)</span>
-                      </div>}
+                      </div>} */}
                       {/* <div className="ds-button">
                         <span className="ds-icon">
                           <svg width="20" height="20" viewBox="0 0 20 20" fill="none"><circle cx="10" cy="10" r="9" stroke="currentColor" strokeWidth="1.8"></circle><path d="M10 1c1.657 0 3 4.03 3 9s-1.343 9-3 9M10 19c-1.657 0-3-4.03-3-9s1.343-9 3-9M1 10h18" stroke="currentColor" strokeWidth="1.8"></path></svg>

--
Gitblit v1.8.0