| ¶Ô±ÈÐÂÎļþ | 
 |  |  | 
 |  |  | <template> | 
 |  |  |   <div class="app-container"> | 
 |  |  |     <el-card class="box-card"> | 
 |  |  |       <div slot="header" class="clearfix"> | 
 |  |  |         <span>çµè¡¨éé管ç</span> | 
 |  |  |         <el-button style="float: right; padding: 3px 0" link @click="refreshData"> | 
 |  |  |           <i class="el-icon-refresh"></i> å·æ° | 
 |  |  |         </el-button> | 
 |  |  |       </div> | 
 |  |  |        | 
 |  |  |              <!-- æµè¯æé® --> | 
 |  |  |        <el-row :gutter="20" style="margin-bottom: 15px;"> | 
 |  |  |          <el-col :span="24"> | 
 |  |  |            <el-button @click="addTestData" type="primary" size="small">æ·»å æµè¯æ°æ®</el-button> | 
 |  |  |            <el-button @click="clearData" type="danger" size="small">æ¸
ç©ºæ°æ®</el-button> | 
 |  |  |            <el-button @click="testChart" type="success" size="small">æµè¯å¾è¡¨</el-button> | 
 |  |  |          </el-col> | 
 |  |  |        </el-row> | 
 |  |  |  | 
 |  |  |        <!-- æç´¢åºå --> | 
 |  |  |        <el-row :gutter="20" class="search-row"> | 
 |  |  |         <el-col :span="6"> | 
 |  |  |           <el-input | 
 |  |  |             v-model="searchForm.meterNo" | 
 |  |  |             placeholder="请è¾å
¥çµè¡¨ç¼å·" | 
 |  |  |             clearable | 
 |  |  |             @keyup.enter.native="handleSearch" | 
 |  |  |           > | 
 |  |  |             <i slot="prefix" class="el-input__icon el-icon-search"></i> | 
 |  |  |           </el-input> | 
 |  |  |         </el-col> | 
 |  |  |         <el-col :span="6"> | 
 |  |  |           <el-select v-model="searchForm.location" placeholder="è¯·éæ©ä½ç½®" clearable> | 
 |  |  |             <el-option label="ç产车é´A" value="车é´A"></el-option> | 
 |  |  |             <el-option label="ç产车é´B" value="车é´B"></el-option> | 
 |  |  |             <el-option label="åå
¬åºå" value="åå
¬åº"></el-option> | 
 |  |  |             <el-option label="é
çµå®¤" value="é
çµå®¤"></el-option> | 
 |  |  |           </el-select> | 
 |  |  |         </el-col> | 
 |  |  |         <el-col :span="6"> | 
 |  |  |           <el-date-picker | 
 |  |  |             v-model="searchForm.dateRange" | 
 |  |  |             type="daterange" | 
 |  |  |             range-separator="è³" | 
 |  |  |             start-placeholder="å¼å§æ¥æ" | 
 |  |  |             end-placeholder="ç»ææ¥æ" | 
 |  |  |             format="yyyy-MM-dd" | 
 |  |  |             value-format="yyyy-MM-dd" | 
 |  |  |           /> | 
 |  |  |         </el-col> | 
 |  |  |         <el-col :span="6"> | 
 |  |  |           <el-button type="primary" @click="handleSearch">æç´¢</el-button> | 
 |  |  |           <el-button @click="resetSearch">éç½®</el-button> | 
 |  |  |         </el-col> | 
 |  |  |       </el-row> | 
 |  |  |  | 
 |  |  |       <!-- çµè¡¨å表 --> | 
 |  |  |       <el-table | 
 |  |  |         :data="meterList" | 
 |  |  |         style="width: 100%" | 
 |  |  |         v-loading="loading" | 
 |  |  |         border | 
 |  |  |         stripe | 
 |  |  |         height="calc(100vh - 22em)" | 
 |  |  |       > | 
 |  |  |         <el-table-column prop="meterNo" label="çµè¡¨ç¼å·" width="120" /> | 
 |  |  |         <el-table-column prop="location" label="å®è£
