1225 lines
62 KiB
C#
1225 lines
62 KiB
C#
using System;
|
|
using System.Collections.Concurrent;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Net;
|
|
using System.Net.WebSockets;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Newtonsoft.Json;
|
|
|
|
namespace Project.Web
|
|
{
|
|
/// <summary>
|
|
/// GroupWare WebSocket 서버
|
|
/// npm run dev 환경에서 핫 리로드 개발을 위한 WebSocket 통신 지원
|
|
/// </summary>
|
|
public class WebSocketServer
|
|
{
|
|
private HttpListener _httpListener;
|
|
private List<WebSocket> _clients = new List<WebSocket>();
|
|
private ConcurrentDictionary<WebSocket, SemaphoreSlim> _socketLocks = new ConcurrentDictionary<WebSocket, SemaphoreSlim>();
|
|
private MachineBridge _bridge;
|
|
private bool _isRunning = false;
|
|
|
|
public WebSocketServer(string url, MachineBridge bridge)
|
|
{
|
|
_bridge = bridge;
|
|
_httpListener = new HttpListener();
|
|
_httpListener.Prefixes.Add(url);
|
|
}
|
|
|
|
public void Start()
|
|
{
|
|
if (_isRunning) return;
|
|
|
|
try
|
|
{
|
|
_httpListener.Start();
|
|
_isRunning = true;
|
|
Console.WriteLine($"[WS] GroupWare WebSocket Server Started");
|
|
Task.Run(AcceptConnections);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"[WS] Start Error: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
public void Stop()
|
|
{
|
|
_isRunning = false;
|
|
try
|
|
{
|
|
_httpListener.Stop();
|
|
_httpListener.Close();
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
private async Task AcceptConnections()
|
|
{
|
|
while (_httpListener.IsListening && _isRunning)
|
|
{
|
|
try
|
|
{
|
|
var context = await _httpListener.GetContextAsync();
|
|
if (context.Request.IsWebSocketRequest)
|
|
{
|
|
ProcessRequest(context);
|
|
}
|
|
else
|
|
{
|
|
context.Response.StatusCode = 400;
|
|
context.Response.Close();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
if (_isRunning)
|
|
Console.WriteLine($"[WS] Accept Error: {ex.Message}");
|
|
}
|
|
}
|
|
}
|
|
|
|
private async void ProcessRequest(HttpListenerContext context)
|
|
{
|
|
WebSocketContext wsContext = null;
|
|
try
|
|
{
|
|
wsContext = await context.AcceptWebSocketAsync(subProtocol: null);
|
|
WebSocket socket = wsContext.WebSocket;
|
|
_socketLocks.TryAdd(socket, new SemaphoreSlim(1, 1));
|
|
|
|
lock (_clients) { _clients.Add(socket); }
|
|
Console.WriteLine("[WS] Client Connected");
|
|
|
|
await ReceiveLoop(socket);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"[WS] Process Error: {ex.Message}");
|
|
}
|
|
finally
|
|
{
|
|
if (wsContext != null)
|
|
{
|
|
WebSocket socket = wsContext.WebSocket;
|
|
lock (_clients) { _clients.Remove(socket); }
|
|
|
|
if (_socketLocks.TryRemove(socket, out var semaphore))
|
|
{
|
|
semaphore.Dispose();
|
|
}
|
|
socket.Dispose();
|
|
}
|
|
}
|
|
}
|
|
|
|
private async Task ReceiveLoop(WebSocket socket)
|
|
{
|
|
var buffer = new byte[1024 * 4];
|
|
while (socket.State == WebSocketState.Open && _isRunning)
|
|
{
|
|
try
|
|
{
|
|
var result = await socket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
|
|
if (result.MessageType == WebSocketMessageType.Close)
|
|
{
|
|
await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", CancellationToken.None);
|
|
}
|
|
else if (result.MessageType == WebSocketMessageType.Text)
|
|
{
|
|
string msg = Encoding.UTF8.GetString(buffer, 0, result.Count);
|
|
await HandleMessage(msg, socket);
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private async Task HandleMessage(string msg, WebSocket socket)
|
|
{
|
|
try
|
|
{
|
|
dynamic json = JsonConvert.DeserializeObject(msg);
|
|
string type = json.type;
|
|
|
|
Console.WriteLine($"[WS] Message: {type}");
|
|
|
|
switch (type)
|
|
{
|
|
// ===== Todo API =====
|
|
case "GET_TODOS":
|
|
{
|
|
string result = _bridge.Todo_GetTodos();
|
|
var response = new { type = "TODOS_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "GET_TODO":
|
|
{
|
|
int id = json.id;
|
|
string result = _bridge.GetTodo(id);
|
|
var response = new { type = "TODO_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "CREATE_TODO":
|
|
{
|
|
string title = json.title ?? "";
|
|
string remark = json.remark ?? "";
|
|
string expire = json.expire;
|
|
int seqno = json.seqno ?? 0;
|
|
bool flag = json.flag ?? false;
|
|
string request = json.request;
|
|
string status = json.status ?? "0";
|
|
|
|
string result = _bridge.CreateTodo(title, remark, expire, seqno, flag, request, status);
|
|
var response = new { type = "TODO_CREATED", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "UPDATE_TODO":
|
|
{
|
|
int idx = json.idx;
|
|
string title = json.title ?? "";
|
|
string remark = json.remark ?? "";
|
|
string expire = json.expire;
|
|
int seqno = json.seqno ?? 0;
|
|
bool flag = json.flag ?? false;
|
|
string request = json.request;
|
|
string status = json.status ?? "0";
|
|
|
|
string result = _bridge.Todo_UpdateTodo(idx, title, remark, expire, seqno, flag, request, status);
|
|
var response = new { type = "TODO_UPDATED", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "DELETE_TODO":
|
|
{
|
|
int id = json.id;
|
|
string result = _bridge.Todo_DeleteTodo(id);
|
|
var response = new { type = "TODO_DELETED", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "GET_URGENT_TODOS":
|
|
{
|
|
string result = _bridge.GetUrgentTodos();
|
|
var response = new { type = "URGENT_TODOS_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
// ===== Dashboard API =====
|
|
case "GET_PURCHASE_WAIT_COUNT":
|
|
{
|
|
string result = _bridge.GetPurchaseWaitCount();
|
|
var response = new { type = "PURCHASE_WAIT_COUNT_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "GET_TODAY_COUNT_H":
|
|
{
|
|
string result = _bridge.TodayCountH();
|
|
var response = new { type = "TODAY_COUNT_H_DATA", count = int.Parse(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "GET_HOLY_USER":
|
|
{
|
|
string result = _bridge.GetHolyUser();
|
|
var response = new { type = "HOLY_USER_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "GET_HOLY_REQUEST_USER":
|
|
{
|
|
string result = _bridge.GetHolyRequestUser();
|
|
var response = new { type = "HOLY_REQUEST_USER_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "GET_PURCHASE_NR_LIST":
|
|
{
|
|
string result = _bridge.GetPurchaseNRList();
|
|
var response = new { type = "PURCHASE_NR_LIST_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "GET_PURCHASE_CR_LIST":
|
|
{
|
|
string result = _bridge.GetPurchaseCRList();
|
|
var response = new { type = "PURCHASE_CR_LIST_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "GET_HOLYDAY_REQUEST_COUNT":
|
|
{
|
|
string result = _bridge.GetHolydayRequestCount();
|
|
var response = new { type = "HOLYDAY_REQUEST_COUNT_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "GET_CURRENT_USER_COUNT":
|
|
{
|
|
string result = _bridge.GetCurrentUserCount();
|
|
var response = new { type = "CURRENT_USER_COUNT_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
// ===== Login API =====
|
|
case "CHECK_LOGIN_STATUS":
|
|
{
|
|
string result = _bridge.CheckLoginStatus();
|
|
var response = new { type = "LOGIN_STATUS_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "LOGIN":
|
|
{
|
|
string gcode = json.gcode ?? "";
|
|
string id = json.id ?? "";
|
|
string password = json.password ?? "";
|
|
bool rememberMe = json.rememberMe ?? false;
|
|
string result = _bridge.Login(gcode, id, password, rememberMe);
|
|
var response = new { type = "LOGIN_RESULT", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "LOGOUT":
|
|
{
|
|
string result = _bridge.Logout();
|
|
var response = new { type = "LOGOUT_RESULT", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "GET_USER_GROUPS":
|
|
{
|
|
string result = _bridge.GetUserGroups();
|
|
var response = new { type = "USER_GROUPS_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "GET_PREVIOUS_LOGIN_INFO":
|
|
{
|
|
string result = _bridge.GetPreviousLoginInfo();
|
|
var response = new { type = "PREVIOUS_LOGIN_INFO_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
// ===== User API =====
|
|
case "GET_CURRENT_USER_INFO":
|
|
{
|
|
string result = _bridge.GetCurrentUserInfo();
|
|
var response = new { type = "CURRENT_USER_INFO_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "GET_USER_INFO_BY_ID":
|
|
{
|
|
string userId = json.userId ?? "";
|
|
string result = _bridge.GetUserInfoById(userId);
|
|
var response = new { type = "USER_INFO_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "SAVE_USER_INFO":
|
|
{
|
|
string userData = JsonConvert.SerializeObject(json.userData);
|
|
string result = _bridge.SaveUserInfo(userData);
|
|
var response = new { type = "USER_INFO_SAVED", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "CHANGE_PASSWORD":
|
|
{
|
|
string oldPassword = json.oldPassword ?? "";
|
|
string newPassword = json.newPassword ?? "";
|
|
string result = _bridge.ChangePassword(oldPassword, newPassword);
|
|
var response = new { type = "PASSWORD_CHANGED", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
// ===== Common Code API =====
|
|
case "COMMON_GET_GROUPS":
|
|
{
|
|
string result = _bridge.Common_GetGroups();
|
|
var response = new { type = "COMMON_GROUPS_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "COMMON_GET_LIST":
|
|
{
|
|
string grp = json.grp ?? "99";
|
|
string result = _bridge.Common_GetList(grp);
|
|
var response = new { type = "COMMON_LIST_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "COMMON_SAVE":
|
|
{
|
|
int idx = json.idx ?? 0;
|
|
string grp = json.grp ?? "";
|
|
string code = json.code ?? "";
|
|
string svalue = json.svalue ?? "";
|
|
int ivalue = json.ivalue ?? 0;
|
|
float fvalue = json.fvalue ?? 0f;
|
|
string svalue2 = json.svalue2 ?? "";
|
|
string memo = json.memo ?? "";
|
|
string result = _bridge.Common_Save(idx, grp, code, svalue, ivalue, fvalue, svalue2, memo);
|
|
var response = new { type = "COMMON_SAVED", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "COMMON_DELETE":
|
|
{
|
|
int idx = json.idx ?? 0;
|
|
string result = _bridge.Common_Delete(idx);
|
|
var response = new { type = "COMMON_DELETED", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "FAVORITE_GET_LIST":
|
|
{
|
|
string result = _bridge.Favorite_GetList();
|
|
var response = new { type = "FAVORITE_LIST_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
// ===== Items API =====
|
|
case "ITEMS_GET_CATEGORIES":
|
|
{
|
|
string result = _bridge.Items_GetCategories();
|
|
var response = new { type = "ITEMS_CATEGORIES_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "ITEMS_GET_LIST":
|
|
{
|
|
string category = json.category ?? "";
|
|
string searchKey = json.searchKey ?? "";
|
|
string result = _bridge.Items_GetList(category, searchKey);
|
|
var response = new { type = "ITEMS_LIST_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "ITEMS_SAVE":
|
|
{
|
|
int idx = json.idx ?? 0;
|
|
string sid = json.sid ?? "";
|
|
string cate = json.cate ?? "";
|
|
string name = json.name ?? "";
|
|
string model = json.model ?? "";
|
|
string scale = json.scale ?? "";
|
|
string unit = json.unit ?? "";
|
|
decimal price = json.price ?? 0m;
|
|
string supply = json.supply ?? "";
|
|
string manu = json.manu ?? "";
|
|
string storage = json.storage ?? "";
|
|
bool disable = json.disable ?? false;
|
|
string memo = json.memo ?? "";
|
|
string result = _bridge.Items_Save(idx, sid, cate, name, model, scale, unit, price, supply, manu, storage, disable, memo);
|
|
var response = new { type = "ITEMS_SAVED", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "ITEMS_DELETE":
|
|
{
|
|
int idx = json.idx ?? 0;
|
|
string result = _bridge.Items_Delete(idx);
|
|
var response = new { type = "ITEMS_DELETED", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "ITEMS_GET_IMAGE":
|
|
{
|
|
int idx = json.idx ?? 0;
|
|
string result = _bridge.Items_GetImage(idx);
|
|
var response = new { type = "ITEMS_IMAGE_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "ITEMS_SAVE_IMAGE":
|
|
{
|
|
int idx = json.idx ?? 0;
|
|
string base64Image = json.base64Image ?? "";
|
|
string result = _bridge.Items_SaveImage(idx, base64Image);
|
|
var response = new { type = "ITEMS_IMAGE_SAVED", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "ITEMS_DELETE_IMAGE":
|
|
{
|
|
int idx = json.idx ?? 0;
|
|
string result = _bridge.Items_DeleteImage(idx);
|
|
var response = new { type = "ITEMS_IMAGE_DELETED", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "ITEMS_GET_DETAIL":
|
|
{
|
|
int idx = json.idx ?? 0;
|
|
string result = _bridge.Items_GetDetail(idx);
|
|
var response = new { type = "ITEMS_DETAIL_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "ITEMS_GET_SUPPLIER_STAFF":
|
|
{
|
|
int supplyIdx = json.supplyIdx ?? 0;
|
|
string result = _bridge.Items_GetSupplierStaff(supplyIdx);
|
|
var response = new { type = "ITEMS_SUPPLIER_STAFF_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "ITEMS_GET_INCOMING_HISTORY":
|
|
{
|
|
int itemIdx = json.itemIdx ?? 0;
|
|
string result = _bridge.Items_GetIncomingHistory(itemIdx);
|
|
var response = new { type = "ITEMS_INCOMING_HISTORY_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "ITEMS_GET_ORDER_HISTORY":
|
|
{
|
|
int itemIdx = json.itemIdx ?? 0;
|
|
string result = _bridge.Items_GetOrderHistory(itemIdx);
|
|
var response = new { type = "ITEMS_ORDER_HISTORY_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
// ===== UserList API =====
|
|
case "USERLIST_GET_CURRENT_LEVEL":
|
|
{
|
|
string result = _bridge.UserList_GetCurrentLevel();
|
|
var response = new { type = "USERLIST_CURRENT_LEVEL_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "USERLIST_GET_DEPTS":
|
|
{
|
|
string result = _bridge.UserList_GetDepts();
|
|
var response = new { type = "USERLIST_DEPTS_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "USERLIST_GET_LIST":
|
|
{
|
|
string process = json.process ?? "%";
|
|
string result = _bridge.UserList_GetList(process);
|
|
var response = new { type = "USERLIST_LIST_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "USERLIST_GET_USER":
|
|
{
|
|
string userId = json.userId ?? "";
|
|
string result = _bridge.UserList_GetUser(userId);
|
|
var response = new { type = "USERLIST_USER_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "USERLIST_SAVE_GROUP_USER":
|
|
{
|
|
string userId = json.userId ?? "";
|
|
string dept = json.dept ?? "";
|
|
int level = json.level ?? 1;
|
|
bool useUserState = json.useUserState ?? false;
|
|
bool useJobReport = json.useJobReport ?? false;
|
|
bool exceptHoly = json.exceptHoly ?? false;
|
|
string result = _bridge.UserList_SaveGroupUser(userId, dept, level, useUserState, useJobReport, exceptHoly);
|
|
var response = new { type = "USERLIST_SAVED", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "USERLIST_SAVE_USER_FULL":
|
|
{
|
|
string userData = JsonConvert.SerializeObject(json.userData);
|
|
string result = _bridge.UserList_SaveUserFull(userData);
|
|
var response = new { type = "USERLIST_USER_FULL_SAVED", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "USERLIST_DELETE_GROUP_USER":
|
|
{
|
|
string userId = json.userId ?? "";
|
|
string result = _bridge.UserList_DeleteGroupUser(userId);
|
|
var response = new { type = "USERLIST_DELETED", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
// ===== JobReport API (JobReport 뷰/테이블) =====
|
|
case "JOBREPORT_GET_LIST":
|
|
{
|
|
string sd = json.sd ?? "";
|
|
string ed = json.ed ?? "";
|
|
string uid = json.uid ?? "";
|
|
string cate = json.cate ?? ""; // 사용안함 (호환성)
|
|
string searchKey = json.searchKey ?? "";
|
|
Console.WriteLine($"[WS] JOBREPORT_GET_LIST: sd={sd}, ed={ed}, uid={uid}, searchKey={searchKey}");
|
|
string result = _bridge.Jobreport_GetList(sd, ed, uid, cate, searchKey);
|
|
var response = new { type = "JOBREPORT_LIST_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "JOBREPORT_GET_USERS":
|
|
{
|
|
string result = _bridge.Jobreport_GetUsers();
|
|
var response = new { type = "JOBREPORT_USERS_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "JOBREPORT_GET_DETAIL":
|
|
{
|
|
int idx = json.idx ?? 0;
|
|
string result = _bridge.Jobreport_GetDetail(idx);
|
|
var response = new { type = "JOBREPORT_DETAIL_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "JOBREPORT_ADD":
|
|
{
|
|
string pdate = json.pdate ?? "";
|
|
string projectName = json.projectName ?? "";
|
|
int pidx = json.pidx ?? -1;
|
|
string requestpart = json.requestpart ?? "";
|
|
string package = json.package ?? "";
|
|
string jobType = json.jobType ?? ""; // type -> jobType (WebSocket type 필드 충돌 방지)
|
|
string process = json.process ?? "";
|
|
string status = json.status ?? "진행 완료";
|
|
string description = json.description ?? "";
|
|
double hrs = json.hrs ?? 0.0;
|
|
double ot = json.ot ?? 0.0;
|
|
string jobgrp = json.jobgrp ?? "";
|
|
string tag = json.tag ?? "";
|
|
string otStart = json.otStart ?? "00:00";
|
|
string otEnd = json.otEnd ?? "00:00";
|
|
string result = _bridge.Jobreport_Add(pdate, projectName, pidx, requestpart, package, jobType, process, status, description, hrs, ot, jobgrp, tag, otStart, otEnd);
|
|
var response = new { type = "JOBREPORT_ADDED", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "JOBREPORT_EDIT":
|
|
{
|
|
int idx = json.idx ?? 0;
|
|
string pdate = json.pdate ?? "";
|
|
string projectName = json.projectName ?? "";
|
|
int pidx = json.pidx ?? -1;
|
|
string requestpart = json.requestpart ?? "";
|
|
string package = json.package ?? "";
|
|
string jobType = json.jobType ?? ""; // type -> jobType (WebSocket type 필드 충돌 방지)
|
|
string process = json.process ?? "";
|
|
string status = json.status ?? "";
|
|
string description = json.description ?? "";
|
|
double hrs = json.hrs ?? 0.0;
|
|
double ot = json.ot ?? 0.0;
|
|
string jobgrp = json.jobgrp ?? "";
|
|
string tag = json.tag ?? "";
|
|
string otStart = json.otStart ?? "00:00";
|
|
string otEnd = json.otEnd ?? "00:00";
|
|
string result = _bridge.Jobreport_Edit(idx, pdate, projectName, pidx, requestpart, package, jobType, process, status, description, hrs, ot, jobgrp, tag, otStart, otEnd);
|
|
var response = new { type = "JOBREPORT_EDITED", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "JOBREPORT_DELETE":
|
|
{
|
|
int idx = json.idx ?? 0;
|
|
string result = _bridge.Jobreport_Delete(idx);
|
|
var response = new { type = "JOBREPORT_DELETED", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "JOBREPORT_GET_PERMISSION":
|
|
{
|
|
string targetUserId = json.targetUserId ?? "";
|
|
string result = _bridge.Jobreport_GetPermission(targetUserId);
|
|
var response = new { type = "JOBREPORT_PERMISSION", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "JOBREPORT_GET_JOBTYPES":
|
|
{
|
|
string process = json.process ?? "";
|
|
string result = _bridge.Jobreport_GetJobTypes(process);
|
|
var response = new { type = "JOBREPORT_JOBTYPES", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "GET_APP_VERSION":
|
|
{
|
|
string result = _bridge.GetAppVersion();
|
|
var response = new { type = "APP_VERSION", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
// ===== Kuntae API =====
|
|
case "GET_KUNTAE_LIST":
|
|
{
|
|
string sd = json.sd ?? "";
|
|
string ed = json.ed ?? "";
|
|
string result = _bridge.Kuntae_GetList(sd, ed);
|
|
var response = new { type = "KUNTAE_LIST_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "DELETE_KUNTAE":
|
|
{
|
|
int id = json.id ?? 0;
|
|
string result = _bridge.Kuntae_Delete(id);
|
|
var response = new { type = "KUNTAE_DELETED", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
// ===== Holyday (근태) API =====
|
|
case "HOLYDAY_GET_LIST":
|
|
{
|
|
string sd = json.sd ?? "";
|
|
string ed = json.ed ?? "";
|
|
string uid = json.uid ?? "%";
|
|
string result = _bridge.Holyday_GetList(sd, ed, uid);
|
|
var response = new { type = "HOLYDAY_LIST_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "HOLYDAY_GET_DETAIL":
|
|
{
|
|
int idx = json.idx ?? 0;
|
|
string result = _bridge.Holyday_GetDetail(idx);
|
|
var response = new { type = "HOLYDAY_DETAIL_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "HOLYDAY_ADD":
|
|
{
|
|
string cate = json.cate ?? "";
|
|
string sdate = json.sdate ?? "";
|
|
string edate = json.edate ?? "";
|
|
double term = json.term ?? 0.0;
|
|
double crtime = json.crtime ?? 0.0;
|
|
double termDr = json.termDr ?? 0.0;
|
|
double drTime = json.drTime ?? 0.0;
|
|
string contents = json.contents ?? "";
|
|
string uid = json.uid ?? "";
|
|
string result = _bridge.Holyday_Add(cate, sdate, edate, term, crtime, termDr, drTime, contents, uid);
|
|
var response = new { type = "HOLYDAY_ADDED", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "HOLYDAY_EDIT":
|
|
{
|
|
int idx = json.idx ?? 0;
|
|
string cate = json.cate ?? "";
|
|
string sdate = json.sdate ?? "";
|
|
string edate = json.edate ?? "";
|
|
double term = json.term ?? 0.0;
|
|
double crtime = json.crtime ?? 0.0;
|
|
double termDr = json.termDr ?? 0.0;
|
|
double drTime = json.drTime ?? 0.0;
|
|
string contents = json.contents ?? "";
|
|
string result = _bridge.Holyday_Edit(idx, cate, sdate, edate, term, crtime, termDr, drTime, contents);
|
|
var response = new { type = "HOLYDAY_EDITED", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "HOLYDAY_DELETE":
|
|
{
|
|
int idx = json.idx ?? 0;
|
|
string result = _bridge.Holyday_Delete(idx);
|
|
var response = new { type = "HOLYDAY_DELETED", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "HOLYDAY_GET_USERLIST":
|
|
{
|
|
string sd = json.sd ?? "";
|
|
string ed = json.ed ?? "";
|
|
string result = _bridge.Holyday_GetUserList(sd, ed);
|
|
var response = new { type = "HOLYDAY_USERLIST_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "HOLYDAY_GET_PERMISSION":
|
|
{
|
|
string result = _bridge.Holyday_GetPermission();
|
|
var response = new { type = "HOLYDAY_PERMISSION_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "HOLYDAY_GET_BALANCE":
|
|
{
|
|
string year = json.year ?? "";
|
|
string uid = json.uid ?? "";
|
|
string result = _bridge.Holyday_GetBalance(year, uid);
|
|
var response = new { type = "HOLYDAY_BALANCE_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
|
|
// ===== Holiday API (월별근무표) =====
|
|
case "HOLIDAY_GET_LIST":
|
|
{
|
|
string month = json.month ?? "";
|
|
string result = _bridge.Holiday_GetList(month);
|
|
var response = new { type = "HOLIDAY_LIST_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "HOLIDAY_SAVE":
|
|
{
|
|
string month = json.month ?? "";
|
|
string holidaysJson = JsonConvert.SerializeObject(json.holidays);
|
|
string result = _bridge.Holiday_Save(month, holidaysJson);
|
|
var response = new { type = "HOLIDAY_SAVED", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "HOLIDAY_INITIALIZE":
|
|
{
|
|
string month = json.month ?? "";
|
|
string result = _bridge.Holiday_Initialize(month);
|
|
var response = new { type = "HOLIDAY_INITIALIZED", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
// ===== MailForm API (메일양식) =====
|
|
case "MAILFORM_GET_LIST":
|
|
{
|
|
string result = _bridge.MailForm_GetList();
|
|
var response = new { type = "MAILFORM_LIST_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "MAILFORM_GET_DETAIL":
|
|
{
|
|
int idx = json.idx ?? 0;
|
|
string result = _bridge.MailForm_GetDetail(idx);
|
|
var response = new { type = "MAILFORM_DETAIL_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "MAILFORM_ADD":
|
|
{
|
|
string cate = json.cate ?? "";
|
|
string title = json.title ?? "";
|
|
string tolist = json.tolist ?? "";
|
|
string bcc = json.bcc ?? "";
|
|
string cc = json.cc ?? "";
|
|
string subject = json.subject ?? "";
|
|
string tail = json.tail ?? "";
|
|
string body = json.body ?? "";
|
|
bool selfTo = json.selfTo ?? false;
|
|
bool selfCC = json.selfCC ?? false;
|
|
bool selfBCC = json.selfBCC ?? false;
|
|
string exceptmail = json.exceptmail ?? "";
|
|
string exceptmailcc = json.exceptmailcc ?? "";
|
|
string result = _bridge.MailForm_Add(cate, title, tolist, bcc, cc, subject, tail, body, selfTo, selfCC, selfBCC, exceptmail, exceptmailcc);
|
|
var response = new { type = "MAILFORM_ADDED", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "MAILFORM_EDIT":
|
|
{
|
|
int idx = json.idx ?? 0;
|
|
string cate = json.cate ?? "";
|
|
string title = json.title ?? "";
|
|
string tolist = json.tolist ?? "";
|
|
string bcc = json.bcc ?? "";
|
|
string cc = json.cc ?? "";
|
|
string subject = json.subject ?? "";
|
|
string tail = json.tail ?? "";
|
|
string body = json.body ?? "";
|
|
bool selfTo = json.selfTo ?? false;
|
|
bool selfCC = json.selfCC ?? false;
|
|
bool selfBCC = json.selfBCC ?? false;
|
|
string exceptmail = json.exceptmail ?? "";
|
|
string exceptmailcc = json.exceptmailcc ?? "";
|
|
string result = _bridge.MailForm_Edit(idx, cate, title, tolist, bcc, cc, subject, tail, body, selfTo, selfCC, selfBCC, exceptmail, exceptmailcc);
|
|
var response = new { type = "MAILFORM_EDITED", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "MAILFORM_DELETE":
|
|
{
|
|
int idx = json.idx ?? 0;
|
|
string result = _bridge.MailForm_Delete(idx);
|
|
var response = new { type = "MAILFORM_DELETED", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
// ===== UserGroup API (그룹정보/권한설정) =====
|
|
case "USERGROUP_GET_LIST":
|
|
{
|
|
string result = _bridge.UserGroup_GetList();
|
|
var response = new { type = "USERGROUP_LIST_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "USERGROUP_ADD":
|
|
{
|
|
string dept = json.dept ?? "";
|
|
string path_kj = json.path_kj ?? "";
|
|
int permission = json.permission ?? 1;
|
|
bool advpurchase = json.advpurchase ?? false;
|
|
bool advkisul = json.advkisul ?? false;
|
|
string managerinfo = json.managerinfo ?? "";
|
|
string devinfo = json.devinfo ?? "";
|
|
bool usemail = json.usemail ?? false;
|
|
string result = _bridge.UserGroup_Add(dept, path_kj, permission, advpurchase, advkisul, managerinfo, devinfo, usemail);
|
|
var response = new { type = "USERGROUP_ADDED", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "USERGROUP_EDIT":
|
|
{
|
|
string originalDept = json.originalDept ?? "";
|
|
string dept = json.dept ?? "";
|
|
string path_kj = json.path_kj ?? "";
|
|
int permission = json.permission ?? 1;
|
|
bool advpurchase = json.advpurchase ?? false;
|
|
bool advkisul = json.advkisul ?? false;
|
|
string managerinfo = json.managerinfo ?? "";
|
|
string devinfo = json.devinfo ?? "";
|
|
bool usemail = json.usemail ?? false;
|
|
string result = _bridge.UserGroup_Edit(originalDept, dept, path_kj, permission, advpurchase, advkisul, managerinfo, devinfo, usemail);
|
|
var response = new { type = "USERGROUP_EDITED", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "USERGROUP_DELETE":
|
|
{
|
|
string dept = json.dept ?? "";
|
|
string result = _bridge.UserGroup_Delete(dept);
|
|
var response = new { type = "USERGROUP_DELETED", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "USERGROUP_GET_PERMISSION_INFO":
|
|
{
|
|
string result = _bridge.UserGroup_GetPermissionInfo();
|
|
var response = new { type = "USERGROUP_PERMISSION_INFO", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
// ===== UserAuth API (사용자 권한) =====
|
|
case "USERAUTH_CAN_ACCESS":
|
|
{
|
|
string result = _bridge.UserAuth_CanAccess();
|
|
var response = new { type = "USERAUTH_CAN_ACCESS_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "USERAUTH_GET_LIST":
|
|
{
|
|
string result = _bridge.UserAuth_GetList();
|
|
var response = new { type = "USERAUTH_LIST_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "USERAUTH_SAVE":
|
|
{
|
|
int idx = json.idx ?? 0;
|
|
string user = json.user ?? "";
|
|
int account = json.account ?? 0;
|
|
int purchase = json.purchase ?? 0;
|
|
int purchaseEB = json.purchaseEB ?? 0;
|
|
int holyday = json.holyday ?? 0;
|
|
int project = json.project ?? 0;
|
|
int jobreport = json.jobreport ?? 0;
|
|
int scheapp = json.scheapp ?? 0;
|
|
int equipment = json.equipment ?? 0;
|
|
int otconfirm = json.otconfirm ?? 0;
|
|
int holyreq = json.holyreq ?? 0;
|
|
int kuntae = json.kuntae ?? 0;
|
|
string result = _bridge.UserAuth_Save(idx, user, account, purchase, purchaseEB, holyday, project, jobreport, scheapp, equipment, otconfirm, holyreq, kuntae);
|
|
var response = new { type = "USERAUTH_SAVED", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "USERAUTH_DELETE":
|
|
{
|
|
int idx = json.idx ?? 0;
|
|
string result = _bridge.UserAuth_Delete(idx);
|
|
var response = new { type = "USERAUTH_DELETED", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "USERAUTH_GET_FIELDS":
|
|
{
|
|
string result = _bridge.UserAuth_GetFields();
|
|
var response = new { type = "USERAUTH_FIELDS_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
// ===== 범용 권한 체크 API =====
|
|
case "CHECK_AUTH":
|
|
{
|
|
string authType = json.authType ?? "";
|
|
int requiredLevel = json.requiredLevel ?? 5;
|
|
string result = _bridge.CheckAuth(authType, requiredLevel);
|
|
var response = new { type = "CHECK_AUTH_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "GET_MY_AUTH":
|
|
{
|
|
string result = _bridge.GetMyAuth();
|
|
var response = new { type = "MY_AUTH_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
// ===== 프로젝트 검색 API (업무일지용) =====
|
|
case "PROJECT_SEARCH":
|
|
{
|
|
string keyword = json.keyword ?? "";
|
|
string result = _bridge.Project_Search(keyword);
|
|
var response = new { type = "PROJECT_SEARCH_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "PROJECT_GET_USER_PROJECTS":
|
|
{
|
|
string result = _bridge.Project_GetUserProjects();
|
|
var response = new { type = "PROJECT_USER_PROJECTS_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "PROJECT_GET_CATEGORIES":
|
|
{
|
|
string result = _bridge.Project_GetCategories();
|
|
var response = new { type = "PROJECT_CATEGORIES_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "PROJECT_GET_PROCESSES":
|
|
{
|
|
string result = _bridge.Project_GetProcesses();
|
|
var response = new { type = "PROJECT_PROCESSES_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "PROJECT_GET_LIST":
|
|
{
|
|
string statusFilter = json.statusFilter ?? "";
|
|
string category = json.category ?? "";
|
|
string process = json.process ?? "";
|
|
string userFilter = json.userFilter ?? "";
|
|
string yearStart = json.yearStart ?? "";
|
|
string yearEnd = json.yearEnd ?? "";
|
|
string dateType = json.dateType ?? "0";
|
|
string result = _bridge.Project_GetList(statusFilter, category, process, userFilter, yearStart, yearEnd, dateType);
|
|
var response = new { type = "PROJECT_LIST_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "PROJECT_GET_HISTORY":
|
|
{
|
|
int projectIdx = json.projectIdx ?? 0;
|
|
string result = _bridge.Project_GetHistory(projectIdx);
|
|
var response = new { type = "PROJECT_HISTORY_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "PROJECT_GET_DAILY_MEMO":
|
|
{
|
|
int projectIdx = json.projectIdx ?? 0;
|
|
string result = _bridge.Project_GetDailyMemo(projectIdx);
|
|
var response = new { type = "PROJECT_DAILY_MEMO_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
// ===== 근태 오류검사 API =====
|
|
case "KUNTAE_ERROR_CHECK":
|
|
{
|
|
string sd = json.sd ?? "";
|
|
string ed = json.ed ?? "";
|
|
string result = _bridge.Kuntae_ErrorCheck(sd, ed);
|
|
var response = new { type = "KUNTAE_ERROR_CHECK_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "KUNTAE_FIX_ERROR":
|
|
{
|
|
string pdate = json.pdate ?? "";
|
|
string result = _bridge.Kuntae_FixError(pdate);
|
|
var response = new { type = "KUNTAE_FIX_ERROR_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
case "KUNTAE_FIX_ERRORS":
|
|
{
|
|
string dates = JsonConvert.SerializeObject(json.dates);
|
|
string result = _bridge.Kuntae_FixErrors(dates);
|
|
var response = new { type = "KUNTAE_FIX_ERRORS_DATA", data = JsonConvert.DeserializeObject(result) };
|
|
await Send(socket, JsonConvert.SerializeObject(response));
|
|
}
|
|
break;
|
|
|
|
default:
|
|
Console.WriteLine($"[WS] Unknown message type: {type}");
|
|
break;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"[WS] Handle Error: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
private async Task Send(WebSocket socket, string message)
|
|
{
|
|
if (_socketLocks.TryGetValue(socket, out var semaphore))
|
|
{
|
|
await semaphore.WaitAsync();
|
|
try
|
|
{
|
|
if (socket.State == WebSocketState.Open)
|
|
{
|
|
byte[] buffer = Encoding.UTF8.GetBytes(message);
|
|
await socket.SendAsync(new ArraySegment<byte>(buffer), WebSocketMessageType.Text, true, CancellationToken.None);
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
semaphore.Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
public async void Broadcast(string message)
|
|
{
|
|
byte[] buffer = Encoding.UTF8.GetBytes(message);
|
|
WebSocket[] clientsCopy;
|
|
|
|
lock (_clients)
|
|
{
|
|
clientsCopy = _clients.ToArray();
|
|
}
|
|
|
|
foreach (var client in clientsCopy)
|
|
{
|
|
if (client.State == WebSocketState.Open && _socketLocks.TryGetValue(client, out var semaphore))
|
|
{
|
|
_ = Task.Run(async () =>
|
|
{
|
|
if (await semaphore.WaitAsync(0))
|
|
{
|
|
try
|
|
{
|
|
if (client.State == WebSocketState.Open)
|
|
{
|
|
await client.SendAsync(new ArraySegment<byte>(buffer), WebSocketMessageType.Text, true, CancellationToken.None);
|
|
}
|
|
}
|
|
catch { }
|
|
finally
|
|
{
|
|
semaphore.Release();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|