Просмотр исходного кода

[Feat 0000]皮带巷需求整改

bobo04052021@163.com 1 неделя назад
Родитель
Сommit
b1efbb98c6

+ 1 - 1
src/views/vent/deviceManager/comment/DeviceModalLeather.vue

@@ -47,7 +47,7 @@
       <a-tab-pane key="12" tab="关联报表" v-if="deviceType == 'managesys'">
         <WorkFaceReportTable :columns="reportColumns" :device="deviceData" />
       </a-tab-pane>
-      <a-tab-pane v-if="deviceType == 'managesys'" key="4" tab="预警条目管理">
+      <a-tab-pane key="4" tab="预警条目管理">
         <ManagerWarningDeviceTable v-if="activeKey == '4'" :deviceId="deviceData.id" />
       </a-tab-pane>
       <a-tab-pane key="5" :tab="deviceType !== 'managesys' ? '点位(报警)配置' : '配置预警设备'">

+ 43 - 0
src/views/vent/deviceManager/comment/warningTabel/warning.data.ts

@@ -329,6 +329,16 @@ export const workFaceWarningFormSchemasLeather: FormSchema[] = [
     field: 'partNum',
     component: 'Input',
   },
+  {
+    label: '预警后自动控制等待时间',
+    field: 'controlWaitTime',
+    component: 'Input',
+  },
+  {
+    label: '预警解除后自动复位等待时间',
+    field: 'resetWaitTime',
+    component: 'Input',
+  },
   {
     label: '处理意见',
     field: 'dealOpinion',
@@ -386,6 +396,24 @@ export const deviceFormColumns: FormSchema[] = [
     component: 'InputNumber',
     colProps: { span: 12 },
   },
+  {
+    label: '数据趋势持续时间单位',
+    field: 'trendCxTimeUnit',
+    component: 'Input',
+    colProps: { span: 12 },
+  },
+  {
+    label: '持续范围下限值',
+    field: 'trendMin',
+    component: 'InputNumber',
+    colProps: { span: 12 },
+  },
+  {
+    label: '持续范围上限值',
+    field: 'trendMax',
+    component: 'InputNumber',
+    colProps: { span: 12 },
+  },
 ];
 export const deviceControlColumns: FormSchema[] = [
   {
@@ -647,6 +675,21 @@ export const monitorWarningFormSchemas = (param) =>
       field: 'trendCxTime',
       component: 'InputNumber',
     },
+    // {
+    //   label: '数据趋势持续时间单位',
+    //   field: 'trendCxTimeUnit',
+    //   component: 'Input',
+    // },
+    // {
+    //   label: '持续范围下限值',
+    //   field: 'trendMin',
+    //   component: 'InputNumber',
+    // },
+    // {
+    //   label: '持续范围上限值',
+    //   field: 'trendMax',
+    //   component: 'InputNumber',
+    // },
   ];
 
 export const controlWarningFormSchemas: FormSchema[] = [

+ 1 - 1
src/views/vent/deviceManager/workingFace/CustomNormalTable.vue

@@ -231,7 +231,7 @@ function handleEdit(data) {
   console.log(data, '----');
   isUpdate.value = true;
   Object.assign(record, toRaw(data));
-  if (data.strtype === 'sys_maintunnel_leather') {
+  if (data.strtype === 'sys_Leather') {
     openModalLeather(true, { record }, false);
   } else {
     openModal(true, { record }, false);

+ 44 - 17
src/views/vent/home/configurable/belt/belt-new.vue

@@ -6,6 +6,7 @@
       :options="options"
       :optionValue="optionValue"
       @change="changeSelectRow"
+      @open-history="goToHistory"
     >
       矿井全域皮带巷三级防灭火系统
     </customHeader>
@@ -47,9 +48,10 @@ import ModuleCommon from './components/ModuleCommon.vue';
 import Three3D from '/@/views/vent/home/configurable/components/three3D.vue';
 import BeltNav from './components/BeltNav.vue';
 import { useRouter, useRoute } from 'vue-router';
-import { getSystem, getMonitorAndAlertBelt, getDevice, getDataHome } from './configurable.api';
+import { getSystem, getMonitorAndAlertBelt, getDevice, getDataHome, getWarnResult } from './configurable.api';
 import { modalAnimate } from './threejs/belt.threejs';
 import History from './components/detail/history.vue';
+import sys from '/@/locales/lang/en/sys';
 // 初始化配置
 const { configs, fetchConfigs } = useInitConfigs();
 const { updateEnhancedConfigs, updateData, data } = useInitPage('矿井全域皮带巷三级防灭火系统');
@@ -70,9 +72,10 @@ const optionValue = ref('');
 async function getSysDataSource() {
   const res = await getDataHome({ dataList: 'risk_evaluator' }).catch(() => {});
   options.value = res.risk_evaluator || [];
-  // 初始时选择第一条数据
-  if (!optionValue.value) {
-    changeSelectRow(options.value[0]['sys_id']);
+  await nextTick();
+  if (options.value.length > 0 && !optionValue.value) {
+    const firstId = options.value[0].sys_id;
+    changeSelectRow(firstId);
   }
 }
 // 切换检测数据
@@ -80,6 +83,15 @@ function changeSelectRow(deviceID) {
   optionValue.value = deviceID;
   // getDeviceList();
 }
+function goToHistory() {
+  if (pageType.value === 'history') {
+    // 当前是历史页 → 切回默认页
+    pageType.value = 'fire_risk_warn';
+  } else {
+    // 当前不是 → 打开历史页
+    pageType.value = 'history';
+  }
+}
 // 刷新数据
 async function refresh() {
   // await fetchConfigs('sys_Leather');
@@ -87,7 +99,7 @@ async function refresh() {
   //   if (pageType.value === 'fire_risk_warn') {
   //     configs.value = testBeltNew;
   //     const res = await getMonitorAndAlertBelt({
-  //       sysId: '1637983899775242242',
+  //       sysId: '2028657172566073346',
   //       dataList: 'fire_risk_warn,warn_result,vehicle_co_correlate',
   //     });
   //     updateData(res);
@@ -95,7 +107,7 @@ async function refresh() {
   //     configs.value = testYjkf;
   //     const res = await getSystem({
   //       devicetype: 'sys',
-  //       systemID: '1637983899775242242',
+  //       systemID: '2028657172566073346',
   //       type: 'ventS',
   //     });
   //     updateData(res);
@@ -129,48 +141,63 @@ async function refresh() {
   const modalRes = {};
   const systemParams = {
     devicetype: 'sys',
-    systemID: '1637983899775242242',
-    type: 'ventS',
+    systemID: '2028657172566073346',
   };
   const resSys = await getSystem(systemParams);
   Object.assign(modalRes, resSys);
   if (pageType.value == 'fire_risk_warn') {
     configs.value = [...testBeltNew];
     const params = {
-      sysId: '1637983899775242242',
+      // sysId: optionValue.value,
+      sysId: '2028657172566073346',
       dataList: 'fire_risk_warn,warn_result,vehicle_co_correlate',
+      alarmLevel: '102,103,104',
     };
     const resWarn = await getMonitorAndAlertBelt(params);
     updateData(resWarn);
     Object.assign(modalRes, resWarn);
   } else if (pageType.value == 'emergencyControl') {
-    //
     updateData(resSys);
     configs.value = [...testYjkf];
+    const alarmParams = {
+      sysId: '2028657172566073346',
+      alarmLevel: '104',
+    };
+    const alarmRes = await getWarnResult(alarmParams);
+    if (alarmRes.warn_result) {
+      data.value.warn_result = alarmRes.warn_result;
+    }
+    updateData(data.value);
   } else if (pageType.value == 'sprayControl') {
     const params = {
       devicetype: 'sys',
       systemID: '2028657172566073346',
     };
-    Promise.resolve(getDevice(params)).then((originalData) => {
+    const params1 = {
+      sysId: '2028657172566073346',
+      alarmLevel: '103,104',
+    };
+    Promise.all([getDevice(params), getWarnResult(params1)]).then(([originalData, alarmRes]) => {
       updateData(originalData);
       const sprayData: any[] = [];
       if (data.value?.msgTxt) {
         data.value.msgTxt.forEach((item) => {
           const hasSprayAuto = item.type && item.type.toLowerCase().includes('spray_auto');
           if (hasSprayAuto) {
-            sprayData.push({
-              ...item,
-              ...item.readData,
-            });
+            sprayData.push({ ...item, ...item.readData });
           }
         });
       }
       data.value.sprayData = sprayData;
+      if (alarmRes.warn_result) {
+        data.value.warn_result = alarmRes.warn_result;
+      } else {
+        console.log('❌ 没有获取到 warn_result');
+      }
       updateData(data.value);
     });
+
     configs.value = [...testSpary];
-    console.log(configs.value);
   } else {
     configs.value = testBeltNew;
   }
@@ -230,8 +257,8 @@ watch(
 );
 
 onMounted(async () => {
-  await refresh();
   await getSysDataSource();
+  await refresh();
   initInterval();
 });
 </script>

+ 23 - 15
src/views/vent/home/configurable/belt/belt.vue

@@ -2,23 +2,28 @@
 <template>
   <div class="company-home">
     <div class="border">
-      <customHeader>矿井全域皮带巷三级防灭火系统</customHeader>
+      <customHeader @open-history="goToHistory">矿井全域皮带巷三级防灭火系统</customHeader>
       <!-- <div class="test" style="width: 100%; height: 100%; position: absolute; left: 0; top: 0; z-index: 0"> -->
       <SubApp />
       <!-- </div> -->
       <div class="box-container">
-        <ModuleCommon
-          v-for="cfg in configs"
-          :key="cfg.deviceType"
-          :show-style="cfg.showStyle"
-          :module-data="cfg.moduleData"
-          :module-name="cfg.moduleName"
-          :device-type="cfg.deviceType"
-          :page-type="cfg.pageType"
-          :data="data"
-          :visible="true"
-          @clickItem="handleItemClick"
-        />
+        <template v-if="showHistory">
+          <History />
+        </template>
+        <template v-else>
+          <ModuleCommon
+            v-for="cfg in configs"
+            :key="cfg.deviceType"
+            :show-style="cfg.showStyle"
+            :module-data="cfg.moduleData"
+            :module-name="cfg.moduleName"
+            :device-type="cfg.deviceType"
+            :page-type="cfg.pageType"
+            :data="data"
+            :visible="true"
+            @clickItem="handleItemClick"
+          />
+        </template>
       </div>
       <!-- 巷道模型组件 -->
     </div>
@@ -31,7 +36,7 @@ import { useInitConfigs, useInitPage } from '../hooks/useInit';
 import { testBeltLaneFire } from './configurable.data';
 import ModuleCommon from './components/ModuleCommon.vue';
 import SubApp from '/@/components/vent/micro/createSubApp.vue';
-// import { BDFireMock } from './mock';
+import History from './components/detail/history.vue';
 import { getDataHome } from './configurable.api';
 const { configs, devicesTypes, fetchConfigs } = useInitConfigs();
 const { updateEnhancedConfigs, updateData, data } = useInitPage('矿井全域皮带巷三级防灭火系统');
@@ -288,12 +293,15 @@ const readData = ref({
 //   });
 // }
 let timer = null;
+const showHistory = ref(false);
 const handleItemClick = (data) => {
   const clickId = data.id;
   if (!clickId) return;
   filterDataById(clickId);
 };
-
+function goToHistory() {
+  showHistory.value = !showHistory.value;
+}
 // 抽离公共筛选方法,初始化 + 点击共用
 const filterDataById = (clickId: string | number) => {
   const source = readData.value;

+ 1 - 42
src/views/vent/home/configurable/belt/components/BeltNav.vue

@@ -14,33 +14,21 @@
         <span>{{ item.name }}</span>
       </div>
     </div>
-    <!-- 右侧圆形图标 -->
-    <!-- <div class="icon-right">
-      <div class="icon-circle">
-        <span class="icon" @click="openModal()">应急控制</span>
-      </div>
-    </div> -->
   </div>
-  <ConfirmModal v-model:visible="modalVisible" @handleCancel="handleCancel" @handleConfirm="handleConfirm" class="btn-confirm-modal"> </ConfirmModal>
 </template>
 
 <script setup lang="ts">
-import ConfirmModal from './confirmModal.vue';
-import { InputPassword } from 'ant-design-vue';
 import { ref, watch, onMounted } from 'vue';
 import { useRouter, useRoute } from 'vue-router';
 const emit = defineEmits(['changePage']);
 const props = defineProps({
   pageType: {
     type: String,
-    default: '',
+    default: 'fire_risk_warn',
   },
 });
 const router = useRouter(); // 获取路由实例
 const route = useRoute(); // 获取路由实例
-const password = ref('');
-const inputWarn = ref('密码错误请重新输入');
-const modalVisible = ref(false);
 // 当前激活菜单
 const activeType = ref('');
 activeType.value = (route.query.pageType as string) || props.pageType || '';
@@ -87,35 +75,6 @@ function handleNavClick(data) {
   activeType.value = pageType; // 点击立刻更新
   emit('changePage', pageType);
 }
-function pathClick() {
-  router.push('/micro-vent-3dModal/configurable/belt/fireS/home');
-}
-function openModal() {
-  modalVisible.value = !modalVisible.value;
-}
-const handleConfirm = async (password) => {
-  try {
-    console.log('用户输入的密码:', password);
-    await new Promise((resolve) => setTimeout(resolve, 500));
-    if (password === '123456') {
-      console.log('密码验证成功!');
-    } else {
-      throw new Error('密码错误,请重新输入');
-    }
-  } catch (error) {
-    return false;
-  }
-};
-
-/**
- * 处理弹窗取消回调
- */
-const handleCancel = () => {
-  console.log('关闭弹窗');
-  password.value = '';
-  inputWarn.value = '';
-  modalVisible.value = false;
-};
 </script>
 
 <style scoped lang="less">

+ 157 - 76
src/views/vent/home/configurable/belt/components/customHeader-belt.vue

@@ -1,97 +1,143 @@
 <template>
   <div class="vent-custom-header">
+    <!-- 顶部标题插槽 -->
     <div class="vent-home-header">
       <div class="header-text"><slot></slot></div>
     </div>
+
+    <!-- 左侧导航菜单 -->
     <div class="nav">
-      <div
-        v-for="(item, index) in menuList"
-        :key="index"
-        @click="handleNavClick(item)"
-        style="cursor: pointer"
-        class="nav-item"
-        :class="{ active: isActive(item.path) }"
-      >
+      <div v-for="(item, index) in menuList" :key="index" @click="handleNavClick(item)" class="nav-item" :class="{ active: isActive(item.path) }">
         <span>{{ item.name }}</span>
       </div>
     </div>
-    <div class="container-title" v-if="fieldNames">
+    <!-- 右侧历史数据 -->
+    <div class="history-nav">
+      <div @click="openModel()" class="nav-item" :class="{ active: visible }">
+        <span>历史数据</span>
+      </div>
+    </div>
+    <!-- 下拉选择器 -->
+    <div class="container-title" v-if="fieldNames && options.length">
       <a-select
         class="title-select"
-        ref="select"
+        ref="selectRef"
         v-model:value="currentTitleValue"
         @change="handleTitleChange"
-        dropdownClassName="drop"
+        dropdown-class-name="drop"
         :field-names="fieldNames"
         :options="options"
-        :dropdownStyle="{ background: 'transparent', borderBottom: '1px solid #ececec66', backdropFilter: 'blur(50px)', color: '#fff' }"
-      >
-      </a-select>
+        :dropdown-style="dropdownStyle"
+      />
     </div>
   </div>
+
+  <!-- 历史数据弹窗 -->
+  <!-- <History v-model:visible="visible" /> -->
 </template>
-<script lang="ts">
-import { defineComponent, computed, ref } from 'vue';
-import { Decoration5 } from '@kjgl77/datav-vue3';
+
+<script lang="ts" setup>
+import { computed, ref, watch } from 'vue';
 import { router } from '/@/router';
-export default defineComponent({
-  name: 'CustomHeader',
-  components: { Decoration5 },
-  props: {
-    optionValue: {
-      type: String,
-    },
-    fieldNames: {
-      type: Object,
-      default: () => {},
-    },
-    options: {
-      type: Array,
-      default: () => [],
-    },
-    Type: {
-      type: String,
-    },
+import History from './detail/history.vue';
+
+// 类型定义
+interface MenuItem {
+  name: string;
+  path: string;
+}
+interface FieldNames {
+  label?: string;
+  value?: string;
+  children?: string;
+}
+
+// Props
+const props = defineProps({
+  optionValue: {
+    type: String,
+    default: '',
   },
-  emits: ['change'],
-  setup(props, { emit }) {
-    const currentTitleValue = computed(() => props.optionValue);
-    const menuList = ref([
-      {
-        name: '首页',
-        path: '/micro-vent-3dModal/configurable/belt/fireS/home',
-      },
-      {
-        name: '详情监控页',
-        path: '/belt/fireS/home',
-      },
-      {
-        name: '灾变模拟分析',
-        path: '/micro-vent-3dModal/dashboard/analysis?type=sysMonitor&deviceType=sysfireTunnel&sysID=2028657172566073346&deviceid=2028650091184177153&sysType=leather',
-      },
-    ]);
-    function isActive(menuPath) {
-      const currentRoutePath = router.currentRoute.value.path;
-      const menuRoutePath = menuPath.split('?')[0];
-      return currentRoutePath.startsWith(menuRoutePath);
-    }
-    function handleNavClick(item) {
-      console.log('✅️点击', item.path);
-      router.push(item.path);
-    }
-    // 标题选择
-    function handleTitleChange(value) {
-      emit('change', value);
-    }
-    return {
-      currentTitleValue,
-      handleTitleChange,
-      menuList,
-      handleNavClick,
-      isActive,
-    };
+  fieldNames: {
+    type: Object as () => FieldNames,
+    default: () => ({}),
+  },
+  options: {
+    type: Array,
+    default: () => [],
+  },
+  Type: {
+    type: String,
+    default: '',
   },
 });
+
+// 自定义事件
+const emit = defineEmits<{
+  change: [value: string];
+  'open-history': [];
+}>();
+
+// 响应式数据
+const currentTitleValue = ref(props.optionValue);
+const visible = ref(false);
+const selectRef = ref(); // 选择器实例
+
+// 导航菜单配置
+const menuList: MenuItem[] = [
+  {
+    name: '首页',
+    path: '/micro-vent-3dModal/configurable/belt/fireS/home',
+  },
+  {
+    name: '详情监控页',
+    path: '/belt/fireS/home',
+  },
+  {
+    name: '灾变模拟分析',
+    path: '/micro-vent-3dModal/dashboard/analysis?type=sysMonitor&deviceType=sysfireTunnel&sysID=2028657172566073346&deviceid=2028650091184177153&sysType=leather',
+  },
+];
+// 下拉框样式
+const dropdownStyle = {
+  background: 'transparent',
+  borderBottom: '1px solid #ececec66',
+  backdropFilter: 'blur(50px)',
+  color: '#fff',
+};
+
+// 当前路由(计算属性)
+const currentPath = computed(() => {
+  return router.currentRoute.value.fullPath.split('?')[0];
+});
+// 监听父组件传入的 optionValue 同步更新
+watch(
+  () => props.optionValue,
+  (val) => {
+    currentTitleValue.value = val;
+  }
+);
+// 判断导航是否选中
+const isActive = (menuPath: string): boolean => {
+  if (!menuPath) return false;
+  const menuRoutePath = menuPath.split('?')[0];
+  return currentPath.value.startsWith(menuRoutePath);
+};
+
+// 导航点击跳转
+const handleNavClick = (item: MenuItem) => {
+  router.push(item.path);
+};
+// 打开/关闭历史数据弹窗
+const openModel = () => {
+  visible.value = !visible.value;
+  emit('open-history');
+};
+// 下拉选择器变化
+const handleTitleChange = (value: string) => {
+  currentTitleValue.value = value;
+  emit('change', value);
+};
 </script>
 <style lang="less">
 @import '/@/design/vent/modal.less';
@@ -119,6 +165,7 @@ export default defineComponent({
   }
 }
 </style>
+
 <style lang="less" scoped>
 @import '/@/design/theme.less';
 @ventSpace: zxm;
@@ -131,6 +178,7 @@ export default defineComponent({
   z-index: 9999;
   height: 60px;
   pointer-events: auto;
+
   .vent-home-header {
     width: 100%;
     position: fixed;
@@ -140,6 +188,7 @@ export default defineComponent({
     background-size: contain;
     display: flex;
     justify-content: center;
+
     .header-icon {
       margin-top: 45px;
     }
@@ -154,27 +203,27 @@ export default defineComponent({
       color: transparent;
     }
   }
+
   .container-title {
     width: 380px;
     height: 34px;
     left: 20px;
-    // background: url('/@/assets/images/vent/new-home/container-title-bg.png') no-repeat;
     background: var(--image-select-bg) no-repeat;
     background-size: contain;
     padding: 0 0 0 20px;
-    // padding: 0 0 0 180px;
     font-size: 20px;
     pointer-events: auto;
     position: relative;
     z-index: 9999;
     top: 70px;
+
     .title-select {
       width: 340px;
       position: absolute;
       top: 0;
-      // left: 160px;
     }
   }
+
   .nav {
     width: 100%;
     position: fixed;
@@ -184,6 +233,7 @@ export default defineComponent({
     gap: 30px;
     top: 15px;
     pointer-events: auto;
+
     .nav-item {
       flex: 1;
       max-width: 120px;
@@ -195,6 +245,33 @@ export default defineComponent({
       text-align: center;
       background: url('/@/assets/images/beltFire/titleNav.png') no-repeat center center;
       background-size: 100% 90%;
+      cursor: pointer;
+      color: #fff;
+    }
+    .nav-item.active {
+      background: url('/@/assets/images/beltFire/titleNavActive.png') no-repeat center center !important;
+      background-size: 100% 190% !important;
+    }
+  }
+
+  .history-nav {
+    position: fixed;
+    top: 15px;
+    right: 230px;
+    pointer-events: auto;
+
+    .nav-item {
+      width: 120px;
+      height: 35px;
+      line-height: 35px;
+      padding: 0;
+      box-sizing: border-box;
+      padding-bottom: 10px;
+      text-align: center;
+      background: url('/@/assets/images/beltFire/titleNav.png') no-repeat center center;
+      background-size: 100% 90%;
+      cursor: pointer;
+      color: #fff;
     }
     .nav-item.active {
       background: url('/@/assets/images/beltFire/titleNavActive.png') no-repeat center center !important;
@@ -202,20 +279,24 @@ export default defineComponent({
     }
   }
 }
+
 :deep(.zxm-select) {
   width: 400px;
+
   .@{ventSpace}-select-selector {
     background: transparent !important;
     border: none !important;
     box-shadow: none !important;
+
     .zxm-select-selection-item {
       color: #fff !important;
       font-size: 20px;
       margin-left: 20px !important;
     }
   }
+
   .@{ventSpace}-select-arrow {
     color: #fff !important;
   }
 }
-</style>
+</style>

+ 3 - 0
src/views/vent/home/configurable/belt/configurable.api.ts

@@ -15,6 +15,8 @@ enum Api {
   getStatus = '/ventanaly-device/safety/deviceVehiclePass/switch/status',
   // 车辆干扰排除控制
   changeStatus = '/ventanaly-device/safety/deviceVehiclePass/switch/change',
+  // 查询预警结果
+  getWarnResult = '/ventanaly-device/monitor/disaster/beltAlertRecords',
 }
 export const getSystem = (params) => defHttp.post({ url: Api.getSystem, params });
 export const getMonitorAndAlertBelt = (params) => defHttp.post({ url: Api.monitorAndAlertBelt, params });
@@ -22,3 +24,4 @@ export const getDataHome = (params) => defHttp.post({ url: Api.getDataHome, para
 export const getStatus = () => defHttp.get({ url: Api.getStatus });
 export const changeStatus = (params) => defHttp.get({ url: Api.changeStatus, params });
 export const getDevice = (params) => defHttp.post({ url: Api.getDevice, params });
+export const getWarnResult = (params) => defHttp.post({ url: Api.getWarnResult, params });

+ 319 - 152
src/views/vent/home/configurable/belt/configurable.data.ts

@@ -295,151 +295,7 @@ export const testBeltLaneFire: Config[] = [
     },
   },
 ];
-export const testYjkf: Config[] = [
-  {
-    deviceType: 'plmhInfo', //
-    moduleName: '',
-    pageType: 'beltYjkf1',
-    moduleData: {
-      header: {
-        show: false,
-        readFrom: '',
-        selector: {
-          show: false,
-          value: '',
-        },
-        slot: {
-          show: false,
-          value: '短路风门管控详情',
-          trans: {},
-        },
-      },
-      background: {
-        show: false,
-        type: 'video',
-        link: '',
-      },
-      layout: {
-        direction: 'column',
-        items: [
-          {
-            name: 'gateBoard',
-            basis: '100%',
-          },
-        ],
-      },
-      board: [],
-      chart: [],
-      gallery: [],
-      gallery_list: [],
-      table: [],
-      list: [],
-      complex_list: [],
-      preset: [
-        {
-          readFrom: 'deviceInfo.gate.datalist',
-          type: 'C',
-          config: {
-            tilte: 'strname',
-            items: [
-              {
-                label: '前门状态',
-                value: '${readData.frontGateOpen}',
-                trans: {
-                  1: '打开',
-                  0: '关闭',
-                },
-              },
-              {
-                label: '后门状态',
-                value: '${readData.rearGateOpen}',
-                trans: {
-                  1: '打开',
-                  0: '关闭',
-                },
-              },
-              {
-                label: '网络状态',
-                value: '${netStatus}',
-                trans: {
-                  1: '连接',
-                  0: '断开',
-                },
-              },
-            ],
-          },
-        },
-      ],
-      // mock: doorMock,
-    },
-    showStyle: {
-      size: 'width:440px;height:820px;',
-      version: '原版',
-      position: 'top:30px;left:25px;',
-    },
-  },
-  {
-    deviceType: '',
-    moduleName: '摄像头视频信号',
-    pageType: 'beltYjkf',
-    moduleData: {
-      header: {
-        show: false,
-        readFrom: '',
-        selector: {
-          show: false,
-          value: '${beltName}',
-        },
-        slot: {
-          show: false,
-          value: '',
-        },
-      },
-      background: {
-        show: false,
-        type: 'video',
-        link: '',
-      },
-      layout: {
-        direction: 'row',
-        items: [
-          {
-            name: 'cameraList',
-            basis: '100%',
-          },
-        ],
-      },
-      board: [],
-      chart: [],
-      gallery: [],
-      gallery_list: [],
-      table: [],
-      list: [],
-      complex_list: [],
-      preset: [
-        {
-          readFrom: 'deviceInfo.gate.datalist',
-          config: {
-            title: 'name',
-            contents: [
-              {
-                code: '',
-                value: '',
-                info: '',
-              },
-            ],
-          },
-        },
-      ],
-      // mock: BDfireMock,
-    },
-    showStyle: {
-      size: 'width:440px;height:850px;',
-      version: '原版',
-      position: 'top:0px;right:25px;',
-    },
-  },
-];
+// 一级
 export const testBeltNew: Config[] = [
   // ==================== 左侧栏:火灾监测设备状态 ====================
   {
@@ -648,16 +504,11 @@ export const testBeltNew: Config[] = [
             {
               name: '区域',
               prop: 'area',
-              width: '130px',
+              width: '220px',
             },
             {
               name: '预警类型',
               prop: 'status',
-            },
-            {
-              name: '状态',
-              prop: 'status',
-              align: 'center',
               width: '80px',
             },
             {
@@ -669,7 +520,7 @@ export const testBeltNew: Config[] = [
               name: '操作',
               prop: 'action',
               render: (row: any) => {
-                return `<button class="btn-start-spray">启动喷淋</button>`;
+                return `<button class="btn-start-spray">执行预案</button>`;
               },
             },
           ],
@@ -889,6 +740,7 @@ export const testBeltNew: Config[] = [
     },
   },
 ];
+// 二级
 export const testSpary: Config[] = [
   {
     deviceType: 'sprayData', //
@@ -1044,6 +896,321 @@ export const testSpary: Config[] = [
       position: 'top:30px;left:25px;',
     },
   },
+  {
+    deviceType: 'warn_result',
+    moduleName: '预警结果',
+    pageType: 'fireMonitorMid',
+    moduleData: {
+      header: {
+        show: false,
+        readFrom: '',
+        selector: {
+          show: true,
+          value: '${beltName}',
+        },
+        slot: {
+          show: false,
+          value: '',
+        },
+      },
+      background: {
+        show: false,
+        type: 'video',
+        link: '',
+      },
+      layout: {
+        direction: 'column',
+        items: [
+          {
+            name: 'warning_result',
+            basis: '100%',
+          },
+        ],
+      },
+      board: [],
+      chart: [],
+      gallery: [],
+      gallery_list: [],
+      table: [],
+      list: [],
+      complex_list: [],
+      preset: [
+        {
+          readFrom: '',
+          type: 'C',
+          tableReadFrom: 'warn_result',
+          columns: [
+            {
+              name: '时间',
+              prop: 'time',
+              width: '180px',
+            },
+            {
+              name: '区域',
+              prop: 'area',
+              width: '220px',
+            },
+            {
+              name: '预警类型',
+              prop: 'status',
+              width: '80px',
+            },
+            {
+              name: '处置意见',
+              prop: 'advice',
+              width: '180px',
+            },
+            {
+              name: '操作',
+              prop: 'action',
+              render: (row: any) => {
+                return `<button class="btn-start-spray">执行预案</button>`;
+              },
+            },
+          ],
+          otherProps: {
+            title: '火灾风险预警',
+            prop: 'status',
+          },
+        },
+      ],
+    },
+    showStyle: {
+      size: 'width:980px;height:300px;',
+      version: '原版',
+      position: 'bottom:25px;left:470px;',
+    },
+  },
+  {
+    deviceType: '',
+    moduleName: '摄像头视频信号',
+    pageType: 'beltYjkf',
+    moduleData: {
+      header: {
+        show: false,
+        readFrom: '',
+        selector: {
+          show: false,
+          value: '${beltName}',
+        },
+        slot: {
+          show: false,
+          value: '',
+        },
+      },
+      background: {
+        show: false,
+        type: 'video',
+        link: '',
+      },
+      layout: {
+        direction: 'row',
+        items: [
+          {
+            name: 'cameraList',
+            basis: '100%',
+          },
+        ],
+      },
+      board: [],
+      chart: [],
+      gallery: [],
+      gallery_list: [],
+      table: [],
+      list: [],
+      complex_list: [],
+      preset: [
+        {
+          readFrom: 'deviceInfo.gate.datalist',
+          config: {
+            title: 'name',
+            contents: [
+              {
+                code: '',
+                value: '',
+                info: '',
+              },
+            ],
+          },
+        },
+      ],
+      // mock: BDfireMock,
+    },
+    showStyle: {
+      size: 'width:440px;height:850px;',
+      version: '原版',
+      position: 'top:0px;right:25px;',
+    },
+  },
+];
+// 三级
+export const testYjkf: Config[] = [
+  {
+    deviceType: 'plmhInfo', //
+    moduleName: '',
+    pageType: 'beltYjkf1',
+    moduleData: {
+      header: {
+        show: false,
+        readFrom: '',
+        selector: {
+          show: false,
+          value: '',
+        },
+        slot: {
+          show: false,
+          value: '短路风门管控详情',
+          trans: {},
+        },
+      },
+      background: {
+        show: false,
+        type: 'video',
+        link: '',
+      },
+      layout: {
+        direction: 'column',
+        items: [
+          {
+            name: 'gateBoard',
+            basis: '100%',
+          },
+        ],
+      },
+      board: [],
+      chart: [],
+      gallery: [],
+      gallery_list: [],
+      table: [],
+      list: [],
+      complex_list: [],
+      preset: [
+        {
+          readFrom: 'deviceInfo.gate.datalist',
+          type: 'C',
+          config: {
+            tilte: 'strname',
+            items: [
+              {
+                label: '前门状态',
+                value: '${readData.frontGateOpen}',
+                trans: {
+                  1: '打开',
+                  0: '关闭',
+                },
+              },
+              {
+                label: '后门状态',
+                value: '${readData.rearGateOpen}',
+                trans: {
+                  1: '打开',
+                  0: '关闭',
+                },
+              },
+              {
+                label: '网络状态',
+                value: '${netStatus}',
+                trans: {
+                  1: '连接',
+                  0: '断开',
+                },
+              },
+            ],
+          },
+        },
+      ],
+      // mock: doorMock,
+    },
+    showStyle: {
+      size: 'width:440px;height:820px;',
+      version: '原版',
+      position: 'top:30px;left:25px;',
+    },
+  },
+  {
+    deviceType: 'warn_result',
+    moduleName: '预警结果',
+    pageType: 'fireMonitorMid',
+    moduleData: {
+      header: {
+        show: false,
+        readFrom: '',
+        selector: {
+          show: true,
+          value: '${beltName}',
+        },
+        slot: {
+          show: false,
+          value: '',
+        },
+      },
+      background: {
+        show: false,
+        type: 'video',
+        link: '',
+      },
+      layout: {
+        direction: 'column',
+        items: [
+          {
+            name: 'warning_result',
+            basis: '100%',
+          },
+        ],
+      },
+      board: [],
+      chart: [],
+      gallery: [],
+      gallery_list: [],
+      table: [],
+      list: [],
+      complex_list: [],
+      preset: [
+        {
+          readFrom: '',
+          type: 'C',
+          tableReadFrom: 'warn_result',
+          columns: [
+            {
+              name: '时间',
+              prop: 'time',
+              width: '180px',
+            },
+            {
+              name: '区域',
+              prop: 'area',
+              width: '220px',
+            },
+            {
+              name: '预警类型',
+              prop: 'status',
+            },
+            {
+              name: '处置意见',
+              prop: 'advice',
+              width: '180px',
+            },
+            {
+              name: '操作',
+              prop: 'action',
+              render: (row: any) => {
+                return `<button class="btn-start-spray">执行预案</button>`;
+              },
+            },
+          ],
+          otherProps: {
+            title: '火灾风险预警',
+            prop: 'status',
+          },
+        },
+      ],
+    },
+    showStyle: {
+      size: 'width:980px;height:300px;',
+      version: '原版',
+      position: 'bottom:25px;left:470px;',
+    },
+  },
   {
     deviceType: '',
     moduleName: '摄像头视频信号',

+ 28 - 30
src/views/vent/home/configurable/components/belt/ComplexList1Belt.vue

@@ -9,11 +9,7 @@
           :key="`vvhccdclc${j}`"
           style="cursor: pointer"
           @click="handleItemClick(i, j)"
-          :class="[
-            `list-item__content_${type}`,
-            getBgClass(ctx.value),
-            { active: activeGroup === i && activeItem === j }, // 关键修复
-          ]"
+          :class="[`list-item__content_${type}`, getBgClass(ctx.value), { active: activeGroup === i && activeItem === j }]"
         >
           <div class="list-item__label"> {{ ctx.label }}</div>
           <div class="list-item__value" :class="`list-item__value_${type}`"> {{ getAlertName(ctx.value) }} </div>
@@ -26,12 +22,13 @@
 <script lang="ts" setup>
 import { onMounted, ref } from 'vue';
 import { getFormattedText } from '../../hooks/helper';
+
 const props = withDefaults(
   defineProps<{
     listConfig: {
       title: string;
       contents: {
-        value: string;
+        value: string | number | null;
         color?: string;
         label: string;
         info?: string;
@@ -45,6 +42,7 @@ const props = withDefaults(
     type: 'C',
   }
 );
+
 const emit = defineEmits<{
   clickItem: [data: any];
 }>();
@@ -52,7 +50,8 @@ const emit = defineEmits<{
 const activeGroup = ref(0);
 const activeItem = ref(0);
 
-const alarmMap: Record<string | number, string> = {
+// 预警映射表
+const alarmMap: Record<string | number | null, string> = {
   '101': '绿色预警',
   '102': '蓝色预警',
   '103': '黄色预警',
@@ -60,21 +59,25 @@ const alarmMap: Record<string | number, string> = {
   '201': '报警',
   '0': '正常',
   '1001': '网络中断',
+  null: '正常',
 };
-const getBgClass = (riskLevel: string) => {
-  switch (riskLevel) {
+
+// 获取背景样式
+const getBgClass = (riskLevel: string | number | null) => {
+  // 统一处理 null → 0
+  const val = riskLevel ?? '0';
+
+  switch (val) {
     case '0':
-      return 'bg-lowRisk';
     case '101':
       return 'bg-lowRisk';
     case '102':
       return 'bg-normalRisk';
     case '103':
-      return 'bg-greaterRisk ';
+      return 'bg-greaterRisk';
     case '104':
       return 'bg-majorRisk';
     case '201':
-      return 'bg-warning';
     case '1001':
       return 'bg-warning';
     default:
@@ -82,21 +85,21 @@ const getBgClass = (riskLevel: string) => {
   }
 };
 
+// 点击事件
 const handleItemClick = (groupIndex: number, itemIndex: number) => {
   activeGroup.value = groupIndex;
   activeItem.value = itemIndex;
-  // 获取原始数据
   const rawData = props.listConfig[groupIndex].contents[itemIndex];
-  const formattedData = {
-    ...rawData,
-  };
-
-  // 抛出去的是处理后的数据
-  emit('clickItem', formattedData);
+  emit('clickItem', rawData);
 };
-const getAlertName = (riskLevel: string | number) => {
-  const key = String(riskLevel);
-  return alarmMap[key] || riskLevel;
+
+// 获取预警名称(核心修复)
+const getAlertName = (riskLevel: string | number | null) => {
+  // 空值:null / undefined / 空字符串 → 正常
+  if (riskLevel === null || riskLevel === undefined || riskLevel === '') {
+    return '正常';
+  }
+  return alarmMap[riskLevel] || '正常';
 };
 
 onMounted(() => {});
@@ -119,11 +122,11 @@ onMounted(() => {});
   text-align: center;
   margin: 21px 0px;
   display: flex;
-  flex-direction: column; /* 竖排 */
-  gap: 5px; /* 间距 */
+  flex-direction: column;
+  gap: 5px;
 }
 .list-item__content_A {
-  position: relative; /* 必须保留,为了定位伪元素 */
+  position: relative;
   display: flex;
   align-items: center;
   justify-content: space-between;
@@ -134,7 +137,6 @@ onMounted(() => {});
   font-size: 13px;
   background-repeat: no-repeat;
   background-size: 100% 100%;
-  /* 确保背景图在底层 */
   z-index: 1;
 }
 .list-item__content_A > .list-item__label {
@@ -175,19 +177,15 @@ onMounted(() => {});
 .list-item__content_A.bg-lowRisk .list-item__value {
   color: #32ddff;
 }
-
 .list-item__content_A.bg-normalRisk .list-item__value {
   color: #ffff00;
 }
-
 .list-item__content_A.bg-greaterRisk .list-item__value {
   color: #ff9d17;
 }
-
 .list-item__content_A.bg-warning .list-item__value {
   color: #ff0000;
 }
-
 .list-item__content_A.bg-majorRisk .list-item__value {
   color: #ff3823;
 }

+ 1 - 1
src/views/vent/home/configurable/components/belt/VehicleCOAnalysis.vue

@@ -294,7 +294,7 @@ onMounted(async () => {
     display: flex;
     align-items: center;
     padding: 2px 12px;
-    gap: 108px;
+    gap: 20px;
     flex: 1;
     color: #fafafa;
     background: url('@/assets/images/beltFire/fireMonitor/2-4.png') no-repeat;

+ 84 - 101
src/views/vent/home/configurable/components/belt/WarningResultList.vue

@@ -1,19 +1,5 @@
 <template>
   <div class="warning-result-panel">
-    <!-- 顶部标题栏 -->
-    <div class="panel-header">
-      <div class="header-left">
-        <div class="icon-fire"></div>
-      </div>
-      <div class="header-right">
-        <span class="title-text">{{ config.otherProps.title }}</span>
-        <div class="risk-tag high-risk">
-          <!-- <div class="status-dot"></div> -->
-          <!-- <span v-if="!!data" class="risk-text">{{ data[config.otherProps.prop] }}</span> -->
-        </div>
-      </div>
-    </div>
-
     <!-- 表格主体 -->
     <div class="table-container">
       <table v-if="!!data" class="warning-table">
@@ -27,9 +13,12 @@
         <tbody>
           <tr v-for="(row, index) in data[config.tableReadFrom]" :key="index" class="table-row">
             <td v-for="col in config.columns" :key="col.prop" class="table-cell">
-              <!-- 如果是 render 函数,且需要渲染 HTML,使用 v-html -->
-              <span v-if="col.render" v-html="col.render(row)"></span>
-              <span v-else>{{ row[col.prop] ? row[col.prop] : '-' }}</span>
+              <!-- 渲染逻辑:如果是 status 字段,自动变色 -->
+              <span v-if="col.render" v-html="col.render(row, index)"></span>
+              <span v-else-if="col.prop === 'status'" :class="getStatusClass(row[col.prop])">
+                {{ row[col.prop] || '-' }}
+              </span>
+              <span v-else>{{ row[col.prop] || '-' }}</span>
             </td>
           </tr>
         </tbody>
@@ -39,7 +28,7 @@
 </template>
 
 <script setup lang="ts">
-import { onMounted } from 'vue';
+import { onMounted, ref } from 'vue';
 
 const props = defineProps<{
   config: {
@@ -47,8 +36,8 @@ const props = defineProps<{
     columns: {
       name: string;
       prop: string;
-      width?: string; // 增加宽度配置
-      render?: (row: any) => string;
+      width?: string;
+      render?: (row: any, index: number) => string;
     }[];
     otherProps: {
       title: string;
@@ -59,9 +48,17 @@ const props = defineProps<{
     [key: string]: any;
   };
 }>();
-onMounted(() => {
-  console.log(props.config, '======');
-});
+
+// 根据 status 返回对应的样式类
+function getStatusClass(status: string) {
+  if (!status) return '';
+  if (status.includes('黄色预警')) return 'status-yellow';
+  if (status.includes('橙色预警')) return 'status-orange';
+  if (status.includes('红色预警')) return 'status-red';
+  return 'status-default';
+}
+
+onMounted(() => {});
 </script>
 
 <style scoped lang="less">
@@ -74,80 +71,7 @@ onMounted(() => {
   max-height: 250px;
   display: flex;
   flex-direction: column;
-  overflow: hidden; /* 禁止外层整体滚动 */
-}
-
-/* --- 顶部标题栏 --- */
-.panel-header {
-  position: relative;
-  display: flex;
-  justify-content: start;
-  align-items: center;
-  padding-bottom: 15px;
-  border-bottom: 1px dashed #0e324b;
-  flex-shrink: 0;
-}
-
-.header-left {
-  display: flex;
-  align-items: center;
-  gap: 10px;
-  font-size: 16px;
-  font-weight: bold;
-  letter-spacing: 1px;
-}
-
-.title-text {
-  margin-left: 20px;
-}
-
-.icon-fire {
-  background: url('@/assets/images/beltFire/2-6.svg') no-repeat;
-  background-size: 100% 100%;
-  width: 20px;
-  height: 20px;
-  margin-top: -2px;
-}
-
-.header-right {
-  margin-left: 10px;
-  height: 30px;
-  width: 50%;
-  background: url('@/assets/images/beltFire/2-7.png') no-repeat;
-  background-size: 100% 100%;
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  .title-text {
-    font-size: 14px;
-  }
-  .status-dot {
-    display: inline-block;
-    width: 8px;
-    height: 8px;
-    border-radius: 50%;
-    margin-right: 4px;
-    background-color: #33ff00;
-    box-shadow: 0 0 6px 2px rgba(104, 255, 45, 0.6);
-  }
-}
-
-.risk-tag {
-  margin-right: 30%;
-  display: inline-flex;
-  align-items: center;
-  gap: 6px;
-  padding: 4px 12px;
-  border-radius: 4px;
-  .risk-text {
-    font-size: 14px;
-    font-weight: bold;
-    font-style: italic;
-  }
-}
-
-.icon-dot {
-  fill: red;
+  overflow: hidden;
 }
 
 /* --- 表格样式 --- */
@@ -160,7 +84,7 @@ onMounted(() => {
 
 .warning-table {
   width: 100%;
-  min-width: 900px; // 防止内容太少表格塌陷
+  min-width: 800px;
   border-collapse: collapse;
 }
 
@@ -170,7 +94,6 @@ thead {
   height: 25px;
 }
 
-/* 表头 */
 thead tr {
   color: #38e4ef;
 }
@@ -187,7 +110,6 @@ thead tr {
   z-index: 1;
 }
 
-/* 表格主体 */
 .table-row {
   height: 20px;
   background: url('@/assets/images/beltFire/2-9.png') no-repeat;
@@ -202,6 +124,23 @@ thead tr {
   text-align: center !important;
 }
 
+/* ====================== 预警类型 ====================== */
+.status-yellow {
+  color: #ffd700 !important;
+  font-weight: bold;
+}
+.status-orange {
+  color: #ff9500 !important;
+  font-weight: bold;
+}
+.status-red {
+  color: #ff3333 !important;
+  font-weight: bold;
+}
+.status-default {
+  color: #ffffff !important;
+}
+
 /* 操作列按钮样式 */
 :deep(.btn-start-spray) {
   background: #2192d9;
@@ -214,4 +153,48 @@ thead tr {
   font-weight: bold;
   transition: all 0.2s;
 }
-</style>
+
+/* ====================== 开关滑块样式 ====================== */
+:deep(.tip) {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  gap: 8px;
+}
+
+:deep(.text),
+:deep(.text1) {
+  font-size: 12px;
+  color: #fff;
+}
+
+:deep(.toggle-switch) {
+  position: relative;
+  display: inline-block;
+  width: 36px;
+  height: 18px;
+  background-color: #ccc;
+  border-radius: 18px;
+  cursor: pointer;
+  transition: background-color 0.3s;
+}
+
+:deep(.toggle-switch.is-on) {
+  background-color: #2192d9;
+}
+
+:deep(.slider) {
+  position: absolute;
+  top: 2px;
+  left: 2px;
+  width: 14px;
+  height: 14px;
+  background-color: white;
+  border-radius: 50%;
+  transition: transform 0.3s;
+}
+
+:deep(.toggle-switch.is-on .slider) {
+  transform: translateX(18px);
+}
+</style>