This commit is contained in:
backuppc
2025-07-11 11:30:52 +09:00
parent ed0db28b1f
commit 4f54a97ace
13 changed files with 1187 additions and 131 deletions

View File

@@ -22,9 +22,9 @@ namespace Project.Dialog
{
InitializeComponent();
#if WEB
InitializeWebView2();
#endif
}
private void InitializeWebView2()

63
Project/Dialog/fWarning.Designer.cs generated Normal file
View File

@@ -0,0 +1,63 @@
namespace Project.Dialog
{
partial class fWarning
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.label1 = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// label1
//
this.label1.Dock = System.Windows.Forms.DockStyle.Fill;
this.label1.Location = new System.Drawing.Point(0, 0);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(543, 66);
this.label1.TabIndex = 0;
this.label1.Text = " 실행 환경을 검사하고 있습니다";
this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// fWarning
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(543, 66);
this.Controls.Add(this.label1);
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "fWarning";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "fWarning";
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Label label1;
}
}

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Project.Dialog
{
public partial class fWarning : Form
{
public fWarning()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -51,7 +51,7 @@
<DebugType>Full</DebugType>
<Optimize>False</Optimize>
<OutputPath>..\..\..\..\..\Amkor\GroupWare\</OutputPath>
<DefineConstants>TRACE;DEBUG;WEB</DefineConstants>
<DefineConstants>TRACE;DEBUG;WEB1</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
@@ -265,6 +265,12 @@
<Compile Include="Dialog\fLogin_WB.Designer.cs">
<DependentUpon>fLogin_WB.cs</DependentUpon>
</Compile>
<Compile Include="Dialog\fWarning.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Dialog\fWarning.Designer.cs">
<DependentUpon>fWarning.cs</DependentUpon>
</Compile>
<Compile Include="Web\Controller\BaseController.cs" />
<Compile Include="Web\Controller\APIController.cs" />
<Compile Include="Web\Controller\DashBoardController.cs" />
@@ -493,6 +499,9 @@
<EmbeddedResource Include="Dialog\fUnZip.resx">
<DependentUpon>fUnZip.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Dialog\fWarning.resx">
<DependentUpon>fWarning.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="fLog.resx">
<DependentUpon>fLog.cs</DependentUpon>
</EmbeddedResource>

View File

@@ -9,6 +9,10 @@ using System.Net.NetworkInformation;
using System.Net;
using System.Data.SqlClient;
using System.Data;
using Microsoft.Web.WebView2.Core;
using Microsoft.Web.WebView2.WinForms;
using System.Drawing;
using System.Windows.Forms;
namespace Project
{
@@ -55,6 +59,55 @@ namespace Project
Lang.Loading(Pub.setting.Language + ".ini");
}
private static WebView2 webView21;
public static void InitializeWebView2()
{
// 수동으로 WebView2 컨트롤 생성
webView21 = new WebView2();
// 기본 속성 설정
webView21.CreationProperties = null;
webView21.DefaultBackgroundColor = Color.White;
webView21.Dock = System.Windows.Forms.DockStyle.Fill;
webView21.Location = new Point(0, 0);
webView21.Name = "webView21";
webView21.Size = new Size(800, 600);
webView21.TabIndex = 0;
webView21.ZoomFactor = 1D;
// 비동기 초기화
InitializeAsync();
}
async private static void InitializeAsync()
{
try
{
// Fixed Version 경로 설정
string runtimePath = System.IO.Path.Combine(Application.StartupPath, "WebView2Runtime");
if (System.IO.Directory.Exists(runtimePath))
{
var env = await CoreWebView2Environment.CreateAsync(runtimePath);
await webView21.EnsureCoreWebView2Async(env);
}
else
{
// 시스템에 설치된 WebView2 사용
await webView21.EnsureCoreWebView2Async();
}
// OWIN 서버의 Login 페이지로 연결
//webView21.Source = new Uri("http://127.0.0.1:9000/Home/Login");
InitWebView = 1;
}
catch (Exception ex)
{
InitWebView = 2;
}
}
public static byte InitWebView = 0;
public static string MakePasswordEnc(string data)
{
var sha1 = new System.Security.Cryptography.SHA1CryptoServiceProvider();
@@ -65,7 +118,7 @@ namespace Project
encpass = encpass.Replace(" ", "");
return encpass;
}
public static void SetFormStatus(ref System.Windows.Forms.Form f, string formid,Boolean read)
public static void SetFormStatus(ref System.Windows.Forms.Form f, string formid, Boolean read)
{
var fi = new System.IO.FileInfo(Util.CurrentPath + "formSetting\\" + formid + ".xml");
if (fi.Directory.Exists == false) fi.Directory.Create();

View File

@@ -28,9 +28,6 @@ namespace Project.Web.Controllers
if (p_order.Key != null) sql += " order by " + p_order.Value;
}
if (FCOMMON.info.Login.gcode == null)
FCOMMON.info.Login.gcode = "EET1P";
sql = sql.Replace("{gcode}", FCOMMON.info.Login.gcode);
var cs = Properties.Settings.Default.gwcs; // "Data Source=K4FASQL.kr.ds.amkor.com,50150;Initial Catalog=EE;Persist Security Info=True;User ID=eeadm;Password=uJnU8a8q&DJ+ug-D!";
@@ -80,8 +77,6 @@ namespace Project.Web.Controllers
}
if (FCOMMON.info.Login.gcode == null)
FCOMMON.info.Login.gcode = "EET1P";
sql = sql.Replace("{gcode}", FCOMMON.info.Login.gcode);
var cs = Properties.Settings.Default.gwcs;// "Data Source=K4FASQL.kr.ds.amkor.com,50150;Initial Catalog=EE;Persist Security Info=True;User ID=eeadm;Password=uJnU8a8q&DJ+ug-D!";

View File

@@ -17,26 +17,35 @@ namespace Project.Web.Controllers
}
// PUT api/values/5
public void Put(int id, [FromBody] string value)
{
}
//// PUT api/values/5
//public void Put(int id, [FromBody] string value)
//{
//}
// DELETE api/values/5
public void Delete(int id)
{
}
//// DELETE api/values/5
//public void Delete(int id)
//{
//}
[HttpGet]
public string TodayCountH()
{
var sql = "select count(*) from EETGW_HolydayRequest " +
"where gcode = 'EET1P' and conf = 1 and HolyDays > 0 and " +
"sdate <= GETDATE() and edate >= GETDATE()";
var cnt = DBM.ExecuteScalar(sql);
return cnt.ToString();
" where gcode = @gcode and isnull(conf,0) = 1 "+
" and HolyDays > 0 and " +
" sdate <= GETDATE() and edate >= GETDATE()";
var cn = DBM.getCn();
cn.Open();
var cmd = new System.Data.SqlClient.SqlCommand(sql, cn);
cmd.Parameters.Add("gcode", SqlDbType.VarChar).Value = FCOMMON.info.Login.gcode;
var cnt1 = (int)cmd.ExecuteScalar();
cmd.Dispose();
cn.Dispose();
return cnt1.ToString();
}
[HttpGet]
@@ -74,11 +83,88 @@ namespace Project.Web.Controllers
};
return CreateJsonResponse(response);
}
}
[HttpGet]
public HttpResponseMessage GetholyRequestUser()
{
var sql = string.Empty;
sql = $" select uid,cate,sdate,edate,HolyReason,Users.name,holydays,holytimes,remark " +
$" from EETGW_HolydayRequest INNER JOIN " +
$" Users ON EETGW_HolydayRequest.uid = Users.id " +
$" where EETGW_HolydayRequest.gcode = @gcode" +
$" and isnull(conf,0) = 0 and HolyDays > 0 and sdate <= GETDATE() and edate >= GETDATE()";
//sql = sql.Replace("{gcode}", FCOMMON.info.Login.gcode);
var cs = Properties.Settings.Default.gwcs;// "Data Source=K4FASQL.kr.ds.amkor.com,50150;Initial Catalog=EE;Persist Security Info=True;User ID=eeadm;Password=uJnU8a8q&DJ+ug-D!";
var cn = new System.Data.SqlClient.SqlConnection(cs);
var cmd = new System.Data.SqlClient.SqlCommand(sql, cn);
cmd.Parameters.AddWithValue("gcode", FCOMMON.info.Login.gcode);
var da = new System.Data.SqlClient.SqlDataAdapter(cmd);
var dt = new System.Data.DataTable();
da.Fill(dt);
da.Dispose();
cmd.Dispose();
cn.Dispose();
var txtjson = JsonConvert.SerializeObject(dt, new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
});
var resp = new HttpResponseMessage()
{
Content = new StringContent(
txtjson,
System.Text.Encoding.UTF8,
"application/json")
};
return resp;
}
[HttpGet]
public HttpResponseMessage GetCurrentUserCount()
{
try
{
var cn = DBM.getCn();
var sql = "select count(*) " +
" from EETGW_GroupUser" +
" where gcode = @gcode" +
" and useUserState = 1 and useJobReport =1";
cn.Open();
var cmd = new System.Data.SqlClient.SqlCommand(sql, cn);
cmd.Parameters.Add("gcode", SqlDbType.VarChar).Value = FCOMMON.info.Login.gcode;
var cnt1 = (int)cmd.ExecuteScalar();
cn.Dispose();
var response = new
{
Count = cnt1,
Message = string.Empty,
};
return CreateJsonResponse(response);
}
catch (Exception ex)
{
var response = new
{
Count = 0,
Message = ex.Message,
};
return CreateJsonResponse(response);
}
}
[HttpGet]
public HttpResponseMessage GetPurchaseWaitCount()
@@ -171,6 +257,135 @@ namespace Project.Web.Controllers
return resp;
}
[HttpGet]
public HttpResponseMessage GetPresentUserList()
{
try
{
var sql = "select * from vGroupUser where gcode = @gcode and useUserState = 1 and useJobReport = 1";
var cs = Properties.Settings.Default.gwcs;
var cn = new System.Data.SqlClient.SqlConnection(cs);
var cmd = new System.Data.SqlClient.SqlCommand(sql, cn);
cmd.Parameters.AddWithValue("gcode", FCOMMON.info.Login.gcode);
var da = new System.Data.SqlClient.SqlDataAdapter(cmd);
var dt = new System.Data.DataTable();
da.Fill(dt);
da.Dispose();
cmd.Dispose();
cn.Dispose();
var txtjson = JsonConvert.SerializeObject(dt, new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
});
var resp = new HttpResponseMessage()
{
Content = new StringContent(
txtjson,
System.Text.Encoding.UTF8,
"application/json")
};
return resp;
}
catch (Exception ex)
{
var response = new
{
Message = ex.Message,
};
return CreateJsonResponse(response);
}
}
[HttpGet]
public HttpResponseMessage GetPurchaseNRList()
{
try
{
var sql = "select pdate, process, pumname, pumscale, pumunit, pumqtyreq, pumprice, pumamt from Purchase where gcode = @gcode and state = '---' order by pdate desc";
var cs = Properties.Settings.Default.gwcs;
var cn = new System.Data.SqlClient.SqlConnection(cs);
var cmd = new System.Data.SqlClient.SqlCommand(sql, cn);
cmd.Parameters.AddWithValue("gcode", FCOMMON.info.Login.gcode);
var da = new System.Data.SqlClient.SqlDataAdapter(cmd);
var dt = new System.Data.DataTable();
da.Fill(dt);
da.Dispose();
cmd.Dispose();
cn.Dispose();
var txtjson = JsonConvert.SerializeObject(dt, new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
});
var resp = new HttpResponseMessage()
{
Content = new StringContent(
txtjson,
System.Text.Encoding.UTF8,
"application/json")
};
return resp;
}
catch (Exception ex)
{
var response = new
{
Message = ex.Message,
};
return CreateJsonResponse(response);
}
}
[HttpGet]
public HttpResponseMessage GetPurchaseCRList()
{
try
{
var sql = "select pdate, process, pumname, pumscale, pumunit, pumqtyreq, pumprice, pumamt from EETGW_PurchaseCR where gcode = @gcode and state = '---' order by pdate desc";
var cs = Properties.Settings.Default.gwcs;
var cn = new System.Data.SqlClient.SqlConnection(cs);
var cmd = new System.Data.SqlClient.SqlCommand(sql, cn);
cmd.Parameters.AddWithValue("gcode", FCOMMON.info.Login.gcode);
var da = new System.Data.SqlClient.SqlDataAdapter(cmd);
var dt = new System.Data.DataTable();
da.Fill(dt);
da.Dispose();
cmd.Dispose();
cn.Dispose();
var txtjson = JsonConvert.SerializeObject(dt, new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
});
var resp = new HttpResponseMessage()
{
Content = new StringContent(
txtjson,
System.Text.Encoding.UTF8,
"application/json")
};
return resp;
}
catch (Exception ex)
{
var response = new
{
Message = ex.Message,
};
return CreateJsonResponse(response);
}
}
[HttpGet]
public HttpResponseMessage Index()

