Преглед на файлове

完成作业日志筛选功能和socket实时更新,未选中的数据提示框功能

wyn преди 3 месеца
родител
ревизия
bb4ac28326
променени са 2 файла, в които са добавени 173 реда и са изтрити 59 реда
  1. 2 1
      src/utils/websocket.js
  2. 171 58
      src/views/mes/job/jobm/NewMarsJob.vue

+ 2 - 1
src/utils/websocket.js

@@ -81,6 +81,7 @@ const initWsEventHandle = () => {
     // 监听服务器端返回的信息
     wsObj.onmessage = event => {
       onWsMessage(event); //接收数据,抛出
+
       heartCheck.reset(); //重置心跳
     };
 
@@ -121,7 +122,7 @@ const onWsOpen = event => {
 //message事件  接收到WebSocket服务器发送的消息时触发
 const onWsMessage = event => {
   const jsonStr = event.data;
-  // writeToScreen("onWsMessage接收到服务器的数据: ", jsonStr);
+  writeToScreen("onWsMessage接收到服务器的数据: ", jsonStr);
   messageCallback(jsonStr);
 };
 

+ 171 - 58
src/views/mes/job/jobm/NewMarsJob.vue

@@ -407,38 +407,42 @@
               <div class="joblogCon">
                   <!--顶部日志内容-->
                 <div class="joblogTop">
-<!--                  <p v-for="(item, index) in joblogList" :key="index">filteredJoblogList-->
                   <p v-for="(item, index) in filteredJoblogList" :key="index">
                     <span v-html="renderLogContent(item.operationContent)"></span>
                   </p>
-
                 </div>
-                  <!-- 底部查询条件-->
+                  <!-- 底部过滤条件-->
                 <div class="bottomCheck">
-<!--                  <el-checkbox :indeterminate="isIndeterminate" v-model="checkjobCheckAll" @change="handleCheckAllChange" class="big-checkbox">全选</el-checkbox>-->
-<!--                  <div style="margin: 15px 0 15px 15px;"></div>-->
-<!--                  <el-checkbox-group v-model="checkedJoblogs" @change="handleCheckedJoblogsChange" class="big-checkbox">-->
-<!--                    <el-checkbox v-for="jobLogtype in jobLogtypes" :label="jobLogtype" :key="jobLogtype" class="big-checkbox">{{jobLogtype}}</el-checkbox>-->
-<!--                  </el-checkbox-group>-->
-                  <el-checkbox-group v-model="checkedJoblogs" @change="handleCheckedJoblogsChange" class="big-checkbox">
+                  <el-checkbox
+                    :indeterminate="isIndeterminate"
+                    :checked="checkAlljoblog"
+                    @change="handleCheckAllChange"
+                    style="margin:3px 25px;font-size: 16px"
+
+                  >
+                    全部
+                  </el-checkbox>
+
+                  <!-- 多选项 -->
+                  <el-checkbox-group
+                    v-model="checkedJoblogs"
+                    @change="handleCheckedJoblogsChange"
+                    class="big-checkbox"
+                  >
                     <el-checkbox
                       v-for="item in jobLogtypes"
-                      :label="item.dictValue"
-                      :key="item.dictValue"
+                      :label="item.value"
+                      :key="item.value"
                       class="big-checkbox"
                     >
-                      {{ item.dictLabel }}
+                      {{ item.label }}
                     </el-checkbox>
                   </el-checkbox-group>
-
                 </div>
               </div>
               </div>
-
             </el-tab-pane>
           </el-tabs>
-
-
           <el-button style="float: right" type="primary" @click="finshJobticket"
           >结束作业
           </el-button>
@@ -449,10 +453,21 @@
           >取消作业
           </el-button>
         </el-card>
-
-
       </div>
     </div>
+    <!-- 作业日志检索内容中未选中类型的新消息-->
+    <el-dialog
+      :visible.sync="JoblogdialogVisible"
+      title="新日志提醒"
+      width="50%"
+      :close-on-click-modal="true"
+    >
+      <div class="joblogTop1">
+        <p>
+          <span v-html="renderLogContent(dialogLog.operationContent)"></span>
+        </p>
+      </div>
+    </el-dialog>
     <!-- 添加或修改外部人员对话框 -->
     <el-dialog :visible.sync="open" width="1400px" append-to-body>
       <div slot="title" class="dialog-title">
@@ -904,6 +919,8 @@ import { selectIsMapById } from '@/api/system/mapconfig'
 import { getIsMapPointPage } from '@/api/system/mappoint'
 import { getIsSystemAttributeByKey } from '@/api/system/configuration'
 import { getDicts } from '@/api/system/dict/data'
+import {connectWebsocket} from "@/utils/websocket";
+import { nextTick } from 'vue';
 const joblogsOptions = [];
 export default {
   name: 'NewSop',
@@ -991,14 +1008,16 @@ export default {
       loading: false,
       LoadStatus: '',//给LockDetail加弹窗加载
       activeName: 'eightSteps', // 默认展示“八大步骤”
+      joblogList:[],//原始作业日志数据列表
+      filteredJoblogList: [], // 过滤后日志
     //   作业日志底部查询
-      checkJobCheckAll: false,
-      isIndeterminate: true,
+      isIndeterminate: false,
       checkedJoblogs: [],
       jobLogtypes: [],
-      labelToValueMap: {},
-      joblogList:[]
-
+      joblogsOptions: [], // 只存所有 dictValue,用于全选逻辑,
+      checkAlljoblog: true,
+      JoblogdialogVisible: false,
+      dialogLog: '',
     }
   },
   computed: {
@@ -1006,11 +1025,6 @@ export default {
       const stepFour = this.EightStepForm.find((step) => step.stepIndex == '4')
       return stepFour && stepFour.stepStatus === '1'
     },
-    // 日志过滤方式
-    filteredJoblogList() {
-      return this.joblogList.filter(log => this.checkedJoblogs.includes(log.operationType?.toString()));
-    }
-
   },
   watch: {
     tabPosition: function(val, oldVal) {
@@ -1032,12 +1046,18 @@ export default {
         this.handlelockerChage(val)
         console.log('我制定了')
       }
+    },
+    "ticketId": function(val) {
+      if(val){
+        console.log(this.ticketId,val,'JIANRT')
+        this.initWebSocket()
+
+      }
     }
   },
 
   mounted() {
     this.getList()
-
   },
 
 
@@ -1629,59 +1649,152 @@ export default {
         })
       }
     },
