Ver Fonte

第一阶段AI开发、理解技术交底书

zhuliu há 5 meses atrás
pai
commit
02b4e8b7bd

+ 35 - 0
src/api/newApi/noveltySearch.js

@@ -27,6 +27,11 @@ export default {
         return axios.post('/xiaoshi/noveltyProject/queryTechnicalCase', data)
     },
 
+    //修改发明点
+    updateInventionPoint(data){
+        return axios.post('/xiaoshi/noveltyProject/updateInventionPoint', data)
+    },
+
     //查询查新报告对比专利
     queryComparePatent(data){
         return axios.post('/xiaoshi/noveltyProject/queryNoveltyCompareLiterature', data)
@@ -115,4 +120,34 @@ export default {
     copyNoveltyMessage(data){
         return axios.post('/xiaoshi/noveltyProject/copyMessage', data)
     },
+
+
+    //上传技术交底书
+    addConfession(data){
+        return axios.post('/xiaoshi/noveltyProject/addConfession', data)
+    },
+    //查询技术交底书
+    queryConfession(params){
+        return axios.get('/xiaoshi/noveltyProject/queryConfession', {params})
+    },
+    //查询会话id
+    querySessionId(params){
+        return axios.get('/xiaoshi/dify/querySessionId', {params})
+    },
+    //查询历史会话
+    queryHistoryMessage(data){
+        return axios.post('/xiaoshi/dify/queryHistoryMessage', data)
+    },
+    //发送消息-技术交底书
+    chatMessage(data){
+        return axios.post('/xiaoshi/dify/chatMessage', data)
+    },
+    //停止响应
+    stopMessage(params){
+        return axios.get('/xiaoshi/dify/stopMessage', {params})
+    },
+    //生成发明点
+    generateInventionPoint(data){
+        return axios.post('/xiaoshi/dify/generateInventionPoint', data)
+    },
 };

Diff do ficheiro suprimidas por serem muito extensas
+ 553 - 72
src/components/xiaoshi_AI/index.vue


+ 1 - 1
src/config/index.js

@@ -4,7 +4,7 @@ export default {
     updateTime:'2023-08-04 08:00:00',
     specialDays:['05-12','09-18','12-13'],
     host: window.location.host,
-    url:process.env.NODE_ENV === 'production' ? 'https://xsip.cn' : 'http://192.168.2.105:8803',
+    url:process.env.NODE_ENV === 'production' ? 'https://xsip.cn' : 'http://192.168.2.24:8803',
     staticURL: process.env.NODE_ENV === 'production' ? 'https://xsip.cn/onlinePreview' : 'http://192.168.2.24:8879/onlinePreview',
     WebSocketPath: process.env.NODE_ENV === 'production' ? 'wss://xsip.cn' : 'ws://192.168.2.24:8879',
     WebSocketPathFMS: process.env.NODE_ENV === 'production' ? 'wss://xsip.cn' : 'ws://192.168.2.105:8803',

+ 11 - 0
src/router/index.js

@@ -522,6 +522,17 @@ const routes = [
             },
             component: () => import('@/views/noveltySearch/components/reuseResults/index.vue'),
           },
+          //理解技术交底书
+          {
+            path: '/technicalDisclosure',
+            name: 'technicalDisclosure',
+            meta: {
+              title: '理解技术交底书',
+              sign: 'technicalDisclosure',
+              belong: 'AllReport',
+            },
+            component: () => import('@/views/noveltySearch/components/technicalDisclosure/index.vue'),
+          }
         ]
       },
       //任务模块

+ 30 - 0
src/utils/markdown.js

