Explorar o código

跟新环境菜单

丁烨烨 hai 1 ano
pai
achega
f551632f7e

+ 2 - 1
auto-imports.d.ts

@@ -6,5 +6,6 @@
 // biome-ignore lint: disable
 export {}
 declare global {
-
+  const ElMessage: typeof import('element-plus/es')['ElMessage']
+  const ElMessageBox: typeof import('element-plus/es')['ElMessageBox']
 }

+ 4 - 0
components.d.ts

@@ -11,6 +11,7 @@ declare module 'vue' {
     ElCard: typeof import('element-plus/es')['ElCard']
     ElCol: typeof import('element-plus/es')['ElCol']
     ElContainer: typeof import('element-plus/es')['ElContainer']
+    ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
     ElDescriptions: typeof import('element-plus/es')['ElDescriptions']
     ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem']
     ElDialog: typeof import('element-plus/es')['ElDialog']
@@ -19,6 +20,7 @@ declare module 'vue' {
     ElHeader: typeof import('element-plus/es')['ElHeader']
     ElIcon: typeof import('element-plus/es')['ElIcon']
     ElInput: typeof import('element-plus/es')['ElInput']
+    ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
     ElLink: typeof import('element-plus/es')['ElLink']
     ElMain: typeof import('element-plus/es')['ElMain']
     ElMenu: typeof import('element-plus/es')['ElMenu']
@@ -35,6 +37,8 @@ declare module 'vue' {
     ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
     ElTag: typeof import('element-plus/es')['ElTag']
     ElText: typeof import('element-plus/es')['ElText']
+    ElTimeline: typeof import('element-plus/es')['ElTimeline']
+    ElTimelineItem: typeof import('element-plus/es')['ElTimelineItem']
     ElTooltip: typeof import('element-plus/es')['ElTooltip']
     ElUpload: typeof import('element-plus/es')['ElUpload']
     IconCommunity: typeof import('./src/components/icons/IconCommunity.vue')['default']

+ 8 - 8
package-lock.json

@@ -11,7 +11,7 @@
         "@element-plus/icons-vue": "^2.3.1",
         "@vueuse/core": "^12.0.0",
         "axios": "^1.7.9",
-        "echarts": "^5.5.1",
+        "echarts": "^5.6.0",
         "element-plus": "^2.9.0",
         "pinia": "^2.2.6",
         "video.js": "^8.21.0",
@@ -3744,13 +3744,13 @@
       "license": "MIT"
     },
     "node_modules/echarts": {
-      "version": "5.5.1",
-      "resolved": "https://registry.npmmirror.com/echarts/-/echarts-5.5.1.tgz",
-      "integrity": "sha512-Fce8upazaAXUVUVsjgV6mBnGuqgO+JNDlcgF79Dksy4+wgGpQB2lmYoO4TSweFg/mZITdpGHomw/cNBJZj1icA==",
+      "version": "5.6.0",
+      "resolved": "https://registry.npmmirror.com/echarts/-/echarts-5.6.0.tgz",
+      "integrity": "sha512-oTbVTsXfKuEhxftHqL5xprgLoc0k7uScAwtryCgWF6hPYFLRwOUHiFmHGCBKP5NPFNkDVopOieyUqYGH8Fa3kA==",
       "license": "Apache-2.0",
       "dependencies": {
         "tslib": "2.3.0",
-        "zrender": "5.6.0"
+        "zrender": "5.6.1"
       }
     },
     "node_modules/echarts/node_modules/tslib": {
@@ -10072,9 +10072,9 @@
       }
     },
     "node_modules/zrender": {
-      "version": "5.6.0",
-      "resolved": "https://registry.npmmirror.com/zrender/-/zrender-5.6.0.tgz",
-      "integrity": "sha512-uzgraf4njmmHAbEUxMJ8Oxg+P3fT04O+9p7gY+wJRVxo8Ge+KmYv0WJev945EH4wFuc4OY2NLXz46FZrWS9xJg==",
+      "version": "5.6.1",
+      "resolved": "https://registry.npmmirror.com/zrender/-/zrender-5.6.1.tgz",
+      "integrity": "sha512-OFXkDJKcrlx5su2XbzJvj/34Q3m6PvyCZkVPHGYpcCJ52ek4U/ymZyfuV1nKE23AyBJ51E/6Yr0mhZ7xGTO4ag==",
       "license": "BSD-3-Clause",
       "dependencies": {
         "tslib": "2.3.0"

+ 1 - 1
package.json

@@ -17,7 +17,7 @@
     "@element-plus/icons-vue": "^2.3.1",
     "@vueuse/core": "^12.0.0",
     "axios": "^1.7.9",
-    "echarts": "^5.5.1",
+    "echarts": "^5.6.0",
     "element-plus": "^2.9.0",
     "pinia": "^2.2.6",
     "video.js": "^8.21.0",

+ 169 - 4
src/views/zhhj/bjcx.vue

@@ -1,11 +1,176 @@
-<script setup lang="ts">
-
-</script>
-
 <template>
+  <div class="alarm-container">
+    <el-card class="query-card">
+      <template #header>
+        <span>查询条件</span>
+      </template>
+      <el-form :inline="true" :model="queryForm" class="demo-form-inline">
+        <el-form-item label="时间范围">
+          <el-date-picker
+            v-model="queryForm.dateRange"
+            type="datetimerange"
+            range-separator="至"
+            start-placeholder="开始日期"
+            end-placeholder="结束日期"
+            format="YYYY-MM-DD HH:mm:ss"
+            value-format="YYYY-MM-DD HH:mm:ss"
+          />
+        </el-form-item>
+        <el-form-item label="组织">
+          <el-select v-model="queryForm.organization" placeholder="请选择组织">
+            <el-option label="园区A" value="parkA"></el-option>
+            <el-option label="园区B" value="parkB"></el-option>
+            <!-- 根据实际需求添加更多选项 -->
+          </el-select>
+        </el-form-item>
+        <el-form-item label="报警状态">
+          <el-select v-model="queryForm.alarmStatus" placeholder="请选择报警状态">
+            <el-option label="已处理" value="handled"></el-option>
+            <el-option label="未处理" value="unhandled"></el-option>
+            <!-- 根据实际需求添加更多选项 -->
+          </el-select>
+        </el-form-item>
+        <el-form-item label="报警等级">
+          <el-select v-model="queryForm.alarmLevel" placeholder="请选择报警等级">
+            <el-option label="低" value="low"></el-option>
+            <el-option label="中" value="medium"></el-option>
+            <el-option label="高" value="high"></el-option>
+            <!-- 根据实际需求添加更多选项 -->
+          </el-select>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="fetchData">查询</el-button>
+        </el-form-item>
+      </el-form>
+    </el-card>
 
+    <!-- 报警记录表格 -->
+    <el-card class="records-card">
+      <template #header>
+        <span>报警记录</span>
+      </template>
+      <el-table :data="alarms" style="width: 100%">
+        <el-table-column prop="timestamp" label="时间"></el-table-column>
+        <el-table-column prop="organization" label="组织"></el-table-column>
+        <el-table-column prop="status" label="报警状态"></el-table-column>
+        <el-table-column prop="level" label="报警等级"></el-table-column>
+        <el-table-column prop="description" label="描述"></el-table-column>
+      </el-table>
+    </el-card>
+
+    <!-- 统计结果展示区 -->
+    <el-card class="statistics-card">
+      <template #header>
+        <span>统计结果</span>
+      </template>
+      <div id="chart" style="width: 100%; height: 400px;"></div>
+    </el-card>
+  </div>
 </template>
 
+<script setup>
+import { ref, onMounted } from 'vue'
+import axios from 'axios'
+import * as echarts from 'echarts'
+
+// 查询表单的数据模型
+const queryForm = ref({
+  dateRange: [],
+  organization: '',
+  alarmStatus: '',
+  alarmLevel: ''
+})
+
+// 报警记录列表
+const alarms = ref([])
+
+// 图表实例
+let chartInstance = null
+
+// 初始化图表
+const initChart = () => {
+  const dom = document.getElementById('chart')
+
+  chartInstance = echarts.init(dom)
+  const option = {
+    title: {
+      text: '动环报警数据统计'
+    },
+    tooltip: {
+      trigger: 'axis'
+    },
+    legend: {
+      data: ['报警次数']
+    },
+    xAxis: {
+      type: 'category',
+      boundaryGap: false,
+      data: []
+    },
+    yAxis: {
+      type: 'value'
+    },
+    series: [
+      {
+        name: '报警次数',
+        type: 'line',
+        data: []
+      }
+    ]
+  }
+  chartInstance.setOption(option)
+}
+
+// 模拟获取数据的函数
+const fetchData = async () => {
+  try {
+    // 构建查询参数
+    const params = {
+      startTime: queryForm.value.dateRange[0],
+      endTime: queryForm.value.dateRange[1],
+      organization: queryForm.value.organization,
+      status: queryForm.value.alarmStatus,
+      level: queryForm.value.alarmLevel
+    }
+
+    const response = await axios.get('https://api.example.com/alarm-data', { params }) // 替换为实际API地址
+    const data = response.data
+
+    // 更新报警记录列表
+    alarms.value = data.records
+
+    // 更新图表数据
+    updateChartData(data.statistics)
+  } catch (error) {
+    console.error('Error fetching data:', error)
+  }
+}
+
+// 更新图表数据
+const updateChartData = (statistics) => {
+  if (!chartInstance) return
+
+  // 假设返回的数据结构是 { timestamps: ["2023-01-01", "2023-01-02"], counts: [5, 3] }
+  const timestamps = statistics.timestamps
+  const countData = statistics.counts
+
+  chartInstance.setOption({
+    xAxis: { data: timestamps },
+    series: [{ data: countData }]
+  })
+}
+
+onMounted(() => {
+  initChart()
+})
+</script>
+
 <style scoped>
+.alarm-container {
+  padding: 20px;
+}
 
+.query-card, .records-card, .statistics-card {
+  margin-bottom: 20px;
+}
 </style>

+ 143 - 5
src/views/zhhj/bjjbpz.vue

@@ -1,11 +1,149 @@
-<script setup lang="ts">
-
-</script>
-
 <template>
-ghdftyytdfhn
+  <div class="alarm-level-container">
+    <el-card class="config-card">
+      <template #header>
+        <span>报警级别配置</span>
+      </template>
+      <el-form :model="levelForm" label-width="100px">
+        <el-table :data="levels" style="width: 100%" border>
+          <el-table-column prop="name" label="级别名称" width="180">
+            <template #default="scope">
+              <el-input v-if="scope.row.editable" v-model="scope.row.name"></el-input>
+              <span v-else>{{ scope.row.name }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="priority" label="优先级" width="180">
+            <template #default="scope">
+              <el-input-number v-if="scope.row.editable" v-model="scope.row.priority" :min="1"></el-input-number>
+              <span v-else>{{ scope.row.priority }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="操作">
+            <template #default="scope">
+              <el-button
+                v-if="!scope.row.editable"
+                type="primary"
+                size="mini"
+                @click="editLevel(scope.$index)"
+              >编辑</el-button>
+              <el-button
+                v-else
+                type="success"
+                size="mini"
+                @click="saveLevel(scope.$index)"
+              >保存</el-button>
+              <el-button
+                type="danger"
+                size="mini"
+                @click="removeLevel(scope.$index)"
+              >删除</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+
+        <!-- 添加新级别 -->
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="新级别名称">
+              <el-input v-model="levelForm.newName"></el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <el-form-item label="优先级">
+              <el-input-number v-model="levelForm.newPriority" :min="1"></el-input-number>
+            </el-form-item>
+          </el-col>
+          <el-col :span="6">
+            <el-button type="primary" @click="addLevel">添加</el-button>
+          </el-col>
+        </el-row>
+      </el-form>
+    </el-card>
+  </div>
 </template>
 
+<script setup>
+import { ref, onMounted } from 'vue'
+import axios from 'axios'
+
+// 报警级别表单的数据模型
+const levelForm = ref({
+  newName: '',
+  newPriority: 1
+})
+
+// 默认报警级别列表
+const levels = ref([
+  { name: '低', priority: 1, editable: false },
+  { name: '中', priority: 2, editable: false },
+  { name: '高', priority: 3, editable: false },
+  { name: '紧急', priority: 4, editable: false }
+])
+
+// 编辑报警级别
+const editLevel = (index) => {
+  levels.value[index].editable = true
+}
+
+// 保存报警级别
+const saveLevel = (index) => {
+  // 在这里处理保存逻辑,例如发送到服务器更新数据
+  console.log('保存级别:', levels.value[index])
+  levels.value[index].editable = false
+}
+
+// 删除报警级别
+const removeLevel = async (index) => {
+  try {
+    const confirmDelete = await ElMessageBox.confirm(
+      '确定要删除此报警级别吗?',
+      '警告',
+      {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }
+    )
+    if (confirmDelete === 'confirm') {
+      // 在这里处理删除逻辑,例如发送到服务器删除数据
+      console.log('删除级别:', levels.value[index])
+      levels.value.splice(index, 1)
+    }
+  } catch (error) {
+    console.error('删除操作被取消或发生错误:', error)
+  }
+}
+
+// 添加新报警级别
+const addLevel = () => {
+  if (levelForm.value.newName && levelForm.value.newPriority) {
+    levels.value.push({
+      name: levelForm.value.newName,
+      priority: levelForm.value.newPriority,
+      editable: false
+    })
+    // 清空输入框
+    levelForm.value.newName = ''
+    levelForm.value.newPriority = 1
+  } else {
+    ElMessage({
+      message: '请填写完整的报警级别信息',
+      type: 'warning'
+    })
+  }
+}
+
+onMounted(() => {
+  // 如果需要从服务器加载初始数据,可以在这里调用API
+})
+</script>
+
 <style scoped>
+.alarm-level-container {
+  padding: 20px;
+}
 
+.config-card {
+  margin-bottom: 20px;
+}
 </style>

+ 105 - 5
src/views/zhhj/bjld.vue

@@ -1,11 +1,111 @@
-<script setup lang="ts">
-
-</script>
-
 <template>
-gfhdfhthfdhfd
+  <div class="alarm-linkage-container">
+    <!-- 告警信息表格 -->
+    <el-card class="alarms-card">
+      <template #header>
+        <span>告警信息</span>
+      </template>
+      <el-table :data="alarms" style="width: 100%" @row-click="handleRowClick">
+        <el-table-column prop="timestamp" label="时间"></el-table-column>
+        <el-table-column prop="location" label="位置"></el-table-column>
+        <el-table-column prop="description" label="描述"></el-table-column>
+        <el-table-column prop="status" label="状态"></el-table-column>
+        <el-table-column prop="level" label="等级"></el-table-column>
+      </el-table>
+    </el-card>
+
+    <!-- 视频播放区 -->
+    <el-card class="video-card" v-if="selectedAlarm">
+      <template #header>
+        <span>{{ selectedAlarm.location }} - {{ selectedAlarm.timestamp }}</span>
+      </template>
+      <video-player
+        class="vjs-custom-skin"
+        ref="videoPlayer"
+        :options="playerOptions"
+        @ready="onPlayerReady"
+      ></video-player>
+    </el-card>
+  </div>
 </template>
 
+<script setup>
+import { ref, onMounted } from 'vue'
+import axios from 'axios'
+
+// 默认告警信息列表
+const alarms = ref([
+  // 模拟数据,实际应用中应从API获取
+])
+
+// 当前选择的告警信息
+const selectedAlarm = ref(null)
+
+// 视频播放器配置
+const playerOptions = ref({
+  playbackRates: [0.7, 1.0, 1.5, 2.0], // 播放速度
+  autoplay: false,
+  muted: false,
+  loop: false,
+  preload: 'auto',
+  language: 'zh-CN',
+  aspectRatio: '16:9',
+  fluid: true,
+  sources: [
+    {
+      type: "video/mp4",
+      src: "" // 默认为空,将在点击行时设置
+    }
+  ],
+  poster: "", // 视频封面图
+  notSupportedMessage: '此视频暂无法播放,请稍后再试',
+  controlBar: {
+    timeDivider: true,
+    durationDisplay: true,
+    remainingTimeDisplay: false,
+    fullscreenToggle: true // 全屏按钮
+  }
+})
+
+// 模拟获取数据的函数
+const fetchData = async () => {
+  try {
+    const response = await axios.get('https://api.example.com/alarm-data') // 替换为实际API地址
+    alarms.value = response.data
+  } catch (error) {
+    console.error('Error fetching alarm data:', error)
+  }
+}
+
+// 处理表格行点击事件
+const handleRowClick = (row) => {
+  selectedAlarm.value = row
+  playerOptions.value.sources[0].src = row.videoUrl // 设置视频源
+}
+
+// 当播放器准备就绪时触发
+const onPlayerReady = (player) => {
+  console.log('player is ready', player)
+}
+
+onMounted(() => {
+  fetchData()
+})
+</script>
+
 <style scoped>
+.alarm-linkage-container {
+  padding: 20px;
+  display: flex;
+  flex-direction: column;
+}
+
+.alarms-card, .video-card {
+  margin-bottom: 20px;
+}
 
+.vjs-custom-skin {
+  width: 100%;
+  height: 360px;
+}
 </style>

+ 118 - 4
src/views/zhhj/ccclpz.vue

@@ -1,11 +1,125 @@
-<script setup lang="ts">
+<template>
+  <div class="data-retention-container">
+    <el-card class="config-card">
+      <template #header>
+        <span>数据保留配置</span>
+      </template>
+      <el-form :model="configForm" label-width="150px" :rules="rules" ref="ruleForm">
+        <!-- 最长存储时间 -->
+        <el-form-item label="监测数据最长存储时间 (天)" prop="maxStorageDays">
+          <el-input-number v-model="configForm.maxStorageDays" :min="1"></el-input-number>
+        </el-form-item>
 
-</script>
+        <!-- 报警数据最长存储时间 -->
+        <el-form-item label="报警数据最长存储时间 (天)" prop="alarmMaxStorageDays">
+          <el-input-number v-model="configForm.alarmMaxStorageDays" :min="1"></el-input-number>
+        </el-form-item>
 
-<template>
-hdhythujnbcv
+        <!-- 统计时间间隔 -->
+        <el-form-item label="统计时间间隔 (分钟)" prop="statisticalInterval">
+          <el-input-number v-model="configForm.statisticalInterval" :min="1"></el-input-number>
+        </el-form-item>
+
+        <!-- 差异存储参数 -->
+        <el-form-item label="差异存储参数 (%)">
+          <el-input-number v-model="configForm.variationThreshold" :min="0" :max="100"></el-input-number>
+        </el-form-item>
+
+        <!-- 保存按钮 -->
+        <el-form-item>
+          <el-button type="primary" @click="submitForm">保存设置</el-button>
+        </el-form-item>
+      </el-form>
+    </el-card>
+
+    <!-- 日志信息 -->
+    <el-card class="log-card">
+      <template #header>
+        <span>操作日志</span>
+      </template>
+      <el-timeline>
+        <el-timeline-item v-for="(log, index) in logs" :key="index" :timestamp="log.timestamp">
+          {{ log.message }}
+        </el-timeline-item>
+      </el-timeline>
+    </el-card>
+  </div>
 </template>
 
+<script setup>
+import { ref, reactive, onMounted } from 'vue'
+import axios from 'axios'
+import ElMessage from 'element-plus'
+
+// 表单验证规则
+const rules = reactive({
+  maxStorageDays: [{ required: true, message: '请输入最长存储时间', trigger: 'blur' }],
+  alarmMaxStorageDays: [{ required: true, message: '请输入报警数据最长存储时间', trigger: 'blur' }],
+  statisticalInterval: [{ required: true, message: '请输入统计时间间隔', trigger: 'blur' }],
+  variationThreshold: [{ required: true, message: '请输入差异存储参数', trigger: 'blur' }]
+})
+
+// 数据保留配置表单的数据模型
+const configForm = reactive({
+  maxStorageDays: 30,
+  alarmMaxStorageDays: 60,
+  statisticalInterval: 5,
+  variationThreshold: 5
+})
+
+// 操作日志
+const logs = ref([])
+
+// 表单引用
+const ruleForm = ref(null)
+
+// 提交表单
+const submitForm = () => {
+  ElMessage({
+    message: '配置已成功保存',
+    type: 'success'
+  })
+  ruleForm.value.validate(async (valid) => {
+
+    //   if (valid) {
+    //     try {
+    //       // 模拟提交配置到服务器
+    //       // await axios.post('https://api.example.com/configure-data-retention', configForm)
+    //       // ElMessage({
+    //       //   message: '配置已成功保存',
+    //       //   type: 'success'
+    //       // })
+    //       // 添加成功日志
+    //       // addLog('配置已成功保存')
+    //     // } catch (error) {
+    //       // console.error('Error saving configuration:', error)
+    //       // ElMessage.error('保存配置时出错')
+    //     // }
+    //   // } else {
+    //   //   console.log('表单验证失败')
+    //   //   return false
+    //   // }
+  })
+}
+
+// 添加日志条目
+const addLog = (message) => {
+  const timestamp = new Date().toLocaleString()
+  logs.value.unshift({ message, timestamp })
+}
+
+onMounted(() => {
+  // 如果需要从服务器加载初始配置,可以在这里调用API
+})
+</script>
+
 <style scoped>
+.data-retention-container {
+  padding: 20px;
+}
 
+.config-card,
+.log-card {
+  margin-bottom: 20px;
+}
 </style>

+ 126 - 4
src/views/zhhj/pzpcyz.vue

@@ -1,11 +1,133 @@
-<script setup lang="ts">
+<template>
+  <div class="data-threshold-container">
+    <el-card class="config-card">
+      <template #header>
+        <span>动环主机及采集数据类型配置</span>
+      </template>
 
-</script>
+      <!-- 主机选择 -->
+      <el-form :model="form" label-width="150px">
+        <el-form-item label="选择动环主机">
+          <el-select v-model="form.selectedHost" placeholder="请选择动环主机">
+            <el-option
+              v-for="host in hosts"
+              :key="host.id"
+              :label="host.name"
+              :value="host.id"
+            />
+          </el-select>
+        </el-form-item>
 
-<template>
-dghdhthdftd
+        <!-- 动态显示选定主机的数据类型 -->
+        <div v-if="selectedHostConfig">
+          <el-form-item
+            v-for="(dataType, index) in selectedHostConfig.dataTypes"
+            :key="index"
+            :label="`${dataType.name} 偏差阈值`"
+          >
+            <el-input-number
+              v-model="dataType.threshold"
+              :min="0"
+              placeholder="设置偏差阈值"
+            ></el-input-number>
+          </el-form-item>
+        </div>
+
+        <!-- 保存按钮 -->
+        <el-form-item>
+          <el-button type="primary" @click="saveConfig">保存配置</el-button>
+        </el-form-item>
+      </el-form>
+
+      <!-- 操作日志 -->
+      <el-card class="log-card">
+        <template #header>
+          <span>操作日志</span>
+        </template>
+        <el-timeline>
+          <el-timeline-item
+            v-for="(log, index) in logs"
+            :key="index"
+            :timestamp="log.timestamp"
+          >
+            {{ log.message }}
+          </el-timeline-item>
+        </el-timeline>
+      </el-card>
+    </el-card>
+  </div>
 </template>
 
+<script setup>
+import { ref, reactive, computed, onMounted } from 'vue'
+import axios from 'axios'
+import ElMessageBox from 'element-plus'
+import ElMessage from 'element-plus'
+
+// 默认动环主机列表(实际应用中应从API获取)
+const hosts = ref([
+  { id: 1, name: '主机A', dataTypes: [{ name: '温度', threshold: 5 }, { name: '湿度', threshold: 3 }] },
+  { id: 2, name: '主机B', dataTypes: [{ name: '电压', threshold: 2 }, { name: '电流', threshold: 1 }] }
+])
+
+// 表单模型
+const form = reactive({
+  selectedHost: null,
+})
+
+// 根据所选主机动态计算其数据类型配置
+const selectedHostConfig = computed(() => {
+  return hosts.value.find(host => host.id === form.selectedHost)
+})
+
+// 操作日志
+const logs = ref([])
+
+// 提交表单
+const saveConfig = async () => {
+  if (!form.selectedHost || !selectedHostConfig.value) {
+    ElMessage.warning('请先选择动环主机')
+    return
+  }
+
+  try {
+    // 模拟提交配置到服务器
+    await axios.post('https://api.example.com/configure-thresholds', {
+      hostId: form.selectedHost,
+      dataTypes: selectedHostConfig.value.dataTypes.map(dt => ({
+        name: dt.name,
+        threshold: dt.threshold
+      }))
+    })
+    ElMessage({
+      message: '配置已成功保存',
+      type: 'success'
+    })
+    // 添加成功日志
+    addLog('配置已成功保存')
+  } catch (error) {
+    console.error('Error saving configuration:', error)
+    ElMessage.error('保存配置时出错')
+  }
+}
+
+// 添加日志条目
+const addLog = (message) => {
+  const timestamp = new Date().toLocaleString()
+  logs.value.unshift({ message, timestamp })
+}
+
+onMounted(() => {
+  // 如果需要从服务器加载初始配置,可以在这里调用API
+})
+</script>
+
 <style scoped>
+.data-threshold-container {
+  padding: 20px;
+}
 
+.config-card, .log-card {
+  margin-bottom: 20px;
+}
 </style>

+ 178 - 5
src/views/zhhj/sjcx.vue

@@ -1,11 +1,184 @@
-<script setup lang="ts">
-
-</script>
-
 <template>
-kjlhjpoh[;o;jh
+  <div class="history-container">
+    <el-card class="query-card">
+      <template #header>
+        <span>查询条件</span>
+      </template>
+      <el-form :inline="true" :model="queryForm" class="demo-form-inline">
+        <el-form-item label="时间范围">
+          <el-date-picker
+            v-model="queryForm.dateRange"
+            type="datetimerange"
+            range-separator="至"
+            start-placeholder="开始日期"
+            end-placeholder="结束日期"
+            format="YYYY-MM-DD HH:mm:ss"
+            value-format="YYYY-MM-DD HH:mm:ss"
+          />
+        </el-form-item>
+        <el-form-item label="组织">
+          <el-select v-model="queryForm.organization" placeholder="请选择组织">
+            <el-option label="园区A" value="parkA"></el-option>
+            <el-option label="园区B" value="parkB"></el-option>
+            <!-- 根据实际需求添加更多选项 -->
+          </el-select>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="fetchData">查询</el-button>
+        </el-form-item>
+      </el-form>
+    </el-card>
+
+    <!-- 统计结果展示区 -->
+    <el-card class="statistics-card">
+      <template #header>
+        <span>统计结果</span>
+      </template>
+      <div id="chart" style="width: 100%; height: 400px;"></div>
+    </el-card>
+  </div>
 </template>
 
+<script setup>
+import { ref, onMounted } from 'vue'
+import axios from 'axios'
+import * as echarts from 'echarts'
+
+// 查询表单的数据模型
+const queryForm = ref({
+  dateRange: [],
+  organization: ''
+})
+
+// 图表实例
+let chartInstance = null
+
+// 初始化图表
+const initChart = () => {
+  const dom = document.getElementById('chart')
+  chartInstance = echarts.init(dom)
+  const option = {
+    title: {
+      text: '动环历史数据统计'
+    },
+    tooltip: {
+      trigger: 'axis'
+    },
+    legend: {
+      data: ['温度', '湿度', '噪声', '风速', '风向', 'PM2.5', '粉尘']
+    },
+    xAxis: {
+      type: 'category',
+      boundaryGap: false,
+      data: []
+    },
+    yAxis: {
+      type: 'value'
+    },
+    series: [
+      {
+        name: '温度',
+        type: 'line',
+        data: []
+      },
+      {
+        name: '湿度',
+        type: 'line',
+        data: []
+      },
+      {
+        name: '噪声',
+        type: 'line',
+        data: []
+      },
+      {
+        name: '风速',
+        type: 'line',
+        data: []
+      },
+      {
+        name: '风向',
+        type: 'line',
+        data: []
+      },
+      {
+        name: 'PM2.5',
+        type: 'line',
+        data: []
+      },
+      {
+        name: '粉尘',
+        type: 'line',
+        data: []
+      }
+    ]
+  }
+  chartInstance.setOption(option)
+}
+
+// 模拟获取数据的函数
+const fetchData = async () => {
+  try {
+    // 构建查询参数
+    const params = {
+      startTime: queryForm.value.dateRange[0],
+      endTime: queryForm.value.dateRange[1],
+      organization: queryForm.value.organization
+    }
+
+    const response = await axios.get('https://api.example.com/history-data', { params }) // 替换为实际API地址
+    const data = response.data
+
+    // 更新图表数据
+    updateChartData(data)
+  } catch (error) {
+    console.error('Error fetching data:', error)
+  }
+}
+
+// 更新图表数据
+const updateChartData = (data) => {
+  if (!chartInstance) return
+
+  // 假设返回的数据结构是 [{ timestamp: "2023-01-01 12:00:00", temperature: 20, humidity: 60, ... }, ...]
+  const timestamps = data.map(item => item.timestamp)
+  const temperatureData = data.map(item => item.temperature)
+  const humidityData = data.map(item => item.humidity)
+  const noiseData = data.map(item => item.noise)
+  const windSpeedData = data.map(item => item.windSpeed)
+  const windDirectionData = data.map(item => item.windDirection)
+  const pm25Data = data.map(item => item.pm25)
+  const dustData = data.map(item => item.dust)
+
+  chartInstance.setOption({
+    xAxis: { data: timestamps },
+    series: [
+      { data: temperatureData },
+      { data: humidityData },
+      { data: noiseData },
+      { data: windSpeedData },
+      { data: windDirectionData },
+      { data: pm25Data },
+      { data: dustData }
+    ]
+  })
+}
+
+onMounted(() => {
+  initChart()
+})
+</script>
+
 <style scoped>
+.history-container {
+  padding: 20px;
+}
+
+.query-card {
+  margin-bottom: 20px;
+}
 
+.statistics-card {
+  width: 100%;
+}
 </style>

+ 118 - 5
src/views/zhhj/ssjc.vue

@@ -1,12 +1,125 @@
-<script setup lang="ts">
+<template>
+  <div class="monitor-container">
+    <el-card v-for="(sensor, index) in sensors" :key="index" class="sensor-card">
+      <template #header>
+        <div class="card-header">
+          <span>{{ sensor.name }}</span>
+        </div>
+      </template>
+      <div class="text item">{{ sensor.value }} {{ sensor.unit }}</div>
+    </el-card>
 
-window.open('https://172.16.102.27:8088/')
-</script>
+    <!-- 添加一个按钮用于手动刷新数据 -->
+    <el-button type="primary" @click="fetchData">刷新数据</el-button>
 
-<template>
-<!--<iframe class="w-full h-90vh" src="https://172.16.102.27:8088/" />-->
+    <!-- 添加一个图表区域用于展示历史数据 -->
+    <div id="chart" style="width: 600px; height: 400px;"></div>
+  </div>
 </template>
 
+<script setup>
+import { ref, onMounted, watch } from 'vue'
+import axios from 'axios'
+import * as echarts from 'echarts'
+
+// 模拟的初始传感器数据
+const sensors = ref([
+  { name: '温度', value: '--', unit: '°C' },
+  { name: '湿度', value: '--', unit: '%' },
+  { name: '噪声', value: '--', unit: 'dB' },
+  { name: '风速', value: '--', unit: 'm/s' },
+  { name: '风向', value: '--', unit: '°' },
+  { name: 'PM2.5', value: '--', unit: 'μg/m³' },
+  { name: '粉尘', value: '--', unit: 'μg/m³' }
+])
+
+// 图表实例
+let chartInstance = null
+
+// 初始化图表
+const initChart = () => {
+  const dom = document.getElementById('chart')
+  chartInstance = echarts.init(dom)
+  const option = {
+    title: {
+      text: '历史数据图表'
+    },
+    tooltip: {
+      trigger: 'axis'
+    },
+    xAxis: {
+      type: 'category',
+      data: [1,2,3,4,5,6,7,]
+    },
+    yAxis: {
+      type: 'value'
+    },
+    series: [
+      {
+        name: '温度',
+        type: 'line',
+        data: [1,2,3,4,5,6,7,]
+      }
+      // 根据需要添加更多系列
+    ]
+  }
+  chartInstance.setOption(option)
+}
+
+// 模拟获取数据的函数
+const fetchData = async () => {
+  try {
+    const response = await axios.get('https://api.example.com/iot-data') // 替换为实际API地址
+    const newData = response.data.sensors
+
+    // 更新传感器数据
+    sensors.value.forEach((sensor, index) => {
+      if (newData[index]) {
+        sensor.value = newData[index].value
+      }
+    })
+
+    // 更新图表数据
+    updateChartData(newData)
+  } catch (error) {
+    console.error('Error fetching data:', error)
+  }
+}
+
+// 更新图表数据
+const updateChartData = (data) => {
+  if (!chartInstance) return
+
+  const xData = data.map(item => new Date().toLocaleTimeString())
+  const yData = data.map(item => item.value)
+
+  chartInstance.setOption({
+    xAxis: { data: xData },
+    series: [{ data: yData }]
+  })
+}
+
+onMounted(() => {
+  initChart()
+  fetchData()
+
+  // 设定定时器每分钟更新一次数据
+  setInterval(fetchData, 60000)
+})
+
+watch(sensors, () => {
+  // 当传感器数据变化时,可以执行额外操作,如更新UI或日志记录
+}, { deep: true })
+</script>
+
 <style scoped>
+.monitor-container {
+  display: flex;
+  flex-wrap: wrap;
+}
 
+.sensor-card {
+  width: calc(33.333% - 20px);
+  margin: 10px;
+}
 </style>