فهرست منبع

feat(设备详情): 优化设备详情页面布局和功能

liujt 6 ماه پیش
والد
کامیت
2b488073e3

+ 37 - 8
src/views/ledgerAssets/components/details/components/GaugeChart.vue

@@ -214,7 +214,7 @@ export default {
         backgroundColor: 'transparent',
         series: [
           {
-            name: this.title || '仪表盘',
+            name: this.title || '',
             type: 'gauge',
             // startAngle: 180,
             // endAngle: 0,
@@ -223,15 +223,44 @@ export default {
             splitNumber: this.splitNumber,
             radius: '90%',
             center: ['50%', '50%'],
+            itemStyle: {
+              color: '#7a71ff',
+              shadowColor: 'rgba(0,138,255,0.45)',
+              shadowBlur: 10,
+              shadowOffsetX: 2,
+              shadowOffsetY: 2,
+              borderCap: 'round'
+            },
             progress: {
               show: true,
-              width: 15,
               roundCap: true,
+              width: 12,
+              itemStyle: {
+                color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
+                  {
+                    offset: 0,
+                    color: '#15b4ff'
+                  },
+                  {
+                    offset: 1,
+                    color: '#716dff'
+                  }
+                ]),
+                shadowColor: 'rgba(0,138,255,0.45)',
+                shadowBlur: 10,
+                shadowOffsetX: 2,
+                shadowOffsetY: 2
+              }
             },
+            // progress: {
+            //   show: true,
+            //   width: 15,
+            //   roundCap: true,
+            // },
             // 优化仪表盘轴线样式 - 采用单一蓝色调
             axisLine: {
               lineStyle: {
-                width: 15,
+                width: 12,
                 roundCap: true,
                 // color: this.calculateColorRanges(),
                 // shadowBlur: 10,
@@ -244,7 +273,7 @@ export default {
               width: 5,
               length: '65%',
               itemStyle: {
-                color: '#5470C6',
+                color: '#716dff',
                 // borderWidth: 1,
                 // borderType: 'solid',
                 // borderColor: '#333'
@@ -263,7 +292,7 @@ export default {
             // 优化分割线 - 与示例图保持一致
             splitLine: {
               distance: 0,
-              length: 10,
+              length: 8,
               lineStyle: {
                 color: '#5470C6',
                 width: 2
@@ -272,8 +301,8 @@ export default {
             // 优化标签位置和样式
             axisLabel: {
               color: '#333',
-              distance: 25,
-              fontSize: 14,
+              distance: 20,
+              fontSize: 12,
               fontWeight: 'normal'
             },
             // 优化中心显示内容 - 居中显示数值
@@ -281,7 +310,7 @@ export default {
               valueAnimation: true,
               formatter: `{value}${this.unit}`,
               color: '#333',
-              fontSize: 20,
+              fontSize: 18,
               fontWeight: 'bold',
               offsetCenter: [0, '40%'],
               borderColor: 'transparent'

+ 1 - 1
src/views/ledgerAssets/components/details/components/LineChart.vue

@@ -25,7 +25,7 @@ export default {
      */
     height: {
       type: String,
-      default: '400px'
+      default: '300px'
     },
     
     /**

+ 228 - 75
src/views/ledgerAssets/components/details/components/internetDetail.vue

@@ -2,8 +2,9 @@
   <div class="internet-detail-container">
     <div class="gauge-charts-container">
         <div class="gauge-charts-wrapper">
-            <div class="gauge-card" v-for="item in realData">
+            <div class="gauge-card" v-for="item in gaugeData">
                 <GaugeChart
+                    height="250px"
                     :value="item.value"
                     :min="item.min"
                     :max="item.max"
@@ -15,35 +16,22 @@
             </div>
         </div>
 
-        <div class="gauge-charts-wrapper">
+        <div class="status-wrapper">
             <el-form label-width="150px" style="width: 100%">
-                <el-row v-for="obj in realData">
-                    <template>
+                <el-row>
+                    <template v-for="obj in realData">
                         <!-- 过滤掉运行状态  v-if="!['status', 'status_m'].includes(key)" -->
                         <el-col :span="12">
-                            <el-form-item :label="obj.name">
+                            <el-form-item v-if="obj.identifier == 'status'" :label="obj.name+':'">
+                                <span>{{ obj.specs[obj.value] }}</span>
+                            </el-form-item>
+                            <el-form-item v-else :label="obj.name+':'">
                                 <span>{{ obj.value }}</span>
                                 <span style="margin-left: 5px" v-if="obj.unit">{{
                                     obj.unit
                                 }}</span>
                             </el-form-item>
                         </el-col>
-                        <el-col :span="12">
-                            <el-form-item label="最大值">
-                                <!-- <span>最大值</span> -->
-                                <span style="margin-left: 5px">{{
-                                    obj.max
-                                }}</span>
-                            </el-form-item>
-                        </el-col>
-                        <el-col :span="12">
-                            <el-form-item label="最小值">
-                                <!-- <span>最小值</span> -->
-                                <span style="margin-left: 5px">{{
-                                    obj.min
-                                }}</span>
-                            </el-form-item>
-                        </el-col>
                     </template>
                     <!-- 运行状态设置 -->
                     <el-col :span="12" v-if="realData.status_m">
@@ -70,7 +58,7 @@
       <div class="chart-card" v-for="item in historyData">
         <el-row :gutter="20">
             <el-col :span="8">{{item.name}}</el-col>
-            <el-col :span="8">最高值{{ item.maxValue }}{{ item.unit}} | 最低值{{ item.minValue }}{{ item.unit}} | 平均值{{ item.avgValue }}{{ item.unit}}</el-col>
+            <el-col :span="8"><span class="detail-span">最高值{{ item.maxValue }} {{ item.unit}}</span> | <span class="detail-span">最低值{{ item.minValue }} {{ item.unit}}</span> | <span class="detail-span">平均值{{ item.avgValue }} {{ item.unit}}</span></el-col>
             <el-col :span="8">
                 <div class="tools">
                     <div class="">
@@ -153,28 +141,41 @@ export default {
     return {
       realData: [],
       dict: {
-        chartTime: {
-        date: 3,
-        month: 2,
-        year: 1
-        }
-    },
+          chartTime: {
+          date: 3,
+          month: 2,
+          year: 1
+          }
+      },
+      gaugeData: [],
       historyData: [], // 存储历史数据数组
     };
   },
   computed: {
-    
   },
+  
+  watch: {
+    // 监听info属性变化,当info数据加载完成后执行getRealData
+    info: {
+      handler(newInfo) {
+        if (newInfo && Object.keys(newInfo).length > 0) {
+          this.getRealData();
+        }
+      },
+      deep: true,
+      immediate: true
+    }
+  },
+  
   mounted() {
-    // this.setMonth();
-    // 初始化数据
-    this.getRealData();
+    // 只有当info已有数据时才初始化
+    // if (this.info && Object.keys(this.info).length > 0) {
+    //   this.getRealData();
+    // }
   },
+  
   beforeDestroy() {
-    // 清除定时器
-    // if (this.timer) {
-    //   clearInterval(this.timer);
-    // }
+    // 组件销毁前的清理工作
   },
   methods: {
     handlsz() {
@@ -199,7 +200,7 @@ export default {
     async refreshHistoryData() {
       try {
         // 并行请求所有property的历史数据
-        const historyPromises = this.realData.map(item => 
+        const historyPromises = this.gaugeData.map(item => 
           this.getHistoryDatas(item)
         );
         
@@ -224,8 +225,14 @@ export default {
                     if (property.identifier == item.identifier) {
                         item.max = property.dataType.specs.max;
                         item.min = property.dataType.specs.min;
-                        item.unit = property.dataType.specs.unit;
+                        item.propertyUnit = property.dataType.specs.unit;
                         item.unitName = property.dataType.specs.unitName;
+                        item.specs = property.dataType.specs;
+                        item.dataType= property.dataType;
+                        item.propertyName = property.name;
+                        item.accessMode = property.accessMode;
+                        item.saveHistory = property.saveHistory;
+                        item.required = property.required;
                         // item.value = property.dataType.specs.scale ? item.value / property.dataType.specs.scale : item.value;
                         // 为每个图表添加独立的状态
                         item.chartTime = new Date();
@@ -233,13 +240,20 @@ export default {
                     }
                 })
             })
-            
+
+            const gaugeData = this.realData.filter(item => item.max !== undefined && item.min !== undefined);
+            this.gaugeData = gaugeData;
             console.log('info~~~~~', this.info);
-            console.log('实时数据~~~~~', this.realData);
+            console.log('实时数据~~~~~', this.gaugeData);
             
             // 并行请求所有property的历史数据
-            const historyPromises = this.realData.map(item => 
-                this.getHistoryDatas(item)
+            const historyPromises = this.gaugeData.map(item => 
+                {
+                  if(item.saveHistory) {
+                    return this.getDefaultHistoryData(item);
+                  }
+                  return null;
+                }
             );
             
             // 等待所有请求完成并存储结果
@@ -250,49 +264,182 @@ export default {
         }
     },
     // 请求历史数据
+    async getDefaultHistoryData(item) {
+        try {
+            // 确保chartTime和timeType属性存在,提供默认值
+            const chartTime = item.chartTime || new Date().toISOString().split('T')[0];
+            const timeType = item.timeType || 'month';
+            
+            // 第一步:先获取时间范围,确保时间参数有效
+            let time;
+            try {
+                // 调用getTimeList方法获取时间范围
+                time = this.getTimeList(chartTime, timeType);
+                
+                // 验证时间范围的有效性
+                if (!time || !time.startTime || !time.endTime) {
+                    // 提供默认时间范围
+                    const defaultDate = new Date().toISOString().split('T')[0];
+                    time = {
+                        startTime: defaultDate + ' 00:00:00',
+                        endTime: defaultDate + ' 23:59:59'
+                    };
+                }
+            } catch (timeError) {
+                // 提供默认时间范围作为最后保障
+                const defaultDate = new Date().toISOString().split('T')[0];
+                time = {
+                    startTime: defaultDate + ' 00:00:00',
+                    endTime: defaultDate + ' 23:59:59'
+                };
+            }
+            const response = {};
+            
+            // 设置必要的属性
+            response.identifier = item.identifier || '';
+            response.name = item.name || '';
+            response.unit = item.unit || '';
+            response.unitName = item.unitName || '';
+            response.chartTime = chartTime;
+            response.timeType = timeType;
+            
+            // 初始化趋势数据结构
+            const trendData = {
+                xAxis: [],
+                series: [
+                    {
+                        name: '',
+                        data: [],
+                        color: '#5470C6'
+                    }
+                ]
+            };
+            response.trendData = trendData;
+            response.timeHistoryList = [];
+            
+            return response;
+        } catch (error) {
+            // console.error(`获取属性 ${item.name || item.identifier} 的历史数据失败:`, error);
+        }
+    },
+    // 请求历史数据
     async getHistoryDatas(item) {
         try {
-            let time = this.getTimeList(item.chartTime, item.timeType);
-            const res = await getHistoryData({
+            // 确保chartTime和timeType属性存在,提供默认值
+            const chartTime = item.chartTime || new Date().toISOString().split('T')[0];
+            const timeType = item.timeType || 'month';
+            
+            // 第一步:先获取时间范围,确保时间参数有效
+            // console.log(`开始获取时间范围 - 属性: ${item.name || item.identifier}, chartTime: ${chartTime}, timeType: ${timeType}`);
+            
+            let time;
+            try {
+                // 调用getTimeList方法获取时间范围
+                time = this.getTimeList(chartTime, timeType);
+                
+                // 验证时间范围的有效性
+                if (!time || !time.startTime || !time.endTime) {
+                    // 提供默认时间范围
+                    const defaultDate = new Date().toISOString().split('T')[0];
+                    time = {
+                        startTime: defaultDate + ' 00:00:00',
+                        endTime: defaultDate + ' 23:59:59'
+                    };
+                }
+            } catch (timeError) {
+                console.error('获取时间范围时出错:', timeError);
+                // 提供默认时间范围作为最后保障
+                const defaultDate = new Date().toISOString().split('T')[0];
+                time = {
+                    startTime: defaultDate + ' 00:00:00',
+                    endTime: defaultDate + ' 23:59:59'
+                };
+            }
+            
+            // 安全获取apiTimeType
+            let apiTimeType = 'month'; // 默认值
+            try {
+                apiTimeType = this.dict?.chartTime?.[timeType] || 'month';
+            } catch (e) {
+                console.warn('获取API时间类型失败,使用默认值month:', e);
+            }
+
+            // 构建完整的请求参数
+            const requestParams = {
                 startTime: time.startTime,
                 endTime: time.endTime,
                 property: item.identifier,
                 substanceId: this.id,
-                timeType: this.dict.chartTime[item.timeType]
-            });
-            console.log('历史数据~~~~~', res);
-            res.identifier = item.identifier;
-            res.name = item.name;
-            res.unit = item.unit;
-            res.unitName = item.unitName;
-            res.chartTime = item.chartTime;
-            res.timeType = item.timeType;
+                timeType: apiTimeType
+            };
+            // 第三步:发送API请求获取历史数据
+   
+            const res = await getHistoryData(requestParams);
+            console.log(`API请求完成 - 属性: ${item.name || item.identifier}, 结果:`, res);
+            // 处理API返回结果,确保res是对象
+            const response = res || {};
+            
+            // 设置必要的属性
+            response.identifier = item.identifier || '';
+            response.name = item.name || '';
+            response.unit = item.unit || '';
+            response.unitName = item.unitName || '';
+            response.chartTime = chartTime;
+            response.timeType = timeType;
+            
+            // 初始化趋势数据结构
             const trendData = {
                 xAxis: [],
                 series: [
-                {
-                    name: '',
-                    data: [],
-                    color: '#5470C6'
-                }
+                    {
+                        name: response.name,
+                        data: [],
+                        color: '#5470C6'
+                    }
                 ]
-            }
-            res.timeHistoryList.map(i => {
-                trendData.xAxis.push(i.time);
-                trendData.series[0].data.push(i.value);
-            })
+            };
+
+            // 处理时间历史数据,确保timeHistoryList是数组
+            const timeHistoryList = Array.isArray(response.timeHistoryList) ? response.timeHistoryList : [];
             
-            trendData.series[0].name = item.name;
-            res.trendData = trendData;
-            console.log(`属性 ${item.name || item.identifier} 的历史数据:`, res);
-            return res; // 返回历史数据供Promise.all收集
+            timeHistoryList.forEach(i => {
+                if (i && i.time !== undefined && i.value !== undefined) {
+                    trendData.xAxis.push(i.time);
+                    trendData.series[0].data.push(i.value);
+                }
+            });
+            response.trendData = trendData;
+            response.timeHistoryList = timeHistoryList;
+            console.log(`获取属性 ${item.name || item.identifier} 的历史数据成功,数据条数:`, timeHistoryList.length);
+            
+            return response;
         } catch (error) {
             console.error(`获取属性 ${item.name || item.identifier} 的历史数据失败:`, error);
-            return null; // 出错时返回null
         }
     },
     dateClick(item, dateType) {
-        item.chartTime = '';
+        // 根据时间类型设置默认日期
+        const now = new Date();
+        let defaultDate = '';
+        
+        switch (dateType) {
+            case 'year':
+                // 当年格式:YYYY
+                defaultDate = now.getFullYear().toString();
+                break;
+            case 'month':
+                // 当月格式:YYYY-MM
+                defaultDate = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}`;
+                break;
+            case 'date':
+                // 当日格式:YYYY-MM-DD
+                defaultDate = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`;
+                break;
+            default:
+                defaultDate = '';
+        }
+        
+        item.chartTime = defaultDate;
         item.timeType = dateType;
     },
     // 日期数据格式化
@@ -336,10 +483,6 @@ export default {
             endTime
         };
     },
-    // 默认当月(不再需要,每个图表有独立的时间设置)
-    setMonth() {
-        // 不再需要设置全局温度时间
-    },
   }
 };
 </script>
@@ -373,15 +516,24 @@ export default {
 
 .gauge-charts-wrapper {
   display: flex;
-  gap: 30px;
+  gap: 10px;
   flex-wrap: wrap;
-  width: 50%;
+  width: 60%;
+}
+
+.status-wrapper {
+  width: 40%;
 }
 
 .line-charts-wrapper {
   margin-top: 30px;
 }
 
+.detail-span {
+  margin-right: 10px;
+  margin-left: 10px;
+}
+
 .gauge-card,
 .chart-card {
   flex: 1;
@@ -391,6 +543,7 @@ export default {
   padding: 20px;
   box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
   margin-bottom: 20px;
+  font-size: 16px;
 }
 
 .gauge-title,

+ 3 - 0
src/views/ledgerAssets/components/details/internet.vue

@@ -6,6 +6,7 @@
         <span class="border-span">物联数据</span>
       </div>
     </div>
+    <div>{{ name }}</div>
     <!-- 挤压机 65 -->
     <!-- <InternetExtruder :info="info" v-if="parentClassId == '65'" /> -->
     <!-- 干燥箱 57 -->
@@ -31,6 +32,8 @@
         iotId: null,
         // 设备信息
         info: '',
+        // 设备名称
+        name: '',
         // 父类id
         parentClassId: '65'
       };

+ 3 - 2
src/views/ledgerAssets/equipment/components/equipment-list.vue

@@ -537,12 +537,13 @@ import importDialog from '@/components/upload/import-dialog.vue';
         this.$refs.table.reload({ pageNum: 1, where: where });
       },
       // 跳转到详情页
-      details({ id, code }) {
+      details({ id, code, name }) {
         this.$router.push({
           path: '/ledgerAssets/equipment/detail',
           query: {
             id,
-            code
+            code,
+            name
           }
         });
       },

+ 3 - 0
src/views/ledgerAssets/equipment/detail.vue

@@ -33,6 +33,7 @@
           :is="activeComp"
           :id="id"
           :code="code"
+          :name="name"
           :showTitle="false"
         ></component>
       </div>
@@ -69,6 +70,7 @@
         // 设备主键id
         id: '',
         code: '',
+        name: '',
         activeComp: 'baseInfo',
         tabOptions: [
           { key: 'baseInfo', name: '设备信息' },
@@ -88,6 +90,7 @@
     created() {
       this.id = this.$route.query.id;
       this.code = this.$route.query.code;
+      this.name = this.$route.query.name;
       console.log('routerouterouteroute', this.$route);
     }
   };