+  //   作业日志连接socket获取数据
+    initWebSocket(){
+      const code= this.ticketId;
+      const address='sys.websocket.address'
+      getIsSystemAttributeByKey(address).then((res) => {
+        // console.log(res, 'websocket地址');
+        this.websocketAddress = res.data.sysAttrValue
+        const isLocalDev = window.location.hostname === 'localhost'
+
+        const baseAddress = isLocalDev
+          ? 'ws://192.168.0.10:9190'
+          : this.websocketAddress;
+        connectWebsocket(
+          `${baseAddress}/websocket/jobTicketLog/${code}`,
+          { w: 'S' },
+          async (res) => {
+            console.log(res, 'websocket接收服务器的作业日志数据');
+            if (res !== 'heartbeat') {
+              // 判断是否需要弹窗显示
+              await this.onNewSocketLog(res);  // 👈传入最新的 WebSocket 消息
+              await this.getJoblogs(); // 抽出专用接口函数
+            }
+          },
+          (err) => {
+            console.log('断开重连');
+          }
+        );
+      }).catch(err => {
+        console.error('获取WebSocket地址失败:', err);
+      });
+    },
+
 
-  //   作业日志tab点击事件
-    handleTabClick(tab) {
+  //   查询作业日志接口获取
+    async getJoblogs() {
+      const joblogdata = {
+        ticketId: this.ticketId,
+        current: 1,
+        size: -1,
+      };
+      const res = await getIsTicketOperLogPage(joblogdata);
+      // console.log('接口返回日志:', res.data.records);
+      this.joblogList = res.data.records;
+      // ✨强制刷新筛选后的列表
+      this.filterJoblogs();
+    },
+
+
+    //   作业日志tab点击事件
+    async handleTabClick(tab) {
       if (tab.name === 'jobLogs') {
-        const joblogdata = {
-          ticketId: this.ticketId,
-          current:1,
-          size:-1
-        }
-        getIsTicketOperLogPage(joblogdata).then((res) => {
-          this.joblogList=res.data.records
-          console.log(res,'查看作业日志',this.joblogList,'赋值成功了吗')
-        })
-        console.log(this.ticketId,'是否拿到了作业id')
+        await this.getJoblogs()
       }
-      getDicts('job_log_type').then(res => {
-        console.log(res, '字典值');
-        this.jobLogtypes = res.data;
-        // 初始化时默认选中全部(或部分)
-        this.checkedJoblogs = res.data.map(item => item.dictValue);
-      });
 
+      const dictRes = await getDicts('job_log_type');
+      const dicts = dictRes.data.map(item => ({
+        label: item.dictLabel,
+        value: String(item.dictValue), // 确保是字符串类型
+      }));
+
+      this.jobLogtypes = dicts;
+      this.joblogsOptions = dicts.map(item => item.value);
+      this.checkedJoblogs = [...this.joblogsOptions]; // 初始化全选
+      console.log(this.checkAlljoblog,'选中状态');
+      this.checkAlljoblog = true;
+      console.log(this.checkAlljoblog,'是否选中');
+      this.isIndeterminate = false;
+      this.filterJoblogs();
     },
 
     // 作业日志页面数据展示样式分割
     renderLogContent(content) {
       if (!content) return ''
-
       // 第一步:先处理 <url>[label] 为 <img> + label
       content = content.replace(/<([^>]+)>\[([^\]]+)\]/g, (match, url, label) => {
         return `<img src="${url}" style="height: 25px; vertical-align: middle;"> <span style="color:#007BFF;margin: 0 3px">${label}</span>`
       })
-
       // 第二步:处理剩下的 [label],转成蓝色字体
       content = content.replace(/\[([^\]]+)\]/g, '<span style="color:#007BFF;margin: 0 5px">$1</span>')