View File

@@ -94,6 +94,26 @@
transform: translateY(-5px);
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
}
/* 스크롤바 스타일링 */
.custom-scrollbar::-webkit-scrollbar {
width: var(--scrollbar-width, 16px); /* 동적 스크롤바 너비 */
}
.custom-scrollbar::-webkit-scrollbar-track {
background: rgba(255, 255, 255, 0.1);
border-radius: 8px;
}
.custom-scrollbar::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.3);
border-radius: 8px;
border: 2px solid rgba(255, 255, 255, 0.1);
}
.custom-scrollbar::-webkit-scrollbar-thumb:hover {
background: rgba(255, 255, 255, 0.5);
}
</style>
</head>
<body class="gradient-bg min-h-screen">
@@ -101,14 +121,27 @@
<!-- 헤더 -->
<div class="text-center mb-8 animate-fade-in">
<h1 class="text-4xl font-bold text-white mb-2">근태현황 대시보드</h1>
<p class="text-white/80 text-lg">실시간 근태 현황을 확인하세요</p>
<p class="text-white/80 text-lg">-- 기능 테스트 중입니다 --</p>
<!-- 스크롤바 설정 -->
<div class="mt-4 flex items-center justify-center gap-4">
<label class="text-white/70 text-sm font-medium">스크롤바 크기:</label>
<select id="scrollbarSize" class="bg-white/20 backdrop-blur-sm border border-white/30 rounded-lg px-3 py-2 text-white text-sm focus:outline-none focus:ring-2 focus:ring-primary-400 transition-all">
<option value="8">작게 (8px)</option>
<option value="12">보통 (12px)</option>
<option value="16" selected>크게 (16px)</option>
<option value="20">매우 크게 (20px)</option>
<option value="24">터치용 (24px)</option>
<option value="32">매우 터치용 (32px)</option>
</select>
</div>
</div>
<!-- 통계 카드 -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-5 gap-6 mb-8">
<!-- 출근 카드 -->
<div class="glass-effect rounded-2xl p-6 card-hover animate-slide-up">
<div class="glass-effect rounded-2xl p-6 card-hover animate-slide-up cursor-pointer" onclick="showPresentUserModal()">
<div class="flex items-center justify-between">
<div>
<p class="text-white/70 text-sm font-medium">출근</p>
@@ -138,7 +171,7 @@
</div>
<!-- 휴가요청 카드 -->
<div class="glass-effect rounded-2xl p-6 card-hover animate-slide-up">
<div class="glass-effect rounded-2xl p-6 card-hover animate-slide-up cursor-pointer" onclick="showHolidayRequestModal()">
<div class="flex items-center justify-between">
<div>
<p class="text-white/70 text-sm font-medium">휴가요청</p>
@@ -153,7 +186,7 @@
</div>
<!-- 구매요청 카드(NR) -->
<div class="glass-effect rounded-2xl p-6 card-hover animate-slide-up">
<div class="glass-effect rounded-2xl p-6 card-hover animate-slide-up cursor-pointer" onclick="showPurchaseNRModal()">
<div class="flex items-center justify-between">
<div>
<p class="text-white/70 text-sm font-medium">구매요청(NR)</p>
@@ -168,7 +201,7 @@
</div>
<!-- 구매요청 카드(CR) -->
<div class="glass-effect rounded-2xl p-6 card-hover animate-slide-up">
<div class="glass-effect rounded-2xl p-6 card-hover animate-slide-up cursor-pointer" onclick="showPurchaseCRModal()">
<div class="flex items-center justify-between">
<div>
<p class="text-white/70 text-sm font-medium">구매요청(CR)</p>
@@ -220,6 +253,207 @@
데이터 업데이트 중...
</div>
</div>
<!-- 출근 대상자 모달 -->
<div id="presentUserModal" class="fixed inset-0 bg-black/50 backdrop-blur-sm hidden z-50">
<div class="flex items-center justify-center min-h-screen p-4">
<div class="glass-effect rounded-2xl w-full max-w-4xl max-h-[80vh] overflow-hidden animate-slide-up">
<!-- 모달 헤더 -->
<div class="px-6 py-4 border-b border-white/10 flex items-center justify-between">
<h2 class="text-xl font-semibold text-white flex items-center">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
금일 출근 대상자 목록
</h2>
<button onclick="hidePresentUserModal()" class="text-white/70 hover:text-white transition-colors">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
</svg>
</button>
</div>
<!-- 모달 내용 -->
<div class="overflow-x-auto max-h-[60vh] custom-scrollbar">
<table class="w-full">
<thead class="bg-white/10 sticky top-0">
<tr>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">사번</th>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">이름</th>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">공정</th>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">직급</th>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">상태</th>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">이메일</th>
</tr>
</thead>
<tbody id="presentUserTable" class="divide-y divide-white/10">
<!-- 데이터가 여기에 표시됩니다 -->
</tbody>
</table>
</div>
<!-- 모달 푸터 -->
<div class="px-6 py-4 border-t border-white/10 flex justify-between items-center">
<p class="text-white/70 text-sm"><span id="presentUserCount">0</span></p>
<button onclick="hidePresentUserModal()" class="bg-white/20 hover:bg-white/30 text-white px-4 py-2 rounded-lg transition-colors">
닫기
</button>
</div>
</div>
</div>
</div>
<!-- 휴가요청 모달 -->
<div id="holidayRequestModal" class="fixed inset-0 bg-black/50 backdrop-blur-sm hidden z-50">
<div class="flex items-center justify-center min-h-screen p-4">
<div class="glass-effect rounded-2xl w-full max-w-6xl max-h-[80vh] overflow-hidden animate-slide-up">
<!-- 모달 헤더 -->
<div class="px-6 py-4 border-b border-white/10 flex items-center justify-between">
<h2 class="text-xl font-semibold text-white flex items-center">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
</svg>
휴가 신청 목록
</h2>
<button onclick="hideHolidayRequestModal()" class="text-white/70 hover:text-white transition-colors">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
</svg>
</button>
</div>
<!-- 모달 내용 -->
<div class="overflow-x-auto max-h-[60vh] custom-scrollbar">
<table class="w-full">
<thead class="bg-white/10 sticky top-0">
<tr>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">사번</th>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">이름</th>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">항목</th>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">일자</th>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">요청일</th>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">요청시간</th>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">비고</th>
</tr>
</thead>
<tbody id="holidayRequestTable" class="divide-y divide-white/10">
<!-- 데이터가 여기에 표시됩니다 -->
</tbody>
</table>
</div>
<!-- 모달 푸터 -->
<div class="px-6 py-4 border-t border-white/10 flex justify-between items-center">
<p class="text-white/70 text-sm"><span id="holidayRequestCount">0</span></p>
<button onclick="hideHolidayRequestModal()" class="bg-white/20 hover:bg-white/30 text-white px-4 py-2 rounded-lg transition-colors">
닫기
</button>
</div>
</div>
</div>
</div>
<!-- 구매NR 모달 -->
<div id="purchaseNRModal" class="fixed inset-0 bg-black/50 backdrop-blur-sm hidden z-50">
<div class="flex items-center justify-center min-h-screen p-4">
<div class="glass-effect rounded-2xl w-full max-w-7xl max-h-[80vh] overflow-hidden animate-slide-up">
<!-- 모달 헤더 -->
<div class="px-6 py-4 border-b border-white/10 flex items-center justify-between">
<h2 class="text-xl font-semibold text-white flex items-center">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z"></path>
</svg>
구매요청(NR) 목록
</h2>
<button onclick="hidePurchaseNRModal()" class="text-white/70 hover:text-white transition-colors">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
</svg>
</button>
</div>
<!-- 모달 내용 -->
<div class="overflow-x-auto max-h-[60vh] custom-scrollbar">
<table class="w-full">
<thead class="bg-white/10 sticky top-0">
<tr>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">요청일</th>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">공정</th>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">품명</th>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">규격</th>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">단위</th>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">수량</th>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">단가</th>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">금액</th>
</tr>
</thead>
<tbody id="purchaseNRTable" class="divide-y divide-white/10">
<!-- 데이터가 여기에 표시됩니다 -->
</tbody>
</table>
</div>
<!-- 모달 푸터 -->
<div class="px-6 py-4 border-t border-white/10 flex justify-between items-center">
<p class="text-white/70 text-sm"><span id="purchaseNRCount">0</span></p>
<button onclick="hidePurchaseNRModal()" class="bg-white/20 hover:bg-white/30 text-white px-4 py-2 rounded-lg transition-colors">
닫기
</button>
</div>
</div>
</div>
</div>
<!-- 구매CR 모달 -->
<div id="purchaseCRModal" class="fixed inset-0 bg-black/50 backdrop-blur-sm hidden z-50">
<div class="flex items-center justify-center min-h-screen p-4">
<div class="glass-effect rounded-2xl w-full max-w-7xl max-h-[80vh] overflow-hidden animate-slide-up">
<!-- 모달 헤더 -->
<div class="px-6 py-4 border-b border-white/10 flex items-center justify-between">
<h2 class="text-xl font-semibold text-white flex items-center">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z"></path>
</svg>
구매요청(CR) 목록
</h2>
<button onclick="hidePurchaseCRModal()" class="text-white/70 hover:text-white transition-colors">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
</svg>
</button>
</div>
<!-- 모달 내용 -->
<div class="overflow-x-auto max-h-[60vh] custom-scrollbar">
<table class="w-full">
<thead class="bg-white/10 sticky top-0">
<tr>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">요청일</th>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">공정</th>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">품명</th>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">규격</th>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">단위</th>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">수량</th>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">단가</th>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">금액</th>
</tr>
</thead>
<tbody id="purchaseCRTable" class="divide-y divide-white/10">
<!-- 데이터가 여기에 표시됩니다 -->
</tbody>
</table>
</div>
<!-- 모달 푸터 -->
<div class="px-6 py-4 border-t border-white/10 flex justify-between items-center">
<p class="text-white/70 text-sm"><span id="purchaseCRCount">0</span></p>
<button onclick="hidePurchaseCRModal()" class="bg-white/20 hover:bg-white/30 text-white px-4 py-2 rounded-lg transition-colors">
닫기
</button>
</div>
</div>
</div>
</div>
</div>
<script>
@@ -333,6 +567,25 @@
});
}
// 사용자카운트 데이터 Ajax 업데이트
function updateCurrentUserCount() {
showLoading();
fetch('http://127.0.0.1:9000/DashBoard/GetCurrentUserCount')
.then(response => response.json())
.then(data => {
if (data) {
// NR 구매요청 카운트 업데이트
if (data.Count !== undefined) {
animateNumberChange('presentCount', data.Count);
}
}
hideLoading();
})
.catch(error => {
console.error('현재유저 카운트 업데이트 중 오류 발생:', error);
hideLoading();
});
}
// 숫자 애니메이션
function animateNumberChange(elementId, newValue) {
@@ -366,13 +619,351 @@
updateHolidayList();
updatePurchaseCount();
updateHolydayRequestCount();
updateCurrentUserCount();
// 스크롤바 크기 설정 초기화
initializeScrollbarSize();
// 30초마다 데이터 새로고침
setInterval(() => {
updateLeaveCount();
updateHolidayList();
updatePurchaseCount();
updateHolydayRequestCount();
updateCurrentUserCount();
}, 30000);
// 출근 대상자 모달 표시
function showPresentUserModal() {
document.getElementById('presentUserModal').classList.remove('hidden');
loadPresentUserList();
}
// 출근 대상자 모달 숨기기
function hidePresentUserModal() {
document.getElementById('presentUserModal').classList.add('hidden');
}
// 출근 대상자 목록 로드
function loadPresentUserList() {
showLoading();
fetch('http://127.0.0.1:9000/DashBoard/GetPresentUserList')
.then(response => response.json())
.then(data => {
let tableRows = '';
if (data && data.length > 0) {
data.forEach(item => {
const statusClass = item.useUserState == 1 ? 'bg-success-500/20 text-success-300' : 'bg-danger-500/20 text-danger-300';
const statusText = item.useUserState == 1 ? '활성' : '비활성';
tableRows += `
<tr class="hover:bg-white/5 transition-colors">
<td class="px-6 py-4 whitespace-nowrap text-white">${item.id || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-white">${item.name || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-white/80">${item.processs || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-white/80">${item.grade || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap">
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${statusClass}">
${statusText}
</span>
</td>
<td class="px-6 py-4 whitespace-nowrap text-white/80">${item.email || '-'}</td>
</tr>
`;
});
document.getElementById('presentUserCount').textContent = data.length;
} else {
tableRows = `
<tr>
<td colspan="5" class="px-6 py-8 text-center text-white/50">
출근 대상자가 없습니다
</td>
</tr>
`;
document.getElementById('presentUserCount').textContent = '0';
}
document.getElementById('presentUserTable').innerHTML = tableRows;
hideLoading();
})
.catch(error => {
console.error('출근 대상자 목록 로드 중 오류 발생:', error);
document.getElementById('presentUserTable').innerHTML = `
<tr>
<td colspan="5" class="px-6 py-8 text-center text-danger-400">
데이터를 불러오는 중 오류가 발생했습니다
</td>
</tr>
`;
document.getElementById('presentUserCount').textContent = '0';
hideLoading();
});
}
// ESC 키로 모달 닫기
document.addEventListener('keydown', function(event) {
if (event.key === 'Escape') {
hidePresentUserModal();
hideHolidayRequestModal();
hidePurchaseNRModal();
hidePurchaseCRModal();
}
});
// 모달 외부 클릭으로 닫기
document.getElementById('presentUserModal').addEventListener('click', function(event) {
if (event.target === this) {
hidePresentUserModal();
}
});
// 휴가요청 모달 표시
function showHolidayRequestModal() {
document.getElementById('holidayRequestModal').classList.remove('hidden');
loadHolidayRequestList();
}
// 휴가요청 모달 숨기기
function hideHolidayRequestModal() {
document.getElementById('holidayRequestModal').classList.add('hidden');
}
// 휴가요청 목록 로드
function loadHolidayRequestList() {
showLoading();
fetch('http://127.0.0.1:9000/DashBoard/GetholyRequestUser')
.then(response => response.json())
.then(data => {
let tableRows = '';
if (data && data.length > 0) {
data.forEach(item => {
// 일자 포맷팅 (시작일 ~ 종료일)
const startDate = item.sdate ? new Date(item.sdate).toLocaleDateString('ko-KR') : '-';
const endDate = item.edate ? new Date(item.edate).toLocaleDateString('ko-KR') : '-';
const dateRange = startDate !== '-' && endDate !== '-' ? `${startDate} ~ ${endDate}` : '-';
// 요청일 포맷팅
const requestDate = item.holyday ? new Date(item.holyday).toLocaleDateString('ko-KR') : '-';
tableRows += `
<tr class="hover:bg-white/5 transition-colors">
<td class="px-6 py-4 whitespace-nowrap text-white">${item.uid || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-white">${item.name || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap">
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-primary-500/20 text-primary-300">
${item.cate || '-'}
</span>
</td>
<td class="px-6 py-4 whitespace-nowrap text-white/80">${dateRange}</td>
<td class="px-6 py-4 whitespace-nowrap text-white/80">${requestDate}</td>
<td class="px-6 py-4 whitespace-nowrap text-white/80">${item.holytime || '-'}</td>
<td class="px-6 py-4 text-white/80">${item.remakr || '-'}</td>
</tr>
`;
});
document.getElementById('holidayRequestCount').textContent = data.length;
} else {
tableRows = `
<tr>
<td colspan="7" class="px-6 py-8 text-center text-white/50">
휴가 신청이 없습니다
</td>
</tr>
`;
document.getElementById('holidayRequestCount').textContent = '0';
}
document.getElementById('holidayRequestTable').innerHTML = tableRows;
hideLoading();
})
.catch(error => {
console.error('휴가요청 목록 로드 중 오류 발생:', error);
document.getElementById('holidayRequestTable').innerHTML = `
<tr>
<td colspan="7" class="px-6 py-8 text-center text-danger-400">
데이터를 불러오는 중 오류가 발생했습니다
</td>
</tr>
`;
document.getElementById('holidayRequestCount').textContent = '0';
hideLoading();
});
}
// 휴가요청 모달 외부 클릭으로 닫기
document.getElementById('holidayRequestModal').addEventListener('click', function(event) {
if (event.target === this) {
hideHolidayRequestModal();
}
});
// 구매NR 모달 표시
function showPurchaseNRModal() {
document.getElementById('purchaseNRModal').classList.remove('hidden');
loadPurchaseNRList();
}
// 구매NR 모달 숨기기
function hidePurchaseNRModal() {
document.getElementById('purchaseNRModal').classList.add('hidden');
}
// 구매NR 목록 로드
function loadPurchaseNRList() {
showLoading();
fetch('http://127.0.0.1:9000/DashBoard/GetPurchaseNRList')
.then(response => response.json())
.then(data => {
let tableRows = '';
if (data && data.length > 0) {
data.forEach(item => {
// 요청일 포맷팅
const requestDate = item.pdate ? new Date(item.pdate).toLocaleDateString('ko-KR') : '-';
// 금액 포맷팅 (천 단위 콤마)
const amount = item.pumamt ? Number(item.pumamt).toLocaleString() : '-';
const price = item.pumprice ? Number(item.pumprice).toLocaleString() : '-';
tableRows += `
<tr class="hover:bg-white/5 transition-colors">
<td class="px-6 py-4 whitespace-nowrap text-white/80">${requestDate}</td>
<td class="px-6 py-4 whitespace-nowrap text-white/80">${item.process || '-'}</td>
<td class="px-6 py-4 text-white">${item.pumname || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-white/80">${item.pumscale || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-white/80">${item.pumunit || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-white/80">${item.pumqtyreq || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-white/80">${price}</td>
<td class="px-6 py-4 whitespace-nowrap text-white font-medium">${amount}</td>
</tr>
`;
});
document.getElementById('purchaseNRCount').textContent = data.length;
} else {
tableRows = `
<tr>
<td colspan="8" class="px-6 py-8 text-center text-white/50">
구매요청이 없습니다
</td>
</tr>
`;
document.getElementById('purchaseNRCount').textContent = '0';
}
document.getElementById('purchaseNRTable').innerHTML = tableRows;
hideLoading();
})
.catch(error => {
console.error('구매NR 목록 로드 중 오류 발생:', error);
document.getElementById('purchaseNRTable').innerHTML = `
<tr>
<td colspan="8" class="px-6 py-8 text-center text-danger-400">
데이터를 불러오는 중 오류가 발생했습니다
</td>
</tr>
`;
document.getElementById('purchaseNRCount').textContent = '0';
hideLoading();
});
}
// 구매NR 모달 외부 클릭으로 닫기
document.getElementById('purchaseNRModal').addEventListener('click', function(event) {
if (event.target === this) {
hidePurchaseNRModal();
}
});
// 구매CR 모달 표시
function showPurchaseCRModal() {
document.getElementById('purchaseCRModal').classList.remove('hidden');
loadPurchaseCRList();
}
// 구매CR 모달 숨기기
function hidePurchaseCRModal() {
document.getElementById('purchaseCRModal').classList.add('hidden');
}
// 구매CR 목록 로드
function loadPurchaseCRList() {
showLoading();
fetch('http://127.0.0.1:9000/DashBoard/GetPurchaseCRList')
.then(response => response.json())
.then(data => {
let tableRows = '';
if (data && data.length > 0) {
data.forEach(item => {
// 요청일 포맷팅
const requestDate = item.pdate ? new Date(item.pdate).toLocaleDateString('ko-KR') : '-';
// 금액 포맷팅 (천 단위 콤마)
const amount = item.pumamt ? Number(item.pumamt).toLocaleString() : '-';
const price = item.pumprice ? Number(item.pumprice).toLocaleString() : '-';
tableRows += `
<tr class="hover:bg-white/5 transition-colors">
<td class="px-6 py-4 whitespace-nowrap text-white/80">${requestDate}</td>
<td class="px-6 py-4 whitespace-nowrap text-white/80">${item.process || '-'}</td>
<td class="px-6 py-4 text-white">${item.pumname || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-white/80">${item.pumscale || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-white/80">${item.pumunit || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-white/80">${item.pumqtyreq || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap text-white/80">${price}</td>
<td class="px-6 py-4 whitespace-nowrap text-white font-medium">${amount}</td>
</tr>
`;
});
document.getElementById('purchaseCRCount').textContent = data.length;
} else {
tableRows = `
<tr>
<td colspan="8" class="px-6 py-8 text-center text-white/50">
구매요청이 없습니다
</td>
</tr>
`;
document.getElementById('purchaseCRCount').textContent = '0';
}
document.getElementById('purchaseCRTable').innerHTML = tableRows;
hideLoading();
})
.catch(error => {
console.error('구매CR 목록 로드 중 오류 발생:', error);
document.getElementById('purchaseCRTable').innerHTML = `
<tr>
<td colspan="8" class="px-6 py-8 text-center text-danger-400">
데이터를 불러오는 중 오류가 발생했습니다
</td>
</tr>
`;
document.getElementById('purchaseCRCount').textContent = '0';
hideLoading();
});
}
// 구매CR 모달 외부 클릭으로 닫기
document.getElementById('purchaseCRModal').addEventListener('click', function(event) {
if (event.target === this) {
hidePurchaseCRModal();
}
});
// 스크롤바 크기 초기화
function initializeScrollbarSize() {
const savedSize = localStorage.getItem('scrollbarSize') || '16';
const select = document.getElementById('scrollbarSize');
select.value = savedSize;
updateScrollbarSize(savedSize);
// 콤보박스 변경 이벤트 리스너
select.addEventListener('change', function() {
const size = this.value;
updateScrollbarSize(size);
localStorage.setItem('scrollbarSize', size);
});
}
// 스크롤바 크기 업데이트
function updateScrollbarSize(size) {
document.documentElement.style.setProperty('--scrollbar-width', size + 'px');
}
</script>
</body>
</html>

View File

@@ -154,11 +154,8 @@
class="input-field w-full px-4 py-3 bg-white/10 border border-white/20 rounded-xl text-white focus:outline-none focus:border-primary-400 input-focus appearance-none"
required
>
<option value="" class="text-gray-800">부서를 선택하세요</option>
<option value="" class="text-white/60">부서를 선택하세요</option>
</select>
<label for="gcode" class="floating-label absolute left-4 top-3 text-white/60 text-sm pointer-events-none">
부서 선택
</label>
<div class="absolute right-3 top-3 pointer-events-none">
<svg class="w-5 h-5 text-white/40" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
@@ -172,13 +169,10 @@
type="text"
id="userId"
name="userId"
class="input-field w-full px-4 py-3 bg-white/10 border border-white/20 rounded-xl text-white placeholder-transparent focus:outline-none focus:border-primary-400 input-focus"
placeholder="사용자 ID"
class="input-field w-full px-4 py-3 bg-white/10 border border-white/20 rounded-xl text-white placeholder-white/60 focus:outline-none focus:border-primary-400 input-focus"
placeholder="사원번호"
required
>
<label for="userId" class="floating-label absolute left-4 top-3 text-white/60 text-sm pointer-events-none">
사용자 ID
</label>
<div class="absolute right-3 top-3">
<svg class="w-5 h-5 text-white/40" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"></path>
@@ -192,13 +186,10 @@
type="password"
id="password"
name="password"
class="input-field w-full px-4 py-3 bg-white/10 border border-white/20 rounded-xl text-white placeholder-transparent focus:outline-none focus:border-primary-400 input-focus"
class="input-field w-full px-4 py-3 bg-white/10 border border-white/20 rounded-xl text-white placeholder-white/60 focus:outline-none focus:border-primary-400 input-focus"
placeholder="비밀번호"
required
>
<label for="password" class="floating-label absolute left-4 top-3 text-white/60 text-sm pointer-events-none">
비밀번호
</label>
<div class="absolute right-3 top-3">
<svg class="w-5 h-5 text-white/40" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"></path>
@@ -439,27 +430,13 @@
// 부서 선택
const gcodeSelect = document.getElementById('gcode');
gcodeSelect.value = data.Gcode;
// 부서 선택 시 라벨 애니메이션 적용
const label = gcodeSelect.nextElementSibling;
if (label && label.classList.contains('floating-label')) {
label.style.transform = 'translateY(-1.5rem) scale(0.85)';
label.style.color = '#3b82f6';
}
hasPreviousInfo = true;
}
if (data && data.UserId) {
// 사용자 ID 설정
document.getElementById('userId').value = data.UserId;
// 사용자 ID 입력 시 라벨 애니메이션 적용
const userIdInput = document.getElementById('userId');
const label = userIdInput.nextElementSibling;
if (label && label.classList.contains('floating-label')) {
label.style.transform = 'translateY(-1.5rem) scale(0.85)';
label.style.color = '#3b82f6';
}
// 사용자 ID 설정 - 세미콜론으로 구분된 경우 첫 번째 요소만 사용
const userId = data.UserId.split(';')[0];
document.getElementById('userId').value = userId;
hasPreviousInfo = true;
}

