Browse Source

红沙泉露天煤矿火灾监测-提交新版本

lxh 2 days ago
parent
commit
57c631407a

+ 1 - 26
src/views/vent/home/configurable/components/content.vue

@@ -222,18 +222,7 @@
         <template v-if="config.name === 'system_view'">
           <SystemView></SystemView>
         </template>
-        <template v-if="config.name === 'rule_table'">
-          <RuleTable
-            :config="config.config"
-            :data="config.data"
-            :selected-row="selectRuleRow"
-            @row-change="onRowClick"
-            @table-refresh="handleTableRefresh"
-          ></RuleTable>
-        </template>
         <template v-if="config.name === 'link_log'"> <LinkLog></LinkLog> </template>
-        <template v-if="config.name === 'rule_num'"> <RuleNum></RuleNum> </template>
-        <template v-if="config.name === 'link_edit'"> <LinkRuleEdit :selected-row="selectRuleRow"> </LinkRuleEdit></template>
       </div>
     </div>
   </div>
@@ -292,12 +281,8 @@ import PermissionManager from './preset/PermissionManager.vue';
 import PermissionSet from './preset/PermissionSet.vue';
 import StatisticDay from './preset/StatisticDay.vue';
 import SystemView from './preset/SystemView.vue';
-import RuleTable from './preset/ruleTable.vue';
 import LinkLog from './preset/linkLog.vue';
