feat: React 프론트엔드 기능 대폭 확장

- 월별근무표: 휴일/근무일 관리, 자동 초기화
- 메일양식: 템플릿 CRUD, To/CC/BCC 설정
- 그룹정보: 부서 관리, 비트 연산 기반 권한 설정
- 업무일지: 수정 성공 메시지 제거, 오늘 근무시간 필터링 수정
- 웹소켓 메시지 type 충돌 버그 수정

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
backuppc
2025-11-27 17:25:31 +09:00
parent b57af6dad7
commit c9b5d756e1
65 changed files with 14028 additions and 467 deletions

View File

@@ -1,6 +1,6 @@
namespace Project.Dialog
{
partial class fDashboardNew
partial class fDashboard
{
/// <summary>
/// Required designer variable.

View File

@@ -15,26 +15,18 @@ using System.Windows.Forms;
namespace Project.Dialog
{
public partial class fDashboardNew : fBase
public partial class fDashboard : fBase
{
private Web.WebSocketServer _wsServer;
private WebView2 webView;
public fDashboardNew()
private Web.MachineBridge _machineBridge;
public fDashboard()
{
InitializeComponent();
InitializeWebView2();
try
{
_wsServer = new Web.WebSocketServer("http://localhost:8081/", this);
}
catch (Exception ex)
{
MessageBox.Show("Failed to start WebSocket Server (Port 8081). Run as Admin or allow port.\n" + ex.Message);
}
_machineBridge = new Web.MachineBridge(this);
}
bool loadok = false;
public void RefreshView()
{
@@ -80,7 +72,7 @@ namespace Project.Dialog
await this.webView.EnsureCoreWebView2Async();
}
var wwwroot = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Web", "wwwroot");
var wwwroot = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Web", "dist");
webView.CoreWebView2.SetVirtualHostNameToFolderMapping(
"hmi.local",
wwwroot,
@@ -88,16 +80,13 @@ namespace Project.Dialog
// 2. Inject Native Object
webView.CoreWebView2.AddHostObjectToScript("machine", new Web.MachineBridge(this));
webView.CoreWebView2.AddHostObjectToScript("machine", _machineBridge);
Pub.WebServiceURL = "http://hmi.local";
// OWIN 서버의 DashBoard 페이지로 연결
if (FCOMMON.info.Login.no.isEmpty())
webView.Source = new Uri($"{Pub.WebServiceURL}/login.html");
else
webView.Source = new Uri($"{Pub.WebServiceURL}/DashBoard");
RefreshPage();
label1.Visible = false;
loadok = true;
}
@@ -106,6 +95,18 @@ namespace Project.Dialog
MessageBox.Show($"WebView2 초기화 실패: {ex.Message}");
}
}
/// <summary>
/// 로그인 상태에 따라서 페이지를 전환한다
/// </summary>
public void RefreshPage()
{
webView.Source = new Uri($"{Pub.WebServiceURL}/index.html");
//if (FCOMMON.info.Login.no.isEmpty())
//webView.Source = new Uri($"{Pub.WebServiceURL}/login.html");
// else
// webView.Source = new Uri($"{Pub.WebServiceURL}/DashBoard/index.html");
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);

View File

@@ -192,24 +192,24 @@ namespace Project.Dialog
}
}
FCOMMON.info.Login.no = drUser.id;
FCOMMON.info.Login.nameK = drUser.name;
FCOMMON.info.Login.dept = cmbDept.Text;// userdr.dept;// cmbDept.Text;
FCOMMON.info.Login.level = drGrpUser.level;
FCOMMON.info.Login.email = drUser.email;
FCOMMON.info.Login.nameE = drUser.nameE;
FCOMMON.info.Login.hp = drUser.hp;
FCOMMON.info.Login.tel = drUser.tel;
FCOMMON.info.Login.title = drUser.dept + "(" + drUser.grade + ")";
FCOMMON.info.NotShowJobReportview = Pub.setting.NotShowJobreportPRewView;
info.Login.no = drUser.id;
info.Login.nameK = drUser.name;
info.Login.dept = cmbDept.Text;// userdr.dept;// cmbDept.Text;
info.Login.level = drGrpUser.level;
info.Login.email = drUser.email;
info.Login.nameE = drUser.nameE;
info.Login.hp = drUser.hp;
info.Login.tel = drUser.tel;
info.Login.title = drUser.dept + "(" + drUser.grade + ")";
info.NotShowJobReportview = Pub.setting.NotShowJobreportPRewView;
//var gcode = FCOMMON.DBM.ExecuteScalar("select isnull(gcode,'NOGCODE') from UserGroup where dept ='" + cmbDept.Text + "'");
var gperm = FCOMMON.DBM.ExecuteScalar("select isnull(permission,0) from UserGroup where dept ='" + cmbDept.Text + "'");
FCOMMON.info.Login.gcode = gCode;// gcode;
FCOMMON.info.Login.process = drUser.id == "dev" ? "개발자" : drGrpUser.Process;
FCOMMON.info.Login.permission = 0;
FCOMMON.info.Login.gpermission = int.Parse(gperm);
//FCOMMON.info.datapath = Pub.setting.SharedDataPath;
FCOMMON.info.ShowBuyerror = Pub.setting.Showbuyerror; //210625
info.Login.gcode = gCode;// gcode;
info.Login.process = drUser.id == "dev" ? "개발자" : drGrpUser.Process;
info.Login.permission = 0;
info.Login.gpermission = int.Parse(gperm);
//info.datapath = Pub.setting.SharedDataPath;
info.ShowBuyerror = Pub.setting.Showbuyerror; //210625
@@ -220,34 +220,34 @@ namespace Project.Dialog
{
return;
}
FCOMMON.info.Login.no = "dev";
FCOMMON.info.Login.nameK = "개발자";
FCOMMON.info.Login.dept = cmbDept.Text;// userdr.dept;// cmbDept.Text;
FCOMMON.info.Login.level = 10;
FCOMMON.info.Login.email = "";
FCOMMON.info.Login.nameE = "DEVELOPER";
FCOMMON.info.Login.hp = "";
FCOMMON.info.Login.tel = "";
FCOMMON.info.Login.title = "업무일지 개발자";
FCOMMON.info.NotShowJobReportview = Pub.setting.NotShowJobreportPRewView;
info.Login.no = "dev";
info.Login.nameK = "개발자";
info.Login.dept = cmbDept.Text;// userdr.dept;// cmbDept.Text;
info.Login.level = 10;
info.Login.email = "";
info.Login.nameE = "DEVELOPER";
info.Login.hp = "";
info.Login.tel = "";
info.Login.title = "업무일지 개발자";
info.NotShowJobReportview = Pub.setting.NotShowJobreportPRewView;
//var gcode = FCOMMON.DBM.ExecuteScalar("select isnull(gcode,'NOGCODE') from UserGroup where dept ='" + cmbDept.Text + "'");
var gperm = FCOMMON.DBM.ExecuteScalar("select isnull(permission,0) from UserGroup where dept ='" + cmbDept.Text + "'");
FCOMMON.info.Login.gcode = gCode;
FCOMMON.info.Login.process = "개발자";
FCOMMON.info.Login.permission = 0;
FCOMMON.info.Login.gpermission = int.Parse(gperm);
info.Login.gcode = gCode;
info.Login.process = "개발자";
info.Login.permission = 0;
info.Login.gpermission = int.Parse(gperm);
//var datapath = FCOMMON.DBM.getCodeSavlue("55", "01");
//FCOMMON.info.datapath = datapath;// Pub.setting.SharedDataPath;
FCOMMON.info.ShowBuyerror = Pub.setting.Showbuyerror; //210625
//info.datapath = datapath;// Pub.setting.SharedDataPath;
info.ShowBuyerror = Pub.setting.Showbuyerror; //210625
}
//if (FCOMMON.info.datapath.isEmpty() && gCode == "EET1P") //210524
// FCOMMON.info.datapath = @"\\k4fs3201n\k4bpartcenter$";
//if (info.datapath.isEmpty() && gCode == "EET1P") //210524
// info.datapath = @"\\k4fs3201n\k4bpartcenter$";
//using (var dbEnity = new EEEntitiesMain())
//{
// var drGrpUser = dbEnity.EETGW_GroupUser.Where(t => t.uid == userdr.id & t.gcode == gCode).FirstOrDefault();
// if (drGrpUser == null) FCOMMON.info.Login.process = (userdr.id == "dev" ? "개발자" : "");
// else FCOMMON.info.Login.process = drGrpUser.Process;
// if (drGrpUser == null) info.Login.process = (userdr.id == "dev" ? "개발자" : "");
// else info.Login.process = drGrpUser.Process;
//}
//로그인정보 기록
@@ -260,7 +260,7 @@ namespace Project.Dialog
Pub.MakeAutoJobReportByAuto();
DialogResult = DialogResult.OK;
FCOMMON.info.Login.loginusetime = (DateTime.Now - dt).TotalMilliseconds;
info.Login.loginusetime = (DateTime.Now - dt).TotalMilliseconds;
}
catch (Exception ex)
{
@@ -293,7 +293,7 @@ namespace Project.Dialog
try
{
var ta = new dsMSSQLTableAdapters.EETGW_LoginInfoTableAdapter();
ta.Insert(FCOMMON.info.Login.no, DateTime.Now, ip, fullname, info.Login.no, DateTime.Now);
ta.Insert(info.Login.no, DateTime.Now, ip, fullname, info.Login.no, DateTime.Now);
}
catch (Exception ex)
{
@@ -336,9 +336,9 @@ namespace Project.Dialog
//}
var gCode = this.cmbDept.SelectedValue.ToString();// as dsMSSQL.UserGroupRow;
FCOMMON.info.Login.gcode = gCode;
FCOMMON.info.Login.no = "new";
FCOMMON.info.Login.dept = this.cmbDept.Text;
info.Login.gcode = gCode;
info.Login.no = "new";
info.Login.dept = this.cmbDept.Text;
var dlg = FCOMMON.Util.MsgQ($"현재 선택된 그룹[{this.cmbDept.Text}]의 사용자를 추가할까요?\n" +
"추가된 사용자는 담당자로부터 승인 완료되어야 접속이 가능 합니다\n" +