Ver código fonte

生成说明书

zhuliu 4 meses atrás
pai
commit
750a9a0e02

+ 7 - 0
src/api/newApi/AI.js

@@ -19,4 +19,11 @@ export default {
     generateClaimExplain(data) {
         return axios.post("/xiaoshi/dify/generateClaimExplain", data);
     },
+
+    /**
+     * 生成说明书
+     */
+    generateInstruction(data) {
+        return axios.post("/xiaoshi/dify/generateInstruction", data);
+    },
 }

+ 11 - 0
src/router/index.js

@@ -565,6 +565,17 @@ const routes = [
             },
             component: () => import('@/views/AITools/OADefense/index.vue'),
           },
+           //生成说明书
+           {
+            path: '/generateInstruction',
+            name: 'generateInstruction',
+            meta: {
+              title: '生成说明书',
+              sign: 'generateInstruction',
+              belong: 'AI',
+            },
+            component: () => import('@/views/AITools/assistWritingInstruction/index.vue'),
+          },
         ]
       },
       //任务模块

Diferenças do arquivo suprimidas por serem muito extensas
+ 372 - 0
src/views/AITools/assistWritingInstruction/assistWritingInstruction.vue


+ 26 - 0
src/views/AITools/assistWritingInstruction/index.vue

@@ -0,0 +1,26 @@
+<template>
+  <div class="height_100">
+    <assistWritingInstruction></assistWritingInstruction>
+  </div>
+</template>
+
+<script>
+import assistWritingInstruction from './assistWritingInstruction.vue';
+export default {
+  components: {
+    assistWritingInstruction
+  },
+  props: {},
+  data() {
+    return {
+    };
+  },
+  watch: {},
+  computed: {},
+  created() {},
+  mounted() {},
+  methods: {},
+};
+</script>
+<style lang="scss" scoped>
+</style>

+ 276 - 0
src/views/AITools/assistWritingInstruction/mixins/index.js

