dujunlong 9 сар өмнө
parent
commit
655a53b802

+ 4 - 0
ruoyi-ui/src/views/equipment/recog/index.vue

@@ -445,6 +445,10 @@ export default {
       // 选项卡
       activeName0: 'first0',
       activeName: 'first',
+
+      highlightedId: null, // 用于存储高亮的 id
+
+
       // 显示
       algChnameXS:'',
       tableXS:'',

+ 211 - 176
ruoyi-ui/src/views/production/recog/index.vue

@@ -225,76 +225,99 @@
 <!--      </el-tab-pane>-->
 
       <el-tab-pane label="指导建议" name="second">
-        <el-card class="update-log" style="min-height: 200px; border-radius: 10px;" v-loading="loading">
+        <el-card class="update-log" v-loading="loading"  style="min-height: 200px; border-radius: 12px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); padding: 20px;">
           <div class="body">
-            <h3>请选择展示数量</h3> <el-select v-model="topN" placeholder="请选择展示数量" style="margin-bottom: 15px; ">
-            <el-option
-              v-for="number in [1, 2, 3, 4, 5]"
-              :key="number"
-              :label="number"
-              :value="number">
-            </el-option>
-          </el-select>
-            <div style="font-size: 16px; line-height: 1.5;" v-if="zdjyData.length > 0">
-              <h4 style="margin-bottom: 15px; font-size: 18px;">建议企业重点关注以下几个方面,以提升生产效率:</h4>
-              <ul style="list-style-type: disc; padding-left: 20px;">
-                <li v-for="item in zdjyData" :key="item.chName" style="font-size: 18px; margin: 10px">
-                  {{ item.chName }}:
-                  <ul>
-                    <li v-for="subItem in item.items" :key="subItem.value">{{ subItem.value }} ({{ subItem.count }})</li>
-                  </ul>
-                </li>
-              </ul>
-              <p style="margin-top: 15px; font-size: 18px;">以上信息在本次异常检测中表现突出,值得重视。</p>
+
+
+
+            <!-- 顶部右侧的展示数量选择器 -->
+            <div v-if="zdjyData.length > 0" style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
+              <h3 style="font-size: 20px; color: #409eff; font-weight: 600;">
+                建议企业重点关注以下几个方面,以提升生产效率:
+              </h3>
+              <div style="display: flex; align-items: center;">
+                <h4 style="margin: 0; font-size: 16px; font-weight: 500;">请选择(或输入)展示数量:</h4>
+                <el-input-number v-model="topN" :min="1" :max="10" label="请选择(或输入)展示数量" style="margin-left: 10px; width: 120px;" />
+              </div>
             </div>
-            <div v-else>
-              <h4 style="margin-bottom: 15px; font-size: 16px;">请运行算法以获取相关建议!</h4>
+
+            <div v-if="zdjyData.length > 0" style="font-size: 16px; line-height: 1.8; color: #333;">
+              <div v-for="(data, index) in zdjyData" :key="index" style="margin-bottom: 25px;">
+                <h3 style="font-size: 18px; color: #333; font-weight: 500; border-bottom: 2px solid #e0e0e0; padding-bottom: 10px;">
+                  {{ data.chName }}
+                </h3>
+                <el-table  :data="data.items" stripe border style="width: 100%; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); border-radius: 8px; overflow: hidden;">
+                  <el-table-column prop="value" label="ID"  align="center">
+                    <template slot-scope="scope">
+                      <span style="font-weight: 500; color: #666;">{{ scope.row.value }}</span>
+                    </template>
+                  </el-table-column>
+                  <el-table-column prop="name" label="名称"  align="center">
+                    <template slot-scope="scope">
+                      <el-link
+                        :to="{ name: 'fourth' }"
+                        @click="highlightData(scope.row, data)">
+                        {{ scope.row.name }}
+                      </el-link>
+                    </template>
+                  </el-table-column>
+                  <el-table-column prop="count" label="异常数量"  align="center">
+                    <template slot-scope="scope">
+                      <span style="font-weight: 500; color: #f56c6c;">{{ scope.row.count }}</span>
+                    </template>
+                  </el-table-column>
+                </el-table>
+
+              </div>
+
+              <p style="margin-top: 25px; font-size: 16px; color: #666;">
+                以上信息在本次异常检测中表现突出,值得重视。
+              </p>
+            </div>
+
+            <!-- 左上角提示信息 -->
+            <div v-else style="position: absolute; top: 20px; left: 20px;">
+              <h4 style="margin: 0; font-size: 18px; color: #999;">
+                请运行算法以获取相关建议!
+              </h4>
             </div>
           </div>
         </el-card>
       </el-tab-pane>
 
       <el-tab-pane label="特征重要性分析" name="third">
-        <!--        <el-card class="update-log" style="min-height: 200px;   border-radius: 10px;" v-loading="loading">-->
-        <!--          <div class="body" >-->
-        <!--            <div style="font-size: 16px; line-height: 1.5;" v-if="tableData.length > 0">-->
-        <!--              <h4 style="margin-bottom: 15px;  font-size: 18px;">在该模型的本次异常检测中,最有可能导致异常的三个数据特征为:</h4>-->
-        <!--              <ul style="list-style-type: disc; padding-left: 20px;">-->
-        <!--                <li v-for="item in featureData" :key="item.enName" style="font-size: 18px; margin: 10px">特征:{{ item.chName }}  特征重要程度:{{ item.value }}</li>-->
-        <!--              </ul>-->
-        <!--              <p style="margin-top: 15px; font-size: 18px; ">企业可参照指导建议及以上数据特征进行调整。</p>-->
-        <!--            </div>-->
-        <!--            <div v-else>-->
-        <!--              <h4 style="margin-bottom: 15px;  font-size: 16px;">请运行算法以获取相关建议!</h4>-->
-        <!--            </div>-->
-        <!--          </div>-->
-
-        <!--        </el-card>-->
+
         <el-card class="update-log" style="min-height: 200px; border-radius: 10px;" v-loading="loading">
-          <div class="body">
-            <div style="font-size: 16px; line-height: 1.5;" v-if="featureData.length > 0">
-              <h4 style="margin-bottom: 15px; font-size: 18px;">该模型对本数据表的异常检测中,所选数据特征对异常检测的重要程度如表所示:</h4>
-
-              <el-table :data="featureData"  border stripe style="width: 100%">
-                <el-table-column prop="chName" label="数据特征">
-                </el-table-column>
-                <el-table-column prop="value" label="数据特征重要程度" >
-                </el-table-column>
-              </el-table>
-
-              <p style="margin-top: 15px; font-size: 15px;">说明:1、数据特征的重要性程度越高,表明该特征在所选模型的异常检测中发挥的作用越显著。</p>
-              <p style="margin-top: 10px; font-size: 15px;">&nbsp;&nbsp;&nbsp;2、企业可以依据数据特征的重要性程度,对特征进行调整后重新进行异常检测,以获取更为精准的指导建议。</p>
+          <div class="body" >
+
+
+            <div v-show="featureData.length > 0" style="display: flex; justify-content: center; align-items: center; gap: 20px;">
+              <div id="fii" style="width: 600px; height: 400px;"></div>
+
+              <div style="display: flex; flex-direction: column; justify-content: center; gap: 10px; max-width: 300px;">
+                <p style="font-size: 15px; line-height: 1.5; text-align: left;">
+                  说明:1、数据特征的重要性程度越高,表明该特征在所选模型的异常检测中发挥的作用越显著。
+                </p>
+                <p style="font-size: 15px; line-height: 1.5; text-align: left;">
+                  2、企业可以依据数据特征的重要性程度,对特征进行调整后重新进行异常检测,以获取更为精准的指导建议。
+                </p>
+              </div>
             </div>
-            <div v-else>
-              <h4 style="margin-bottom: 15px; font-size: 16px;">请运行算法以获取数据特征重要性分析!</h4>
+
+            <div v-show="featureData.length <= 0" style="text-align: left;">
+              <h4 style="margin-bottom: 15px; font-size: 18px; color: #999;">
+                请运行算法以获取数据特征重要性分析!
+              </h4>
             </div>
           </div>
         </el-card>
 
+
       </el-tab-pane>
 
 
 
+
       <el-tab-pane label="异常原始数据" name="fourth">
         <el-card class="update-log" v-loading="loading" style="max-height: 700px; min-height: 200px; overflow-y: auto;">
           <el-checkbox-group v-model="selectedColumns" @change="updateColumns">
@@ -307,13 +330,14 @@
             </el-checkbox>
           </el-checkbox-group>
 
-          <el-table :data="tableData" border stripe style="width: 100%">
+          <el-table :row-style="tableRowStyle"  :data="tableData" border  style="width: 100%" >
             <el-table-column
               v-for="column in visibleColumns"
               :key="column.prop"
               :prop="column.prop"
               :label="column.label"
               :sortable="true"
+
             ></el-table-column>
           </el-table>
         </el-card>
@@ -374,6 +398,7 @@ import qs from 'qs';
 import {getAlgorithm} from "@/api/algorithm/algorithm";
 import {getLine} from "@/api/line/line";
 import {getEquip} from "@/api/equip/equip";
+import * as echarts from "echarts";
 
 export default {
   name: "Index",
@@ -401,6 +426,10 @@ export default {
       // 选项卡
       activeName0: 'first0',
       activeName: 'first',
+
+      highlightedId: null, // 用于存储高亮的 id
+
+
       // 显示
       algChnameXS:'',
       tableXS:'',
@@ -564,6 +593,39 @@ export default {
     //
     //
     // },
+    // tab页跳转
+    highlightData(row, data) {
+      console.log('tab页跳转:')
+      // 这里可以添加其他逻辑,例如存储高亮的 id
+      this.highlightedId = {"enName": data.enName, "item":row.value}; // 假设有一个 data 中的 highlightedId 用于保存高亮的 id
+
+      // 跳转
+      this.activeName = 'fourth';
+
+      // 重新排序,将高亮的行放在最前面
+      this.tableData.sort((a, b) => {
+        if (a[this.highlightedId.enName] === this.highlightedId.item) return -1;
+        if (b[this.highlightedId.enName] === this.highlightedId.item) return 1;
+        return 0;
+      });
+    },
+
+    // 高亮
+    tableRowStyle({ row, rowIndex }) {
+      // console.log(row)
+      // console.log("高亮")
+      // console.log(this.highlightedId)
+      if (this.highlightedId) {
+        let x = this.highlightedId.enName
+        // return row[x] === this.highlightedId.item ? { background: '#f0f9eb' } : {};
+        return row[x] === this.highlightedId.item ? { background: 'oldlace' } : {};
+      }
+      else {
+        return {}
+      }
+
+
+    },
 
     setTable(tableName) {
       // 根据选择的表名加载列配置
@@ -698,7 +760,8 @@ export default {
         // // 处理特征重要性数据
         this.feature(this.table)
 
-        console.log(this.featureData)
+        // 显示特征重要性柱状图
+        this.barFeature()
 
         // 指导建议:统计
         this.tableDataCopy = response.data.data.result
@@ -802,6 +865,89 @@ export default {
       }));
     },
 
+    // 显示特征重要性柱状图
+    barFeature() {
+      try {
+        var chartDom = document.getElementById('fii');
+        var myChart = echarts.init(chartDom);
+        var option;
+
+        // 处理this.featureData 生成dataset中的source
+        var sourceNew = this.featureData.map(item => [item.chName, item.enName, item.value]);
+        console.log('sourceNew');
+        console.log(sourceNew);
+
+        option = {
+          title: {
+            text: '特征重要性分析',
+            left: 'center',
+            textStyle: {
+              fontSize: 18,
+              fontWeight: 'bold',
+              color: '#333'
+            }
+          },
+          tooltip: {
+            trigger: 'axis',
+            axisPointer: { type: 'shadow' },
+            formatter: (params) => {
+              const data = params[0].data;
+              const name = data[0];
+              const value = data[2] ? data[2].toFixed(3) : '-';
+              return `${name}: ${value}`;
+            }
+          },
+          dataset: [
+            {
+              dimensions: ['chName', 'enName', 'value'],
+              source: sourceNew
+            },
+            {
+              transform: {
+                type: 'sort',
+                config: { dimension: 'value', order: 'desc' }
+              }
+            }
+          ],
+          xAxis: {
+            type: 'category',
+            axisLabel: { interval: 0, rotate: 30, color: '#666' },
+            axisLine: { lineStyle: { color: '#ccc' } }
+          },
+          yAxis: {
+            axisLine: { lineStyle: { color: '#ccc' } },
+            splitLine: { lineStyle: { type: 'dashed', color: '#eaeaea' } }
+          },
+          grid: {
+            left: '5%',
+            right: '5%',
+            bottom: '10%',
+            top: '15%',
+            containLabel: true
+          },
+          series: {
+            type: 'bar',
+            encode: { x: 'chName', y: 'value' },
+            datasetIndex: 1,
+            itemStyle: {
+              color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
+                { offset: 0, color: '#83bff6' },
+                { offset: 0.5, color: '#188df0' },
+                { offset: 1, color: '#188df0' }
+              ]),
+              barBorderRadius: [4, 4, 0, 0]
+            },
+            barWidth: '60%' // 增加柱体宽度
+          }
+        };
+
+        option && myChart.setOption(option);
+      } catch (err) {
+        console.log('运行错误');
+        console.log(err);
+      }
+    },
+
     // 处理特征重要性数据
     feature(tableName) {
       // 根据 tableName 选择对应的配置
@@ -821,116 +967,7 @@ export default {
       // this.featureData = this.featureData.slice(0, 3); // 只保留前3项
     },
 
-    // // 统计
-    // async statistic(tableData, tableName) {
-    //   // 先进行重置
-    //   this.zdjyData = []
-    //
-    //   const statistics = tableData.reduce((acc, item) => {
-    //     this.staConfig[tableName].forEach(field => {
-    //       const key = item[field.enName];
-    //       acc[field.enName] = acc[field.enName] || {};
-    //       acc[field.enName][key] = (acc[field.enName][key] || 0) + 1;
-    //     });
-    //     return acc;
-    //   }, {});
-    //
-    //   // 找到出现次数最多的元素并打印
-    //   for (const field of this.staConfig[tableName]) {
-    //     const maxItem = Object.keys(statistics[field.enName]).reduce((a, b) => statistics[field.enName][a] > statistics[field.enName][b] ? a : b);
-    //
-    //     // 将设备号、产线号 转换成 设备名、产线名
-    //     if (field.chName === '设备号') {
-    //
-    //
-    //       await getEquip(maxItem).then(res => {
-    //
-    //         if (res.data !== undefined && res.data.name !== null) {
-    //           this.zdjyData.push({chName: field.chName, enName: field.enName, value: res.data.name});
-    //         }
-    //         else {
-    //           this.zdjyData.push({chName: field.chName, enName: field.enName, value: maxItem});
-    //         }
-    //
-    //
-    //       }).catch(res => {
-    //       })
-    //
-    //     } else if (field.chName === '产线号') {
-    //
-    //
-    //       await getLine(maxItem).then(res => {
-    //
-    //         if (res.data !== undefined && res.data.lineName !== null) {
-    //           this.zdjyData.push({chName: field.chName, enName: field.enName, value: res.data.lineName});
-    //         }
-    //         else {
-    //           this.zdjyData.push({chName: field.chName, enName: field.enName, value: maxItem});
-    //         }
-    //
-    //       }).catch(res => {
-    //       })
-    //
-    //     } else {
-    //       this.zdjyData.push({chName: field.chName, enName: field.enName, value: maxItem});
-    //     }
-    //   }
-    // }
-    // // 统计
-    // async statistic(tableData, tableName) {
-    //   // 先进行重置
-    //   this.zdjyData = []
-    //
-    //   const statistics = tableData.reduce((acc, item) => {
-    //     this.staConfig[tableName].forEach(field => {
-    //       const key = item[field.enName];
-    //       acc[field.enName] = acc[field.enName] || {};
-    //       acc[field.enName][key] = (acc[field.enName][key] || 0) + 1;
-    //     });
-    //     return acc;
-    //   }, {});
-    //
-    //   // 找到出现次数最多的元素并打印
-    //   for (const field of this.staConfig[tableName]) {
-    //     const maxItem = Object.keys(statistics[field.enName]).reduce((a, b) => statistics[field.enName][a] > statistics[field.enName][b] ? a : b);
-    //
-    //     // 将设备号、产线号 转换成 设备名、产线名
-    //     if (field.chName === '设备号') {
-    //
-    //
-    //       await getEquip(maxItem).then(res => {
-    //
-    //         if (res.data !== undefined && res.data.name !== null) {
-    //           this.zdjyData.push({chName: '设备', enName: field.enName, value: res.data.name});
-    //         }
-    //         else {
-    //           this.zdjyData.push({chName: field.chName, enName: field.enName, value: maxItem});
-    //         }
-    //
-    //
-    //       }).catch(res => {
-    //       })
-    //
-    //     } else if (field.chName === '产线号') {
-    //
-    //
-    //       await getLine(maxItem).then(res => {
-    //
-    //         if (res.data !== undefined && res.data.lineName !== null) {
-    //           this.zdjyData.push({chName: '产线', enName: field.enName, value: res.data.lineName});
-    //         }
-    //         else {
-    //           this.zdjyData.push({chName: field.chName, enName: field.enName, value: maxItem});
-    //         }
-    //
-    //       }).catch(res => {
-    //       })
-    //
-    //     } else {
-    //       this.zdjyData.push({chName: field.chName, enName: field.enName, value: maxItem});
-    //     }
-    //   }
-    // }
+
 
     async statistic(tableData, tableName) {
       // 重置数据
@@ -955,6 +992,7 @@ export default {
         // 初始化每列的数据对象
         const categoryData = {
           chName: field.chName,
+          enName: field.enName,
           items: [],
         };
 
@@ -963,22 +1001,25 @@ export default {
           if (field.chName === '设备号') {
             await getEquip(item).then(res => {
               categoryData.items.push({
-                value: res.data && res.data.name ? res.data.name : item,
+                value: item, // ID
+                name: res.data && res.data.name ? res.data.name : item, // 名称
                 count,
               });
-              categoryData.chName = '设备'
             }).catch(() => {});
+            categoryData.chName = '设备';
           } else if (field.chName === '产线号') {
             await getLine(item).then(res => {
               categoryData.items.push({
-                value: res.data && res.data.lineName ? res.data.lineName : item,
+                value: item, // ID
+                name: res.data && res.data.lineName ? res.data.lineName : item, // 名称
                 count,
               });
-              categoryData.chName = '产线'
             }).catch(() => {});
+            categoryData.chName = '产线';
           } else {
             categoryData.items.push({
-              value: item,
+              value: item, // ID
+              name: item, // 名称(直接使用ID作为名称)
               count,
             });
           }
@@ -986,15 +1027,9 @@ export default {
 
         // 将每列的数据对象加入zdjyData
         this.zdjyData.push(categoryData);
-
-
       }
-      console.log(23423423423)
-      console.log(this.zdjyData)
-
-
-
 
+      //console.log(this.zdjyData);
     },
   }
 };