@@ -0,0 +1,30 @@
+
+import MarkdownIt from 'markdown-it'
+
+function escapeHtml(text) {
+    return text
+      .replace(/&/g, '&')
+      .replace(/"/g, '"')
+      .replace(/'/g, ''')
+      .replace(/</g, '&lt;')
+      .replace(/>/g, '&gt;');
+}
+
+// 初始化 markdown-it
+const md = new MarkdownIt({
+    highlight: (str, lang) => {
+      // 返回一个占位符,后续会被替换为组件
+      return `<code-block language="${lang}" code="${escapeHtml(str)}"></code-block>`;
+    },
+    html: true, // 允许 HTML 标签
+    breaks: true,
+    linkify: true,
+});
+
+export function renderMarkdown(text) {
+    if(!text){
+      return '';
+    }
+    // 只渲染非代码块的文本
+    return md.render(text);
+}

+ 176 - 7
src/views/noveltySearch/components/dialog/inventionPoint/inventionPoint.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="inventionPointDialog" v-if="show2">
-    <div class="mini" :style="miniStyle" @click="changeDom('mini')" v-if="!show" v-drag="getPosition" ref="mini">查新</div>
-    <div class="plus" v-else v-drag2="getPosition" ref="plus" :style="plusStyle">
+    <div class="mini" :style="miniStyle" @click="changeDom('mini')" v-show="!show" v-drag="getPosition" ref="mini" :class="!show?'show':''">查新</div>
+    <div class="plus" v-show="show" v-drag2="getPosition" ref="plus" :style="plusStyle" :class="show?'show':''">
       <div class="head" ondragstart="return false">
         <div>{{ text }}</div>
         <div style="width: 20px; height: 20px">
@@ -11,7 +11,7 @@
       <div class="main">
         <div class="main_head" ondragstart="return false">
           <div>
-            <span style="font-size:12px">发明点:</span>
+            <span style="font-size:12px">技术交底书:</span>
             <el-button v-if="projectId" style="margin-left:10px" type="text" size="mini" @click="intoProject" >进入项目</el-button>
           </div>
           <div>
@@ -21,9 +21,34 @@
             <el-button  type="text"  size="mini"  :loading="loading" v-if="btns.indexOf(3)!=-1"  @click="submit(3)">保存</el-button>
           </div>
         </div>
+        <!-- 技术交底书 -->
+        <div class="confession">
+          <div v-if="confession.guid" class="confessionBox" :title="confession.originalName">
+            <div class="confessionName">{{ confession.originalName }}</div>
+            <div class="confessionBtn">
+              <el-button class="understandConfession" type="text" size="mini" @click="understandConfession">AI智能解析</el-button>
+              <!-- <el-button type="text" size="mini" @click="viewConfession">预览</el-button> -->
+              <el-button type="text" size="mini" @click="delConfession">删除</el-button>
+            </div>
+          </div>
+          <div v-else>
+            <el-upload
+                class="upload-demo"
+                ref="uploadConfession"
+                action="#"
+                :auto-upload="false"
+                :show-file-list="false"
+                :on-change="onChangeConfession"
+                :limit="1">
+                <el-button type="text" size="mini">点击上传</el-button>
+            </el-upload>
+          </div>
+        </div>
+        <!-- 发明点输入 -->
         <div class="main_input">
           <myRichText  type="textarea" v-model="technicalCase.inventionPoint"  resize="none" customStyle="height:220px;font-size: 14px;color:#606266" :rows="10"  placeholder="请输入发明点"></myRichText>
         </div>
+
         <div class="main_result" v-if="showResult">
           <div class="description">{{description[clickType]}}</div>
           <div class="result" v-loading="loading">
@@ -222,7 +247,8 @@ export default {
         3:'以下是根据您输入的发明点找到的可能相同的案件,您确认一下是否是相同案件,如果是请相同案件的点击“进入”按钮,如果没有相同的案件就点击“保存”按钮保存输入的发明点'
       },
       chooseContrastFile:[],
-      cWidth:document.body.clientWidth
+      cWidth:document.body.clientWidth,
+      confession:{}
     };
   },
   watch: {
@@ -312,8 +338,10 @@ export default {
         this.technicalCase={
           inventionPoint:'',
         }
+        this.confession = {}
         return
       }
+      this.getConfession()
       var params = {
         projectId:this.projectId
       }
@@ -327,6 +355,79 @@ export default {
         }
       })
     },