@@ -0,0 +1,276 @@
+
+export default {
+    data() {
+        return {
+            controller:null
+        }
+    },
+    computed:{
+        userinfo(){
+            return this.$s.getObj('userinfo')
+        }
+    },
+    methods: {
+        async getResult(){
+            if(this.loading){
+                this.$message.warning('请等当前执行完成')
+                return
+            }
+            if(!this.inputs.claim){
+                this.$message.warning('请输入权利要求')
+                return
+            }
+            if(!this.inputs.background){
+                this.$message.warning('请输入背景技术')
+                return
+            }
+            this.loading = true
+            this.show = false
+            this.result = []
+            this.confession = {}
+            this.controller = new AbortController();
+            var params = this.inputs
+            const response = await fetch('/api/xiaoshi/dify/generateInstruction', {
+              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 调用失败');
+            const reader = response.body.getReader();
+            const decoder = new TextDecoder('utf-8');
+            let noFinishMessage = ''
+            while (true) {
+                const { done, value } = await reader.read();
+                if (done){
+                    this.loading = false
+                    break;
+                } 
+                const chunk = decoder.decode(value);
+                const lines2 = chunk.split('\n\n').filter(line => line.trim() !== '' && line.trim() !== 'data:event: ping')
+                for(const line of lines2){
+                    const jsonStr1 = line.replace(/^data:\s{0,}/, '');
+                    const jsonStr = jsonStr1.trim()
+                    if(jsonStr == 'event: ping' || jsonStr ==''){
+                        continue;
+                    }
+                    try {
+                        const json = JSON.parse(jsonStr);
+                        if(json.event == 'all_start'){
+                        }else if(json.event == 'start'){
+                            this.result.push(
+                                {
+                                    field:json.field,
+                                    content:json.content,
+                                    title:this.title_obj[json.field],
+                                    state:'start'
+                                }
+                            )
+                        }else if(json.event == 'message'){
+                            let obj = this.result.find(item=>{
+                                return item.field == json.field
+                            })
+                            if(obj){
+                                obj.content += json.content.replace(/\n/g,'<br>')
+                            }
+                        }else if(json.event == 'end'){
+                            let obj = this.result.find(item=>{
+                                return item.field == json.field
+                            })
+                            if(obj){
+                                obj.state = 'end'
+                            }
+                            if(json.field == 'title'){
+                                this.currentConversation.id = json.id
+                                this.queryConfessionSession(1)
+                            }
+                        }else if(json.event == 'all_end'){
+                            this.queryConfessionSession(false,true)  
+                            this.loading = false
+                            break;
+                        }
+                        
+                    } catch (e) {
+                        if(jsonStr.indexOf('{') == 0){
+                            noFinishMessage = jsonStr
+                        }else{
+                            noFinishMessage += jsonStr
+                            if(jsonStr.lastIndexOf('}') == jsonStr.length - 1){
+                                try{
+                                    const json = JSON.parse(noFinishMessage);
+                                    if(json.event == 'all_start'){
+                                    }else if(json.event == 'start'){
+                                        this.result.push(
+                                            {
+                                                field:json.field,
+                                                content:json.content,
+                                                title:this.title_obj[json.field],
+                                                state:'start'
+                                            }
+                                        )
+                                    }else if(json.event == 'message'){
+                                        let obj = this.result.find(item=>{
+                                            return item.field == json.field
+                                        })
+                                        if(obj){
+                                            obj.content += json.content.replace(/\n/g,'<br>')
+                                        }
+                                    }else if(json.event == 'end'){
+                                        let obj = this.result.find(item=>{
+                                            return item.field == json.field
+                                        })
+                                        if(obj){
+                                            obj.state = 'end'
+                                        }
+                                        if(json.field == 'title'){
+                                            this.currentConversation.id = json.id
+                                            this.queryConfessionSession(1)
+                                        }
+                                    }else if(json.event == 'all_end'){
+                                        this.queryConfessionSession(false,true)  
+                                        this.loading = false
+                                        break;
+                                    }
+                                }
+                                catch(e){
+                                    console.error('解析响应数据出错:', e);
+                                }finally{
+                                    noFinishMessage = ''
+                                }
+                            }
+                        }
+                    }
+                    
+                }
+            }
+        },
+        formattedText(text) {
+            // 将<br>替换为<p>标签
+            return text.replace(/<br>/gi, '</p><p>').replace(/^<p>|<\/p>$/gi, '');
+        },
+        cancelRun(){
+            if (this.controller) {
+                this.controller.abort();
+            }
+            this.loading = false
+        },
+        //格式化AI答复
+        formateAIAnswer(chat){
+            let answer = chat.replace('null','')
+            let len = answer.length
+
+            let signs = [
+                {
+                    start:'<think>',
+                    end:'</think>'
+                },
+                {
+                    start:'<details style="color:gray;background-color: #f8f8f8;padding: 8px;border-radius: 4px;" open> <summary> Thinking... </summary>',
+                    end:'</details>'
+                },
+            ]
+            let sign_obj = {}
+            let start_index = -1
+            let end_index = -1
+
+            for(let i = 0;i<signs.length;i++){
+                let item = signs[i]
+                let index = answer.indexOf(item.start)
+                if(index!=-1){
+                    sign_obj = item
+                    start_index = index
+                    end_index = answer.indexOf(item.end)
+                    break;
+                }
+            }
+
+            var arr = []
+            if(start_index == -1){
+                let obj = {
+                    type:'text',
+                    content:answer.trim()
+                }
+                arr.push(obj)
+                return arr
+            }
+            if(end_index == -1){
+                let obj = {
+                    type:'text',
+                    content:answer.substring(0, start_index).trim()
+                }
+                arr.push(obj)
+                obj = {
+                    type:'think',
+                    content:answer.substring(start_index + sign_obj.start.length,len).trim(),
+                    show:false
+                }
+                if(chat.id == this.currentMessage.id){
+                    obj.show = true
+                }
+                arr.push(obj)
+                return arr
+            }
+            let obj = {
+                type:'text',
+                content:answer.substring(0, start_index).trim()
+            }
+            arr.push(obj)
+            obj = {
+                type:'think',
+                show:false,
+                content:answer.substring(start_index + sign_obj.start.length, end_index).trim()
+            }
+            arr.push(obj)
+            obj = {
+                type:'text',
+                content:answer.substring(end_index + sign_obj.end.length,len).trim()
+            }
+            arr.push(obj)
+            return arr
+
+        },
+        async copy(chat){
+            let answerDomList = document.querySelectorAll('#answer')
+    
+            if(answerDomList.length == 0){
+                return
+            }
+            let answerDom = answerDomList[answerDomList.length - 1]
+            let answerHtml = answerDom.innerHTML
+            let answer_text = answerDom.textContent || answerDom.innerText;
+            if(navigator.clipboard && navigator.clipboard.write){
+                // 复制复杂内容(纯文本 + HTML)
+                navigator.clipboard.write([
+                    new ClipboardItem({
+                        'text/html': new Blob([answerHtml], { type: 'text/html' }),
+                        'text/plain': new Blob([answer_text], { type: 'text/plain' })
+                    })
+                ]).then(() => {
+                    console.log('内容已复制到剪贴板');
+                    this.$message.success('复制成功');
+                });
+                return
+            }
+            
+            let textArea = document.createElement("textarea");
+            textArea.value = answer_text;
+            // 防止滚动到页面底部
+            textArea.style.top = "0";
+            textArea.style.left = "0";
+            textArea.style.position = "fixed";
+            textArea.style.opacity = "0";
+            document.body.appendChild(textArea);
+            textArea.select();
+            try {
+                document.execCommand('copy');
+                this.$message.success('复制成功');
+            } catch (err) {
+                this.$message.error('复制失败');
+            }
+            document.body.removeChild(textArea);
+        },
+    },
+}

+ 1 - 0
src/views/AITools/components/conversationRecords.vue

@@ -237,6 +237,7 @@ export default {
           }
           svg{
             min-width: 15px;
+            width: 15px;
             height: 15px;
           }
           .name{

+ 3 - 2
src/views/AITools/technicalDisclosure/technicalDisclosure.vue

@@ -627,13 +627,14 @@ export default {
           }
           svg{
             min-width: 15px;
+            width: 15px;
             height: 15px;
           }
           .name{
             // word-break: break-all;
             overflow: hidden;
-              white-space: nowrap;
-              text-overflow:ellipsis;
+            white-space: nowrap;
+            text-overflow:ellipsis;
             flex-grow: 1;
             margin-left: 6px;
             margin-right: 5px;

+ 1 - 0
src/views/layout/components/UserBar.vue

@@ -11,6 +11,7 @@
             <el-dropdown-item command="/technicalDisclosure">技术交底书解析</el-dropdown-item>
             <el-dropdown-item command="/claimsExplain">权利要求解释及有益效果</el-dropdown-item>
             <el-dropdown-item command="/OADefense">OA答辩</el-dropdown-item>
+            <el-dropdown-item command="/generateInstruction">生成说明书</el-dropdown-item>
           </el-dropdown-menu>
         </el-dropdown>
       </span>