-
       return content
-
     },
 
-
     //   作业日志底部筛选功能
+    handleCheckedJoblogsChange(val) {
+      const checkedCount = val.length;
+      this.checkAlljoblog = checkedCount === this.joblogsOptions.length;
+      this.isIndeterminate = checkedCount > 0 && checkedCount < this.joblogsOptions.length;
+
+      this.filterJoblogs();
+    },
     handleCheckAllChange(val) {
-      this.checkedJoblogs = val ? joblogsOptions : [];
+      this.checkedJoblogs = val ? [...this.joblogsOptions] : [];
       this.isIndeterminate = false;
+      this.filterJoblogs();
     },
-    handleCheckedJoblogsChange(value) {
-      let checkedCount = value.length;
-      this.checkjobCheckAll = checkedCount === this.jobLogtypes.length;
-      this.isIndeterminate = checkedCount > 0 && checkedCount < this.jobLogtypes.length;
-    }
 
+    // 实际日志筛选逻辑
+    filterJoblogs() {
+      if (this.checkedJoblogs.includes('ALL')) {
+        this.filteredJoblogList = this.joblogList;
+      } else {
+        this.filteredJoblogList = this.joblogList.filter(log =>
+          this.checkedJoblogs.includes(String(log.operationType))
+        );
+      }
+    },
 
+  //   作业日志弹框
+  parseLogString(logStr) {
+    const obj = {};
+    const match = logStr.match(/^[^(]+?\((.*)\)$/);
+    if (!match) return obj;
+    const keyValuePairs = match[1].split(/,\s*(?=\w+=)/); // 处理 "key=value" 中的逗号
+    keyValuePairs.forEach(pair => {
+      const [key, value] = pair.split('=');
+      if (value === 'null') {
+        obj[key] = null;
+      } else if (!isNaN(value)) {
+        obj[key] = Number(value);
+      } else {
+        obj[key] = value;
+      }
+  });
+
+  return obj;
+},
+
+// 判断某条日志是否在当前筛选之外(即是否未被选中)
+    async onNewSocketLog(rawLogStr) {
+      // 1. 将字符串解析为对象
+      const newLog = this.parseLogString(rawLogStr);
+
+      // 2. 获取当前勾选的类型(都转成字符串)
+      const selectedTypes = this.checkedJoblogs.map(String);
+      const newLogType = String(newLog.operationType);
+      // console.log('新日志类型:', newLogType, '勾选类型:', selectedTypes);
+      // 3. 判断是否未被选中 → 弹窗
+      if (!selectedTypes.includes(newLogType)) {
+        this.dialogLog = newLog;
+        this.JoblogdialogVisible = true;
+        // console.log('弹框内容:', newLog);
+      } else {
+        this.JoblogdialogVisible = false;
+        // console.log('该类型已勾选,不弹框');
+      }
+    }
 
   }
 }