zhuliu 3 mesi fa
parent
commit
a7c3e3401b

+ 2 - 2
src/components/VabOnlyOffice/index.vue

@@ -1,7 +1,7 @@
 <!--onlyoffice 编辑器-->
 <!--onlyoffice 编辑器-->
 <template>
 <template>
   <div style="height:100%;width:100%" v-loading="loading">
   <div style="height:100%;width:100%" v-loading="loading">
-    <div id='vabOnlyOffice' v-if="show"></div>
+    <div :id='"vabOnlyOffice" + option.key' v-if="show"></div>
   </div>
   </div>
  
  
 </template>
 </template>
@@ -201,7 +201,7 @@ import mixins from './index.js'
         }
         }
        
        
         // eslint-disable-next-line no-undef,no-unused-vars
         // eslint-disable-next-line no-undef,no-unused-vars
-        this.docEditor = new DocsAPI.DocEditor('vabOnlyOffice', config)
+        this.docEditor = new DocsAPI.DocEditor('vabOnlyOffice' + option.key, config)
       },
       },
       async onRequestHistory(event){
       async onRequestHistory(event){
         var params = {
         var params = {

File diff suppressed because it is too large
+ 339 - 80
src/views/AITools/OADefense/OADefense1.vue


+ 88 - 0
src/views/AITools/OADefense/dialog/errorTip.vue

@@ -0,0 +1,88 @@
+<template>
+    <div>
+      <el-dialog title="文件缺少提示" v-draggable :visible.sync="visible" width="500px" :before-close="handleClose" :close-on-click-modal="false" :modal-append-to-body="false">
+          <div>
+            <div style="font-size:16px" v-html="tip"></div>
+            <div style="padding: 10px 0;">
+                <div><b>请上传缺少的文件(申请文件和对比文件):</b></div>
+                <div style="font-size:12px;color:red">注:上传的文件名称要包含本申请文件或者对比文件名称</div>
+            </div>
+            <div>
+                <myUpload :file-list="patent_fileUrls" @on-change="onchangeFile" @on-remove="onRemove" style="height: 180px;" :autoUpload="true"></myUpload>
+            </div>
+          </div>
+        <span slot="footer" class="dialog-footer">
+          <el-button size="mini" @click="handleClose">取 消</el-button>
+          <el-button size="mini" type="primary" :loading="loading" @click="submit">再次运行</el-button>
+        </span>
+      </el-dialog>
+    </div>
+</template>
+  
+<script>
+  export default {
+    components: {},
+    props: {},
+    data() {
+      return {
+          visible:false,
+          loading:false,
+          tip:'',
+          patent_fileUrls:[]
+      };
+    },
+    watch: {},
+    computed: {},
+    created() {},
+    mounted() {},
+    methods: {
+        open(tip){
+            this.tip = tip.replace('\n','<br>')
+            this.$set(this,'patent_fileUrls',[])
+            this.visible = true
+        },
+        /**
+         * 上传文件处理
+         *  */
+        // 上传的文件监听
+        onchangeFile(file, fileList) {
+            if(!this.patent_fileUrls){
+                this.$set(this,'patent_fileUrls',[])
+            }
+            if (file.guid) {
+                let index = this.patent_fileUrls.findIndex(item => {
+                    return item.uid == file.uid
+                })
+                if (index != -1) {
+                    this.patent_fileUrls.splice(index, 1, file)
+                }
+            } else {
+                this.patent_fileUrls.push(file.raw)
+            }
+    
+        },
+        // 删除上传的文件
+        onRemove(file, fileList) {
+            let index = this.patent_fileUrls.findIndex(item => {
+                return item.uid == file.uid
+            })
+            if (index != -1) {
+                this.patent_fileUrls.splice(index, 1)
+            }
+        },
+        handleClose(){
+            this.visible = false
+        },
+        submit(){
+            if(this.patent_fileUrls.length == 0){
+                this.$message.warning('请上传缺少的相关文件后再运行!')
+                return
+            }
+            this.$emit('submit',this.patent_fileUrls)
+            this.handleClose()
+        },
+    },
+  };
+  </script>
+  <style lang="scss" scoped>
+  </style>

+ 1 - 1
src/views/AITools/OADefense/index.vue

@@ -5,7 +5,7 @@
 </template>
 </template>
   
   
 <script>
 <script>
-import OADefense from './OADefense.vue'
+import OADefense from './OADefense1.vue'
 export default {
 export default {
     components: {
     components: {
         OADefense
         OADefense

+ 71 - 40
src/views/AITools/OADefense/mixins/index1.js

@@ -1,9 +1,9 @@
 const api_key = 'app-NvKwdHvEK2UmJdmjTGDR0xu6'
 const api_key = 'app-NvKwdHvEK2UmJdmjTGDR0xu6'
-const url = 'https://ai.xsip.cn/v1'
+const url = 'http://192.168.2.24/v1'
 export default {
 export default {
     data() {
     data() {
         return {
         return {
-            controller:null
+            controller:null,
         }
         }
     },
     },
     computed:{
     computed:{
@@ -13,42 +13,63 @@ export default {
     },
     },
     methods: {
     methods: {
         async getResult(){
         async getResult(){
-            if(!this.confession.guid){
+            if(!this.notice_file.guid){
                 this.$message.warning('请先上传审查意见书')
                 this.$message.warning('请先上传审查意见书')
                 return
                 return
             }
             }
-            this.loading = true
-            this.result = null
+            
+            this.cancelRun()
+
             this.controller = new AbortController();
             this.controller = new AbortController();
+            let patent_fileUrls = {}
+            if(this.patent_fileUrls && this.patent_fileUrls.length){
+                this.patent_fileUrls.forEach(item=>{
+                    patent_fileUrls[item.name] = item.guid
+                })
+            }
+            // var params = {
+            //     inputs:{
+            //         fileUrl:'http://192.168.2.24:8803/fileManager/downloadFile?fileId='+this.notice_file.guid,
+            //         patent_fileUrls:JSON.stringify(patent_fileUrls)
+            //     },
+            //     query:'OA答辩',
+            //     response_mode:'streaming',
+            //     user:this.userinfo.id
+            // }
+            // this.loading = true
+            // this.result = null
+            // const response = await fetch('https://ai.xsip.cn/v1/chat-messages', {
+            //   method: 'POST',
+            //   headers: {
+            //     'Content-Type': 'application/json',
+            //     // 'Accept': 'text/event-stream',
+            //     'Authorization': `Bearer ${api_key}`,
+            //   },
+            //   body:JSON.stringify(params),
+            //   signal: this.controller.signal
+            // });
             var params = {
             var params = {
-                query:{
-                    fileUrl:this.confession.guid,
-                    patent_fileUrls:patent_fileUrls.map(item=>{
-                        return item.guid
-                    })
-                },
-                response_mode:'streaming',
-                user:this.userinfo.id
+                confessionSessionId:this.currentConversation.id,
+                patentFileUrls:JSON.stringify(patent_fileUrls)
             }
             }
-            const response = await fetch(url + '/chat-messages', {
-              method: 'POST',
-              headers: {
-                'Content-Type': 'application/json',
-                // 'Accept': 'text/event-stream',
-                'Authorization':'Bearer ' + api_key
-              },
-              data:JSON.stringify(params),
-              signal: this.controller.signal
-            });
+            this.loading = true
+            this.result = null
+            const response = await fetch('/api/xiaoshi/dify/sendOADefense', {
+                method: 'POST',
+                headers: {
+                  'Content-Type': 'application/json',
+                  'Accept': 'text/event-stream',
+                },
+                body:JSON.stringify(params),
+                signal: this.controller.signal
+              });
             if (!response.ok) throw new Error('AI API 调用失败');
             if (!response.ok) throw new Error('AI API 调用失败');
-            this.finish = false
             const reader = response.body.getReader();
             const reader = response.body.getReader();
             const decoder = new TextDecoder('utf-8');
             const decoder = new TextDecoder('utf-8');
             let noFinishMessage = ''
             let noFinishMessage = ''
             while (true) {
             while (true) {
                 const { done, value } = await reader.read();
                 const { done, value } = await reader.read();
                 if (done){
                 if (done){
-                    this.finish = true
                     this.loading = false
                     this.loading = false
                     break;
                     break;
                 } 
                 } 
@@ -63,16 +84,21 @@ export default {
                     try {
                     try {
                         const json = JSON.parse(jsonStr);
                         const json = JSON.parse(jsonStr);
                         if(json.event == 'message'){
                         if(json.event == 'message'){
-                            this.result += json.answer;
-                        }else if(json.event == 'message_replace'){
-                            this.result = json.answer
-                        }else if(json.event == 'text_chunk'){
-                            if(json.data){
-                               this.result += json.data.text; 
+                            let answer = json.answer
+                            try{
+                                let answer_json = JSON.parse(answer)
+                                if(answer_json.code == 1001){//缺少专利文件
+                                    this.$refs.errorTip.open(answer_json.data)
+                                }else if(answer_json.code == 200){
+                                    this.queryConfessionSession(false,false,true) 
+                                }
+                            }catch(e){
+                                this.result += answer;
                             }
                             }
                             
                             
-                        }else if(json.event == 'workflow_finished'){
-                            this.queryConfessionSession(false,false,true) 
+                        }else if(json.event == 'message_replace'){
+                            this.result = json.answer
+                        }else  if(json.event == 'message_end'){
                         }
                         }
                         
                         
                     } catch (e) {
                     } catch (e) {
@@ -84,15 +110,20 @@ export default {
                                 try{
                                 try{
                                     const json = JSON.parse(noFinishMessage);
                                     const json = JSON.parse(noFinishMessage);
                                     if(json.event == 'message'){
                                     if(json.event == 'message'){
-                                        this.result += json.answer;
+                                        let answer = json.answer
+                                        try{
+                                            let answer_json = JSON.parse(answer)
+                                            if(answer_json.code == 1001){//缺少专利文件
+                                                this.$refs.errorTip.open(answer_json.data)
+                                            }else if(answer_json.code == 200){
+                                                this.queryConfessionSession(false,false,true) 
+                                            }
+                                        }catch(e){
+                                            this.result += answer;
+                                        }
                                     }else if(json.event == 'message_replace'){
                                     }else if(json.event == 'message_replace'){
                                         this.result = json.answer
                                         this.result = json.answer
-                                    }else if(json.event == 'text_chunk'){
-                                        if(json.data){
-                                            this.result += json.data.text; 
-                                         }
-                                    }else if(json.event == 'workflow_finished'){
-                                        this.queryConfessionSession(false,false,true) 
+                                    }else if(json.event == 'message_end'){
                                     }
                                     }
                                 }
                                 }
                                 catch(e){
                                 catch(e){

+ 16 - 3
src/views/AITools/assistWritingInstruction/assistWritingInstruction.vue

@@ -69,7 +69,7 @@
                     <span>.</span>
                     <span>.</span>
                 </div>
                 </div>
             </div>
             </div>
-            <div class="result" v-else>
+            <div class="result" ref="AIMessage" v-else>
                 <!-- 结果 -->
                 <!-- 结果 -->
                 <template v-if="confession.guid">
                 <template v-if="confession.guid">
                     <div class="height_100" v-if="show">
                     <div class="height_100" v-if="show">
@@ -85,6 +85,9 @@
                         </div>
                         </div>
                     </div>
                     </div>
                 </template>
                 </template>
+                <div class="jiazai" v-if="result && result.length>0 && loading">
+                    <i class="el-icon-loading margin-left_10"></i>
+                </div>
             </div>
             </div>
         </div>
         </div>
     </div>
     </div>
@@ -95,6 +98,7 @@ import vabOnlyOffice from '@/components/VabOnlyOffice/index.vue'
 import  mixin  from './mixins/index.js';
 import  mixin  from './mixins/index.js';
 import conversationRecords from '../components/conversationRecords.vue';
 import conversationRecords from '../components/conversationRecords.vue';
 import { downLoad2 } from '@/utils'
 import { downLoad2 } from '@/utils'
+import { scrollToBottom } from '../components/mixins/scrollToBottom'
 const default_input = {
 const default_input = {
     claim:'',
     claim:'',
     background:''
     background:''
@@ -105,7 +109,7 @@ export default {
       vabOnlyOffice
       vabOnlyOffice
     },
     },
     props: {},
     props: {},
-    mixins:[mixin],
+    mixins:[mixin,scrollToBottom],
     data() {
     data() {
       return {
       return {
         title_obj:{
         title_obj:{
@@ -140,7 +144,11 @@ export default {
         confession:{},//文件信息
         confession:{},//文件信息
       };
       };
     },
     },
-    watch: {},
+    watch: {
+        result(){
+            this.scrollToBottom()
+        }
+    },
     computed: {},
     computed: {},
     created() {
     created() {
         this.getInit()
         this.getInit()
@@ -352,6 +360,11 @@ export default {
                     }
                     }
                 }
                 }
             }
             }
+            .jiazai{
+                display: flex;
+                align-items: center;
+                height: 20px;
+            }
         }
         }
         .loading-container{
         .loading-container{
             display: flex;
             display: flex;

+ 47 - 0
src/views/AITools/components/mixins/scrollToBottom.js

@@ -0,0 +1,47 @@
+export const scrollToBottom = {
+    data() {
+        return {
+            scrollLock:false,
+        }
+    },
+    mounted() {
+        // 添加滚动事件监听
+        const messageBox = this.$refs.AIMessage;
+        if (messageBox) {
+            messageBox.addEventListener('scroll', this.handleScroll);
+        }
+    },
+    beforeDestroy() {
+        // 移除滚动事件监听
+        const messageBox = this.$refs.AIMessage;
+        if (messageBox) {
+          messageBox.removeEventListener('scroll', this.handleScroll);
+        }
+    },
+    methods: {
+        // 监听滚动事件
+        async handleScroll() {
+            const messageBox = this.$refs.AIMessage;
+            if (!messageBox) return;
+            // 计算是否在底部附近(允许 100px 的误差)
+            const isNearBottom =  (messageBox.scrollHeight - messageBox.scrollTop - messageBox.clientHeight) < 50;
+            this.scrollLock = !isNearBottom;
+        },
+        //滚动到底端
+        scrollToBottom() {
+            if(this.scrollLock){
+                return
+            }
+            const container = this.$refs.AIMessage;
+            this.$nextTick(() => {
+                if (container) {
+                    // 使用平滑滚动效果
+                    container.scrollTo({
+                        top: container.scrollHeight,
+                        behavior: 'instant'
+                    });
+                }
+            });
+        }, 
+    },
+}

+ 1 - 0
src/views/login/compoments/resePassword.vue

@@ -73,6 +73,7 @@ export default {
   methods: {
   methods: {
     
     
     open() {
     open() {
+      this.form = {}
       this.visible = true
       this.visible = true
     },
     },
     sure() {
     sure() {