feat: Add real-time IO/interlock updates, HW status display, and history page

- Implement real-time IO value updates via IOValueChanged event
- Add interlock toggle and real-time interlock change events
- Fix ToggleLight to check return value of DIO.SetRoomLight
- Add HW status display in Footer matching WinForms HWState
- Implement GetHWStatus API and 250ms broadcast interval
- Create HistoryPage React component for work history viewing
- Add GetHistoryData API for database queries
- Add date range selection, search, filter, and CSV export
- Add History button in Header navigation
- Add PickerMoveDialog component for manage operations
- Fix DataSet column names (idx, PRNATTACH, PRNVALID, qtymax)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-27 00:14:47 +09:00
parent bb67d04d90
commit 3bd35ad852
19 changed files with 2917 additions and 81 deletions

View File

@@ -334,6 +334,13 @@ namespace Project.WebUI
var response = new { type = "MANAGE_RESULT", data = Newtonsoft.Json.JsonConvert.DeserializeObject(resultJson) };
await Send(socket, Newtonsoft.Json.JsonConvert.SerializeObject(response));
}
else if (type == "CLOSE_MANAGE")
{
var bridge = new MachineBridge(_mainForm);
string resultJson = bridge.CloseManage();
var response = new { type = "CLOSE_MANAGE_RESULT", data = Newtonsoft.Json.JsonConvert.DeserializeObject(resultJson) };
await Send(socket, Newtonsoft.Json.JsonConvert.SerializeObject(response));
}
else if (type == "OPEN_MANUAL")
{
var bridge = new MachineBridge(_mainForm);
@@ -376,6 +383,151 @@ namespace Project.WebUI
var response = new { type = "FOLDER_RESULT", data = Newtonsoft.Json.JsonConvert.DeserializeObject(resultJson) };
await Send(socket, Newtonsoft.Json.JsonConvert.SerializeObject(response));
}
// ===== PICKER MOVE HANDLERS =====
else if (type == "GET_PICKER_STATUS")
{
var bridge = new MachineBridge(_mainForm);
string resultJson = bridge.GetPickerStatus();
var response = new { type = "PICKER_STATUS", data = Newtonsoft.Json.JsonConvert.DeserializeObject(resultJson) };
await Send(socket, Newtonsoft.Json.JsonConvert.SerializeObject(response));
}
else if (type == "PICKER_MOVE_LEFT")
{
var bridge = new MachineBridge(_mainForm);
string resultJson = bridge.PickerMoveLeft();
var response = new { type = "PICKER_RESULT", data = Newtonsoft.Json.JsonConvert.DeserializeObject(resultJson) };
await Send(socket, Newtonsoft.Json.JsonConvert.SerializeObject(response));
}
else if (type == "PICKER_MOVE_LEFT_WAIT")
{
var bridge = new MachineBridge(_mainForm);
string resultJson = bridge.PickerMoveLeftWait();
var response = new { type = "PICKER_RESULT", data = Newtonsoft.Json.JsonConvert.DeserializeObject(resultJson) };
await Send(socket, Newtonsoft.Json.JsonConvert.SerializeObject(response));
}
else if (type == "PICKER_MOVE_CENTER")
{
var bridge = new MachineBridge(_mainForm);
string resultJson = bridge.PickerMoveCenter();
var response = new { type = "PICKER_RESULT", data = Newtonsoft.Json.JsonConvert.DeserializeObject(resultJson) };
await Send(socket, Newtonsoft.Json.JsonConvert.SerializeObject(response));
}
else if (type == "PICKER_MOVE_RIGHT_WAIT")
{
var bridge = new MachineBridge(_mainForm);
string resultJson = bridge.PickerMoveRightWait();
var response = new { type = "PICKER_RESULT", data = Newtonsoft.Json.JsonConvert.DeserializeObject(resultJson) };
await Send(socket, Newtonsoft.Json.JsonConvert.SerializeObject(response));
}
else if (type == "PICKER_MOVE_RIGHT")
{
var bridge = new MachineBridge(_mainForm);
string resultJson = bridge.PickerMoveRight();
var response = new { type = "PICKER_RESULT", data = Newtonsoft.Json.JsonConvert.DeserializeObject(resultJson) };
await Send(socket, Newtonsoft.Json.JsonConvert.SerializeObject(response));
}
else if (type == "PICKER_JOG_START")
{
var bridge = new MachineBridge(_mainForm);
string direction = json["direction"]?.ToString() ?? "";
string resultJson = bridge.PickerJogStart(direction);
var response = new { type = "PICKER_JOG_RESULT", data = Newtonsoft.Json.JsonConvert.DeserializeObject(resultJson) };
await Send(socket, Newtonsoft.Json.JsonConvert.SerializeObject(response));
}
else if (type == "PICKER_JOG_STOP")
{
var bridge = new MachineBridge(_mainForm);
string resultJson = bridge.PickerJogStop();
var response = new { type = "PICKER_JOG_RESULT", data = Newtonsoft.Json.JsonConvert.DeserializeObject(resultJson) };
await Send(socket, Newtonsoft.Json.JsonConvert.SerializeObject(response));
}
else if (type == "PICKER_STOP")
{
var bridge = new MachineBridge(_mainForm);
string resultJson = bridge.PickerStop();
var response = new { type = "PICKER_RESULT", data = Newtonsoft.Json.JsonConvert.DeserializeObject(resultJson) };
await Send(socket, Newtonsoft.Json.JsonConvert.SerializeObject(response));
}
else if (type == "CANCEL_VISION_VALIDATION")
{
var bridge = new MachineBridge(_mainForm);
string side = json["side"]?.ToString() ?? "left";
string resultJson = bridge.CancelVisionValidation(side);
var response = new { type = "VISION_CANCEL_RESULT", data = Newtonsoft.Json.JsonConvert.DeserializeObject(resultJson) };
await Send(socket, Newtonsoft.Json.JsonConvert.SerializeObject(response));
}
else if (type == "PICKER_MANAGE_POSITION")
{
var bridge = new MachineBridge(_mainForm);
string side = json["side"]?.ToString() ?? "left";
string resultJson = bridge.PickerManagePosition(side);
var response = new { type = "PICKER_MANAGE_RESULT", data = Newtonsoft.Json.JsonConvert.DeserializeObject(resultJson) };
await Send(socket, Newtonsoft.Json.JsonConvert.SerializeObject(response));
}
else if (type == "PICKER_MANAGE_RETURN")
{
var bridge = new MachineBridge(_mainForm);
string resultJson = bridge.PickerManageReturn();
var response = new { type = "PICKER_MANAGE_RESULT", data = Newtonsoft.Json.JsonConvert.DeserializeObject(resultJson) };
await Send(socket, Newtonsoft.Json.JsonConvert.SerializeObject(response));
}
else if (type == "PICKER_Z_HOME")
{
var bridge = new MachineBridge(_mainForm);
string resultJson = bridge.PickerZHome();
var response = new { type = "PICKER_RESULT", data = Newtonsoft.Json.JsonConvert.DeserializeObject(resultJson) };
await Send(socket, Newtonsoft.Json.JsonConvert.SerializeObject(response));
}
else if (type == "PICKER_Z_ZERO")
{
var bridge = new MachineBridge(_mainForm);
string resultJson = bridge.PickerZZero();
var response = new { type = "PICKER_RESULT", data = Newtonsoft.Json.JsonConvert.DeserializeObject(resultJson) };
await Send(socket, Newtonsoft.Json.JsonConvert.SerializeObject(response));
}
else if (type == "PICKER_TEST_PRINT")
{
var bridge = new MachineBridge(_mainForm);
string side = json["side"]?.ToString() ?? "left";
string resultJson = bridge.PickerTestPrint(side);
var response = new { type = "PICKER_PRINT_RESULT", data = Newtonsoft.Json.JsonConvert.DeserializeObject(resultJson) };
await Send(socket, Newtonsoft.Json.JsonConvert.SerializeObject(response));
}
else if (type == "CAN_CLOSE_MANAGE")
{
var bridge = new MachineBridge(_mainForm);
string resultJson = bridge.CanCloseManage();
var response = new { type = "CAN_CLOSE_MANAGE_RESULT", data = Newtonsoft.Json.JsonConvert.DeserializeObject(resultJson) };
await Send(socket, Newtonsoft.Json.JsonConvert.SerializeObject(response));
}
// ===== HISTORY DATA =====
else if (type == "GET_HISTORY_DATA")
{
var bridge = new MachineBridge(_mainForm);
string startDate = json["startDate"]?.ToString() ?? DateTime.Now.ToShortDateString();
string endDate = json["endDate"]?.ToString() ?? DateTime.Now.ToShortDateString();
string search = json["search"]?.ToString() ?? "";
string resultJson = bridge.GetHistoryData(startDate, endDate, search);
var response = new { type = "HISTORY_DATA_RESULT", data = Newtonsoft.Json.JsonConvert.DeserializeObject(resultJson) };
await Send(socket, Newtonsoft.Json.JsonConvert.SerializeObject(response));
}
// ===== INTERLOCK HANDLERS =====
else if (type == "TOGGLE_INTERLOCK")
{
var bridge = new MachineBridge(_mainForm);
int axisIndex = json["axisIndex"]?.ToObject<int>() ?? 0;
int lockIndex = json["lockIndex"]?.ToObject<int>() ?? 0;
string resultJson = bridge.ToggleInterlock(axisIndex, lockIndex);
var response = new { type = "TOGGLE_INTERLOCK_RESULT", data = Newtonsoft.Json.JsonConvert.DeserializeObject(resultJson) };
await Send(socket, Newtonsoft.Json.JsonConvert.SerializeObject(response));
}
else if (type == "GET_INTERLOCK_LIST")
{
var bridge = new MachineBridge(_mainForm);
string resultJson = bridge.GetInterlockList();
var response = new { type = "INTERLOCK_LIST_RESULT", data = Newtonsoft.Json.JsonConvert.DeserializeObject(resultJson) };
await Send(socket, Newtonsoft.Json.JsonConvert.SerializeObject(response));
}
}
catch (Exception ex)
{