ä½ç½®" width="120" /> | 
 |  |  |         <el-table-column prop="meterType" label="çµè¡¨ç±»å" width="120" /> | 
 |  |  |         <el-table-column prop="voltage" label="çµåç级" width="100" /> | 
 |  |  |         <el-table-column prop="currentReading" label="å½å读æ°(kWh)" width="140" /> | 
 |  |  |         <el-table-column prop="lastReading" label="䏿¬¡è¯»æ°(kWh)" width="140" /> | 
 |  |  |         <el-table-column prop="consumption" label="ç¨çµé(kWh)" width="120" /> | 
 |  |  |         <el-table-column prop="power" label="åç(kW)" width="100" /> | 
 |  |  |         <el-table-column prop="powerFactor" label="åçå æ°" width="100" /> | 
 |  |  |                           <el-table-column prop="status" label="ç¶æ" width="80"> | 
 |  |  |            <template #default="scope"> | 
 |  |  |              <el-tag :type="scope.row.status === 'æ£å¸¸' ? 'success' : 'danger'"> | 
 |  |  |                {{ scope.row.status }} | 
 |  |  |              </el-tag> | 
 |  |  |            </template> | 
 |  |  |          </el-table-column> | 
 |  |  |          <el-table-column prop="lastUpdateTime" label="æåæ´æ°æ¶é´" width="160" /> | 
 |  |  |          <el-table-column label="æä½" width="180" fixed="right" align="center"> | 
 |  |  |            <template #default="scope"> | 
 |  |  |              <el-button link @click="viewDetails(scope.row)"> | 
 |  |  |                æ¥ç详æ
 | 
 |  |  |              </el-button> | 
 |  |  |              <el-button link @click="manualCollection(scope.row)"> | 
 |  |  |                æå¨éé | 
 |  |  |              </el-button> | 
 |  |  |            </template> | 
 |  |  |          </el-table-column> | 
 |  |  |       </el-table> | 
 |  |  |       <!-- å页 --> | 
 |  |  |             <pagination | 
 |  |  |                 :total="pagination.total" | 
 |  |  |                 layout="total, sizes, prev, pager, next, jumper" | 
 |  |  |                 :page="pagination.currentPage" | 
 |  |  |                 :limit="pagination.pageSize" | 
 |  |  |                 @pagination="handleCurrentChange" | 
 |  |  |             /> | 
 |  |  |     </el-card> | 
 |  |  |  | 
 |  |  |               <!-- è¯¦æ
å¯¹è¯æ¡ --> | 
 |  |  |       <el-dialog  | 
 |  |  |         title="çµè¡¨è¯¦æ
"  | 
 |  |  |         v-model="detailDialogVisible"  | 
 |  |  |         width="60%" | 
 |  |  |         @opened="onDialogOpened" | 
 |  |  |       > | 
 |  |  |        <el-row :gutter="20"> | 
 |  |  |          <el-col :span="12"> | 
 |  |  |            <div class="detail-item"> | 
 |  |  |              <label>çµè¡¨ç¼å·:</label> | 
 |  |  |              <span>{{ currentMeter.meterNo }}</span> | 
 |  |  |            </div> | 
 |  |  |          </el-col> | 
 |  |  |          <el-col :span="12"> | 
 |  |  |            <div class="detail-item"> | 
 |  |  |              <label>å®è£