View File

@@ -105,10 +105,12 @@ namespace Project
this.Text = Application.ProductName + " v" + Application.ProductVersion;
Pub.init();
Pub.InitializeWebView2();
setToolbar();
var f = new Dialog.fWarning();
f.TopMost = true;
f.Show();
_SetLang();
if (Pub.setting.FullScreen) this.WindowState = FormWindowState.Maximized;
@@ -137,10 +139,6 @@ namespace Project
//Data Source=K4FASQL.kr.ds.amkor.com,50150;Initial Catalog=EE;Persist Security Info=True;User ID=eeadm;Password=uJnU8a8q&DJ+ug-D;Encrypt=False;TrustServerCertificate=True
Pub.barcode = new Device.Barcode();
if (!Pub.setting.Barcode.isEmpty()) Pub.barcode.PortName = Pub.setting.Barcode;
Pub.barcode.ReceiveData += barcode_ReceiveData;
@@ -167,8 +165,22 @@ namespace Project
webok = false;
}
var wat = new System.Diagnostics.Stopwatch();
wat.Restart();
while(true)
{
if (Pub.InitWebView != 0) break;
if (wat.ElapsedMilliseconds > 5000) break;
System.Threading.Thread.Sleep(1000);
Application.DoEvents();
}
f.Dispose();
Func_Login();
///즐겨찾기 목록 갱신
Update_FavoriteSite();
@@ -204,18 +216,19 @@ namespace Project
void Func_Login()
{
#if WEB
//Pub.InitWebView = 2;
if (Pub.InitWebView == 1)
{
using (var f = new Dialog.fLogin_WB())
if (f.ShowDialog() != System.Windows.Forms.DialogResult.OK)
Application.ExitThread();
#else
}
else
{
using (var f = new Dialog.fLogin())
if (f.ShowDialog() != System.Windows.Forms.DialogResult.OK)
Application.ExitThread();
#endif
}
this.mn_purchase.Visible = FCOMMON.Util.getBit(FCOMMON.info.Login.gpermission, (int)FCOMMON.eGroupPermission.menu_purchase);

Submodule Sub/AmkorRestfulService deleted from 69b33b6e3c

View File

@@ -78,7 +78,7 @@ namespace FCOMMON
var retval = new UserGroupModel();
var cn = getCn();
var sql = "select * from UserGroup where gcode = @gcode";
var sql = "select gcode,dept,isnull(permission,0) as permission from UserGroup where gcode = @gcode";
var cmd = new System.Data.SqlClient.SqlCommand(sql, cn);
cmd.Parameters.Add("gcode", SqlDbType.VarChar).Value = gcode;
cn.Open();
@@ -88,6 +88,7 @@ namespace FCOMMON
{
retval.gcode = rdr["gcode"].ToString();
retval.name = rdr["dept"].ToString();
retval.perm = int.Parse(rdr["permission"].ToString());
cnt += 1;
}
cn.Dispose();