| | |
| | | <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> |
| | |
| | | </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"> |
| | | <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> |