Преглед изворни кода

BUG的修改和农机设备管理

zmj пре 9 месеци
родитељ
комит
d5c51aeb5e

+ 1 - 0
src/api/base/machineAlarmRecords.js

@@ -17,6 +17,7 @@ export function getMachineAlarmRecords(id) {
   })
 }
 
+
 // 新增农机故障告警记录
 export function addMachineAlarmRecords(data) {
   return request({

+ 9 - 0
src/api/base/machineWorkRecords.js

@@ -26,6 +26,15 @@ export function addMachineWorkRecords(data) {
   })
 }
 
+
+
+export function getMachineNameFieldUser(farmId) {
+  return request({
+    url: '/base/machineWorkRecords/MachineNameFieldUser/' + farmId,
+    method: 'get'
+  })
+}
+
 // 修改农机作业记录
 export function updateMachineWorkRecords(data) {
   return request({

+ 8 - 1
src/api/base/sensor.js

@@ -8,4 +8,11 @@ export function getInfoLatestTime(deviceId) {
     url: '/base/sensor/LatestTime/' + deviceId,
     method: 'get'
   })
-}
+}
+
+export function listSensorStatistics(deviceId) {
+  return request({
+    url: '/base/sensor/listSensorStatistics/' + deviceId,
+    method: 'get',
+  })
+}

+ 19 - 0
src/api/base/weather.js

@@ -0,0 +1,19 @@
+import request from '@/utils/request'
+
+
+
+export function getInfoWeatherLatestTime(deviceId) {
+  return request({
+    url: '/base/weather/LatestTime/' + deviceId,
+    method: 'get'
+  })
+}
+
+
+export function listWeatherStatistics(query) {
+  return request({
+    url: '/base/weather/listWeatherStatistics',
+    method: 'get',
+    params: query
+  })
+}

Разлика између датотеке није приказан због своје велике величине
+ 183 - 158
src/views/base/device/device-monitor.vue


+ 417 - 94
src/views/base/device/index.vue

@@ -7,12 +7,6 @@
       <el-form-item label="设备名称" prop="deviceName">
         <el-input v-model="queryParams.deviceName" placeholder="请输入设备名称" clearable @keyup.enter.native="handleQuery" />
       </el-form-item>
-
-      <!-- <el-form-item label="设备类型" prop="deviceTypeId">
-        <el-input v-model="queryParams.deviceTypeId" placeholder="请输入设备类型" clearable
-          @keyup.enter.native="handleQuery" />
-      </el-form-item> -->
-
       <el-form-item label="设备类型" prop="deviceTypeId">
         <el-select v-model="queryParams.deviceTypeId" placeholder="请输入设备类型" clearable>
           <el-option v-for="dict in dict.type.device_type" :key="dict.value" :label="dict.label" :value="dict.value" />
@@ -20,23 +14,15 @@
       </el-form-item>
 
       <el-form-item label="所属地块" prop="fieldIdList">
-        <!-- <el-input
-          v-model="queryParams.supplierName"
-          placeholder="请输入供应商名称"
-          clearable
-          @keyup.enter.native="handleQuery"
-        /> -->
         <el-select v-model="queryParams.fieldIdList" placeholder="请选择地块" multiple collapse-tags filterable clearable>
           <el-option v-for="dict in fieldIdList" :key="dict.value" :label="dict.label" :value="dict.value" />
         </el-select>
       </el-form-item>
 
-      <!-- <el-form-item label="所属农场" prop="farmId">
-        <el-input v-model="queryParams.farmId" placeholder="请输入所属农场" clearable @keyup.enter.native="handleQuery" />
-      </el-form-item> -->
+
       <el-form-item label="所属农场" prop="deptIdList">
         <treeselect v-model="queryParams.deptIdList" :options="deptOptions" multiple :flat="true" :limit="1"
-          :limitText="count => `+${count}`" style="width:200px" :show-count="true" placeholder="请选所属机构" />
+          :limitText="count => `+${count}`" style="width:200px" :show-count="true" placeholder="请选所属农场" />
       </el-form-item>
 
 
@@ -56,19 +42,19 @@
     <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="['system:device:add']">新增</el-button>
+          v-hasPermi="['base: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="['system:device:edit']">修改</el-button>
+          v-hasPermi="['base: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="['system:device:remove']">删除</el-button>
+          v-hasPermi="['base: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="['system:device:export']">导出</el-button>
+          v-hasPermi="['base:device:export']">导出</el-button>
       </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
@@ -85,9 +71,6 @@
       </el-table-column>
       <el-table-column label="所属地块" align="center" key="fieldName" prop="fieldName" />
       <el-table-column label="所属农场" align="center" key="deptName" prop="dept.deptName" />
-      <!-- <template slot-scope="scope">
-          <dict-tag :options="dict.type.device_status" :value="scope.row.farmId"/>
-        </template> -->
 
       <el-table-column label="设备型号" align="center" prop="model" />
       <el-table-column label="厂家" align="center" prop="manufacturer" />
@@ -104,12 +87,12 @@
       <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="handleView(scope.row)"
-            v-hasPermi="['system:device:edit']">查看</el-button>
+            v-hasPermi="['base:device:edit']">查看</el-button>
 
           <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
-            v-hasPermi="['system:device:edit']">修改</el-button>
+            v-hasPermi="['base:device:edit']">修改</el-button>
           <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
-            v-hasPermi="['system:device:remove']">删除</el-button>
+            v-hasPermi="['base:device:remove']">删除</el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -126,31 +109,19 @@
         <el-form-item label="设备名称" prop="deviceName">
           <el-input v-model="form.deviceName" placeholder="请输入设备名称" />
         </el-form-item>
-        <!-- <el-form-item label="设备类型" prop="deviceTypeId">
-          <el-input v-model="form.deviceTypeId" placeholder="请输入设备类型" />
-        </el-form-item> -->
-
-
         <el-form-item label="设备类型" prop="deviceTypeId">
           <el-select v-model="form.deviceTypeId" placeholder="请选择设备类型">
             <el-option v-for="dict in dict.type.device_type" :key="dict.value" :label="dict.label"
               :value="dict.value"></el-option>
           </el-select>
         </el-form-item>
-
         <el-form-item label="厂家" prop="manufacturer">
           <el-input v-model="form.manufacturer" placeholder="请输入厂家" />
         </el-form-item>
-        <!-- <el-form-item label="所属农场" prop="farmId">
-          <el-input v-model="form.farmId" placeholder="请输入所属农场" />
-        </el-form-item> -->
-
         <el-form-item label="所属农场" prop="farmId">
           <treeselect v-model="form.farmId" :options="deptOptions" :show-count="true" placeholder="请选所属机构"
             @input='queryPersonCharge(form.farmId)' />
         </el-form-item>
-
-
         <el-form-item label="设备型号" prop="model">
           <el-input v-model="form.model" placeholder="请输入设备型号" />
         </el-form-item>
@@ -256,7 +227,7 @@
                 <el-card>
                   <div class="item-content">
 
-                    <div class="item-value" style="color: #059669;">{{ sensorRealTime.temperature }}</div>
+                    <div class="item-value" style="color: #059669;">{{ sensorRealTime.temperature }}°C</div>
                     <div class="item-title">温度 (°C)</div>
                   </div>
                 </el-card>
@@ -274,7 +245,7 @@
                 <el-card>
                   <div class="item-content">
 
-                    <div class="item-value">{{ sensorRealTime.illuminance }}</div>
+                    <div class="item-value">{{ sensorRealTime.lightIntensity }}</div>
                     <div class="item-title">光照 (lux)</div>
                   </div>
                 </el-card>
@@ -297,8 +268,9 @@
               <el-col :span="6">
                 <el-card>
                   <div class="item-content">
-                    <div class="item-title">平均温度</div>
-                    <div class="item-value" style="color: #059669;">{{ AverageSensorRealTime.temperature }}</div>
+                    <div class="item-title">温度</div>
+                    <div style="color: #1e1e1e;">最高温度{{ AverageSensorRealTime.temperature }}°C</div>
+                    <div style="color: #1e1e1e;">最低温度{{ AverageSensorRealTime.temperature }}°C</div>
 
                   </div>
                 </el-card>
@@ -315,7 +287,7 @@
                 <el-card>
                   <div class="item-content">
                     <div class="item-title">平均光照</div>
-                    <div class="item-value">{{ AverageSensorRealTime.illuminance }}</div>
+                    <div class="item-value">{{ AverageSensorRealTime.lightIntensity }}lux</div>
 
                   </div>
                 </el-card>
@@ -408,14 +380,14 @@
           <el-card class="box-card">
             <div slot="header" class="clearfix">
               <span>实时气象数据</span>
-              <el-badge style="margin-left: 70%;">最后更新: {{ sensorRealTime.lastUpdateTime }}</el-badge>
+              <el-badge style="margin-left: 70%;">最后更新: {{ weatherRealTime.collectTime }}</el-badge>
             </div>
             <el-row :gutter="20">
               <el-col :span="6">
                 <el-card>
                   <div class="item-content">
 
-                    <div class="item-value" style="color: #059669;">{{ sensorRealTime.temperature }}</div>
+                    <div class="item-value" style="color: #059669;">{{ weatherRealTime.temperature }}°C</div>
                     <div class="item-title">气温 (°C)</div>
                   </div>
                 </el-card>
@@ -424,7 +396,7 @@
                 <el-card>
                   <div class="item-content">
 
-                    <div class="item-value" style="color: #2563eb;">{{ sensorRealTime.humidity }}%</div>
+                    <div class="item-value" style="color: #2563eb;">{{ weatherRealTime.humidity }}%</div>
                     <div class="item-title">湿度</div>
                   </div>
                 </el-card>
@@ -433,7 +405,7 @@
                 <el-card>
                   <div class="item-content">
 
-                    <div class="item-value">{{ sensorRealTime.illuminance }}</div>
+                    <div class="item-value">{{ weatherRealTime.rainfall }}mm</div>
                     <div class="item-title">降雨量 (lux)</div>
                   </div>
                 </el-card>
@@ -442,7 +414,7 @@
                 <el-card>
                   <div class="item-content">
 
-                    <div class="item-value" style="color: #7c3aed;">{{ sensorRealTime.soilMoisture }}%</div>
+                    <div class="item-value" style="color: #7c3aed;">{{ weatherRealTime.windDirection }}</div>
                     <div class="item-title">风向</div>
                   </div>
                 </el-card>
@@ -455,7 +427,7 @@
                 <el-card>
                   <div class="item-content">
 
-                    <div class="item-value" style="color: #059669;">{{ sensorRealTime.temperature }}</div>
+                    <div class="item-value" style="color: #059669;">{{ weatherRealTime.windSpeed }}m/s</div>
                     <div class="item-title">风速</div>
                   </div>
                 </el-card>
@@ -464,7 +436,7 @@
                 <el-card>
                   <div class="item-content">
 
-                    <div class="item-value" style="color: #2563eb;">{{ sensorRealTime.humidity }}%</div>
+                    <div class="item-value" style="color: #2563eb;">{{ weatherRealTime.airPressure }}hPa</div>
                     <div class="item-title">气压</div>
                   </div>
                 </el-card>
@@ -473,23 +445,66 @@
                 <el-card>
                   <div class="item-content">
 
-                    <div class="item-value">{{ sensorRealTime.illuminance }}</div>
+                    <div class="item-value">{{ weatherRealTime.lightIntensity }}lux</div>
                     <div class="item-title">光照</div>
                   </div>
                 </el-card>
               </el-col>
 
+              <el-col :span="6">
+                <el-card>
+                  <div class="item-content">
+
+                    <div class="item-value">{{ weatherRealTime.soilN }}</div>
+                    <div class="item-title">土壤氮</div>
+                  </div>
+                </el-card>
+              </el-col>
+            </el-row>
+
+            <el-row :gutter="20">
+              <el-col :span="6">
+                <el-card>
+                  <div class="item-content">
+
+                    <div class="item-value">{{ weatherRealTime.soilP }}</div>
+                    <div class="item-title">土壤磷</div>
+                  </div>
+                </el-card>
+              </el-col>
+
+              <el-col :span="6">
+                <el-card>
+                  <div class="item-content">
+
+                    <div class="item-value">{{ weatherRealTime.soilK }}</div>
+                    <div class="item-title">土壤钾</div>
+                  </div>
+                </el-card>
+              </el-col>
             </el-row>
           </el-card>
-          <div ref="chart" id="demoDiv" style="width: 750px; height: 400px;">
+          <div>
+
+            <div class="weather-chart-header">
+              <p>气象数据统计图</p>
+              <div class="time-btns">
+                <el-button @click="twentyFourHours" round>24小时</el-button>
+                <el-button @click="sevenDays" round>7天</el-button>
+                <el-button @click="thirtyDays" round>30天</el-button>
+              </div>
+            </div>
+            <div ref="chart" id="weather" style="width: 750px; height: 400px;"></div>
+
           </div>
+
           <el-card class="box-card">
             <el-row :gutter="20">
               <el-col :span="6">
                 <el-card>
                   <div class="item-content">
                     <div class="item-title">平均气温</div>
-                    <div class="item-value" style="color: #059669;">{{ AverageSensorRealTime.temperature }}</div>
+                    <div class="item-value" style="color: #059669;">{{ AverageweatherRealTime.temperature }}°C</div>
 
                   </div>
                 </el-card>
@@ -498,7 +513,7 @@
                 <el-card>
                   <div class="item-content">
                     <div class="item-title">平均湿度</div>
-                    <div class="item-value" style="color: #2563eb;">{{ AverageSensorRealTime.humidity }}%</div>
+                    <div class="item-value" style="color: #2563eb;">{{ AverageweatherRealTime.humidity }}%</div>
                   </div>
                 </el-card>
               </el-col>
@@ -506,7 +521,7 @@
                 <el-card>
                   <div class="item-content">
                     <div class="item-title">累计降雨量</div>
-                    <div class="item-value">{{ AverageSensorRealTime.illuminance }}</div>
+                    <div class="item-value">{{ AverageweatherRealTime.rainfallA }}mm</div>
 
                   </div>
                 </el-card>
@@ -515,7 +530,36 @@
                 <el-card>
                   <div class="item-content">
                     <div class="item-title">平均风速</div>
-                    <div class="item-value" style="color: #7c3aed;">{{ AverageSensorRealTime.soilMoisture }}%</div>
+                    <div class="item-value" style="color: #7c3aed;">{{ AverageweatherRealTime.windSpeed }}m/s</div>
+
+                  </div>
+                </el-card>
+              </el-col>
+            </el-row>
+
+            <el-row :gutter="20">
+              <el-col :span="6">
+                <el-card>
+                  <div class="item-content">
+                    <div class="item-title">土壤氮</div>
+                    <div class="item-value" style="color: #059669;">{{ AverageweatherRealTime.soilN }}</div>
+
+                  </div>
+                </el-card>
+              </el-col>
+              <el-col :span="6">
+                <el-card>
+                  <div class="item-content">
+                    <div class="item-title">土壤磷</div>
+                    <div class="item-value" style="color: #2563eb;">{{ AverageweatherRealTime.soilP }}</div>
+                  </div>
+                </el-card>
+              </el-col>
+              <el-col :span="6">
+                <el-card>
+                  <div class="item-content">
+                    <div class="item-title">土壤钾</div>
+                    <div class="item-value">{{ AverageweatherRealTime.soilK }}</div>
 
                   </div>
                 </el-card>
@@ -650,7 +694,8 @@
 
 <script>
 import { listDevice, getDevice, delDevice, addDevice, updateDevice } from "@/api/base/device"
-import { getInfoLatestTime } from "@/api/base/sensor"
+import { getInfoLatestTime, listSensorStatistics } from "@/api/base/sensor"
+import { getInfoWeatherLatestTime, listWeatherStatistics } from "@/api/base/weather"
 import { listFieldName } from "@/api/base/field"
 import { deptTreeSelect } from "@/api/system/user";
 import Treeselect from "@riophae/vue-treeselect";
@@ -699,15 +744,40 @@ export default {
       openControllerView: false,
 
       // 传感器日期数据
-      sensorDate: ['5/31', '6/1', '6/2', '6/3', '6/4', '6/5', '6/6'],
-      // 传感器温度数据
-      sensorTemperature: [22, 24, 28, 26, 24, 22, 22],
+      sensorDate: [],
+      // 传感器最高温度数据
+      maxTemperature: [],
+      // 传感器最底温度数据
+      minTemperature: [],
       // 传感器湿度数据
-      sensorHumidity: [70, 60, 65, 75, 55, 60, 67],
+      avgHumidity: [],
       // 传感器光照数据
-      sensorIllumination: [null, null, null, 78, 55, 60, 68],
+      avgLightIntensity: [],
       // 传感器土壤湿度数据
-      sensorSoilMoisture: [20, 22, 25, 24, 22, 22, 22],
+      avgSoilMoisture: [],
+
+
+
+
+      // 气象设备日期数据
+      weatherDate: ['6/20', '6/21', '6/22', '6/23', '6/24', '6/25', '6/26'],
+      /* weatherDate: ['00:00', '01:00', '02:00', '03:00', '04:00', '05:00', '06:00', '07:00', '08:00', '09:00', '10:00', '11:00', '12:00', '13:00', '14:00', '15:00', '16:00', '17:00', '18:00', '19:00', '20:00', '21:00', '22:00', '23:00'], */
+      // 气象设备最高温度数据
+      weatherMaxTemperature: [31, 20, 25, 13, 24, 23, 26],
+      // 气象设备最低温度数据
+      weatherMinTemperature: [31, 20, 25, 13, 24, 23, 26],
+      // 气象设备湿度数据
+      weatherHumidity: [75, 63, 65, 73, 58, 50, 65],
+      // 气象设备降雨数据
+      weatherRainfall: [70, 23, 45, 38, 55, 60, 68],
+      // 气象设备风速数据
+      weatherWindSpeed: [20, 22, 25, 24, 22, 22, 22],
+      // 气象设备氮数据
+      weatherAvgSoilN: [20, 22, 25, 24, 22, 22, 22],
+      // 气象设备磷数据
+      weatherAvgSoilP: [20, 22, 25, 24, 22, 22, 22],
+      // 气象设备钾数据
+      weatherAvgSoilK: [20, 22, 25, 24, 22, 22, 22],
 
       controlStatus: [
         { name: '水泵1#', status: 'success' },
@@ -716,6 +786,7 @@ export default {
         { name: '灌溉阀门', status: 'warning' },
         { name: '照明系统', status: 'info' }
       ],
+
       systemMode: 'auto',
       waterPump1Flow: 65,
       fanSpeed: 80,
@@ -730,26 +801,58 @@ export default {
 
       // 传感器实时数据
       sensorRealTime: {
-        temperature: 26.5,
-        humidity: 65,
-        illuminance: 782,
-        soilMoisture: 25,
-        collectTime: '2023-10-16 15:45',
+        temperature: null,
+        humidity: null,
+        lightIntensity: null,
+        soilMoisture: null,
+        collectTime: null,
       },
       // 传感器实时数据平均
       AverageSensorRealTime: {
-        temperature: 26.5,
-        humidity: 65,
-        illuminance: 782,
-        soilMoisture: 25,
-        lastUpdateTime: '2023-10-16 15:45',
+        temperature: null,
+        humidity: null,
+        lightIntensity: null,
+        soilMoisture: null,
       },
-      weatherRealTime: {
 
+      weatherRealTime: {
+        temperature: null,
+        humidity: null,
+        rainfall: null,
+        collectTime: null,
+        windSpeed: null,
+        windDirection: null,
+        airPressure: null,
+        lightIntensity: null,
       },
-      AverageweatherRealTime:{
+
+      /*  weatherRealTime: {
+         temperature: 24.8,
+         humidity: 76,
+         rainfall: 2.5,
+         collectTime: '2025-10-16 15:50',
+         windSpeed: 3.2,
+         windDirection: '东北',
+         airPressure: 1013,
+         lightIntensity: 12500,
+       }, */
+      AverageweatherRealTime: {
+        temperature: null,
+        humidity: null,
+        rainfallA: null,
+        windSpeed: null,
+        soilN: null,
+        soilP: null,
+        soilK: null,
 
       },
+      /* AverageweatherRealTime: {
+        temperature: null,
+        humidity: null,
+        rainfall: null,
+        windSpeed: null,
+
+      }, */
       deviceInfo: {
         deviceCode: 'DEV20230001',
         deviceName: '温湿度传感器-A1',
@@ -803,6 +906,9 @@ export default {
         updateTime: [
           { required: true, message: "更新时间不能为空", trigger: "blur" }
         ],
+        farmId: [
+          { required: true, message: "所属农场不能为空", trigger: "blur" }
+        ],
       }
     }
   },
@@ -831,13 +937,9 @@ export default {
           x.value = x.id;
           x.label = x.fieldName;
         })
-        console.info(this.deviceList)
       });
     },
 
-
-
-
     Sensor() {
       // let lCharts = echarts.init(document.getElementById('demoDiv'))
       const chart = echarts.init(document.getElementById('sensor'));
@@ -847,7 +949,7 @@ export default {
         },
         tooltip: {},
         legend: {
-          data: ['温度', '湿度', '光照', '土壤湿度']
+          data: ['最低温度', '最高温度', '湿度', '光照', '土壤湿度']
         },
         xAxis: {
           type: 'category',
@@ -863,9 +965,18 @@ export default {
         },
         series: [
           {
-            name: '温度',
+            name: '最低温度',
+            type: 'line',
+            data: this.minTemperature,
+            smooth: true,
+            areaStyle: {
+
+            }
+          },
+          {
+            name: '最高温度',
             type: 'line',
-            data: this.sensorTemperature,
+            data: this.maxTemperature,
             smooth: true,
             areaStyle: {
 
@@ -874,7 +985,7 @@ export default {
           {
             name: '湿度',
             type: 'line',
-            data: this.sensorHumidity,
+            data: this.avgHumidity,
             smooth: true,
             areaStyle: {
 
@@ -883,7 +994,7 @@ export default {
           {
             name: '光照',
             type: 'line',
-            data: this.sensorIllumination,
+            data: this.avgLightIntensity,
             smooth: true,
             areaStyle: {
 
@@ -892,7 +1003,110 @@ export default {
           {
             name: '土壤湿度',
             type: 'line',
-            data: this.sensorSoilMoisture,
+            data: this.avgSoilMoisture,
+            smooth: true,
+            areaStyle: {
+
+            }
+          }
+        ]
+      };
+      chart.setOption(option);
+
+    },
+
+    /* 气象设备数据图 */
+    weather() {
+      // let lCharts = echarts.init(document.getElementById('demoDiv'))
+      const chart = echarts.init(document.getElementById('weather'));
+      const option = {
+        /* title: {
+          text: '数据统计图'
+        }, */
+        tooltip: {},
+        legend: {
+          data: ['最高温度', '最低温度', '湿度', '降雨量', '风速','土壤氮','土壤磷','土壤钾']
+        },
+        xAxis: {
+          type: 'category',
+          data: this.weatherDate
+        },
+        yAxis: {
+          type: 'value'
+        },
+        toolbox: {
+          feature: {
+            saveAsImage: {}
+          }
+        },
+        series: [
+          {
+            name: '最高温度',
+            type: 'line',
+            data: this.weatherMaxTemperature,
+            smooth: true,
+            areaStyle: {
+
+            }
+          },
+          {
+            name: '最低温度',
+            type: 'line',
+            data: this.weatherMinTemperature,
+            smooth: true,
+            areaStyle: {
+
+            }
+          },
+          {
+            name: '湿度',
+            type: 'line',
+            data: this.weatherHumidity,
+            smooth: true,
+            areaStyle: {
+
+            }
+          },
+          {
+            name: '降雨量',
+            type: 'line',
+            data: this.weatherRainfall,
+            smooth: true,
+            areaStyle: {
+
+            }
+          },
+          {
+            name: '风速',
+            type: 'line',
+            data: this.weatherWindSpeed,
+            smooth: true,
+            areaStyle: {
+
+            }
+          },
+          {
+            name: '土壤氮',
+            type: 'line',
+            data: this.weatherAvgSoilN,
+            smooth: true,
+            areaStyle: {
+
+            }
+          },
+          {
+            name: '土壤磷',
+            type: 'line',
+            data: this.weatherAvgSoilP,
+            smooth: true,
+            areaStyle: {
+
+            }
+          },
+          {
+            name: '土壤钾',
+            type: 'line',
+            data: this.weatherAvgSoilK,
             smooth: true,
             areaStyle: {
 
@@ -946,9 +1160,38 @@ export default {
         console.log("传感器第二个");
         console.log(this.deviceId);
 
-        getInfoLatestTime(this.deviceId).then(response => {
-        this.sensorRealTime = response.rows
-      })
+
+        /* getInfoLatestTime(this.deviceId).then(response => {
+          this.sensorRealTime = response.data
+        }) */
+        getInfoLatestTime(this.deviceId)
+          .then(response => {
+            const data = response?.data;
+            if (data == null || (Array.isArray(data) && data.length === 0)) {
+              console.warn('实时传感器数据为空');
+            } else {
+              this.sensorRealTime = data;
+            }
+          })
+          .catch(err => {
+            console.error('获取实时数据失败', err);
+            this.sensorRealTime = null;
+          });
+        listSensorStatistics(this.deviceId).then(response => {
+          this.sensorDate = response.data.sensorDate
+          this.maxTemperature = response.data.maxTemperature
+          this.minTemperature = response.data.minTemperature
+          this.avgHumidity = response.data.avgHumidity
+          this.avgLightIntensity = response.data.avgLightIntensity
+          this.avgSoilMoisture = response.data.avgSoilMoisture
+          this.$nextTick(() => {
+            this.Sensor();
+          });
+          this.AverageSensorRealTime = response.data.sensorRealtimeData
+
+        })
+
+
       } else {
         //网络请求3getUserField
         console.log("传感器第三个");
@@ -957,6 +1200,43 @@ export default {
     },
 
 
+    _fetchWeather(days = null) {
+      const query = { deviceId: this.deviceId };
+      if (days != null) query.NumberDay = days;
+
+      const label = days == null ? '7天' : days === 24 ? '24小时' : `${days}天`;
+      console.log(`按${label}键了`);
+
+      listWeatherStatistics(query).then(({ data }) => {
+        Object.assign(this, {
+          weatherDate: data.weatherDate,
+          weatherMaxTemperature: data.weatherMaxTemperature,
+          weatherMinTemperature: data.weatherMinTemperature,
+          weatherHumidity: data.weatherHumidity,
+          weatherRainfall: data.weatherRainfall,
+          weatherWindSpeed: data.weatherWindSpeed,
+          weatherAvgSoilN: data.weatherAvgSoilN,
+          weatherAvgSoilP: data.weatherAvgSoilP,
+          weatherAvgSoilK: data.weatherAvgSoilK,
+          AverageweatherRealTime: data.weatherRealtimeData
+        });
+
+        this.$nextTick(this.weather);
+      });
+    },
+
+    /* 三个按钮入口 */
+    twentyFourHours() {
+      this._fetchWeather(24);
+    },
+    sevenDays() {
+      this._fetchWeather();
+    },
+    thirtyDays() {
+      this._fetchWeather(30);
+    },
+
+
     /* 气象设备切换事件 */
     handleClickWeather(tab, event) {
       console.log(tab, event);
@@ -964,6 +1244,45 @@ export default {
         console.log("气象设备第一个");
       } else if (tab.index == 1) {
 
+
+        /* getInfoWeatherLatestTime(this.deviceId).then(response => {
+          if (response.data) {
+            this.weatherRealTime = response.data;
+          }
+        }) */
+
+        getInfoWeatherLatestTime(this.deviceId)
+          .then(response => {
+            const data = response?.data;
+            if (data == null || Object.keys(data).length === 0) {
+              console.warn('最新气象数据为空');
+            } else {
+              this.weatherRealTime = data;
+            }
+          })
+          .catch(err => {
+            console.error('获取最新气象数据失败', err);
+          });
+
+        const query = { deviceId: this.deviceId };
+
+        listWeatherStatistics(query).then(response => {
+          this.weatherDate = response.data.weatherDate
+          this.weatherMaxTemperature = response.data.weatherMaxTemperature
+          this.weatherMinTemperature = response.data.weatherMinTemperature
+          this.weatherHumidity = response.data.weatherHumidity
+          this.weatherRainfall = response.data.weatherRainfall
+          this.weatherWindSpeed = response.data.weatherWindSpeed
+          this.weatherAvgSoilN = response.data.weatherAvgSoilN
+          this.weatherAvgSoilP = response.data.weatherAvgSoilP
+          this.weatherAvgSoilK = response.data.weatherAvgSoilK
+          this.$nextTick(() => {
+            this.weather();
+          });
+          this.AverageweatherRealTime = response.data.weatherRealtimeData
+
+        })
+
         console.log("气象设备第二个");
       } else {
         //网络请求3getUserField
@@ -1101,11 +1420,6 @@ export default {
 
         this.openView = true
 
-        this.$nextTick(() => {
-          this.Sensor();
-        });
-
-
       } else if (row.deviceTypeId == 2) {// 摄像头
       } else if (row.deviceTypeId == 3) {// 控制器
         this.openControllerView = true
@@ -1146,7 +1460,7 @@ export default {
     },
     /** 导出按钮操作 */
     handleExport() {
-      this.download('system/device/export', {
+      this.download('base/device/export', {
         ...this.queryParams
       }, `device_${new Date().getTime()}.xlsx`)
     }
@@ -1188,4 +1502,13 @@ ul {
 .item-value {
   font-size: 24px;
 }
+
+.weather-chart-header {
+  display: flex;
+  /* 关键:让子元素横向排列 */
+  align-items: center;
+  /* 垂直居中 */
+  gap: 12px;
+  /* 按钮之间的间距 */
+}
 </style>

+ 14 - 12
src/views/base/field/index.vue

@@ -46,8 +46,8 @@
         </el-select>
       </el-form-item>
 
-      <el-form-item label="负责人" prop="managerId">
-        <el-input v-model="queryParams.managerId" placeholder="请输入负责人" clearable @keyup.enter.native="handleQuery" />
+      <el-form-item label="负责人" prop="managerName">
+        <el-input v-model="queryParams.managerName" placeholder="请输入负责人" clearable @keyup.enter.native="handleQuery" />
       </el-form-item>
       <!-- <el-form-item label="创建时间" prop="createdTime">
         <el-date-picker clearable v-model="queryParams.createdTime" type="date" value-format="yyyy-MM-dd"
@@ -71,19 +71,19 @@
     <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="['system:field:add']">新增</el-button>
+          v-hasPermi="['base:field: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="['system:field:edit']">修改</el-button>
+          v-hasPermi="['base:field: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="['system:field:remove']">删除</el-button>
+          v-hasPermi="['base:field: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="['system:field:export']">导出</el-button>
+          v-hasPermi="['base:field:export']">导出</el-button>
       </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
@@ -137,11 +137,11 @@
         <template slot-scope="scope">
 
           <el-button size="mini" type="text" icon="el-icon-edit" @click="management(scope.row)"
-            v-hasPermi="['system:field:edit']">管理</el-button>
+            v-hasPermi="['base:field:management']">管理</el-button>
           <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
-            v-hasPermi="['system:field:edit']">修改</el-button>
+            v-hasPermi="['base:field:edit']">修改</el-button>
           <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
-            v-hasPermi="['system:field:remove']">删除</el-button>
+            v-hasPermi="['base:field:remove']">删除</el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -271,6 +271,7 @@ export default {
         irrigationType: null,
         status: null,
         managerId: null,
+        managerName: null,
         description: null,
         locationData: null,
         createdTime: null,
@@ -292,7 +293,7 @@ export default {
           { required: true, message: "地块名称不能为空", trigger: "blur" }
         ],
         farmId: [
-          { required: true, message: "所属农场ID不能为空", trigger: "blur" }
+          { required: true, message: "所属农场不能为空", trigger: "blur" }
         ],
         fieldType: [
           { required: true, message: "地块类型不能为空", trigger: "change" }
@@ -344,7 +345,7 @@ export default {
     getList() {
 
       console.log(this.queryParams);
-      
+
       this.loading = true
       if (null != this.queryParams.rangeTime && '' != this.queryParams.rangeTime) {
         this.queryParams.params["beginfieldDate"] = this.queryParams.rangeTime[0];
@@ -375,6 +376,7 @@ export default {
         irrigationType: null,
         status: null,
         managerId: null,
+        managerName: null,
         description: null,
         locationData: null,
         createdTime: null,
@@ -421,7 +423,7 @@ export default {
     /** 管理按钮操作 */
     management(row) {
       //console.log(row.id);
-      
+
        this.$router.push('/management/index/' + row.id);
     },
     /** 提交按钮 */

+ 4 - 4
src/views/base/field/management.vue

@@ -74,11 +74,11 @@
               </el-form-item></el-col>
             <el-col :span="6">
               <el-form-item label="绑定设备">
-                <span>{{ basicInfo.devices }}</span>
+                <span>{{ basicInfo.bindDeviceCount }}</span>
               </el-form-item></el-col>
             <el-col :span="6">
               <el-form-item label="绑定人员">
-                <span>{{ basicInfo.bindPeople }}</span>
+                <span>{{ basicInfo.bindUserCount }}</span>
               </el-form-item>
             </el-col>
             <el-col :span="6">
@@ -177,7 +177,7 @@
             </el-table-column>
             <el-table-column prop="status" label="状态">
               <template slot-scope="scope">
-          
+
                 <dict-tag :options="dict.type.device_status" :value="scope.row.status" />
               </template>
             </el-table-column>
@@ -506,4 +506,4 @@ export default {
   width: 100%;
   height: 800px;
 }
-</style>
+</style>

+ 216 - 235
src/views/base/machineAlarmRecords/index.vue

@@ -1,66 +1,49 @@
 <template>
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
-      <el-form-item label="农机编号" prop="machineId">
-        <el-input
-          v-model="queryParams.machineId"
-          placeholder="请输入农机编号关键词"
-          clearable
-          @keyup.enter.native="handleQuery"
-        />
+      <el-form-item label="农机编号" prop="machineCode">
+        <el-input v-model="queryParams.machineCode" placeholder="请输入农机编号关键词" clearable
+          @keyup.enter.native="handleQuery" />
       </el-form-item>
       <el-form-item label="农机名称" prop="machineName">
-        <el-input
-          v-model="queryParams.machineName"
-          placeholder="请输入农机名称关键词"
-          clearable
-          @keyup.enter.native="handleQuery"
-        />
+        <el-input v-model="queryParams.machineName" placeholder="请输入农机名称关键词" clearable
+          @keyup.enter.native="handleQuery" />
       </el-form-item>
+
       <el-form-item label="告警等级" prop="alarmLevel">
         <el-select v-model="queryParams.alarmLevel" placeholder="所有告警等级" clearable>
-          <el-option label="提示" value="3" />
-          <el-option label="告警" value="2" />
-          <el-option label="紧急" value="1" />
+          <el-option v-for="dict in dict.type.machine_alarm_level" :key="dict.value" :label="dict.label"
+            :value="dict.value" />
         </el-select>
       </el-form-item>
+
+
       <el-form-item label="农机类型" prop="machineType">
         <el-select v-model="queryParams.machineType" placeholder="所有农机类型" clearable>
-          <el-option label="拖拉机" value="tractor" />
-          <el-option label="收割机" value="harvester" />
-          <el-option label="播种机" value="seeder" />
-          <el-option label="喷药机" value="sprayer" />
-          <el-option label="耕地机" value="cultivator" />
+          <el-option v-for="dict in dict.type.agricultural_machine_type" :key="dict.value" :label="dict.label"
+            :value="dict.value" />
         </el-select>
       </el-form-item>
-      <el-form-item label="所属农场" prop="farmId">
-        <el-select v-model="queryParams.farmId" placeholder="所有农场" clearable>
-          <el-option label="绿野农场" value="1" />
-          <el-option label="丰收农场" value="2" />
-          <el-option label="田园农场" value="3" />
-          <el-option label="生态农场" value="4" />
-          <el-option label="科技农场" value="5" />
-        </el-select>
+
+
+
+      <el-form-item label="所属农场" prop="deptIdList">
+        <treeselect v-model="queryParams.deptIdList" :options="deptOptions" multiple :flat="true" :limit="1"
+          :limitText="count => `+${count}`" style="width:200px" :show-count="true" placeholder="请选所属农场" />
       </el-form-item>
+
       <el-form-item label="告警时间">
-        <el-date-picker
-          v-model="daterangeAlarmTime"
-          style="width: 240px"
-          value-format="yyyy-MM-dd"
-          type="daterange"
-          range-separator="至"
-          start-placeholder="年/月/日"
-          end-placeholder="年/月/日"
-        ></el-date-picker>
+        <el-date-picker v-model="daterangeAlarmTime" style="width: 240px" value-format="yyyy-MM-dd" type="daterange"
+          range-separator="至" start-placeholder="年/月/日" end-placeholder="年/月/日"></el-date-picker>
       </el-form-item>
+
       <el-form-item label="处理状态" prop="handledStatus">
         <el-select v-model="queryParams.handledStatus" placeholder="所有状态" clearable>
-          <el-option label="未处理" value="0" />
-          <el-option label="已处理" value="1" />
-          <el-option label="处理中" value="2" />
-          <el-option label="忽略" value="3" />
+          <el-option v-for="dict in dict.type.machine_handled_status" :key="dict.value" :label="dict.label"
+            :value="dict.value" />
         </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>
@@ -82,7 +65,7 @@
               </div>
             </div>
           </div>
-      </el-col>
+        </el-col>
         <el-col :span="6">
           <div class="stat-card emergency">
             <div class="stat-header">
@@ -95,7 +78,7 @@
               </div>
             </div>
           </div>
-      </el-col>
+        </el-col>
         <el-col :span="6">
           <div class="stat-card warning">
             <div class="stat-header">
@@ -108,7 +91,7 @@
               </div>
             </div>
           </div>
-      </el-col>
+        </el-col>
         <el-col :span="6">
           <div class="stat-card info">
             <div class="stat-header">
@@ -127,14 +110,8 @@
 
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button
-          type="warning"
-          plain
-          icon="el-icon-download"
-          size="mini"
-          @click="handleExport"
-          v-hasPermi="['base:machineAlarmRecords:export']"
-        >导出</el-button>
+        <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport"
+          v-hasPermi="['base:machineAlarmRecords:export']">导出</el-button>
       </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
@@ -142,38 +119,54 @@
     <el-table v-loading="loading" :data="machineAlarmRecordsList" @selection-change="handleSelectionChange">
       <el-table-column type="selection" width="55" align="center" />
       <el-table-column label="告警ID" align="center" prop="id" />
-      <el-table-column label="告警等级" align="center" prop="alarmLevel">
+      <!-- <el-table-column label="告警等级" align="center" prop="alarmLevel">
         <template slot-scope="scope">
           <span :class="['custom-tag', 'level-tag', getAlertLevelClass(scope.row.alarmLevel)]">
             {{ getAlertLevelText(scope.row.alarmLevel) }}
           </span>
         </template>
-      </el-table-column>
-      <el-table-column label="农机名称" align="center" prop="machineName">
+</el-table-column> -->
+
+
+      <el-table-column label="告警等级" align="center" prop="alarmLevel">
         <template slot-scope="scope">
-          <span>{{ getMachineName(scope.row.machineId) }}</span>
+          <dict-tag :options="dict.type.machine_alarm_level" :value="scope.row.alarmLevel" />
         </template>
       </el-table-column>
-      <el-table-column label="农机编号" align="center" prop="machineId" />
-      <el-table-column label="农机类型" align="center" prop="machineType">
+
+      <el-table-column label="农机名称" align="center" key="machineName" prop="machineName" />
+
+      <el-table-column label="农机编号" align="center" prop="machineCode" />
+
+      <!--  <el-table-column label="农机类型" align="center" prop="machineType">
         <template slot-scope="scope">
           <span>{{ getMachineType(scope.row.machineId) }}</span>
         </template>
+      </el-table-column> -->
+
+      <el-table-column label="农机类型" align="center" prop="machineType">
+        <template slot-scope="scope">
+          <dict-tag :options="dict.type.agricultural_machine_type" :value="scope.row.machineType" />
+        </template>
       </el-table-column>
-      <el-table-column label="所属农场" align="center" prop="farmName">
+
+      <el-table-column label="所属农场" align="center" key="deptName" prop="deptName" />
+
+
+      <!-- <el-table-column label="所属农场" align="center" prop="farmName">
         <template slot-scope="scope">
           <span>{{ getFarmName(scope.row.machineId) }}</span>
         </template>
-      </el-table-column>
+      </el-table-column> -->
       <el-table-column label="告警类型" align="center" prop="alarmType">
         <template slot-scope="scope">
-          <dict-tag :options="dict.type.machine_alarm_type" :value="scope.row.alarmType"/>
+          <dict-tag :options="dict.type.machine_alarm_type" :value="scope.row.alarmType" />
         </template>
       </el-table-column>
       <el-table-column label="告警内容" align="center" prop="alarmDesc" />
       <el-table-column label="告警时间" align="center" prop="alarmTime" width="180">
         <template slot-scope="scope">
-          <span>{{ parseTime(scope.row.alarmTime, '{y}-{m}-{d}') }}</span>
+          <span>{{ scope.row.alarmTime }}</span>
         </template>
       </el-table-column>
       <el-table-column label="处理状态" align="center" prop="handledStatus">
@@ -186,36 +179,22 @@
       <el-table-column label="处理人" align="center" prop="handlerName" />
       <el-table-column label="处理时间" align="center" prop="handleTime" width="180">
         <template slot-scope="scope">
-          <span>{{ parseTime(scope.row.handleTime, '{y}-{m}-{d}') }}</span>
+          <span>{{ scope.row.handleTime }}</span>
         </template>
       </el-table-column>
       <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-view"
-            @click="handleDetail(scope.row)"
-          >查看</el-button>
+          <el-button size="mini" type="text" icon="el-icon-view" @click="handleDetail(scope.row)">查看</el-button>
           <el-button
             v-if="scope.row.handledStatus == 0 || scope.row.handledStatus == '0' || scope.row.handledStatus == 2 || scope.row.handledStatus == '2'"
-            size="mini"
-            type="text"
-            icon="el-icon-edit"
-            @click="handleProcess(scope.row)"
-            v-hasPermi="['base:machineAlarmRecords:edit']"
-          >处理</el-button>
+            size="mini" type="text" icon="el-icon-edit" @click="handleProcess(scope.row)"
+            v-hasPermi="['base:machineAlarmRecords:edit']">处理</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="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
+      @pagination="getList" />
 
     <!-- 告警详情对话框 -->
     <el-dialog title="告警详情" :visible.sync="detailOpen" width="600px" append-to-body>
@@ -231,13 +210,13 @@
             </div>
             <div class="alert-time">{{ parseTime(currentRecord.alarmTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</div>
           </div>
-          
+
           <!-- 告警内容 -->
           <div class="alert-content">
             {{ getAlertContent(currentRecord) }}
           </div>
         </div>
-        
+
         <!-- 设备信息 -->
         <div class="section">
           <div class="section-title">设备信息</div>
@@ -245,24 +224,26 @@
             <div class="info-grid">
               <div class="info-item">
                 <span class="label">农机名称</span>
-                <span class="value">{{ getMachineName(currentRecord.machineId) }}</span>
+                <span class="value">{{ currentRecord.machineName }}</span>
               </div>
               <div class="info-item">
                 <span class="label">农机编号</span>
-                <span class="value">{{ currentRecord.machineId }}</span>
+                <span class="value">{{ currentRecord.machineCode }}</span>
               </div>
               <div class="info-item">
                 <span class="label">农机类型</span>
-                <span class="value">{{ getMachineType(currentRecord.machineId) }}</span>
+                <span class="value status">
+                  <dict-tag :options="dict.type.agricultural_machine_type" :value="currentRecord.machineType" />
+                </span>
+              </div>
+              <div class="info-item">
+                <span class="label">所属农场</span>
+                <span class="value">{{ currentRecord.deptName }}</span>
               </div>
-                             <div class="info-item">
-                 <span class="label">所属农场</span>
-                 <span class="value">{{ getFarmName(currentRecord.machineId) }}</span>
-               </div>
             </div>
           </div>
         </div>
-        
+
         <!-- 处理状态 -->
         <div class="section">
           <div class="section-title">处理状态</div>
@@ -270,19 +251,23 @@
             <div class="status-item">
               <span class="label">当前状态</span>
               <span class="value status">
-                <span :class="['custom-tag', 'status-tag', getProcessStatusClass(currentRecord.handledStatus)]">
+                <!-- <span :class="['custom-tag', 'status-tag', getProcessStatusClass(currentRecord.handledStatus)]">
                   {{ getProcessStatusText(currentRecord.handledStatus) }}
-                </span>
+                </span> -->
+                <dict-tag :options="dict.type.machine_handled_status" :value="currentRecord.handledStatus" />
               </span>
             </div>
             <div class="status-item">
               <span class="label">处理人</span>
               <span class="value">{{ currentRecord.handlerName || '-' }}</span>
             </div>
-                         <div class="status-item">
-               <span class="label">处理时间</span>
-               <span class="value">{{ currentRecord.handleTime ? parseTime(currentRecord.handleTime, '{y}-{m}-{d} {h}:{i}:{s}') : '-' }}</span>
-             </div>
+            <div class="status-item">
+              <span class="label">处理时间</span>
+              <span class="value">{{
+                currentRecord.handleTime
+
+                }}</span>
+            </div>
             <div class="status-item full-width">
               <span class="label">处理记录</span>
               <div class="process-record">
@@ -291,13 +276,14 @@
             </div>
           </div>
         </div>
-        
+
         <!-- 附件信息 -->
         <div class="section">
           <div class="section-title">附件信息</div>
           <div class="attachment-info">
             <div v-if="currentRecord.attachments && currentRecord.attachments.length > 0" class="attachment-list">
-              <div v-for="(attachment, index) in getAttachmentList(currentRecord.attachments)" :key="index" class="attachment-item">
+              <div v-for="(attachment, index) in getAttachmentList(currentRecord.attachments)" :key="index"
+                class="attachment-item">
                 <div class="attachment-preview">
                   <i v-if="isImage(attachment.name)" class="el-icon-picture-outline"></i>
                   <i v-else class="el-icon-document"></i>
@@ -308,7 +294,8 @@
                 </div>
                 <div class="attachment-actions">
                   <el-button size="mini" type="text" @click="downloadAttachment(attachment)">下载</el-button>
-                  <el-button v-if="isImage(attachment.name)" size="mini" type="text" @click="previewImage(attachment)">预览</el-button>
+                  <el-button v-if="isImage(attachment.name)" size="mini" type="text"
+                    @click="previewImage(attachment)">预览</el-button>
                 </div>
               </div>
             </div>
@@ -319,7 +306,7 @@
           </div>
         </div>
       </div>
-      
+
       <div slot="footer" class="dialog-footer">
         <el-button @click="detailOpen = false">关闭</el-button>
       </div>
@@ -329,19 +316,19 @@
     <el-dialog title="处理告警" :visible.sync="processOpen" width="500px" append-to-body>
       <el-form ref="processForm" :model="processForm" :rules="processRules" label-width="80px">
         <el-form-item label="告警信息">
-                     <div class="process-alert-info">
-             <div class="info-item-row">
-               <span class="label">农机编号:</span>
-               <span class="value">{{ processForm.machineId }}</span>
-             </div>
-             <div class="info-item-row">
-               <span class="label">农机名称:</span>
-               <span class="value">{{ getMachineName(processForm.machineId) }}</span>
-             </div>
-             <div class="alert-content-preview">
-               {{ getAlertContent(processForm) }}
-             </div>
-           </div>
+          <div class="process-alert-info">
+            <div class="info-item-row">
+              <span class="label">农机编号:</span>
+              <span class="value">{{ processForm.machineCode }}</span>
+            </div>
+            <div class="info-item-row">
+              <span class="label">农机名称:</span>
+              <span class="value">{{ processForm.machineName }}</span>
+            </div>
+            <div class="alert-content-preview">
+              {{ getAlertContent(processForm) }}
+            </div>
+          </div>
         </el-form-item>
         <el-form-item label="处理结果" prop="handledStatus">
           <el-select v-model="processForm.handledStatus" placeholder="请选择处理结果">
@@ -350,21 +337,16 @@
             <el-option label="处理中" :value="2"></el-option>
             <el-option label="忽略" :value="3"></el-option>
           </el-select>
+
         </el-form-item>
-                 <el-form-item label="处理备注" prop="handleDesc">
-           <el-input 
-             v-model="processForm.handleDesc" 
-             type="textarea" 
-             :rows="4"
-             placeholder="请输入处理备注..."
-             maxlength="500"
-             show-word-limit
-           />
-         </el-form-item>
-         <el-form-item label="附件上传">
-           <file-upload v-model="processForm.attachments" :limit="5" />
-         </el-form-item>
-       </el-form>
+        <el-form-item label="处理备注" prop="handleDesc">
+          <el-input v-model="processForm.handleDesc" type="textarea" :rows="4" placeholder="请输入处理备注..." maxlength="500"
+            show-word-limit />
+        </el-form-item>
+        <el-form-item label="附件上传">
+          <file-upload v-model="processForm.attachments" :limit="5" />
+        </el-form-item>
+      </el-form>
       <div slot="footer" class="dialog-footer">
         <el-button type="primary" @click="submitProcess" :loading="processLoading">确 定</el-button>
         <el-button @click="cancelProcess">取 消</el-button>
@@ -379,32 +361,21 @@
         </el-form-item>
         <el-form-item label="报警类型" prop="alarmType">
           <el-select v-model="form.alarmType" placeholder="请选择报警类型">
-            <el-option
-              v-for="dict in dict.type.machine_alarm_type"
-              :key="dict.value"
-              :label="dict.label"
-              :value="dict.value"
-            ></el-option>
+            <el-option v-for="dict in dict.type.machine_alarm_type" :key="dict.value" :label="dict.label"
+              :value="dict.value"></el-option>
           </el-select>
         </el-form-item>
         <el-form-item label="报警级别" prop="alarmLevel">
           <el-select v-model="form.alarmLevel" placeholder="请选择报警级别">
-            <el-option
-              v-for="dict in dict.type.machine_alarm_level"
-              :key="dict.value"
-              :label="dict.label"
-              :value="dict.value"
-            ></el-option>
+            <el-option v-for="dict in dict.type.machine_alarm_level" :key="dict.value" :label="dict.label"
+              :value="dict.value"></el-option>
           </el-select>
         </el-form-item>
         <el-form-item label="报警描述" prop="alarmDesc">
           <el-input v-model="form.alarmDesc" type="textarea" placeholder="请输入内容" />
         </el-form-item>
         <el-form-item label="报警时间" prop="alarmTime">
-          <el-date-picker clearable
-            v-model="form.alarmTime"
-            type="date"
-            value-format="yyyy-MM-dd"
+          <el-date-picker clearable v-model="form.alarmTime" type="date" value-format="yyyy-MM-dd"
             placeholder="请选择报警时间">
           </el-date-picker>
         </el-form-item>
@@ -413,11 +384,9 @@
         </el-form-item>
         <el-form-item label="处理状态" prop="handledStatus">
           <el-radio-group v-model="form.handledStatus">
-            <el-radio
-              v-for="dict in dict.type.machine_handled_status"
-              :key="dict.value"
-              :label="parseInt(dict.value)"
-            >{{dict.label}}</el-radio>
+            <el-radio v-for="dict in dict.type.machine_handled_status" :key="dict.value"
+              :label="parseInt(dict.value)">{{
+                dict.label }}</el-radio>
           </el-radio-group>
         </el-form-item>
         <el-form-item label="处理人ID" prop="handlerId">
@@ -427,10 +396,7 @@
           <el-input v-model="form.handlerName" placeholder="请输入处理人姓名" />
         </el-form-item>
         <el-form-item label="处理时间" prop="handleTime">
-          <el-date-picker clearable
-            v-model="form.handleTime"
-            type="date"
-            value-format="yyyy-MM-dd"
+          <el-date-picker clearable v-model="form.handleTime" type="date" value-format="yyyy-MM-dd"
             placeholder="请选择处理时间">
           </el-date-picker>
         </el-form-item>
@@ -438,10 +404,7 @@
           <el-input v-model="form.handleDesc" type="textarea" placeholder="请输入内容" />
         </el-form-item>
         <el-form-item label="解决时间" prop="resolvedTime">
-          <el-date-picker clearable
-            v-model="form.resolvedTime"
-            type="date"
-            value-format="yyyy-MM-dd"
+          <el-date-picker clearable v-model="form.resolvedTime" type="date" value-format="yyyy-MM-dd"
             placeholder="请选择解决时间">
           </el-date-picker>
         </el-form-item>
@@ -459,10 +422,13 @@
 
 <script>
 import { listMachineAlarmRecords, getMachineAlarmRecords, delMachineAlarmRecords, addMachineAlarmRecords, updateMachineAlarmRecords } from "@/api/base/machineAlarmRecords"
-
+import { deptTreeSelect } from "@/api/system/user";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
 export default {
   name: "MachineAlarmRecords",
-  dicts: ['machine_alarm_level', 'machine_alarm_type', 'machine_handled_status', 'machine_type', 'farm_list'],
+  components: { Treeselect },
+  dicts: ['machine_alarm_level', 'machine_alarm_type', 'machine_handled_status', 'agricultural_machine_type'],
   data() {
     return {
       // 遮罩层
@@ -496,6 +462,9 @@ export default {
         handledStatus: [{ required: true, message: '请选择处理结果', trigger: 'change' }],
         handleDesc: [{ required: true, message: '请输入处理备注', trigger: 'blur' }],
       },
+
+      // 部门树选项
+      deptOptions: undefined,
       // 处理按钮加载中
       processLoading: false,
       // 告警时间范围
@@ -504,13 +473,14 @@ export default {
       queryParams: {
         pageNum: 1,
         pageSize: 10,
-        machineId: null,
+        machineCode: null,
         machineName: null,
         alarmLevel: null,
         machineType: null,
+        handledStatus: null,
         farmId: null,
         alarmTime: null,
-        handledStatus: null,
+        deptIdList: [],
       },
       // 表单参数
       form: {},
@@ -550,9 +520,19 @@ export default {
   },
   created() {
     this.getList()
-    this.getStatistics()
+    this.getDeptTree();
+    //this.getStatistics()
   },
   methods: {
+
+    /** 查询部门下拉树结构 */
+    getDeptTree() {
+      deptTreeSelect().then(response => {
+        this.deptOptions = response.data;
+      });
+    },
+
+
     /** 查询农机故障告警记录列表 */
     getList() {
       this.loading = true
@@ -597,43 +577,53 @@ export default {
       if (!this.machineAlarmRecordsList || this.machineAlarmRecordsList.length === 0) {
         return
       }
-      
+
       // 重置统计数据
       this.levelStatistics = {
         emergency: { total: 0, unprocessed: 0 },
         warning: { total: 0, unprocessed: 0 },
         info: { total: 0, unprocessed: 0 }
       }
-      
+
       // 今日日期
-      const today = new Date().toISOString().slice(0, 10)
-      let todayCount = 0
-      
+      const toDateStr = (dateLike) =>
+        new Date(dateLike).toISOString().slice(0, 10);
+
+      const today = toDateStr(new Date());
+      const yesterday = toDateStr(Date.now() - 86400000);
+
+      let todayCount = 0;
+      let yesterdayCount = 0;
+
       // 遍历记录统计
       this.machineAlarmRecordsList.forEach(record => {
         // 统计今日告警
-        if (record.alarmTime && record.alarmTime.includes(today)) {
-          todayCount++
-        }
-        
+        if (!record.alarmTime) return;          // 空值跳过
+        const alertDay = toDateStr(record.alarmTime);
+
+        if (alertDay === today) todayCount++;
+        if (alertDay === yesterday) yesterdayCount++;
+
         // 统计各等级告警
         const level = record.alarmLevel
         const isUnprocessed = record.handledStatus == 0 || record.handledStatus == '0' || record.handledStatus == 2 || record.handledStatus == '2'
-        
+
         // 根据告警等级统计 (1-紧急, 2-告警, 3-提示)
-        if (level == 1 || level == '1') {
-          this.levelStatistics.emergency.total++
-          if (isUnprocessed) this.levelStatistics.emergency.unprocessed++
-        } else if (level == 2 || level == '2') {
-          this.levelStatistics.warning.total++
-          if (isUnprocessed) this.levelStatistics.warning.unprocessed++
-        } else if (level == 3 || level == '3') {
+        // 根据告警等级统计 (1-提示, 2-告警, 3-紧急)
+        if (level == 1 || level === '1') {
           this.levelStatistics.info.total++
           if (isUnprocessed) this.levelStatistics.info.unprocessed++
+        } else if (level == 2 || level === '2') {
+          this.levelStatistics.warning.total++
+          if (isUnprocessed) this.levelStatistics.warning.unprocessed++
+        } else if (level == 3 || level === '3') {
+          this.levelStatistics.emergency.total++
+          if (isUnprocessed) this.levelStatistics.emergency.unprocessed++
         }
       })
-      
+
       // 更新今日统计 (这里只是示例,实际应该从后端获取完整统计)
+      this.todayStatistics.change = todayCount - yesterdayCount;
       if (todayCount > 0) {
         this.todayStatistics.total = todayCount
       }
@@ -648,6 +638,8 @@ export default {
       this.form = {
         id: null,
         machineId: null,
+        machineCode: null,
+        machineName: null,
         alarmType: null,
         alarmLevel: null,
         alarmDesc: null,
@@ -681,7 +673,7 @@ export default {
     // 多选框选中数据
     handleSelectionChange(selection) {
       this.ids = selection.map(item => item.id)
-      this.single = selection.length!==1
+      this.single = selection.length !== 1
       this.multiple = !selection.length
     },
     /** 新增按钮操作 */
@@ -723,12 +715,12 @@ export default {
     /** 删除按钮操作 */
     handleDelete(row) {
       const ids = row.id || this.ids
-      this.$modal.confirm('是否确认删除农机故障告警记录编号为"' + ids + '"的数据项?').then(function() {
+      this.$modal.confirm('是否确认删除农机故障告警记录编号为"' + ids + '"的数据项?').then(function () {
         return delMachineAlarmRecords(ids)
       }).then(() => {
         this.getList()
         this.$modal.msgSuccess("删除成功")
-      }).catch(() => {})
+      }).catch(() => { })
     },
     /** 导出按钮操作 */
     handleExport() {
@@ -801,7 +793,7 @@ export default {
     getAlertLevelClass(level) {
       const levelMap = {
         '1': 'emergency',
-        '2': 'warning', 
+        '2': 'warning',
         '3': 'info',
         1: 'emergency',
         2: 'warning',
@@ -816,7 +808,7 @@ export default {
         '2': '告警',
         '3': '提示',
         1: '紧急',
-        2: '告警', 
+        2: '告警',
         3: '提示'
       }
       return levelMap[level] || '未知'
@@ -828,7 +820,7 @@ export default {
       //   this.currentRecord = response.data
       //   this.detailOpen = true
       // })
-      
+
       // 当前直接使用列表数据显示
       this.currentRecord = { ...record }
       this.detailOpen = true
@@ -838,9 +830,9 @@ export default {
       if (!record.alarmDesc) {
         return '暂无告警内容'
       }
-      
+
       let content = record.alarmDesc
-      
+
       // 尝试去掉设备名称前缀
       // 匹配模式:设备XXX + 告警内容
       const devicePatterns = [
@@ -852,7 +844,7 @@ export default {
         /^.+?号(.+)$/,
         /^.+?站(.+)$/
       ]
-      
+
       // 如果告警内容包含设备信息,尝试去掉设备前缀
       if (record.machineId && content.includes(record.machineId)) {
         // 去掉设备编号前缀
@@ -867,29 +859,19 @@ export default {
           }
         }
       }
-      
+
       // 清理开头的标点符号
       content = content.replace(/^[::,,\s]+/, '')
-      
+
       return content || record.alarmDesc
     },
     /** 处理告警 */
     handleProcess(record) {
       this.resetProcessForm()
-      this.currentRecord = { ...record }
-             this.processForm = {
-         id: record.id,
-         machineId: record.machineId,
-         alarmType: record.alarmType,
-         alarmLevel: record.alarmLevel,
-         alarmDesc: record.alarmDesc,
-         alarmTime: record.alarmTime,
-         locationInfo: record.locationInfo,
-         handledStatus: 0, // 默认设为未处理,用户可以修改
-         handleDesc: '',
-         handlerName: '',
-         attachments: ''
-       }
+      // this.currentRecord = { ...record }
+      this.processForm = {
+        ...record
+      }
       this.processOpen = true
     },
     /** 提交处理 */
@@ -897,16 +879,15 @@ export default {
       this.$refs.processForm.validate((valid) => {
         if (valid) {
           this.processLoading = true
-          
-                     // 准备要更新的数据
-           const updateData = {
-             id: this.processForm.id,
-             handledStatus: this.processForm.handledStatus,
-             handleDesc: this.processForm.handleDesc,
-             handlerName: this.processForm.handlerName || '当前用户',
-             attachments: this.processForm.attachments
-           }
-          
+
+          // 准备要更新的数据
+          const updateData = {
+            id: this.processForm.id,
+            handledStatus: this.processForm.handledStatus,
+            handleDesc: this.processForm.handleDesc,
+            attachments: this.processForm.attachments
+          }
+
           updateMachineAlarmRecords(updateData).then(response => {
             this.$modal.msgSuccess("处理成功")
             this.processOpen = false
@@ -927,19 +908,19 @@ export default {
     },
     /** 重置处理表单 */
     resetProcessForm() {
-             this.processForm = {
-         id: null,
-         machineId: null,
-         alarmType: null,
-         alarmLevel: null,
-         alarmDesc: null,
-         alarmTime: null,
-         locationInfo: null,
-         handledStatus: 0,
-         handleDesc: null,
-         handlerName: null,
-         attachments: null
-       }
+      this.processForm = {
+        id: null,
+        machineId: null,
+        alarmType: null,
+        alarmLevel: null,
+        alarmDesc: null,
+        alarmTime: null,
+        locationInfo: null,
+        handledStatus: 0,
+        handleDesc: null,
+        handlerName: null,
+        attachments: null
+      }
       if (this.$refs.processForm) {
         this.$refs.processForm.resetFields()
       }
@@ -1066,7 +1047,7 @@ export default {
   padding: 20px;
   background: #fff;
   border-radius: 12px;
-  box-shadow: 0 1px 3px rgba(0,0,0,0.08);
+  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
 }
 
 /* 统一各部分间距 */
@@ -1091,7 +1072,7 @@ export default {
   justify-content: space-between;
   transition: all 0.3s ease;
   cursor: pointer;
-  box-shadow: 0 4px 15px rgba(0,0,0,0.1), 0 2px 6px rgba(0,0,0,0.05);
+  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1), 0 2px 6px rgba(0, 0, 0, 0.05);
   position: relative;
   overflow: hidden;
   color: #fff;
@@ -1099,7 +1080,7 @@ export default {
 
 .stat-card:hover {
   transform: translateY(-3px);
-  box-shadow: 0 8px 25px rgba(0,0,0,0.15), 0 4px 10px rgba(0,0,0,0.1);
+  box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15), 0 4px 10px rgba(0, 0, 0, 0.1);
 }
 
 .stat-card.total {
@@ -1184,7 +1165,7 @@ export default {
   padding: 20px;
   margin-bottom: 20px;
   border: 1px solid #e9ecef;
-  box-shadow: 0 2px 4px rgba(0,0,0,0.05);
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
   border-left: 4px solid #f56c6c;
 }
 

+ 219 - 280
src/views/base/machineWorkRecords/index.vue

@@ -2,98 +2,58 @@
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="80px">
       <el-form-item label="农机编号" prop="machineCode">
-        <el-input
-          v-model="queryParams.machineCode"
-          placeholder="请输入农机编号"
-          clearable
-          @keyup.enter.native="handleQuery"
-        />
+        <el-input v-model="queryParams.machineCode" placeholder="请输入农机编号" clearable @keyup.enter.native="handleQuery" />
       </el-form-item>
       <el-form-item label="农机名称" prop="machineName">
-        <el-input
-          v-model="queryParams.machineName"
-          placeholder="请输入农机名称"
-          clearable
-          @keyup.enter.native="handleQuery"
-        />
+        <el-input v-model="queryParams.machineName" placeholder="请输入农机名称" clearable @keyup.enter.native="handleQuery" />
       </el-form-item>
-      <el-form-item label="所属农场" prop="farmName">
-        <el-select v-model="queryParams.farmName" placeholder="请选择所属农场" clearable>
-          <el-option
-            v-for="farm in farmOptions"
-            :key="farm.value"
-            :label="farm.label"
-            :value="farm.value"
-          />
-        </el-select>
+
+      <el-form-item label="所属农场" prop="deptIdList">
+        <treeselect v-model="queryParams.deptIdList" :options="deptOptions" multiple :flat="true" :limit="1"
+          :limitText="count => `+${count}`" style="width:200px" :show-count="true" placeholder="请选所属机构" />
       </el-form-item>
-      <el-form-item label="作业地块" prop="fieldName">
-        <el-select v-model="queryParams.fieldName" placeholder="请选择作业地块" clearable>
-          <el-option
-            v-for="field in fieldOptions"
-            :key="field.value"
-            :label="field.label"
-            :value="field.value"
-          />
+
+
+      <el-form-item label="作业地块" prop="fieldIdList">
+        <el-select v-model="queryParams.fieldIdList" placeholder="请选择地块" multiple collapse-tags filterable clearable>
+          <el-option v-for="dict in fieldIdList" :key="dict.value" :label="dict.label" :value="dict.value" />
         </el-select>
       </el-form-item>
+
       <el-form-item label="作业名称" prop="taskName">
-        <el-input
-          v-model="queryParams.taskName"
-          placeholder="请输入作业名称"
-          clearable
-          @keyup.enter.native="handleQuery"
-        />
+        <el-input v-model="queryParams.taskName" placeholder="请输入作业名称" clearable @keyup.enter.native="handleQuery" />
       </el-form-item>
+
+
+
       <el-form-item label="作业类型" prop="taskType">
         <el-select v-model="queryParams.taskType" placeholder="请选择作业类型" clearable>
-          <el-option
-            v-for="dict in taskTypeOptions"
-            :key="dict.value"
-            :label="dict.label"
-            :value="dict.value"
-          />
+          <el-option v-for="dict in dict.type.machine_work_task_type" :key="dict.value" :label="dict.label"
+            :value="dict.value" />
         </el-select>
       </el-form-item>
+
+
       <el-form-item label="作业状态" prop="status">
         <el-select v-model="queryParams.status" placeholder="请选择作业状态" clearable>
-          <el-option
-            v-for="dict in statusOptions"
-            :key="dict.value"
-            :label="dict.label"
-            :value="dict.value"
-          />
+          <el-option v-for="dict in dict.type.machine_work_status" :key="dict.value" :label="dict.label"
+            :value="dict.value" />
         </el-select>
       </el-form-item>
+
+
       <el-form-item label="开始时间" prop="startTime">
-        <el-date-picker
-          v-model="daterangeStartTime"
-          style="width: 240px"
-          value-format="yyyy-MM-dd"
-          type="daterange"
-          range-separator="至"
-          start-placeholder="开始日期"
-          end-placeholder="结束日期">
+        <el-date-picker v-model="daterangeStartTime" style="width: 240px" value-format="yyyy-MM-dd" type="daterange"
+          range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期">
         </el-date-picker>
       </el-form-item>
       <el-form-item label="结束时间" prop="endTime">
-        <el-date-picker
-          v-model="daterangeEndTime"
-          style="width: 240px"
-          value-format="yyyy-MM-dd"
-          type="daterange"
-          range-separator="至"
-          start-placeholder="开始日期"
-          end-placeholder="结束日期">
+        <el-date-picker v-model="daterangeEndTime" style="width: 240px" value-format="yyyy-MM-dd" type="daterange"
+          range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期">
         </el-date-picker>
       </el-form-item>
-      <el-form-item label="操作员" prop="operatorName">
-        <el-input
-          v-model="queryParams.operatorName"
-          placeholder="请输入操作员"
-          clearable
-          @keyup.enter.native="handleQuery"
-        />
+      <el-form-item label="操作员" prop="userName">
+        <el-input v-model="queryParams.userName" placeholder="请输入操作员" clearable @keyup.enter.native="handleQuery" />
       </el-form-item>
       <el-form-item>
         <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
@@ -103,81 +63,55 @@
 
     <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="['base:machineWorkRecords:add']"
-        >新增</el-button>
+        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
+          v-hasPermi="['base:machineWorkRecords: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="['base:machineWorkRecords:edit']"
-        >修改</el-button>
+        <el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate"
+          v-hasPermi="['base:machineWorkRecords: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="['base:machineWorkRecords:remove']"
-        >删除</el-button>
+        <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete"
+          v-hasPermi="['base:machineWorkRecords: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="['base:machineWorkRecords:export']"
-        >导出</el-button>
+        <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport"
+          v-hasPermi="['base:machineWorkRecords:export']">导出</el-button>
       </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
 
     <el-table v-loading="loading" :data="machineWorkRecordsList" @selection-change="handleSelectionChange">
       <el-table-column type="selection" width="55" align="center" :fixed="false" />
-      <el-table-column label="作业单号" align="center" prop="workOrderId" width="200">
+      <el-table-column label="作业单号" align="center" prop="id" width="200">
         <template slot-scope="scope">
-          <span>{{ scope.row.workOrderId || '—' }}</span>
+          <span>{{ scope.row.id || '—' }}</span>
         </template>
       </el-table-column>
       <el-table-column label="农机编号" align="center" prop="machineCode" />
       <el-table-column label="农机名称" align="center" prop="machineName" />
       <el-table-column label="农机类型" align="center" prop="machineType">
         <template slot-scope="scope">
-          <span>{{ getMachineTypeLabel(scope.row.machineType) }}</span>
+          <dict-tag :options="dict.type.agricultural_machine_type" :value="scope.row.machineType" />
         </template>
       </el-table-column>
-      <el-table-column label="所属农场" align="center" prop="farmName" />
+
+      <el-table-column label="所属农场" align="center" prop="deptName" />
       <el-table-column label="作业地块" align="center" prop="fieldName" />
       <el-table-column label="作业名称" align="center" prop="taskName" />
       <el-table-column label="作业类型" align="center" prop="taskType">
         <template slot-scope="scope">
-          <span>{{ getTaskTypeLabel(scope.row.taskType) }}</span>
+          <dict-tag :options="dict.type.machine_work_task_type" :value="scope.row.taskType" />
         </template>
       </el-table-column>
-      <el-table-column label="作业状态" align="center" prop="status" :show-overflow-tooltip="false" width="100">
+
+
+      <el-table-column label="作业状态" align="center" prop="status">
         <template slot-scope="scope">
-          <div style="overflow: visible !important; text-overflow: clip !important; white-space: nowrap !important;">
-            <span 
-              :class="['work-status-tag', getStatusClass(scope.row.status)]"
-            >{{ getStatusLabel(scope.row.status) }}</span>
-          </div>
+          <dict-tag :options="dict.type.machine_work_status" :value="scope.row.status" />
         </template>
       </el-table-column>
+
       <el-table-column label="开始时间" align="center" prop="startTime" width="180">
         <template slot-scope="scope">
           <span>{{ parseTime(scope.row.startTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
@@ -188,44 +122,30 @@
           <span>{{ parseTime(scope.row.endTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
         </template>
       </el-table-column>
-      <el-table-column label="作业时长(小时)" align="center" prop="workDuration" />
+      <el-table-column label="作业时长(小时)" align="center" prop="workHours" />
       <el-table-column label="作业面积(亩)" align="center" prop="workArea" />
       <el-table-column label="油耗(升)" align="center" prop="fuelConsumption" />
-      <el-table-column label="操作员" align="center" prop="operatorName" />
+      <el-table-column label="操作员" align="center" prop="userName" />
       <el-table-column label="备注" align="center" prop="remark">
         <template slot-scope="scope">
-          <el-tooltip class="item" effect="dark" :content="scope.row.remark" placement="top" :disabled="!scope.row.remark">
+          <el-tooltip class="item" effect="dark" :content="scope.row.remark" placement="top"
+            :disabled="!scope.row.remark">
             <span class="remark-text">{{ scope.row.remark }}</span>
           </el-tooltip>
         </template>
       </el-table-column>
       <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="handleUpdate(scope.row)"
-            v-hasPermi="['base:machineWorkRecords:edit']"
-          >修改</el-button>
-          <el-button
-            size="mini"
-            type="text"
-            icon="el-icon-delete"
-            @click="handleDelete(scope.row)"
-            v-hasPermi="['base:machineWorkRecords:remove']"
-          >删除</el-button>
+          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
+            v-hasPermi="['base:machineWorkRecords:edit']">修改</el-button>
+          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
+            v-hasPermi="['base:machineWorkRecords:remove']">删除</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="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
+      @pagination="getList" />
 
     <!-- 添加或修改农机作业记录对话框 -->
     <el-dialog :title="title" :visible.sync="open" width="800px" append-to-body>
@@ -238,96 +158,78 @@
             </el-form-item>
           </el-col>
         </el-row>
-        
+
         <!-- 第一步:选择所属农场(必填) -->
         <el-row :gutter="20">
           <el-col :span="24">
-            <el-form-item label="所属农场" prop="farmName">
-              <el-select 
-                v-model="form.farmName" 
-                placeholder="请先选择所属农场" 
-                style="width: 100%" 
-                @change="handleFarmChange">
-                <el-option
-                  v-for="farm in farmOptions"
-                  :key="farm.value"
-                  :label="farm.label"
-                  :value="farm.value"
-                />
+            <!-- <el-form-item label="所属农场" prop="farmName">
+              <el-select v-model="form.farmName" placeholder="请先选择所属农场" style="width: 100%" @change="handleFarmChange">
+                <el-option v-for="farm in farmOptions" :key="farm.value" :label="farm.label" :value="farm.value" />
               </el-select>
+            </el-form-item> -->
+            <el-form-item label="所属农场" prop="farmId">
+              <treeselect v-model="form.farmId" :options="enabledDeptOptions" :show-count="true"
+                @input="queryMachineNameFieldUser(form.farmId)" placeholder="请先选择所属农场" />
             </el-form-item>
           </el-col>
         </el-row>
-        
+
         <!-- 第二步:根据农场过滤的字段 -->
         <el-row :gutter="20">
           <el-col :span="12">
-            <el-form-item label="农机名称" prop="machineName">
-              <el-select 
-                v-model="form.machineName" 
-                placeholder="请选择农机" 
-                style="width: 100%" 
-                @change="handleMachineNameChange"
-                :disabled="!form.farmName">
-                <el-option
-                  v-for="machine in filteredMachineOptions"
-                  :key="machine.value"
-                  :label="machine.label"
-                  :value="machine.value"
-                />
+            <el-form-item label="农机名称" prop="machineId">
+              <!-- <el-select v-model="form.machineName" placeholder="请选择农机" style="width: 100%"
+                @change="handleMachineNameChange" :disabled="!form.farmName">
+                <el-option v-for="machine in filteredMachineOptions" :key="machine.value" :label="machine.label"
+                  :value="machine.value" />
+              </el-select> -->
+
+              <el-select v-model="form.machineId" placeholder="请选择农机" :disabled="!form.farmId">
+                <el-option v-for="item in machinesList" :key="item.id" :label="item.machineName" :value="item.id">
+                </el-option>
               </el-select>
             </el-form-item>
           </el-col>
           <el-col :span="12">
-            <el-form-item label="作业地块" prop="fieldName">
-              <el-select 
-                v-model="form.fieldName" 
-                placeholder="请选择作业地块" 
-                style="width: 100%"
-                :disabled="!form.farmName">
-                <el-option
-                  v-for="field in filteredFieldOptions"
-                  :key="field.value"
-                  :label="field.label"
-                  :value="field.value"
-                />
+            <el-form-item label="作业地块" prop="fieldId">
+              <!-- <el-select v-model="form.fieldName" placeholder="请选择作业地块" style="width: 100%" :disabled="!form.farmName">
+                <el-option v-for="field in filteredFieldOptions" :key="field.value" :label="field.label"
+                  :value="field.value" />
+              </el-select> -->
+
+              <el-select v-model="form.fieldId" placeholder="请选择作业地块" :disabled="!form.farmId">
+                <el-option v-for="item in fields" :key="item.id" :label="item.fieldName" :value="item.id">
+                </el-option>
               </el-select>
             </el-form-item>
           </el-col>
         </el-row>
-        
+
         <el-row :gutter="20">
           <el-col :span="12">
-            <el-form-item label="操作员" prop="operatorName">
-              <el-select 
-                v-model="form.operatorName" 
-                placeholder="请选择操作员" 
-                filterable 
-                style="width: 100%"
+            <el-form-item label="操作员" prop="operatorId">
+              <!-- <el-select v-model="form.operatorName" placeholder="请选择操作员" filterable style="width: 100%"
                 :disabled="!form.farmName">
-                <el-option
-                  v-for="operator in filteredOperatorOptions"
-                  :key="operator.value"
-                  :label="operator.label"
-                  :value="operator.value"
-                />
+                <el-option v-for="operator in filteredOperatorOptions" :key="operator.value" :label="operator.label"
+                  :value="operator.value" />
+              </el-select> -->
+
+              <el-select v-model="form.operatorId" placeholder="请选择操作员" :disabled="!form.farmId">
+                <el-option v-for="item in userName" :key="item.userId" :label="item.nickName" :value="item.userId">
+                </el-option>
               </el-select>
             </el-form-item>
           </el-col>
           <el-col :span="12">
             <el-form-item label="作业类型" prop="taskType">
               <el-select v-model="form.taskType" placeholder="请选择作业类型" style="width: 100%">
-                <el-option
-                  v-for="dict in taskTypeOptions"
-                  :key="dict.value"
-                  :label="dict.label"
-                  :value="dict.value"
-                ></el-option>
+                <el-option v-for="dict in dict.type.machine_work_task_type" :key="dict.value" :label="dict.label"
+                  :value="dict.value"></el-option>
               </el-select>
             </el-form-item>
           </el-col>
         </el-row>
-        
+
         <el-row :gutter="20">
           <el-col :span="12">
             <el-form-item label="作业名称" prop="taskName">
@@ -337,42 +239,30 @@
           <el-col :span="12">
             <el-form-item label="作业状态" prop="status">
               <el-select v-model="form.status" placeholder="请选择作业状态" style="width: 100%">
-                <el-option
-                  v-for="dict in statusOptions"
-                  :key="dict.value"
-                  :label="dict.label"
-                  :value="dict.value"
-                ></el-option>
+                <el-option v-for="dict in dict.type.machine_work_status" :key="dict.value" :label="dict.label"
+                  :value="dict.value"></el-option>
               </el-select>
             </el-form-item>
           </el-col>
         </el-row>
-        
+
         <el-row :gutter="20">
           <el-col :span="12">
             <el-form-item label="开始时间" prop="startTime">
-              <el-date-picker clearable
-                v-model="form.startTime"
-                type="datetime"
-                value-format="yyyy-MM-dd HH:mm:ss"
-                placeholder="请选择开始时间"
-                style="width: 100%">
+              <el-date-picker clearable v-model="form.startTime" type="datetime" value-format="yyyy-MM-dd HH:mm:ss"
+                placeholder="请选择开始时间" style="width: 100%">
               </el-date-picker>
             </el-form-item>
           </el-col>
           <el-col :span="12">
             <el-form-item label="结束时间" prop="endTime">
-              <el-date-picker clearable
-                v-model="form.endTime"
-                type="datetime"
-                value-format="yyyy-MM-dd HH:mm:ss"
-                placeholder="请选择结束时间"
-                style="width: 100%">
+              <el-date-picker clearable v-model="form.endTime" type="datetime" value-format="yyyy-MM-dd HH:mm:ss"
+                placeholder="请选择结束时间" style="width: 100%">
               </el-date-picker>
             </el-form-item>
           </el-col>
         </el-row>
-        
+
         <el-row>
           <el-col :span="24">
             <el-form-item label="备注" prop="remark">
@@ -390,10 +280,16 @@
 </template>
 
 <script>
-import { listMachineWorkRecords, getMachineWorkRecords, delMachineWorkRecords, addMachineWorkRecords, updateMachineWorkRecords } from "@/api/base/machineWorkRecords"
-
+import { listMachineWorkRecords, getMachineWorkRecords, delMachineWorkRecords, addMachineWorkRecords, updateMachineWorkRecords, getMachineNameFieldUser } from "@/api/base/machineWorkRecords"
+import { deptTreeSelect } from "@/api/system/user";
+import { listFieldName } from "@/api/base/field";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
 export default {
   name: "MachineWorkRecords",
+  components: {
+    Treeselect
+  },
   dicts: ['machine_work_task_type', 'machine_work_status', 'agricultural_machine_type'],
   data() {
     return {
@@ -419,7 +315,19 @@ export default {
       daterangeStartTime: [],
       // 结束时间范围
       daterangeEndTime: [],
-      
+
+      // 部门树选项
+      deptOptions: undefined,
+      // 过滤掉已禁用部门树选项
+      enabledDeptOptions: undefined,
+      // 所属地块
+      fieldIdList: [],
+      machinesList: [],
+      fields: [],
+      userName: [],
+
+
+
       // 字典数据
       statusOptions: [
         { value: '0', label: '待开始' },
@@ -470,12 +378,15 @@ export default {
       form: {},
       // 表单校验
       rules: {
-        farmName: [
+        farmId: [
           { required: true, message: "所属农场不能为空", trigger: "change" }
         ],
-        machineName: [
+        machineId: [
           { required: true, message: "农机名称不能为空", trigger: "change" }
         ],
+        fieldId: [
+          { required: true, message: "作业地块不能为空", trigger: "change" }
+        ],
         taskName: [
           { required: true, message: "作业名称不能为空", trigger: "blur" }
         ],
@@ -488,7 +399,10 @@ export default {
         startTime: [
           { required: true, message: "开始时间不能为空", trigger: "change" }
         ],
-        operatorName: [
+        endTime: [
+          { required: true, message: "结束时间不能为空", trigger: "change" }
+        ],
+        operatorId: [
           { required: true, message: "操作员不能为空", trigger: "change" }
         ]
       }
@@ -496,6 +410,9 @@ export default {
   },
   created() {
     this.getList()
+    this.getDeptTree()
+    this.getFieldNameList()
+
     this.getMachineOptions()
     this.getFarmOptions()
     this.getFieldOptions()
@@ -503,6 +420,52 @@ export default {
 
   },
   methods: {
+
+    queryMachineNameFieldUser(farmId) {
+      if (farmId === undefined || farmId === null || farmId === '') {
+        this.fields = [];
+        this.machinesList = [];
+        this.userName = [];
+        return;
+      }
+      console.log(farmId)
+      getMachineNameFieldUser(farmId).then(response => {
+        this.fields = response.data.fields
+        this.machinesList = response.data.machinesList
+        this.userName = response.data.users
+      })
+
+    },
+
+    /** 查询地块名称 **/
+    getFieldNameList() {
+      listFieldName().then(res => {
+        this.fieldIdList = res;
+        this.fieldIdList.forEach(x => {
+          x.value = x.id;
+          x.label = x.fieldName;
+        })
+      });
+    },
+
+    getDeptTree() {
+      deptTreeSelect().then(response => {
+        this.deptOptions = response.data;
+        this.enabledDeptOptions = this.filterDisabledDept(JSON.parse(JSON.stringify(response.data)))
+      });
+    },
+    filterDisabledDept(deptList) {
+      return deptList.filter(dept => {
+        if (dept.disabled) {
+          return false
+        }
+        if (dept.children && dept.children.length) {
+          dept.children = this.filterDisabledDept(dept.children)
+        }
+        return true
+      })
+    },
+
     /** 获取农机选项 */
     getMachineOptions() {
       // 模拟数据,实际应该从API获取,包含农场关联
@@ -559,48 +522,27 @@ export default {
         this.queryParams.params["beginEndTime"] = this.daterangeEndTime[0]
         this.queryParams.params["endEndTime"] = this.daterangeEndTime[1]
       }
-      
-      // 直接使用示例数据,确保作业单号正确显示
-      this.addExampleData()
-      this.loading = false
-      
-      // 暂时注释掉API调用,因为返回的数据格式可能不符合预期
-      /*
+
+
+
       listMachineWorkRecords(this.queryParams).then(response => {
-        // 如果返回的数据中没有作业单号,则为每条记录生成一个
-        this.machineWorkRecordsList = response.rows.map(item => {
-          if (!item.id || item.id === 'null' || item.id === '') {
-            item.id = this.generateWorkOrderId()
-          }
-          return item
-        })
+        this.machineWorkRecordsList = response.rows
         this.total = response.total
         this.loading = false
-        
-        // 如果没有数据,添加一些示例数据用于展示
-        if (this.machineWorkRecordsList.length === 0 && this.queryParams.pageNum === 1) {
-          this.addExampleData()
-        }
-      }).catch(error => {
-        // 如果API调用失败,使用示例数据
-        console.warn('API调用失败,使用示例数据:', error)
-        this.addExampleData()
-        this.loading = false
       })
-      */
     },
-    
+
     /** 添加示例数据 */
     addExampleData() {
       const now = new Date()
       const yesterday = new Date(now)
       yesterday.setDate(yesterday.getDate() - 1)
-      
+
       // 生成固定的示例作业单号
       const exampleWorkOrderId1 = 'Z20250723154530001'
       const exampleWorkOrderId2 = 'Z20250723160015002'
       const exampleWorkOrderId3 = 'Z20250724080000003'
-      
+
       const exampleData = [
         {
           id: 1, // 数字类型主键
@@ -660,11 +602,11 @@ export default {
           remark: '计划明日开始播种作业'
         }
       ]
-      
+
       this.machineWorkRecordsList = exampleData
       this.total = exampleData.length
     },
-    
+
     /** 格式化日期时间 */
     formatDateTime(date, hour, minute) {
       const year = date.getFullYear()
@@ -672,28 +614,28 @@ export default {
       const day = String(date.getDate()).padStart(2, '0')
       const hours = String(hour || 0).padStart(2, '0')
       const minutes = String(minute || 0).padStart(2, '0')
-      
+
       return `${year}-${month}-${day} ${hours}:${minutes}:00`
     },
-    
+
     /** 生成作业单号 */
     generateWorkOrderId(customDate) {
       // 格式: ZYYYYMMDDHHMMSSNN
       const now = customDate || new Date()
-      
+
       // 获取年月日
       const year = now.getFullYear()
       const month = String(now.getMonth() + 1).padStart(2, '0')
       const day = String(now.getDate()).padStart(2, '0')
-      
+
       // 获取时分秒
       const hours = String(now.getHours()).padStart(2, '0')
       const minutes = String(now.getMinutes()).padStart(2, '0')
       const seconds = String(now.getSeconds()).padStart(2, '0')
-      
+
       // 生成3位随机序号,避免同一秒内重复
       const randomNum = String(Math.floor(Math.random() * 1000)).padStart(3, '0')
-      
+
       // 组合成最终的作业单号,确保格式为 ZYYYYMMDDHHMMSSNN
       return `Z${year}${month}${day}${hours}${minutes}${seconds}${randomNum}`
     },
@@ -745,7 +687,7 @@ export default {
     // 多选框选中数据
     handleSelectionChange(selection) {
       this.ids = selection.map(item => item.id)
-      this.single = selection.length!==1
+      this.single = selection.length !== 1
       this.multiple = !selection.length
     },
     /** 新增按钮操作 */
@@ -756,18 +698,18 @@ export default {
       this.open = true
       this.title = "添加农机作业记录"
     },
-    
+
     /** 修改按钮操作 */
     handleUpdate(row) {
       this.reset()
-      
+
       // 直接使用行数据进行回显(因为目前使用模拟数据)
       this.form = { ...row }
-      
+
       // 确保所有字段都正确回显
       this.form.workOrderId = row.workOrderId || row.id
       this.form.machineCode = row.machineCode
-      this.form.machineName = row.machineName  
+      this.form.machineName = row.machineName
       this.form.machineType = row.machineType
       this.form.farmName = row.farmName
       this.form.fieldName = row.fieldName
@@ -778,15 +720,15 @@ export default {
       this.form.endTime = row.endTime
       this.form.operatorName = row.operatorName
       this.form.remark = row.remark
-      
+
       // 编辑时根据农场初始化过滤选项(传递初始化标志,保持原有值)
       if (this.form.farmName) {
         this.handleFarmChange(this.form.farmName, true)
       }
-      
+
       this.open = true
       this.title = "修改农机作业记录"
-      
+
       // 如果将来需要使用API,可以使用以下代码
       /*
       const id = row.id || this.ids
@@ -816,7 +758,7 @@ export default {
           if (!this.form.workOrderId || this.form.workOrderId === 'null' || this.form.workOrderId === '') {
             this.form.workOrderId = this.generateWorkOrderId()
           }
-          
+
           if (this.title.indexOf("修改") !== -1) {
             updateMachineWorkRecords(this.form).then(response => {
               this.$modal.msgSuccess("修改成功")
@@ -837,18 +779,18 @@ export default {
         }
       })
     },
-    
+
 
     /** 删除按钮操作 */
     handleDelete(row) {
       const ids = row.id || this.ids
       const workOrderId = row.workOrderId || '未知'
-      this.$modal.confirm('是否确认删除作业单号为"' + workOrderId + '"的数据项?').then(function() {
+      this.$modal.confirm('是否确认删除作业单号为"' + workOrderId + '"的数据项?').then(function () {
         return delMachineWorkRecords(ids)
       }).then(() => {
         this.getList()
         this.$modal.msgSuccess("删除成功")
-      }).catch(() => {})
+      }).catch(() => { })
     },
     /** 导出按钮操作 */
     handleExport() {
@@ -888,7 +830,7 @@ export default {
         this.filteredMachineOptions = this.machineOptions.filter(machine => machine.farmId === farmValue)
         this.filteredFieldOptions = this.fieldOptions.filter(field => field.farmId === farmValue)
         this.filteredOperatorOptions = this.operatorOptions.filter(operator => operator.farmId === farmValue)
-        
+
         // 只有在用户主动变更农场时才清空依赖字段,初始化加载时不清空
         if (!isInitialLoad) {
           this.form.machineName = null
@@ -900,14 +842,14 @@ export default {
         this.filteredMachineOptions = []
         this.filteredFieldOptions = []
         this.filteredOperatorOptions = []
-        
+
         // 清空依赖字段
         this.form.machineName = null
         this.form.fieldName = null
         this.form.operatorName = null
       }
     },
-    
+
     /** 农机名称变更处理 */
     handleMachineNameChange(machineValue) {
       const selectedMachine = this.machineOptions.find(m => m.value === machineValue)
@@ -918,7 +860,7 @@ export default {
       }
     },
 
-    
+
 
 
   }
@@ -926,9 +868,6 @@ export default {
 </script>
 
 <style scoped>
-
-
-
 /* 作业状态标签样式 */
 .work-status-tag {
   display: inline-block !important;

+ 125 - 227
src/views/base/machines/index.vue

@@ -2,127 +2,61 @@
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
       <el-form-item label="农机编号" prop="machineCode">
-        <el-input
-          v-model="queryParams.machineCode"
-          placeholder="请输入农机编号"
-          clearable
-          @keyup.enter.native="handleQuery"
-        />
+        <el-input v-model="queryParams.machineCode" placeholder="请输入农机编号" clearable @keyup.enter.native="handleQuery" />
       </el-form-item>
       <el-form-item label="农机名称" prop="machineName">
-        <el-input
-          v-model="queryParams.machineName"
-          placeholder="请输入农机名称"
-          clearable
-          @keyup.enter.native="handleQuery"
-        />
+        <el-input v-model="queryParams.machineName" placeholder="请输入农机名称" clearable @keyup.enter.native="handleQuery" />
       </el-form-item>
       <el-form-item label="农机类型" prop="machineType">
         <el-select v-model="queryParams.machineType" placeholder="请选择农机类型" clearable>
-          <el-option
-            v-for="dict in dict.type.agricultural_machine_type"
-            :key="dict.value"
-            :label="dict.label"
-            :value="dict.value"
-          />
+          <el-option v-for="dict in dict.type.agricultural_machine_type" :key="dict.value" :label="dict.label"
+            :value="dict.value" />
         </el-select>
       </el-form-item>
       <el-form-item label="厂家" prop="manufacturer">
-        <el-input
-          v-model="queryParams.manufacturer"
-          placeholder="请输入厂家"
-          clearable
-          @keyup.enter.native="handleQuery"
-        />
+        <el-input v-model="queryParams.manufacturer" placeholder="请输入厂家" clearable @keyup.enter.native="handleQuery" />
       </el-form-item>
       <el-form-item label="型号" prop="model">
-        <el-input
-          v-model="queryParams.model"
-          placeholder="请输入型号"
-          clearable
-          @keyup.enter.native="handleQuery"
-        />
+        <el-input v-model="queryParams.model" placeholder="请输入型号" clearable @keyup.enter.native="handleQuery" />
       </el-form-item>
-      <el-form-item label="所属农场" prop="farmId">
-        <el-select v-model="queryParams.farmId" placeholder="请选择所属农场" clearable>
-          <el-option
-            v-for="farm in farmOptions"
-            :key="farm.value"
-            :label="farm.label"
-            :value="farm.value"
-          />
-        </el-select>
-      </el-form-item>
-      <el-form-item label="所属地块" prop="fieldId">
-        <el-select v-model="queryParams.fieldId" placeholder="请选择所属地块" clearable>
-          <el-option
-            v-for="field in fieldOptions"
-            :key="field.value"
-            :label="field.label"
-            :value="field.value"
-          />
-        </el-select>
+
+      <el-form-item label="所属农场" prop="deptIdList">
+        <treeselect v-model="queryParams.deptIdList" :options="deptOptions" multiple :flat="true" :limit="1"
+          :limitText="count => `+${count}`" style="width:200px" :show-count="true" placeholder="请选所属机构" />
       </el-form-item>
-      <el-form-item label="负责人" prop="managerId">
-        <el-input
-          v-model="queryParams.managerId"
-          placeholder="请输入负责人"
-          clearable
-          @keyup.enter.native="handleQuery"
-        />
+
+
+      <el-form-item label="负责人" prop="managerName">
+        <el-input v-model="queryParams.managerName" placeholder="请输入负责人" clearable @keyup.enter.native="handleQuery" />
       </el-form-item>
       <el-form-item label="启用时间" prop="purchaseDate">
-        <el-date-picker
-          v-model="daterangePurchaseDate"
-          style="width: 240px"
-          value-format="yyyy-MM-dd"
-          type="daterange"
-          range-separator="至"
-          start-placeholder="开始日期"
-          end-placeholder="结束日期">
+        <el-date-picker v-model="daterangePurchaseDate" style="width: 240px" value-format="yyyy-MM-dd" type="daterange"
+          range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期">
         </el-date-picker>
       </el-form-item>
       <el-form-item label="生产日期" prop="manufactureDate">
-        <el-date-picker
-          v-model="daterangeManufactureDate"
-          style="width: 240px"
-          value-format="yyyy-MM-dd"
-          type="daterange"
-          range-separator="至"
-          start-placeholder="开始日期"
-          end-placeholder="结束日期">
+        <el-date-picker v-model="daterangeManufactureDate" style="width: 240px" value-format="yyyy-MM-dd"
+          type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期">
         </el-date-picker>
       </el-form-item>
       <el-form-item label="当前状态" prop="onlineStatus">
         <el-select v-model="queryParams.onlineStatus" placeholder="请选择当前状态" clearable>
-          <el-option
-            v-for="dict in dict.type.agricultural_online_status"
-            :key="dict.value"
-            :label="dict.label"
-            :value="dict.value"
-          />
+          <el-option v-for="dict in dict.type.agricultural_online_status" :key="dict.value" :label="dict.label"
+            :value="dict.value" />
         </el-select>
       </el-form-item>
 
 
       <el-form-item label="保养状态" prop="maintenanceStatus">
         <el-select v-model="queryParams.maintenanceStatus" placeholder="请选择保养状态" clearable>
-          <el-option
-            v-for="dict in dict.type.agricultural_maintenance_status"
-            :key="dict.value"
-            :label="dict.label"
-            :value="dict.value"
-          />
+          <el-option v-for="dict in dict.type.agricultural_maintenance_status" :key="dict.value" :label="dict.label"
+            :value="dict.value" />
         </el-select>
       </el-form-item>
       <el-form-item label="定位状态" prop="locationStatus">
         <el-select v-model="queryParams.locationStatus" placeholder="请选择定位状态" clearable>
-          <el-option
-            v-for="dict in dict.type.agricultural_location_status"
-            :key="dict.value"
-            :label="dict.label"
-            :value="dict.value"
-          />
+          <el-option v-for="dict in dict.type.agricultural_location_status" :key="dict.value" :label="dict.label"
+            :value="dict.value" />
         </el-select>
       </el-form-item>
       <el-form-item>
@@ -133,46 +67,20 @@
 
     <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="['base:machines:add']"
-        >新增</el-button>
+        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
+          v-hasPermi="['base:machines: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="['base:machines:edit']"
-        >修改</el-button>
+        <el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate"
+          v-hasPermi="['base:machines: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="['base:machines:remove']"
-        >删除</el-button>
+        <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete"
+          v-hasPermi="['base:machines: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="['base:machines:export']"
-        >导出</el-button>
+        <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport"
+          v-hasPermi="['base:machines:export']">导出</el-button>
       </el-col>
 
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
@@ -184,12 +92,12 @@
       <el-table-column label="农机名称" align="center" prop="machineName" />
       <el-table-column label="农机类型" align="center" prop="machineType">
         <template slot-scope="scope">
-          <dict-tag :options="dict.type.agricultural_machine_type" :value="scope.row.machineType"/>
+          <dict-tag :options="dict.type.agricultural_machine_type" :value="scope.row.machineType" />
         </template>
       </el-table-column>
-      <el-table-column label="所属农场" align="center" prop="farmId" />
-      <el-table-column label="所属地块" align="center" prop="fieldArea" />
-      <el-table-column label="负责人" align="center" prop="managerId" />
+      <el-table-column label="所属农场" align="center" key="deptName" prop="deptName" />
+      <!-- <el-table-column label="所属地块" align="center" prop="fieldArea" /> -->
+      <el-table-column label="负责人" align="center" prop="managerName" />
       <el-table-column label="厂家" align="center" prop="manufacturer" />
       <el-table-column label="型号" align="center" prop="model" />
       <el-table-column label="生产日期" align="center" prop="manufactureDate" width="180">
@@ -204,30 +112,21 @@
       </el-table-column>
       <el-table-column label="当前状态" align="center" prop="onlineStatus" width="100">
         <template slot-scope="scope">
-          <dict-tag 
-            :options="dict.type.agricultural_online_status" 
-            :value="scope.row.onlineStatus"
-            :class="['online-status-tag', getOnlineStatusClass(scope.row.onlineStatus)]"
-          />
+          <dict-tag :options="dict.type.agricultural_online_status" :value="scope.row.onlineStatus"
+            :class="['online-status-tag', getOnlineStatusClass(scope.row.onlineStatus)]" />
         </template>
       </el-table-column>
       <el-table-column label="当前任务" align="center" prop="currentTask" />
       <el-table-column label="保养状态" align="center" prop="maintenanceStatus" width="100">
         <template slot-scope="scope">
-          <dict-tag 
-            :options="dict.type.agricultural_maintenance_status" 
-            :value="scope.row.maintenanceStatus"
-            :class="['maintenance-status-tag', getMaintenanceStatusClass(scope.row.maintenanceStatus)]"
-          />
+          <dict-tag :options="dict.type.agricultural_maintenance_status" :value="scope.row.maintenanceStatus"
+            :class="['maintenance-status-tag', getMaintenanceStatusClass(scope.row.maintenanceStatus)]" />
         </template>
       </el-table-column>
       <el-table-column label="定位状态" align="center" prop="locationStatus" width="100">
         <template slot-scope="scope">
-          <dict-tag 
-            :options="dict.type.agricultural_location_status" 
-            :value="scope.row.locationStatus"
-            :class="['location-status-tag', getLocationStatusClass(scope.row.locationStatus)]"
-          />
+          <dict-tag :options="dict.type.agricultural_location_status" :value="scope.row.locationStatus"
+            :class="['location-status-tag', getLocationStatusClass(scope.row.locationStatus)]" />
         </template>
       </el-table-column>
       <el-table-column label="报警次数" align="center" prop="alarmCount" />
@@ -238,32 +137,18 @@
             type="text"
             icon="el-icon-view"
             @click="handleView(scope.row)"
+            v-hasPermi="['base:machines:view']"
           >查看</el-button>
-          <el-button
-            size="mini"
-            type="text"
-            icon="el-icon-edit"
-            @click="handleUpdate(scope.row)"
-            v-hasPermi="['base:machines:edit']"
-          >修改</el-button>
-          <el-button
-            size="mini"
-            type="text"
-            icon="el-icon-delete"
-            @click="handleDelete(scope.row)"
-            v-hasPermi="['base:machines:remove']"
-          >删除</el-button>
+          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
+            v-hasPermi="['base:machines:edit']">修改</el-button>
+          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
+            v-hasPermi="['base:machines:remove']">删除</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="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
+      @pagination="getList" />
 
     <!-- 添加或修改农机管理列表对话框 -->
     <el-dialog :title="title" :visible.sync="open" width="800px" append-to-body>
@@ -284,84 +169,56 @@
           <el-col :span="12">
             <el-form-item label="农机类型" prop="machineType">
               <el-select v-model="form.machineType" placeholder="请选择农机类型" style="width: 100%">
-                <el-option
-                  v-for="dict in dict.type.agricultural_machine_type"
-                  :key="dict.value"
-                  :label="dict.label"
-                  :value="dict.value"
-                ></el-option>
+                <el-option v-for="dict in dict.type.agricultural_machine_type" :key="dict.value" :label="dict.label"
+                  :value="dict.value"></el-option>
               </el-select>
             </el-form-item>
           </el-col>
           <el-col :span="12">
             <el-form-item label="所属农场" prop="farmId">
-              <el-select v-model="form.farmId" placeholder="请选择所属农场" clearable style="width: 100%">
-                <el-option
-                  v-for="farm in farmOptions"
-                  :key="farm.value"
-                  :label="farm.label"
-                  :value="farm.value"
-                />
-              </el-select>
+              <treeselect v-model="form.farmId" :options="enabledDeptOptions" :show-count="true" placeholder="请先选择所属农场" />
             </el-form-item>
+
           </el-col>
         </el-row>
         <el-row :gutter="20">
           <el-col :span="12">
-            <el-form-item label="所属地块" prop="fieldArea">
-              <el-select v-model="form.fieldArea" placeholder="请选择所属地块" clearable style="width: 100%">
-                <el-option
-                  v-for="field in fieldOptions"
-                  :key="field.value"
-                  :label="field.label"
-                  :value="field.value"
-                />
-              </el-select>
+            <el-form-item label="负责人" prop="managerName">
+              <el-input v-model="form.managerName" placeholder="请输入负责人" />
             </el-form-item>
           </el-col>
-          <el-col :span="12">
-            <el-form-item label="负责人" prop="managerId">
-              <el-input v-model="form.managerId" placeholder="请输入负责人" />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row :gutter="20">
           <el-col :span="12">
             <el-form-item label="厂家" prop="manufacturer">
               <el-input v-model="form.manufacturer" placeholder="请输入厂家" />
             </el-form-item>
           </el-col>
+        </el-row>
+        <el-row :gutter="20">
+
           <el-col :span="12">
             <el-form-item label="型号" prop="model">
               <el-input v-model="form.model" placeholder="请输入型号" />
             </el-form-item>
           </el-col>
-        </el-row>
-        <el-row :gutter="20">
           <el-col :span="12">
             <el-form-item label="生产日期" prop="manufactureDate">
-              <el-date-picker 
-                clearable
-                v-model="form.manufactureDate"
-                type="date"
-                value-format="yyyy-MM-dd"
-                placeholder="请选择生产日期"
-                style="width: 100%">
+              <el-date-picker clearable v-model="form.manufactureDate" type="date" value-format="yyyy-MM-dd"
+                placeholder="请选择生产日期" style="width: 100%">
               </el-date-picker>
             </el-form-item>
           </el-col>
+
+        </el-row>
+        <el-row :gutter="20">
+
           <el-col :span="12">
             <el-form-item label="启用时间" prop="purchaseDate">
-              <el-date-picker 
-                clearable
-                v-model="form.purchaseDate"
-                type="date"
-                value-format="yyyy-MM-dd"
-                placeholder="请选择启用时间"
-                style="width: 100%">
+              <el-date-picker clearable v-model="form.purchaseDate" type="date" value-format="yyyy-MM-dd"
+                placeholder="请选择启用时间" style="width: 100%">
               </el-date-picker>
             </el-form-item>
           </el-col>
+
         </el-row>
         <el-row>
           <el-col :span="24">
@@ -389,11 +246,16 @@
 <script>
 import { listMachines, getMachines, delMachines, addMachines, updateMachines } from "@/api/base/machines"
 import ImageUpload from "@/components/ImageUpload"
+import { deptTreeSelect } from "@/api/system/user";
+import { listFieldName } from "@/api/base/field";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
 
 export default {
   name: "Machines",
   components: {
-    ImageUpload
+    ImageUpload,
+    Treeselect
   },
   dicts: ['agricultural_machine_type', 'agricultural_maintenance_status', 'agricultural_online_status', 'agricultural_location_status'],
   data() {
@@ -402,6 +264,7 @@ export default {
       loading: true,
       // 选中数组
       ids: [],
+      machineCodes: [],
       // 非单个禁用
       single: true,
       // 非多个禁用
@@ -424,6 +287,14 @@ export default {
       farmOptions: [],
       // 地块选项列表
       fieldOptions: [],
+
+      // 部门树选项
+      deptOptions: undefined,
+      // 过滤掉已禁用部门树选项
+      enabledDeptOptions: undefined,
+
+      // 所属地块
+      fieldIdList: [],
       // 查询参数
       queryParams: {
         pageNum: 1,
@@ -460,7 +331,7 @@ export default {
         fieldArea: [
           { required: true, message: "所属地块不能为空", trigger: "change" }
         ],
-        managerId: [
+        managerName: [
           { required: true, message: "负责人不能为空", trigger: "blur" }
         ],
         manufacturer: [
@@ -474,22 +345,47 @@ export default {
   },
   created() {
     this.getList()
-    this.getFarmOptions()
-    this.getFieldOptions()
+    this.getDeptTree()
+    this.getFieldNameList()
   },
   methods: {
+
+    /** 查询地块名称 **/
+    getFieldNameList() {
+      listFieldName().then(res => {
+        this.fieldIdList = res;
+        this.fieldIdList.forEach(x => {
+          x.value = x.id;
+          x.label = x.fieldName;
+        })
+      });
+    },
+
+
+    getDeptTree() {
+      deptTreeSelect().then(response => {
+        this.deptOptions = response.data;
+        this.enabledDeptOptions = this.filterDisabledDept(JSON.parse(JSON.stringify(response.data)))
+      });
+    },
+
+    filterDisabledDept(deptList) {
+      return deptList.filter(dept => {
+        if (dept.disabled) {
+          return false
+        }
+        if (dept.children && dept.children.length) {
+          dept.children = this.filterDisabledDept(dept.children)
+        }
+        return true
+      })
+    },
     /** 获取农场选项 */
     getFarmOptions() {
       // 暂时没有数据,可以在后续添加API调用
       // 示例: getFarmList().then(response => { this.farmOptions = response.data })
       this.farmOptions = []
     },
-    /** 获取地块选项 */
-    getFieldOptions() {
-      // 暂时没有数据,可以在后续添加API调用
-      // 示例: getFieldList().then(response => { this.fieldOptions = response.data })
-      this.fieldOptions = []
-    },
     /** 查询农机管理列表列表 */
     getList() {
       this.loading = true
@@ -512,9 +408,9 @@ export default {
     getDictLabel(options, value) {
       if (!options || (value === null || value === undefined || value === '')) return ''
       // 尝试字符串和数字匹配
-      const item = options.find(option => 
-        option.value === value || 
-        option.value === String(value) || 
+      const item = options.find(option =>
+        option.value === value ||
+        option.value === String(value) ||
         String(option.value) === String(value)
       )
       return item ? item.label : value
@@ -604,7 +500,8 @@ export default {
     // 多选框选中数据
     handleSelectionChange(selection) {
       this.ids = selection.map(item => item.id)
-      this.single = selection.length!==1
+      this.machineCodes = selection.map(item => item.machineCode)
+      this.single = selection.length !== 1
       this.multiple = !selection.length
     },
     /** 新增按钮操作 */
@@ -654,12 +551,13 @@ export default {
     /** 删除按钮操作 */
     handleDelete(row) {
       const ids = row.id || this.ids
-      this.$modal.confirm('是否确认删除农机管理列表编号为"' + ids + '"的数据项?').then(function() {
+      const machineCodes = row.machineCode || this.machineCodes
+      this.$modal.confirm('确认删除农机管理列表编号为"' + machineCodes + '"的数据项?').then(function () {
         return delMachines(ids)
       }).then(() => {
         this.getList()
         this.$modal.msgSuccess("删除成功")
-      }).catch(() => {})
+      }).catch(() => { })
     },
     /** 导出按钮操作 */
     handleExport() {

+ 172 - 283
src/views/base/record/index.vue

@@ -2,42 +2,24 @@
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
       <el-form-item label="设备编号" prop="deviceId">
-        <el-input
-          v-model="queryParams.deviceId"
-          placeholder="请输入设备编号关键词"
-          clearable
-          @keyup.enter.native="handleQuery"
-        />
+        <el-input v-model="queryParams.deviceId" placeholder="请输入设备编号关键词" clearable @keyup.enter.native="handleQuery" />
       </el-form-item>
       <el-form-item label="设备名称" prop="deviceName">
-        <el-input
-          v-model="queryParams.deviceName"
-          placeholder="请输入设备名称关键词"
-          clearable
-          @keyup.enter.native="handleQuery"
-        />
+        <el-input v-model="queryParams.deviceName" placeholder="请输入设备名称关键词" clearable
+          @keyup.enter.native="handleQuery" />
       </el-form-item>
       <el-form-item label="告警等级" prop="alertLevel">
         <el-select v-model="queryParams.alertLevel" placeholder="所有告警等级" clearable>
-          <el-option
-            v-for="dict in dict.type.alert_level"
-            :key="dict.value"
-            :label="dict.label"
-            :value="dict.value"
-          />
+          <el-option v-for="dict in dict.type.alert_level" :key="dict.value" :label="dict.label" :value="dict.value" />
         </el-select>
       </el-form-item>
       <el-form-item label="设备类型" prop="deviceType">
         <el-select v-model="queryParams.deviceType" placeholder="所有设备类型" clearable>
-          <el-option
-            v-for="dict in dict.type.alert_device_type"
-            :key="dict.value"
-            :label="dict.label"
-            :value="dict.value"
-          />
+          <el-option v-for="dict in dict.type.alert_device_type" :key="dict.value" :label="dict.label"
+            :value="dict.value" />
         </el-select>
       </el-form-item>
-      <el-form-item label="所属地块" prop="fieldId">
+      <!-- <el-form-item label="所属地块" prop="fieldId">
         <el-select v-model="queryParams.fieldId" placeholder="所有地块" clearable>
           <el-option
             v-for="dict in dict.type.field_list"
@@ -46,8 +28,15 @@
             :value="dict.value"
           />
         </el-select>
+      </el-form-item> -->
+
+      <el-form-item label="所属地块" prop="fieldIdList">
+        <el-select v-model="queryParams.fieldIdList" placeholder="请选择地块" multiple collapse-tags filterable clearable>
+          <el-option v-for="dict in fieldIdList" :key="dict.value" :label="dict.label" :value="dict.value" />
+        </el-select>
       </el-form-item>
-      <el-form-item label="所属农场" prop="farmId">
+
+      <!-- <el-form-item label="所属农场" prop="farmId">
         <el-select v-model="queryParams.farmId" placeholder="所有农场" clearable>
           <el-option
             v-for="dict in dict.type.farm_list"
@@ -56,26 +45,23 @@
             :value="dict.value"
           />
         </el-select>
+      </el-form-item> -->
+
+
+      <el-form-item label="所属农场" prop="deptIdList">
+        <treeselect v-model="queryParams.deptIdList" :options="deptOptions" multiple :flat="true" :limit="1"
+          :limitText="count => `+${count}`" style="width:200px" :show-count="true" placeholder="请选所属农场" />
       </el-form-item>
+
+
       <el-form-item label="告警时间">
-        <el-date-picker
-          v-model="daterangeAlertTime"
-          style="width: 240px"
-          value-format="yyyy-MM-dd"
-          type="daterange"
-          range-separator="至"
-          start-placeholder="年/月/日"
-          end-placeholder="年/月/日"
-        ></el-date-picker>
+        <el-date-picker v-model="daterangeAlertTime" style="width: 240px" value-format="yyyy-MM-dd" type="daterange"
+          range-separator="至" start-placeholder="年/月/日" end-placeholder="年/月/日"></el-date-picker>
       </el-form-item>
       <el-form-item label="处理状态" prop="processStatus">
         <el-select v-model="queryParams.processStatus" placeholder="所有状态" clearable>
-          <el-option
-            v-for="dict in dict.type.alert_process_status"
-            :key="dict.value"
-            :label="dict.label"
-            :value="dict.value"
-          />
+          <el-option v-for="dict in dict.type.alert_process_status" :key="dict.value" :label="dict.label"
+            :value="dict.value" />
         </el-select>
       </el-form-item>
       <el-form-item>
@@ -105,12 +91,12 @@
             <div class="stat-header">
               <span class="stat-title">紧急告警</span>
             </div>
-                         <div class="stat-content">
-               <div class="stat-number">{{ levelStatistics.emergency.total }}</div>
-               <div class="stat-detail">
-                 <span>未处理: {{ levelStatistics.emergency.unprocessed }}</span>
-               </div>
-             </div>
+            <div class="stat-content">
+              <div class="stat-number">{{ levelStatistics.emergency.total }}</div>
+              <div class="stat-detail">
+                <span>未处理: {{ levelStatistics.emergency.unprocessed }}</span>
+              </div>
+            </div>
           </div>
         </el-col>
         <el-col :span="6">
@@ -118,12 +104,12 @@
             <div class="stat-header">
               <span class="stat-title">警告</span>
             </div>
-                         <div class="stat-content">
-               <div class="stat-number">{{ levelStatistics.warning.total }}</div>
-               <div class="stat-detail">
-                 <span>未处理: {{ levelStatistics.warning.unprocessed }}</span>
-               </div>
-             </div>
+            <div class="stat-content">
+              <div class="stat-number">{{ levelStatistics.warning.total }}</div>
+              <div class="stat-detail">
+                <span>未处理: {{ levelStatistics.warning.unprocessed }}</span>
+              </div>
+            </div>
           </div>
         </el-col>
         <el-col :span="6">
@@ -131,12 +117,12 @@
             <div class="stat-header">
               <span class="stat-title">提示信息</span>
             </div>
-                         <div class="stat-content">
-               <div class="stat-number">{{ levelStatistics.info.total }}</div>
-               <div class="stat-detail">
-                 <span>未处理: {{ levelStatistics.info.unprocessed }}</span>
-               </div>
-             </div>
+            <div class="stat-content">
+              <div class="stat-number">{{ levelStatistics.info.total }}</div>
+              <div class="stat-detail">
+                <span>未处理: {{ levelStatistics.info.unprocessed }}</span>
+              </div>
+            </div>
           </div>
         </el-col>
       </el-row>
@@ -144,14 +130,8 @@
 
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button
-          type="warning"
-          plain
-          icon="el-icon-download"
-          size="mini"
-          @click="handleExport"
-          v-hasPermi="['base:record:export']"
-        >导出</el-button>
+        <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport"
+          v-hasPermi="['base:record:export']">导出</el-button>
       </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
@@ -160,20 +140,21 @@
       <el-table-column label="告警ID" align="center" prop="alertId" />
       <el-table-column label="告警等级" align="center" prop="alertLevel">
         <template slot-scope="scope">
-          <span :class="['custom-tag', 'level-tag', getAlertLevelClass(scope.row.alertLevel)]">
-            {{ getAlertLevelText(scope.row.alertLevel) }}
-          </span>
+          <dict-tag :options="dict.type.alert_level" :value="scope.row.alertLevel" />
         </template>
       </el-table-column>
       <el-table-column label="设备名称" align="center" prop="deviceName" />
       <el-table-column label="设备编号" align="center" prop="deviceId" />
       <el-table-column label="设备类型" align="center" prop="deviceType">
         <template slot-scope="scope">
-          <dict-tag :options="dict.type.alert_device_type" :value="scope.row.deviceType"/>
+          <dict-tag :options="dict.type.alert_device_type" :value="scope.row.deviceType" />
         </template>
       </el-table-column>
-      <el-table-column label="所属地块" align="center" prop="fieldId" />
-      <el-table-column label="所属农场" align="center" prop="farmId" />
+      <!-- <el-table-column label="所属地块" align="center" prop="fieldId" />
+      <el-table-column label="所属农场" align="center" prop="farmId" /> -->
+      <el-table-column label="所属地块" align="center" key="fieldName" prop="fieldName" />
+      <el-table-column label="所属农场" align="center" key="deptName" prop="deptName" />
+
       <el-table-column label="告警内容" align="center" prop="alertContent" />
       <el-table-column label="告警时间" align="center" prop="alertTime" width="180">
         <template slot-scope="scope">
@@ -182,9 +163,7 @@
       </el-table-column>
       <el-table-column label="处理状态" align="center" prop="processStatus">
         <template slot-scope="scope">
-          <span :class="['custom-tag', 'status-tag', getProcessStatusClass(scope.row.processStatus)]">
-            {{ getProcessStatusText(scope.row.processStatus) }}
-          </span>
+          <dict-tag :options="dict.type.alert_process_status" :value="scope.row.processStatus" />
         </template>
       </el-table-column>
       <el-table-column label="处理人" align="center" prop="processor" />
@@ -195,31 +174,15 @@
       </el-table-column>
       <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-view"
-            @click="handleDetail(scope.row)"
-          >查看</el-button>
-          <el-button
-            v-if="scope.row.processStatus == 0 || scope.row.processStatus == '0' || scope.row.processStatus == 2 || scope.row.processStatus == '2'"
-            size="mini"
-            type="text"
-            icon="el-icon-edit"
-            @click="handleProcess(scope.row)"
-            v-hasPermi="['base:record:edit']"
-          >处理</el-button>
+          <el-button size="mini" type="text" icon="el-icon-view" @click="handleDetail(scope.row)">查看</el-button>
+          <el-button v-if="scope.row.processStatus == 0 || scope.row.processStatus == '0'" size="mini" type="text"
+            icon="el-icon-edit" @click="handleProcess(scope.row)" v-hasPermi="['base:record:edit']">处理</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="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
+      @pagination="getList" />
 
     <!-- 告警详情对话框 -->
     <el-dialog title="告警详情" :visible.sync="detailOpen" width="600px" append-to-body>
@@ -229,19 +192,17 @@
           <!-- 头部信息 -->
           <div class="alert-header">
             <div class="alert-level-tag">
-              <span :class="['custom-tag', 'level-tag', getAlertLevelClass(currentRecord.alertLevel)]">
-                {{ getAlertLevelText(currentRecord.alertLevel) }}
-              </span>
+              <dict-tag :options="dict.type.alert_level" :value="currentRecord.alertLevel" />
             </div>
             <div class="alert-time">{{ parseTime(currentRecord.alertTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</div>
           </div>
-          
+
           <!-- 告警内容 -->
           <div class="alert-content">
             {{ getAlertContent(currentRecord) }}
           </div>
         </div>
-        
+
         <!-- 设备信息 -->
         <div class="section">
           <div class="section-title">设备信息</div>
@@ -263,16 +224,16 @@
               </div>
               <div class="info-item">
                 <span class="label">所属地块</span>
-                <span class="value">{{ currentRecord.fieldId }}</span>
+                <span class="value">{{ currentRecord.fieldName }}</span>
               </div>
               <div class="info-item">
                 <span class="label">所属农场</span>
-                <span class="value">{{ currentRecord.farmId }}</span>
+                <span class="value">{{ currentRecord.deptName }}</span>
               </div>
             </div>
           </div>
         </div>
-        
+
         <!-- 处理状态 -->
         <div class="section">
           <div class="section-title">处理状态</div>
@@ -280,9 +241,7 @@
             <div class="status-item">
               <span class="label">当前状态</span>
               <span class="value status">
-                <span :class="['custom-tag', 'status-tag', getProcessStatusClass(currentRecord.processStatus)]">
-                  {{ getProcessStatusText(currentRecord.processStatus) }}
-                </span>
+                <dict-tag :options="dict.type.alert_process_status" :value="currentRecord.processStatus" />
               </span>
             </div>
             <div class="status-item">
@@ -301,13 +260,14 @@
             </div>
           </div>
         </div>
-        
+
         <!-- 附件信息 -->
         <div class="section">
           <div class="section-title">附件信息</div>
           <div class="attachment-info">
             <div v-if="currentRecord.attachments && currentRecord.attachments.length > 0" class="attachment-list">
-              <div v-for="(attachment, index) in getAttachmentList(currentRecord.attachments)" :key="index" class="attachment-item">
+              <div v-for="(attachment, index) in getAttachmentList(currentRecord.attachments)" :key="index"
+                class="attachment-item">
                 <div class="attachment-preview">
                   <i v-if="isImage(attachment.name)" class="el-icon-picture-outline"></i>
                   <i v-else class="el-icon-document"></i>
@@ -318,7 +278,8 @@
                 </div>
                 <div class="attachment-actions">
                   <el-button size="mini" type="text" @click="downloadAttachment(attachment)">下载</el-button>
-                  <el-button v-if="isImage(attachment.name)" size="mini" type="text" @click="previewImage(attachment)">预览</el-button>
+                  <el-button v-if="isImage(attachment.name)" size="mini" type="text"
+                    @click="previewImage(attachment)">预览</el-button>
                 </div>
               </div>
             </div>
@@ -329,7 +290,7 @@
           </div>
         </div>
       </div>
-      
+
       <div slot="footer" class="dialog-footer">
         <el-button @click="detailOpen = false">关闭</el-button>
       </div>
@@ -339,15 +300,15 @@
     <el-dialog title="处理告警" :visible.sync="processOpen" width="500px" append-to-body>
       <el-form ref="processForm" :model="processForm" :rules="processRules" label-width="80px">
         <el-form-item label="告警信息">
-                     <div class="process-alert-info">
-             <div class="info-item">
-               <span class="label">设备编号:</span>
-               <span class="value">{{ processForm.deviceId }}</span>
-             </div>
-             <div class="info-item">
-               <span class="label">设备名称:</span>
-               <span class="value">{{ processForm.deviceName }}</span>
-             </div>
+          <div class="process-alert-info">
+            <div class="info-item">
+              <span class="label">设备编号:</span>
+              <span class="value">{{ processForm.deviceId }}</span>
+            </div>
+            <div class="info-item">
+              <span class="label">设备名称:</span>
+              <span class="value">{{ processForm.deviceName }}</span>
+            </div>
             <div class="alert-content-preview">
               {{ getAlertContent(processForm) }}
             </div>
@@ -356,20 +317,14 @@
         <el-form-item label="处理结果" prop="processStatus">
           <el-select v-model="processForm.processStatus" placeholder="请选择处理结果">
             <el-option label="未处理" :value="0"></el-option>
-            <el-option label="已处理" :value="1"></el-option>
-            <el-option label="处理" :value="2"></el-option>
+            <el-option label="已确认" :value="1"></el-option>
+            <el-option label="处理" :value="2"></el-option>
             <el-option label="忽略" :value="3"></el-option>
           </el-select>
         </el-form-item>
         <el-form-item label="处理备注" prop="processComment">
-          <el-input 
-            v-model="processForm.processComment" 
-            type="textarea" 
-            :rows="4"
-            placeholder="请输入处理备注..."
-            maxlength="500"
-            show-word-limit
-          />
+          <el-input v-model="processForm.processComment" type="textarea" :rows="4" placeholder="请输入处理备注..."
+            maxlength="500" show-word-limit />
         </el-form-item>
         <el-form-item label="附件上传">
           <file-upload v-model="processForm.attachments" :limit="5" />
@@ -386,9 +341,13 @@
 
 <script>
 import { listRecord, getRecord, updateRecord } from "@/api/base/record"
-
+import { deptTreeSelect } from "@/api/system/user";
+import { listFieldName } from "@/api/base/field";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
 export default {
   name: "Record",
+  components: { Treeselect },
   dicts: ['alert_process_status', 'alert_level', 'alert_device_type', 'field_list', 'farm_list'],
   data() {
     return {
@@ -402,6 +361,14 @@ export default {
       recordList: [],
       // 告警时间范围
       daterangeAlertTime: [],
+
+
+      // 部门树选项
+      deptOptions: undefined,
+
+      // 所属地块
+      fieldIdList: [],
+
       // 查询参数
       queryParams: {
         pageNum: 1,
@@ -414,6 +381,8 @@ export default {
         processStatus: null,
         farmId: null,
         fieldId: null,
+
+        deptIdList: [],
       },
       // 告警详情对话框
       detailOpen: false,
@@ -455,8 +424,30 @@ export default {
   created() {
     this.getList()
     this.getStatistics()
+    this.getDeptTree();
+    this.getFieldNameList();
   },
   methods: {
+
+
+    /** 查询地块名称 **/
+    getFieldNameList() {
+      listFieldName().then(res => {
+        this.fieldIdList = res;
+        this.fieldIdList.forEach(x => {
+          x.value = x.id;
+          x.label = x.fieldName;
+        })
+      });
+    },
+
+
+    /** 查询部门下拉树结构 */
+    getDeptTree() {
+      deptTreeSelect().then(response => {
+        this.deptOptions = response.data;
+      });
+    },
     /** 查询告警记录列表 */
     getList() {
       this.loading = true
@@ -478,21 +469,21 @@ export default {
       // 这里可以调用专门的统计API
       // 暂时使用模拟数据
       this.todayStatistics = {
-        total: 24,
-        change: 8
+        total: 0,
+        change: 0
       }
       this.levelStatistics = {
         emergency: {
-          total: 5,
-          unprocessed: 2
+          total: 0,
+          unprocessed: 0
         },
         warning: {
-          total: 12,
-          unprocessed: 4
+          total: 0,
+          unprocessed: 0
         },
         info: {
-          total: 7,
-          unprocessed: 1
+          total: 0,
+          unprocessed: 0
         }
       }
     },
@@ -501,43 +492,50 @@ export default {
       if (!this.recordList || this.recordList.length === 0) {
         return
       }
-      
+
       // 重置统计数据
       this.levelStatistics = {
         emergency: { total: 0, unprocessed: 0 },
         warning: { total: 0, unprocessed: 0 },
         info: { total: 0, unprocessed: 0 }
       }
-      
+
       // 今日日期
-      const today = new Date().toISOString().slice(0, 10)
-      let todayCount = 0
-      
-      // 遍历记录统计
+      const toDateStr = (dateLike) =>
+        new Date(dateLike).toISOString().slice(0, 10);
+
+      const today = toDateStr(new Date());
+      const yesterday = toDateStr(Date.now() - 86400000);
+
+      let todayCount = 0;
+      let yesterdayCount = 0;
+
       this.recordList.forEach(record => {
-        // 统计今日告警
-        if (record.alertTime && record.alertTime.includes(today)) {
-          todayCount++
-        }
-        
+        if (!record.alertTime) return;          // 空值跳过
+        const alertDay = toDateStr(record.alertTime);
+
+        if (alertDay === today) todayCount++;
+        if (alertDay === yesterday) yesterdayCount++;
         // 统计各等级告警
         const level = record.alertLevel
-        const isUnprocessed = record.processStatus == 0 || record.processStatus == '0' || record.processStatus == 2 || record.processStatus == '2'
-        
-        // 根据告警等级统计 (假设: 1-紧急, 2-警告, 3-提示)
+        const isUnprocessed = record.processStatus == 0 || record.processStatus == '0'
+
+
         if (level == 1 || level == '1') {
-          this.levelStatistics.emergency.total++
-          if (isUnprocessed) this.levelStatistics.emergency.unprocessed++
+          this.levelStatistics.info.total++
+          if (isUnprocessed) this.levelStatistics.info.unprocessed++
         } else if (level == 2 || level == '2') {
           this.levelStatistics.warning.total++
           if (isUnprocessed) this.levelStatistics.warning.unprocessed++
         } else if (level == 3 || level == '3') {
-          this.levelStatistics.info.total++
-          if (isUnprocessed) this.levelStatistics.info.unprocessed++
+          this.levelStatistics.emergency.total++
+          if (isUnprocessed) this.levelStatistics.emergency.unprocessed++
         }
+
       })
-      
-      // 更新今日统计 (这里只是示例,实际应该从后端获取完整统计)
+
+      this.todayStatistics.change = todayCount - yesterdayCount;
+      // 更新今日统计
       if (todayCount > 0) {
         this.todayStatistics.total = todayCount
       }
@@ -566,7 +564,7 @@ export default {
       //   this.currentRecord = response.data
       //   this.detailOpen = true
       // })
-      
+
       // 当前直接使用列表数据显示
       this.currentRecord = { ...record }
       this.detailOpen = true
@@ -589,21 +587,21 @@ export default {
       if (!record.alertContent) {
         return '暂无告警内容'
       }
-      
+
       let content = record.alertContent
-      
+
       // 尝试去掉设备名称前缀
       // 匹配模式:设备XXX + 告警内容
       const devicePatterns = [
         // 匹配"设备D1001温度异常"格式
         /^设备[A-Za-z0-9]+(.+)$/,
-        // 匹配"D1001温度异常"格式  
+        // 匹配"D1001温度异常"格式
         /^[A-Za-z0-9]+(.+)$/,
         // 匹配设备名称开头的格式
         /^.+?号(.+)$/,
         /^.+?站(.+)$/
       ]
-      
+
       // 如果告警内容包含设备信息,尝试去掉设备前缀
       if (record.deviceId && content.includes(record.deviceId)) {
         // 去掉设备编号前缀
@@ -621,10 +619,10 @@ export default {
           }
         }
       }
-      
+
       // 清理开头的标点符号
       content = content.replace(/^[::,,\s]+/, '')
-      
+
       return content || record.alertContent
     },
     /** 获取附件列表 */
@@ -707,7 +705,7 @@ export default {
       this.$refs.processForm.validate((valid) => {
         if (valid) {
           this.processLoading = true
-          
+
           // 准备要更新的数据
           const updateData = {
             alertId: this.processForm.alertId,
@@ -715,7 +713,7 @@ export default {
             processComment: this.processForm.processComment,
             attachments: this.processForm.attachments
           }
-          
+
           updateRecord(updateData).then(response => {
             this.$modal.msgSuccess("处理成功")
             this.processOpen = false
@@ -753,58 +751,6 @@ export default {
       if (this.$refs.processForm) {
         this.$refs.processForm.resetFields()
       }
-    },
-    /** 获取告警等级样式类 */
-    getAlertLevelClass(level) {
-      const levelMap = {
-        '1': 'emergency',
-        '2': 'warning', 
-        '3': 'info',
-        1: 'emergency',
-        2: 'warning',
-        3: 'info'
-      }
-      return levelMap[level] || 'info'
-    },
-    /** 获取告警等级文本 */
-    getAlertLevelText(level) {
-      const levelMap = {
-        '1': '紧急',
-        '2': '警告',
-        '3': '提示',
-        1: '紧急',
-        2: '警告', 
-        3: '提示'
-      }
-      return levelMap[level] || '未知'
-    },
-    /** 获取处理状态样式类 */
-    getProcessStatusClass(status) {
-      const statusMap = {
-        '0': 'pending',
-        '1': 'processed',
-        '2': 'processing',
-        '3': 'ignored',
-        0: 'pending',
-        1: 'processed',
-        2: 'processing',
-        3: 'ignored'
-      }
-      return statusMap[status] || 'pending'
-    },
-    /** 获取处理状态文本 */
-    getProcessStatusText(status) {
-      const statusMap = {
-        '0': '未处理',
-        '1': '已处理', 
-        '2': '处理中',
-        '3': '忽略',
-        0: '未处理',
-        1: '已处理',
-        2: '处理中',
-        3: '忽略'
-      }
-      return statusMap[status] || '未知'
     }
   }
 }
@@ -821,7 +767,7 @@ export default {
   padding: 20px;
   margin-bottom: 20px;
   border: 1px solid #e9ecef;
-  box-shadow: 0 2px 4px rgba(0,0,0,0.05);
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
   border-left: 4px solid #f56c6c;
 }
 
@@ -1068,7 +1014,7 @@ export default {
   padding: 20px;
   background: #fff;
   border-radius: 12px;
-  box-shadow: 0 1px 3px rgba(0,0,0,0.08);
+  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
 }
 
 /* 统一各部分间距 */
@@ -1093,7 +1039,7 @@ export default {
   justify-content: space-between;
   transition: all 0.3s ease;
   cursor: pointer;
-  box-shadow: 0 4px 15px rgba(0,0,0,0.1), 0 2px 6px rgba(0,0,0,0.05);
+  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1), 0 2px 6px rgba(0, 0, 0, 0.05);
   position: relative;
   overflow: hidden;
   color: #fff;
@@ -1101,7 +1047,7 @@ export default {
 
 .stat-card:hover {
   transform: translateY(-3px);
-  box-shadow: 0 8px 25px rgba(0,0,0,0.15), 0 4px 10px rgba(0,0,0,0.1);
+  box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15), 0 4px 10px rgba(0, 0, 0, 0.1);
 }
 
 .stat-card.total {
@@ -1174,61 +1120,4 @@ export default {
   line-height: 1.2;
   margin: 0;
 }
-
-/* 自定义标签样式 */
-.custom-tag {
-  display: inline-block;
-  padding: 4px 12px;
-  border-radius: 12px;
-  font-size: 12px;
-  font-weight: 500;
-  text-align: center;
-  min-width: 50px;
-  line-height: 1.2;
-}
-
-/* 告警等级标签 */
-.level-tag.emergency {
-  background-color: #fef2f2;
-  color: #dc2626;
-  border: 1px solid #fecaca;
-}
-
-.level-tag.warning {
-  background-color: #fffbeb;
-  color: #d97706;
-  border: 1px solid #fed7aa;
-}
-
-.level-tag.info {
-  background-color: #eff6ff;
-  color: #2563eb;
-  border: 1px solid #bfdbfe;
-}
-
-/* 处理状态标签 */
-.status-tag.pending {
-  background-color: #fef2f2;
-  color: #dc2626;
-  border: 1px solid #fecaca;
-}
-
-.status-tag.processing {
-  background-color: #fffbeb;
-  color: #d97706;
-  border: 1px solid #fed7aa;
-}
-
-.status-tag.processed {
-  background-color: #f0fdf4;
-  color: #16a34a;
-  border: 1px solid #bbf7d0;
-}
-
-.status-tag.ignored {
-  background-color: #f9fafb;
-  color: #6b7280;
-  border: 1px solid #d1d5db;
-}
 </style>
-

+ 1 - 1
src/views/system/dept/index.vue

@@ -9,7 +9,7 @@
           @keyup.enter.native="handleQuery"
         />
       </el-form-item>
-      <el-form-item label="状态cs" prop="status">
+      <el-form-item label="状态" prop="status">
         <el-select v-model="queryParams.status" placeholder="部门状态" clearable>
           <el-option
             v-for="dict in dict.type.sys_normal_disable"

+ 1 - 1
vue.config.js

@@ -36,7 +36,7 @@ module.exports = {
     proxy: {
       // detail: https://cli.vuejs.org/config/#devserver-proxy
       [process.env.VUE_APP_BASE_API]: {
-        target: `http://121.4.16.100:8080`,
+        target: `http://localhost:8080`,
         changeOrigin: true,
         pathRewrite: {
           ['^' + process.env.VUE_APP_BASE_API]: ''

Неке датотеке нису приказане због велике количине промена