ä½ç½®:</label> | 
 |  |  |              <span>{{ currentMeter.location }}</span> | 
 |  |  |            </div> | 
 |  |  |          </el-col> | 
 |  |  |          <el-col :span="12"> | 
 |  |  |            <div class="detail-item"> | 
 |  |  |              <label>çµè¡¨ç±»å:</label> | 
 |  |  |              <span>{{ currentMeter.meterType }}</span> | 
 |  |  |            </div> | 
 |  |  |          </el-col> | 
 |  |  |          <el-col :span="12"> | 
 |  |  |            <div class="detail-item"> | 
 |  |  |              <label>çµåç级:</label> | 
 |  |  |              <span>{{ currentMeter.voltage }}</span> | 
 |  |  |            </div> | 
 |  |  |          </el-col> | 
 |  |  |          <el-col :span="12"> | 
 |  |  |            <div class="detail-item"> | 
 |  |  |              <label>å½å读æ°:</label> | 
 |  |  |              <span>{{ currentMeter.currentReading }} kWh</span> | 
 |  |  |            </div> | 
 |  |  |          </el-col> | 
 |  |  |          <el-col :span="12"> | 
 |  |  |            <div class="detail-item"> | 
 |  |  |              <label>䏿¬¡è¯»æ°:</label> | 
 |  |  |              <span>{{ currentMeter.lastReading }} kWh</span> | 
 |  |  |            </div> | 
 |  |  |          </el-col> | 
 |  |  |          <el-col :span="12"> | 
 |  |  |            <div class="detail-item"> | 
 |  |  |              <label>ç¨çµé:</label> | 
 |  |  |              <span>{{ currentMeter.consumption }} kWh</span> | 
 |  |  |            </div> | 
 |  |  |          </el-col> | 
 |  |  |          <el-col :span="12"> | 
 |  |  |            <div class="detail-item"> | 
 |  |  |              <label>åç:</label> | 
 |  |  |              <span>{{ currentMeter.power }} kW</span> | 
 |  |  |            </div> | 
 |  |  |          </el-col> | 
 |  |  |          <el-col :span="12"> | 
 |  |  |            <div class="detail-item"> | 
 |  |  |              <label>åçå æ°:</label> | 
 |  |  |              <span>{{ currentMeter.powerFactor }}</span> | 
 |  |  |            </div> | 
 |  |  |          </el-col> | 
 |  |  |          <el-col :span="12"> | 
 |  |  |            <div class="detail-item"> | 
 |  |  |              <label>ç¶æ:</label> | 
 |  |  |              <el-tag :type="currentMeter.status === 'æ£å¸¸' ? 'success' : 'danger'"> | 
 |  |  |                {{ currentMeter.status }} | 
 |  |  |              </el-tag> | 
 |  |  |            </div> | 
 |  |  |          </el-col> | 
 |  |  |          <el-col :span="12"> | 
 |  |  |            <div class="detail-item"> | 
 |  |  |              <label>æåæ´æ°æ¶é´:</label> | 
 |  |  |              <span>{{ currentMeter.lastUpdateTime }}</span> | 
 |  |  |            </div> | 
 |  |  |          </el-col> | 
 |  |  |        </el-row> | 
 |  |  |        | 
 |  |  |       <!-- ç¨çµè¶å¿å¾ --> | 
 |  |  |       <div style="margin-top: 20px;"> | 
 |  |  |         <h4>24å°æ¶ç¨çµè¶å¿</h4> | 
 |  |  |         <div ref="chartContainer" style="height: 300px;"></div> | 
 |  |  |       </div> | 
 |  |  |     </el-dialog> | 
 |  |  |   </div> | 
 |  |  | </template> | 
 |  |  |  | 
 |  |  | <script> | 
 |  |  | import * as echarts from 'echarts' | 
 |  |  |  | 
 |  |  | export default { | 
 |  |  |   name: 'MeterCollection', | 
 |  |  |   data() { | 
 |  |  |     return { | 
 |  |  |       loading: false, | 
 |  |  |       searchForm: { | 
 |  |  |         meterNo: '', | 
 |  |  |         location: '', | 
 |  |  |         dateRange: [] | 
 |  |  |       }, | 
 |  |  |       meterList: [], | 
 |  |  |       pagination: { | 
 |  |  |         currentPage: 1, | 
 |  |  |         pageSize: 10, | 
 |  |  |         total: 0 | 
 |  |  |       }, | 
 |  |  |       detailDialogVisible: false, | 
 |  |  |       currentMeter: {}, | 
 |  |  |       chart: null | 
 |  |  |     } | 
 |  |  |   }, | 
 |  |  |   created() { | 
 |  |  |     // ç«å³çæä¸äºæµè¯æ°æ® | 
 |  |  |     this.meterList = [ | 
 |  |  |       { | 
 |  |  |         id: 1, | 
 |  |  |         meterNo: 'M001', | 
 |  |  |         location: '车é´A', | 
 |  |  |         meterType: 'æºè½çµè¡¨', | 
 |  |  |         voltage: '380V', | 
 |  |  |         currentReading: 8500, | 
 |  |  |         lastReading: 8400, | 
 |  |  |         consumption: 100, | 
 |  |  |         power: '75.5', | 
 |  |  |         powerFactor: '0.85', | 
 |  |  |         status: 'æ£å¸¸', | 
 |  |  |         lastUpdateTime: '2024-01-15 10:30:00' | 
 |  |  |       }, | 
 |  |  |       { | 
 |  |  |         id: 2, | 
 |  |  |         meterNo: 'M002', | 
 |  |  |         location: '车é´B', | 
 |  |  |         meterType: 'å¤åè½çµè¡¨', | 
 |  |  |         voltage: '220V', | 
 |  |  |         currentReading: 6200, | 
 |  |  |         lastReading: 6100, | 
 |  |  |         consumption: 100, | 
 |  |  |         power: '45.2', | 
 |  |  |         powerFactor: '0.92', | 
 |  |  |         status: 'æ£å¸¸', | 
 |  |  |         lastUpdateTime: '2024-01-15 10:25:00' | 
 |  |  |       } | 
 |  |  |     ] | 
 |  |  |     this.pagination.total = this.meterList.length | 
 |  |  |   }, | 
 |  |  |   mounted() { | 
 |  |  |     // å»¶è¿ä¸ç¹æ¶é´åè°ç¨ï¼ç¡®ä¿DOMå·²ç»æ¸²æ | 
 |  |  |     this.$nextTick(() => { | 
 |  |  |       this.getMeterList() | 
 |  |  |     }) | 
 |  |  |   }, | 
 |  |  |   watch: { | 
 |  |  |     meterList: { | 
 |  |  |       handler(newVal) { | 
 |  |  |         console.log('meterListæ°æ®åå:', newVal) | 
 |  |  |       }, | 
 |  |  |       deep: true, | 
 |  |  |       immediate: true | 
 |  |  |     } | 
 |  |  |   }, | 
 |  |  |   methods: { | 
 |  |  |     // è·åçµè¡¨å表 | 
 |  |  |     getMeterList() { | 
 |  |  |       this.loading = true | 
 |  |  |       // æ¨¡æAPIè°ç¨ | 
 |  |  |       setTimeout(() => { | 
 |  |  |         const mockData = this.generateMockData() | 
 |  |  |         this.meterList = mockData | 
 |  |  |         this.pagination.total = this.meterList.length | 
 |  |  |         this.loading = false | 
 |  |  |       }, 500) | 
 |  |  |     }, | 
 |  |  |  | 
 |  |  |     // çææ¨¡ææ°æ® | 
 |  |  |     generateMockData() { | 
 |  |  |       const locations = ['车é´A', '车é´B', 'åå
¬åº', 'é
çµå®¤'] | 
 |  |  |       const meterTypes = ['æºè½çµè¡¨', 'å¤åè½çµè¡¨', 'æ®éçµè¡¨'] | 
 |  |  |       const voltages = ['220V', '380V', '10kV'] | 
 |  |  |       const statuses = ['æ£å¸¸', 'å¼å¸¸'] | 
 |  |  |        | 
 |  |  |       const data = [] | 
 |  |  |       for (let i = 1; i <= 25; i++) { | 
 |  |  |         const currentReading = Math.floor(Math.random() * 10000) + 5000 | 
 |  |  |         const lastReading = currentReading - Math.floor(Math.random() * 100) - 10 | 
 |  |  |         const consumption = currentReading - lastReading | 
 |  |  |         const power = Math.random() * 100 + 20 | 
 |  |  |         const powerFactor = (Math.random() * 0.3 + 0.7).toFixed(2) | 
 |  |  |          | 
 |  |  |         data.push({ | 
 |  |  |           id: i, | 
 |  |  |           meterNo: `M${String(i).padStart(3, '0')}`, | 
 |  |  |           location: locations[Math.floor(Math.random() * locations.length)], | 
 |  |  |           meterType: meterTypes[Math.floor(Math.random() * meterTypes.length)], | 
 |  |  |           voltage: voltages[Math.floor(Math.random() * voltages.length)], | 
 |  |  |           currentReading: currentReading, | 
 |  |  |           lastReading: lastReading, | 
 |  |  |           consumption: consumption, | 
 |  |  |           power: power.toFixed(2), | 
 |  |  |           powerFactor: powerFactor, | 
 |  |  |           status: statuses[Math.floor(Math.random() * statuses.length)], | 
 |  |  |           lastUpdateTime: this.formatDate(new Date(Date.now() - Math.random() * 86400000)) | 
 |  |  |         }) | 
 |  |  |       } | 
 |  |  |       return data | 
 |  |  |     }, | 
 |  |  |  | 
 |  |  |     // æ ¼å¼åæ¥æ | 
 |  |  |     formatDate(date) { | 
 |  |  |       const year = date.getFullYear() | 
 |  |  |       const month = String(date.getMonth() + 1).padStart(2, '0') | 
 |  |  |       const day = String(date.getDate()).padStart(2, '0') | 
 |  |  |       const hours = String(date.getHours()).padStart(2, '0') | 
 |  |  |       const minutes = String(date.getMinutes()).padStart(2, '0') | 
 |  |  |       return `${year}-${month}-${day} ${hours}:${minutes}` | 
 |  |  |     }, | 
 |  |  |  | 
 |  |  |     // æç´¢ | 
 |  |  |     handleSearch() { | 
 |  |  |       this.pagination.currentPage = 1 | 
 |  |  |       this.getMeterList() | 
 |  |  |     }, | 
 |  |  |  | 
 |  |  |     // éç½®æç´¢ | 
 |  |  |     resetSearch() { | 
 |  |  |       this.searchForm = { | 
 |  |  |         meterNo: '', | 
 |  |  |         location: '', | 
 |  |  |         dateRange: [] | 
 |  |  |       } | 
 |  |  |       this.handleSearch() | 
 |  |  |     }, | 
 |  |  |  | 
 |  |  |     // æ¥ç详æ
 | 
 |  |  |     viewDetails(row) { | 
 |  |  |       this.currentMeter = row | 
 |  |  |       this.detailDialogVisible = true | 
 |  |  |     }, | 
 |  |  |  | 
 |  |  |     // å¯¹è¯æ¡æå¼ååå§åå¾è¡¨ | 
 |  |  |     onDialogOpened() { | 
 |  |  |       this.$nextTick(() => { | 
 |  |  |         setTimeout(() => { | 
 |  |  |           this.initChart() | 
 |  |  |         }, 100) | 
 |  |  |       }) | 
 |  |  |     }, | 
 |  |  |  | 
 |  |  |     // æå¨éé | 
 |  |  |     manualCollection(row) { | 
 |  |  |       this.$message.success(`æ£å¨ééçµè¡¨ ${row.meterNo} çæ°æ®...`) | 
 |  |  |       // æ¨¡æééè¿ç¨ | 
 |  |  |       setTimeout(() => { | 
 |  |  |         row.currentReading = Math.floor(Math.random() * 100) + row.currentReading | 
 |  |  |         row.lastUpdateTime = this.formatDate(new Date()) | 
 |  |  |         this.$message.success('æ°æ®éé宿') | 
 |  |  |       }, 1000) | 
 |  |  |     }, | 
 |  |  |  | 
 |  |  |     // å·æ°æ°æ® | 
 |  |  |     refreshData() { | 
 |  |  |       this.getMeterList() | 
 |  |  |       this.$message.success('æ°æ®å·²å·æ°') | 
 |  |  |     }, | 
 |  |  |  | 
 |  |  |     // æ·»å æµè¯æ°æ® | 
 |  |  |     addTestData() { | 
 |  |  |       const testData = { | 
 |  |  |         id: Date.now(), | 
 |  |  |         meterNo: `M${String(this.meterList.length + 1).padStart(3, '0')}`, | 
 |  |  |         location: 'æµè¯ä½ç½®', | 
 |  |  |         meterType: 'æµè¯çµè¡¨', | 
 |  |  |         voltage: '220V', | 
 |  |  |         currentReading: Math.floor(Math.random() * 10000) + 1000, | 
 |  |  |         lastReading: Math.floor(Math.random() * 5000) + 500, | 
 |  |  |         consumption: Math.floor(Math.random() * 100) + 10, | 
 |  |  |         power: (Math.random() * 100 + 10).toFixed(2), | 
 |  |  |         powerFactor: (Math.random() * 0.3 + 0.7).toFixed(2), | 
 |  |  |         status: 'æ£å¸¸', | 
 |  |  |         lastUpdateTime: this.formatDate(new Date()) | 
 |  |  |       } | 
 |  |  |       this.meterList.push(testData) | 
 |  |  |       this.pagination.total = this.meterList.length | 
 |  |  |       this.$message.success('æµè¯æ°æ®å·²æ·»å ') | 
 |  |  |     }, | 
 |  |  |  | 
 |  |  |     // æ¸
ç©ºæ°æ® | 
 |  |  |     clearData() { | 
 |  |  |       this.meterList = [] | 
 |  |  |       this.pagination.total = 0 | 
 |  |  |       this.$message.success('æ°æ®å·²æ¸
空') | 
 |  |  |     }, | 
 |  |  |  | 
 |  |  |     // æµè¯å¾è¡¨ | 
 |  |  |     testChart() { | 
 |  |  |       this.$message.info('å¾è¡¨æµè¯åè½') | 
 |  |  |       // å建ä¸ä¸ªæµè¯å¯¹è¯æ¡æ¥æµè¯å¾è¡¨ | 
 |  |  |       this.currentMeter = { | 
 |  |  |         meterNo: 'TEST001', | 
 |  |  |         location: 'æµè¯ä½ç½®', | 
 |  |  |         meterType: 'æµè¯çµè¡¨', | 
 |  |  |         voltage: '220V', | 
 |  |  |         currentReading: 1000, | 
 |  |  |         lastReading: 900, | 
 |  |  |         consumption: 100, | 
 |  |  |         power: '50.0', | 
 |  |  |         powerFactor: '0.85', | 
 |  |  |         status: 'æ£å¸¸', | 
 |  |  |         lastUpdateTime: '2024-01-15 12:00:00' | 
 |  |  |       } | 
 |  |  |       this.detailDialogVisible = true | 
 |  |  |     }, | 
 |  |  |  | 
 |  |  |     // å页大尿¹å | 
 |  |  |     handleSizeChange(val) { | 
 |  |  |       this.pagination.pageSize = val | 
 |  |  |       this.getMeterList() | 
 |  |  |     }, | 
 |  |  |  | 
 |  |  |     // å½å页æ¹å | 
 |  |  |     handleCurrentChange(val) { | 
 |  |  |       this.pagination.pageSize = val.limit | 
 |  |  |       this.pagination.currentPage = val.page | 
 |  |  |       this.getMeterList() | 
 |  |  |     }, | 
 |  |  |  | 
 |  |  |     // åå§åå¾è¡¨ | 
 |  |  |     initChart() { | 
 |  |  |       try { | 
 |  |  |         if (this.chart) { | 
 |  |  |           this.chart.dispose() | 
 |  |  |           this.chart = null | 
 |  |  |         } | 
 |  |  |          | 
 |  |  |         // ç¡®ä¿DOMå
ç´ åå¨ | 
 |  |  |         if (!this.$refs.chartContainer) { | 
 |  |  |           console.error('å¾è¡¨å®¹å¨ä¸åå¨ï¼çå¾
DOMæ´æ°...') | 
 |  |  |           // å¦æå®¹å¨ä¸åå¨ï¼çå¾
ä¸ä¸åè¯ | 
 |  |  |           setTimeout(() => { | 
 |  |  |             this.initChart() | 
 |  |  |           }, 100) | 
 |  |  |           return | 
 |  |  |         } | 
 |  |  |          | 
 |  |  |         // æ£æ¥å®¹å¨å°ºå¯¸ | 
 |  |  |         const container = this.$refs.chartContainer | 
 |  |  |         if (container.offsetWidth === 0 || container.offsetHeight === 0) { | 
 |  |  |           setTimeout(() => { | 
 |  |  |             this.initChart() | 
 |  |  |           }, 100) | 
 |  |  |           return | 
 |  |  |         } | 
 |  |  |         this.chart = echarts.init(container) | 
 |  |  |          | 
 |  |  |         // çæ24å°æ¶æ¨¡ææ°æ® | 
 |  |  |         const hours = [] | 
 |  |  |         const consumption = [] | 
 |  |  |         for (let i = 0; i < 24; i++) { | 
 |  |  |           hours.push(`${i}:00`) | 
 |  |  |           consumption.push(Math.floor(Math.random() * 50) + 20) | 
 |  |  |         } | 
 |  |  |          | 
 |  |  |         const option = { | 
 |  |  |           title: { | 
 |  |  |             text: '24å°æ¶ç¨çµéè¶å¿', | 
 |  |  |             left: 'center' | 
 |  |  |           }, | 
 |  |  |           tooltip: { | 
 |  |  |             trigger: 'axis', | 
 |  |  |             formatter: '{b}<br/>ç¨çµé: {c} kWh' | 
 |  |  |           }, | 
 |  |  |           xAxis: { | 
 |  |  |             type: 'category', | 
 |  |  |             data: hours, | 
 |  |  |             axisLabel: { | 
 |  |  |               rotate: 45 | 
 |  |  |             } | 
 |  |  |           }, | 
 |  |  |           yAxis: { | 
 |  |  |             type: 'value', | 
 |  |  |             name: 'ç¨çµé (kWh)' | 
 |  |  |           }, | 
 |  |  |           series: [{ | 
 |  |  |             data: consumption, | 
 |  |  |             type: 'line', | 
 |  |  |             smooth: true, | 
 |  |  |             areaStyle: { | 
 |  |  |               opacity: 0.3 | 
 |  |  |             }, | 
 |  |  |             itemStyle: { | 
 |  |  |               color: '#409EFF' | 
 |  |  |             } | 
 |  |  |           }] | 
 |  |  |         } | 
 |  |  |          | 
 |  |  |         this.chart.setOption(option) | 
 |  |  |       } catch (error) { | 
 |  |  |         console.error('å¾è¡¨åå§å失败:', error) | 
 |  |  |         this.$message.error('å¾è¡¨åå§å失败: ' + error.message) | 
 |  |  |       } | 
 |  |  |     } | 
 |  |  |   }, | 
 |  |  |    | 
 |  |  |   beforeUnmount() { | 
 |  |  |     if (this.chart) { | 
 |  |  |       try { | 
 |  |  |         this.chart.dispose() | 
 |  |  |         this.chart = null | 
 |  |  |       } catch (error) { | 
 |  |  |         console.error('æ¸
çå¾è¡¨å¤±è´¥:', error) | 
 |  |  |       } | 
 |  |  |     } | 
 |  |  |   } | 
 |  |  | } | 
 |  |  | </script> | 
 |  |  |  | 
 |  |  | <style scoped> | 
 |  |  | .search-row { | 
 |  |  |   margin-bottom: 20px; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .pagination { | 
 |  |  |   margin-top: 20px; | 
 |  |  |   text-align: right; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .el-table { | 
 |  |  |   margin-top: 20px; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .detail-item { | 
 |  |  |   margin-bottom: 15px; | 
 |  |  |   padding: 10px; | 
 |  |  |   border: 1px solid #ebeef5; | 
 |  |  |   border-radius: 4px; | 
 |  |  |   background-color: #fafafa; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .detail-item label { | 
 |  |  |   font-weight: bold; | 
 |  |  |   color: #606266; | 
 |  |  |   margin-right: 10px; | 
 |  |  |   min-width: 100px; | 
 |  |  |   display: inline-block; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .detail-item span { | 
 |  |  |   color: #303133; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | .detail-item .el-tag { | 
 |  |  |   margin-left: 0; | 
 |  |  | } | 
 |  |  | </style> |