-import RuleNum from './preset/ruleNum.vue';
-import LinkRuleEdit from './preset/linkRuleEdit.vue';
-// import FIreWarn from './preset/FIreWarn.vue';
-// import FIreControl from './preset/FIreControl.vue';
+
 
 const props = defineProps<{
   data: any;
@@ -306,16 +291,6 @@ const props = defineProps<{
 }>();
 
 const { background, layout } = props.moduleData;
-// 存储当前选中行
-const selectRuleRow = ref<null | Record<string, any>>(null);
-const onRowClick = (singleRow) => {
-  selectRuleRow.value = singleRow;
-};
-const emit = defineEmits(['table-refresh']);
-// 接收 RuleTable 子组件刷新信号,向上抛给顶层父组件
-const handleTableRefresh = () => {
-  emit('table-refresh');
-};
 // 获取当原始配置带 items 项时的最终 items 配置
 function getItems(raw, items: CommonItem[]) {
   return items.map((i) => {

+ 0 - 149
src/views/vent/home/configurable/components/preset/ruleNum.vue

@@ -1,149 +0,0 @@
-<template>
-  <div class="long-list">
-    <div class="list-title">
-      <span>规则统计</span>
-    </div>
-    <div class="list-content">
-      <div class="stat-item blue">
-        <div class="icon-wrap icon-1"></div>
-        <div class="label-wrap">
-          <span>总规则</span>
-        </div>
-        <div class="num-wrap">
-          <span>10</span>
-        </div>
-      </div>
-      <div class="stat-item green">
-        <div class="icon-wrap icon-2"></div>
-        <div class="label-wrap">
-          <span>已启用</span>
-        </div>
-        <div class="num-wrap">
-          <span>7</span>
-        </div>
-      </div>
-      <div class="stat-item green">
-        <div class="icon-wrap icon-3"></div>
-        <div class="label-wrap">
-          <span>已禁用</span>
-        </div>
-        <div class="num-wrap">
-          <span>2</span>
-        </div>
-      </div>
-      <div class="stat-item blue">
-        <div class="icon-wrap icon-4"></div>
-        <div class="label-wrap">
-          <span>触发中</span>
-        </div>
-        <div class="num-wrap">
-          <span>2</span>
-        </div>
-      </div>
-    </div>
-  </div>
-</template>
-
-<script setup lang="ts">
-import { ref } from 'vue';
-</script>
-
-<style lang="less" scoped>
-@import '/@/design/theme.less';
-
-.long-list {
-  --image-box-bg: url('@/assets/images/home-container/configurable/hsq/2-5.png');
-  --image-box-bg-green: url('@/assets/images/home-container/configurable/hsq/4-2.png');
-  --image-box-bg-blue: url('@/assets/images/home-container/configurable/hsq/4-3.png');
-  --image-box-svg1: url('@/assets/images/home-container/configurable/hsq/4-total.svg');
-  --image-box-svg2: url('@/assets/images/home-container/configurable/hsq/4-cf.svg');
-  --image-box-svg3: url('@/assets/images/home-container/configurable/hsq/4-qy.svg');
-  --image-box-svg4: url('@/assets/images/home-container/configurable/hsq/4-jy.svg');
-
-  position: relative;
-  width: 100%;
-  height: 100%;
-  padding: 15px 15px;
-  box-sizing: border-box;
-  .list-title {
-    width: 177px;
-    height: 30px;
-    line-height: 22px;
-    color: #01fefc;
-    font-weight: bolder;
-    background: var(--image-box-bg) no-repeat;
-    background-size: 80% 100%;
-    margin-bottom: 10px;
-  }
-
-  .list-content {
-    display: flex;
-    flex-wrap: wrap;
-    gap: 20px;
-  }
-
-  .stat-item {
-    width: calc(50% - 10px);
-    display: flex;
-    align-items: center;
-    height: 40px;
-    padding-left: 6px;
-    box-sizing: border-box;
-    background-repeat: no-repeat;
-    background-position: center;
-    background-size: 100% 100%;
-
-    &.blue {
-      background-image: var(--image-box-bg-blue);
-    }
-    &.green {
-      background-image: var(--image-box-bg-green);
-    }
-  }
-
-  .icon-wrap {
-    width: 30px;
-    height: 30px;
-    flex-shrink: 0;
-    background-repeat: no-repeat;
-    background-position: center;
-    background-size: 60% 70%;
-
-    &.icon-1 {
-      background-image: var(--image-box-svg1);
-    }
-    &.icon-2 {
-      background-image: var(--image-box-svg3);
-    }
-    &.icon-3 {
-      background-image: var(--image-box-svg4);
-    }
-    &.icon-4 {
-      background-image: var(--image-box-svg2);
-    }
-  }
-
-  .label-wrap {
-    margin-left: 10px;
-    flex: 1;
-    display: flex;
-    align-items: center;
-    justify-content: center;
-    color: #fff;
-    font-size: 14px;
-    white-space: nowrap;
-  }
-
-  .num-wrap {
-    width: 100px;
-    height: 100%;
-    flex-shrink: 0;
-    display: flex;
-    justify-content: center;
-    align-items: center;
-    color: #fff;
-    font-size: 16px;
-    font-weight: bold;
-  }
-}
-</style>

+ 0 - 478
src/views/vent/home/configurable/components/preset/ruleTable.vue

@@ -1,478 +0,0 @@
-<template>
-  <div class="search-table">
-    <div class="search-area" v-if="config.type === 'C'">
-      <div class="list-title">
-        <span>联动规则列表</span>
-      </div>
-      <div class="search-btn" @click="handleAdd">
-        <div class="btn-item">配置</div>
-      </div>
-    </div>
-    <div v-if="config.type === 'D'" class="search-new">
-      <div class="list-title">
-        <span>联动日志</span>
-      </div>
-      <div class="time-picker-wrap">
-        <div class="form-row">
-          <label class="form-label">开始时间:</label>
-          <a-date-picker
-            v-model:value="filterForm.startDate"
-            placeholder="请选择开始时间"
-            class="date-picker"
-            show-time
-            format="YYYY-MM-DD HH:mm:ss"
-            style="width: 300px !important"
-          />
-        </div>
-      </div>
-      <div class="time-select">
-        <span class="span">快捷时间:</span>
-        <div class="btn" :class="{ active: timeType === 1 }" @click="setTimeRange(1)">今日</div>
-        <div class="btn" :class="{ active: timeType === 2 }" @click="setTimeRange(2)">近三天</div>
-        <div class="btn" :class="{ active: timeType === 3 }" @click="setTimeRange(3)">近一月</div>
-        <div class="search-btn" @click="confirmDetail">
-          <div class="btn-item">详情</div>
-        </div>
-      </div>
-    </div>
-    <div class="content-area">
-      <div class="table-container">
-        <table class="warning-table">
-          <colgroup>
-            <col
-              v-for="col in config.type === 'C' ? config.columns : filterDeviceColumns"
-              :key="col.dataIndex || col.prop"
-              :style="{ width: col.width }"
-            />
-          </colgroup>
-          <thead class="table-header">
-            <tr>
-              <th v-for="col in config.type === 'C' ? config.columns : filterDeviceColumns" :key="col.dataIndex || col.prop">
-                {{ col.title || col.name }}
-              </th>
-            </tr>
-          </thead>
-          <tbody class="table-body">
-            <tr
-              v-for="(row, index) in realTableData"
-              :key="index"
-              class="table-row"
-              :class="config.type === 'C' ? { box_active: isCurrentSelectRow(row) } : ''"
-              @click="config.type === 'C' ? handleRowClick(row) : ''"
-            >
-              <td v-for="col in config.type === 'C' ? config.columns : filterDeviceColumns" :key="col.dataIndex || col.prop" class="table-cell">
-                <template v-if="config.type === 'C' && col.prop === 'operation'">
-                  <span class="text-look" @click="handleEditClick(row)">编辑</span>
-                </template>
-                <template v-else>
-                  <span class="text-ellipsis" :title="getCellText(row, col)">
-                    {{ getCellText(row, col) }}
-                  </span>
-                </template>
-              </td>
-            </tr>
-          </tbody>
-        </table>
-      </div>
-    </div>
-    <DeviceModal
-      @register="registerModal"
-      :show-tab="true"
-      @saveOrUpdate="saveOrUpdateHandler"
-      :device-type="deviceType"
-      :select-sys-alarm-id="currentSelectInfo.alarmId"
-      :select-sys-id="currentSelectInfo.sysId"
-    />
-    <RuleTableModal
-      @register="register"
-      @update="onSubmit"
-      :destroy-on-close="true"
-      @success="handleModalSuccess"
-      :form-schemas="workFaceWarningSchemas"
-    />
-  </div>
-</template>
-
-<script setup lang="ts">
-import { ref, reactive, watch, onMounted, nextTick, computed } from 'vue';
-import dayjs, { Dayjs } from 'dayjs';
-import { message } from 'ant-design-vue';
-import DeviceModal from './deviceModal.vue';
-import { useModal } from '/@/components/Modal';
-import { getAlarmLogList } from '../../configurable.api';
-import { getTableHeaderColumns } from '/@/hooks/web/useWebColumns';
-import { func } from 'vue-types';
-import { useLinkRuleStore } from '/@/store/modules/linkRule';
-import RuleTableModal from '../../../../deviceManager/comment/warningTabel/RuleTableModal.vue';
-import { FormSchema } from '/@/components/Table';
-import { warningLogEdit, warningLogList } from '../../../../deviceManager/comment/warningTabel/warning.api';
-import { workFaceWarningFormSchemas } from '../../../../deviceManager/comment/warningTabel/warning.data';
-const FIXED_STRTYPE = 'sys_openair_fire';
-const deviceType = ref('managesys');
-const isUpdate = ref(false);
-const instanceId = ref(`${Date.now()}_${Math.floor(Math.random() * 10000)}`);
-const [registerModal, { openModal, closeModal }] = useModal(instanceId.value);
-const linkRuleStore = useLinkRuleStore();
-const emit = defineEmits(['row-change', 'table-refresh']);
-const currentSelectInfo = ref({
-  sysId: '',
-  alarmId: '',
-});
-const alarmMap: Record<string, string> = {
-  '102': '黄色预警',
-  '103': '橙色预警',
-  '104': '红色预警',
-};
-// 获取单元格文本内容
-const getCellText = (row: any, col: any) => {
-  const field = col.dataIndex ?? col.prop;
-  const val = row[field];
-  if (field === 'alarmLevel' && alarmMap[val]) {
-    return alarmMap[val];
-  }
-  return val ?? '-';
-};
-const deviceColumns = getTableHeaderColumns('alarm_history') as [];
-
-// 过滤日志只展示指定4列
-const filterDeviceColumns = computed(() => {
-  const showKeys = ['devicename', 'wardescrip', 'starttime', 'warntime'];
-  return deviceColumns.filter((item) => showKeys.includes(item.dataIndex));
-});
-
-const realTableData = computed(() => {
-  return props.config.type === 'D' ? alarmList.value : tableList.value;
-});
-const props = defineProps<{
-  config: {
-    type: string;
-    tableReadFrom: string;
-    columns: {
-      name: string;
-      prop: string;
-      width?: string;
-    }[];
-  };
-  data: Record<string, any>;
-  selectedRow?: any | null;
-}>();
-
-const handleEditClick = (row: any) => {
-  openModalRule(true, {
-    isUpdate: true,
-    record: row,
-  });
-};
-// 弹窗保存成功触发
-const handleModalSuccess = () => {
-  emit('table-refresh');
-};
-const workFaceWarningSchemas: FormSchema[] = [
-  ...workFaceWarningFormSchemas,
-  {
-    label: '关联条目',
-    field: 'relatedEntries',
-    component: 'ApiSelect',
-    componentProps: {
-      labelField: 'alarmName',
-      valueField: 'id',
-      resultField: 'records',
-      api: warningLogList.bind(null, { sysId: currentSelectInfo.value.sysId }),
-    },
-  },
-  {
-    label: '预警后自动控制',
-    field: 'isAutoControl',
-    component: 'RadioGroup',
-    componentProps: {
-      //options里面由一个一个的radio组成,支持disabled
-      options: [
-        { label: '是', value: true },
-        { label: '否', value: false },
-      ],
-    },
-  },
-  {
-    label: '解除后自动复位',
-    field: 'isAutoReset',
-    component: 'RadioGroup',
-    componentProps: {
-      //options里面由一个一个的radio组成,支持disabled
-      options: [
-        { label: '是', value: true },
-        { label: '否', value: false },
-      ],
-    },
-  },
-];
-const [register, { openModal: openModalRule, closeModal: closeModalRule }] = useModal();
-async function onSubmit(flag, values) {
-  await warningLogEdit(values);
-  closeModalRule();
-  // 通知外层刷新表格
-  handleModalSuccess();
-}
-// C类型数据源
-const tableList = ref<any[]>([]);
-// D类型数据源
-const alarmList = ref<any[]>([]);
-
-const timeType = ref(3);
-const filterForm = reactive<{ startDate: Dayjs | null }>({
-  startDate: null,
-});
-// 默认选中第一条(仅Type='C'时执行)
-const autoSelectFirstRow = async () => {
-  await nextTick();
-  if (props.config.type !== 'C') return;
-
-  const list = realTableData.value;
-  if (list.length > 0) {
-    const firstRow = list[0];
-    emit('row-change', firstRow);
-    linkRuleStore.setSelectedRow(firstRow);
-    currentSelectInfo.value.sysId = firstRow.sysId ?? '';
-    currentSelectInfo.value.alarmId = firstRow.alarmId ?? '';
-  } else {
-    emit('row-change', null);
-    linkRuleStore.clearSelectedRow();
-    currentSelectInfo.value = { sysId: '', alarmId: '' };
-  }
-};
-const isCurrentSelectRow = (row: any) => {
-  if (!props.selectedRow) return false;
-  return props.selectedRow === row;
-};
-
-const handleRowClick = (row: any) => {
-  emit('row-change', row);
-  linkRuleStore.setSelectedRow(row);
-  currentSelectInfo.value.sysId = row.sysId ?? '';
-  currentSelectInfo.value.alarmId = row.alarmId ?? '';
-};
-
-async function getAlarmHistory() {
-  const res = await getAlarmLogList({
-    column: 'createTime',
-    deviceKind: null,
-    isOk: false,
-    pageNo: 1,
-    pageSize: 100,
-    startTime: filterForm.startDate?.format('YYYY-MM-DD HH:mm:ss'),
-    systemType: 'ventS',
-  });
-  alarmList.value = res.records || [];
-}
-
-onMounted(() => {
-  getAlarmHistory();
-  autoSelectFirstRow();
-  setTimeRange(3);
-});
-
-// 监听父组件传入数据,赋值给tableList(Type为C时生效)
-watch(
-  () => props.data,
-  (newData) => {
-    const list = newData?.[props.config.tableReadFrom];
-    tableList.value = list || [];
-    autoSelectFirstRow();
-  },
-  { deep: true, immediate: true }
-);
-
-async function handleAdd() {
-  isUpdate.value = false;
-  openModal(true, {});
-}
-
-const saveOrUpdateHandler = async () => {
-  try {
-    message.success(isUpdate.value ? '编辑成功' : '新增成功');
-    closeModal();
-  } catch (error) {
-    message.error('保存失败,请联系管理员');
-  }
-};
-
-const setTimeRange = (type: number) => {
-  timeType.value = type;
-  let start: Dayjs;
-  switch (type) {
-    case 1:
-      start = dayjs().startOf('day');
-      break;
-    case 2:
-      start = dayjs().subtract(3, 'day').startOf('day');
-      break;
-    case 3:
-      start = dayjs().subtract(30, 'day').startOf('day');
-      break;
-    default:
-      start = dayjs().startOf('day');
-  }
-  filterForm.startDate = start;
-  getAlarmHistory();
-};
-
-// 跳转详情
-function confirmDetail() {
-  window.open('/monitorChannel/device-monitor/warningHistory/home');
-}
-</script>
-
-<style lang="less" scoped>
-@import '/@/design/theme.less';
-.search-table {
-  --image-box-bg: url('@/assets/images/home-container/configurable/hsq/2-5.png');
-  --image-box-bg2: url('@/assets/images/home-container/configurable/hsq/2-24.png');
-  position: relative;
-  width: 100%;
-  height: 100%;
-  padding: 10px;
-  box-sizing: border-box;
-}
-.list-title {
-  width: 177px;
-  height: 30px;
-  line-height: 22px;
-  color: #01fefc;
-  font-weight: bolder;
-  background: var(--image-box-bg) no-repeat;
-  background-size: 80% 100%;
-  margin-bottom: 5px;
-}
-.search-area {
-  height: 42px;
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  margin-bottom: 5px;
-}
-.search-btn {
-  width: 85px;
-  height: 30px;
-  border: 1px solid #01fefc;
-  border-radius: 4px;
-  padding: 3px;
-  cursor: pointer;
-}
-.search-new .time-picker-wrap {
-  padding: 10px;
-  .form-row {
-    display: flex;
-    align-items: center;
-    margin-bottom: 8px;
-    .form-label {
-      width: 60px;
-      font-size: 13px;
-      color: #fff;
-      flex-shrink: 0;
-    }
-  }
-}
-:deep(.zxm-picker) {
-  border: 1px solid #3ae1ff !important;
-  background-color: #104064 !important;
-}
-:deep(.zxm-picker-input > input) {
-  color: #fff !important;
-}
-:deep(.zxm-picker-suffix) {
-  color: #fff !important;
-}
-.time-select {
-  display: flex;
-  align-items: center;
-  padding-left: 10px;
-  margin-bottom: 8px;
-  gap: 6px;
-  white-space: nowrap;
-  .span {
-    color: #fff;
-    font-size: 13px;
-  }
-  .btn {
-    padding: 3px 8px;
-    background: #114268;
-    border: 1px solid transparent;
-    border-radius: 4px;
-    color: #fff;
-    cursor: pointer;
-    font-size: 13px;
-    &.active {
-      background-color: #185f8e;
-      border-color: #2084c0;
-    }
-  }
-}
-.btn-item {
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  width: 100%;
-  height: 100%;
-  background-color: rgba(32, 166, 169);
-}
-.content-area {
-  height: 100%;
-}
-.table-container {
-  width: 100%;
-  height: 100%;
-  overflow-y: auto;
-}
-.warning-table {
-  width: 100%;
-  table-layout: fixed;
-  border-collapse: collapse;
-}
-.table-header tr {
-  position: sticky;
-  top: 0;
-  z-index: 10;
-  background: var(--image-box-bg2) no-repeat;
-  background-size: 100% 100%;
-}
-.table-row {
-  height: 36px;
-  &:nth-child(odd) {
-    background-color: #0e3455;
-  }
-  &:nth-child(even) {
-    background-color: #114268;
-  }
-  &.box_active {
-    box-shadow: 2px 0 0 0 #ffa024, inset 0 0 0 2px #ffa024;
-  }
-}
-
-th,
-.table-cell {
-  text-align: center;
-  padding: 5px;
-  font-size: 14px;
-  box-sizing: border-box;
-  vertical-align: middle;
-}
-th {
-  font-weight: bold;
-  color: #38e4ef;
-  height: 30px;
-}
-.text-look {
-  padding: 0 3px;
-  margin: 0 2px;
-  border-radius: 2px;
-  background-color: #2484bc;
-  cursor: pointer;
-}
-/* 文字省略样式 */
-.text-ellipsis {
-  display: block;
-  width: 100%;
-  overflow: hidden;
-  white-space: nowrap;
-  text-overflow: ellipsis;
-}
-</style>

+ 1 - 581
src/views/vent/home/configurable/configurable.data.ts

@@ -3,587 +3,7 @@ import { Config } from '../../deviceManager/configurationTable/types';
 import { getThemifyImagesURL } from '/@/utils/ui';
 
 
-//联动配置
-export const testConfigLink: Config[] = [
-  {
-    deviceType: '',
-    moduleName: '联动规则列表',
-    pageType: 'gas_injection',
-    moduleData: {
-      header: {
-        show: false,
-        readFrom: '',
-        selector: {
-          show: false,
-          value: '${strinstallpos}',
-        },
-        slot: {
-          show: false,
-          value: '',
-          trans: {},
-        },
-      },
-      background: {
-        show: false,
-        type: 'video',
-        link: '',
-      },
-      layout: {
-        direction: 'column',
-        items: [
-          {
-            name: 'rule_table',
-            basis: '100%',
-          },
-        ],
-      },
-      board: [],
-      list: [],
-      chart: [],
-      table: [],
-      gallery: [],
-      complex_list: [],
-      gallery_list: [],
-      preset: [
-        {
-          readFrom: '',
-          type: 'C',
-          tableReadFrom: 'warnInfo',
-          columns: [
-            {
-              name: '报警条目',
-              prop: 'alarmName',
-            },
-            {
-              name: '预警等级',
-              prop: 'alarmLevel',
-            },
-            {
-              name: '所属系统',
-              prop: 'systemType_dictText',
-            },
-            {
-              name: '预警类型',
-              prop: 'alarmType_dictText',
-            },
-            {
-              name: '创建人',
-              prop: 'createBy',
-            },
-            {
-              name: '操作',
-              prop: 'operation',
-            },
-          ],
-        },
-      ],
-      to: '',
-    },
-    showStyle: {
-      size: 'width:500px;height:calc(100% - 200px);',
-      version: '普通版',
-      position: 'top:0px;left:10px;',
-    },
-  },
-  {
-    deviceType: '',
-    moduleName: '联动规则编辑器',
-    pageType: 'gas_injection',
-    moduleData: {
-      header: {
-        show: false,
-        readFrom: '',
-        selector: {
-          show: false,
-          value: '${strinstallpos}',
-        },
-        slot: {
-          show: false,
-          value: '',
-          trans: {},
-        },
-      },
-      background: {
-        show: false,
-        type: 'video',
-        link: '',
-      },
-      layout: {
-        direction: 'column',
-        items: [
-          {
-            name: 'link_edit',
-            basis: '100%',
-          },
-        ],
-      },
-      board: [],
-      list: [],
-      chart: [],
-      table: [],
-      gallery: [],
-      complex_list: [],
-      gallery_list: [],
-      preset: [
-        {
-          readFrom: '',
-        },
-      ],
-      to: '',
-    },
-    showStyle: {
-      size: 'width:940px;height:calc(100% - 76px);',
-      version: '普通版',
-      position: 'top:65px;left:520px;',
-    },
-  },
-  {
-    deviceType: '',
-    moduleName: '联动日志',
-    pageType: 'gas_injection',
-    moduleData: {
-      header: {
-        show: false,
-        readFrom: '',
-        selector: {
-          show: false,
-          value: '${strinstallpos}',
-        },
-        slot: {
-          show: false,
-          value: '',
-          trans: {},
-        },
-      },
-      background: {
-        show: false,
-        type: 'video',
-        link: '',
-      },
-      layout: {
-        direction: 'column',
-        items: [
-          {
-            name: 'rule_table',
-            basis: '100%',
-          },
-        ],
-      },
-      board: [],
-      list: [],
-      chart: [],
-      table: [],
-      gallery: [],
-      complex_list: [],
-      gallery_list: [],
-      preset: [
-        {
-          readFrom: '',
-          type: 'D',
-        },
-      ],
-      to: '',
-    },
-    showStyle: {
-      size: 'width:420px;height:calc(100% - 10px);',
-      version: '普通版',
-      position: 'top:0px;right:10px;',
-    },
-  },
-  {
-    deviceType: '',
-    moduleName: '规则统计',
-    pageType: 'gas_injection',
-    moduleData: {
-      header: {
-        show: false,
-        readFrom: '',
-        selector: {
-          show: false,
-          value: '${strinstallpos}',
-        },
-        slot: {
-          show: false,
-          value: '',
-          trans: {},
-        },
-      },
-      background: {
-        show: false,
-        type: 'video',
-        link: '',
-      },
-      layout: {
-        direction: 'column',
-        items: [
-          {
-            name: 'rule_num',
-            basis: '100%',
-          },
-        ],
-      },
-      board: [],
-      list: [],
-      chart: [],
-      table: [],
-      gallery: [],
-      complex_list: [],
-      gallery_list: [],
-      preset: [
-        {
-          readFrom: '',
-        },
-      ],
-      to: '',
-    },
-    showStyle: {
-      size: 'width:500px;height:180px;',
-      version: '普通版',
-      position: 'bottom:10px;bottom:10px;',
-    },
-  },
-];
-//系统管理
-export const testConfigSystem: Config[] = [
-  {
-    deviceType: 'listLeft',
-    moduleName: '',
-    pageType: 'gas_injection',
-    moduleData: {
-      header: {
-        show: false,
-        readFrom: '',
-        selector: {
-          show: false,
-          value: '${strinstallpos}',
-        },
-        slot: {
-          show: false,
-          value: '',
-          trans: {},
-        },
-      },
-      background: {
-        show: false,
-        type: 'video',
-        link: '',
-      },
-      layout: {
-        direction: 'column',
-        items: [
-          {
-            name: 'user_list',
-            basis: '100%',
-          },
-        ],
-      },
-      board: [],
-      list: [],
-      chart: [],
-      table: [],
-      gallery: [],
-      complex_list: [],
-      gallery_list: [],
-      preset: [
-        {
-          readFrom: '',
-        },
-      ],
-      to: '/micro-vent-3dModal/dashboard/analysis?type=tunMonitor&deviceType=fanmain',
-    },
-    showStyle: {
-      size: 'width:770px;height:calc(100% - 315px);',
-      version: '普通版',
-      position: 'top:65px;left:10px;',
-    },
-  },
-  {
-    deviceType: 'listLeft',
-    moduleName: '',
-    pageType: 'gas_injection',
-    moduleData: {
-      header: {
-        show: false,
-        readFrom: '',
-        selector: {
-          show: false,
-          value: '${strinstallpos}',
-        },
-        slot: {
-          show: false,
-          value: '',
-          trans: {},
-        },
-      },
-      background: {
-        show: false,
-        type: 'video',
-        link: '',
-      },
-      layout: {
-        direction: 'column',
-        items: [
-          {
-            name: 'user_edit',
-            basis: '100%',
-          },
-        ],
-      },
-      board: [],
-      list: [],
-      chart: [],
-      table: [],
-      gallery: [],
-      complex_list: [],
-      gallery_list: [],
-      preset: [
-        {
-          readFrom: '',
-        },
-      ],
-      to: '/micro-vent-3dModal/dashboard/analysis?type=tunMonitor&deviceType=fanmain',
-    },
-    showStyle: {
-      size: 'width:670px;height:calc(100% - 315px);',
-      version: '普通版',
-      position: 'top:65px;left:790px;',
-    },
-  },
-  {
-    deviceType: 'listLeft',
-    moduleName: '',
-    pageType: 'gas_injection',
-    moduleData: {
-      header: {
-        show: false,
-        readFrom: '',
-        selector: {
-          show: false,
-          value: '${strinstallpos}',
-        },
-        slot: {
-          show: false,
-          value: '',
-          trans: {},
-        },
-      },
-      background: {
-        show: false,
-        type: 'video',
-        link: '',
-      },
-      layout: {
-        direction: 'column',
-        items: [
-          {
-            name: 'permission_info',
-            basis: '50%',
-          },
-          {
-            name: 'permission_set',
-            basis: '50%',
-          },
-        ],
-      },
-      board: [],
-      list: [],
-      chart: [],
-      table: [],
-      gallery: [],
-      complex_list: [],
-      gallery_list: [],
-      preset: [
-        {
-          readFrom: '',
-        },
-        {
-          readFrom: '',
-        },
-      ],
-      to: '/micro-vent-3dModal/dashboard/analysis?type=tunMonitor&deviceType=fanmain',
-    },
-    showStyle: {
-      size: 'width:420px;height:calc(100% - 251px);',
-      version: '普通版',
-      position: 'top:0px;right:10px;',
-    },
-  },
-  {
-    deviceType: 'listLeft',
-    moduleName: '',
-    pageType: 'gas_injection',
-    moduleData: {
-      header: {
-        show: false,
-        readFrom: '',
-        selector: {
-          show: false,
-          value: '${strinstallpos}',
-        },
-        slot: {
-          show: false,
-          value: '',
-          trans: {},
-        },
-      },
-      background: {
-        show: false,
-        type: 'video',
-        link: '',
-      },
-      layout: {
-        direction: 'column',
-        items: [
-          {
-            name: 'log_audit',
-            basis: '100%',
-          },
-        ],
-      },
-      board: [],
-      list: [],
-      chart: [],
-      table: [],
-      gallery: [],
-      complex_list: [],
-      gallery_list: [],
-      preset: [
-        {
-          readFrom: '',
-        },
-      ],
-      to: '/micro-vent-3dModal/dashboard/analysis?type=tunMonitor&deviceType=fanmain',
-    },
-    showStyle: {
-      size: 'width:770px;height:230px;',
-      version: '普通版',
-      position: 'bottom:10px;left:10px;',
-    },
-  },
-  {
-    deviceType: 'listLeft',
-    moduleName: '',
-    pageType: 'gas_injection',
-    moduleData: {
-      header: {
-        show: false,
-        readFrom: '',
-        selector: {
-          show: false,
-          value: '${strinstallpos}',
-        },
-        slot: {
-          show: false,
-          value: '',
-          trans: {},
-        },
-      },
-      background: {
-        show: false,
-        type: 'video',
-        link: '',
-      },
-      layout: {
-        direction: 'row',
-        items: [
-          {
-            name: 'statistic_day',
-            basis: '50%',
-          },
-          {
-            name: 'chart',
-            basis: '50%',
-          },
-        ],
-      },
-      board: [],
-      list: [],
-      chart: [
-        {
-          type: 'bar_cylinder_wide',
-          readFrom: '',
-          grid: {
-            top: 55,
-            left: 20,
-            bottom: 35,
-            right: 50,
-          },
-          legend: { show: false },
-          xAxis: [{ show: true }],
-          yAxis: [{ show: true, name: '', position: 'left' }],
-          series: [{ readFrom: 'areaTemptureData', xprop: 'x', yprop: 'y', label: '温度' }],
-        },
-      ],
-      table: [],
-      gallery: [],
-      complex_list: [],
-      gallery_list: [],
-      preset: [
-        {
-          readFrom: '',
-        },
-      ],
-      to: '/micro-vent-3dModal/dashboard/analysis?type=tunMonitor&deviceType=fanmain',
-    },
-    showStyle: {
-      size: 'width:670px;height:230px;',
-      version: '普通版',
-      position: 'bottom:10px;left:790px;',
-    },
-  },
-  {
-    deviceType: 'listLeft',
-    moduleName: '',
-    pageType: 'gas_injection',
-    moduleData: {
-      header: {
-        show: false,
-        readFrom: '',
-        selector: {
-          show: false,
-          value: '${strinstallpos}',
-        },
-        slot: {
-          show: false,
-          value: '',
-          trans: {},
-        },
-      },
-      background: {
-        show: false,
-        type: 'video',
-        link: '',
-      },
-      layout: {
-        direction: 'column',
-        items: [
-          {
-            name: 'system_view',
-            basis: '100%',
-          },
-        ],
-      },
-      board: [],
-      list: [],
-      chart: [],
-      table: [],
-      gallery: [],
-      complex_list: [],
-      gallery_list: [],
-      preset: [
-        {
-          readFrom: '',
-        },
-      ],
-      to: '/micro-vent-3dModal/dashboard/analysis?type=tunMonitor&deviceType=fanmain',
-    },
-    showStyle: {
-      size: 'width:420px;height:230px;',
-      version: '普通版',
-      position: 'bottom:10px;right:10px;',
-    },
-  },
-];
+
 export const testConfigVentSsl: Config[] = [
   {
     deviceType: 'fanmain',

+ 0 - 108
src/views/vent/home/configurable/gasInjection.vue

@@ -1,108 +0,0 @@
-<template>
-  <div class="deviceManger">
-    <div class="top-bg">
-      <div class="main-title">{{ mainTitle }}</div>
-    </div>
-    <div class="nav">
-      <navMenu @changeMenu="changeMenu"></navMenu>
-    </div>
-    <div class="main-container">
-      <component :is="activeComponente"></component>
-    </div>
-  </div>
-</template>
-
-<script setup lang="ts">
-import { ref } from 'vue';
-import { useInitConfigs, useInitPage } from './hooks/useInit';
-import navMenu from './components/navMenu.vue';
-import fireMonitor from './fireMonitor.vue';
-import deviceManger from './deviceManger.vue';
-import warnMonitor from './warnMonitor.vue';
-import systemManger from './systemManger.vue';
-import largeScreen from './largeScreen.vue';
-import linkConfiguration from './linkConfiguration.vue';
-const { mainTitle, data, updateData } = useInitPage('红沙泉露天煤矿系统');
-//当前激活界面
-const activeComponente = ref<any>(fireMonitor);
-
-//menu选项切换
-function changeMenu(param) {
-  switch (param) {
-    case 'yzt':
-      activeComponente.value = fireMonitor;
-      break;
-    case 'jcyj':
-      activeComponente.value = warnMonitor;
-      break;
-    case 'sbgl':
-      activeComponente.value = deviceManger;
-      break;
-    case 'ldpz':
-      activeComponente.value = linkConfiguration;
-      break;
-    case 'xtgl':
-      activeComponente.value = systemManger;
-      break;
-    case 'dpzs':
-      activeComponente.value = largeScreen;
-      break;
-  }
-}
-</script>
-
-<style lang="less" scoped>
-@import '/@/design/theme.less';
-
-@{theme-deepblue} {
-  .deviceManger {
-  }
-}
-
-.deviceManger {
-  --image-modal-top: url('@/assets/images/vent/vent-header1.png');
-  position: relative;
-  width: 100%;
-  height: 100%;
-  color: #fff;
-  /* background: url('@/assets/images/vent/homeNew/bg.png') no-repeat center; */
-
-  .top-bg {
-    width: 100%;
-    height: 80px;
-    background: var(--image-modal-top) no-repeat center;
-    background-size: 100% 100%;
-    position: absolute;
-    z-index: 1;
-
-    .main-title {
-      height: 80px;
-      line-height: 62px;
-      font-family: 'douyuFont';
-      font-size: 22px;
-      letter-spacing: 2px;
-      display: flex;
-      justify-content: center;
-    }
-  }
-
-  .nav {
-    position: absolute;
-    left: 54%;
-    top: 60px;
-    transform: translate(-50%, 0);
-    width: 1000px;
-    height: 68px;
-    z-index: 9999;
-  }
-
-  .main-container {
-    position: absolute;
-    top: 70px;
-    width: 100%;
-    height: calc(100% - 70px);
-    padding: 0px 10px;
-    box-sizing: border-box;
-  }
-}
-</style>

+ 0 - 103
src/views/vent/home/configurable/linkConfiguration.vue

@@ -1,103 +0,0 @@
-<template>
-  <div class="device-manger">
-    <ModuleCommonHsq
-      v-for="cfg in configs"
-      :key="cfg.deviceType"
-      :show-style="cfg.showStyle"
-      :module-data="cfg.moduleData"
-      :module-name="cfg.moduleName"
-      :device-type="cfg.deviceType"
-      :data="data"
-      :visible="true"
-      @table-refresh="handleTableRefresh"
-    />
-  </div>
-</template>
-<script lang="ts" setup>
-import { onMounted, onUnmounted, ref, watch } from 'vue';
-import { useInitConfigs, useInitPage } from './hooks/useInit';
-import ModuleCommonHsq from './components/ModuleCommonHsq.vue';
-import { getAlarmLogList, warningList } from './configurable.api';
-import { testConfigLink } from './configurable.data';
-
-const { configs, fetchConfigs } = useInitConfigs();
-const { data, updateData } = useInitPage('红沙泉露天煤矿系统');
-const warnResult = ref({
-  warnInfo: [] as any[],
-});
-let interval: number | undefined;
-onMounted(() => {
-  fetchConfigs('gas_injection').then(() => {
-    configs.value = testConfigLink;
-    refresh();
-  });
-});
-// 刷新数据
-async function refresh() {
-  const res = await warningList({ sysId: '2074416476136718337' });
-  const newWarnData = {
-    ...warnResult.value,
-    warnInfo: res.records,
-  };
-  warnResult.value = newWarnData;
-  updateData(newWarnData);
-}
-const handleTableRefresh = async () => {
-  await refresh();
-};
-watch(
-  () => data.value,
-  (newData, oldData) => {}
-);
-
-onUnmounted(() => {
-  clearInterval(interval);
-});
-</script>
-
-<style lang="less" scoped>
-@import '/@/design/theme.less';
-
-@{theme-deepblue} {
-  .device-manger {
-  }
-}
-
-.device-manger {
-  --image-box1-bg: url('@/assets/images/home-container/configurable/hsq/2-4.png');
-  --image-box1-bg1: url('@/assets/images/home-container/configurable/hsq/2-10.png');
-  --image-box1-bg2: url('@/assets/images/home-container/configurable/hsq/4-1bg.png');
-  width: 100%;
-  height: 100%;
-  color: @white;
-  position: relative;
-  padding: 0px 10px;
-  box-sizing: border-box;
-  background-color: #09172c;
-}
-
-.vent-box1-bg {
-  &:nth-child(1) {
-    background: var(--image-box1-bg) no-repeat;
-    background-size: 100% 100%;
-  }
-
-  &:nth-child(2) {
-    background: var(--image-box1-bg1) no-repeat;
-    background-size: 100% 100%;
-  }
-
-  &:nth-child(3) {
-    background: var(--image-box1-bg) no-repeat;
-    background-size: 100% 100%;
-  }
-  &:nth-child(4) {
-    background: var(--image-box1-bg2) no-repeat;
-    background-size: 100% 100%;
-  }
-}
-
-:deep(.loading-box) {
-  position: unset;
-}
-</style>

+ 0 - 263
src/views/vent/monitorManager/hsqHome/components/LinkLogPanel.vue

@@ -1,263 +0,0 @@
-<template>
-  <div class="search-table">
-    <div class="list-title">
-      <span>联动日志</span>
-    </div>
-    <div class="search-area">
-      <div class="title-top">
-        <a-input v-model:value="searchWarn" placeholder="搜索" size="small" class="zxm-input zxm-input-sm" />
-        <div class="search-btn">
-          <div class="btn-item">筛选</div>
-        </div>
-      </div>
-    </div>
-
-    <div class="time-select">
-      <span class="span">时间范围:</span>
-      <div
-        class="btn"
-        :class="{ active: timeType === item.value }"
-        v-for="item in timeOptions"
-        :key="item.value"
-        @click="timeType = item.value"
-      >
-        {{ item.label }}
-      </div>
-    </div>
-    <div class="content-area">
-      <div class="content-title">
-        <div class="title-item col-time">时间</div>
-        <div class="title-item col-rule">规则</div>
-        <div class="title-item col-grade">动作</div>
-        <div class="title-item col-status">说明</div>
-      </div>
-      <div class="history-content">
-        <div class="content-item" v-for="(item, index) in tableData" :key="index">
-          <div class="item-text col-time">{{ item.time }}</div>
-          <div class="item-text col-rule">{{ item.rule }}</div>
-          <div class="item-text col-grade item-text2">{{ item.grade }}</div>
-          <div class="item-text col-status item-text1">{{ item.status }}</div>
-        </div>
-      </div>
-    </div>
-  </div>
-</template>
-
-<script setup lang="ts">
-import { ref } from 'vue';
-
-interface ILogItem {
-  time: string;
-  rule: string;
-  grade: string;
-  status: string;
-}
-
-interface ITimeOption {
-  label: string;
-  value: number;
-}
-
-const searchWarn = ref('');
-const timeType = ref(1);
-
-const timeOptions: ITimeOption[] = [
-  { label: '今日', value: 1 },
-  { label: '近三天', value: 2 },
-  { label: '近七天', value: 3 },
-  { label: '自定义', value: 4 },
-];
-
-const tableData = ref<ILogItem[]>([
-  { time: '14:31:22', rule: '001', grade: '触发', status: '温度65.3℃超过阈值' },
-  { time: '14:31:22', rule: '001', grade: '触发', status: '温度65.3℃超过阈值' },
-  { time: '14:31:22', rule: '001', grade: '触发', status: '温度65.3℃超过阈值' },
-  { time: '14:31:22', rule: '001', grade: '触发', status: '温度65.3℃超过阈值' },
-  { time: '14:31:22', rule: '001', grade: '触发', status: '温度65.3℃超过阈值' },
-  { time: '14:31:22', rule: '001', grade: '触发', status: '温度65.3℃超过阈值' },
-  { time: '14:31:22', rule: '001', grade: '触发', status: '温度65.3℃超过阈值' },
-  { time: '14:31:22', rule: '001', grade: '触发', status: '温度65.3℃超过阈值' },
-  { time: '14:31:22', rule: '001', grade: '触发', status: '温度65.3℃超过阈值' },
-]);
-</script>
-
-<style lang="less" scoped>
-@import '/@/design/theme.less';
-
-.search-table {
-  --image-box-bg: url('@/assets/images/home-container/configurable/hsq/2-5.png');
-  --image-box-bg1: url('@/assets/images/home-container/configurable/hsq/2-6.png');
-  --image-box-bg2: url('@/assets/images/home-container/configurable/hsq/2-24.png');
-  position: relative;
-  width: 100%;
-  height: 100%;
-  padding: 15px;
-  box-sizing: border-box;
-}
-
-.list-title {
-  width: 177px;
-  height: 30px;
-  line-height: 22px;
-  color: #01fefc;
-  font-weight: bolder;
-  background: var(--image-box-bg) no-repeat;
-  background-size: 80% 100%;
-  margin-bottom: 5px;
-}
-
-.search-area {
-  margin-bottom: 5px;
-}
-
-.title-top {
-  display: flex;
-  align-items: center;
-  gap: 10px;
-}
-
-.search-btn {
-  width: 85px;
-  height: 30px;
-  border: 1px solid #01fefc;
-  border-radius: 4px;
-  padding: 3px;
-  cursor: pointer;
-  flex-shrink: 0;
-}
-
-.time-select {
-  display: flex;
-  align-items: center;
-  padding-left: 10px;
-  margin-bottom: 8px;
-  gap: 6px;
-  white-space: nowrap;
-
-  .span {
-    color: #fff;
-    font-size: 13px;
-  }
-
-  .btn {
-    padding: 3px 8px;
-    background: #114268;
-    border: 1px solid transparent;
-    border-radius: 4px;
-    color: #fff;
-    cursor: pointer;
-    margin-right: 4px;
-    font-size: 13px;
-    white-space: nowrap;
-    transition: all 0.2s;
-
-    &.active {
-      background-color: #185f8e;
-      border-color: #2084c0;
-    }
-  }
-}
-
-.btn-item {
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  width: 100%;
-  height: 100%;
-  background-color: rgba(32, 166, 169);
-}
-
-.content-area {
-  height: calc(100% - 120px);
-}
-
-.content-title {
-  display: flex;
-  align-items: center;
-  height: 34px;
-  background: var(--image-box-bg2) no-repeat;
-  background-size: 100% 100%;
-  margin-bottom: 6px;
-}
-
-.title-item {
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  color: #01fefc;
-}
-
-.history-content {
-  height: calc(100% - 40px);
-  overflow-y: auto;
-
-  &::-webkit-scrollbar {
-    display: none;
-  }
-}
-
-.content-item {
-  display: flex;
-  align-items: center;
-  height: 36px;
-
-  &:nth-child(odd) {
-    background-color: #0e3455;
-  }
-
-  &:nth-child(even) {
-    background-color: #114268;
-  }
-}
-
-.item-text {
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  white-space: nowrap;
-  overflow: hidden;
-  text-overflow: ellipsis;
-}
-
-.col-time {
-  width: 90px;
-  flex-shrink: 0;
-}
-
-.col-rule {
-  width: 70px;
-  flex-shrink: 0;
-}
-
-.col-grade {
-  width: 70px;
-  flex-shrink: 0;
-}
-
-.col-status {
-  flex: 1;
-  padding: 0 10px;
-  justify-content: center;
-}
-
-.item-text1 {
-  color: #fc002a;
-}
-
-.item-text2 {
-  color: orange;
-}
-
-.zxm-input {
-  height: 42px;
-  color: #fff;
-  background-color: transparent;
-  border: none;
-  background: var(--image-box-bg1) no-repeat;
-  background-size: 100% 100%;
-}
-
-.zxm-input-sm {
-  padding: 0 20px;
-}
-</style>

+ 63 - 163
src/views/vent/monitorManager/hsqHome/components/LinkRuleEditor.vue

@@ -31,22 +31,22 @@
           </div>
           <div class="table-content">
             <div class="content-item" v-for="(item, index) in tableData" :key="index">
-              <div class="item-text">{{ item.index }}</div>
+              <div class="item-text">{{ item.indnex }}</div>
               <div class="item-text item-text1">
                 <span>{{ item.actionType }}</span>
               </div>
               <div class="item-text">
-                <span>{{ item.action }}</span>
+                <span> {{ item.action }}</span>
               </div>
               <div class="item-text">
-                <div class="switch" :class="{ active: item.qy === 1 }" @click="toggleSwitch(item)">
+                <div class="switch" :class="{ active: item.qy === 1 }">
                   <div class="switch-dot"></div>
                 </div>
               </div>
               <div class="item-text">{{ item.delayTime }}</div>
               <div class="item-text">{{ item.duration }}</div>
               <div class="item-text">
-                <span class="text-look">配置</span>
+                <span class="text-look">查看</span>
               </div>
             </div>
           </div>
@@ -58,12 +58,11 @@
         <div class="workflow-container">
           <div class="steps-wrapper">
             <div v-for="(step, index) in steps" :key="index" class="step-item">
-              <div class="step-icon" :class="`icon-${step.id}`">
-                <span class="icon-inner"></span>
-              </div>
-              <div class="step-frame">
+              <div class="step-icon" :class="`icon-${step.id}`"></div>
+              <div class="step-frame" :class="`frame-${step.id}`">
                 <span class="step-text">{{ step.name }}</span>
               </div>
+              <!-- 底部小圆点 -->
               <div class="step-dot">
                 <div class="dot" :class="{ active: step.status === 1 }"></div>
               </div>
@@ -78,9 +77,9 @@
 
 <script setup lang="ts">
 import { reactive, ref, onMounted, watch, computed } from 'vue';
-import basicBorder from '../BasicBorder.vue';
+import basicBorder from './basicBorder.vue';
 import { useLinkRuleStore } from '/@/store/modules/linkRule';
-import { getWarningDeviceList } from '../../configurable.api';
+import { getWarningDeviceList } from '../hsqHome.api.js';
 const props = defineProps<{
   selectedRow?: any | null;
 }>();
@@ -88,48 +87,25 @@ const props = defineProps<{
 const linkRuleStore = useLinkRuleStore();
 const currentSelectedRow = computed(() => linkRuleStore.getSelectedRow);
 
-interface ITitleItem {
-  label: string;
-}
-
-interface IActionItem {
-  index: string;
-  actionType: string;
-  action: string;
-  qy: number;
-  delayTime: string;
-  duration: string;
-}
-
-interface IStepItem {
-  id: string;
-  name: string;
-  status: number;
-}
-
-interface IFormField {
-  label: string;
-  key: keyof typeof formData;
-}
-
-const titleList = ref<ITitleItem[]>([
-  { label: '序号' },
-  { label: '动作类型' },
-  { label: '动作说明' },
-  { label: '启用' },
-  { label: '延迟' },
-  { label: '持续' },
-  { label: '操作' },
+let titleList = ref<any[]>([
+  { label: '序号', value: '1' },
+  { label: '动作类型', value: '2' },
+  { label: '动作说明', value: '3' },
+  { label: '启用', value: '4' },
+  { label: '延迟', value: '5' },
+  { label: '持续', value: '6' },
+  { label: '操作', value: '7' },
 ]);
 
-const tableData = ref<IActionItem[]>([
-  { index: '1', actionType: '声光报警器', action: '触发报警声+红色闪烁', qy: 1, delayTime: '0s', duration: '300s' },
-  { index: '2', actionType: '声光报警器', action: '触发报警声', qy: 1, delayTime: '1s', duration: '200s' },
-  { index: '3', actionType: '声光报警器', action: '红色闪烁', qy: 0, delayTime: '2s', duration: '180s' },
+let tableData = ref<any[]>([
+  { indnex: '1', actionType: '声光报警器', action: '触发报警声+红色闪烁', qy: 1, delayTime: '0s', duration: '300s' },
+  { indnex: '2', actionType: '声光报警器', action: '触发报警声', qy: 1, delayTime: '1s', duration: '200s' },
+  { indnex: '3', actionType: '声光报警器', action: '红色闪烁', qy: 0, delayTime: '2s', duration: '180s' },
 ]);
 
-const steps = ref<IStepItem[]>([
-  { id: 'alarm', name: '报警触发', status: 1 },
+// 流程图,添加 status 字段
+const steps = ref([
+  { id: 'alarm', name: '报警触发', status: 0 },
   { id: 'condition', name: '条件判断', status: 0 },
   { id: 'search', name: '查找规则', status: 0 },
   { id: 'action', name: '执行动作', status: 0 },
@@ -235,6 +211,11 @@ const updateFormData = (row: any) => {
 
 .long-list1 {
   --image-box-bg: url('@/assets/images/home-container/configurable/hsq/2-5.png');
+  --image-box-bg1: url('@/assets/images/home-container/configurable/hsq/2-13.png');
+  --image-box-bg2: url('@/assets/images/home-container/configurable/hsq/2-14.png');
+  --image-box-bg3: url('@/assets/images/home-container/configurable/hsq/2-15.png');
+  --image-box-bg4: url('@/assets/images/home-container/configurable/hsq/2-16.png');
+  --image-box-bg5: url('@/assets/images/home-container/configurable/hsq/2-17.png');
   --image-box-bg6: url('@/assets/images/home-container/configurable/hsq/2-24.png');
 
   position: relative;
@@ -255,22 +236,7 @@ const updateFormData = (row: any) => {
   }
   .basic-box2 {
     margin-top: 10px;
-
-    :deep(.basic-border) {
-      height: 100%;
-    }
-  }
-
-  .basic-box2 {
-    flex: 0.85;
-    min-height: 0;
-    margin-top: 10px;
-
-    :deep(.basic-border) {
-      height: 100%;
-    }
   }
-
   .edit-wrap {
     display: flex;
     width: 100%;
@@ -283,9 +249,7 @@ const updateFormData = (row: any) => {
     width: 80px;
     text-align: right;
     margin-right: 5px;
-    flex-shrink: 0;
   }
-
   .edit-right {
     background: #0e395d;
     width: 100%;
@@ -351,24 +315,6 @@ const updateFormData = (row: any) => {
     line-height: 25px;
     font-weight: bold;
     padding: 0 5px;
-
-    &:nth-child(1) {
-      color: #fc002a;
-    }
-
-    &:nth-child(2),
-    &:nth-child(3),
-    &:nth-child(4) {
-      color: #29a1d4;
-    }
-
-    &:nth-child(5) {
-      color: #46e8a3;
-    }
-
-    &:nth-child(6) {
-      margin-top: 10px;
-    }
   }
   .right-item:nth-child(4) {
     color: #fc002a;
@@ -390,13 +336,17 @@ const updateFormData = (row: any) => {
     background: var(--image-box-bg) no-repeat;
     background-size: 80% 100%;
     margin-bottom: 5px;
-    flex-shrink: 0;
   }
 
   .basic-table {
     height: 100%;
   }
 
+  .item-label1 {
+    width: 105px;
+    text-align: right;
+    margin-right: 5px;
+  }
   .table-title {
     display: flex;
     align-items: center;
@@ -420,21 +370,15 @@ const updateFormData = (row: any) => {
   .table-content {
     height: calc(100% - 40px);
     overflow-y: auto;
-
-    &::-webkit-scrollbar {
-      display: none;
-    }
   }
 
   .content-item {
     display: flex;
     align-items: center;
     height: 36px;
-
     &:nth-child(odd) {
       background-color: #0e3455;
     }
-
     &:nth-child(even) {
       background-color: #114268;
     }
@@ -454,6 +398,9 @@ const updateFormData = (row: any) => {
   .item-text1 {
     color: #fc002a;
   }
+  .item-text2 {
+    color: orange;
+  }
 
   .switch {
     width: 36px;
@@ -464,7 +411,6 @@ const updateFormData = (row: any) => {
     transition: all 0.2s ease;
     cursor: pointer;
     border: 1px solid #35d9e5;
-
     .switch-dot {
       width: 14px;
       height: 14px;
@@ -475,10 +421,9 @@ const updateFormData = (row: any) => {
       left: 1px;
       transition: all 0.2s ease;
     }
-
-    &.active .switch-dot {
-      left: 20px;
-    }
+  }
+  .switch.active .switch-dot {
+    left: 20px;
   }
 
   .text-look {
@@ -487,24 +432,20 @@ const updateFormData = (row: any) => {
   }
 }
 
+/*流程图*/
 .workflow-container {
   width: 100%;
-  height: 100%;
-  padding: 10px 0;
+  padding: 20px 0;
   position: relative;
-  display: flex;
-  align-items: center;
 }
 
 .steps-wrapper {
   display: flex;
   justify-content: space-between;
   align-items: flex-end;
-  width: 100%;
   padding: 0 20px;
   position: relative;
   z-index: 2;
-
   &::before {
     content: '';
     position: absolute;
@@ -516,7 +457,6 @@ const updateFormData = (row: any) => {
     background: #4a9eff;
     z-index: 1;
   }
-
   &::after {
     content: '';
     position: absolute;
@@ -528,7 +468,6 @@ const updateFormData = (row: any) => {
     background: #4a9eff;
     z-index: 1;
   }
-
   .steps-arrow {
     position: absolute;
     left: 5%;
@@ -539,12 +478,10 @@ const updateFormData = (row: any) => {
     background: url('@/assets/images/home-container/configurable/hsq/arrow.svg') center / contain no-repeat;
     z-index: 2;
   }
-
   .step-item:first-child .steps-arrow {
     display: none;
   }
 }
-
 .step-item {
   display: flex;
   flex-direction: column;
@@ -556,62 +493,26 @@ const updateFormData = (row: any) => {
 .step-icon {
   width: 56px;
   height: 56px;
-  display: flex;
-  align-items: center;
-  justify-content: center;
+  background-size: contain;
+  background-repeat: no-repeat;
+  background-position: center;
   margin-bottom: -6px;
-  position: relative;
-
-  .icon-inner {
-    width: 36px;
-    height: 36px;
-    border: 2px solid #4facfe;
-    transform: rotate(45deg);
-    background: linear-gradient(135deg, rgba(20, 80, 140, 0.9), rgba(10, 40, 80, 0.9));
-    box-shadow: 0 0 12px rgba(79, 172, 254, 0.5);
-    position: relative;
-
-    &::after {
-      content: '';
-      position: absolute;
-      inset: 6px;
-      border: 1px solid rgba(79, 172, 254, 0.6);
-    }
-  }
-
-  &.icon-alarm .icon-inner {
-    background: linear-gradient(135deg, rgba(180, 40, 40, 0.8), rgba(80, 20, 20, 0.9));
-    border-color: #ff6b6b;
-    box-shadow: 0 0 12px rgba(255, 77, 77, 0.5);
-  }
-
-  &.icon-condition .icon-inner {
-    background: linear-gradient(135deg, rgba(30, 100, 160, 0.9), rgba(15, 50, 90, 0.9));
-  }
-
-  &.icon-search .icon-inner {
-    background: linear-gradient(135deg, rgba(40, 120, 100, 0.9), rgba(20, 60, 50, 0.9));
-    border-color: #46e8a3;
-    box-shadow: 0 0 12px rgba(70, 232, 163, 0.4);
-  }
-
-  &.icon-action .icon-inner {
-    background: linear-gradient(135deg, rgba(160, 100, 30, 0.9), rgba(80, 50, 15, 0.9));
-    border-color: #ffa500;
-    box-shadow: 0 0 12px rgba(255, 165, 0, 0.4);
-  }
-
-  &.icon-log .icon-inner {
-    background: linear-gradient(135deg, rgba(60, 80, 160, 0.9), rgba(30, 40, 80, 0.9));
-  }
 }
 
-.icon-alarm,
-.icon-condition,
-.icon-search,
-.icon-action,
+.icon-alarm {
+  background-image: url('@/assets/images/home-container/configurable/hsq/bjcf.png');
+}
+.icon-condition {
+  background-image: url('@/assets/images/home-container/configurable/hsq/tjpd.png');
+}
+.icon-search {
+  background-image: url('@/assets/images/home-container/configurable/hsq/czgz.png');
+}
+.icon-action {
+  background-image: url('@/assets/images/home-container/configurable/hsq/zxdz.png');
+}
 .icon-log {
-  background-image: none;
+  background-image: url('@/assets/images/home-container/configurable/hsq/jlrz.png');
 }
 
 .step-frame {
@@ -656,11 +557,10 @@ const updateFormData = (row: any) => {
   background: #2c5a8c;
   border: 1px solid #4a9eff;
   transition: all 0.3s ease;
-
-  &.active {
-    background: #4facfe;
-    border-color: #4facfe;
-    box-shadow: 0 0 6px rgba(79, 172, 254, 0.6);
-  }
+}
+.dot.active {
+  background: #4facfe;
+  border-color: #4facfe;
+  box-shadow: 0 0 6px rgba(79, 172, 254, 0.6);
 }
 </style>

+ 33 - 24
src/views/vent/monitorManager/hsqHome/components/LinkRuleStats.vue

@@ -4,13 +4,40 @@
       <span>规则统计</span>
     </div>
     <div class="list-content">
-      <div class="stat-item" :class="item.type" v-for="(item, index) in statList" :key="index">
-        <div class="icon-wrap" :class="`icon-${index + 1}`"></div>
+      <div class="stat-item blue">
+        <div class="icon-wrap icon-1"></div>
         <div class="label-wrap">
-          <span>{{ item.label }}</span>
+          <span>总规则</span>
         </div>
         <div class="num-wrap">
-          <span>{{ item.value }}</span>
+          <span>10</span>
+        </div>
+      </div>
+      <div class="stat-item green">
+        <div class="icon-wrap icon-2"></div>
+        <div class="label-wrap">
+          <span>已启用</span>
+        </div>
+        <div class="num-wrap">
+          <span>7</span>
+        </div>
+      </div>
+      <div class="stat-item green">
+        <div class="icon-wrap icon-3"></div>
+        <div class="label-wrap">
+          <span>已禁用</span>
+        </div>
+        <div class="num-wrap">
+          <span>2</span>
+        </div>
+      </div>
+      <div class="stat-item blue">
+        <div class="icon-wrap icon-4"></div>
+        <div class="label-wrap">
+          <span>触发中</span>
+        </div>
+        <div class="num-wrap">
+          <span>2</span>
         </div>
       </div>
     </div>
@@ -19,19 +46,6 @@
 
 <script setup lang="ts">
 import { ref } from 'vue';
-
-interface IStatItem {
-  label: string;
-  value: number;
-  type: 'blue' | 'green';
-}
-
-const statList = ref<IStatItem[]>([
-  { label: '总规则', value: 10, type: 'blue' },
-  { label: '已启用', value: 7, type: 'green' },
-  { label: '已禁用', value: 2, type: 'green' },
-  { label: '触发中', value: 2, type: 'blue' },
-]);
 </script>
 
 <style lang="less" scoped>
@@ -49,9 +63,8 @@ const statList = ref<IStatItem[]>([
   position: relative;
   width: 100%;
   height: 100%;
-  padding: 10px 15px;
+  padding: 15px 15px;
   box-sizing: border-box;
-
   .list-title {
     width: 177px;
     height: 30px;
@@ -66,7 +79,7 @@ const statList = ref<IStatItem[]>([
   .list-content {
     display: flex;
     flex-wrap: wrap;
-    gap: 16px 20px;
+    gap: 20px;
   }
 
   .stat-item {
@@ -83,7 +96,6 @@ const statList = ref<IStatItem[]>([
     &.blue {
       background-image: var(--image-box-bg-blue);
     }
-
     &.green {
       background-image: var(--image-box-bg-green);
     }
@@ -100,15 +112,12 @@ const statList = ref<IStatItem[]>([
     &.icon-1 {
       background-image: var(--image-box-svg1);
     }
-
     &.icon-2 {
       background-image: var(--image-box-svg3);
     }
-
     &.icon-3 {
       background-image: var(--image-box-svg4);
     }
-
     &.icon-4 {
       background-image: var(--image-box-svg2);
     }

+ 392 - 132
src/views/vent/monitorManager/hsqHome/components/LinkRuleTable.vue

@@ -1,79 +1,328 @@
 <template>
   <div class="search-table">
-    <div class="search-area">
+    <div class="search-area" v-if="config.type === 'C'">
       <div class="list-title">
         <span>联动规则列表</span>
       </div>
-      <div class="search-btn">
-        <div class="btn-item">新增</div>
+      <div class="search-btn" @click="handleAdd">
+        <div class="btn-item">配置</div>
       </div>
     </div>
-    <div class="content-area">
-      <div class="content-title">
-        <div class="title-item" v-for="(item, index) in titleList" :key="index">{{ item.label }}</div>
+    <div v-if="config.type === 'D'" class="search-new">
+      <div class="list-title">
+        <span>联动日志</span>
+      </div>
+      <div class="time-picker-wrap">
+        <div class="form-row">
+          <label class="form-label">开始时间:</label>
+          <a-date-picker
+            v-model:value="filterForm.startDate"
+            placeholder="请选择开始时间"
+            class="date-picker"
+            show-time
+            format="YYYY-MM-DD HH:mm:ss"
+            style="width: 300px !important"
+          />
+        </div>
       </div>
-      <div class="history-content">
-        <div
-          class="content-item"
-          :class="{ 'row-active': activeIndex === index }"
-          v-for="(item, index) in tableData"
-          :key="index"
-          @click="activeIndex = index"
-        >
-          <div class="item-text">{{ item.ruleId }}</div>
-          <div class="item-text">{{ item.ruleName }}</div>
-          <div class="item-text item-text1">{{ item.condition }}</div>
-          <div class="item-text">{{ item.action }}</div>
-          <div class="item-text item-text2">{{ item.status }}</div>
-          <div class="item-text">
-            <span class="text-look">编辑</span>
-          </div>
+      <div class="time-select">
+        <span class="span">快捷时间:</span>
+        <div class="btn" :class="{ active: timeType === 1 }" @click="setTimeRange(1)">今日</div>
+        <div class="btn" :class="{ active: timeType === 2 }" @click="setTimeRange(2)">近三天</div>
+        <div class="btn" :class="{ active: timeType === 3 }" @click="setTimeRange(3)">近一月</div>
+        <div class="search-btn" @click="confirmDetail">
+          <div class="btn-item">详情</div>
         </div>
       </div>
     </div>
+    <div class="content-area">
+      <div class="table-container">
+        <table class="warning-table">
+          <colgroup>
+            <col
+              v-for="col in config.type === 'C' ? config.columns : filterDeviceColumns"
+              :key="col.dataIndex || col.prop"
+              :style="{ width: col.width }"
+            />
+          </colgroup>
+          <thead class="table-header">
+            <tr>
+              <th v-for="col in config.type === 'C' ? config.columns : filterDeviceColumns" :key="col.dataIndex || col.prop">
+                {{ col.title || col.name }}
+              </th>
+            </tr>
+          </thead>
+          <tbody class="table-body">
+            <tr
+              v-for="(row, index) in realTableData"
+              :key="index"
+              class="table-row"
+              :class="config.type === 'C' ? { box_active: isCurrentSelectRow(row) } : ''"
+              @click="config.type === 'C' ? handleRowClick(row) : ''"
+            >
+              <td v-for="col in config.type === 'C' ? config.columns : filterDeviceColumns" :key="col.dataIndex || col.prop" class="table-cell">
+                <template v-if="config.type === 'C' && col.prop === 'operation'">
+                  <span class="text-look" @click="handleEditClick(row)">编辑</span>
+                </template>
+                <template v-else>
+                  <span class="text-ellipsis" :title="getCellText(row, col)">
+                    {{ getCellText(row, col) }}
+                  </span>
+                </template>
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+    </div>
+    <DeviceModal
+      @register="registerModal"
+      :show-tab="true"
+      @saveOrUpdate="saveOrUpdateHandler"
+      :device-type="deviceType"
+      :select-sys-alarm-id="currentSelectInfo.alarmId"
+      :select-sys-id="currentSelectInfo.sysId"
+    />
+    <RuleTableModal
+      @register="register"
+      @update="onSubmit"
+      :destroy-on-close="true"
+      @success="handleModalSuccess"
+      :form-schemas="workFaceWarningSchemas"
+    />
   </div>
 </template>
 
 <script setup lang="ts">
-import { ref } from 'vue';
-
-interface ITitleItem {
-  label: string;
-}
-
-interface IRuleItem {
-  ruleId: string;
-  ruleName: string;
-  condition: string;
-  action: string;
-  status: string;
-}
-
-const activeIndex = ref(1);
-
-const titleList = ref<ITitleItem[]>([
-  { label: '规则ID' },
-  { label: '规则名称' },
-  { label: '触发条件' },
-  { label: '联动动作' },
-  { label: '状态' },
-  { label: '操作' },
-]);
-
-const tableData = ref<IRuleItem[]>([
-  { ruleId: 'LINK001', ruleName: '温度报警联动', condition: '温度>60℃', action: '声光报警', status: '启用' },
-  { ruleId: 'LINK001', ruleName: '温度报警联动', condition: '温度>60℃', action: '声光报警', status: '启用' },
-  { ruleId: 'LINK001', ruleName: '温度报警联动', condition: '温度>60℃', action: '声光报警', status: '启用' },
-  { ruleId: 'LINK001', ruleName: '温度报警联动', condition: '温度>60℃', action: '声光报警', status: '启用' },
-  { ruleId: 'LINK001', ruleName: '温度报警联动', condition: '温度>60℃', action: '声光报警', status: '启用' },
-  { ruleId: 'LINK001', ruleName: '温度报警联动', condition: '温度>60℃', action: '声光报警', status: '启用' },
-  { ruleId: 'LINK001', ruleName: '温度报警联动', condition: '温度>60℃', action: '声光报警', status: '启用' },
-]);
+import { ref, reactive, watch, onMounted, nextTick, computed } from 'vue';
+import dayjs, { Dayjs } from 'dayjs';
+import { message } from 'ant-design-vue';
+import DeviceModal from './deviceModal.vue';
+import { useModal } from '/@/components/Modal';
+import { getAlarmLogList } from '../hsqHome.api.js';
+import { getTableHeaderColumns } from '/@/hooks/web/useWebColumns';
+import { func } from 'vue-types';
+import { useLinkRuleStore } from '/@/store/modules/linkRule';
+import RuleTableModal from '../../../deviceManager/comment/warningTabel/RuleTableModal.vue';
+import { FormSchema } from '/@/components/Table';
+import { warningLogEdit, warningLogList } from '../../../deviceManager/comment/warningTabel/warning.api';
+import { workFaceWarningFormSchemas } from '../../../deviceManager/comment/warningTabel/warning.data';
+const FIXED_STRTYPE = 'sys_openair_fire';
+const deviceType = ref('managesys');
+const isUpdate = ref(false);
+const instanceId = ref(`${Date.now()}_${Math.floor(Math.random() * 10000)}`);
+const [registerModal, { openModal, closeModal }] = useModal(instanceId.value);
+const linkRuleStore = useLinkRuleStore();
+const emit = defineEmits(['row-change', 'table-refresh']);
+const currentSelectInfo = ref({
+  sysId: '',
+  alarmId: '',
+});
+const alarmMap: Record<string, string> = {
+  '102': '黄色预警',
+  '103': '橙色预警',
+  '104': '红色预警',
+};
+// 获取单元格文本内容
+const getCellText = (row: any, col: any) => {
+  const field = col.dataIndex ?? col.prop;
+  const val = row[field];
+  if (field === 'alarmLevel' && alarmMap[val]) {
+    return alarmMap[val];
+  }
+  return val ?? '-';
+};
+const deviceColumns = getTableHeaderColumns('alarm_history') as [];
+
+// 过滤日志只展示指定4列
+const filterDeviceColumns = computed(() => {
+  const showKeys = ['devicename', 'wardescrip', 'starttime', 'warntime'];
+  return deviceColumns.filter((item) => showKeys.includes(item.dataIndex));
+});
+
+const realTableData = computed(() => {
+  return props.config.type === 'D' ? alarmList.value : tableList.value;
+});
+const props = defineProps<{
+  config: {
+    type: string;
+    tableReadFrom: string;
+    columns: {
+      name: string;
+      prop: string;
+      width?: string;
+    }[];
+  };
+  data: Record<string, any>;
+  selectedRow?: any | null;
+}>();
+
+const handleEditClick = (row: any) => {
+  openModalRule(true, {
+    isUpdate: true,
+    record: row,
+  });
+};
+// 弹窗保存成功触发
+const handleModalSuccess = () => {
+  emit('table-refresh');
+};
+const workFaceWarningSchemas: FormSchema[] = [
+  ...workFaceWarningFormSchemas,
+  {
+    label: '关联条目',
+    field: 'relatedEntries',
+    component: 'ApiSelect',
+    componentProps: {
+      labelField: 'alarmName',
+      valueField: 'id',
+      resultField: 'records',
+      api: warningLogList.bind(null, { sysId: currentSelectInfo.value.sysId }),
+    },
+  },
+  {
+    label: '预警后自动控制',
+    field: 'isAutoControl',
+    component: 'RadioGroup',
+    componentProps: {
+      //options里面由一个一个的radio组成,支持disabled
+      options: [
+        { label: '是', value: true },
+        { label: '否', value: false },
+      ],
+    },
+  },
+  {
+    label: '解除后自动复位',
+    field: 'isAutoReset',
+    component: 'RadioGroup',
+    componentProps: {
+      //options里面由一个一个的radio组成,支持disabled
+      options: [
+        { label: '是', value: true },
+        { label: '否', value: false },
+      ],
+    },
+  },
+];
+const [register, { openModal: openModalRule, closeModal: closeModalRule }] = useModal();
+async function onSubmit(flag, values) {
+  await warningLogEdit(values);
+  closeModalRule();
+  // 通知外层刷新表格
+  handleModalSuccess();
+}
+// C类型数据源
+const tableList = ref<any[]>([]);
+// D类型数据源
+const alarmList = ref<any[]>([]);
+
+const timeType = ref(3);
+const filterForm = reactive<{ startDate: Dayjs | null }>({
+  startDate: null,
+});
+// 默认选中第一条(仅Type='C'时执行)
+const autoSelectFirstRow = async () => {
+  await nextTick();
+  if (props.config.type !== 'C') return;
+
+  const list = realTableData.value;
+  if (list.length > 0) {
+    const firstRow = list[0];
+    emit('row-change', firstRow);
+    linkRuleStore.setSelectedRow(firstRow);
+    currentSelectInfo.value.sysId = firstRow.sysId ?? '';
+    currentSelectInfo.value.alarmId = firstRow.alarmId ?? '';
+  } else {
+    emit('row-change', null);
+    linkRuleStore.clearSelectedRow();
+    currentSelectInfo.value = { sysId: '', alarmId: '' };
+  }
+};
+const isCurrentSelectRow = (row: any) => {
+  if (!props.selectedRow) return false;
+  return props.selectedRow === row;
+};
+
+const handleRowClick = (row: any) => {
+  emit('row-change', row);
+  linkRuleStore.setSelectedRow(row);
+  currentSelectInfo.value.sysId = row.sysId ?? '';
+  currentSelectInfo.value.alarmId = row.alarmId ?? '';
+};
+
+async function getAlarmHistory() {
+  const res = await getAlarmLogList({
+    column: 'createTime',
+    deviceKind: null,
+    isOk: false,
+    pageNo: 1,
+    pageSize: 100,
+    startTime: filterForm.startDate?.format('YYYY-MM-DD HH:mm:ss'),
+    systemType: 'ventS',
+  });
+  alarmList.value = res.records || [];
+}
+
+onMounted(() => {
+  getAlarmHistory();
+  autoSelectFirstRow();
+  setTimeRange(3);
+});
+
+// 监听父组件传入数据,赋值给tableList(Type为C时生效)
+watch(
+  () => props.data,
+  (newData) => {
+    const list = newData?.[props.config.tableReadFrom];
+    tableList.value = list || [];
+    autoSelectFirstRow();
+  },
+  { deep: true, immediate: true }
+);
+
+async function handleAdd() {
+  isUpdate.value = false;
+  openModal(true, {});
+}
+
+const saveOrUpdateHandler = async () => {
+  try {
+    message.success(isUpdate.value ? '编辑成功' : '新增成功');
+    closeModal();
+  } catch (error) {
+    message.error('保存失败,请联系管理员');
+  }
+};
+
+const setTimeRange = (type: number) => {
+  timeType.value = type;
+  let start: Dayjs;
+  switch (type) {
+    case 1:
+      start = dayjs().startOf('day');
+      break;
+    case 2:
+      start = dayjs().subtract(3, 'day').startOf('day');
+      break;
+    case 3:
+      start = dayjs().subtract(30, 'day').startOf('day');
+      break;
+    default:
+      start = dayjs().startOf('day');
+  }
+  filterForm.startDate = start;
+  getAlarmHistory();
+};
+
+// 跳转详情
+function confirmDetail() {
+  window.open('/monitorChannel/device-monitor/warningHistory/home');
+}
 </script>
 
 <style lang="less" scoped>
 @import '/@/design/theme.less';
-
 .search-table {
   --image-box-bg: url('@/assets/images/home-container/configurable/hsq/2-5.png');
   --image-box-bg2: url('@/assets/images/home-container/configurable/hsq/2-24.png');
@@ -83,7 +332,6 @@ const tableData = ref<IRuleItem[]>([
   padding: 10px;
   box-sizing: border-box;
 }
-
 .list-title {
   width: 177px;
   height: 30px;
@@ -94,7 +342,6 @@ const tableData = ref<IRuleItem[]>([
   background-size: 80% 100%;
   margin-bottom: 5px;
 }
-
 .search-area {
   height: 42px;
   display: flex;
@@ -102,7 +349,6 @@ const tableData = ref<IRuleItem[]>([
   align-items: center;
   margin-bottom: 5px;
 }
-
 .search-btn {
   width: 85px;
   height: 30px;
@@ -111,7 +357,55 @@ const tableData = ref<IRuleItem[]>([
   padding: 3px;
   cursor: pointer;
 }
-
+.search-new .time-picker-wrap {
+  padding: 10px;
+  .form-row {
+    display: flex;
+    align-items: center;
+    margin-bottom: 8px;
+    .form-label {
+      width: 60px;
+      font-size: 13px;
+      color: #fff;
+      flex-shrink: 0;
+    }
+  }
+}
+:deep(.zxm-picker) {
+  border: 1px solid #3ae1ff !important;
+  background-color: #104064 !important;
+}
+:deep(.zxm-picker-input > input) {
+  color: #fff !important;
+}
+:deep(.zxm-picker-suffix) {
+  color: #fff !important;
+}
+.time-select {
+  display: flex;
+  align-items: center;
+  padding-left: 10px;
+  margin-bottom: 8px;
+  gap: 6px;
+  white-space: nowrap;
+  .span {
+    color: #fff;
+    font-size: 13px;
+  }
+  .btn {
+    padding: 3px 8px;
+    background: #114268;
+    border: 1px solid transparent;
+    border-radius: 4px;
+    color: #fff;
+    cursor: pointer;
+    font-size: 13px;
+    &.active {
+      background-color: #185f8e;
+      border-color: #2084c0;
+    }
+  }
+}
 .btn-item {
   display: flex;
   justify-content: center;
@@ -120,94 +414,52 @@ const tableData = ref<IRuleItem[]>([
   height: 100%;
   background-color: rgba(32, 166, 169);
 }
-
 .content-area {
-  height: calc(100% - 47px);
+  height: 100%;
 }
-
-.content-title {
-  display: flex;
-  align-items: center;
-  height: 34px;
-  background: var(--image-box-bg2) no-repeat;
-  background-size: 100% 100%;
-  margin-bottom: 6px;
+.table-container {
+  width: 100%;
+  height: 100%;
+  overflow-y: auto;
 }
-
-.title-item {
-  display: flex;
-  flex: 1;
-  justify-content: center;
-  align-items: center;
-  color: #01fefc;
-  white-space: nowrap;
-  overflow: hidden;
-  text-overflow: ellipsis;
+.warning-table {
+  width: 100%;
+  table-layout: fixed;
+  border-collapse: collapse;
 }
-
-.history-content {
-  height: calc(100% - 40px);
-  overflow-y: auto;
-
-  &::-webkit-scrollbar {
-    display: none;
-  }
+.table-header tr {
+  position: sticky;
+  top: 0;
+  z-index: 10;
+  background: var(--image-box-bg2) no-repeat;
+  background-size: 100% 100%;
 }
-
-.content-item {
-  display: flex;
-  align-items: center;
+.table-row {
   height: 36px;
-  cursor: pointer;
-
   &:nth-child(odd) {
     background-color: #0e3455;
   }
-
   &:nth-child(even) {
     background-color: #114268;
   }
-
-  &.row-active {
-    border: 1px solid #f4933d;
-    box-shadow: inset 0 0 6px rgba(244, 147, 61, 0.3);
+  &.box_active {
+    box-shadow: 2px 0 0 0 #ffa024, inset 0 0 0 2px #ffa024;
   }
 }
 
-.item-text {
-  display: flex;
-  flex: 1;
-  justify-content: center;
-  align-items: center;
-  white-space: nowrap;
-  overflow: hidden;
-  text-overflow: ellipsis;
-  padding: 0 4px;
-}
-
-.title-item:nth-child(2),
-.item-text:nth-child(2) {
-  flex: 1.8;
-}
-
-.title-item:nth-child(3),
-.item-text:nth-child(3) {
-  flex: 1.5;
-}
-
-.title-item:nth-child(4),
-.item-text:nth-child(4) {
-  flex: 1.5;
-}
-
-.item-text1 {
-  color: #f4933d;
+th,
+.table-cell {
+  text-align: center;
+  padding: 5px;
+  font-size: 14px;
+  box-sizing: border-box;
+  vertical-align: middle;
 }
-
-.item-text2 {
-  color: #4cf3a6;
+th {
+  font-weight: bold;
+  color: #38e4ef;
+  height: 30px;
 }
-
 .text-look {
   padding: 0 3px;
   margin: 0 2px;
@@ -215,4 +467,12 @@ const tableData = ref<IRuleItem[]>([
   background-color: #2484bc;
   cursor: pointer;
 }
+/* 文字省略样式 */
+.text-ellipsis {
+  display: block;
+  width: 100%;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+}
 </style>

+ 76 - 0
src/views/vent/monitorManager/hsqHome/components/deviceModal.vue

@@ -0,0 +1,76 @@
+<template>
+  <BasicModal
+    v-bind="$attrs"
+    @register="registerModal"
+    :title="title"
+    width="1000px"
+    :showCancelBtn="false"
+    :showOkBtn="false"
+    :footer="null"
+    :destroyOnClose="true"
+    :mask-closable="false"
+    @cancel="closeModalFn"
+  >
+    <a-tabs v-if="props.showTab" v-model:activeKey="activeKey">
+      <a-tab-pane key="5" tab="配置预警设备" force-render>
+        <template v-if="activeKey == '5'">
+          <BackWindDeviceTable :deviceId="selectSysId" />
+        </template>
+      </a-tab-pane>
+
+      <a-tab-pane key="6" tab="配置控制设备" force-render>
+        <template v-if="activeKey == '6'">
+          <ManagerWarningTable :deviceId="selectSysId" />
+        </template>
+      </a-tab-pane>
+    </a-tabs>
+  </BasicModal>
+</template>
+<script lang="ts" setup>
+import { computed, unref, inject, reactive, ref } from 'vue';
+import { BasicModal, useModalInner } from '/@/components/Modal';
+import FormModal from '../../../deviceManager/comment/FormModal.vue';
+import BackWindDeviceTable from '../../../deviceManager/comment/warningTabel/index3.vue';
+import ManagerWarningTable from '../../../deviceManager/comment/warningTabel/index1.vue';
+
+const props = defineProps({
+  showTab: { type: Boolean, required: true },
+  deviceType: { type: String, default: '' },
+  selectSysId: { type: String, default: '' },
+  selectSysAlarmId: { type: String, default: '' },
+});
+
+const emit = defineEmits(['saveOrUpdate', 'register', 'closeModal']);
+const isUpdate = inject('isUpdate');
+const deviceData = inject('formData') as any;
+const deviceType = inject('deviceType') as any;
+const record = reactive({});
+const activeKey = ref('5');
+
+const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
+  setModalProps({ confirmLoading: false });
+  for (const key in deviceData) delete deviceData[key];
+  Object.assign(deviceData, data.record);
+  activeKey.value = '5';
+});
+
+// 标题
+const title = '编辑';
+
+const closeModalFn = () => {
+  activeKey.value = '5';
+  closeModal();
+  emit('closeModal');
+};
+</script>
+<style scoped lang="less">
+::v-deep .suffix {
+  height: 32px;
+  line-height: 32px;
+  margin-left: 5px;
+  color: #fff;
+}
+::v-deep .j-box-bottom-button-float {
+  background: none !important;
+}
+</style>

+ 9 - 13
src/views/vent/monitorManager/hsqHome/components/navMenu.vue

@@ -1,12 +1,7 @@
 <template>
   <div class="nav-menu">
-    <div
-      :class="activeIndex == index ? 'menu-item-active' : 'menu-item'"
-      v-for="(item, index) in menuList"
-      :key="index"
-      @click="handlerClick(item, index)"
-      >{{ item.label }}</div
-    >
+    <div :class="activeIndex == index ? 'menu-item-active' : 'menu-item'" v-for="(item, index) in menuList" :key="index"
+      @click="handlerClick(item, index)">{{ item.label }}</div>
   </div>
 </template>
 
@@ -21,7 +16,7 @@ let menuList = ref<any[]>([
   { label: '设备管理', value: 'sbgl' },
   { label: '联动配置', value: 'ldpz' },
   { label: '系统管理', value: 'xtgl' },
-  { label: '大屏展示', value: 'dpzs' },
+  // { label: '大屏展示', value: 'dpzs' },
 ]);
 let $emit = defineEmits(['changeMenu']);
 
@@ -36,8 +31,7 @@ function handlerClick(item, index) {
 @import '/@/design/theme.less';
 
 @{theme-deepblue} {
-  .nav-menu {
-  }
+  .nav-menu {}
 }
 
 .nav-menu {
@@ -48,7 +42,7 @@ function handlerClick(item, index) {
   justify-content: space-around;
   align-items: center;
   position: relative;
-  width: 90%;
+  width: 100%;
   height: 100%;
   background: var(--image-modal-nav) no-repeat;
   background-size: 100% 100%;
@@ -64,7 +58,8 @@ function handlerClick(item, index) {
     background: var(--image-modal-nav1) no-repeat;
     background-size: 100% 100%;
     cursor: pointer;
-    user-select: none; /* 禁止选择文本 */
+    user-select: none;
+    /* 禁止选择文本 */
   }
 
   .menu-item-active {
@@ -76,7 +71,8 @@ function handlerClick(item, index) {
     background: var(--image-modal-nav2) no-repeat;
     background-size: 100% 100%;
     cursor: pointer;
-    user-select: none; /* 禁止选择文本 */
+    user-select: none;
+    /* 禁止选择文本 */
   }
 }
 </style>

+ 8 - 1
src/views/vent/monitorManager/hsqHome/hsqHome.api.ts

@@ -12,7 +12,10 @@ enum Api {
   managesysList = '/safety/ventanalyManageSystem/list', //获取场景信息
   monitorSystem = '/monitor/system', //场景设备列表
   queryRoleAndUserNum = '/sys/role/queryRoleAndUserNum', //查询角色和用户数量
-
+  getWarningDeviceList = '/safety/managesysAlarm/list', //获取配置预警设备数据
+  getAlarmLogList = '/monitor/groupCompany/getAlarmLogList',  // 设备预警历史查询
+  warningList = '/safety/managesysAlarmInfo/list',//预警条目list
+  
 }
 /**
 * 日志列表接口
@@ -75,3 +78,7 @@ export const monitorSystem = (params) => defHttp.post({ url: Api.monitorSystem,
 * @param params
 */
 export const queryRoleAndUserNum = (params) => defHttp.get({ url: Api.queryRoleAndUserNum, params });
+
+export const getWarningDeviceList = (params) => defHttp.get({ url: Api.getWarningDeviceList, params });
+export const getAlarmLogList = (params) => defHttp.post({ url: Api.getAlarmLogList, params });
+export const warningList = (params) => defHttp.get({ url: Api.warningList, params });

+ 38 - 1
src/views/vent/monitorManager/hsqHome/hsqHome.data.ts

@@ -165,7 +165,7 @@ export let warnTitle = [
   { label: '操作', value: 'operation' },
 ]
 
-export let alarmColumns:any[] =[
+export let alarmColumns: any[] = [
   {
     name: '时间',
     prop: 'starttime',
@@ -179,3 +179,40 @@ export let alarmColumns:any[] =[
     prop: 'alarmLevelC',
   },
 ]
+
+//联动规则配置
+export let warnTableConfig: any = {
+  readFrom: '',
+  type: 'C',
+  tableReadFrom: 'warnInfo',
+  columns: [
+    {
+      name: '报警条目',
+      prop: 'alarmName',
+    },
+    {
+      name: '预警等级',
+      prop: 'alarmLevel',
+    },
+    {
+      name: '所属系统',
+      prop: 'systemType_dictText',
+    },
+    {
+      name: '预警类型',
+      prop: 'alarmType_dictText',
+    },
+    {
+      name: '创建人',
+      prop: 'createBy',
+    },
+    {
+      name: '操作',
+      prop: 'operation',
+    },
+  ],
+}
+export let warnTableConfigD: any = {
+  readFrom: '',
+  type: 'D',
+}

+ 1 - 1
src/views/vent/monitorManager/hsqHome/index.vue

@@ -97,7 +97,7 @@ function changeMenu(param: MenuKey) {
     left: 50%;
     top: 60px;
     transform: translate(-50%, 0);
-    width: 1000px;
+    width: 1028px;
     height: 68px;
     z-index: 9999;
   }

+ 60 - 4
src/views/vent/monitorManager/hsqHome/linkConfiguration.vue

@@ -2,17 +2,19 @@
   <div class="link-configuration">
     <div class="link-left">
       <div class="link-left-top">
-        <LinkRuleTable />
+        <LinkRuleTable :data="warnResult" :config="warnTableConfig" :selected-row="selectRuleRow"
+          @row-change="onRowClick" @table-refresh="handleTableRefresh" />
       </div>
       <div class="link-left-bottom">
         <LinkRuleStats />
       </div>
     </div>
     <div class="link-center">
-      <LinkRuleEditor />
+      <LinkRuleEditor :selected-row="selectRuleRow" />
     </div>
     <div class="link-right">
-      <LinkLogPanel />
+      <LinkRuleTable :data="warnResult" :config="warnTableConfigD" :selected-row="selectRuleRow"
+        @row-change="onRowClick" @table-refresh="handleTableRefresh" />
     </div>
   </div>
 </template>
@@ -21,7 +23,61 @@
 import LinkRuleTable from './components/LinkRuleTable.vue';
 import LinkRuleStats from './components/LinkRuleStats.vue';
 import LinkRuleEditor from './components/LinkRuleEditor.vue';
-import LinkLogPanel from './components/LinkLogPanel.vue';
+import { warningList } from './hsqHome.api.js';
+import { onMounted, onUnmounted, ref } from 'vue';
+import { warnTableConfig, warnTableConfigD } from './hsqHome.data.js'
+
+const warnResult = ref({
+  warnInfo: [] as any[],
+});
+// 存储当前选中行
+const selectRuleRow = ref<null | Record<string, any>>(null);
+/** 定时获取监测数据定时器 */
+let timer: null | NodeJS.Timeout = null;
+
+/**
+ * 定时获取监测数据
+ * 通过定时器循环调用数据获取方法,更新表格数据
+ *
+ * @param flag - 是否立即执行(首次调用时传true跳过延时)
+ */
+function getMonitor(flag?: boolean) {
+  timer = setTimeout(async () => {
+    await getWarningList();
+    if (timer) {
+      timer = null;
+    }
+    getMonitor();
+  }, flag ? 0 : 30000);
+}
+
+async function getWarningList() {
+  const res = await warningList({ sysId: '2074416476136718337' });
+  const newWarnData = {
+    ...warnResult.value,
+    warnInfo: res.records,
+  };
+  warnResult.value = newWarnData
+  console.log(warnResult.value, 'rnTable格数据')
+}
+const onRowClick = (singleRow) => {
+  selectRuleRow.value = singleRow;
+};
+// 接收 RuleTable 子组件刷新信号,向上抛给顶层父组件
+const handleTableRefresh = () => {
+  getWarningList();
+};
+
+onMounted(() => {
+  getMonitor(true);
+});
+
+onUnmounted(() => {
+  if (timer) {
+    clearTimeout(timer);
+    timer = null;
+  }
+});
 </script>
 
 <style lang="less" scoped>