浏览代码

能耗监测子系统管理

learshaw 2 天之前
父节点
当前提交
5aa9c99b13

+ 8 - 0
ems-ui-cloud/src/api/adapter/subsystem.js

@@ -26,6 +26,14 @@ export function getSubsystem(id) {
   })
 }
 
+// 查询能源子系统详细
+export function getSubsystemByCode(systemCode) {
+  return request({
+    url: '/ems/subsystem/getByCode?systemCode=' + systemCode,
+    method: 'get'
+  })
+}
+
 // 新增能源子系统
 export function addSubsystem(data) {
   return request({

+ 0 - 21
ems-ui-cloud/src/api/basecfg/objLog.js

@@ -1,27 +1,6 @@
 import request from '@/utils/request'
 
 /**
- * 查询设备上报日志列表
- */
-export function listReportLog(query) {
-  return request({
-    url: '/ems/object/log/reportLog/list',
-    method: 'get',
-    params: query
-  })
-}
-
-/**
- * 获取设备上报日志详细
- */
-export function getReportLog(id) {
-  return request({
-    url: '/ems/object/log/reportLog/' + id,
-    method: 'get'
-  })
-}
-
-/**
  * 查询调用日志列表
  */
 export function listCallLog(query) {

+ 940 - 1143
ems-ui-cloud/src/views/adapter/nhjc/index.vue

@@ -1,1261 +1,1058 @@
 <template>
   <div class="app-container">
-    <el-row :gutter="20">
-      <el-col :span="4" :xs="24">
-        <div class="head-container">
-          <el-input v-model="areaName" placeholder="请输入区域名称" clearable size="small" prefix-icon="el-icon-search"
-                    style="margin-bottom: 20px"
-          />
-        </div>
-        <div class="head-container" style="height: 100vh; overflow: hidden; position: relative;">
-          <el-tree :data="treeAreaOptions" :props="defaultProps" :expand-on-click-node="false"
-                   :filter-node-method="filterNode" ref="tree" node-key="id" default-expand-all highlight-current
-                   @node-click="handleNodeClick" style="height: calc(100vh - 50px); overflow-y: auto;"
-          />
-        </div>
-      </el-col>
-      <el-col :span="20" :xs="24">
-        <div class="contents">
-          <div class="other-content">
-            <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch"
-                     label-width="68px"
-            >
-              <el-form-item label="设备分类" prop="deviceSubCategory">
-                <el-select v-model="queryParams.deviceSubCategory">
-                  <el-option v-for="item in subCategoryOptions" placeholder="设备分类" :label="item.name"
-                             :value="item.code"
-                             :key="item.code"
-                  />
-                </el-select>
+    <!-- 系统基础信息卡片 -->
+    <el-card class="system-info-card">
+      <div slot="header" class="card-header">
+        <span class="title">
+          <i class="el-icon-s-platform"></i>
+          能耗监测
+        </span>
+        <el-tag :type="systemStatus === '1' ? 'success' : 'danger'" effect="dark">
+          {{ systemStatus === '1' ? '正常' : '异常' }}
+        </el-tag>
+      </div>
+
+      <el-row :gutter="20">
+        <el-col :span="8">
+          <div class="info-group">
+            <div class="group-title">系统信息</div>
+            <div class="info-item">
+              <label>系统代码:</label>
+              <span class="code">{{ systemInfo.systemCode }}</span>
+            </div>
+            <div class="info-item">
+              <label>系统名称:</label>
+              <span>{{ systemInfo.systemName }}</span>
+            </div>
+          </div>
+        </el-col>
+        <el-col :span="8">
+          <div class="info-group">
+            <div class="group-title">厂商信息</div>
+            <div class="info-item">
+              <label>对接厂商:</label>
+              <span>{{ systemInfo.manFacturer || '-' }}</span>
+            </div>
+            <div class="info-item">
+              <label>联系人:</label>
+              <span>{{ systemInfo.contactPerson || '-' }}</span>
+            </div>
+            <div class="info-item">
+              <label>联系电话:</label>
+              <span>{{ systemInfo.contactNumber || '-' }}</span>
+            </div>
+          </div>
+        </el-col>
+        <el-col :span="8">
+          <div class="info-group">
+            <div class="group-title">维护信息</div>
+            <div class="info-item">
+              <label>维护人:</label>
+              <span>{{ systemInfo.maintainerPerson || '-' }}</span>
+            </div>
+            <div class="info-item">
+              <label>维护电话:</label>
+              <span>{{ systemInfo.maintainerNumber || '-' }}</span>
+            </div>
+          </div>
+        </el-col>
+      </el-row>
+    </el-card>
+
+    <!-- 系统详情标签页 -->
+    <el-card class="detail-card">
+      <el-tabs v-model="activeTab" @tab-click="handleTabClick">
+        <!-- 系统属性标签页 -->
+        <el-tab-pane label="系统属性" name="attributes">
+          <div class="tab-content">
+            <!-- 协议属性 -->
+            <div class="attr-section" v-if="protocolAttrs.length > 0">
+              <h4 class="section-title">
+                <i class="el-icon-connection"></i>
+                协议信息
+              </h4>
+              <el-table :data="protocolAttrs" border stripe>
+                <el-table-column prop="attrName" label="属性名称" width="200"></el-table-column>
+                <el-table-column label="属性值">
+                  <template slot-scope="scope">
+                    <span v-if="scope.row.attrKey === 'url'" class="url-text">
+                      {{ scope.row.attrValue }}
+                    </span>
+                    <span v-else>{{ scope.row.attrValue || '-' }}</span>
+                  </template>
+                </el-table-column>
+              </el-table>
+            </div>
+
+            <!-- 状态属性 -->
+            <div class="attr-section" v-if="stateAttrs.length > 0">
+              <h4 class="section-title">
+                <i class="el-icon-info"></i>
+                状态信息
+              </h4>
+              <el-table :data="stateAttrs" border stripe>
+                <el-table-column prop="attrName" label="属性名称" width="200"></el-table-column>
+                <el-table-column label="属性值">
+                  <template slot-scope="scope">
+                    <el-tag v-if="scope.row.attrKey === 'interfaceStatus'"
+                            :type="scope.row.attrValue === '1' ? 'success' : 'danger'">
+                      {{ scope.row.attrValueName }}
+                    </el-tag>
+                    <span v-else>{{ scope.row.attrValueName || scope.row.attrValue || '-' }}</span>
+                  </template>
+                </el-table-column>
+                <el-table-column prop="updateTime" label="更新时间" width="180"></el-table-column>
+              </el-table>
+            </div>
+          </div>
+        </el-tab-pane>
+
+        <!-- 系统能力标签页 -->
+        <el-tab-pane label="系统能力" name="abilities">
+          <div class="tab-content">
+            <el-table :data="systemAbilities" border stripe v-loading="abilityLoading">
+              <el-table-column prop="abilityName" label="能力名称" width="200"></el-table-column>
+              <el-table-column prop="abilityKey" label="能力标识" width="180"></el-table-column>
+              <el-table-column prop="abilityDesc" label="能力描述"></el-table-column>
+              <el-table-column label="操作" width="150" align="center">
+                <template slot-scope="scope">
+                  <el-button
+                    type="primary"
+                    size="mini"
+                    icon="el-icon-caret-right"
+                    @click="executeAbility(scope.row)"
+                    :loading="scope.row.executing">
+                    执行
+                  </el-button>
+                </template>
+              </el-table-column>
+            </el-table>
+          </div>
+        </el-tab-pane>
+
+        <!-- 关联设备标签页 -->
+        <el-tab-pane label="关联设备" name="devices">
+          <div class="tab-content">
+            <!-- 设备统计 -->
+            <div class="device-stats">
+              <el-row :gutter="20">
+                <el-col :span="6">
+                  <div class="stat-item">
+                    <div class="stat-value">{{ deviceStats.total }}</div>
+                    <div class="stat-label">设备总数</div>
+                  </div>
+                </el-col>
+                <el-col :span="6">
+                  <div class="stat-item online">
+                    <div class="stat-value">{{ deviceStats.online }}</div>
+                    <div class="stat-label">在线设备</div>
+                  </div>
+                </el-col>
+                <el-col :span="6">
+                  <div class="stat-item offline">
+                    <div class="stat-value">{{ deviceStats.offline }}</div>
+                    <div class="stat-label">离线设备</div>
+                  </div>
+                </el-col>
+                <el-col :span="6">
+                  <div class="stat-item">
+                    <div class="stat-value">{{ deviceStats.points }}</div>
+                    <div class="stat-label">测点总数</div>
+                  </div>
+                </el-col>
+              </el-row>
+            </div>
+
+            <!-- 设备列表 -->
+            <el-table
+              :data="deviceList"
+              border
+              stripe
+              v-loading="deviceLoading"
+              @row-click="handleDeviceClick"
+              ref="deviceTable">
+              <el-table-column type="expand">
+                <template slot-scope="props">
+                  <div class="device-detail">
+                    <el-tabs v-model="props.row.detailTab">
+                      <el-tab-pane label="设备属性" name="attrs">
+                        <el-descriptions :column="2" border size="small">
+                          <el-descriptions-item label="IP地址">
+                            {{ getDeviceAttr(props.row.deviceCode, 'ip') }}
+                          </el-descriptions-item>
+                          <el-descriptions-item label="网关地址">
+                            {{ getDeviceAttr(props.row.deviceCode, 'gateway') }}
+                          </el-descriptions-item>
+                          <el-descriptions-item label="子网掩码">
+                            {{ getDeviceAttr(props.row.deviceCode, 'subnetMask') }}
+                          </el-descriptions-item>
+                        </el-descriptions>
+                      </el-tab-pane>
+                      <el-tab-pane label="测点信息" name="points">
+                        <div v-for="(channel, idx) in getDeviceChannels(props.row.deviceCode)" :key="idx">
+                          <h5>{{ channel.name }} ({{ channel.points.length }}个测点)</h5>
+                          <el-table :data="channel.points" size="mini" max-height="200">
+                            <el-table-column prop="name" label="测点名称"></el-table-column>
+                            <el-table-column prop="key" label="测点标识"></el-table-column>
+                            <el-table-column prop="value" label="当前值">
+                              <template slot-scope="scope">
+                                {{ scope.row.value || '-' }}
+                              </template>
+                            </el-table-column>
+                            <el-table-column prop="updateTime" label="更新时间"></el-table-column>
+                          </el-table>
+                        </div>
+                      </el-tab-pane>
+                    </el-tabs>
+                  </div>
+                </template>
+              </el-table-column>
+              <el-table-column prop="deviceCode" label="设备代码" width="150"></el-table-column>
+              <el-table-column prop="deviceName" label="设备名称"></el-table-column>
+              <el-table-column prop="location" label="安装位置"></el-table-column>
+              <el-table-column prop="areaCode" label="区域" width="150">
+                <template slot-scope="scope">
+                  {{ scope.row.areaCode.includes('3001') ? '北区' : '南区' }}
+                </template>
+              </el-table-column>
+              <el-table-column label="设备状态" width="100" align="center">
+                <template slot-scope="scope">
+                  <el-tag :type="scope.row.deviceStatus === 1 ? 'success' : 'info'">
+                    {{ scope.row.deviceStatus === 1 ? '在线' : '离线' }}
+                  </el-tag>
+                </template>
+              </el-table-column>
+              <el-table-column label="操作" width="100" align="center">
+                <template slot-scope="scope">
+                  <el-dropdown
+                    trigger="click"
+                    @command="handleDeviceCommand"
+                    @visible-change="(visible) => handleAbilityLoad(visible, scope.row)">
+                    <el-button type="text" size="mini">
+                      操作<i class="el-icon-arrow-down el-icon--right"></i>
+                    </el-button>
+                    <el-dropdown-menu slot="dropdown">
+                      <el-dropdown-item
+                        v-for="ability in deviceAbilities[scope.row.deviceCode] || []"
+                        :key="ability.abilityKey"
+                        :command="{device: scope.row, ability: ability}">
+                        {{ ability.abilityName }}
+                      </el-dropdown-item>
+                      <el-dropdown-item
+                        v-if="!deviceAbilities[scope.row.deviceCode] || deviceAbilities[scope.row.deviceCode].length === 0"
+                        disabled>
+                        无可用操作
+                      </el-dropdown-item>
+                    </el-dropdown-menu>
+                  </el-dropdown>
+                </template>
+              </el-table-column>
+            </el-table>
+          </div>
+        </el-tab-pane>
+
+        <!-- 调用日志标签页 -->
+        <el-tab-pane label="调用日志" name="callLogs">
+          <div class="tab-content">
+            <el-form :inline="true" :model="callLogQuery" class="log-filter">
+              <el-form-item label="时间范围">
+                <el-date-picker
+                  v-model="callLogQuery.dateRange"
+                  type="datetimerange"
+                  range-separator="至"
+                  start-placeholder="开始日期"
+                  end-placeholder="结束日期"
+                  value-format="yyyy-MM-dd HH:mm:ss">
+                </el-date-picker>
               </el-form-item>
-              <el-form-item label="归属设施" prop="refFacs">
-                <el-select v-model="queryParams.refFacs">
-                  <el-option v-for="item in facsOptions" :label="item.facsName" :value="item.facsCode"
-                             :key="item.facsCode"
-                  />
-                </el-select>
+              <el-form-item label="能力标识">
+                <el-input v-model="callLogQuery.abilityKey" placeholder="请输入能力标识" clearable></el-input>
               </el-form-item>
-              <el-form-item label="子系统" prop="subsystemCode">
-                <el-select v-model="queryParams.subsystemCode">
-                  <el-option v-for="item in subsystemOptions" :label="item.systemName" :value="item.systemCode"
-                             :key="item.systemCode"
-                  />
+              <el-form-item label="调用状态">
+                <el-select v-model="callLogQuery.callStatus" placeholder="全部" clearable>
+                  <el-option label="成功" :value="0"></el-option>
+                  <el-option label="进行中" :value="1"></el-option>
+                  <el-option label="失败" :value="2"></el-option>
                 </el-select>
               </el-form-item>
               <el-form-item>
-                <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
-                <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+                <el-button type="primary" @click="queryCallLogs">查询</el-button>
+                <el-button @click="resetCallLogQuery">重置</el-button>
               </el-form-item>
             </el-form>
 
-            <el-row :gutter="10" class="mb8">
-              <el-col :span="1.5">
-                <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
-                           v-hasPermi="['ems:device:add']"
-                >新增
-                </el-button>
-              </el-col>
-              <el-col :span="1.5">
-                <el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate"
-                           v-hasPermi="['ems:device:edit']"
-                >修改
-                </el-button>
-              </el-col>
-              <el-col :span="1.5">
-                <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple"
-                           @click="handleDelete"
-                           v-hasPermi="['ems:device:remove']"
-                >删除
-                </el-button>
-              </el-col>
-              <el-col :span="1.5">
-                <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport"
-                           v-hasPermi="['ems:device:export']"
-                >导出
-                </el-button>
-              </el-col>
-              <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
-            </el-row>
-          </div>
-
-          <div class="table-content">
-            <!--分页-->
-            <div class="button-group-container">
-              <el-button-group>
-                <el-button :type="primary1" icon="el-icon-s-fold" @click="switchData(1)"/>
-                <el-button :type="primary2" icon="el-icon-menu" @click="switchData(2)"/>
-              </el-button-group>
-            </div>
-
-            <el-table v-loading="loading" :data="deviceList" @selection-change="handleSelectionChange"
-                      v-if="istable === 1">
-              <el-table-column type="selection" width="55" align="center"/>
-              <el-table-column label="设备名称" align="left" prop="deviceName"/>
-              <el-table-column label="安装位置" align="left" prop="areaPath" width="220px"/>
-              <el-table-column label="归属设施" align="center" prop="refFacsName"/>
-              <el-table-column label="设备分类" align="center" prop="deviceCategoryName"/>
-              <el-table-column label="子系统" align="center" prop="subsystemName"/>
-              <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+            <el-table :data="callLogList" border stripe v-loading="logLoading">
+              <el-table-column prop="objCode" label="对象代码" min-width="150"></el-table-column>
+              <el-table-column prop="objName" label="对象名称" min-width="200"></el-table-column>
+              <el-table-column prop="abilityName" label="能力名称" min-width="150"></el-table-column>
+              <el-table-column prop="callTime" label="调用时间" width="180"></el-table-column>
+              <el-table-column label="调用状态" width="100" align="center">
                 <template slot-scope="scope">
-                  <el-button size="mini" type="text" icon="el-icon-info" @click="handleDevProcess(scope.row)"
-                             v-hasPermi="['basecfg:device:edit']" v-if="shouldShowDevProcessButton(scope.row)"
-                  >
-                    器件
-                  </el-button>
-                  <el-button size="mini" type="text" icon="el-icon-info" @click="handleDetail(scope.row)"
-                             v-hasPermi="['basecfg:device:edit']"
-                  >
-                    详情
-                  </el-button>
-                  <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
-                             v-hasPermi="['basecfg:device:edit']"
-                  >
-                    修改
-                  </el-button>
-                  <el-button size="mini" type="text" icon="el-icon-delete" class="deleteBtn"
-                             @click="handleDelete(scope.row)" v-hasPermi="['basecfg:device:remove']"
-                  >
-                    删除
-                  </el-button>
-
+                  <el-tag size="small" :type="getCallStatusType(scope.row.callStatus)">
+                    {{ formatCallStatus(scope.row.callStatus) }}
+                  </el-tag>
+                </template>
+              </el-table-column>
+              <el-table-column label="操作" width="80" align="center">
+                <template slot-scope="scope">
+                  <el-button type="text" size="mini" @click="handleCallLogDetail(scope.row)">详情</el-button>
                 </template>
               </el-table-column>
             </el-table>
 
-            <div v-else-if="istable === 2">
-              <el-row :gutter="20" class="device-list">
-                <el-col v-for="device in deviceList" :key="device.id" :span="6">
-                  <div :class="`device-card ${backStyle(device.areaPath)}`">
-                    <div class="device-header">
-                      <i class="el-icon-s-operation" style="margin-right: 8px;"></i>
-                      {{ device.deviceName }}
-                    </div>
-                    <div class="device-body">
-                      <p>设备代码:<span class="device-code">{{ device.deviceCode }}</span></p>
-                      <p>安装位置:<span class="deviceOthers">{{ device.areaPath }}</span></p>
-                      <p>归属设施:<span class="deviceOthers">{{ device.refFacsName }}</span></p>
-                      <p>设备分类:<span class="deviceOthers">{{ device.deviceCategoryName }}</span></p>
-                      <p>子系统:<span class="deviceOthers">{{ device.subsystemName }}</span></p>
-                    </div>
-                    <div class="device-footer">
-                      <el-button size="mini" plain icon=" el-icon-document" @click="handleDetail(device)">详情
-                      </el-button>
-                      <el-button size="mini" plain icon="el-icon-edit" @click="handleUpdate(device)">修改</el-button>
-                      <el-button size="mini" plain icon="el-icon-delete" type="danger" @click="handleDelete(device)">
-                        删除
-                      </el-button>
-                    </div>
-                  </div>
-                </el-col>
-              </el-row>
-            </div>
+            <pagination
+              v-show="callLogTotal > 0"
+              :total="callLogTotal"
+              :page.sync="callLogQuery.pageNum"
+              :limit.sync="callLogQuery.pageSize"
+              @pagination="queryCallLogs"
+            />
+          </div>
+        </el-tab-pane>
+
+        <!-- 事件日志标签页 -->
+        <el-tab-pane label="事件日志" name="eventLogs">
+          <div class="tab-content">
+            <el-form :inline="true" :model="eventLogQuery" class="log-filter">
+              <el-form-item label="时间范围">
+                <el-date-picker
+                  v-model="eventLogQuery.dateRange"
+                  type="datetimerange"
+                  range-separator="至"
+                  start-placeholder="开始日期"
+                  end-placeholder="结束日期"
+                  value-format="yyyy-MM-dd HH:mm:ss">
+                </el-date-picker>
+              </el-form-item>
+              <el-form-item label="事件标识">
+                <el-input v-model="eventLogQuery.eventKey" placeholder="请输入事件标识" clearable></el-input>
+              </el-form-item>
+              <el-form-item>
+                <el-button type="primary" @click="queryEventLogs">查询</el-button>
+                <el-button @click="resetEventLogQuery">重置</el-button>
+              </el-form-item>
+            </el-form>
 
+            <el-table :data="eventLogList" border stripe v-loading="eventLogLoading">
+              <el-table-column prop="objCode" label="对象编号" min-width="150"></el-table-column>
+              <el-table-column prop="objName" label="对象名称" min-width="200"></el-table-column>
+              <el-table-column prop="eventName" label="事件名称" min-width="200"></el-table-column>
+              <el-table-column prop="eventTime" label="事件时间" width="180"></el-table-column>
+              <el-table-column label="操作" width="80" align="center">
+                <template slot-scope="scope">
+                  <el-button type="text" size="mini" @click="handleEventLogDetail(scope.row)">详情</el-button>
+                </template>
+              </el-table-column>
+            </el-table>
 
-            <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
-                        :limit.sync="queryParams.pageSize"
-                        @pagination="getList"
+            <pagination
+              v-show="eventLogTotal > 0"
+              :total="eventLogTotal"
+              :page.sync="eventLogQuery.pageNum"
+              :limit.sync="eventLogQuery.pageSize"
+              @pagination="queryEventLogs"
             />
+          </div>
+        </el-tab-pane>
+      </el-tabs>
+    </el-card>
+
+    <!-- 执行结果对话框 -->
+    <el-dialog
+      :title="executeDialog.title"
+      :visible.sync="executeDialog.visible"
+      width="600px">
+      <div class="execute-result">
+        <el-alert
+          :title="executeDialog.status"
+          :type="executeDialog.type"
+          :description="executeDialog.message"
+          show-icon>
+        </el-alert>
+        <div v-if="executeDialog.data" class="result-data">
+          <pre>{{ JSON.stringify(executeDialog.data, null, 2) }}</pre>
+        </div>
+      </div>
+      <span slot="footer">
+        <el-button @click="executeDialog.visible = false">关闭</el-button>
+      </span>
+    </el-dialog>
+
+    <!-- 调用日志详情弹窗 -->
+    <el-dialog :visible.sync="callLogDetailDialog" title="调用日志详情" width="60%">
+      <div v-if="callLogDetailData">
+        <el-descriptions :column="2" border>
+          <el-descriptions-item label="对象代码">{{ callLogDetailData.objCode }}</el-descriptions-item>
+          <el-descriptions-item label="模型代码">{{ callLogDetailData.modelCode }}</el-descriptions-item>
+          <el-descriptions-item label="能力标识">{{ callLogDetailData.abilityKey }}</el-descriptions-item>
+          <el-descriptions-item label="调用时间">{{ callLogDetailData.callTime }}</el-descriptions-item>
+          <el-descriptions-item label="响应时间">{{ callLogDetailData.resTime }}</el-descriptions-item>
+          <el-descriptions-item label="调用结果">
+            <el-tag :type="getCallStatusType(callLogDetailData.callStatus)">
+              {{ formatCallStatus(callLogDetailData.callStatus) }}
+            </el-tag>
+          </el-descriptions-item>
+        </el-descriptions>
+
+        <div style="margin-top: 20px;">
+          <h4>调用载体</h4>
+          <pre style="white-space: pre-wrap; background-color: #f5f5f5; padding: 10px; border-radius: 4px; max-height: 300px; overflow: auto;">{{ callLogDetailData.callPayload }}</pre>
+        </div>
 
-            <!-- 添加或修改能源设备对话框 -->
-            <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
-              <el-form ref="form" :model="form" :rules="rules" label-width="80px">
-                <el-form-item label="归属设施" prop="refFacs">
-                  <el-select v-model="form.refFacs">
-                    <el-option v-for="item in facsOptions" :label="item.facsName" :value="item.facsCode"
-                               :key="item.facsCode"
-                    />
-                  </el-select>
-                </el-form-item>
-
-                <el-form-item label="设备代码" prop="deviceCode">
-                  <el-input v-model="form.deviceCode" placeholder="请输入设备代码"/>
-                </el-form-item>
-                <el-form-item label="设备名称" prop="deviceName">
-                  <el-input v-model="form.deviceName" placeholder="请输入设备名称"/>
-                </el-form-item>
-
-
-                <el-form-item label="功能类型" prop="psCode" v-if="queryParams.deviceCategory === 'W'">
-                  <el-select v-model="form.psCode">
-                    <el-option v-for="item in devOptions" :label="item.psName" :value="item.psCode"
-                               :key="item.psCode"
-                    />
-                  </el-select>
-                </el-form-item>
-
-                <el-form-item label="设备类型" prop="deviceType">
-                  <el-select v-model="form.deviceCategory">
-                    <el-option v-for="item in subCategoryOptions" :label="item.name" :value="item.code"
-                               :key="item.code"
-                    />
-                  </el-select>
-                </el-form-item>
-                <el-form-item label="设备模型" prop="deviceModel">
-                  <el-select v-model="form.deviceModel" style="width:100%" @change="handleModelChange">
-                    <el-option
-                      v-for="item in modelList"
-                      :label="item.modelName"
-                      :value="item.modelCode"
-                      :key="item.modelCode"
-                    />
-                  </el-select>
-                </el-form-item>
-                <!-- 这里可以展示属性名称和属性值 -->
-                <div v-if="attrList.length > 0" class="attr-list-container">
-                  <h3>模型属性:</h3>
-                  <ul>
-                    <li v-for="attr in attrList" :key="attr.attrKey" class="attr-item">
-                      <span class="attr-name">{{ attr.attrName }} ({{ attr.attrUnit }}):</span>
-                      <!-- 使用 el-input 组件允许用户编辑属性值 -->
-                      <el-input
-                        v-model="attrValuesMap[attr.attrKey]"
-                        placeholder="点击编辑"
-                        size="small"
-                        @blur="updateAttrValue(attr.attrKey, attrValuesMap[attr.attrKey])"
-                      >
-                      </el-input>
-                    </li>
-                  </ul>
-                </div>
-                <h3 class="attr-list-container" v-if="attrList.length > 0">自定义属性
-                  <el-form-item label="" prop="attrList">
-                    <el-table class="attr-table" v-loading="loading" :data="form.customAttrs" max-height="280px"
-                              key="'customAttrs'"
-                    >
-                      <el-table-column label="标识" align="center" prop="attrKey">
-                        <template slot-scope="scope">
-                          <el-input size="mini" v-model="scope.row.attrKey" placeholder="请输入标识"/>
-                        </template>
-                      </el-table-column>
-                      <el-table-column label="属性名" align="center" prop="attrName">
-                        <template slot-scope="scope">
-                          <el-input size="mini" v-model="scope.row.attrName" placeholder="请输入属性名"/>
-                        </template>
-                      </el-table-column>
-                      <el-table-column label="属性值" align="center" prop="attrValue">
-                        <template slot-scope="scope">
-                          <el-input size="mini" v-model="scope.row.attrValue" placeholder="请输入属性值"/>
-                        </template>
-                      </el-table-column>
-                      <el-table-column align="center" label="操作">
-                        <template slot="header">
-                          <div class="operateBtns" @click="addCustomAttr">
-                            <span>添加</span><i class="el-icon-circle-plus-outline"></i>
-                          </div>
-                        </template>
-                        <template slot-scope="scope">
-                          <i class="el-icon-delete" @click="deleteCustomAttr(scope.$index)"></i>
-                        </template>
-                      </el-table-column>
-                    </el-table>
-                  </el-form-item>
-                </h3>
-                <el-form-item label="子系统" prop="subsystemCode">
-                  <el-select v-model="form.subsystemCode">
-                    <el-option v-for="item in subsystemOptions" :label="item.systemName" :value="item.systemCode"
-                               :key="item.systemCode"
-                    />
-                  </el-select>
-                </el-form-item>
-              </el-form>
-              <div slot="footer" class="dialog-footer">
-                <el-button type="primary" @click="submitForm">确 定</el-button>
-                <el-button @click="cancel">取 消</el-button>
-              </div>
-            </el-dialog>
-
-            <!--设备器件-->
-            <el-drawer :title=ComponentRow.deviceName size="80%" :visible.sync="showDevProcessDrawer" direction="rtl">
-              <div class="drawer-content" style="padding-left:50px">
-                <el-row :gutter="10" class="mb8">
-                  <el-col :span="1.5">
-                    <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleComponentAdd"
-                               v-hasPermi="['ems:component:add']"
-                    >新增
-                    </el-button>
-                  </el-col>
-                </el-row>
-                <el-table v-loading="loading" :data="ComponentList">
-                  <el-table-column type="selection" width="55" align="center"/>
-                  <el-table-column label="部件编码" align="center" prop="compoCode"/>
-                  <el-table-column label="部件标签" align="center" prop="compoTag">
-                    <template slot-scope="scope">
-                      {{ objComTypeMapping[scope.row.compoTag] }}
-                    </template>
-                  </el-table-column>
-                  <el-table-column label="工艺标识代码" align="center" prop="psCode"/>
-                  <el-table-column label="外系统部件编码" align="center" prop="extCompoCode"/>
-                  <el-table-column label="部件模型" align="center" prop="compoModel"/>
-                  <el-table-column label="部件品牌" align="center" prop="compoBrand"/>
-                  <el-table-column label="部件型号" align="center" prop="compoSpec"/>
-                  <el-table-column label="祖籍列表" align="center" prop="ancestors"/>
-                  <el-table-column label="上级部件" align="center" prop="parentEqpt"/>
-
-                  <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
-                    <template slot-scope="scope">
-                      <el-button size="mini" type="text" icon="el-icon-edit" @click="handleComponentUpdate(scope.row)"
-                                 v-hasPermi="['ems:component:edit']"
-                      >
-                        修改
-                      </el-button>
-                      <el-button size="mini" type="text" icon="el-icon-delete" class="deleteBtn"
-                                 @click="handleComponentDelete(scope.row)" v-hasPermi="['ems:component:remove']"
-                      >
-                        删除
-                      </el-button>
-                    </template>
-                  </el-table-column>
-                </el-table>
-                <pagination v-show="total>0" :total="total" :page.sync="queryComponentParams.pageNum"
-                            :limit.sync="queryComponentParams.pageSize"
-                            @pagination="getComponentList"
-                />
-
-                <!-- 添加或修改设备器件对话框 -->
-                <el-dialog :title="title" :visible.sync="componentOpen" width="500px" append-to-body>
-                  <el-form ref="componentForm" :model="componentForm" :rules="componentRules" label-width="150px">
-                    <!--                <el-form-item label="设备code" prop="deviceCode">-->
-                    <!--                  <el-input v-model="componentForm.deviceCode" placeholder="请输入设备code" />-->
-                    <!--                </el-form-item>-->
-                    <el-form-item label="部件编码" prop="compoCode">
-                      <el-input v-model="componentForm.compoCode" placeholder="请输入部件编码"/>
-                    </el-form-item>
-                    <el-form-item label="部件标签" prop="compoTag">
-                      <el-select v-model="componentForm.compoTag" placeholder="请输入部件标签">
-                        <el-option v-for="item in objComTypeOptions"
-                                   :label="item.name"
-                                   :value="item.code"
-                                   :key="item.code"
-                        />
-
-                      </el-select>
-                    </el-form-item>
-                    <el-form-item label="工艺标签代码" prop="psCode">
-                      <el-select v-model="componentForm.psCode" placeholder="请输入工艺标签代码">
-                        <el-option v-for="item in devOptions" :label="item.psCode" :value="item.psCode"
-                                   :key="item.psCode"/>
-                      </el-select>
-                    </el-form-item>
-                    <el-form-item label="外系统部件编码" prop="extCompoCode">
-                      <el-input v-model="componentForm.extCompoCode" placeholder="请输入外系统部件编码"/>
-                    </el-form-item>
-                    <el-form-item label="部件模型" prop="compoModel">
-                      <el-select v-model="componentForm.compoModel" placeholder="请输入部件模型">
-                        <el-option v-for="item in this.modelList" :label="item.modelCode" :value="item.modelCode"
-                                   :key="item.modelCode"
-                        />
-                      </el-select>
-                    </el-form-item>
-                    <el-form-item label="部件品牌" prop="compoBrand">
-                      <el-input v-model="componentForm.compoBrand" placeholder="请输入部件品牌"/>
-                    </el-form-item>
-                    <el-form-item label="部件型号" prop="compoSpec">
-                      <el-input v-model="componentForm.compoSpec" placeholder="请输入部件型号"/>
-                    </el-form-item>
-                    <el-form-item label="祖籍列表" prop="ancestors">
-                      <el-input v-model="componentForm.ancestors" placeholder="请输入祖籍列表"/>
-                    </el-form-item>
-                    <el-form-item label="上级列表" prop="parentCompo">
-                      <el-input v-model="componentForm.parentCompo" placeholder="请输入上级列表"/>
-                    </el-form-item>
-
-                  </el-form>
-                  <div slot="footer" class="dialog-footer">
-                    <el-button type="primary" @click="submitComponentForm">确 定</el-button>
-                    <el-button @click="ComponentCancel">取 消</el-button>
-                  </div>
-                </el-dialog>
-              </div>
-            </el-drawer>
-
-            <!-- 详情弹框 -->
-            <el-dialog :visible.sync="showDrawer" title="设备详情">
-              <div v-if="curRow">
-                <!-- 设备基本信息 -->
-                <el-card class="box-card">
-                  <div slot="header" class="clearfix">
-                    <span class="section-title">设备基本信息</span>
-                  </div>
-                  <div>
-                    <p>设备代码:{{ curRow.deviceCode }}</p>
-                    <p>设备名称:{{ curRow.deviceName }}</p>
-                    <p>设备类型:{{ curRow.deviceCategoryName }}</p>
-                    <p>子系统:{{ curRow.subsystemName }}</p>
-                    <p>归属区域:{{ curRow.areaPath }}</p>
-                    <p>归属设施:{{ curRow.refFacsName }}</p>
-                  </div>
-                </el-card>
-                <el-card class="box-card" style="margin-top: 10px">
-                  <div slot="header" class="clearfix">
-                    <span class="section-title">状态属性</span>
-                  </div>
-                  <div>
-                    <p v-for="attr in statusAttr" :key="attr.attr">{{ attr.attr }}:{{ attr.attrValue }} {{
-                        attr.attrUnit
-                      }}</p>
-                  </div>
-                </el-card>
-                <!-- 属性信息 -->
-                <el-card class="box-card" v-if="attrData.length > 0">
-                  <div slot="header" class="clearfix">
-                    <span class="section-title">属性定义</span>
-                  </div>
-                  <div v-for="(item, index) in attrData" :key="index">
-                    <p>属性名称:{{ item.attrName }}</p>
-                    <p>属性值:{{ item.attrValue }}</p>
-                    <p>属性单位:{{ item.attrUnit }}</p>
-                    <!-- 在每个条目之后添加横线,除了最后一个条目 -->
-                    <div v-if="index < attrData.length - 1" class="divider"></div>
-                  </div>
-                </el-card>
-                <!-- 能力信息 -->
-                <el-card class="box-card" v-if="abilityData.length > 0">
-                  <div slot="header" class="clearfix">
-                    <span class="section-title">能力定义</span>
-                  </div>
-                  <div v-for="(item, index) in abilityData" :key="index">
-                    <p>能力名称:{{ item.abilityName }}</p>
-                    <p>能力键:{{ item.abilityKey }}</p>
-                    <p>能力参数:{{ item.abilityParam }}</p>
-                    <p>能力描述:{{ item.abilityDesc }}</p>
-                    <!-- 在每个条目之后添加横线,除了最后一个条目 -->
-                    <div v-if="index < abilityData.length - 1" class="divider"></div>
-                  </div>
-                </el-card>
-                <!-- 事件信息 -->
-                <el-card class="box-card" v-if="eventData.length > 0">
-                  <div slot="header" class="clearfix">
-                    <span class="section-title">事件定义</span>
-                  </div>
-                  <div v-for="(item, index) in eventData" :key="index">
-                    <p>事件名称:{{ item.eventKey }}</p>
-                    <p>事件类型:{{ item.eventType === 1 ? '消息上报' : '异常告警' }}</p>
-                    <p>事件代码:{{ item.eventCode }}</p>
-                    <p>外部事件代码:{{ item.extEventCode }}</p>
-                    <!-- 在每个条目之后添加横线,除了最后一个条目 -->
-                    <div v-if="index < eventData.length - 1" class="divider"></div>
-                  </div>
-                </el-card>
-              </div>
-            </el-dialog>
+        <div style="margin-top: 20px;">
+          <h4>响应载体</h4>
+          <pre style="white-space: pre-wrap; background-color: #f5f5f5; padding: 10px; border-radius: 4px; max-height: 300px; overflow: auto;">{{ callLogDetailData.resPayload }}</pre>
+        </div>
+      </div>
+    </el-dialog>
+
+    <!-- 事件日志详情弹窗 -->
+    <el-dialog :visible.sync="eventLogDetailDialog" title="事件日志详情" width="60%">
+      <div v-if="eventLogDetailData">
+        <el-descriptions :column="2" border>
+          <el-descriptions-item label="对象编号">{{ eventLogDetailData.objCode }}</el-descriptions-item>
+          <el-descriptions-item label="对象名称">{{ eventLogDetailData.objName }}</el-descriptions-item>
+          <el-descriptions-item label="事件名称">{{ eventLogDetailData.eventName }}</el-descriptions-item>
+          <el-descriptions-item label="事件标识">{{ eventLogDetailData.eventKey }}</el-descriptions-item>
+          <el-descriptions-item label="事件时间" :span="2">{{ eventLogDetailData.eventTime }}</el-descriptions-item>
+        </el-descriptions>
+
+        <div style="margin-top: 20px;">
+          <h4>事件描述</h4>
+          <div style="background-color: #f5f5f5; padding: 10px; border-radius: 4px;">
+            {{ eventLogDetailData.eventDetail || '无' }}
           </div>
         </div>
-      </el-col>
-    </el-row>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
 <script>
-import {addDevice, delDevice, getDevice, listDevRecursionByArea, updateDevice} from '@/api/device/device'
-import {areaTreeSelect} from '@/api/basecfg/area'
-import {getFacsCategorygetByCode, listAllFacs} from '@/api/basecfg/emsfacs'
-import {listSubsystemAll} from '@/api/adapter/subsystem'
-import {getModelByCode, listAllModel} from '@/api/basecfg/objModel'
-import {getObjAttr} from '@/api/basecfg/objAttribute'
-import {addAttrValueBatch} from '@/api/basecfg/objAttributeValue'
-import {addComponent, delComponent, getComponent, listByDevice, updateComponent} from '@/api/basecfg/component'
-import Treeselect from '@riophae/vue-treeselect'
-import '@riophae/vue-treeselect/dist/vue-treeselect.css'
+import { getSubsystemByCode } from '@/api/adapter/subsystem'
+import { getModelByCode } from '@/api/basecfg/objModel'
+import { getObjAttr } from '@/api/basecfg/objAttribute'
+import { listcallAbility } from '@/api/basecfg/objAbility'
+import { getByCondition } from '@/api/device/device'
+import { listCallLog, listEventLog, getCallLog, getEventLog } from '@/api/basecfg/objLog'
 
 export default {
-  name: 'Device',
-  components: {Treeselect},
+  name: 'SubsystemIntegration',
   data() {
     return {
-      primary1: 'primary',
-      primary2: '',
-      ComponentRow: [],
-      componentForm: {},
-      subcategoryCode: '',
-      attrList: [], // 属性模板数组
-      attrValues: [],
-      ComponentList: [],
-      attrValuesMap: {},
-      modelList: [],
-      showDrawer: false,
-      showDevProcessDrawer: false,
-      componentOpen: false,
-      istable: 2,
-      // 遮罩层
-      loading: true,
-      // 选中数组
-      ids: [],
-      // 非单个禁用
-      single: true,
-      // 非多个禁用
-      multiple: true,
-      // 显示搜索条件
-      showSearch: true,
-      // 总条数
-      total: 0,
-      // 能源设备表格数据
+      // 系统代码
+      systemCode: 'SYS_NHJC',
+      // 系统信息
+      systemInfo: {},
+      // 系统状态
+      systemStatus: '1',
+      // 当前标签页
+      activeTab: 'attributes',
+      // 协议属性
+      protocolAttrs: [],
+      // 状态属性
+      stateAttrs: [],
+      // 系统能力
+      systemAbilities: [],
+      abilityLoading: false,
+      // 设备列表
       deviceList: [],
-      // 弹出层标题
-      title: '',
-      // 是否显示弹出层
-      open: false,
-      // 区域名称
-      areaName: undefined,
-      // 区域树选项
-      treeAreaOptions: undefined,
-      totalAreaOptions: undefined,
-      // 设施选项
-      facsOptions: undefined,
-      // 设备分类
-      subCategoryOptions: undefined,
-      subsystemOptions: undefined,
-      devOptions: undefined,
-
-      defaultProps: {
-        children: 'children',
-        label: 'label'
+      deviceLoading: false,
+      deviceAttrs: {},
+      deviceChannels: {},
+      // 设备能力缓存
+      deviceAbilities: {},
+      // 设备统计
+      deviceStats: {
+        total: 0,
+        online: 0,
+        offline: 0,
+        points: 0
       },
-      // 查询参数
-      queryParams: {
-        psCode: null,
+      // 所有模型代码(系统 + 设备)
+      allModelCodes: [],
+      // 调用日志查询
+      callLogQuery: {
+        dateRange: [],
+        abilityKey: '',
+        callStatus: '',
         pageNum: 1,
-        pageSize: 10,
-        deviceCode: null,
-        deviceSubCategory: '',
-        deviceCategory: 'E',
-        locationType: null,
-        locationRef: null,
-        refFacs: null,
-        customAttrs: null
+        pageSize: 10
       },
-      queryComponentParams: {
+      callLogList: [],
+      callLogTotal: 0,
+      logLoading: false,
+      // 事件日志查询
+      eventLogQuery: {
+        dateRange: [],
+        eventKey: '',
         pageNum: 1,
         pageSize: 10
       },
-      objComTypeMapping: {
-        1: '总开',
-        2: '照明',
-        3: '风机'
-      },
-      objComTypeOptions: [
-        {code: 1, name: '总开'},
-        {code: 2, name: '照明'},
-        {code: 3, name: '风机'}
-
-      ],
-      curRow: {},
-      attrData: [],
-      abilityData: [],
-      eventData: [],
-      statusAttr: [{
-        attr: '用能',
-        attrUnit: 'kW',
-        attrValue: '10'
-      },
-        {
-          attr: '能耗',
-          attrUnit: 'kW·h',
-          attrValue: '20'
-        },
-        {
-          attr: '趋势',
-          attrUnit: '',
-          attrValue: '上升'
-        },
-        {
-          attr: '能耗排名',
-          attrUnit: '',
-          attrValue: '1'
-        }
-      ],
-      // 表单参数
-      form: {
-        customAttrs: [] // 自定义属性数组
-      },
-      // 表单校验
-      rules: {
-        refFacs: [
-          {required: true, message: '归属设施', trigger: 'blur'}
-        ],
-        refArea: [
-          {required: true, message: '安装位置', trigger: 'blur'}
-        ],
-        deviceCode: [
-          {required: true, message: '设备代码不能为空', trigger: 'blur'}
-        ],
-        deviceName: [
-          {required: true, message: '设备名称不能为空', trigger: 'blur'}
-        ]
-      },
-      componentRules: {
-        deviceCode: [
-          {required: true, message: '设备code不能为空', trigger: 'blur'}
-        ],
-        compoCode: [
-          {required: true, message: '部件编码不能为空', trigger: 'blur'}
-        ],
-        psCode: [
-          {required: true, message: '工艺标签代码不能为空', trigger: 'blur'}
-        ]
+      eventLogList: [],
+      eventLogTotal: 0,
+      eventLogLoading: false,
+      // 调用日志详情
+      callLogDetailDialog: false,
+      callLogDetailData: null,
+      // 事件日志详情
+      eventLogDetailDialog: false,
+      eventLogDetailData: null,
+      // 执行结果对话框
+      executeDialog: {
+        visible: false,
+        title: '',
+        status: '',
+        type: 'success',
+        message: '',
+        data: null
       }
     }
   },
-  watch: {
-    // 根据名称筛选区域树
-    areaName(val) {
-      this.$refs.tree.filter(val)
-    }
-  },
   created() {
-    this.queryParams.deviceCategory = 'NHJC'; // 确保初始加载时就设置为 'NHJC'
-    this.getList()
-    this.getAreaTree('0', 1)
-    this.getFacsOptions()
-    this.getSubsystem()
-    this.getSubCategorygetByCode()
-    this.getFacsModel()
-    // this.getAllDevProcess(this.subcategoryCode)
+    this.loadSystemInfo()
+    this.initDateRange()
   },
   methods: {
-    /**分页切换*/
-    switchData(v) {
-      if (v === 1) {
-        this.primary1 = "primary";
-        this.primary2 = "";
-      } else {
-        this.primary1 = "";
-        this.primary2 = "primary";
-      }
-      this.istable = v;
+    // 初始化时间范围(默认今天)
+    initDateRange() {
+      const now = new Date()
+      const startOfDay = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0)
+      const endOfDay = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 23, 59, 59)
+
+      this.callLogQuery.dateRange = [
+        this.formatDate(startOfDay),
+        this.formatDate(endOfDay)
+      ]
+      this.eventLogQuery.dateRange = [
+        this.formatDate(startOfDay),
+        this.formatDate(endOfDay)
+      ]
     },
-    /** 查询能源设备列表 */
-    getList() {
-      this.loading = true
-      listDevRecursionByArea(this.queryParams).then(response => {
-        console.log('参数', JSON.stringify(this.queryParams))
-        this.deviceList = response.rows
-        this.total = response.total
-        this.loading = false
-      })
-    },
-    /**新增、修改、删除*/
-    handleComponentAdd() {
-      this.componentReset()
-      this.componentOpen = true
-      this.title = '添加设备器件属性'
-      this.componentForm.deviceCode = this.ComponentRow.deviceCode // 设置默认设备代码
 
+    // 格式化日期
+    formatDate(date) {
+      if (!date) return ''
+      const year = date.getFullYear()
+      const month = (date.getMonth() + 1).toString().padStart(2, '0')
+      const day = date.getDate().toString().padStart(2, '0')
+      const hours = date.getHours().toString().padStart(2, '0')
+      const minutes = date.getMinutes().toString().padStart(2, '0')
+      const seconds = date.getSeconds().toString().padStart(2, '0')
+      return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
     },
-    handleComponentUpdate(row) {
-      this.componentReset()
-      const id = row.id || this.ids
-      getComponent(id).then(response => {
-        this.componentForm = response.data
-        this.componentOpen = true
-        this.title = '修改设备器件属性'
-        this.componentForm.deviceCode = this.ComponentRow.deviceCode // 设置默认设备代码
-      })
-    },
-    handleComponentDelete(row) {
-      const ids = row.id || this.ids
-      this.$modal.confirm('是否确认删除能源对象属性编号为"' + ids + '"的数据项?').then(function () {
-        return delComponent(ids)
-      }).then(() => {
-        console.log('删除row', row.deviceCode)
-        this.getComponentList(row.deviceCode)
-        this.$modal.msgSuccess('删除成功')
-      }).catch(() => {
-      })
-    },
-    submitComponentForm() {
-      this.$refs['componentForm'].validate(valid => {
-        if (valid) {
-          if (this.componentForm.id != null) {
-            updateComponent(this.componentForm).then(response => {
-              this.$modal.msgSuccess('修改成功')
-              this.componentOpen = false
-              this.getComponentList(this.componentForm.deviceCode)
-            })
-          } else {
-            addComponent(this.componentForm).then(response => {
-              this.$modal.msgSuccess('新增成功')
-              this.componentOpen = false
-              this.getComponentList(this.componentForm.deviceCode)
-            })
-          }
+
+    // 加载系统信息
+    async loadSystemInfo() {
+      try {
+        // 1. 获取系统基础信息
+        const sysRes = await getSubsystemByCode(this.systemCode)
+        this.systemInfo = sysRes.data
+
+        // 2. 获取模型信息
+        if (this.systemInfo.modelCode) {
+          // 添加系统模型代码
+          this.allModelCodes.push(this.systemInfo.modelCode)
+
+          const modelRes = await getModelByCode(this.systemInfo.modelCode)
+          const modelData = modelRes.data
+
+          // 获取能力列表
+          this.systemAbilities = (modelData.abilityList || []).map(item => ({
+            ...item,
+            executing: false
+          }))
         }
-      })
-    },
-    ComponentCancel() {
-      this.componentOpen = false
-      this.componentReset()
-    },
-    /**查询部件列表*/
-    getComponentList(deviceCode) {
-      listByDevice(deviceCode).then(response => {
-        this.ComponentList = response.data
-      })
-    },
-    /** 查询区域树结构 */
-    getAreaTree(areaCode, layer) {
-      areaTreeSelect(areaCode, layer).then(response => {
-        this.treeAreaOptions = [{
-          id: '-1',
-          label: '全部',
-          children: response.data
-        }]
-      })
-    },
-    // 筛选节点
-    filterNode(value, data) {
-      if (!value) return true
-      return data.label.indexOf(value) !== -1
-    },
-    // 节点单击事件
-    handleNodeClick(data) {
-      if (data.id === '-1') {
-        this.queryParams.locationType = null;
-        this.queryParams.locationRef = null;
-      } else {
-        this.queryParams.locationType = data.tier;
-        this.queryParams.locationRef = data.id;
-      }
-      this.handleQuery();
-    },
-    // 取消按钮
-    cancel() {
-      this.open = false
-      this.reset()
-    },
-    // 表单重置
-    reset() {
-      this.form = {
-        id: null,
-        deviceCode: null,
-        deviceName: null,
-        deviceType: null,
-        deviceStatus: null,
-        deviceModel: null,
-        refArea: null,
-        refFacs: null,
-        subsystemCode: null,
-        psCode: null,
-        createTime: null,
-        updateTime: null
 
-      }
-      this.resetForm('form')
-    },
-    componentReset() {
-      this.componentForm = {
-        id: null,
-        deviceCode: this.ComponentRow.deviceCode || '', // 使用ComponentRow的deviceCode,或者空字符串
-        compoCode: null,
-        compoTag: null,
-        psCode: null,
-        extCompoCode: null,
-        compoModel: null,
-        compoBrand: null,
-        compoSpec: null,
-        ancestors: null,
-        parentCompo: null
+        // 3. 获取系统属性值
+        const attrRes = await getObjAttr(3, this.systemCode)
+        const attrData = attrRes.data
 
-      }
-      this.resetForm('componentForm')
-    },
-    /** 搜索按钮操作 */
-    handleQuery() {
-      this.queryParams.pageNum = 1
-      console.log('搜索按钮this.queryParams', JSON.stringify(this.queryParams))
-      this.getList()
-    },
-    /** 重置按钮操作 */
-    resetQuery() {
-      this.queryParams.locationType = null
-      this.queryParams.locationRef = null
-      this.resetForm('queryForm')
-      this.handleQuery()
-    },
-    // 多选框选中数据
-    handleSelectionChange(selection) {
-      this.ids = selection.map(item => item.id)
-      this.single = selection.length !== 1
-      this.multiple = !selection.length
-    },
-    /** 新增按钮操作 */
-    handleAdd() {
-      this.reset()
-      this.open = true
-      this.title = '添加能源设备'
-    },
-    /**设备器件按钮*/
-    handleDevProcess(row) {
-      this.showDevProcessDrawer = true
-      this.ComponentRow = row
-      console.log('row', row)
-      listByDevice(this.ComponentRow.deviceCode).then(response => {
-        this.ComponentList = response.data
-      })
+        this.protocolAttrs = attrData.Protocol || []
+        this.stateAttrs = attrData.State || []
 
-    },
-    shouldShowDevProcessButton(row) {
-      const categoryIsW = this.queryParams.deviceCategory === 'W'
-      const validPsCodes = ['AA', 'AH', 'AJ', 'AM', 'AP', 'AL', 'APE', 'ALE', 'AF', 'ACC']
-      const psCodeIsValid = validPsCodes.includes(row.psCode)
-      // 只有当设备分类为输能设备且设备工艺代码有效时,才返回true
-      return categoryIsW && psCodeIsValid
-    },
-    backStyle(areaPath) {
-      const firstLevel = areaPath.split('/')[0];
-      switch (firstLevel) {
-        case '北区':
-          return 'north';
-        case '南区':
-          return 'south';
-        case '主路':
-          return 'main';
-        default:
-          return '';
+        // 设置系统状态
+        const statusAttr = this.stateAttrs.find(attr => attr.attrKey === 'interfaceStatus')
+        if (statusAttr) {
+          this.systemStatus = statusAttr.attrValue
+        }
+
+        // 4. 加载关联设备
+        await this.loadDevices()
+      } catch (error) {
+        this.$message.error('加载系统信息失败:' + error.message)
       }
     },
-    /**设备详情按钮*/
-    handleDetail(row) {
-      this.showDrawer = true
-      this.curRow = row
-      console.log('data', this.curRow)
-      this.subKey = this.$options.data().subKey
-      getModelByCode(this.curRow.facsModel).then(response => {
-        const code = response.data
-        console.log('code', code)
-        this.eventData = response.data.eventList
-        this.abilityData = response.data.abilityList
-
-      })
-      getObjAttr(2, this.curRow.deviceCode).then(response => {
-        console.log('response值', response.data)
-        const attrs = response.data.attrs
-        const attrValues = response.data.attrValues
-
-        // 合并 attrs 和 attrValues 数组
-        const mergedData = attrValues.map(attrValue => {
-          const attr = attrs.find(a => a.attrKey === attrValue.attrKey)
-          return {
-            ...attrValue,
-            attrName: attr ? attr.attrName : attrValue.attrName,
-            attrUnit: attr ? attr.attrUnit : ''
+
+    // 加载设备列表
+    async loadDevices() {
+      this.deviceLoading = true
+      try {
+        const res = await getByCondition({
+          subsystemCode: this.systemCode
+        })
+
+        // 兼容不同的数据结构
+        const deviceData = res.data || res.rows || []
+
+        this.deviceList = deviceData.map(device => ({
+          ...device,
+          detailTab: 'attrs'
+        }))
+
+        // 收集所有设备的模型代码
+        const deviceModelCodes = new Set()
+        this.deviceList.forEach(device => {
+          if (device.deviceModel) {
+            deviceModelCodes.add(device.deviceModel)
           }
         })
-        this.attrData = mergedData
-      })
-    },
-    /** 修改按钮操作 */
-    handleUpdate(row) {
-      this.reset()
-      const id = row.id || this.ids
-      getDevice(id).then(response => {
-        this.form = response.data
-        this.open = true
-        this.title = '修改能源设备'
-      })
-      const layer = 1
-      const areaCode = '0'
-      areaTreeSelect(areaCode, layer).then(response => {
-        this.totalAreaOptions = response.data
-      })
-    },
-    /** 提交按钮 */
-    submitForm() {
-      // 重置 attrList 和 form.customAttrs
-      if (!this.attrList) {
-        this.attrList = []
-      }
-      if (!this.form.customAttrs) {
-        this.form.customAttrs = []
-      }
-      // 准备要发送的数据
-      let dataToSubmit = []
-      // 添加模型属性数据
-      this.attrList.forEach(attr => {
-        const attrName = attr.attrName
-        const attrKey = attr.attrKey
-        const attrValue = this.attrValuesMap[attrKey]
-        const existingIndex = dataToSubmit.findIndex(item => item.attrKey === attrKey)
-        if (existingIndex === -1) {
-          // 如果attrKey不存在于dataToSubmit中,则添加
-          dataToSubmit.push({
-            modelCode: this.form.deviceModel, // 模型代码
-            objCode: this.form.deviceCode, // 设备代码
-            objType: 2, // 对象类型
-            attrKey: attrKey,
-            attrValue: attrValue,
-            attrName: attrName
 
-          })
+        // 将设备模型代码添加到总列表
+        deviceModelCodes.forEach(modelCode => {
+          if (!this.allModelCodes.includes(modelCode)) {
+            this.allModelCodes.push(modelCode)
+          }
+        })
+
+        // 统计设备信息
+        this.deviceStats.total = this.deviceList.length
+        this.deviceStats.online = this.deviceList.filter(d => d.deviceStatus === 1).length
+        this.deviceStats.offline = this.deviceList.filter(d => d.deviceStatus !== 1).length
+
+        // 加载每个设备的属性
+        for (const device of this.deviceList) {
+          await this.loadDeviceAttrs(device.deviceCode)
         }
-      })
-
-      // 添加自定义属性数据
-      this.form.customAttrs.forEach(customAttr => {
-        const attrName = customAttr.attrName
-        const attrKey = customAttr.attrKey
-        const attrValue = customAttr.attrValue
-        const existingIndex = dataToSubmit.findIndex(item => item.attrKey === attrKey)
-        if (existingIndex === -1) {
-          // 如果attrKey不存在于dataToSubmit中,则添加
-          dataToSubmit.push({
-            modelCode: '', // 模型代码
-            objCode: this.form.deviceCode, // 设备代码
-            objType: 2, // 对象类型
-            attrKey: attrKey,
-            attrValue: attrValue,
-            attrName: attrName
+      } catch (error) {
+        this.$message.error('加载设备列表失败')
+      } finally {
+        this.deviceLoading = false
+      }
+    },
+
+    // 加载设备属性
+    async loadDeviceAttrs(deviceCode) {
+      try {
+        const res = await getObjAttr(2, deviceCode)
+        const attrData = res.data
+
+        // 存储基础属性
+        const baseAttrs = {}
+        if (attrData.Base) {
+          attrData.Base.forEach(attr => {
+            baseAttrs[attr.attrKey] = attr.attrValue
           })
         }
-      })
-
-      this.$refs['form'].validate(valid => {
-        if (valid) {
-          if (this.form.id != null) {
-            updateDevice(this.form).then(response => {
-              this.$modal.msgSuccess('修改成功')
-              this.open = false
-              this.getList()
-            }).catch(error => {
-              console.error('修改失败:', error)
-              this.$message.error('修改失败')
-            })
-
-            if (dataToSubmit.length > 0) {
-              addAttrValueBatch(dataToSubmit)
-                .then(response => {
-                  if (response.code === 200) {
-                    this.$message.success('属性添加成功')
-                  } else {
-                    this.$message.error('属性添加失败')
-                  }
-                }).catch(error => {
-                console.error('属性添加失败:', error)
-                this.$message.error('属性添加失败')
-              })
+        this.deviceAttrs[deviceCode] = baseAttrs
+
+        // 处理测点通道信息
+        const channels = []
+        if (attrData.Measure) {
+          attrData.Measure.forEach(attr => {
+            if (attr.attrKey.startsWith('interface')) {
+              try {
+                const points = JSON.parse(attr.attrValue || '[]')
+                channels.push({
+                  name: attr.attrName,
+                  key: attr.attrKey,
+                  points: points
+                })
+                // 统计测点数
+                this.deviceStats.points += points.length
+              } catch (e) {
+                // 忽略解析错误
+              }
             }
-          } else {
-            addDevice(this.form).then(response => {
-              this.$modal.msgSuccess('新增成功')
-              this.open = false
-              this.getList()
-            }).catch(error => {
-              console.error('新增失败:', error)
-              this.$message.error('新增失败')
-            })
-
-            if (dataToSubmit.length > 0) {
-              addAttrValueBatch(dataToSubmit)
-                .then(response => {
-                  if (response.code === 200) {
-                    this.$message.success('属性添加成功')
-                  } else {
-                    this.$message.error('属性添加失败')
-                  }
-                }).catch(error => {
-                console.error('属性添加失败:', error)
-                this.$message.error('属性添加失败')
-              })
-            } else {
-              // this.$message.info('没有属性需要添加');
-            }
-          }
+          })
         }
-      })
-    },
-    /** 删除按钮操作 */
-    handleDelete(row) {
-      const ids = row.id || this.ids
-      this.$modal.confirm('是否确认删除能源设备编号为"' + ids + '"的数据项?').then(function () {
-        return delDevice(ids)
-      }).then(() => {
-        this.getList()
-        this.$modal.msgSuccess('删除成功')
-      }).catch(() => {
-      })
-    },
-    /** 导出按钮操作 */
-    handleExport() {
-      this.download('ems/basecfg/device/export', {
-        ...this.queryParams
-      }, `device_${new Date().getTime()}.xlsx`)
-    },
-    getFacsOptions() {
-      const getFacsParams = {
-        facsCategory: this.queryParams.deviceCategory,
-        subCategory: this.queryParams.deviceSubCategory
+        this.deviceChannels[deviceCode] = channels
+      } catch (error) {
+        // 忽略加载错误
       }
-      listAllFacs(getFacsParams).then(response => {
-        this.facsOptions = response.data
-      })
-    },
-    getSubCategorygetByCode() {
-      getFacsCategorygetByCode(this.queryParams.deviceCategory).then(response => {
-        this.subCategoryOptions = response.data.subtypeList || []
-      })
-    },
-    getSubsystem() {
-      listSubsystemAll().then(response => {
-        this.subsystemOptions = response.data
-      })
     },
-    /**自定义属性表格*/
-    addCustomAttr() {
-      // 添加一个新的自定义属性
-      if (!Array.isArray(this.form.customAttrs)) {
-        this.form.customAttrs = []
-      }
-      this.form.customAttrs.push({
-        attrKey: '',
-        attrName: '',
-        attrValue: ''
-      })
-      // 强制更新视图
-      this.$forceUpdate()
 
+    // 获取设备属性
+    getDeviceAttr(deviceCode, attrKey) {
+      return this.deviceAttrs[deviceCode]?.[attrKey] || '-'
     },
-    deleteCustomAttr(index) {
-      // 删除指定索引的自定义属性
-      if (this.form.customAttrs.length > 0) {
-        this.form.customAttrs.splice(index, 1)
-      }
 
+    // 获取设备通道
+    getDeviceChannels(deviceCode) {
+      return this.deviceChannels[deviceCode] || []
     },
-    /**设备模型*/
-    updateAttrValue(attrKey, newValue) {
-      this.attrValuesMap[attrKey] = newValue
+
+    // 加载设备能力(当下拉菜单显示时)
+    async handleAbilityLoad(visible, device) {
+      if (visible && !this.deviceAbilities[device.deviceCode]) {
+        try {
+          // 确保设备有模型代码
+          if (!device.deviceModel) {
+            this.$set(this.deviceAbilities, device.deviceCode, [])
+            return
+          }
+
+          const res = await getModelByCode(device.deviceModel)
+          // 获取能力列表,hiddenFlag = 1 表示在操作菜单中显示的能力
+          const abilities = res.data?.abilityList?.filter(item => item.hiddenFlag === 1) || []
+          this.$set(this.deviceAbilities, device.deviceCode, abilities)
+        } catch (error) {
+          this.$set(this.deviceAbilities, device.deviceCode, [])
+        }
+      }
     },
 
-    getFacsModel() {
-      listAllModel(2).then(response => {
-        this.modelList = response.data
-        console.log('this.modelList', this.modelList)
-        this.modelList.forEach(model => {
-          console.log(model.modelCode)
+    // 处理设备操作命令
+    async handleDeviceCommand(command) {
+      const { device, ability } = command
+      try {
+        await listcallAbility({
+          objCode: device.deviceCode,
+          objType: 2,
+          modelCode: device.deviceModel,
+          abilityKey: ability.abilityKey,
+          abilityParam: ability.abilityParam
         })
-      })
+
+        this.$message.success(`${ability.abilityName}执行成功`)
+
+        // 如果是抄表相关能力,重新加载设备属性
+        if (ability.abilityKey.toLowerCase().includes('meter') ||
+          ability.abilityKey.toLowerCase().includes('reading')) {
+          await this.loadDeviceAttrs(device.deviceCode)
+        }
+      } catch (error) {
+        this.$message.error(`${ability.abilityName}执行失败:${error.message}`)
+      }
     },
-    handleModelChange(modelCode) {
-      if (modelCode) {
-        this.getModelByCode(modelCode)
-        console.log('设备代码', this.form.deviceCode)
-        this.getObjAttr(2, this.form.deviceCode)
+
+    // 执行系统能力
+    async executeAbility(ability) {
+      ability.executing = true
+      try {
+        const res = await listcallAbility({
+          objCode: this.systemCode,
+          objType: 3,
+          modelCode: this.systemInfo.modelCode,
+          abilityKey: ability.abilityKey,
+          abilityParam: ability.abilityParam
+        })
+
+        this.executeDialog = {
+          visible: true,
+          title: '执行结果 - ' + ability.abilityName,
+          status: '执行成功',
+          type: 'success',
+          message: '系统能力执行完成',
+          data: res.data
+        }
+
+        // 刷新设备数据
+        if (ability.abilityKey === 'MeterReadingGw') {
+          this.loadDevices()
+        }
+      } catch (error) {
+        this.executeDialog = {
+          visible: true,
+          title: '执行结果 - ' + ability.abilityName,
+          status: '执行失败',
+          type: 'error',
+          message: error.message,
+          data: null
+        }
+      } finally {
+        ability.executing = false
       }
     },
-    getModelByCode(modelCode) {
-      getModelByCode(modelCode).then(response => {
-        // this.attrList = response.data.attrList;
-        const filteredAttrList = response.data.attrList.filter(attr => attr.attrType === 0)
-        this.attrList = filteredAttrList
 
-      })
+    // 处理设备行点击 - 展开/收起行详情
+    handleDeviceClick(row) {
+      this.$refs.deviceTable?.toggleRowExpansion(row)
     },
-    getObjAttr(objType, deviceCode) {
-      getObjAttr(objType, deviceCode).then(response => {
-        // const attrs = response.data.attrs;
-        const attrs = response.data.attrs.filter(attr => attr.attrType === 0)
-        console.log('attrs', attrs)
-        const attrValues = response.data.attrValues || [] // 确保是一个数组
-        console.log('attrValues', attrValues)
-
-        // 创建一个映射对象,用于存储 attrKey 与对应的 attrValue
-        const attrValuesMap = {}
-
-        // 遍历 attrs 数组
-        attrs.forEach(attr => {
-          // 查找 attrValues 数组中是否有匹配的 attrKey
-          const attrValueObj = attrValues.find(value => value.attrKey === attr.attrKey)
-          // 如果找到匹配的 attrValue,更新 attrValuesMap
-          if (attrValueObj) {
-            attrValuesMap[attr.attrKey] = attrValueObj.attrValue
-          } else {
-            // 如果没有找到匹配的 attrValue,则设置为 '暂无数据'
-            attrValuesMap[attr.attrKey] = ''
-          }
-        })
 
-        // 更新 attrValuesMap 到组件的数据中
-        this.attrValuesMap = attrValuesMap
-        // 打印更新后的 attrValuesMap,用于调试
-        console.log('Updated attrValuesMap', this.attrValuesMap)
+    // 标签页切换
+    handleTabClick(tab) {
+      if (tab.name === 'callLogs' && this.callLogList.length === 0) {
+        this.queryCallLogs()
+      } else if (tab.name === 'eventLogs' && this.eventLogList.length === 0) {
+        this.queryEventLogs()
+      }
+    },
 
-      })
-    }
-  }
-}
-</script>
-<style lang="scss" scoped>
+    // 查询调用日志
+    async queryCallLogs() {
+      this.logLoading = true
+      try {
+        const params = {
+          modelCodes: this.allModelCodes,
+          pageNum: this.callLogQuery.pageNum,
+          pageSize: this.callLogQuery.pageSize
+        }
 
-.divider {
-  border-bottom: 2px solid #ebeef5;
-  margin: 10px 0;
-}
+        // 添加时间范围
+        if (this.callLogQuery.dateRange && this.callLogQuery.dateRange.length === 2) {
+          params.startRecTime = this.callLogQuery.dateRange[0]
+          params.endRecTime = this.callLogQuery.dateRange[1]
+        }
 
-.section-title {
-  font-size: 18px;
-  font-weight: bold;
-  margin-top: 20px;
-  margin-bottom: 10px;
-}
+        // 添加能力标识
+        if (this.callLogQuery.abilityKey) {
+          params.abilityKey = this.callLogQuery.abilityKey
+        }
 
-.drawer-content {
-  padding: 0 20px;
-}
+        // 添加调用状态
+        if (this.callLogQuery.callStatus !== '') {
+          params.callStatus = this.callLogQuery.callStatus
+        }
 
+        const res = await listCallLog(params)
+        this.callLogList = res.rows || []
+        this.callLogTotal = res.total || 0
+      } catch (error) {
+        this.$message.error('查询调用日志失败')
+      } finally {
+        this.logLoading = false
+      }
+    },
 
-.section-title {
-  font-size: 18px;
-  font-weight: bold;
-}
+    // 重置调用日志查询
+    resetCallLogQuery() {
+      this.initDateRange()
+      this.callLogQuery.abilityKey = ''
+      this.callLogQuery.callStatus = ''
+      this.callLogQuery.pageNum = 1
+      this.queryCallLogs()
+    },
 
-.attr-list-container {
-  border: 1px solid #ccc;
-  padding: 10px;
-  margin: 10px 0;
-  font-weight: bold;
-}
+    // 查询事件日志
+    async queryEventLogs() {
+      this.eventLogLoading = true
+      try {
+        const params = {
+          modelCodes: this.allModelCodes,
+          pageNum: this.eventLogQuery.pageNum,
+          pageSize: this.eventLogQuery.pageSize
+        }
 
-.attr-list-container h3 {
-  font-weight: bold;
-}
+        // 添加时间范围
+        if (this.eventLogQuery.dateRange && this.eventLogQuery.dateRange.length === 2) {
+          params.startRecTime = this.eventLogQuery.dateRange[0]
+          params.endRecTime = this.eventLogQuery.dateRange[1]
+        }
 
-.attr-item {
-  list-style-type: none;
-  margin-bottom: 5px;
-}
+        // 添加事件标识
+        if (this.eventLogQuery.eventKey) {
+          params.eventKey = this.eventLogQuery.eventKey
+        }
 
-.attr-name {
-  font-weight: bold;
-}
+        const res = await listEventLog(params)
+        this.eventLogList = res.rows || []
+        this.eventLogTotal = res.total || 0
+      } catch (error) {
+        this.$message.error('查询事件日志失败')
+      } finally {
+        this.eventLogLoading = false
+      }
+    },
 
+    // 重置事件日志查询
+    resetEventLogQuery() {
+      this.initDateRange()
+      this.eventLogQuery.eventKey = ''
+      this.eventLogQuery.pageNum = 1
+      this.queryEventLogs()
+    },
 
-.contents {
-  border: 20px solid #f2f2f5;
-  background-color: #f2f2f5;
-}
+    // 格式化调用状态
+    formatCallStatus(status) {
+      const statusMap = {
+        0: '成功',
+        1: '进行中',
+        2: '失败'
+      }
+      return statusMap[status] || '未知'
+    },
 
+    // 获取调用状态类型
+    getCallStatusType(status) {
+      const typeMap = {
+        0: 'success',
+        1: 'warning',
+        2: 'danger'
+      }
+      return typeMap[status] || 'info'
+    },
 
-.other-content {
-  background-color: #ffffff; /* 白色背景 */
-  padding: 20px;
-  margin-bottom: 20px;
+    // 查看调用日志详情
+    async handleCallLogDetail(row) {
+      try {
+        const res = await getCallLog(row.id)
+        this.callLogDetailData = res.data
+        this.callLogDetailDialog = true
+      } catch (error) {
+        this.$message.error('获取调用日志详情失败')
+      }
+    },
+
+    // 查看事件日志详情
+    async handleEventLogDetail(row) {
+      try {
+        const res = await getEventLog(row.id)
+        this.eventLogDetailData = res.data
+        this.eventLogDetailDialog = true
+      } catch (error) {
+        this.$message.error('获取事件日志详情失败')
+      }
+    }
+  }
 }
+</script>
 
-.table-content {
-  background-color: #ffffff; /* 白色背景 */
+<style lang="scss" scoped>
+.app-container {
   padding: 20px;
+  background: #f5f7fa;
+  min-height: calc(100vh - 84px);
 }
 
-.pagination-container {
+.system-info-card {
   margin-bottom: 20px;
-}
 
-.button-group-container {
-  display: flex;
-  justify-content: flex-end;
-  min-width: 200px;
-  padding: 5px;
-}
+  .card-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
 
-.device-list {
-  margin-top: 20px;
-}
+    .title {
+      font-size: 18px;
+      font-weight: bold;
 
-.device-card {
-  background-color: #fff;
-  border: 1px solid #bfcbd9;
-  border-radius: 4px;
-  overflow: hidden;
-  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
-  transition: 0.3s;
-  padding: 10px;
-  font-size: 14px;
-  height: 200px;
-  margin-bottom: 20px;
-  display: flex;
-  flex-direction: column;
-}
+      i {
+        margin-right: 8px;
+        color: #409EFF;
+      }
+    }
+  }
 
-.device-header {
-  //background-color: #f2f2f5;
-  //padding: 10px;
-  color: #545353;
-  font-size: 20px;
-  font-weight: bold;
-}
+  .info-group {
+    .group-title {
+      font-size: 14px;
+      font-weight: bold;
+      color: #606266;
+      margin-bottom: 12px;
+      padding-bottom: 6px;
+      border-bottom: 1px solid #EBEEF5;
+    }
+  }
 
-.device-code {
-  color: cornflowerblue;
-}
+  .info-item {
+    margin-bottom: 12px;
+    font-size: 14px;
 
-.deviceOthers {
-  color: black;
-}
+    label {
+      color: #909399;
+      margin-right: 8px;
+      display: inline-block;
+      min-width: 80px;
+    }
 
-.device-body {
-  padding: 10px;
-  color: #666666;
-  flex: 1; /* 使设备主体内容占据剩余空间 */
-  overflow-y: auto; /* 如果内容过多,允许滚动 */
+    .code {
+      font-family: monospace;
+      color: #409EFF;
+      background: #f0f9ff;
+      padding: 2px 6px;
+      border-radius: 3px;
+    }
+  }
 }
 
-.device-footer {
-  display: flex;
-  justify-content: space-between;
-  padding: 5px;
-  // background-color: #f9f9f9;
-}
+.detail-card {
+  .tab-content {
+    min-height: 400px;
+  }
 
-.device-footer .el-button {
-  padding: 5px 15px;
-  border: none; /* 移除默认边框 */
-  color: #5a5e66;
-  transition: background-color 0.3s; /* 平滑过渡背景色变化 */
-}
+  .attr-section {
+    margin-bottom: 30px;
 
-/* 为按钮分配不同的颜色 */
-.device-footer .el-button:first-child {
-  background-color: #d5f1d5; /* 淡绿色 */
-  border: 1px solid lightgreen;
-  color: #71e2aa;
+    .section-title {
+      margin: 20px 0 15px 0;
+      color: #303133;
 
-}
+      i {
+        margin-right: 8px;
+        color: #409EFF;
+      }
+    }
 
-.device-footer .el-button:nth-child(2) {
-  background-color: #ffe5b4; /* 淡橙色 */
-  border: 1px solid #ffba00;
-  color: #faad14;
-}
+    .url-text {
+      color: #409EFF;
+      font-family: monospace;
+    }
+  }
 
-.device-footer .el-button:last-child {
-  background-color: #ffd5d5; /* 淡红色 */
-  border: 1px solid lightpink;
-  color: #f5222d;
-}
+  .device-stats {
+    margin-bottom: 20px;
+
+    .stat-item {
+      text-align: center;
+      padding: 20px;
+      background: #fff;
+      border: 1px solid #EBEEF5;
+      border-radius: 4px;
+
+      .stat-value {
+        font-size: 28px;
+        font-weight: bold;
+        color: #303133;
+        margin-bottom: 8px;
+      }
 
-/* 鼠标悬停时加深颜色 */
-.device-footer .el-button:hover {
-  filter: brightness(0.5); /* 颜色加深效果 */
-}
+      .stat-label {
+        font-size: 14px;
+        color: #909399;
+      }
 
-/* 背景色样式 */
-.north {
-  background: linear-gradient(to right, #e1f3d8, #fafafa);
-}
+      &.online .stat-value {
+        color: #67C23A;
+      }
 
-.south {
-  background: linear-gradient(to right, #fff7e8, #fafafa);
-}
+      &.offline .stat-value {
+        color: #F56C6C;
+      }
+    }
+  }
 
-.main {
-  background: linear-gradient(to right, #e0e0e0, #fafafa);
-}
+  .device-detail {
+    padding: 20px;
+    background: #f5f7fa;
 
+    h5 {
+      margin: 15px 0 10px 0;
+      color: #303133;
+    }
+  }
 
-.el-table {
-  background-color: #ffffff; /* 白色背景 */
+  .log-filter {
+    margin-bottom: 20px;
+    padding: 15px;
+    background: #f5f7fa;
+    border-radius: 4px;
+  }
 }
 
-.el-card {
-  background-color: #ffffff; /* 白色背景 */
+.execute-result {
+  .result-data {
+    margin-top: 20px;
+
+    pre {
+      background: #f5f7fa;
+      padding: 15px;
+      border-radius: 4px;
+      overflow: auto;
+      max-height: 400px;
+      font-family: monospace;
+      font-size: 12px;
+    }
+  }
 }
 </style>

文件差异内容过多而无法显示
+ 375 - 503
ems-ui-cloud/src/views/basecfg/device/index.vue


+ 69 - 162
ems-ui-cloud/src/views/devmgr/device/index.vue

@@ -48,17 +48,17 @@
 
           <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
             <el-form-item label="设备分类" prop="deviceSubCategory">
-              <el-select v-model="queryParams.deviceSubCategory">
-                <el-option v-for="item in subCategoryOptions" placeholder="设备分类" :label="item.name" :value="item.code" :key="item.code" />
+              <el-select v-model="queryParams.deviceSubCategory" placeholder="请选择">
+                <el-option v-for="item in subCategoryOptions" :label="item.name" :value="item.code" :key="item.code" />
               </el-select>
             </el-form-item>
             <el-form-item label="归属设施" prop="refFacs">
-              <el-select v-model="queryParams.refFacs">
+              <el-select v-model="queryParams.refFacs" placeholder="请选择">
                 <el-option v-for="item in facsOptions" :label="item.facsName" :value="item.facsCode" :key="item.facsCode" />
               </el-select>
             </el-form-item>
             <el-form-item label="归属系统" prop="subsystemCode">
-              <el-select v-model="queryParams.subsystemCode">
+              <el-select v-model="queryParams.subsystemCode" placeholder="请选择">
                 <el-option v-for="item in subsystemOptions" :label="item.systemName" :value="item.systemCode" :key="item.systemCode" />
               </el-select>
             </el-form-item>
@@ -85,8 +85,7 @@
                   color: getDeviceStatusTextColor(scope.row.deviceStatus),
                   backgroundColor: getDeviceStatusBgColor(scope.row.deviceStatus),
                   minWidth: '70px',
-                  height: '35px',
-                  textAlign: 'center'
+                  height: '35px'
                 }">
                   {{ getDeviceStatusText(scope.row.deviceStatus) }}
                 </span>
@@ -138,17 +137,6 @@
           </div>
         </el-dialog>
 
-        <!-- 设备日志详情弹窗 -->
-        <el-dialog :visible.sync="reportDetailDialog" title="设备日志详情" width="50%">
-          <div v-if="reportDetailData">
-            <p><strong>对象代码:</strong>{{ reportDetailData.objCode }}</p>
-            <p><strong>消息描述:</strong>{{ reportDetailData.msgDesc }}</p>
-            <p><strong>上报时间:</strong>{{ reportDetailData.reportTime }}</p>
-            <p><strong>上报载体:</strong></p>
-            <pre style="white-space: pre-wrap; background-color: #f5f5f5; padding: 10px; border-radius: 4px;">{{ reportDetailData.reportPayload }}</pre>
-          </div>
-        </el-dialog>
-
         <!-- 事件日志详情弹框 -->
         <el-dialog :visible.sync="eventLogDetailDialog" title="事件日志详情" width="50%">
           <div v-if="eventLogDetailData">
@@ -168,30 +156,28 @@
               <el-tab-pane label="设备参数" name="attr"></el-tab-pane>
               <el-tab-pane label="设备能力" name="ability"></el-tab-pane>
               <el-tab-pane label="调用日志" name="callLog"></el-tab-pane>
-              <el-tab-pane label="设备日志" name="reportLog"></el-tab-pane>
               <el-tab-pane label="事件日志" name="eventLog"></el-tab-pane>
             </el-tabs>
 
-            <!-- 设备基本信息 -->
+            <!-- 设备基本信息 - 使用el-descriptions优化展示 -->
             <div v-if="activeTab === 'basic'">
               <el-card class="box-card">
-                <div>
-                  <p><span class="bold">设备名称:</span>{{ curRow.deviceName }}</p>
-                  <p><span class="bold">设备代码:</span>{{ curRow.deviceCode }}</p>
-                  <p><span class="bold">设备分类:</span>{{ curRow.deviceCategoryName + getPsName(curRow.psName) }}</p>
-                  <p><span class="bold">设备型号:</span>{{ curRow.deviceSpec }}</p>
-                  <p><span class="bold">供应商:</span>{{ curRow.deviceBrand }}</p>
-                  <p><span class="bold">归属设施:</span>{{ curRow.refFacsName }}</p>
-                  <p><span class="bold">归属区域:</span>{{ buildRefAreaName(curRow) }}</p>
-                  <p><span class="bold">安装位置:</span>{{ curRow.location === null ? '无' : curRow.location }}</p>
-                  <p><span class="bold">归属系统:</span>{{ curRow.subsystemName === null ? '无' : curRow.subsystemName }}</p>
-                  <p>
-                    <span class="bold">设备状态:</span>
-                    <span :class="getDeviceStatusClass(curRow.deviceStatus)">
-                       {{ getDeviceStatus(curRow.deviceStatus) }}
-                    </span>
-                  </p>
-                </div>
+                <el-descriptions :column="2" border>
+                  <el-descriptions-item label="设备名称">{{ curRow.deviceName }}</el-descriptions-item>
+                  <el-descriptions-item label="设备代码">{{ curRow.deviceCode }}</el-descriptions-item>
+                  <el-descriptions-item label="设备分类">{{ curRow.deviceCategoryName + getPsName(curRow.psName) }}</el-descriptions-item>
+                  <el-descriptions-item label="设备型号">{{ curRow.deviceSpec || '-' }}</el-descriptions-item>
+                  <el-descriptions-item label="供应商">{{ curRow.deviceBrand || '-' }}</el-descriptions-item>
+                  <el-descriptions-item label="归属设施">{{ curRow.refFacsName || '-' }}</el-descriptions-item>
+                  <el-descriptions-item label="归属区域">{{ buildRefAreaName(curRow) }}</el-descriptions-item>
+                  <el-descriptions-item label="安装位置">{{ curRow.location || '-' }}</el-descriptions-item>
+                  <el-descriptions-item label="归属系统">{{ curRow.subsystemName || '-' }}</el-descriptions-item>
+                  <el-descriptions-item label="设备状态">
+                    <el-tag :type="curRow.deviceStatus === 1 ? 'success' : 'danger'">
+                      {{ curRow.deviceStatus === 1 ? '在线' : '离线' }}
+                    </el-tag>
+                  </el-descriptions-item>
+                </el-descriptions>
               </el-card>
             </div>
 
@@ -217,8 +203,8 @@
                         <span v-if="scope.row.attrUnit">{{ scope.row.attrUnit }}</span>
                         </span>
                         <span v-else>
-                  {{ scope.row.attrValue }}
-                </span>
+                          {{ scope.row.attrValue }}
+                        </span>
                       </template>
                     </el-table-column>
                   </el-table>
@@ -226,16 +212,23 @@
               </el-card>
             </div>
 
-            <!-- 设备能力 -->
+            <!-- 设备能力 - 使用统一的执行按钮样式 -->
             <div v-if="activeTab === 'ability'">
               <el-card class="box-card">
                 <el-table :data="abilityData" style="width: 100%" :show-header="true" :empty-text="'暂无数据'">
                   <el-table-column type="index" label="序号" width="50" align="center"></el-table-column>
                   <el-table-column label="能力名称" prop="abilityName"></el-table-column>
                   <el-table-column label="能力描述" prop="abilityDesc"></el-table-column>
-                  <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+                  <el-table-column label="操作" align="center" width="150">
                     <template slot-scope="scope">
-                      <el-button size="mini" type="text" icon="el-icon-info" @click="handleOperate(scope.row)">执行</el-button>
+                      <el-button
+                        type="primary"
+                        size="mini"
+                        icon="el-icon-caret-right"
+                        @click="handleOperate(scope.row)"
+                        :loading="scope.row.executing">
+                        执行
+                      </el-button>
                     </template>
                   </el-table-column>
                 </el-table>
@@ -291,6 +284,7 @@
                 @pagination="handleEventLogQuery"
               />
             </div>
+
             <!-- 调用日志 -->
             <div v-if="activeTab === 'callLog'">
               <el-form inline>
@@ -355,46 +349,6 @@
                 @pagination="handleCallLogQuery"
               />
             </div>
-
-            <!-- 设备日志 -->
-            <div v-if="activeTab === 'reportLog'">
-              <el-form inline>
-                <el-form-item label="记录时间">
-                  <el-date-picker
-                    v-model="logDaterangeTime"
-                    style="width: 240px"
-                    value-format="yyyy-MM-dd HH:mm"
-                    type="datetimerange"
-                    range-separator="-"
-                    start-placeholder="开始日期"
-                    end-placeholder="结束日期"
-                  ></el-date-picker>
-                </el-form-item>
-                <el-form-item>
-                  <el-button type="primary" @click="handleLogQuery">查询</el-button>
-                  <el-button @click="resetLogQuery">重置</el-button>
-                </el-form-item>
-              </el-form>
-              <el-table :data="reportLogData" style="width: 100%" :show-header="true" :empty-text="'暂无数据'">
-                <el-table-column type="index" label="序号" width="50" align="center"></el-table-column>
-                <el-table-column label="对象编号" prop="objCode"></el-table-column>
-                <el-table-column label="对象名称" prop="objName"></el-table-column>
-                <el-table-column label="消息类型" prop="msgDesc"></el-table-column>
-                <el-table-column label="上报时间" prop="reportTime" width="180"></el-table-column>
-                <el-table-column label="操作" align="center" width="100">
-                  <template slot-scope="scope">
-                    <el-button type="text" size="mini" icon="el-icon-info" @click="handleReportLogDetail(scope.row)">详情</el-button>
-                  </template>
-                </el-table-column>
-              </el-table>
-              <pagination
-                v-show="logQueryTotal > 0"
-                :total="logQueryTotal"
-                :page.sync="logQueryParams.pageNum"
-                :limit.sync="logQueryParams.pageSize"
-                @pagination="handleLogQuery"
-              />
-            </div>
           </div>
         </el-dialog>
 
@@ -423,7 +377,7 @@ import Treeselect from '@riophae/vue-treeselect'
 import '@riophae/vue-treeselect/dist/vue-treeselect.css'
 import { listcallAbility } from '@/api/basecfg/objAbility'
 import { getObjAttr } from '@/api/basecfg/objAttribute'
-import { listReportLog, getReportLog, listCallLog, getCallLog,listEventLog,getEventLog } from '@/api/basecfg/objLog'
+import { listCallLog, getCallLog, listEventLog, getEventLog } from '@/api/basecfg/objLog'
 
 export default {
   name: 'Device',
@@ -504,13 +458,6 @@ export default {
       },
       callDaterangeTime: [],
       logDaterangeTime: [],
-      logQueryParams: {
-        startTime: '',
-        endTime: '',
-        pageNum: 1,
-        pageSize: 10
-      },
-      logQueryTotal: 0,
       callLogQueryParams: {
         abilityKey: '',
         callStatus: '',
@@ -540,17 +487,12 @@ export default {
       },
       callLogDetailDialog: false,
       callLogDetailData: {},
-      reportDetailDialog: false,
-      reportDetailData: {},
       callLog: false,
-      reportLog: false,
       callLogData: [],
-      reportLogData: [],
       // 表格属性详情弹窗
       tableAttrDetailDialog: false,
       tableAttrDetailData: [],
       tableAttrDetailTitle: ''
-
     }
   },
   watch: {
@@ -559,8 +501,6 @@ export default {
       if (newVal === 'callLog') {
         // 当切换到"调用日志"时,调用查询接口
         this.handleCallLogQuery()
-      } else if(newVal ==='reportLog'){
-        this.handleLogQuery()
       } else if (newVal === 'eventLog') {
         this.handleEventLogQuery()
       }
@@ -575,14 +515,11 @@ export default {
     const now = new Date()
     const startOfDay = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0)
     const endOfDay = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 23, 59, 59)
-    this.logQueryParams.startTime = this.formatDate(startOfDay)
-    this.logQueryParams.endTime = this.formatDate(endOfDay)
     this.callLogQueryParams.startTime = this.formatDate(startOfDay)
     this.callLogQueryParams.endTime = this.formatDate(endOfDay)
     // 设置默认日期范围
     this.callDaterangeTime = [this.formatDate(startOfDay), this.formatDate(endOfDay)]
     this.logDaterangeTime = [this.formatDate(startOfDay), this.formatDate(endOfDay)]
-
   },
   methods: {
     // 获取树节点图标
@@ -598,6 +535,20 @@ export default {
       this.$refs.tree.filter(this.areaName)
     },
 
+    // 根据区域代码获取区域名称
+    buildRefAreaName(curRow) {
+      if (!this.treeAreaOptions) {
+        return '未知区域';
+      }
+      const area = this.treeAreaOptions.find(a => a.id === curRow.areaCode);
+      const areaName = area ? area.label : '未知区域';
+
+      if (curRow.locationRef !== curRow.areaCode) {
+        return areaName + ' - ' + curRow.locationRefName;
+      }
+      return areaName;
+    },
+
     formatDate(date) {
       if (!date) return ''
       const year = date.getFullYear()
@@ -608,6 +559,7 @@ export default {
       const seconds = date.getSeconds().toString().padStart(2, '0')
       return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
     },
+
     formatCallStatus(status) {
       const statusMap = {
         0: '成功',
@@ -700,45 +652,6 @@ export default {
       })
     },
 
-    /**重置设备日志*/
-    resetLogQuery() {
-      this.logDaterangeTime = []
-      this.logQueryParams.pageNum = 1
-      this.logQueryParams.pageSize = 10
-      this.handleLogQuery() // 重新查询
-    },
-    /** 查询设备日志*/
-    handleLogQuery() {
-      if (this.curRow) {
-        const startTime = this.logDaterangeTime[0]
-        const endTime = this.logDaterangeTime[1]
-        this.getReportLog(this.curRow.deviceCode, startTime, endTime)
-      }
-    },
-    /**设备日志表格*/
-    getReportLog(deviceCode, startTime, endTime) {
-      const query = {
-        objCode: deviceCode,
-        objType: '2',
-        startRecTime: startTime,
-        endRecTime: endTime,
-        pageNum: this.logQueryParams.pageNum,
-        pageSize: this.logQueryParams.pageSize
-
-      }
-      listReportLog(query).then(response => {
-        this.reportLogData = response.rows || []
-        this.logQueryTotal = response.total
-      })
-    },
-    /**设备日志详情*/
-    handleReportLogDetail(row) {
-      getReportLog(row.id).then(response => {
-        this.reportDetailData = response.data || {}
-        this.reportDetailDialog = true
-
-      })
-    },
     loadAbilities(row) {
       if (!this.curRow) {
         this.$message.warning('请选择一条设备记录')
@@ -746,46 +659,39 @@ export default {
       }
       getModelByCode(row.deviceModel).then(response => {
         this.abilityDevice = response.data?.abilityList.filter(item => item.hiddenFlag === 1) || []
-
-
       })
     },
     /**设备能力-执行按钮*/
     handleDeviceOperate(row, curRow) {
       listcallAbility({
-        abilityKey: row.abilityKey,
         objCode: curRow.deviceCode,
         objType: '2',
-        modeCode: row.modeCode,
+        modelCode: curRow.deviceModel,  // 使用设备的modelCode
+        abilityKey: row.abilityKey,
         abilityParam: row.abilityParam
       }).then(response => {
         this.$message({ message: '设备能力执行成功', type: 'success' })
       })
     },
-    // 根据区域代码获取区域名称
-    buildRefAreaName(curRow) {
-      if (!this.treeAreaOptions) {
-        return '未知区域'; // 或者返回一个默认值
-      }
-      const area = this.treeAreaOptions.find(a => a.id === curRow.areaCode);
-      const areaName = area ? area.label : '未知区域';
 
-      if (curRow.locationRef !== curRow.areaCode) {
-        return areaName + ' - ' + curRow.locationRefName;
-      }
-      return areaName;
-    },
     handleOperate(row) {
+      // 设置执行状态
+      row.executing = true
+
       listcallAbility({
-        abilityKey: row.abilityKey,
         objCode: this.curRow.deviceCode,
         objType: '2',
-        modeCode: row.modeCode,
+        modelCode: this.curRow.deviceModel,  // 使用设备的modelCode
+        abilityKey: row.abilityKey,
         abilityParam: row.abilityParam
       }).then(response => {
         this.$message({ message: '设备能力执行成功', type: 'success' })
+      }).finally(() => {
+        // 重置执行状态
+        row.executing = false
       })
     },
+
     getPsName(psName) {
       return psName === null ? '' : ' - '+psName;
     },
@@ -814,12 +720,12 @@ export default {
     getDeviceStatusTextColor(status) {
       if (status === 0) return '#FF0000'
       if (status === 1) return '#00FF00'
-      return '#000000' // 默认黑色文字
+      return '#000000'
     },
     getDeviceStatusBgColor(status) {
       if (status === 0) return '#FFDDDD'
       if (status === 1) return '#DDFFDD'
-      return 'transparent' // 默认无背景色
+      return 'transparent'
     },
     /** 查询能源设备列表 */
     getList() {
@@ -828,7 +734,6 @@ export default {
         this.deviceList = response.rows
         this.total = response.total
         this.loading = false
-
       })
     },
     /** 查询区域树结构 */
@@ -880,13 +785,16 @@ export default {
     handleDetail(row) {
       this.reset()
       this.curRow = row
-      console.log('设备this.curRow', this.curRow)
       // 重置调用日志数据
       this.callLogData = []
       this.callLogQueryTotal = 0
       getModelByCode(this.curRow.deviceModel).then(response => {
         this.open = true
-        this.abilityData = response.data?.abilityList.filter(item => item.hiddenFlag === 1) || []
+        // 添加执行状态属性
+        this.abilityData = (response.data?.abilityList.filter(item => item.hiddenFlag === 1) || []).map(item => ({
+          ...item,
+          executing: false
+        }))
         this.attrData = response.data?.attrList || []
         this.eventData = response.data?.eventList || []
       })
@@ -941,7 +849,6 @@ export default {
       this.queryParams.deviceSubCategory = ''
       this.queryParams.refFacs = null
       this.queryParams.subsystemCode = null
-
     }
   }
 }

+ 83 - 4
ems-ui-cloud/src/views/mgr/powergrid.vue

@@ -128,13 +128,21 @@
                     size="small"
                   />
                 </div>
+                <!-- 市电标签页下的数据表格区域 -->
                 <el-table v-loading="loading" :data="pgSupplyHList" class="data-table">
                   <el-table-column label="日期" align="center" prop="date" width="180">
                     <template slot-scope="scope">
                       <span>{{ parseTime(scope.row.date, '{y}-{m}-{d}') }}</span>
                     </template>
                   </el-table-column>
-                  <el-table-column label="时间" align="center" prop="time" />
+
+                  <!-- 时间列:格式化为 HH:mm -->
+                  <el-table-column label="时间" align="center" prop="time">
+                    <template slot-scope="scope">
+                      <span>{{ formatTime(scope.row.time) }}</span>
+                    </template>
+                  </el-table-column>
+
                   <el-table-column label="计量类型" align="center" prop="meterType">
                     <template slot-scope="scope">
                       <el-tag :type="getMeterTypeTag(scope.row.meterType)" size="small">
@@ -142,19 +150,31 @@
                       </el-tag>
                     </template>
                   </el-table-column>
+
+                  <!-- 单位电价:保留2位小数,鼠标悬停显示原值 -->
                   <el-table-column label="单位电价(¥)" align="center" prop="meterUnitPrice">
                     <template slot-scope="scope">
-                      <span class="data-value">{{ scope.row.meterUnitPrice }}</span>
+                      <el-tooltip
+                        :content="`原始值: ${scope.row.meterUnitPrice}`"
+                        placement="top"
+                        effect="dark"
+                      >
+                        <span class="data-value">{{ formatPrice(scope.row.meterUnitPrice) }}</span>
+                      </el-tooltip>
                     </template>
                   </el-table-column>
+
+                  <!-- 供电量:保留1位小数 -->
                   <el-table-column label="供电量(kW·h)" align="center" prop="useElecQuantity">
                     <template slot-scope="scope">
-                      <span class="data-value primary">{{ scope.row.useElecQuantity }}</span>
+                      <span class="data-value primary">{{ formatQuantity(scope.row.useElecQuantity) }}</span>
                     </template>
                   </el-table-column>
+
+                  <!-- 供电电费:保留2位小数 -->
                   <el-table-column label="供电电费(¥)" align="center" prop="useElecCost">
                     <template slot-scope="scope">
-                      <span class="data-value warning">{{ scope.row.useElecCost }}</span>
+                      <span class="data-value warning">{{ formatCost(scope.row.useElecCost) }}</span>
                     </template>
                   </el-table-column>
                 </el-table>
@@ -946,6 +966,34 @@ export default {
         '2': '尖峰电'
       }
       return meterTypeMap[meterType] || '平峰电'
+    },
+
+    // 格式化时间,从 HH:mm:ss 转为 HH:mm
+    formatTime(time) {
+      if (!time) return '-'
+      // 如果时间格式是 HH:mm:ss,截取前5位
+      if (time.length === 8 && time.includes(':')) {
+        return time.substring(0, 5)
+      }
+      return time
+    },
+
+    // 格式化单位电价,保留2位小数
+    formatPrice(price) {
+      if (price === null || price === undefined || price === '') return '-'
+      return Number(price).toFixed(2)
+    },
+
+    // 格式化供电量,保留1位小数
+    formatQuantity(quantity) {
+      if (quantity === null || quantity === undefined || quantity === '') return '-'
+      return Number(quantity).toFixed(1)
+    },
+
+    // 格式化供电电费,保留2位小数
+    formatCost(cost) {
+      if (cost === null || cost === undefined || cost === '') return '-'
+      return Number(cost).toFixed(2)
     }
   }
 }
@@ -1262,5 +1310,36 @@ export default {
     }
   }
 }
+
+.data-table {
+  ::v-deep .el-table__body {
+    .data-value {
+      font-weight: 500;
+      cursor: default; // 添加默认光标
+
+      &.primary {
+        color: #409eff;
+      }
+
+      &.success {
+        color: #67c23a;
+      }
+
+      &.info {
+        color: #409eff;
+      }
+
+      &.warning {
+        color: #e6a23c;
+      }
+    }
+
+    // 为带有 tooltip 的单元格添加特殊样式
+    .el-tooltip {
+      display: inline-block;
+      width: 100%;
+    }
+  }
+}
 </style>
 <style lang="scss" scoped src="./index.scss"></style>

部分文件因为文件数量过多而无法显示