5 Commits 14eb78bff7 ... 5a9015a5e0

Autore SHA1 Messaggio Data
  zhuliu 5a9015a5e0 技术交底书理解升级 3 settimane fa
  zhuliu 1934cf2eb1 Merge branch 'product' into modelDesign 3 settimane fa
  zhuliu 43907f23c0 上传进度显示 3 settimane fa
  zhuliu 2119fdab20 导出官方无效报告 3 settimane fa
  zhuliu 8aa3110a83 导出报告 3 settimane fa

+ 24 - 2
src/api/newApi/file.js

@@ -1,8 +1,30 @@
 import axios from "@/utils/axios";
+import {showModal} from '@/utils/model/progress/index'
 // 新系统文件新接口
 export default {
-  uploadFile(data){
-    return axios.post('/fileManager/uploadNormalFile', data)
+  uploadFile(data,uploadProgress){
+    let ProgressModalControl = null
+    return axios.post('/fileManager/uploadNormalFile', data,{
+      onUploadProgress: progressEvent => { 
+        if (progressEvent.total) {  
+          const percent = Math.round((progressEvent.loaded * 100) / progressEvent.total);  
+          if (typeof uploadProgress === 'function') {  
+            uploadProgress(percent);  
+          }else{
+            if(percent == 0){
+              ProgressModalControl = showModal()
+            }
+            if(ProgressModalControl){
+              ProgressModalControl.update(percent)
+              if(percent == 100){
+                ProgressModalControl.hide()
+              }
+            }
+            
+          }
+        }  
+      } 
+    })
   },
   downLoadFile(params, prop = {}) {
     return axios.get('/fileManager/downloadFile', {params},prop)

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

@@ -876,4 +876,11 @@ updateSupplyEvidence(data) {
   queryStatuesVOS(data) {
     return axios.post("/xiaoshi/invalidStatutes/queryStatuesVOS", data);
   },
+  /**
+    * 官方无效-韶音
+    * 导出报告清单
+  */
+  exportReportList(data) {
+    return axios.post("/xiaoshi/reportExport/exportReportList", data,{responseType:'blob'});
+  },
 };

+ 13 - 7
src/components/xiaoshi_AI/index.vue

@@ -135,16 +135,18 @@ export default {
         type:String,
         default:'app-DDGJt4QUmzlc2aFQ5voOAXIj'
     },
+    AItype:{
+        type:Number,
+        default:0
+    },
     chatApi:{
         type:String,
         default:'/api/xiaoshi/dify/chatMessage'
     },
     slotDataFunction:{
         type:Function,
-        default:()=>{
-            return (val)=>{
-                return val
-            }
+        default:(val)=>{
+            return val
         }
     }
   },
@@ -185,7 +187,7 @@ export default {
             this.queryChatHistory.has_more = true
             this.getChatHistory(1)
         }else{
-            this.chatHistory = []
+            this.$set(this,'chatHistory',[])
         }
     }
   },
@@ -316,6 +318,7 @@ export default {
         }
         var params = {
             conversationId:this.conversationId,
+            type:this.AItype,
             ...this.queryChatHistory
         }
         await this.$api.queryHistoryMessage(params).then(response=>{
@@ -414,7 +417,8 @@ export default {
           signal: this.controller.signal
         });
         if (!response.ok) throw new Error('AI API 调用失败');
-        
+        this.showHistory = true
+        this.$emit('getShowHistory',this.showHistory)
         const reader = response.body.getReader();
         const decoder = new TextDecoder('utf-8');
         var messageId = ''
@@ -560,7 +564,8 @@ export default {
         }
         if(this.currentTaskId){
             var params = {
-                taskId:this.currentTaskId
+                taskId:this.currentTaskId,
+                type:this.AItype
             }
             this.$api.stopMessage(params).then(response=>{
                 if(response.code == 200){
@@ -762,6 +767,7 @@ export default {
     --padding:20px;
     padding: var(--padding) 0;
     margin:0 auto;
+    min-width: 450px;
     width: calc(100% - 0px);
     height: calc(100% - var(--padding) - var(--padding));
     max-width: 720px;

+ 3 - 2
src/utils/axios.js

@@ -62,11 +62,12 @@ _axios.interceptors.response.use(
       loadingInstance.close()
     }
     let { code, message } = response.data
-    if(code != 0 && !code ){
+    
+    if (code === 200 || config.responseType === 'blob') {
       isRefreshing = false
       return response.data
     }
-    if (code === 200 || config.responseType === 'blob') {
+    if(code != 0 && !code ){
       isRefreshing = false
       return response.data
     }

+ 4 - 1
src/utils/index.js

@@ -22,7 +22,10 @@ export const downLoad = (data, fileName) => {
   element.setAttribute('download', fileName);
   document.body.appendChild(element);
   element.click();
-  document.body.removeChild(element);
+  setTimeout(() => {
+    document.body.removeChild(element);
+    URL.revokeObjectURL(objectUrl);
+  }, 100);
 }
 
 export const getFileName = (type) => {

+ 31 - 0
src/utils/model/progress/index.js

@@ -0,0 +1,31 @@
+import Vue from "vue";
+import ProgressModal from "./index.vue";
+
+// 创建弹窗的构造函数
+const ProgressModalConstructor = Vue.extend(ProgressModal);
+
+// 实例化弹窗
+let modalInstance = null;
+
+/**
+ * 打开弹窗
+ * @param {Object} options - 弹窗配置
+ */
+export function showModal(options = {}) {
+  // 创建实例
+  modalInstance = new ProgressModalConstructor({
+    propsData: {
+      fileName: options.fileName || ""
+    },
+  });
+ 
+  // 手动挂载到 DOM
+  modalInstance.$mount();
+  document.body.appendChild(modalInstance.$el);
+ 
+  // 显示弹窗
+  modalInstance.show();
+ 
+  // 返回实例,以便外部手动关闭
+  return modalInstance;
+}

+ 76 - 0
src/utils/model/progress/index.vue

@@ -0,0 +1,76 @@
+<template>
+  <div class="myProgress_model" v-if="visible">
+    <div class="myProgress_model_content">
+      <el-progress type="circle" :percentage="percentage" text-color="#ffffff" :format="format()"></el-progress>  
+    </div>
+    
+  </div>
+</template>
+
+<script>
+export default {
+  components: {},
+  props: {
+    fileName:{
+        type:String,
+        default:''
+    }
+  },
+  data() {
+    return {
+        percentage:0,
+        visible:false,
+    };
+  },
+  watch: {},
+  computed: {},
+  created() {},
+  mounted() {},
+  methods: {
+    format(){
+        return ()=>{return "文件上传中... "+ this.percentage + '%'}
+    },
+    show(){
+        this.visible = true
+    },
+    update(percent){
+        this.percentage = percent
+    },
+    hide(){
+        this.visible = false
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.myProgress_model {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  z-index: 9999;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  background: rgba(0,0,0,0.5);
+  .myProgress_model_content{
+    width: 150px;
+    height: 150px;
+    border-radius: 150px;
+    // background: white;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+  }
+}
+</style>
+<style lang="scss">
+    .myProgress_model{
+        .myProgress_model_content{
+            .el-progress__text{
+                color: white !important;
+            }
+        }
+    }
+</style>

+ 16 - 3
src/utils/model/upload/index.vue

@@ -44,7 +44,16 @@
                 }}</span>
               </div>
             </myTooltip>
-            <div class="type" v-if="autoUpload">{{ item.guid ? "已上传" : "待上传" }}</div>
+            <div class="type" v-if="autoUpload">
+              <div v-if="item.guid">
+                {{ item.guid ? "已上传" : "待上传" }}
+              </div>
+              <div v-else>
+                上传中... {{ percent }}%
+              </div>
+              
+              
+            </div>
             <div class="icon" @click="onRemove(item, fileList)">
               <i class="el-icon-close"></i>
             </div>
@@ -183,7 +192,8 @@ export default {
       exist2:[],
       showExist:false,
       dialogVisible:false,
-      show : false
+      show : false,
+      percent:''
     };
   },
   watch: {},
@@ -279,7 +289,10 @@ export default {
       let formData = new FormData()
       formData.append('sourceId',this.$constants.sourceId)
       formData.append('files',file.raw)
-      this.$api.uploadFile(formData).then(response=>{
+      this.percent = 0
+      this.$api.uploadFile(formData,(percent)=>{
+        this.percent = percent
+      }).then(response=>{
         if(response.code == 200){
           file.guid = response.data[0]
           file.raw.guid = response.data[0]

+ 237 - 84
src/views/AITools/technicalDisclosure/technicalDisclosure.vue

@@ -10,7 +10,7 @@
               <el-button size="mini" :type="showOption.showLeft?'success':'info'" @click="showOption.showLeft = !showOption.showLeft">{{showOption.showLeft?"隐藏":"显示"}}左侧</el-button>
               <el-button size="mini" :type="showOption.showRight?'success':'info'" @click="showOption.showRight = !showOption.showRight">{{showOption.showRight?"隐藏":"显示"}}右侧</el-button>
             </div>
-            <el-upload
+            <!-- <el-upload
               ref="uploadConfession"
               class="upload-demo"
               action="#"
@@ -19,17 +19,22 @@
               :on-change="onChangeConfession"
               :limit="1">
               <el-button type="primary" size="mini">切换技术交底书</el-button>
-            </el-upload>
+            </el-upload> -->
+            <el-button type="primary" size="mini" @click="addConversation">添加新会话</el-button>
           </div>
           <div class="topMenu_right">
-            <el-button type="primary" size="mini" v-if="!editTechnical" @click="changeEditTechnical()">修改</el-button>
-            <el-button type="primary" size="mini" v-else @click="changeEditTechnical()">完成</el-button>
-            <el-button type="info" size="mini" disabled>查新检索</el-button>
-            <el-button type="info" size="mini" disabled>辅助撰写说明书</el-button>
+            <el-button :type="styleShow=='style1'?'success':'info'" size="mini" @click="styleShow='style1'">样式一</el-button>
+            <el-button :type="styleShow=='style2'?'success':'info'" size="mini" @click="styleShow='style2'">样式二</el-button>
+            <el-button :type="styleShow=='style3'?'success':'info'" size="mini" @click="styleShow='style3'">样式三</el-button>
+
+            <el-button type="primary" size="mini" v-if="!editTechnical" @click="changeEditTechnical()">编辑模式</el-button>
+            <el-button type="primary" size="mini" v-else @click="changeEditTechnical()">返回预览模式</el-button>
+            <el-button type="info" size="mini" @click="$message.info('敬请期待')">查新检索</el-button>
+            <el-button type="info" size="mini" @click="$message.info('敬请期待')">辅助撰写说明书</el-button>
 
           </div>
         </div>
-        <div class="technicalDisclosure_content">
+        <div :class="['technicalDisclosure_content',styleShow]">
           <!-- 左侧文件展示 -->
           <div class="left" v-loading="loading" v-show="showOption.showLeft" :style="!showOption.showRight?'width:calc(100% - 0px) !important':''">
               <template v-if="show">
@@ -42,6 +47,16 @@
           <div class="right" v-show="showOption.showRight" :style="!showOption.showLeft?'width:calc(100% - 0px) !important':''">
             <!-- 格式化技术交底书内容 -->
             <div class="mainContent">
+              <!-- 背景技术 -->
+              <div class="background_technology content_box">
+                <div class="title">背景技术</div>
+                <div v-if="!editTechnical">
+                  {{ technicalContent.background }}
+                </div>
+                <div v-else>
+                  <el-input type="textarea" v-model="editTechnicalContent.background" placeholder="请输入背景技术" @change="saveTechnicalContent"></el-input>
+                </div>
+              </div>
               <!-- 技术领域 --> 
               <div class="technical_field content_box">
                 <div class="title">技术领域</div>
@@ -60,7 +75,7 @@
                     <div class="delBtn">
                       <el-button class="delTextBtn" type="text" @click="delData('technicalCase',technicalContent.technicalCase,index)">删除技术问题</el-button>
                     </div>
-                    <div class="text"><span class="childTitle">技术问题:</span>{{ item.technicalProblem }}</div>
+                    <div class="text"><span class="childTitle">技术问题{{index+1}}:</span>{{ item.technicalProblem }}</div>
                     <div class="technical_means">
                       <div class="title">技术手段:</div>
                       <div v-for="(mean,inde) in item.technicalMeans" :key="'mean'+inde" class="technical_means_item">
@@ -193,30 +208,10 @@
                   </div>
                 </div>
               </div>
-              <!-- 背景技术 -->
-              <div class="background_technology content_box">
-                <div class="title">背景技术</div>
-                <div v-if="!editTechnical">
-                  {{ technicalContent.background }}
-                </div>
-                <div v-else>
-                  <el-input type="textarea" v-model="editTechnicalContent.background" placeholder="请输入背景技术" @change="saveTechnicalContent"></el-input>
-                </div>
-              </div>
-              <!-- 术语解释 -->
-              <div class="terminology_explanation content_box">
-                <div class="title">术语解释</div>
-                <div>
-                  <div v-for="(item,index) in technicalContent.termsExplanation" :key="index" class="terminology_explanation_item">
-                    <div class="childTitle">{{ item.terms }}</div>
-                    <div class="text">{{ item.explanation }}</div>
-                  </div>
-                </div>
-              </div>
               <!-- 布局建议 -->
               <div class="layout_suggestions content_box">
                 <div class="title">布局建议</div>
-                <div class="text">
+                <div class="text" v-if="technicalContent.claimSuggestions">
                   <p v-if="technicalContent.claimSuggestions.mainClaimSuggestions">
                     <span class="childTitle">独权建议:</span> {{technicalContent.claimSuggestions.mainClaimSuggestions}}
                   </p>
@@ -232,12 +227,24 @@
                   {{ technicalContent.additionalSuggestions || '无' }}
                 </div>
               </div>
+              
+              <!-- 术语解释 -->
+              <div class="terminology_explanation content_box">
+                <div class="title">术语解释</div>
+                <div>
+                  <div v-for="(item,index) in technicalContent.termsExplanation" :key="index" class="terminology_explanation_item">
+                    <div class="childTitle">{{ item.terms }}</div>
+                    <div class="text">{{ item.explanation }}</div>
+                  </div>
+                </div>
+              </div>
+              
               <!-- 空白 -->
               <div class="kongbai"></div>
             </div>
             <!-- AI对话框 -->
             <div class="AIChat" :style="showHistory?'height:100%':'height:auto'">
-              <xiaoshiAI style="width:100%;max-width:100%" :slotDataFunction="slotDataFunction" :chat_id="chat_id" :params="AIParams" :API_KEY="API_KEY" :chatApi="chat_api" :defaultShowHistory="showHistory" @getShowHistory="getShowHistory" @getConversationId="getConversationId">
+              <xiaoshiAI style="width:100%;max-width:100%" :AItype="4" :slotDataFunction="slotDataFunction" :chat_id="chat_id" :params="AIParams" :API_KEY="API_KEY" :chatApi="chat_api" :defaultShowHistory="showHistory" @getShowHistory="getShowHistory" @getConversationId="getConversationId">
                 <template slot="questionBtn">
                   <div>
                     <el-button size="mini" :type="AIModel=='chat'?'success':'info'" round @click="changeAIModel('chat')">AI对话</el-button>
@@ -246,6 +253,13 @@
                 </template>
                 <template v-if="AIModel == 'edit'" v-slot:answer="data">
                   <div class="mainContent">
+                     <!-- 背景技术 -->
+                    <div class="background_technology content_box">
+                      <div class="title">背景技术</div>
+                      <div>
+                        {{ data.data.background }}
+                      </div>
+                    </div>
                     <!-- 技术领域 --> 
                     <div class="technical_field content_box">
                       <div class="title">技术领域</div>
@@ -302,27 +316,10 @@
                         </div>
                       </div>
                     </div>
-                    <!-- 背景技术 -->
-                    <div class="background_technology content_box">
-                      <div class="title">背景技术</div>
-                      <div>
-                        {{ data.data.background }}
-                      </div>
-                    </div>
-                    <!-- 术语解释 -->
-                    <div class="terminology_explanation content_box">
-                      <div class="title">术语解释</div>
-                      <div>
-                        <div v-for="(item,index) in data.data.termsExplanation" :key="index" class="terminology_explanation_item">
-                          <div class="childTitle">{{ item.terms }}</div>
-                          <div class="text">{{ item.explanation }}</div>
-                        </div>
-                      </div>
-                    </div>
-                    <!-- 布局建议 -->
+                   <!-- 布局建议 -->
                     <div class="layout_suggestions content_box">
                       <div class="title">布局建议</div>
-                      <div class="text">
+                      <div class="text" v-if="data.data.claimSuggestions">
                         <p v-if="data.data.claimSuggestions.mainClaimSuggestions">
                           <span class="childTitle">独权建议:</span> {{data.data.claimSuggestions.mainClaimSuggestions}}
                         </p>
@@ -338,10 +335,21 @@
                         {{ data.data.additionalSuggestions || '无' }}
                       </div>
                     </div>
+                    <!-- 术语解释 -->
+                    <div class="terminology_explanation content_box">
+                      <div class="title">术语解释</div>
+                      <div>
+                        <div v-for="(item,index) in data.data.termsExplanation" :key="index" class="terminology_explanation_item">
+                          <div class="childTitle">{{ item.terms }}</div>
+                          <div class="text">{{ item.explanation }}</div>
+                        </div>
+                      </div>
+                    </div>
+                    
                   </div>
                 </template>
                 <template v-if="AIModel == 'edit'"  v-slot:messageBtn="data">
-                  <div @click="ying">
+                  <div @click="applyResults(data.data)">
                     应用
                   </div>
                 </template>
@@ -470,7 +478,8 @@ export default {
         editTechnicalContent:{},
         editTechnical:false,
         showHistory:false,
-        AIModel:'chat'
+        AIModel:'chat',
+        styleShow:'style1'
     };
   },
   watch: {
@@ -484,15 +493,12 @@ export default {
     
   },
   methods: {
-    slotDataFunction(){
-      return (val)=>{
-        let obj = {}
-        try{
-          obj = JSON.parse(val)
-        }catch{}
-        return obj
-      }
-      
+    slotDataFunction(val){
+      let obj = {}
+      try{
+        obj = JSON.parse(val)
+      }catch{}
+      return obj
     },
     getShowHistory(val){
       this.showHistory = val
@@ -501,8 +507,10 @@ export default {
       this.AIModel = val
       if(this.AIModel == 'chat'){
         this.chat_id = this.currentConversation.dialogueConversationId
+        this.AIParams.type = 31
       }else if(this.AIModel == 'edit'){
         this.chat_id = this.currentConversation.aiUpdateConversationId
+        this.AIParams.type = 32
       }
     },
     addData(field,parentData){
@@ -532,19 +540,46 @@ export default {
     },
     delData(field,parentData,index){
       parentData.splice(index,1)
+      this.saveTechnicalContent()
+    },
+    applyResults(data){
+      var params = {
+        confessionSessionId:this.currentConversation.id,
+        discoveryResult:JSON.stringify(data)
+      }
+      this.$api.updateDiscoveryResult(params).then(response=>{
+        if(response.code == 200){
+          this.$message.success('应用成功')
+          this.technicalContent = data
+          if(this.editTechnical){
+            this.editTechnicalContent = JSON.parse(JSON.stringify(data))
+          }
+        }
+      }).catch(error=>{
+        
+      })
     },
     saveTechnicalContent(){
       var params = {
         confessionSessionId:this.currentConversation.id,
-        discoveryResult:JSON.stringify(this.editTechnicalContent)
+      }
+      if(this.editTechnical){
+        params.discoveryResult = JSON.stringify(this.editTechnicalContent)
+      }else{
+        params.discoveryResult = JSON.stringify(this.technicalContent)
       }
       this.$api.updateDiscoveryResult(params).then(response=>{
         if(response.code == 200){
           this.$message.success('修改成功')
-          this.technicalContent = JSON.parse(JSON.stringify(this.editTechnicalContent))
+          if(this.editTechnical){
+            this.technicalContent = JSON.parse(JSON.stringify(this.editTechnicalContent))
+          }
         }
       }).catch(error=>{
-        this.editTechnicalContent = JSON.parse(JSON.stringify(this.technicalContent))
+        if(this.editTechnical){
+          this.editTechnicalContent = JSON.parse(JSON.stringify(this.technicalContent))
+        }
+        
       })
       
     },
@@ -596,13 +631,14 @@ export default {
       this.queryConfessionSession(true)
     },
     //切换会话
-    async changeConversation(obj){
+    async changeConversation(obj,generate){
       if(obj.id == this.currentConversation.id){
         this.currentConversation = obj
         return
       }
       this.currentConversation = obj
       this.AIParams.confessionSessionId = obj.id
+      this.chat_id = ''
       if(this.AIModel == 'chat'){
         this.AIParams.type = 31
       }else if(this.AIModel == 'edit'){
@@ -611,6 +647,8 @@ export default {
       this.$set(this,'addNewConversation',false)
       if(!this.currentConversation.discoveryResult){
         await this.getDiscoveryResultDetail()
+      }else{
+        this.changeAIModel(this.AIModel)
       }
       if(this.currentConversation.discoveryFiles && this.currentConversation.discoveryFiles.length){
         this.confession = this.currentConversation.discoveryFiles[0]
@@ -618,8 +656,32 @@ export default {
         this.confession = {}
       }
       this.getOption()
+      if(generate){
+        this.generateDiscoveryResult()
+      }
       
     },
+    async generateDiscoveryResult(){
+      let params = {
+        confessionSessionId:this.currentConversation.id
+      }
+      this.generateLoading = true
+      const loading = this.$loading({
+        lock: true,
+        text: '技术交底书信息提取中...',
+        spinner: 'el-icon-loading',
+        background: 'rgba(0, 0, 0, 0.7)'
+      });
+      await this.$api.generateDiscoveryResult(params).then(response=>{
+        if(response.code == 200){
+          this.currentConversation.discoveryResult = response.data
+          this.technicalContent=response.data
+          loading.close();
+        }
+      }).catch(error=>{
+        loading.close();
+      })
+    },
      //上传技术交底书
      onChangeConfession(file){
         let formData = new FormData()
@@ -636,7 +698,7 @@ export default {
               this.$refs.uploadConfession.clearFiles()
               var params = {
                 fileGuid:guid,
-                type:3
+                type:4
               }
               this.$api.addConfessionSession(params).then(response=>{
                 if(response.code == 200){
@@ -644,7 +706,7 @@ export default {
                   this.$message.success('文件上传成功')
                   
                   //查询技术交底书会话记录
-                  this.queryConfessionSession()
+                  this.queryConfessionSession(false,true)
                 }
               }).catch(error=>{
                 message.close()
@@ -653,16 +715,16 @@ export default {
         })
     },
     //查询技术交底书会话记录
-    queryConfessionSession(onlyQuery){
+    queryConfessionSession(onlyQuery,generate){
       var params = {
-        type:3
+        type:4
       }
       this.$api.queryConfessionSession(params).then(response=>{
         if(response.code == 200){
           this.confessionSessionList = response.data || []
           if(!onlyQuery && this.confessionSessionList.length>0){
             let obj = this.confessionSessionList[0]
-            this.changeConversation(obj)
+            this.changeConversation(obj,generate)
           }else if(this.confessionSessionList.length==0){
             this.currentConversation = {}
             this.AIParams.confessionSessionId = null
@@ -745,15 +807,15 @@ export default {
           this.changeAIModel(this.AIModel)
         }
       }).catch(error=>{
-        // this.technicalContent = {
-        //   technicalField:'',
-        //   technicalCase:[],
-        //   technicalFeature:[],
-        //   background:'',
-        //   termsExplanation:[],
-        //   claimSuggestions:{},
-        //   additionalSuggestions:''
-        // }
+        this.technicalContent = {
+          technicalField:'',
+          technicalCase:[],
+          technicalFeature:[],
+          background:'',
+          termsExplanation:[],
+          claimSuggestions:{},
+          additionalSuggestions:''
+        }
       })
     },
 
@@ -801,7 +863,7 @@ export default {
       height: calc(100% - 40px);
     }
     .left{
-        width:40%;
+        width:45%;
         height:calc(100% - 0px);
         padding-right: 10px;
         text-align: center;
@@ -836,7 +898,7 @@ export default {
         background: #e6e6e6;
     }
     .right{
-      width:calc(100% - 40% - 2px);
+      width:calc(100% - 45% - 2px);
       min-width: 450px;
       height:100%;
       padding-left: 10px;
@@ -845,9 +907,12 @@ export default {
       position: relative;
       .mainContent{
         width: calc(100% - 10px);
+        min-width: 400px;
         padding:0 10px;
         height:calc(100% - 0px);
         overflow-y: auto;
+        line-height: 1.8em;
+        font-size: 16px;
         &>*{
           padding: 5px 0;
         }
@@ -867,13 +932,14 @@ export default {
         
         .title{
           font-weight: bolder;
-          font-size: 18px;
+          font-size: 20px;
           height:20px;
           background: white;
           padding: 2px;
           position: absolute;
-          top: -17px;
+          top: -19px;
           left: 10px;
+          color: #3498db;
         }
         .childTitle{
           font-weight: bolder;
@@ -983,10 +1049,10 @@ export default {
             border:1px dashed  black;
             padding: 10px;
             .title{
-              font-size: 16px;
+              font-size: 18px;
             }
             .text{
-              font-size: 14px;
+              font-size: 16px;
             }
             .technical_means_item{
               
@@ -1042,4 +1108,91 @@ export default {
 
     }
 }
+</style>
+<style lang="scss" scoped>
+  .style2{
+    font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif;
+    .right{
+      background:#f3f5f8;
+    }
+    .content_box{
+      background: white;
+      border-radius: 10px;
+      box-shadow: 0 4px 15px rgb(0 0 0 / 5%) !important;
+      transition: transform 0.3s ease;
+      font-size: 16px;
+      margin-bottom: 20px !important;
+      .title{
+        position: unset !important;
+        height: auto !important;
+        padding: 0 !important;
+      }
+      .text{
+        font-size: 16px !important;
+      }
+      .technical_means{
+        border: none !important;
+        margin-top: 0 !important;
+        background: #ecf0f1;
+        border-radius: 10px;
+        .title{
+          background: unset;
+        }
+      }
+      .layout_suggestions{
+        
+      }
+      .terminology_explanation{
+        .childTitle{
+          font-size: 18px !important;
+        }
+      }
+    }
+  }
+  .style3{
+    .content_box{
+      box-shadow: unset !important;
+      font-size: 16px;
+      margin-bottom: 0px !important;
+      .title{
+        position: unset !important;
+        height: auto !important;
+        padding: 0 !important;
+      }
+      .text{
+        font-size: 16px !important;
+      }
+      .technical_means{
+        border: none !important;
+        margin-top: 0 !important;
+        padding-bottom: 0 !important;
+        padding-top: 0 !important;
+        .title{
+          background: unset;
+        }
+      }
+      .layout_suggestions{
+        p{
+          // margin: 0 !important;
+        }
+      }
+      .terminology_explanation{
+        .childTitle{
+          font-size: 18px !important;
+        }
+      }
+    }
+    hr{
+      display: none !important;
+    }
+  }
+</style>
+<style lang="scss">
+  .style3{
+    .layout_suggestions{
+      p{
+        margin-top: 0 !important;
+      }
+    }
+  }
 </style>

+ 29 - 1
src/views/report/components/index.vue

@@ -33,6 +33,7 @@
             </el-dropdown>
             <el-button type="primary" class="margin-left_10 margin-right_10" size="small" @click="showField">显示栏位管理</el-button>
             <el-button v-if="$permission.FunPermissions('xiaoshi/IPREmail')" type="primary" class="margin-right_10" size="small" @click="IPREmail">联系邮箱</el-button>
+            <el-button type="primary" v-if="componentType==2 && $permission.FunPermissions('xiaoshi/exportReportList')" class="margin-right_10" size="small" :loading="exportBtnLoading" @click="exportExcel">导 出</el-button>
           </div>
 
         </div>
@@ -82,6 +83,7 @@ import patentShare from '@/views/components/drawer/Share.vue';
 
 import IPREmailDialog from '../InvalidResponse/components/dialog/IPREmail.vue'
 import handlePersonDialog from './dialog/handlePerson.vue'
+import { formatDate,downLoad } from '@/utils';
 export default {
   components: {
     Table,
@@ -182,7 +184,8 @@ export default {
           label:'被动',
           value:0
         },
-      ]
+      ],
+      exportBtnLoading:false
     };
   },
   watch: {
@@ -290,6 +293,31 @@ export default {
     IPREmail(){
       this.$refs.IPREmailDialog.open()
     },
+    //导出报告成excel
+    exportExcel(){
+      let params = {
+        searchQuery: this.$commonJS.objectToString(this.searchOption),//检索条件
+        orderDTOList: this.sort,//排序信息
+      }
+      params.ifInvalidReport = 0
+      if(this.fixedSearch.reportType){
+        params.ifInvalidReport = 1
+        if(params.searchQuery){
+          params.searchQuery = params.searchQuery + ' and reportType=(' + this.fixedSearch.reportType.join(' OR ') + ')'
+        }else{
+          params.searchQuery ='reportType=(' + this.fixedSearch.reportType.join(' OR ') + ')'
+        }
+      }
+      this.exportBtnLoading = true
+      this.$api.exportReportList(params).then(response=>{
+        this.exportBtnLoading = false
+        let now = formatDate(new Date(),"YYYY-MM-DD")
+        downLoad(response,now + '- 无效案件详情表.xlsx')
+      }).catch(error=>{
+        this.$message.error('导出失败')
+        this.exportBtnLoading = false
+      })
+    },
     //标签页点击
     async tabChange(name){
       var type = Number(name)