liudl
2025-03-13 b71144811c970ddb7296f5243f722ec6b00cf805
Web/src/views/device/deviceMonitor/index.vue
@@ -1,56 +1,58 @@
<template>
    <el-container>
        <el-aside style="width: auto;height: auto;">
        <el-aside style="width: auto; height: auto;">
            <el-card class="box-card">
                <div slot="header" class="linefix">
                    <span>输送线</span>
                    <div class="lineStatus"></div>
                    <div :class="['lineStatus', stationValue.status ? 'device-status-0' : 'device-status-1']"></div>
                </div>
                <div class="choosefix">
                    <el-select v-model="lineValue" placeholder="请选择">
                        <el-option
                        v-for="item in lineOptions"
                        :key="item.value"
                        :label="item.label"
                        :value="item.value">
                        </el-option>
                    <el-select v-model="lineValue" placeholder="请选择" @change="handleLineChange('item', $event)">
                        <el-option v-for="item in lineOptions" :key="item.id" :label="item.text"
                            :value="item.id"></el-option>
                    </el-select>
                    <el-select v-model="stationValue" placeholder="请选择" style="margin-top: 10px;">
                        <el-option
                        v-for="item in stationOptions"
                        :key="item.value"
                        :label="item.label"
                        :value="item.value">
                    <el-select v-model="stationValue" placeholder="请选择" style="margin-top: 10px;" filterable
                        value-key="stationNum">
                        <el-option v-for="item in listStationsData" :key="item.id" :label="item.stationNum"
                            :value="item">
                        </el-option>
                    </el-select>
                </div>
                <div class="lineValuefix" >
                    <el-form label-position="left" label-width="60px">
                <div class="lineValuefix">
                    <el-form label-position="left" label-width="80px">
                        <el-form-item label="任务号">
                            <el-input></el-input>
                            <el-input v-model="stationValue.taskNo"></el-input>
                        </el-form-item>
                        <el-form-item label="任务类型">
                            <el-input></el-input>
                            <el-select clearable v-model="stationValue.taskType" placeholder="请选择任务类型">
                                <el-option v-for="(item, index) in dl('TaskTypeEnum')" :key="index"
                                    :value="Number(item.value)" :label="`${item.name} [${item.value}]`"></el-option>
                            </el-select>
                        </el-form-item>
                        <el-form-item label="起始工位">
                            <el-input></el-input>
                            <el-input v-model="stationValue.startLocatNo"></el-input>
                        </el-form-item>
                        <el-form-item label="目的工位">
                            <el-input></el-input>
                            <el-input v-model="stationValue.endLocatNo"></el-input>
                        </el-form-item>
                        <el-form-item label="托盘码">
                            <el-input></el-input>
                            <el-input v-model="stationValue.palletNo"></el-input>
                        </el-form-item>
                        <el-form-item label="PLC">
                            <el-input v-model="stationValue.plc"></el-input>
                        </el-form-item>
                        <el-form-item label="WCS">
                            <el-input v-model="stationValue.wcs"></el-input>
                        </el-form-item>
                        <el-form-item label="状态">
                            <el-input></el-input>
                            <el-input :value="stationValue.status ? '在线' : '离线'" readonly></el-input>
                        </el-form-item>
                    </el-form>
                </div>
                <div class="lineButtonfix">
                    <el-form label-position="left" label-width="60px">
                    <el-form label-position="left" label-width="80px">
                        <el-form-item>
                            <el-button type="primary">写入</el-button>
                            <el-button>设置</el-button>
                            <el-button @click="openDialog">设置</el-button>
                        </el-form-item>
                    </el-form>
                </div>
