index1.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. const api_key = 'app-NvKwdHvEK2UmJdmjTGDR0xu6'
  2. const url = 'http://192.168.2.24/v1'
  3. export default {
  4. data() {
  5. return {
  6. controller:null,
  7. }
  8. },
  9. computed:{
  10. userinfo(){
  11. return this.$s.getObj('userinfo')
  12. }
  13. },
  14. methods: {
  15. async getResult(){
  16. if(!this.notice_file.guid){
  17. this.$message.warning('请先上传审查意见书')
  18. return
  19. }
  20. this.cancelRun()
  21. this.controller = new AbortController();
  22. let patent_fileUrls = {}
  23. // if(this.patent_fileUrls && this.patent_fileUrls.length){
  24. // this.patent_fileUrls.forEach(item=>{
  25. // patent_fileUrls[item.name] = item.guid
  26. // })
  27. // }
  28. if(this.relevant_file.contrast_file && this.relevant_file.contrast_file.length){
  29. this.relevant_file.contrast_file.forEach(item=>{
  30. if(item.file && item.file.guid){
  31. patent_fileUrls['D' + item.order + '-' + item.file.name] = item.file.guid
  32. }
  33. })
  34. }
  35. // var params = {
  36. // inputs:{
  37. // fileUrl:'http://192.168.2.24:8803/fileManager/downloadFile?fileId='+this.notice_file.guid,
  38. // patent_fileUrls:JSON.stringify(patent_fileUrls)
  39. // },
  40. // query:'OA答辩',
  41. // response_mode:'streaming',
  42. // user:this.userinfo.id
  43. // }
  44. // this.loading = true
  45. // this.result = null
  46. // const response = await fetch('https://ai.xsip.cn/v1/chat-messages', {
  47. // method: 'POST',
  48. // headers: {
  49. // 'Content-Type': 'application/json',
  50. // // 'Accept': 'text/event-stream',
  51. // 'Authorization': `Bearer ${api_key}`,
  52. // },
  53. // body:JSON.stringify(params),
  54. // signal: this.controller.signal
  55. // });
  56. var params = {
  57. confessionSessionId:this.currentConversation.id,
  58. patentFileUrls:JSON.stringify(patent_fileUrls),
  59. appFileGuid:this.relevant_file.app_file.guid,
  60. modifyFileGuid:this.relevant_file.modify_file.guid
  61. }
  62. this.loading = true
  63. this.loading_text = ''
  64. var loading_text = ''
  65. this.result = null
  66. const response = await fetch('/api/xiaoshi/dify/sendOADefense', {
  67. method: 'POST',
  68. headers: {
  69. 'Content-Type': 'application/json',
  70. 'Accept': 'text/event-stream',
  71. },
  72. body:JSON.stringify(params),
  73. signal: this.controller.signal
  74. });
  75. if (!response.ok) throw new Error('AI API 调用失败');
  76. const reader = response.body.getReader();
  77. const decoder = new TextDecoder('utf-8');
  78. let noFinishMessage = ''
  79. while (true) {
  80. const { done, value } = await reader.read();
  81. if (done){
  82. this.loading = false
  83. break;
  84. }
  85. const chunk = decoder.decode(value);
  86. const lines2 = chunk.split('\n\n').filter(line => line.trim() !== '' && line.trim() !== 'data:event: ping')
  87. for(const line of lines2){
  88. const jsonStr1 = line.replace(/^data:\s{0,}/, '');
  89. const jsonStr = jsonStr1.trim()
  90. if(jsonStr == 'event: ping' || jsonStr ==''){
  91. continue;
  92. }
  93. try {
  94. const json = JSON.parse(jsonStr);
  95. if(json.event == 'message'){
  96. let answer = json.answer
  97. try{
  98. let answer_json = JSON.parse(answer)
  99. if(answer_json.code == 1001){//缺少专利文件
  100. this.result = answer_json
  101. this.$refs.errorTip.open(answer_json)
  102. }else if(answer_json.code == 200){
  103. this.queryConfessionSession(false,false,true)
  104. }else if(answer_json.code == 1003){
  105. this.loading_text = answer_json.data
  106. loading_text = answer_json.data
  107. }
  108. }catch(e){
  109. if(loading_text!=''){
  110. loading_text = ''
  111. this.loading_text = ''
  112. }
  113. this.result += answer;
  114. }
  115. }else if(json.event == 'message_replace'){
  116. this.result = json.answer
  117. }else if(json.event == 'message_end'){
  118. }
  119. } catch (e) {
  120. if(jsonStr.indexOf('{') == 0){
  121. noFinishMessage = jsonStr
  122. }else{
  123. noFinishMessage += jsonStr
  124. if(jsonStr.lastIndexOf('}') == jsonStr.length - 1){
  125. try{
  126. const json = JSON.parse(noFinishMessage);
  127. if(json.event == 'message'){
  128. let answer = json.answer
  129. try{
  130. let answer_json = JSON.parse(answer)
  131. if(answer_json.code == 1001){//缺少专利文件
  132. this.result = answer_json
  133. this.$refs.errorTip.open(answer_json)
  134. }else if(answer_json.code == 1001){//请求超时
  135. this.result = answer_json
  136. }else if(answer_json.code == 200){
  137. this.queryConfessionSession(false,false,true)
  138. }else if(answer_json.code == 1003){
  139. this.loading_text = answer_json.data
  140. loading_text = answer_json.data
  141. }
  142. }catch(e){
  143. if(loading_text!=''){
  144. loading_text = ''
  145. this.loading_text = ''
  146. }
  147. this.result += answer;
  148. }
  149. }else if(json.event == 'message_replace'){
  150. this.result = json.answer
  151. }else if(json.event == 'message_end'){
  152. }
  153. }
  154. catch(e){
  155. console.error('解析响应数据出错:', e);
  156. }finally{
  157. noFinishMessage = ''
  158. }
  159. }
  160. }
  161. }
  162. }
  163. }
  164. },
  165. cancelRun(){
  166. if (this.controller) {
  167. this.controller.abort();
  168. }
  169. this.loading = false
  170. },
  171. //格式化AI答复
  172. formateAIAnswer(chat){
  173. let answer = chat.replace('null','')
  174. // let regx1 = /<think>[\s\S]*<\/think>/g
  175. // let regx2 = /<details style="color:gray;background-color: #f8f8f8;padding: 8px;border-radius: 4px;" open> <summary> Thinking... <\/summary>[\s\S]*<\/details>/g
  176. // // let regx1 = new RegExp("<think>.*</think>", "g")
  177. // // let regx2 = new RegExp('<details style="color:gray;background-color: #f8f8f8;padding: 8px;border-radius: 4px;" open> <summary> Thinking... </summary>.*</details>', "g")
  178. // let text = answer.replace(regx1,'').replace(regx2,'')
  179. // return [
  180. // {
  181. // type:'text',
  182. // content:text.trim()
  183. // }
  184. // ]
  185. let len = answer.length
  186. let signs = [
  187. {
  188. start:'<think>',
  189. end:'</think>'
  190. },
  191. {
  192. start:'<details style="color:gray;background-color: #f8f8f8;padding: 8px;border-radius: 4px;" open> <summary> Thinking... </summary>',
  193. end:'</details>'
  194. },
  195. ]
  196. let sign_obj = {}
  197. let start_index = -1
  198. let end_index = -1
  199. for(let i = 0;i<signs.length;i++){
  200. let item = signs[i]
  201. let index = answer.indexOf(item.start)
  202. if(index!=-1){
  203. sign_obj = item
  204. start_index = index
  205. end_index = answer.indexOf(item.end)
  206. break;
  207. }
  208. }
  209. var arr = []
  210. if(start_index == -1){
  211. let obj = {
  212. type:'text',
  213. content:answer.trim()
  214. }
  215. arr.push(obj)
  216. return arr
  217. }
  218. if(end_index == -1){
  219. let obj = {
  220. type:'text',
  221. content:answer.substring(0, start_index).trim()
  222. }
  223. arr.push(obj)
  224. obj = {
  225. type:'think',
  226. content:answer.substring(start_index + sign_obj.start.length,len).trim(),
  227. show:false
  228. }
  229. if(chat.id == this.currentMessage.id){
  230. obj.show = true
  231. }
  232. arr.push(obj)
  233. return arr
  234. }
  235. let obj = {
  236. type:'text',
  237. content:answer.substring(0, start_index).trim()
  238. }
  239. arr.push(obj)
  240. obj = {
  241. type:'think',
  242. show:false,
  243. content:answer.substring(start_index + sign_obj.start.length, end_index).trim()
  244. }
  245. arr.push(obj)
  246. obj = {
  247. type:'text',
  248. content:answer.substring(end_index + sign_obj.end.length,len).trim()
  249. }
  250. arr.push(obj)
  251. return arr
  252. },
  253. async copy(chat){
  254. let answerDomList = document.querySelectorAll('#answer')
  255. if(answerDomList.length == 0){
  256. return
  257. }
  258. let answerDom = answerDomList[answerDomList.length - 1]
  259. let answerHtml = answerDom.innerHTML
  260. let answer_text = answerDom.textContent || answerDom.innerText;
  261. if(navigator.clipboard && navigator.clipboard.write){
  262. // 复制复杂内容(纯文本 + HTML)
  263. navigator.clipboard.write([
  264. new ClipboardItem({
  265. 'text/html': new Blob([answerHtml], { type: 'text/html' }),
  266. 'text/plain': new Blob([answer_text], { type: 'text/plain' })
  267. })
  268. ]).then(() => {
  269. console.log('内容已复制到剪贴板');
  270. this.$message.success('复制成功');
  271. });
  272. return
  273. }
  274. let textArea = document.createElement("textarea");
  275. textArea.value = answer_text;
  276. // 防止滚动到页面底部
  277. textArea.style.top = "0";
  278. textArea.style.left = "0";
  279. textArea.style.position = "fixed";
  280. textArea.style.opacity = "0";
  281. document.body.appendChild(textArea);
  282. textArea.select();
  283. try {
  284. document.execCommand('copy');
  285. this.$message.success('复制成功');
  286. } catch (err) {
  287. this.$message.error('复制失败');
  288. }
  289. document.body.removeChild(textArea);
  290. },
  291. /**
  292. * 上传文件处理
  293. * */
  294. // 上传的文件监听
  295. onchangeFile(file, fileList) {
  296. if(!this.patent_fileUrls){
  297. this.$set(this,'patent_fileUrls',[])
  298. }
  299. if (file.guid) {
  300. let index = this.patent_fileUrls.findIndex(item => {
  301. return item.uid == file.uid
  302. })
  303. if (index != -1) {
  304. this.patent_fileUrls.splice(index, 1, file)
  305. }
  306. } else {
  307. this.patent_fileUrls.push(file.raw)
  308. }
  309. },
  310. // 删除上传的文件
  311. onRemove(file, fileList) {
  312. let index = this.patent_fileUrls.findIndex(item => {
  313. return item.uid == file.uid
  314. })
  315. if (index != -1) {
  316. this.patent_fileUrls.splice(index, 1)
  317. }
  318. },
  319. },
  320. }