Admin.NET/WCS.Application/Hub/ITaskLogHub.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Admin.NET/WCS.Application/Hub/TaskLogHub.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Admin.NET/WCS.Application/PLC/PLCJob.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Admin.NET/WCS.Application/PLC/PLCService.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Admin.NET/WCS.Application/PLC/PLCTaskAction.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Web/src/views/wcs/wcsDevice/component/editDialog.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Web/src/views/wcs/wcsTask/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Web/src/views/wcs/wcsTask/signalR.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
Admin.NET/WCS.Application/Hub/ITaskLogHub.cs
New file @@ -0,0 +1,25 @@ namespace WCS.Application; public interface ITaskLogHub { /// <summary> /// 下发任务 /// </summary> /// <param name="context"></param> /// <returns></returns> Task PublicTask(WcsTaskOutput context); /// <summary> /// 下发任务明细 /// </summary> /// <param name="context"></param> /// <returns></returns> Task PublicTaskMonitor(WcsTaskMonitorOutput context); /// <summary> /// 接收消息 /// </summary> /// <param name="context"></param> /// <returns></returns> Task ReceiveMessage(object context); } Admin.NET/WCS.Application/Hub/TaskLogHub.cs
New file @@ -0,0 +1,56 @@ using Furion.InstantMessaging; using Microsoft.AspNetCore.SignalR; namespace WCS.Application; /// <summary> /// 任务日志集线器 /// </summary> [MapHub("/hubs/TaskLog")] public class TaskLogHub : Hub<ITaskLogHub> { private readonly IHubContext<TaskLogHub, ITaskLogHub> _taskLogHubContext; public TaskLogHub(IHubContext<TaskLogHub, ITaskLogHub> taskLogHubContext) { _taskLogHubContext = taskLogHubContext; } /// <summary> /// 连接 /// </summary> /// <returns></returns> public override async Task OnConnectedAsync() { await base.OnConnectedAsync(); } /// <summary> /// 断开 /// </summary> /// <param name="exception"></param> /// <returns></returns> public override async Task OnDisconnectedAsync(Exception exception) { await base.OnDisconnectedAsync(exception); } /// <summary> /// 下发任务 /// </summary> /// <returns></returns> public async Task PublicTask(WcsTaskOutput context) { await _taskLogHubContext.Clients.All.PublicTask(context); } /// <summary> /// 下发任务明细 /// </summary> /// <returns></returns> public async Task PublicTaskMonitor(WcsTaskMonitorOutput context) { await _taskLogHubContext.Clients.All.PublicTaskMonitor(context); } } Admin.NET/WCS.Application/PLC/PLCJob.cs
@@ -1,4 +1,5 @@ using Furion.Schedule; using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.Logging; namespace WCS.Application; Admin.NET/WCS.Application/PLC/PLCService.cs
@@ -1,12 +1,19 @@ using Furion.Logging; using IoTClient; using Microsoft.AspNetCore.SignalR; using System.Data; namespace WCS.Application; public static class PLCService { private static readonly ISqlSugarClient _db = SqlSugarSetup.ITenant.GetConnectionScope(SqlSugarConst.MainConfigId); private static readonly IHubContext<TaskLogHub, ITaskLogHub> _taskLogHubContext; static PLCService() { _taskLogHubContext = App.GetService<IHubContext<TaskLogHub, ITaskLogHub>>(); } public static void OnChangeEvent(object sender, EventArgs e) { @@ -107,12 +114,8 @@ modTaskMonitor.InteractiveMsg = "起始储位为空!"; _db.Insertable(modTaskMonitor).ExecuteCommand(); // 通知任务界面任务已存在更新 请更新界面 //if (TaskAction.refresh) //{ // wSChat.AlarmInformation("1"); //} //下发任务日志 _taskLogHubContext.Clients.All.PublicTaskMonitor(modTaskMonitor.Adapt<WcsTaskMonitorOutput>()); break; } //给PLC写入任务数据 @@ -165,11 +168,8 @@ EndLocat = outStationNum, }; _db.Insertable(modInsertTaskMonitor).ExecuteCommand(); // 通知任务界面任务已存在更新 请更新界面 //if (TaskAction.refresh) //{ // wSChat.AlarmInformation("1"); //} //下发任务日志 _taskLogHubContext.Clients.All.PublicTaskMonitor(modInsertTaskMonitor.Adapt<WcsTaskMonitorOutput>()); //修改led屏信息 //LedDisplay(modDevice.LedIP, "工位:" + modTask.EndLocate, "出库中 " + $"储位地址:{modTask.StartLocate}", "托盘号:" + modTask.PalletNo); } @@ -236,11 +236,8 @@ Status = TaskStatusEnum.Complete }; _db.Insertable(modTaskMonitor).ExecuteCommand(); //通知任务界面任务已存在更新 请更新界面 //if (TaskAction.refresh) //{ // wSChat.AlarmInformation("1"); //} //下发任务日志 _taskLogHubContext.Clients.All.PublicTaskMonitor(modTaskMonitor.Adapt<WcsTaskMonitorOutput>()); } else if (modTask.TaskType.Value == TaskTypeEnum.Out) @@ -277,11 +274,8 @@ Status = TaskStatusEnum.Complete }; _db.Insertable(modTaskMonitor).ExecuteCommand(); //通知任务界面任务已存在更新 请更新界面 //if (TaskAction.refresh) //{ // wSChat.AlarmInformation("1"); //} //下发任务日志 _taskLogHubContext.Clients.All.PublicTaskMonitor(modTaskMonitor.Adapt<WcsTaskMonitorOutput>()); } } break; @@ -344,11 +338,8 @@ Status = TaskStatusEnum.Complete }; _db.Insertable(modTaskMonitor).ExecuteCommand(); // 通知任务界面任务已存在更新 请更新界面 //if (TaskAction.refresh) //{ // wSChat.AlarmInformation("1"); //} //下发任务日志 _taskLogHubContext.Clients.All.PublicTaskMonitor(modTaskMonitor.Adapt<WcsTaskMonitorOutput>()); } else { @@ -427,11 +418,8 @@ }; _db.Insertable(modTaskMonitor).ExecuteCommand(); // 通知任务界面任务已存在更新 请更新界面 //if (TaskAction.refresh) //{ // wSChat.AlarmInformation("1"); //} //下发任务日志 _taskLogHubContext.Clients.All.PublicTaskMonitor(modTaskMonitor.Adapt<WcsTaskMonitorOutput>()); //todo:垛机出库不空跑 } Admin.NET/WCS.Application/PLC/PLCTaskAction.cs
@@ -1,5 +1,5 @@ using Admin.NET.Core.Service; using Furion.Logging; using Furion.Logging; using Microsoft.AspNetCore.SignalR; namespace WCS.Application; public static class PLCTaskAction Web/src/views/wcs/wcsDevice/component/editDialog.vue
@@ -138,6 +138,10 @@ const ruleForm = ref<any>({}); //自行添加其他规则 const rules = ref<FormRules>({ dbNumber: [{ required: true, message: '请输入DB区域!', trigger: 'blur', },], stationNum: [{ required: true, message: '请输入工位号!', trigger: 'blur', },], plcPos: [{ required: true, message: '请输入PLC偏移量!', trigger: 'blur', },], wcsPos: [{ required: true, message: '请输入WCS偏移量!', trigger: 'blur', },], }); // 页面加载时 Web/src/views/wcs/wcsTask/index.vue
@@ -4,8 +4,9 @@ <el-col :span="12" :xs="24" style="display: flex; height: 100%; flex: 1"> <el-card class="full-table" shadow="hover" ::body-style="{ height: 'calc(100% - 51px)' }"> <template #header> <el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"><ele-Collection /></el-icon>任务日志 </template> <el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"><ele-Collection /></el-icon>任务日志 </template> <el-form :model="queryParams" ref="queryForm" labelWidth="90"> <el-row> <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10"> @@ -53,8 +54,8 @@ </el-col> </el-row> </el-form> <el-table :data="tableData" style="width: 100%" v-loading="loading" tooltip-effect="light" row-key="id" @row-click="handleClick" @sort-change="sortChange" border=""> <el-table :data="tableData" style="width: 100%" v-loading="loading" tooltip-effect="light" row-key="id" @row-click="handleClick" @sort-change="sortChange" border=""> <el-table-column type="index" label="序号" width="55" align="center" /> <el-table-column prop="taskNo" label="任务号" show-overflow-tooltip="" /> <el-table-column prop="taskType" width="85" label="任务类型" show-overflow-tooltip=""> @@ -104,8 +105,9 @@ <el-col :span="12" :xs="24" style="display: flex; height: 100%; flex: 1"> <el-card class="full-table" shadow="hover" :body-style="{ height: 'calc(100% - 51px)' }"> <template #header> <el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"><ele-Collection /></el-icon>任务详情 </template> <el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"><ele-Collection /></el-icon>任务详情 </template> <el-form :model="queryParams2" ref="queryForm2" labelWidth="90"> <el-row> <el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="4" class="mb10"> @@ -122,7 +124,8 @@ </el-col> </el-row> </el-form> <el-table :data="tableData2" style="width: 100%" v-loading="loading" tooltip-effect="light" row-key="id" border=""> <el-table :data="tableData2" style="width: 100%" v-loading="loading" tooltip-effect="light" row-key="id" border=""> <el-table-column type="index" label="序号" width="55" align="center" /> <el-table-column prop="taskNo" label="任务号" show-overflow-tooltip="" /> <el-table-column prop="plcId" label="交互工位号" show-overflow-tooltip="" /> @@ -146,22 +149,18 @@ <script lang="ts" setup="" name="wcsTask"> import ModifyRecord from '/@/components/table/modifyRecord.vue'; import { ref } from "vue"; import { onMounted, reactive, ref } from 'vue'; import { ElMessageBox, ElMessage } from "element-plus"; import { auth } from '/@/utils/authFunction'; import { getDictDataItem as di, getDictDataList as dl } from '/@/utils/dict-utils'; import { getDictLabelByVal as dv } from '/@/utils/dict-utils'; import { formatDate } from '/@/utils/formatTime'; import printDialog from '/@/views/system/print/component/hiprint/preview.vue' import editDialog from '/@/views/wcs/wcsTask/component/editDialog.vue' import { pageWcsTask, deleteWcsTask } from '/@/api/wcs/wcsTask'; import { pageWcsMonitorTask } from '/@/api/wcs/wcsTaskMonitor'; import { getAPI } from '/@/utils/axios-utils'; import { SysEnumApi } from '/@/api-services/api'; import commonFunction from '/@/utils/commonFunction'; import { signalR } from './signalR'; const showAdvanceQueryUI = ref(false); const printDialogRef = ref(); @@ -183,7 +182,25 @@ }); const printWcsTaskTitle = ref(""); const editWcsTaskTitle = ref(""); //连接signalR 监听后台任务日志变更 onMounted(async () => { signalR.off('PublicTask'); signalR.on('PublicTask', (data: any) => { console.log(data) if (tableData.value.filter(t => t.id == data.id).length == 0) { tableData.value.unshift(data) } }); signalR.off('PublicTaskMonitor'); signalR.on('PublicTaskMonitor', async (data: any) => { console.log(data); if (queryParams2.value.taskNo == undefined || queryParams2.value.taskNo == data.taskNo) { if (tableData2.value.filter(t => t.id == data.id).length == 0) { tableData2.value.unshift(data) } } }); }); // 改变高级查询的控件显示状态 const changeAdvanceQueryUI = () => { showAdvanceQueryUI.value = !showAdvanceQueryUI.value; @@ -239,8 +256,8 @@ } // 点击表格 const handleClick = (row: any, event: any, column: any) => { queryParams2.value.taskNo = row.taskNo; handleQuery2(); queryParams2.value.taskNo = row.taskNo; handleQuery2(); }; // 删除 const delWcsTask = (row: any) => { Web/src/views/wcs/wcsTask/signalR.ts
New file @@ -0,0 +1,37 @@ import * as SignalR from '@microsoft/signalr'; import { getToken } from '/@/utils/axios-utils'; // 初始化SignalR对象 const connection = new SignalR.HubConnectionBuilder() .configureLogging(SignalR.LogLevel.Information) .withUrl(`${window.__env__.VITE_API_URL}/hubs/TaskLog?token=${getToken()}`, { transport: SignalR.HttpTransportType.WebSockets, skipNegotiation: true }) .withAutomaticReconnect({ nextRetryDelayInMilliseconds: () => { return 5000; // 每5秒重连一次 }, }) .build(); connection.keepAliveIntervalInMilliseconds = 15 * 1000; // 心跳检测15s connection.serverTimeoutInMilliseconds = 30 * 60 * 1000; // 超时时间30m // 启动连接 connection.start().then(() => { console.log('启动连接task'); }); // 断开连接 connection.onclose(async () => { console.log('断开连接task'); }); // 重连中 connection.onreconnecting(() => { console.log('服务器已断线task'); }); // 重连成功 connection.onreconnected(() => { console.log('重连成功task'); }); connection.on('PublicTask', () => {}); export { connection as signalR };