@@ -58,220 +60,262 @@
        </el-aside>
        <el-main style="padding: 0 0 0 5px;">
            <div class="card-container">
                <el-card class="other-box-card" v-for="deviceInfo in deviceList" :key="deviceInfo.id">
                <el-card class="other-box-card" v-for="deviceInfo in listStackingMachineData" :key="deviceInfo.id">
                    <div slot="header" class="linefix">
                        <span>{{ deviceInfo.name }}</span>
                        <div :class="['lineStatus', { 'device-status-0': deviceInfo.status === 0 }, { 'device-status-1': deviceInfo.status === 1 }]"></div>
                        <span>{{ deviceInfo.text }}</span>
                        <div
                            :class="['lineStatus', { 'device-status-0': deviceInfo.status === true }, { 'device-status-1': deviceInfo.status === false }]">
                        </div>
                    </div>
                    <div class="otherValuefix" >
                        <el-form label-position="left" label-width="60px">
                    <div class="otherValuefix">
                        <el-form label-position="left" label-width="80px">
                            <el-form-item label="任务号">
                                <el-input v-model="deviceInfo.taskNumber"></el-input>
                                <el-input v-model="deviceInfo.taskNo"></el-input>
                            </el-form-item>
                            <el-form-item label="任务类型">
                                <el-input></el-input>
                                <el-select clearable="" v-model="deviceInfo.taskType" placeholder="请选择状态">
                                    <el-option v-for="(item, index) in dl('TaskTypeEnum')" :key="index"
                                        :value="Number(item.value)" :label="`${item.name} [${item.value}] `" />
                                </el-select>
                            </el-form-item>
                            <el-form-item label="起始工位">
                                <el-input v-model="deviceInfo.startLocatNo"></el-input>
                            </el-form-item>
                            <el-form-item label="目的工位">
                                <el-input v-model="deviceInfo.endLocatNo"></el-input>
                            </el-form-item>
                            <el-form-item label="托盘码">
                                <el-input v-model="deviceInfo.palletNo"></el-input>
                            </el-form-item>
                            <el-form-item label="PLC">
                                <el-input></el-input>
                                <el-input v-model="deviceInfo.plc"></el-input>
                            </el-form-item>
                            <el-form-item label="WCS">
                                <el-input></el-input>
                                <el-input v-model="deviceInfo.wcs"></el-input>
                            </el-form-item>
                            <el-form-item label="状态">
                                <el-input></el-input>
                                <el-input :value="deviceInfo.status ? '在线' : '离线'" readonly></el-input>
                            </el-form-item>
                        </el-form>
                    </div>
                    <div class="otherButtonfix">
                        <el-form label-position="left" label-width="60px">
                        <el-form label-position="left">
                            <el-form-item>
                                <el-button type="primary">写入</el-button>
                                <el-button>设置</el-button>
                                <el-button @click="write(deviceInfo)">写入</el-button>
                            </el-form-item>
                        </el-form>
                    </div>
                </el-card>
            </div>
        </el-main>
    </el-container>
        <setting ref="settingDialogRef" :title="title" v-model:listStationsData="listStationsData"
            v-model:stationValue="stationValue" />
    </el-container>
