Browse Source

feat(newControlPage): 新设备控制页

wangpx 7 tháng trước cách đây
mục cha
commit
78db57043e

+ 11 - 3
ui/src/router/index.js

@@ -286,17 +286,25 @@ export const constantRoutes = [
   //   component: () => import('@/views/hnyzConfiguratePage/Na2SO4_G3FJ2/index'),
   //   name: 'Na2SO4_G3FJ2',
   // },
-  { // 页面设计器
+  {
     path: '/deviceState',
     hidden: false,
     component: () => import('@/views/simulator/deviceState/index'),
     name: 'DeviceState',
     meta: { title: '设备模拟页', icon: 'edit' }
   },
+  // 新控制页面(使用 Element Plus 响应式布局)
+  {
+    path: '/newControlPage/reaction',
+    component: () => import('@/views/newControlPage/reaction/index'),
+    name: 'NewReactionControl',
+    hidden: 0,
+    meta: { title: '新控制页面', icon: 'tool' }
+  },
   { // 页面设计器
     path: '/pageDesigner',
-    component: Layout,
-    hidden: true,
+    // component: Layout,
+    // hidden: true,
     name: 'PageDesigner',
     meta: { title: '页面设计器', icon: 'edit' },
     children: [

+ 2 - 1
ui/src/views/dcsForm2/flow/index.vue

@@ -39,7 +39,7 @@
 
     <el-table v-loading="loading" :data="flowList" @selection-change="handleSelectionChange">
       <el-table-column type="selection" width="55" align="center" />
-      <el-table-column label="流程id" align="center" prop="flowId" />
+      <!-- <el-table-column label="流程id" align="center" prop="flowId" /> -->
       <el-table-column label="流程名称" align="center" prop="flowName" />
       <el-table-column label="流程标识" align="center" prop="flowCode" />
       <el-table-column label="流程顺序" align="center" prop="sort" />
@@ -121,6 +121,7 @@ const data = reactive({
     pageNum: 1,
     pageSize: 10,
     flowName: null,
+    flowAttribution: null,
     status: null,
   },
   rules: {

+ 206 - 0
ui/src/views/newControlPage/components/DeviceConfigItem.vue

@@ -0,0 +1,206 @@
+<template>
+    <div class="device_item">
+        <div class="device_name_code">
+            <div class="device_name">
+                <span v-for="(name, index) in deviceName.split('||')" :key="index">{{ name }}</span>
+            </div>
+            <div class="device_code">{{ deviceCode }}</div>
+        </div>
+        <div class="device_set">
+            <div class="set_item" v-for="(setting, index) in validSettings" :key="index">
+                <div class="set_title">
+                    {{ setting.title }}
+                </div>
+                <component v-if="setting.item.component && componentMap[setting.item.component]"
+                    :is="componentMap[setting.item.component]" v-bind="setting.item.props || {}"
+                    @update:value="handleItemUpdate(setting, $event)"
+                    @click:button="handleItemUpdate(setting, $event)" />
+                <div v-else class="error-message">
+                    组件配置错误: {{ setting.item?.component || '未定义组件' }}
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import { defineProps, defineEmits, computed } from 'vue'
+import { defineAsyncComponent } from 'vue'
+
+// 定义组件映射
+const componentMap = {
+    statusSet: defineAsyncComponent(() => import('./statusSet.vue')),
+    statusView: defineAsyncComponent(() => import('./statusView.vue')),
+    numberInput: defineAsyncComponent(() => import('./numberInput.vue'))
+}
+
+// 定义props
+const props = defineProps({
+    // 设备名称
+    deviceName: {
+        type: String,
+        required: true
+    },
+    deviceCode: {
+        type: String,
+    },
+    // 设置列表
+    settingList: {
+        type: Array,
+        required: true,
+        default: () => []
+        /*
+        格式示例:
+        [
+            {
+                title: "当前模式", // 设置项标题
+                item: {
+                    component: "statusSet", // 组件名称
+                    props: {
+                        buttonInfo: [
+                            { value: 0, type: 'success', label: '正吹', active: 1 },
+                            { value: 1, type: 'danger', label: '反吹', active: 0 }
+                        ]
+                    }
+                }
+            },
+            {
+                title: "模式设置",
+                item: {
+                    component: "statusSet",
+                    props: {
+                        buttonInfo: [
+                            { value: 0, type: 'success', label: '开', active: 1 },
+                            { value: 1, type: 'danger', label: '关', active: 0 }
+                        ]
+                    }
+                }
+            },
+            {
+                title: "状态",
+                item: {
+                    component: "statusView",
+                    props: {
+                        active: 2
+                    }
+                }
+            },
+            {
+                title: "速度",
+                item: {
+                    component: "numberInput",
+                    props: {
+                        value: 500,
+                        unit: "转",
+                        max: 5000
+                    }
+                }
+            }
+        ]
+        */
+    }
+})
+
+// 过滤有效的设置项
+const validSettings = computed(() => {
+    return props.settingList.filter(setting => setting && setting.item)
+})
+
+// 定义emits
+const emit = defineEmits(['update', 'change'])
+
+// 处理子组件值更新
+const handleItemUpdate = (setting, newValue) => {
+    // console.log('DeviceConfigItem 接收到子组件更新:', {
+    //     deviceName: props.deviceName,
+    //     settingTitle: setting.title,
+    //     newValue: newValue,
+    //     setting: setting
+    // })
+
+    const eventData = {
+        title: setting.title,
+        value: newValue,
+        setting: setting
+    }
+
+    emit('update', eventData)
+    emit('change', eventData)
+}
+</script>
+
+<style lang="scss" scoped>
+.device_item {
+    display: inline-flex;
+    padding: 4px;
+    justify-content: flex-start;
+    align-items: center;
+    gap: 4px;
+    background: #21335F;
+    color: #E2FEFF;
+
+    &:hover {
+        transform: translateY(-2px);
+        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
+    }
+
+    .device_name_code {
+        display: flex;
+        max-width: 120px;
+        // max-width: 100px;
+        min-height: 80px;
+        align-self: stretch;
+        padding: 10px;
+        justify-content: center;
+        gap: 10px;
+        flex-direction: column;
+        align-items: center;
+        background: #316297;
+
+        .device_name {
+            display: flex;
+            flex-direction: column;
+            font-family: OPPOSans;
+            font-size: 16px;
+            font-style: normal;
+            font-weight: 400;
+            line-height: normal;
+        }
+    }
+
+    .device_set {
+        display: flex;
+        padding: 4px;
+        flex-direction: column;
+        align-items: flex-start;
+        gap: 5px;
+        font-size: 14px;
+
+        .set_item {
+            display: flex;
+            align-items: center;
+            gap: 10px;
+
+            .set_title {
+                width: 57px;
+                color: #E2FEFF;
+                text-align: right;
+                font-family: OPPOSans;
+                font-size: 14px;
+                font-style: normal;
+                font-weight: 400;
+                line-height: normal;
+            }
+        }
+    }
+
+    .error-message {
+        color: #ff6b6b;
+        font-size: 12px;
+        padding: 4px 8px;
+        background: rgba(255, 107, 107, 0.1);
+        border-radius: 4px;
+        border: 1px solid rgba(255, 107, 107, 0.3);
+    }
+}
+</style>

+ 125 - 0
ui/src/views/newControlPage/components/StatusCard.vue

@@ -0,0 +1,125 @@
+<template>
+    <div class="status_card" shadow="hover">
+        <div class="card_header">
+            <span class="card_title">{{ title }}</span>
+            <span class="card_subtitle">{{ subtitle }}</span>
+        </div>
+        <div class="device_grid">
+            <DeviceConfigItem v-for="(device, index) in deviceList" :key="index" :deviceName="device.deviceName"
+                :deviceCode="device.deviceCode" :settingList="device.settingList" @change="handleDeviceConfigChange" />
+        </div>
+    </div>
+</template>
+
+<script setup>
+import { defineProps, defineEmits } from 'vue'
+import DeviceConfigItem from './DeviceConfigItem.vue'
+
+// 定义props
+const props = defineProps({
+    // 卡片标题
+    title: {
+        type: String,
+        required: true
+    },
+    // 卡片副标题(设备编号)
+    subtitle: {
+        type: String,
+        // required: true
+    },
+    // 设备列表
+    deviceList: {
+        type: Array,
+        required: true,
+        default: () => []
+        /*
+        格式示例:
+        [
+            {
+                deviceName: "工作模式",
+                settingList: [
+                    {
+                        title: "当前模式",
+                        item: {
+                            component: "statusSet",
+                            props: {
+                                buttonInfo: [...]
+                            }
+                        }
+                    }
+                ]
+            }
+        ]
+        */
+    }
+})
+
+// 定义emits
+const emit = defineEmits(['deviceChange'])
+
+// 处理设备配置变化
+const handleDeviceConfigChange = (data) => {
+    // console.log('StatusCard 接收到设备配置变化:', {
+    //     cardTitle: props.title,
+    //     cardSubtitle: props.subtitle,
+    //     ...data
+    // })
+
+    emit('deviceChange', {
+        cardTitle: props.title,
+        cardSubtitle: props.subtitle,
+        ...data
+    })
+}
+</script>
+
+<style lang="scss" scoped>
+.status_card {
+    max-width: 1610px;
+    display: flex;
+    padding: 10px;
+    flex-direction: column;
+    align-items: center;
+    gap: 5px;
+    border-radius: 10px 10px 0 0;
+    border: 2px solid #3B51A2;
+    background: linear-gradient(180deg, rgba(52, 81, 156, 0.89) -6.07%, rgba(52, 139, 201, 0.00) 20.29%);
+
+    .card_header {
+        display: flex;
+        padding: 10px;
+        flex-direction: column;
+        justify-content: flex-end;
+        align-items: center;
+        gap: 10px;
+
+        .card_title {
+            color: #9ED3FF;
+            font-family: OPPOSans;
+            font-size: 24px;
+            font-style: normal;
+            font-weight: 400;
+            line-height: normal;
+        }
+
+        .card_subtitle {
+            color: #9ED3FF;
+            font-family: OPPOSans;
+            font-size: 20px;
+            font-style: normal;
+            font-weight: 400;
+            line-height: normal;
+        }
+    }
+
+    .device_grid {
+        display: flex;
+        max-width: 1590px;
+        row-gap: 5px;
+        column-gap: 5px;
+        flex-wrap: wrap;
+        justify-content: flex-start;
+        align-items: flex-start;
+    }
+}
+</style>

+ 125 - 0
ui/src/views/newControlPage/components/numberInput.vue

@@ -0,0 +1,125 @@
+<template>
+    <div class="set_value">
+        <div class="number_input">
+            <el-input-number v-model="localValue" :min="min" :max="max" :disabled="disable" :step="step"
+                controls-position="right" :controls="false">
+                <!-- <template #decrease-icon>
+                    <el-icon>
+                        <Minus />
+                    </el-icon>
+                </template>
+<template #increase-icon>
+                    <el-icon>
+                        <Plus />
+                    </el-icon>
+                </template> -->
+            </el-input-number>
+            <div class="set_unit">
+                {{ unit }}
+            </div>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue';
+const props = defineProps({
+    value: {
+        type: Number,
+        default: 0,
+        required: true
+    },
+    unit: {
+        type: String,
+        default: ''
+    },
+    min: {
+        type: Number,
+        default: 0.001
+    },
+    max: {
+        type: Number,
+        default: 9999
+    },
+    step: {
+        type: Number,
+        default: 1
+    },
+    disable: {
+        type: Boolean,
+        default: false
+    }
+})
+
+const emit = defineEmits(['update:value'])
+const localValue = computed({
+    get() {
+        return props.value
+    },
+    set(newValue) {
+        emit('update:value', newValue)
+    }
+})
+</script>
+
+<style lang="scss">
+.set_value {
+    max-width: 84px;
+    max-height: 66px;
+    row-gap: 4px;
+    column-gap: 4px;
+    display: flex;
+    flex-direction: row;
+    flex-wrap: wrap;
+
+    .number_input {
+        // width: 55px;
+        display: flex;
+        align-items: center;
+
+        .el-input-number {
+            width: 40px;
+
+            .el-input-number__decrease,
+            .el-input-number__increase {
+                width: 20px;
+            }
+
+            .el-input__wrapper {
+                border-radius: 5px;
+                background: #0F1E39;
+                padding-left: 5px;
+                // padding-right: 22px;
+                padding-right: 5px;
+
+                border: none !important;
+                box-shadow: none !important;
+
+                .el-input__inner {
+                    width: 30px;
+                    color: #E2FEFF;
+                    font-family: OPPOSans;
+                    font-size: 14px;
+                    font-style: normal;
+                    font-weight: 400;
+                    line-height: normal;
+                }
+            }
+        }
+
+        .el-input.is-disabled .el-input__inner {
+            -webkit-text-fill-color: #E2FEFF;
+            color: #E2FEFF;
+        }
+
+        .set_unit {
+            margin-left: 5px;
+            font-family: OPPOSans;
+            font-size: 10px;
+            font-style: normal;
+            font-weight: 400;
+            line-height: normal;
+        }
+    }
+}
+</style>

+ 48 - 0
ui/src/views/newControlPage/components/statusSet.vue

@@ -0,0 +1,48 @@
+<template>
+    <div class="set_value">
+        <el-button :type="item.active == 1 ? item.type : 'info'" v-for="(item, index) in buttonInfo" :key="index" class="set_button" @click="handleClick(item.value)">{{ item.label }}</el-button>
+    </div>
+</template>
+
+<script setup>
+const props = defineProps({
+    buttonInfo: {
+        type: Array,
+        default: () => [
+            { value: 0, label: '开', type: 'success' }
+        ]
+    },
+    disable: {
+        type: Boolean,
+        default: false
+    }
+})
+const emit = defineEmits(['click:button'])
+const handleClick = (value) => {
+    if (props.disable) return
+    emit('click:button', value)
+}
+</script>
+
+<style lang="scss">
+.set_value {
+    max-width: 100px;
+    max-height: 66px;
+    row-gap: 4px;
+    column-gap: 4px;
+    display: flex;
+    flex-direction: row;
+    flex-wrap: wrap;
+
+    .set_button {
+        display: flex;
+        width: 38px;
+        height: 28px;
+        padding: 5px;
+        justify-content: center;
+        align-items: center;
+        gap: 5px;
+        margin-left: 0;
+    }
+}
+</style>

+ 61 - 0
ui/src/views/newControlPage/components/statusView.vue

@@ -0,0 +1,61 @@
+<template>
+    <div class="set_value">
+        <div class="signal">
+            <div class="square greed" :class="active == 0 ? 'active' : ''"></div>
+            <div class="square red" :class="active == 1 ? 'active' : ''"></div>
+            <div class="square yellow" :class="active == 2 ? 'active' : ''"></div>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import { ref } from 'vue';
+
+const props = defineProps({
+    active: {
+        type: Number,
+        default: 0
+    }
+})
+</script>
+
+<style lang="scss">
+.set_value {
+    max-width: 84px;
+    max-height: 66px;
+    row-gap: 4px;
+    column-gap: 4px;
+    display: flex;
+    flex-direction: row;
+    flex-wrap: wrap;
+
+    .signal {
+        display: flex;
+        align-items: center;
+        gap: 5px;
+
+        .square {
+            width: 20px;
+            height: 20px;
+            aspect-ratio: 1/1;
+            opacity: 0.5;
+        }
+
+        .red {
+            background-color: #DF0000;
+        }
+
+        .greed {
+            background-color: #00D35F;
+        }
+
+        .yellow {
+            background-color: #FFC926;
+        }
+
+        .active {
+            opacity: 1;
+        }
+    }
+}
+</style>

+ 588 - 0
ui/src/views/newControlPage/reaction/index.vue

@@ -0,0 +1,588 @@
+<template>
+    <div class="page">
+        <!-- 固定头部 -->
+        <div class="fixed-header" ref="fixedHeader">
+            <HeaderComponent title="硫酸钠-反应控制台" backTo="/controlPage/flowSelect" />
+            <!-- <PageNav :items="navItems" :currentCode="flowCode" /> -->
+        </div>
+        <!-- 主内容区 -->
+        <div class="content_page">
+            <div class="device_status_container">
+                <!-- 1#反应釜 状态卡片 -->
+                <!-- <div class="status_card" shadow="hover">
+                    <div class="card_header">
+                        <span class="card_title">1#反应釜</span>
+                        <span class="card_subtitle">C3001</span>
+                    </div>
+                    <div class="device_grid">
+                        <DeviceConfigItem :deviceName="workModeConfig.deviceName"
+                            :settingList="workModeConfig.settingList" @change="handleDeviceConfigChange" />
+                        <DeviceConfigItem :deviceName="feedConfig.deviceName" :settingList="feedConfig.settingList"
+                            @change="handleDeviceConfigChange" />
+                    </div>
+                </div> -->
+                <StatusCard title="1#反应釜" subtitle="C3001" :deviceList="deviceList"
+                    @deviceChange="handleDeviceConfigChange">
+                </StatusCard>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script setup>
+const pageCode = 'MGM';
+const flowId = 9;//当前页面流程Id
+import { onMounted, computed, reactive, ref } from 'vue';
+import { useRoute } from 'vue-router';
+const route = useRoute();
+import { useEquipmentLayout } from '@/hooks/useEquipmentLayout'
+import { useValveHelper } from '@/hooks/useValveHelper'
+import { updateZTPageConfig } from '@/api/dcs/configurePage';
+import { getMainSetParam } from '@/api/hnyz/param'
+import { setValues } from '@/api/dcs/flowControl'
+import { stompClient } from '@/utils/ws/stompClient';
+
+import DeviceConfigItem from '../components/DeviceConfigItem.vue';
+import StatusCard from '../components/StatusCard.vue';
+
+import HeaderComponent from '@/components/DCS/HeaderComponent.vue';
+import PageNav from '@/components/GeneralComponents/control/PageNavComponent.vue';
+import { getFlowNav } from '@/api/hnyz/flow';
+const flowCode = computed(() => route.params.flowCode);
+const navItems = ref();
+const fixedHeader = ref(null);
+const headerHeight = ref(0);
+// 计算固定头部高度
+const calculateHeaderHeight = () => { headerHeight.value = fixedHeader.value?.offsetHeight || 0; }
+onMounted(async () => {
+    const res = await getFlowNav('Na2SO4', 'flowSelect');
+    navItems.value = res.data;
+    calculateHeaderHeight();
+    window.addEventListener('resize', calculateHeaderHeight);
+});
+
+onMounted(async () => {
+    // loadInitialData();
+});
+
+const num = ref(1)
+const speedValue = ref(500)
+const weightValue = ref(500)
+const flowValue = ref(100)
+const temperatureValue = ref(25)
+// 工作模式配置
+const workModeConfig = computed(() => ({
+    deviceName: '工作模式',
+    settingList: [
+        {
+            title: '当前模式',
+            item: {
+                component: 'statusSet',
+                props: {
+                    buttonInfo: [
+                        { value: 0, type: 'success', label: '正吹', active: 1 },
+                        { value: 1, type: 'danger', label: '反吹', active: 0 }
+                    ],
+                    disable: true
+                }
+            }
+        },
+        {
+            title: '模式设置',
+            item: {
+                component: 'statusSet',
+                props: {
+                    buttonInfo: [
+                        { value: 0, type: 'success', label: '开', active: 1 },
+                        { value: 1, type: 'danger', label: '关', active: 0 },
+                        { value: 2, type: 'success', label: '正吹', active: 0 },
+                        { value: 3, type: 'success', label: '反吹', active: 0 }
+                    ]
+                }
+            }
+        }
+    ]
+}))
+
+// 原矿进料配置
+const feedConfig = computed(() => ({
+    deviceName: '原矿进料',
+    settingList: [
+        {
+            title: '状态',
+            item: {
+                component: 'statusView',
+                props: {
+                    active: 2
+                }
+            }
+        },
+        {
+            title: '速度',
+            item: {
+                component: 'numberInput',
+                props: {
+                    value: speedValue.value,
+                    unit: '转',
+                    max: 5000
+                }
+            }
+        },
+        {
+            title: '进料量',
+            item: {
+                component: 'numberInput',
+                props: {
+                    value: weightValue.value,
+                    unit: 'T'
+                }
+            }
+        }
+    ]
+}))
+
+const deviceList = computed(() => [
+    {
+        deviceName: '原矿进料',
+        settingList: [
+            {
+                title: '状态',
+                item: {
+                    component: 'statusView',
+                    props: {
+                        active: 2
+                    }
+                }
+            },
+            {
+                title: '操作',
+                item: {
+                    component: 'statusSet',
+                    props: {
+                        buttonInfo: [
+                            { value: 0, type: 'success', label: '启动', active: 1 },
+                            { value: 1, type: 'danger', label: '停止', active: 0 },
+                        ]
+                    }
+                }
+            },
+            {
+                title: '实时转速',
+                code: 'yljksjzs',
+                item: {
+                    component: 'numberInput',
+                    props: {
+                        value: speedValue.value,
+                        unit: '%',
+                        disable: true
+                    }
+                }
+            },
+            {
+                title: '设定转速',
+                code: 'yljksdzs',
+                item: {
+                    component: 'numberInput',
+                    props: {
+                        value: speedValue.value,
+                        unit: '%',
+                        min: 0,
+                        max: 5000
+                    }
+                }
+            },
+            {
+                title: '进料量',
+                code: 'yljkjll',
+                item: {
+                    component: 'numberInput',
+                    props: {
+                        value: weightValue.value,
+                        unit: 'kg',
+                        min: 0,
+                    }
+                }
+            }
+        ]
+    },
+    {
+        deviceName: '1#硫酸||进料泵',
+        deviceCode: 'P5003',
+        settingList: [
+            {
+                title: '状态',
+                item: {
+                    component: 'statusView',
+                    props: {
+                        active: 2
+                    }
+                }
+            },
+            {
+                title: '操作',
+                item: {
+                    component: 'statusSet',
+                    props: {
+                        buttonInfo: [
+                            { value: 0, type: 'success', label: '启动', active: 1 },
+                            { value: 1, type: 'danger', label: '停止', active: 0 },
+                        ]
+                    }
+                }
+            }
+        ]
+    },
+    {
+        deviceName: '2#硫酸||进料泵',
+        deviceCode: 'P5004',
+        settingList: [
+            {
+                title: '状态',
+                item: {
+                    component: 'statusView',
+                    props: {
+                        active: 2
+                    }
+                }
+            },
+            {
+                title: '操作',
+                item: {
+                    component: 'statusSet',
+                    props: {
+                        buttonInfo: [
+                            { value: 0, type: 'success', label: '启动', active: 1 },
+                            { value: 1, type: 'danger', label: '停止', active: 0 },
+                        ]
+                    }
+                }
+            }
+        ]
+    },
+    {
+        deviceName: '硫酸流量计',
+        deviceCode: 'FIT3001',
+        settingList: [
+            {
+                title: '实时值',
+                code: 'lslljssz',
+                item: {
+                    component: 'numberInput',
+                    props: {
+                        value: 100,
+                        unit: 'm³/h',
+                        disable: true
+                    }
+                }
+            },
+            {
+                title: '设定值',
+                code: 'lslljsdz',
+                item: {
+                    component: 'numberInput',
+                    props: {
+                        value: 100,
+                        unit: 'm³/h',
+                        min: 0,
+                    }
+                }
+            }
+        ]
+    },
+    {
+        deviceName: '1#反应釜||温度计',
+        deviceCode: 'TT3001',
+        settingList: [
+            {
+                title: '实时值',
+                code: 'fyfwdjssz',
+                item: {
+                    component: 'numberInput',
+                    props: {
+                        value: 0,
+                        unit: '°C',
+                        disable: true
+                    }
+                }
+            },
+            {
+                title: '设定值',
+                code: 'fyfwdjsdz',
+                item: {
+                    component: 'numberInput',
+                    props: {
+                        value: 0,
+                        unit: '°C',
+                        min: 0,
+                    }
+                }
+            }
+        ]
+    },
+    {
+        deviceName: '1#反应釜||搅拌电机',
+        deviceCode: 'M3001',
+        settingList: [
+            {
+                title: '状态',
+                item: {
+                    component: 'statusView',
+                    props: {
+                        active: 2
+                    }
+                }
+            },
+            {
+                title: '操作',
+                item: {
+                    component: 'statusSet',
+                    props: {
+                        buttonInfo: [
+                            { value: 0, type: 'success', label: '启动', active: 1 },
+                            { value: 1, type: 'danger', label: '停止', active: 0 },
+                        ]
+                    }
+                }
+            }
+        ]
+    },
+    {
+        deviceName: '1#反应釜||PH计',
+        deviceCode: 'PH3001',
+        settingList: [
+            {
+                title: '实时值',
+                code: 'fyfphjssz',
+                item: {
+                    component: 'numberInput',
+                    props: {
+                        value: 0,
+                        disable: true
+                    }
+                }
+            },
+            {
+                title: '设定值',
+                code: 'fyfphjsdz',
+                item: {
+                    component: 'numberInput',
+                    props: {
+                        value: 0,
+                        min: 0,
+                    }
+                }
+            }
+        ]
+    },
+    {
+        deviceName: '硫酸进料阀',
+        deviceCode: 'QQF5004',
+        settingList: [
+            {
+                title: '状态',
+                item: {
+                    component: 'statusView',
+                    props: {
+                        active: 2
+                    }
+                }
+            },
+            {
+                title: '操作',
+                item: {
+                    component: 'statusSet',
+                    props: {
+                        buttonInfo: [
+                            { value: 0, type: 'success', label: '开', active: 1 },
+                            { value: 1, type: 'danger', label: '关', active: 0 },
+                        ]
+                    }
+                }
+            }
+        ]
+    },
+    {
+        deviceName: '硫酸进料阀',
+        deviceCode: 'QQF5003',
+        settingList: [
+            {
+                title: '状态',
+                item: {
+                    component: 'statusView',
+                    props: {
+                        active: 2
+                    }
+                }
+            },
+            {
+                title: '操作',
+                item: {
+                    component: 'statusSet',
+                    props: {
+                        buttonInfo: [
+                            { value: 0, type: 'success', label: '开', active: 1 },
+                            { value: 1, type: 'danger', label: '关', active: 0 },
+                        ]
+                    }
+                }
+            }
+        ]
+    },
+    {
+        deviceName: '1#反应釜||液位计',
+        deviceCode: 'LT3101',
+        settingList: [
+            {
+                title: '实时值',
+                code: 'fyfywjssz',
+                item: {
+                    component: 'numberInput',
+                    props: {
+                        value: 0,
+                        disable: true
+                    }
+                }
+            },
+            {
+                title: '设定值',
+                code: 'fyfywjsdz',
+                item: {
+                    component: 'numberInput',
+                    props: {
+                        value: 0,
+                        min: 0,
+                    }
+                }
+            }
+        ]
+    }
+])
+
+// const {
+//     generatePageParams,
+// } = useEquipmentLayout(pageCode)
+
+// 根据设备类型返回组件
+function getComponentByType(equipmentType) {
+    const type = Number(equipmentType);
+    if ([1, 5].includes(type)) return ValveControlComponent;
+    if (type === 2) return PumpControlComponent;
+    if (type === 4) return SensorControl;
+    return 'div';
+}
+
+// const { getDataArrByCode, getValveStatusArr } = useValveHelper(computed(() => [
+//     ...deviceDataGroup.VALVES,
+//     ...deviceDataGroup.SENSORS
+// ]))
+const handleChange = (value) => {
+    console.log("handleChange", value)
+}
+
+// 处理速度变化
+const handleSpeedChange = (newValue) => {
+    console.log("速度变化:", newValue)
+    // TODO
+}
+
+// 处理进料量变化
+const handleWeightChange = (newValue) => {
+    console.log("进料量变化:", newValue)
+    // TODO
+}
+
+// 处理设备配置变化
+const handleDeviceConfigChange = (data) => {
+    console.log('主页面接收到设备配置变化:', data)
+    const { title, value, setting, cardTitle, cardSubtitle } = data
+
+    // console.log('卡片信息:', { cardTitle, cardSubtitle })
+    // console.log('设置项信息:', { title, value, setting })
+
+    if (title === '设定转速') {
+        console.log('处理速度变化:', value)
+        handleSpeedChange(value)
+        speedValue.value = value
+        // 同步更新配置中的值
+        const speedSetting = feedConfig.value.settingList.find(item => item.title === '速度')
+        if (speedSetting) {
+            speedSetting.item.props.value = value
+        }
+    } else if (title === '进料量') {
+        console.log('处理进料量变化:', value)
+        handleWeightChange(value)
+        weightValue.value = value
+        // 同步更新配置中的值
+        const weightSetting = feedConfig.value.settingList.find(item => item.title === '进料量')
+        if (weightSetting) {
+            weightSetting.item.props.value = value
+        }
+    } else {
+        console.log('处理其他设置项变化:', { title, value })
+    }
+}
+</script>
+
+<style lang="scss">
+@import '@/assets/styles/dcs/hnyzConfiguratePage.scss';
+
+.page {
+    // width: 1920px;
+    // height: 1080px;
+    // background-color: #030709;
+
+    .content_page {
+        position: relative;
+        width: 100%;
+        // min-height: 100vh;
+        padding: 20px;
+        margin-top: 30px;
+        display: flex;
+        justify-content: flex-start;
+        align-items: flex-start;
+
+        .device_status_container {
+            display: inline-flex;
+            padding: 10px;
+            flex-direction: column;
+            align-items: flex-start;
+            gap: 20px;
+            margin: 0 97px 0;
+
+            .light-control-card {
+                background: rgba(255, 255, 255, 0.95);
+                border-radius: 8px;
+
+                .card_header {
+                    display: flex;
+                    justify-content: space-between;
+                    align-items: center;
+
+                    .card_title {
+                        font-size: 18px;
+                        font-weight: 600;
+                        color: #303133;
+                    }
+                }
+
+                .light-button-grid {
+                    display: grid;
+                    grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
+                    gap: 12px;
+
+                    .el-button+.el-button {
+                        margin-left: 0;
+                    }
+                }
+
+                .light-button {
+                    width: 100%;
+                    font-size: 12px;
+                    padding: 8px 4px;
+                    line-height: 1.2;
+                }
+            }
+        }
+    }
+}
+</style>