+    //查询报告的技术交底书
+    getConfession(){
+      var params = {
+        projectId:this.projectId
+      }
+      this.$api.queryConfession(params).then(response=>{
+        if(response.code == 200){
+          this.confession = response.data || {}
+        }
+      }).catch(error=>{
+        this.confession = {}
+      })
+    },
+    //上传技术交底书
+    onChangeConfession(file){
+        let formData = new FormData()
+        formData.append('sourceId',this.$constants.sourceId)
+        formData.append('files',file.raw)
+        var message = this.$message({
+            message: '文件上传中...',
+            type: 'warning',
+            duration:0
+        });
+        this.$api.uploadFile(formData).then(response=>{
+            if(response.code == 200){
+                let guid = response.data[0]
+                this.$refs.uploadConfession.clearFiles()
+                var params = {
+                  projectId:this.projectId,
+                  fileGuid:guid
+                }
+                this.$api.addConfession(params).then(response=>{
+                  if(response.code == 200){
+                    message.close()
+                    this.$message.success('文件上传成功')
+                    if(!this.projectId){
+                      this.$emit('getProjectId',response.data)
+                    }else{
+                      this.getConfession()
+                    }
+                  }
+                }).catch(error=>{
+                  message.close()
+                })
+            }
+        })
+    },
+    //理解技术交底书
+    understandConfession(){
+      let router = this.$router.resolve({
+          path: '/technicalDisclosure',
+          query: {
+            projectId: this.projectId,
+          }
+        })
+        window.open(router.href, '_blank')
+    },
+    //查看技术交底书
+    viewConfession(){},
+    //删除技术交底书
+    delConfession(){
+      var params = {
+        projectId:this.projectId,
+        fileGuid:''
+      }
+      this.$api.addConfession(params).then(response=>{
+        if(response.code == 200){
+          this.$message.success('文件删除成功')
+          this.getConfession()
+        }
+      }).catch(error=>{
+      })
+    },
     //选择关键词
     chooseKeyword(item) {
       var index = this.checkList.indexOf(item);
@@ -386,18 +487,25 @@ export default {
     // 保存发明点
     saveInventionPoint(){
       var params = this.technicalCase
+      var api = 'addOrUpdateTechnicalCase'
       if(this.projectId){
         params.projectId = this.projectId
+        api = 'updateInventionPoint'
       }
-      this.$api.addOrUpdateTechnicalCase(params).then(response=>{
+      this.$api[api](params).then(response=>{
         if(response.code == 200){
           this.$message.success('保存成功')
           if(!this.technicalCase.projectId){
             this.$emit('getProjectId',response.data.projectId)
           }
           this.$emit('updateInventionPoint')
-          this.technicalCase.technicalCaseId = response.data.technicalCaseId
-          this.technicalCase.projectId = response.data.projectId
+          if(response.data.technicalCaseId){
+            this.technicalCase.technicalCaseId = response.data.technicalCaseId
+          }
+          if(response.data.projectId){
+            this.technicalCase.projectId = response.data.projectId
+          }
+          
         }
       }).catch(error=>{
         this.$message.error('保存失败')
@@ -436,6 +544,7 @@ export default {
 <style lang="scss" scoped>
 .inventionPointDialog {
   z-index: 99999;
+  
   .mini {
     position: fixed;
     // top: 0;
@@ -450,6 +559,10 @@ export default {
     font-weight: bold;
     cursor: pointer;
     box-shadow: 0 1px 3px rgba(0, 0, 0, .3);
+    opacity: 0;
+    transform: scale(2);
+    visibility: hidden;
+    transition: opacity  0.5s ease,transform 0.5s ease;
   }
   .plus {
     padding: 10px;
@@ -460,6 +573,10 @@ export default {
     width: 350px;
     height: auto;
     border-radius: 10px;
+    opacity: 0;
+    transform: scale(0.1);
+    visibility: hidden;
+    transition: opacity  0.5s ease,transform 0.5s ease;
     .head {
       width: 100%;
       display: flex;
@@ -478,6 +595,53 @@ export default {
         align-items: center;
         line-height: 30px;
       }
+
+      .confession{
+        margin: 0 0 10px 0;
+        .confessionBox{
+          display: flex;
+          align-items: center;
+          justify-content: space-between;
+          flex-wrap: nowrap;
+          .confessionBtn{
+            // width:0;
+            // height: 0;
+            // opacity: 0;
+            // pointer-events: none;
+            .understandConfession{
+              font-size: 15px;
+              background: linear-gradient(to right, blue, red);
+              -webkit-background-clip: text;
+              color: transparent;
+            }
+          }
+          .confessionName{
+            font-size: 12px;
+            flex:1;
+            // width:calc(100% - 1px);
+            width:calc(100% - 30px);
+            line-height:28px;
+            overflow: hidden;
+            white-space: nowrap;
+            text-overflow:ellipsis;
+          }
+          &:hover{
+            // color:#66b1ff;
+            transform: scale(1.02) translateY(-2px);
+            transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 1.94);
+            // &> .confessionName{
+            //   width:calc(100% - 30px);
+            // }
+          }
+          // &:hover> .confessionBtn{
+          //   width:auto;
+          //   height: auto;
+          //   opacity: 1;
+          //   pointer-events: all;
+          // }
+        }
+      }
+
       .main_result {
         margin-top: 20px;
         background: white;
@@ -512,5 +676,10 @@ export default {
       }
     }
   }
+  .show{
+    opacity: 1;
+    transform: scale(1) ;
+    visibility: visible ;
+  }
 }
 </style>

+ 7 - 1
src/views/noveltySearch/components/noveltySearchCard.vue

@@ -30,7 +30,7 @@
                     </div>
                     <el-form label-width="100px">
                         <el-form-item label="发明点:">
-                              <div v-html="item.inventionPoint"></div>
+                              <div class="inventionPoint" v-html="item.inventionPoint"></div>
                         </el-form-item>
                         <el-form-item label="创建人:">
                               <div v-html="item.createName"></div>
@@ -313,6 +313,12 @@ import createNoveltySearch from './dialog/createNoveltySearch.vue';
     color: #958b8b8c;
     font-size: 20px;
   }
+  .box-card{
+    .inventionPoint{
+      max-height: 200px;
+      overflow-y: auto;
+    }
+  }
   </style>
   <style lang="scss">
     .box-card{

+ 30 - 0
src/views/noveltySearch/components/technicalDisclosure/index.vue

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

+ 248 - 0
src/views/noveltySearch/components/technicalDisclosure/technicalDisclosure.vue

@@ -0,0 +1,248 @@
+<template>
+  <div class="technicalDisclosure">
+    <!-- 左侧文件展示 -->
+    <div class="left" v-loading="loading">
+        <template v-if="show">
+            <vabOnlyOffice :option='option'></vabOnlyOffice>
+        </template>
+    </div>
+    <!-- 中间的线 -->
+    <div class="line"></div>
+    <!-- 右侧发明点和对话框 -->
+    <div class="right">
+        <div class="inventionPoint">
+            <span style="font-size:12px">
+              <span class="cursor_pointer">
+                <i v-if="!showInventionPoint" class="el-icon-caret-right" @click="showInventionPoint = !showInventionPoint"></i>
+                <i v-else class="el-icon-caret-bottom" @click="showInventionPoint = !showInventionPoint"></i>
+              </span>
+              发明点:
+            </span>
+            <myRichText v-loading="loading2" v-show="showInventionPoint" type="textarea" v-model="technicalCase.inventionPoint" @change="saveInventionPoint"  resize="none" customStyle="height:150px;font-size: 14px;color:#606266" :rows="10"  placeholder="请输入发明点"></myRichText>
+        </div>
+        <div class></div>
+        <div class="AIChat" v-if="showChat">
+            <xiaoshiAI :chat_id="chat_id" @noChatId="generateInventionPoint"></xiaoshiAI>
+        </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import vabOnlyOffice from '@/components/VabOnlyOffice/index.vue'
+import xiaoshiAI from '@/components/xiaoshi_AI'
+export default {
+  components: {
+    vabOnlyOffice,
+    xiaoshiAI
+  },
+  props: {
+    projectId:{}
+  },
+  data() {
+    return {
+        technicalCase:{},
+        confession:{},
+        //参考vabOnlyOffice组件参数配置
+        option: {
+            url: '',
+            isEdit: true,
+            fileType: '',
+            title: '',
+            lang: 'zh-CN',
+            isPrint: true,
+            user: {
+                id: this.$s.getObj('userinfo').id,
+                name: this.$s.getObj('userinfo').name
+            }
+        },
+        show:false,
+        loading:false,
+        chat_id:'',
+        loading2:false,
+        showChat:false,
+        showInventionPoint:true
+    };
+  },
+  watch: {
+    projectId(){
+        this.getInit()
+    },
+  },
+  computed: {},
+  created() {
+    this.getInit()
+  },
+  mounted() {
+    
+  },
+  methods: {
+    async getInit(){
+        if(!this.projectId){
+            this.technicalCase={
+                inventionPoint:'',
+            }
+            this.$message.warning('网页参数错误')
+            return
+        }
+        //获取技术交底书
+        this.getConfession()
+        //获取发明点
+        await this.getTechnicalCase()
+        this.showChat = true
+    },
+    //生成发明点
+    generateInventionPoint(){
+      if(this.technicalCase && this.technicalCase.inventionPoint){
+        return
+      }
+      var params = {
+        conversationId:null,
+        projectId:this.projectId
+      }
+      this.loading2 = true
+      this.$api.generateInventionPoint(params).then(response=>{
+        if(response.code == 200 && response.data){
+          if(response.data.invention_point){
+            let invention_point = response.data.invention_point
+            this.$set(this.technicalCase,'inventionPoint',invention_point)
+          }
+          // if(response.data.conversation_id){
+          //   this.$set(this,'chat_id',response.data.conversation_id)
+          // }
+          this.loading2 = false
+        }
+      }).catch(error=>{
+        this.loading2 = false
+      })
+    },
+    //获取发明点
+    async getTechnicalCase(){
+        var params = {
+            projectId:this.projectId
+        }
+        await this.$api.queryTechnicalCase(params).then(response=>{
+            if(response.code == 200){
+                this.technicalCase = response.data || {}
+            }
+        }).catch(error=>{
+            this.technicalCase={
+                inventionPoint:'',
+            }
+        })
+    },
+    // 保存发明点
+    saveInventionPoint(){
+      var params = this.technicalCase
+      if(this.projectId){
+        params.projectId = this.projectId
+      }
+      this.$api.updateInventionPoint(params).then(response=>{
+        if(response.code == 200){
+          if(!this.technicalCase.projectId){
+            this.$emit('getProjectId',response.data.projectId)
+          }
+          if(response.data.technicalCaseId){
+            this.technicalCase.technicalCaseId = response.data.technicalCaseId
+          }
+          if(response.data.projectId){
+            this.technicalCase.projectId = response.data.projectId
+          }
+        }
+      }).catch(error=>{
+        this.$message.error('发明点保存失败')
+      })
+    },
+    
+    getConfession(){
+      var params = {
+        projectId:this.projectId
+      }
+      this.loading = true
+      this.$api.queryConfession(params).then(response=>{
+        if(response.code == 200){
+          this.confession = response.data || {}
+          this.getOption()
+          this.loading = false
+        }
+      }).catch(error=>{
+        this.confession = {}
+        this.loading = false
+      })
+    },
+    getOption(){
+        if(!this.confession.guid){
+            this.$message.warning('技术交底书不存在')
+            return 
+        }
+        this.option.name = this.confession.originalName
+        this.option.id = this.confession.guid
+        this.option.title = this.confession.originalName
+        this.option.url = this.$c.url+ (this.$c.env=='production'?'/api':'')+'/fileManager/downloadFile?fileId=' + this.confession.guid
+        this.option.fileType = this.confession.type
+        this.option.key = this.confession.guid
+        
+        this.option.model = 'view'
+        this.$nextTick(()=>{
+            this.show = true
+        })
+        
+        // this.option.token = optionTemp.token
+    },
+  },
+};
+</script>
+<style lang="scss">
+  .technicalDisclosure{
+    .right{
+      .el-loading-spinner::after {
+        content: "正在生成发明点";
+        color: gray;
+        margin-top: 20px;
+        display: block;
+      }
+    }
+    
+  }
+</style>
+<style lang="scss" scoped>
+.technicalDisclosure{
+    display: flex;
+    align-items: stretch;
+    height: calc(100% - 20px);
+    width:calc(100% - 20px);
+    padding: 10px;
+    .left{
+        width:65%;
+        height:100%;
+        padding-right: 10px;
+        text-align: center;
+        &:empty::after{
+            content: "暂无技术交底书";
+            color:#c2c5c9;
+        }
+    }
+    .line{
+        width:2px;
+        height: 100%;
+        background: #e6e6e6;
+    }
+    .right{
+        width:calc(100% - 65% - 2px);
+        height:100%;
+        padding-left: 10px;
+        display: flex;
+        flex-direction: column;
+        .inventionPoint{
+            max-height: 190px;
+            padding-bottom: 9px;
+            border-bottom: 1px dashed;
+        }
+        .AIChat{
+            flex: 1;
+            margin-top: 10px;
+            height: calc(100% - 190px - 10px);
+        }
+    }
+}
+</style>