</template>
  <script lang="ts" setup>
  import { ref, reactive } from 'vue';
  const lineOptions=[{
          value: '001',
          label: '一楼输送线'
        }, {
          value: '002',
          label: '二楼输送线'
        }, {
          value: '003',
          label: '三楼输送线'
    }];
  const lineValue='001';
  const stationOptions=[{
          value: '200',
          label: '200'
        }, {
          value: '202',
          label: '202'
        }, {
          value: '300',
          label: '300'
    }];
  const stationValue='200';
  const deviceList=[
        {
          id: 1,
          name: '1号码垛机器人',
          taskNumber: 'T000001',
          taskType: '',
          plc: '',
          wcs: '',
          status: 0
        },
        {
          id: 2,
          name: '2号码垛机器人',
          taskNumber: '',
          taskType: '',
          plc: '',
          wcs: '',
          status: 1
        },
        {
          id: 3,
          name: '3号码垛机器人',
          taskNumber: '',
          taskType: '',
          plc: '',
          wcs: '',
          status: 0
        },{
          id: 4,
          name: '4号码垛机器人',
          taskNumber: '',
          taskType: '',
          plc: '',
          wcs: '',
          status: 1
        },{
          id: 5,
          name: '5号码垛机器人',
          taskNumber: '',
          taskType: '',
          plc: '',
          wcs: '',
          status: 0
        },{
          id: 6,
          name: '6号码垛机器人',
          taskNumber: '',
          taskType: '',
          plc: '',
          wcs: '',
          status: 0
        },{
          id: 7,
          name: '7号码垛机器人',
          taskNumber: '',
          taskType: '',
          plc: '',
          wcs: '',
          status: ''
        },{
          id: 8,
          name: '8号码垛机器人',
          taskNumber: '',
          taskType: '',
          plc: '',
          wcs: '',
          status: 0
<script lang="ts" setup>
import { ref, onMounted  } from 'vue';
import { listWcsDevice, writeValue } from '/@/api/wcs/wcsDevice';
import { getDictDataItem as di, getDictDataList as dl } from '/@/utils/dict-utils';
import { listWcsPlc } from '/@/api/wcs/wcsPlc';
import { ElMessageBox, ElMessage } from 'element-plus';
import setting from '/@/views/device/deviceMonitor/component/setting.vue'
import { signalR,stopConnection } from './signalR';
//连接signalR 监听变更
onMounted(async () => {
    signalR.off('PublicPlcDevice');
    signalR.on('PublicPlcDevice', (data: any) => {
        //todo 需要测试
        if (data.type == 0) {
            var index = listStackingMachineData.value.findIndex(s => s.id == data.id);
            if (index !== -1) {
                listStackingMachineData.value.splice(index, 1, data);
            }
        }
      ]
  </script>
  <style scoped>
   .text {
        font-size: 14px;
    }
        else if (data.type == 1) {
            lineOptions.value.forEach(s => {
                var index = stations.value[s.id].findIndex(s => s.id == data.id);
                if (index !== -1) {
                    stations.value[s.id].splice(index, 1, data);
                }
            });
            if (stationValue.value.id == data.id) {
                stationValue.value = data;
            }
        }
    });
});
    .item {
        margin-bottom: 18px;
const stations = ref<any>([]);
const listStationsData = ref<any>([]);
const listStackingMachineData = ref<any>([]);
const lineOptions = ref<any>([]);
const lineValue = ref(1);
const title = ref<string>('');
const stationValue = ref<any>({
    taskNo: '',
    taskType: '',
    startLocatNo: '',
    endLocatNo: '',
    plc: '',
    wcs: '',
    status: false
});
const settingDialogRef = ref();
// 打开打印页面
const openDialog = async () => {
    settingDialogRef.value.openDialog(stationValue);
}
const write = async (row: any) => {
    await writeValue(row);
    ElMessage.success('写入成功!');
}
// 查询操作
const handleQuery = async () => {
    const listplc = await listWcsPlc({ type: 1 });
    lineOptions.value = listplc.data.result;
    lineValue.value = listplc.data.result[0].id;
    const res = await listWcsDevice();
    listStackingMachineData.value = res.data.result.filter(s => s.type == 0);
    const listConveyorLineData = res.data.result.filter(s => s.type == 1);
    listplc.data.result.forEach(s => {
        stations.value[s.id] = listConveyorLineData.filter(c => c.plcId === s.id)
    });
    if (stations.value[lineValue.value].length > 0) {
        listStationsData.value = stations.value[lineValue.value];
        stationValue.value = listStationsData.value[0];
    }
    else {
        listStationsData.value = [];
        stationValue.value = {
            stationNum: '',
            taskNo: '',
            taskType: '',
            startLocatNo: '',
            endLocatNo: '',
            plc: '',
            wcs: '',
            status: false
        };
    }
    title.value = listStationsData.value[0].text;
};
    .linefix{
        border-bottom: 1px solid rgb(197, 195, 195);
        display: flex;
        align-items: center;
        height: 40px;
        position: relative;
    }
    .lineStatus{
        position: absolute;
        right: 0;
        float: right;
        height: 20px;
        width: 20px;
        border-radius: 20px;
        background-color: #67C23A;
    }
handleQuery();
    .choosefix{
        width: 100%;
        height: auto;
        padding: 10px;
        border-bottom: 1px solid rgb(197, 195, 195);
    }
    .box-card {
        width: 280px;
    }
    .lineValuefix{
        width: 100%;
        height: 500px;
        padding: 10px;
        border-bottom: 1px solid rgb(197, 195, 195);
    }
   .lineButtonfix{
        width: 100%;
        height: 50px;
        display: flex;
        align-items: center;
    }
const handleLineChange = (field: string, value: number) => {
    listStationsData.value = stations.value[value];
    title.value = lineOptions.value.filter(s => s.id == value)[0].text;
    if (listStationsData.value.length > 0)
        stationValue.value = listStationsData.value[0];
};
    .otherValuefix{
        width: 100%;
        height: 220px;
        padding: 10px;
        border-bottom: 1px solid rgb(197, 195, 195);
    }
</script>
    .card-container {
        display: grid;
        grid-template-columns: repeat(4, 1fr);
        gap: 10px;
    }
<style scoped>
.text {
    font-size: 14px;
}
    .other-box-card {
        box-sizing: border-box;
    }
    .otherButtonfix{
        width: 100%;
        height: 50px;
        display: flex;
        align-items: center;
        justify-content: center;
        padding: 0;
    }
    .device-status-0{
        background-color: #67C23A;
    }
    .device-status-1{
        background-color: red;
    }
  </style>
.el-form-item--small {
    margin-bottom: 10px;
}
.el-button {
    background-color: #fff;
    border-color: #fff;
    color: #000000;
}
.linefix {
    border-bottom: 1px solid rgb(197, 195, 195);
    display: flex;
    align-items: center;
    height: 30px;
    position: relative;
}
.lineStatus {
    position: absolute;
    right: 0;
    height: 20px;
    width: 20px;
    border-radius: 50%;
    background-color: #67C23A;
}
.choosefix {
    width: 100%;
    padding: 10px;
    border-bottom: 1px solid rgb(197, 195, 195);
}
.box-card {
    width: 100%;
    max-width: 280px;
    background: linear-gradient(135deg, #66ccff, #3399ff);
    border-radius: 10px;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
    color: #fff;
}
.lineValuefix {
    width: 100%;
    padding: 10px;
    border-bottom: 1px solid rgb(197, 195, 195);
}
.lineButtonfix {
    width: 100%;
    display: flex;
    justify-content: space-between;
    padding: 10px;
}
.otherValuefix {
    width: 100%;
    padding: 10px;
    border-bottom: 1px solid rgb(197, 195, 195);
    display: flex;
    flex-direction: column;
    gap: 10px;
    /* Optional, for spacing between form items */
}
.card-container {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 10px;
}
.other-box-card {
    box-sizing: border-box;
    background: linear-gradient(135deg, #66ccff, #3399ff);
    border-radius: 10px;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
    color: #fff;
    display: flex;
    flex-direction: column;
    height: auto;
    /* Ensure card height adjusts based on content */
}
.otherButtonfix {
    width: 100%;
    display: flex;
    justify-content: center;
    padding: 10px;
}
.device-status-0 {
    background-color: #67C23A;
}
.device-status-1 {
    background-color: red;
}
.linefix span {
    color: #fff;
}
</style>