Quellcode durchsuchen

feat(device): 电表列表及互感值功能

- 新增电表列表组件,实现电表数据获取和展示
- 添加设备统计功能,显示总设备数、在线和离线设备数
- 电表列表增加报警状态、位置和备注字段
- 新增互感值设置功能,可为电表设置和修改互感值
- 优化电表数据详情展示,调整电压、电流等数据的格式化方式
- 更新 API 接口调用,适配新的数据结构
nahida vor 1 Jahr
Ursprung
Commit
8047dbbd20

+ 210 - 18
src/views/device/electricity/components/device-list.vue

@@ -9,9 +9,6 @@
           clearable
           prefix-icon="Search"
       >
-        <template #prefix>
-          <Search class="text-gray-400"/>
-        </template>
       </el-input>
     </div>
 
@@ -19,8 +16,8 @@
       <template #header>
         <div class="flex justify-between items-center">
           <span>设备统计</span>
-          <el-button type="primary" size="small">
-            <RefreshCw class="mr-1"/>
+          <el-button type="primary" size="small" @click="reloadData">
+            <RefreshCw class="mr-1 w-15px"/>
             刷新
           </el-button>
         </div>
@@ -28,15 +25,15 @@
       <div class="grid grid-cols-1 md:grid-cols-3 gap-4">
         <div class="stat-card bg-blue-50 p-4 rounded-lg">
           <div class="text-blue-500 text-lg font-medium">总设备数</div>
-          <div class="text-2xl font-bold mt-2">{{ meters.length }}</div>
+          <div class="text-2xl font-bold mt-2">{{ deviceStatistics.allDevice }}</div>
         </div>
         <div class="stat-card bg-green-50 p-4 rounded-lg">
           <div class="text-green-500 text-lg font-medium">在线设备</div>
-          <div class="text-2xl font-bold mt-2">{{ meters.filter(m => m.status === 'online').length }}</div>
+          <div class="text-2xl font-bold mt-2">{{ deviceStatistics.onlineDevice }}</div>
         </div>
         <div class="stat-card bg-red-50 p-4 rounded-lg">
           <div class="text-red-500 text-lg font-medium">离线设备</div>
-          <div class="text-2xl font-bold mt-2">{{ meters.filter(m => m.status === 'offline').length }}</div>
+          <div class="text-2xl font-bold mt-2">{{ deviceStatistics.offlineDevice }}</div>
         </div>
       </div>
     </el-card>
@@ -49,26 +46,42 @@
         @row-click="handleRowClick"
         row-class-name="cursor-pointer hover:bg-gray-100"
     >
+      <el-table-column prop="deviceName" label="设备名称"/>
       <el-table-column prop="tableNumber" label="电表编号" width="180"/>
-      <el-table-column prop="location" label="安装位置"/>
-      <el-table-column prop="lastReading" label="最近读数" width="120"/>
-      <el-table-column label="状态" width="100">
+      <el-table-column label="设备状态" width="100">
         <template #default="scope">
           <el-tag :type="scope.row.status === 'online' ? 'success' : 'danger'" size="small">
             {{ scope.row.status === 'online' ? '在线' : '离线' }}
           </el-tag>
         </template>
       </el-table-column>
-      <el-table-column label="操作" width="150">
+      <el-table-column prop="alarmStatus" label="报警状态">
+        <template #default="scope">
+          <el-tag :type="scope.row.alarmStatus ? 'success' : 'danger'" size="small">
+            {{ scope.row.alarmStatus ? '正常' : '报警' }}
+          </el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column prop="location" label="位置"/>
+      <el-table-column prop="remarks" label="备注"/>
+      <el-table-column label="操作" >
         <template #default="scope">
           <el-button
               type="primary"
               size="small"
               @click.stop="viewDetails(scope.row.tableNumber)"
           >
-            <Eye class="mr-1"/>
+            <Eye class="mr-1 w-15px"/>
             查看详情
           </el-button>
+          <el-button
+              type="success"
+              size="small"
+              @click.stop="openMutualInductanceDialog(scope.row.id)"
+          >
+            <Eye class="mr-1 w-15px"/>
+            互感值
+          </el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -82,23 +95,64 @@
           :total="filteredMeters.length"
       />
     </div>
+
+    <!-- 互感值对话框 -->
+    <el-dialog
+        v-model="mutualInductanceDialogVisible"
+        title="互感值设置"
+        width="30%"
+        destroy-on-close
+    >
+      <el-form :model="mutualInductanceForm" label-width="120px">
+        <el-form-item label="互感值">
+          <el-input
+              v-model="mutualInductanceForm.mutualInductance"
+              type="number"
+              placeholder="请输入互感值"
+          />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="mutualInductanceDialogVisible = false">取消</el-button>
+          <el-button type="primary" @click="saveMutualInductance" :loading="saveLoading">
+            保存
+          </el-button>
+        </span>
+      </template>
+    </el-dialog>
   </div>
 </template>
 
 <script setup>
-import {computed, ref} from 'vue';
-import {Eye, RefreshCw, Search} from 'lucide-vue-next'
+import {computed, onMounted, ref} from 'vue';
+import {Eye, RefreshCw} from 'lucide-vue-next'
+import request from "@/utils/request.js";
+import {ElMessage} from "element-plus";
 
 // 模拟电表数据
-const meters = ref([
-  {tableNumber: '110125022003', location: '1号楼3单元', lastReading: '1532 kWh', status: 'online'}
-]);
+const meters = ref([]);
+
+const deviceStatistics = ref({
+  allDevice: 0,
+  onlineDevice: 0,
+  offlineDevice: 0
+})
 
 // 分页和搜索
 const currentPage = ref(1);
 const pageSize = ref(10);
 const searchQuery = ref('');
 
+// 互感值对话框相关
+const mutualInductanceDialogVisible = ref(false);
+const mutualInductanceForm = ref({
+  id: '',
+  electricityId: '',
+  mutualInductance: ''
+});
+const saveLoading = ref(false);
+
 // 过滤后的电表列表
 const filteredMeters = computed(() => {
   const query = searchQuery.value.toLowerCase().trim();
@@ -122,4 +176,142 @@ const viewDetails = (tableNumber) => {
 const handleRowClick = (row) => {
   viewDetails(row.tableNumber);
 };
+
+const getList = async () => {
+  const arr = [];
+  arr.push({
+    column: "type",
+    type: "eq",
+    value: "2"
+  })
+  const res = await request.get("/base/devices/findByPage", {
+    params: {
+      pageNum: currentPage.value,
+      pageSize: pageSize.value,
+      conditionJson: encodeURIComponent(JSON.stringify(arr)),
+    }
+  })
+
+  if (res.code !== 200) {
+    ElMessage.error(res.msg)
+    return
+  }
+  meters.value = res.data.records.map(q => {
+    return {
+      id: q.id,
+      tableNumber: q.deviceNumber,
+      location: q.location,
+      status: q.onlineStatus === 1 ? 'online' : 'offline',
+      alarmStatus: q.alarmStatus === '0',
+      deviceName: q.deviceName,
+      remarks: q.remarks,
+    }
+  })
+}
+
+const getDeviceStatistics = async () => {
+  const arr = [];
+  arr.push({
+    column: "type",
+    type: "eq",
+    value: "2"
+  })
+  const res = await request.get("/base/devices/getAll", {
+    params: {
+      pageNum: currentPage.value,
+      pageSize: pageSize.value,
+      conditionJson: encodeURIComponent(JSON.stringify(arr)),
+    }
+  })
+
+  if (res.code !== 200) {
+    ElMessage.error(res.msg)
+    return
+  }
+  deviceStatistics.value = {
+    allDevice: res.data.length,
+    onlineDevice: res.data.filter(q => q.onlineStatus === 1).length,
+    offlineDevice: res.data.filter(q => q.onlineStatus === 0).length
+  }
+}
+
+// 打开互感值对话框
+const openMutualInductanceDialog = async (deviceId) => {
+  mutualInductanceForm.value.electricityId = deviceId;
+  mutualInductanceForm.value.id = '';
+  mutualInductanceForm.value.mutualInductance = '';
+
+  // 获取当前互感值
+  await getMutualInductance(deviceId);
+
+  // 显示对话框
+  mutualInductanceDialogVisible.value = true;
+}
+
+//根据id获取互感值
+const getMutualInductance = async (deviceId) => {
+  const arr = [];
+  arr.push({
+    column: "electricity_id",
+    type: "eq",
+    value: deviceId
+  })
+  const res = await request.get("/dbMutualInductance/getAll", {
+    params: {
+      conditionJson: encodeURIComponent(JSON.stringify(arr)),
+    }
+  })
+
+  if (res.code !== 200) {
+    ElMessage.error(res.msg)
+    return
+  }
+
+  // 如果有数据,填充到表单中
+  if (res.data && res.data.length > 0) {
+    mutualInductanceForm.value.id = res.data[0].id;
+    mutualInductanceForm.value.mutualInductance = res.data[0].mutualInductance;
+  }
+}
+
+// 保存互感值
+const saveMutualInductance = async () => {
+  if (!mutualInductanceForm.value.mutualInductance) {
+    ElMessage.warning('请输入互感值');
+    return;
+  }
+  if(Number.isInteger(mutualInductanceForm.value.mutualInductance)){
+    ElMessage.warning('请输入数字');
+    return;
+  }
+
+  saveLoading.value = true;
+  try {
+    const res = await request.post("/dbMutualInductance/updateOrInsert", {
+      electricityId: mutualInductanceForm.value.electricityId,
+      id: mutualInductanceForm.value.id,
+      mutualInductance: mutualInductanceForm.value.mutualInductance,
+    });
+
+    if (res.code === 200) {
+      ElMessage.success('互感值保存成功');
+      mutualInductanceDialogVisible.value = false;
+    } else {
+      ElMessage.error(res.msg || '保存失败');
+    }
+  } catch (error) {
+    ElMessage.error('保存失败:' + error.message);
+  } finally {
+    saveLoading.value = false;
+  }
+}
+
+const reloadData = () => {
+  getList();
+  getDeviceStatistics();
+}
+
+onMounted(() => {
+  reloadData();
+})
 </script>

+ 32 - 28
src/views/device/electricity/components/electricity-detail.vue

@@ -1,10 +1,10 @@
 <script setup>
-import { computed, onMounted, ref } from "vue";
+import {computed, onMounted, ref} from "vue";
 import request from "@/utils/request.js";
-import { ElMessage } from "element-plus";
+import {ElMessage} from "element-plus";
 import ECharts from "vue-echarts";
 import "echarts";
-import { parseTime } from "@/utils/ruoyi.js";
+import {parseTime} from "@/utils/ruoyi.js";
 
 // Data refs
 const newElectricityData = ref(null);
@@ -27,18 +27,18 @@ const props = defineProps({
 const formattedVoltages = computed(() => {
   if (!newElectricityData.value) return { a: "0", b: "0", c: "0" };
   return {
-    a: parseFloat(newElectricityData.value.aVoltage || 0).toFixed(2),
-    b: parseFloat(newElectricityData.value.bVoltage || 0).toFixed(2),
-    c: parseFloat(newElectricityData.value.cVoltage || 0).toFixed(2),
+    a: parseFloat(newElectricityData.value.avoltage || 0).toFixed(2),
+    b: parseFloat(newElectricityData.value.bvoltage || 0).toFixed(2),
+    c: parseFloat(newElectricityData.value.cvoltage || 0).toFixed(2),
   };
 });
 
 const formattedCurrents = computed(() => {
   if (!newElectricityData.value) return { a: "0", b: "0", c: "0" };
   return {
-    a: parseFloat(newElectricityData.value.aCurrent || 0).toFixed(2),
-    b: parseFloat(newElectricityData.value.bCurrent || 0).toFixed(2),
-    c: parseFloat(newElectricityData.value.cCurrent || 0).toFixed(2),
+    a: parseFloat(newElectricityData.value.acurrent || 0).toFixed(2),
+    b: parseFloat(newElectricityData.value.bcurrent || 0).toFixed(2),
+    c: parseFloat(newElectricityData.value.ccurrent || 0).toFixed(2),
   };
 });
 
@@ -81,17 +81,17 @@ const voltageChartOption = computed(() => {
       {
         name: "A相电压",
         type: "line",
-        data: data.map((item) => parseFloat(item.aVoltage || 0)),
+        data: data.map((item) => parseFloat(item.avoltage || 0)),
       },
       {
         name: "B相电压",
         type: "line",
-        data: data.map((item) => parseFloat(item.bVoltage || 0)),
+        data: data.map((item) => parseFloat(item.bvoltage || 0)),
       },
       {
         name: "C相电压",
         type: "line",
-        data: data.map((item) => parseFloat(item.cVoltage || 0)),
+        data: data.map((item) => parseFloat(item.cvoltage || 0)),
       },
     ],
   };
@@ -162,8 +162,10 @@ const getNewElectricityData = async () => {
       },
     ];
 
-    const res = await request.get("/messageParse/getAll", {
+    const res = await request.get("/messageParse/findByPageWithMutualInductance", {
       params: {
+        pageNum:1,
+        pageSize:1,
         conditionJson: encodeURIComponent(JSON.stringify(arr)),
       },
     });
@@ -173,12 +175,12 @@ const getNewElectricityData = async () => {
       return;
     }
 
-    if (res.data.length === 0) {
+    if (res.data.records.length === 0) {
       ElMessage.warning("暂无数据");
       return;
     }
 
-    newElectricityData.value = res.data[0];
+    newElectricityData.value = res.data.records[0];
   } catch (error) {
     ElMessage.error("获取最新电表数据失败");
     console.error(error);
@@ -219,7 +221,7 @@ const getElectricityData = async () => {
       });
     }
 
-    const res = await request.get("/messageParse/findByPage", {
+    const res = await request.get("/messageParse/findByPageWithMutualInductance", {
       params: {
         pageNum: currentPage.value,
         pageSize: pageSize.value,
@@ -232,6 +234,8 @@ const getElectricityData = async () => {
       return;
     }
 
+    console.log(res.data);
+
     electricityRecords.value = res.data.records;
     totalRecords.value = res.data.total;
   } catch (error) {
@@ -496,15 +500,15 @@ onMounted(() => {
             <div class="grid grid-cols-3 gap-2">
               <div>
                 <span class="text-xs text-gray-500">A相:</span>
-                <span>{{ parseFloat(scope.row.aVoltage || 0).toFixed(2) }}</span>
+                <span>{{ parseFloat(scope.row.avoltage || 0).toFixed(2) }}</span>
               </div>
               <div>
                 <span class="text-xs text-gray-500">B相:</span>
-                <span>{{ parseFloat(scope.row.bVoltage || 0).toFixed(2) }}</span>
+                <span>{{ parseFloat(scope.row.bvoltage || 0).toFixed(2) }}</span>
               </div>
               <div>
                 <span class="text-xs text-gray-500">C相:</span>
-                <span>{{ parseFloat(scope.row.cVoltage || 0).toFixed(2) }}</span>
+                <span>{{ parseFloat(scope.row.cvoltage || 0).toFixed(2) }}</span>
               </div>
             </div>
           </template>
@@ -514,15 +518,15 @@ onMounted(() => {
             <div class="grid grid-cols-3 gap-2">
               <div>
                 <span class="text-xs text-gray-500">A相:</span>
-                <span>{{ parseFloat(scope.row.aCurrent || 0).toFixed(2) }}</span>
+                <span>{{ parseFloat(scope.row.acurrent || 0).toFixed(2) }}</span>
               </div>
               <div>
                 <span class="text-xs text-gray-500">B相:</span>
-                <span>{{ parseFloat(scope.row.bCurrent || 0).toFixed(2) }}</span>
+                <span>{{ parseFloat(scope.row.bcurrent || 0).toFixed(2) }}</span>
               </div>
               <div>
                 <span class="text-xs text-gray-500">C相:</span>
-                <span>{{ parseFloat(scope.row.cCurrent || 0).toFixed(2) }}</span>
+                <span>{{ parseFloat(scope.row.ccurrent || 0).toFixed(2) }}</span>
               </div>
             </div>
           </template>
@@ -537,15 +541,15 @@ onMounted(() => {
               <div class="grid grid-cols-3 gap-2 mt-1">
                 <div>
                   <span class="text-xs text-gray-500">A相:</span>
-                  <span>{{ parseFloat(scope.row.aActivePower || 0).toFixed(2) }}</span>
+                  <span>{{ parseFloat(scope.row.aactivePower || 0).toFixed(2) }}</span>
                 </div>
                 <div>
                   <span class="text-xs text-gray-500">B相:</span>
-                  <span>{{ parseFloat(scope.row.bActivePower || 0).toFixed(2) }}</span>
+                  <span>{{ parseFloat(scope.row.bactivePower || 0).toFixed(2) }}</span>
                 </div>
                 <div>
                   <span class="text-xs text-gray-500">C相:</span>
-                  <span>{{ parseFloat(scope.row.cActivePower || 0).toFixed(2) }}</span>
+                  <span>{{ parseFloat(scope.row.cactivePower || 0).toFixed(2) }}</span>
                 </div>
               </div>
             </div>
@@ -561,15 +565,15 @@ onMounted(() => {
               <div class="grid grid-cols-3 gap-2 mt-1">
                 <div>
                   <span class="text-xs text-gray-500">A相:</span>
-                  <span>{{ parseFloat(scope.row.aPower || 0).toFixed(2) }}</span>
+                  <span>{{ parseFloat(scope.row.apower || 0).toFixed(2) }}</span>
                 </div>
                 <div>
                   <span class="text-xs text-gray-500">B相:</span>
-                  <span>{{ parseFloat(scope.row.bPower || 0).toFixed(2) }}</span>
+                  <span>{{ parseFloat(scope.row.bpower || 0).toFixed(2) }}</span>
                 </div>
                 <div>
                   <span class="text-xs text-gray-500">C相:</span>
-                  <span>{{ parseFloat(scope.row.cPower || 0).toFixed(2) }}</span>
+                  <span>{{ parseFloat(scope.row.cpower || 0).toFixed(2) }}</span>
                 </div>
               </div>
             </div>

+ 2 - 2
vite.config.js

@@ -36,9 +36,9 @@ export default defineConfig(({ mode, command }) => {
         },
         // https://cn.vitejs.dev/config/#server-proxy
         '/dev-api': {
-          target: 'http://192.168.110.235:8100/background',
+          // target: 'http://192.168.110.235:8100/background',
           // target: 'http://localhost:8100/background',
-          // target: 'http://localhost:8101/',
+          target: 'http://localhost:8101/',
           changeOrigin: true,
           rewrite: (p) => p.replace(/^\/dev-api/, '')
         },