Compare commits

...

7 Commits

Author SHA1 Message Date
backuppc
479a736b80 .. 2025-07-14 16:30:03 +09:00
backuppc
032f6e4c4e web server port 9000 -> 7979 2025-07-14 10:58:26 +09:00
backuppc
d97c17cfcb .. 2025-07-11 11:31:56 +09:00
backuppc
4f54a97ace .. 2025-07-11 11:30:52 +09:00
backuppc
ed0db28b1f dashboard 2025-07-10 17:40:31 +09:00
backuppc
26cb328f8f udpate login.html 2025-07-10 14:36:05 +09:00
backuppc
43526a26ec 요청자 : k5 김예희(EST)
업무일지 - 사용자목록 오름차순 정렬
ot목록 - 사용자목록 오름차순 정렬,  ot시작,종료시간 추가
2025-07-10 09:22:47 +09:00
57 changed files with 3479 additions and 574 deletions

View File

@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.6.33801.468
# Visual Studio Express 15 for Windows Desktop
VisualStudioVersion = 15.0.36123.18
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EETGW", "Project\EETGW.csproj", "{65F3E762-800C-499E-862F-A535642EC59F}"
EndProject
@@ -27,8 +27,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FPM0000", "SubProject\FPM00
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "arControl", "Sub\arCtl\arControl.csproj", "{F31C242C-1B15-4518-9733-48558499FE4B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AmkorRestfulService", "Sub\AmkorRestfulService\AmkorRestfulService.csproj", "{58CFC90C-5068-46A2-A8DE-0E92EE9E0990}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "arTCPService.Shared", "Sub\tcpservice\arTCPService.Shared\arTCPService.Shared.csproj", "{3CD79316-211A-4B57-A6B4-00FA6091C29D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UMSControl", "SubProject\CMSControl\UMSControl.csproj", "{55EF08A8-6E94-4569-8371-7AAC9DE916AB}"
@@ -46,6 +44,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YARTE", "Sub\YARTE\YARTE.cs
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Console_SendMail", "Sub\Console_SendMail\Console_SendMail.csproj", "{8C94D335-7468-4964-AA24-1E3313CF7ABA}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AmkorRestfulService", "SubProject\AmkorRestfulService\AmkorRestfulService.csproj", "{58CFC90C-5068-46A2-A8DE-0E92EE9E0990}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -120,14 +120,6 @@ Global
{F31C242C-1B15-4518-9733-48558499FE4B}.Release|Any CPU.Build.0 = Release|Any CPU
{F31C242C-1B15-4518-9733-48558499FE4B}.Release|x86.ActiveCfg = Release|Any CPU
{F31C242C-1B15-4518-9733-48558499FE4B}.Release|x86.Build.0 = Release|Any CPU
{58CFC90C-5068-46A2-A8DE-0E92EE9E0990}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{58CFC90C-5068-46A2-A8DE-0E92EE9E0990}.Debug|Any CPU.Build.0 = Debug|Any CPU
{58CFC90C-5068-46A2-A8DE-0E92EE9E0990}.Debug|x86.ActiveCfg = Debug|x86
{58CFC90C-5068-46A2-A8DE-0E92EE9E0990}.Debug|x86.Build.0 = Debug|x86
{58CFC90C-5068-46A2-A8DE-0E92EE9E0990}.Release|Any CPU.ActiveCfg = Release|Any CPU
{58CFC90C-5068-46A2-A8DE-0E92EE9E0990}.Release|Any CPU.Build.0 = Release|Any CPU
{58CFC90C-5068-46A2-A8DE-0E92EE9E0990}.Release|x86.ActiveCfg = Release|x86
{58CFC90C-5068-46A2-A8DE-0E92EE9E0990}.Release|x86.Build.0 = Release|x86
{3CD79316-211A-4B57-A6B4-00FA6091C29D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3CD79316-211A-4B57-A6B4-00FA6091C29D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3CD79316-211A-4B57-A6B4-00FA6091C29D}.Debug|x86.ActiveCfg = Debug|Any CPU
@@ -176,6 +168,14 @@ Global
{8C94D335-7468-4964-AA24-1E3313CF7ABA}.Release|Any CPU.Build.0 = Release|Any CPU
{8C94D335-7468-4964-AA24-1E3313CF7ABA}.Release|x86.ActiveCfg = Release|Any CPU
{8C94D335-7468-4964-AA24-1E3313CF7ABA}.Release|x86.Build.0 = Release|Any CPU
{58CFC90C-5068-46A2-A8DE-0E92EE9E0990}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{58CFC90C-5068-46A2-A8DE-0E92EE9E0990}.Debug|Any CPU.Build.0 = Debug|Any CPU
{58CFC90C-5068-46A2-A8DE-0E92EE9E0990}.Debug|x86.ActiveCfg = Debug|x86
{58CFC90C-5068-46A2-A8DE-0E92EE9E0990}.Debug|x86.Build.0 = Debug|x86
{58CFC90C-5068-46A2-A8DE-0E92EE9E0990}.Release|Any CPU.ActiveCfg = Release|Any CPU
{58CFC90C-5068-46A2-A8DE-0E92EE9E0990}.Release|Any CPU.Build.0 = Release|Any CPU
{58CFC90C-5068-46A2-A8DE-0E92EE9E0990}.Release|x86.ActiveCfg = Release|x86
{58CFC90C-5068-46A2-A8DE-0E92EE9E0990}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -190,12 +190,12 @@ Global
{150859D3-1C5D-4E20-B324-F9EBE188D893} = {28105E67-9D33-4627-8E26-FCE67700622F}
{D01A7891-AD0B-489B-8C45-F598C875FE26} = {6C7EC99E-7367-4255-A039-EF5E8D75A2F6}
{F31C242C-1B15-4518-9733-48558499FE4B} = {28105E67-9D33-4627-8E26-FCE67700622F}
{58CFC90C-5068-46A2-A8DE-0E92EE9E0990} = {28105E67-9D33-4627-8E26-FCE67700622F}
{3CD79316-211A-4B57-A6B4-00FA6091C29D} = {28105E67-9D33-4627-8E26-FCE67700622F}
{55EF08A8-6E94-4569-8371-7AAC9DE916AB} = {28105E67-9D33-4627-8E26-FCE67700622F}
{CAFE5CD0-C055-4C77-9253-8D5EE9558D43} = {6C7EC99E-7367-4255-A039-EF5E8D75A2F6}
{3869B8C1-1290-4864-B72D-D771475F914D} = {6C7EC99E-7367-4255-A039-EF5E8D75A2F6}
{DB5EE9C8-EACF-4231-877E-B9DFD7A714DE} = {28105E67-9D33-4627-8E26-FCE67700622F}
{58CFC90C-5068-46A2-A8DE-0E92EE9E0990} = {6C7EC99E-7367-4255-A039-EF5E8D75A2F6}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B5B1FD72-356F-4840-83E8-B070AC21C8D9}

View File

@@ -21,7 +21,11 @@ namespace Project.Dialog
public fDashboard()
{
InitializeComponent();
InitializeWebView2();
}
private void InitializeWebView2()
{
@@ -62,7 +66,7 @@ namespace Project.Dialog
await this.webView21.EnsureCoreWebView2Async();
}
// OWIN 서버의 DashBoard 페이지로 연결
webView21.Source = new Uri("http://127.0.0.1:9000/DashBoard");
webView21.Source = new Uri($"{Pub.setting.WebServiceURL}/DashBoard");
label1.Visible = false;
}
catch (Exception ex)

46
Project/Dialog/fJobReport.Designer.cs generated Normal file
View File

@@ -0,0 +1,46 @@
namespace Project.Dialog
{
partial class fJobReport
{
/// <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.SuspendLayout();
//
// fJobReport
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(1063, 567);
this.Name = "fJobReport";
this.Text = "업무일지";
this.ResumeLayout(false);
}
#endregion
}
}

View File

@@ -0,0 +1,86 @@
using FCM0000.Mail;
using FCOMMON;
using Microsoft.Web.WebView2.Core;
using Microsoft.Web.WebView2.WinForms;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Project.Dialog
{
public partial class fJobReport : fBase
{
private WebView2 webView21;
public fJobReport()
{
InitializeComponent();
InitializeWebView2();
}
private void InitializeWebView2()
{
// 수동으로 WebView2 컨트롤 생성
this.webView21 = new WebView2();
// 기본 속성 설정
this.webView21.CreationProperties = null;
this.webView21.DefaultBackgroundColor = Color.White;
this.webView21.Dock = DockStyle.Fill;
this.webView21.Location = new Point(0, 0);
this.webView21.Name = "webView21";
this.webView21.Size = new Size(800, 600);
this.webView21.TabIndex = 0;
this.webView21.ZoomFactor = 1D;
// 폼에 추가
this.Controls.Add(this.webView21);
// 비동기 초기화
InitializeAsync();
}
private async void InitializeAsync()
{
try
{
// Fixed Version 경로 설정
string runtimePath = Path.Combine(Application.StartupPath, "WebView2Runtime");
if (Directory.Exists(runtimePath))
{
var env = await CoreWebView2Environment.CreateAsync(runtimePath);
await this.webView21.EnsureCoreWebView2Async(env);
}
else
{
// 시스템에 설치된 WebView2 사용
await this.webView21.EnsureCoreWebView2Async();
}
// OWIN 서버의 DashBoard 페이지로 연결
webView21.Source = new Uri($"{Pub.setting.WebServiceURL}/Jobreport");
}
catch (Exception ex)
{
MessageBox.Show($"WebView2 초기화 실패: {ex.Message}");
}
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
EnsureVisibleAndUsableSize();
}
private void label1_Click(object sender, EventArgs e)
{
}
}
}

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

@@ -76,8 +76,11 @@ namespace Project.Dialog
// 시스템에 설치된 WebView2 사용
await this.webView21.EnsureCoreWebView2Async();
}
// OWIN 서버의 DashBoard 페이지로 연결
webView21.Source = new Uri("http://127.0.0.1:9000/Home/Login");
// WebView2에서 C# 메서드를 호출할 수 있도록 설정
webView21.CoreWebView2.WebMessageReceived += WebView2_WebMessageReceived;
// OWIN 서버의 Login 페이지로 연결
webView21.Source = new Uri($"{Pub.setting.WebServiceURL}/Home/Login");
label1.Visible = false;
}
catch (Exception ex)
@@ -85,6 +88,62 @@ namespace Project.Dialog
MessageBox.Show($"WebView2 초기화 실패: {ex.Message}");
}
}
// WebView2에서 보낸 메시지를 받아서 처리
private void WebView2_WebMessageReceived(object sender, CoreWebView2WebMessageReceivedEventArgs e)
{
try
{
var message = e.TryGetWebMessageAsString();
if (message == "LOGIN_SUCCESS")
{
// UI 스레드에서 실행
this.Invoke(new Action(() =>
{
// button1_Click과 동일한 로직 실행
ExecuteLoginLogic();
}));
}
}
catch (Exception ex)
{
Console.WriteLine($"WebView2 메시지 처리 오류: {ex.Message}");
}
}
// 로그인 성공 시 실행할 로직 (button1_Click과 동일)
private void ExecuteLoginLogic()
{
DateTime dt = DateTime.Now;
// 로그인 정보가 이미 설정되어 있다고 가정 (웹에서 처리됨)
if (string.IsNullOrEmpty(FCOMMON.info.Login.no))
{
MessageBox.Show("로그인 정보가 설정되지 않았습니다.");
return;
}
try
{
// 로그인정보 기록
AddLoginInfo();
//210221
MakeAutoJobReportbyLogin();
//210613
MakeAutoJobReportByAuto();
DialogResult = DialogResult.OK;
FCOMMON.info.Login.loginusetime = (DateTime.Now - dt).TotalMilliseconds;
}
catch (Exception ex)
{
Util.MsgE("로그인 처리 중 오류가 발생했습니다.\n\n" + ex.Message);
DialogResult = System.Windows.Forms.DialogResult.Cancel;
}
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);

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>DEBUG;TRACE</DefineConstants>
<DefineConstants>TRACE;DEBUG;WEB1</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
@@ -259,12 +259,24 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Dialog\fJobReport.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Dialog\fJobReport.Designer.cs">
<DependentUpon>fJobReport.cs</DependentUpon>
</Compile>
<Compile Include="Dialog\fLogin_WB.cs">
<SubType>Form</SubType>
</Compile>
<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" />
@@ -463,6 +475,9 @@
<EmbeddedResource Include="Dev\fDisableItem.resx">
<DependentUpon>fDisableItem.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Dialog\fJobReport.resx">
<DependentUpon>fJobReport.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Dialog\fDashboard.resx">
<DependentUpon>fDashboard.cs</DependentUpon>
</EmbeddedResource>
@@ -493,6 +508,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>
@@ -636,15 +654,15 @@
<Content Include="Web\wwwroot\DashBoard\index.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Web\wwwroot\Jobreport\index.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Web\wwwroot\login.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<None Include="Web\wwwroot\index.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Web\wwwroot\dashboard.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.0">

View File

@@ -17,35 +17,7 @@ namespace Project.Manager
return cn;
}
/// <summary>
/// 입력된 id의 그룹정보를 반환
/// </summary>
/// <param name="gcode"></param>
/// <param name="uid"></param>
/// <returns></returns>
public static GroupUserModel GetGroupUser(string gcode, string uid)
{
var retval = new GroupUserModel();
var cn = getCn();
var sql = "select * from EETGW_GroupUser where gcode = @gcode and uid = @uid";
var cmd = new System.Data.SqlClient.SqlCommand(sql,cn);
cmd.Parameters.Add("gcode", SqlDbType.VarChar).Value = gcode;
cmd.Parameters.Add("uid", SqlDbType.VarChar).Value = uid;
cn.Open();
var rdr = cmd.ExecuteReader();
var cnt = 0;
foreach(var dr in rdr)
{
cnt += 1;
}
retval.Gcode = gcode;
retval.uid = uid;
cn.Dispose();
return retval;
}
public static List<String> getGroupList(string GroupColumn, string table, string where = "")

View File

@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호가 자동으로
// 지정되도록 할 수 있습니다.
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("25.07.02.2320")]
[assembly: AssemblyFileVersion("25.07.02.2320")]
[assembly: AssemblyVersion("25.07.14.1050")]
[assembly: AssemblyFileVersion("25.07.14.1050")]

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
{
@@ -26,7 +30,7 @@ namespace Project
public static CResult Result = new CResult();
public static DatabaseConnectionString.DatabaseInfo dbinfo = null;
public static void init()
public static void init()
{
FCOMMON.info.Path = Util.CurrentPath;
if (Util.isLocalApplication())
@@ -48,67 +52,114 @@ namespace Project
//log
log = new arUtil.Log();
//clear login info
//clear login info
FCOMMON.info.Login = new FCOMMON.info.sUserInfo();
//language
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();
}
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();
var buffer = System.Text.Encoding.Default.GetBytes(data);
var hashbuf = sha1.ComputeHash(buffer);
var encpass = hashbuf.GetHexString();
var ta = new dsMSSQLTableAdapters.UsersTableAdapter();
encpass = encpass.Replace(" ", "");
return encpass;
}
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();
arUtil.XMLHelper xml = new arUtil.XMLHelper(fi.FullName);
if (!xml.Exist())
{
xml.CreateFile();
if (read) return; //읽기인데 파일이 없으므로 넘어간다.
}
if (read)
{
var leftStr = xml.get_Data("position", "left");
var topStr = xml.get_Data("position", "top");
int l = 0;
int t = 0;
if (!int.TryParse(leftStr, out l)) l = 0;
if (!int.TryParse(topStr, out t)) t = 0;
if (l != 0 || t != 0)
{
f.Location = new System.Drawing.Point(l, t);
}
{
var sha1 = new System.Security.Cryptography.SHA1CryptoServiceProvider();
var buffer = System.Text.Encoding.Default.GetBytes(data);
var hashbuf = sha1.ComputeHash(buffer);
var encpass = hashbuf.GetHexString();
var ta = new dsMSSQLTableAdapters.UsersTableAdapter();
encpass = encpass.Replace(" ", "");
return encpass;
}
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();
arUtil.XMLHelper xml = new arUtil.XMLHelper(fi.FullName);
if (!xml.Exist())
{
xml.CreateFile();
if (read) return; //읽기인데 파일이 없으므로 넘어간다.
}
if (read)
{
var leftStr = xml.get_Data("position", "left");
var topStr = xml.get_Data("position", "top");
int l = 0;
int t = 0;
if (!int.TryParse(leftStr, out l)) l = 0;
if (!int.TryParse(topStr, out t)) t = 0;
if (l != 0 || t != 0)
{
f.Location = new System.Drawing.Point(l, t);
}
var wStr = xml.get_Data("size", "width");
var hStr = xml.get_Data("size", "height");
int w = 0;
int h = 0;
if (!int.TryParse(wStr, out w)) w = 0;
if (!int.TryParse(hStr, out h)) h = 0;
if (w != 0 || h != 0)
{
f.Size = new System.Drawing.Size(w, h);
}
}
else
{
xml.set_Data("position", "left", f.Left.ToString());
xml.set_Data("position", "top", f.Top.ToString());
xml.set_Data("size", "width", f.Width.ToString());
xml.set_Data("size", "height", f.Height.ToString());
xml.Save();
}
var wStr = xml.get_Data("size", "width");
var hStr = xml.get_Data("size", "height");
int w = 0;
int h = 0;
if (!int.TryParse(wStr, out w)) w = 0;
if (!int.TryParse(hStr, out h)) h = 0;
if (w != 0 || h != 0)
{
f.Size = new System.Drawing.Size(w, h);
}
}
else
{
xml.set_Data("position", "left", f.Left.ToString());
xml.set_Data("position", "top", f.Top.ToString());
xml.set_Data("size", "width", f.Width.ToString());
xml.set_Data("size", "height", f.Height.ToString());
xml.Save();
}
}
}
public static void CheckNRegister3(string prgmName, string develop, string prgmVersion)
{
if (prgmName.Length > 50) prgmName = prgmName.Substring(0, 50); //길이제한

View File

@@ -8,7 +8,7 @@ namespace Project
{
public enum eFormList
{
=0,
= 0,
NR구매관리,
,
,
@@ -34,7 +34,7 @@ namespace Project
#endregion
[DisplayName("업무일지8시간초과입력불가"),Description("업무일지 근무시간 란에 8시간을 초과 입력 할 수 없게 합니다")]
[DisplayName("업무일지8시간초과입력불가"), Description("업무일지 근무시간 란에 8시간을 초과 입력 할 수 없게 합니다")]
public Boolean Disable8HourOver { get; set; }
//[DisplayName("원달러환율")]
@@ -61,7 +61,7 @@ namespace Project
public string SharedDataPath { get; set; }
[Category("구매"),DisplayName("오류항목표시")]
[Category("구매"), DisplayName("오류항목표시")]
public Boolean Showbuyerror { get; set; }
[DisplayName("업무일지 미리보기 창 숨김")]
@@ -70,6 +70,8 @@ namespace Project
[Category("Barcode"), DisplayName("Port Name")]
public string Barcode { get; set; }
public string WebServiceURL { get; set; }
[Browsable(false)]
public string lastid { get; set; }
[Browsable(false)]
@@ -81,7 +83,10 @@ namespace Project
[DisplayName("Tool Bar")]
public eToolPosition HideToolbar { get; set; }
public Setting() : this(Util.CurrentPath + "setting.xml") {}
public Setting() : this(Util.CurrentPath + "setting.xml") { }
@@ -100,6 +105,9 @@ namespace Project
public override void AfterLoad()
{
//if (wondoller < 1) wondoller = 1200;
if (WebServiceURL.isEmpty())
WebServiceURL = "http://127.0.0.1:7979";
if (Language.isEmpty()) Language = "Kor";
if (Password_Setup.isEmpty()) Password_Setup = "0000";
if (Password_User.isEmpty()) Password_User = "9999";
@@ -112,9 +120,9 @@ namespace Project
var = Xml.get_Data("startForm");
var list = Enum.GetNames(typeof(eFormList));
int idx = -1;
for(int i = 0 ;i<list.Length;i++)
for (int i = 0; i < list.Length; i++)
{
if(list[i] == )
if (list[i] == )
{
idx = i;
}

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

@@ -4,7 +4,7 @@ using System.Linq;
using System.Net;
using System.Web.Http;
using agi = HtmlAgilityPack;
using Project.Web.Model;
namespace Project.Web.Controllers
{

View File

@@ -1,6 +1,7 @@
using FCOMMON;
using Newtonsoft.Json;
using System;
using System.Data;
using System.Linq;
using System.Net.Http;
using System.Security.Cryptography;
@@ -16,46 +17,91 @@ 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 sdate <= convert(varchar(10),GETDATE(),120) and edate >= convert(varchar(10),GETDATE(),120)";
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]
public HttpResponseMessage GetHolydayRequestCount()
{
try
{
var cn = DBM.getCn();
var sql = "select count(*) from EETGW_HolydayRequest" +
" where gcode = @gcode" +
" and isnull(conf,0) = 0";
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
{
HOLY = cnt1,
Message = string.Empty,
};
return CreateJsonResponse(response);
}
catch (Exception ex)
{
var response = new
{
HOLY = 0,
Message = ex.Message,
};
return CreateJsonResponse(response);
}
}
[HttpGet]
public HttpResponseMessage GetholyUser()
public HttpResponseMessage GetholyRequestUser()
{
var sql = string.Empty;
sql = $"select uid,cate,sdate,edate,HolyReason " +
$"from EETGW_HolydayRequest " +
$"where gcode = '{FCOMMON.info.Login.gcode}'" +
$"and conf = 1 and HolyDays > 0 and sdate <= GETDATE() and edate >= GETDATE()";
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 sdate <= convert(varchar(10),GETDATE(),120) and edate >= convert(varchar(10),GETDATE(),120)";
if (info.Login.gcode == null)
info.Login.gcode = "EET1P";
sql = sql.Replace("{gcode}", FCOMMON.info.Login.gcode);
//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);
@@ -77,10 +123,325 @@ namespace Project.Web.Controllers
};
return resp;
}
[HttpGet]
public HttpResponseMessage GetJobData(string startDate = "", string endDate = "")
{
var sql = string.Empty;
// 기본값 설정 (이번 달)
if (string.IsNullOrEmpty(startDate) || string.IsNullOrEmpty(endDate))
{
var now = DateTime.Now;
var firstDayOfMonth = new DateTime(now.Year, now.Month, 1);
var lastDayOfMonth = firstDayOfMonth.AddMonths(1).AddDays(-1);
startDate = firstDayOfMonth.ToString("yyyy-MM-dd");
endDate = lastDayOfMonth.ToString("yyyy-MM-dd");
}
sql = $" select idx,pdate,status,projectName, uid, requestpart, package,type,process,description," +
" hrs,ot,otStart,otEnd" +
" from JobReport" +
" where gcode = @gcode and uid = @uid" +
" and pdate between @startDate and @endDate" +
" order by pdate desc, wdate 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);
cmd.Parameters.AddWithValue("uid", FCOMMON.info.Login.no);
cmd.Parameters.AddWithValue("startDate", startDate);
cmd.Parameters.AddWithValue("endDate", endDate);
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()
{
try
{
FCOMMON.DBM.GetPurchaseWaitCount(FCOMMON.info.Login.gcode, out int cnt1, out int cnt2);
var response = new
{
NR = cnt1,
CR = cnt2,
Message = string.Empty,
};
return CreateJsonResponse(response);
}
catch (Exception ex)
{
var response = new
{
NR = 0,
CR = 0,
Message = ex.Message,
};
return CreateJsonResponse(response);
}
}
[HttpGet]
public HttpResponseMessage GetUserGroups()
{
var dt = DBM.GetUserGroups();
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 GetholyUser()
{
var sql = string.Empty;
sql = $" select uid,cate,sdate,edate,HolyReason,Users.name " +
$" from EETGW_HolydayRequest INNER JOIN " +
$" Users ON EETGW_HolydayRequest.uid = Users.id " +
$" where EETGW_HolydayRequest.gcode = @gcode" +
$" and conf = 1 " +
$" and sdate <= convert(varchar(10),GETDATE(),120) and edate >= convert(varchar(10),GETDATE(),120)";
//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 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()
{
@@ -112,5 +473,21 @@ namespace Project.Web.Controllers
return resp;
}
private HttpResponseMessage CreateJsonResponse(object data)
{
var json = JsonConvert.SerializeObject(data, new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
});
return new HttpResponseMessage()
{
Content = new StringContent(
json,
System.Text.Encoding.UTF8,
"application/json")
};
}
}
}

View File

@@ -4,12 +4,14 @@ using System.Net.Http;
using System.Web.Http;
using Newtonsoft.Json;
using System.Collections.Generic;
using FCOMMON;
namespace Project.Web.Controllers
{
// 로그인 요청 모델
public class LoginRequest
{
public string Gcode { get; set; }
public string UserId { get; set; }
public string Password { get; set; }
public bool RememberMe { get; set; }
@@ -48,6 +50,12 @@ namespace Project.Web.Controllers
return "test";
}
[HttpGet]
public string TestLogin()
{
return "HomeController Login Test - 접근 성공!";
}
[HttpPost]
public HttpResponseMessage Login([FromBody] LoginRequest request)
{
@@ -56,16 +64,16 @@ namespace Project.Web.Controllers
try
{
// 입력값 검증
if (string.IsNullOrEmpty(request?.UserId) || string.IsNullOrEmpty(request?.Password))
if (string.IsNullOrEmpty(request?.Gcode) || string.IsNullOrEmpty(request?.UserId) || string.IsNullOrEmpty(request?.Password))
{
response.Success = false;
response.Message = "사용자 ID비밀번호를 입력해주세요.";
response.Message = "그룹코드/사용자ID/비밀번호를 입력해주세요.";
return CreateJsonResponse(response);
}
// TODO: 여기에 실제 데이터베이스 로그인 로직을 구현하세요
// 예시: 데이터베이스에서 사용자 정보 확인
bool isValidUser = ValidateUser(request.UserId, request.Password);
bool isValidUser = ValidateUser(request.Gcode, request.UserId, request.Password);
if (isValidUser)
{
@@ -75,11 +83,12 @@ namespace Project.Web.Controllers
response.RedirectUrl = "/DashBoard";
// 사용자 정보 설정 (세션 또는 쿠키)
SetUserSession(request.UserId, request.RememberMe);
SetUserSession(request.Gcode, request.UserId, request.RememberMe);
// 사용자 데이터 반환
response.UserData = new
{
Gcode = request.Gcode,
UserId = request.UserId,
LoginTime = DateTime.Now,
RememberMe = request.RememberMe
@@ -125,6 +134,10 @@ namespace Project.Web.Controllers
return CreateJsonResponse(response);
}
[HttpGet]
public HttpResponseMessage CheckLoginStatus()
{
@@ -159,42 +172,83 @@ namespace Project.Web.Controllers
}
// 헬퍼 메서드들
private bool ValidateUser(string userId, string password)
private bool ValidateUser(string gcode, string userId, string password)
{
// TODO: 실제 데이터베이스 검증 로직을 여기에 구현하세요
// 예시: 데이터베이스에서 사용자 정보 조회 및 비밀번호 검증
var encpass = Pub.MakePasswordEnc(password.Trim());
if(userId.ToLower()=="dev" && password == "123")
{
return true;
}
// 임시 테스트용 (실제로는 데이터베이스에서 확인)
return userId == "admin" && password == "admin";
var GInfo = DBM.GetUserGroup(gcode);
if (GInfo == null) return false;
var UGInfo = DBM.GetGroupUser(gcode, userId);
if (UGInfo == null) return false;
var UInfo = DBM.GetUserInfo(userId);
if (UInfo == null) return false;
return UInfo.password.Equals(encpass);
}
private void SetUserSession(string userId, bool rememberMe)
private void SetUserSession(string gcode, string userId, bool rememberMe)
{
// TODO: 세션 또는 쿠키에 사용자 정보 저장
// 예시: HttpContext.Session["UserId"] = userId;
// 예시: 쿠키 설정 (rememberMe가 true인 경우)
//데이터베이스에서 해당 정보를 찾아와서 처리해야한다
if(userId.ToLower().Equals("dev"))
{
var GInfo = DBM.GetUserGroup(gcode);
var UInfo = DBM.GetUserInfo(userId);
info.Login.no = "dev";
info.Login.nameK = "개발자";
info.Login.dept = GInfo.name;
info.Login.level = 9;
info.Login.email = UInfo.email;
info.Login.hp = UInfo.hp;
info.Login.tel = UInfo.tel;
info.Login.title = GInfo.name + "(" + UInfo.grade + ")";
info.NotShowJobReportview = Pub.setting.NotShowJobreportPRewView;
info.Login.gcode = gcode;// gcode;
info.Login.process = "개발자";
info.Login.permission =GInfo.perm;
info.Login.gpermission = GInfo.perm;
info.ShowBuyerror = Pub.setting.Showbuyerror; //210625
}
else
{
// TODO: 세션 또는 쿠키에 사용자 정보 저장
// 예시: HttpContext.Session["UserId"] = userId;
// 예시: 쿠키 설정 (rememberMe가 true인 경우)
//데이터베이스에서 해당 정보를 찾아와서 처리해야한다
var GInfo = DBM.GetUserGroup(gcode);
var UInfo = DBM.GetUserInfo(userId);
var UGInfo = DBM.GetGroupUser(gcode, userId);
info.Login.no = userId;
info.Login.nameK = UInfo.name;
info.Login.dept = GInfo.name;
info.Login.level = UGInfo.level;
info.Login.email = UInfo.email;
info.Login.hp = UInfo.hp;
info.Login.tel = UInfo.tel;
info.Login.title = GInfo.name + "(" + UInfo.grade + ")";
info.NotShowJobReportview = Pub.setting.NotShowJobreportPRewView;
info.Login.gcode = gcode;// gcode;
info.Login.process = UInfo.id == "dev" ? "개발자" : UGInfo.Process;
info.Login.permission = UGInfo.level;
info.Login.gpermission = GInfo.perm;
info.ShowBuyerror = Pub.setting.Showbuyerror; //210625
//로그인기록저장
Pub.setting.lastid = userId;// tbID.Text.Trim();
Pub.setting.lastdpt = GInfo.name;
Pub.setting.lastgcode = GInfo.gcode;
Pub.setting.Save();
}
FCOMMON.info.Login.no = userId;
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;
//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
}
@@ -214,7 +268,8 @@ namespace Project.Web.Controllers
{
// TODO: 현재 로그인된 사용자 정보 반환
// 예시: HttpContext.Session["UserId"]에서 사용자 정보 조회
return null; // 임시로 null 반환
if (string.IsNullOrEmpty(FCOMMON.info.Login.no)) return null;
else return FCOMMON.info.Login;
}
private HttpResponseMessage CreateJsonResponse(object data)
@@ -295,5 +350,35 @@ namespace Project.Web.Controllers
return resp;
}
[HttpGet]
public HttpResponseMessage GetPreviousLoginInfo()
{
try
{
// pub.setting에서 이전 로그인 정보 읽기
var previousLoginInfo = new
{
Gcode = Pub.setting.lastgcode ?? "",
UserId = Pub.setting.lastid ?? "",
Dept = Pub.setting.lastdpt ?? "",
RememberMe = false // 기본값으로 설정
};
return CreateJsonResponse(new
{
Success = true,
Data = previousLoginInfo
});
}
catch (Exception ex)
{
return CreateJsonResponse(new
{
Success = false,
Message = "이전 로그인 정보를 가져오는 중 오류가 발생했습니다: " + ex.Message
});
}
}
}
}

View File

@@ -288,93 +288,32 @@ namespace Project.Web.Controllers
[HttpGet]
public HttpResponseMessage Index()
{
//로그인이 되어있지않다면 로그인을 가져온다
MethodResult result;
result = View();
// 직접 파일을 읽어서 반환
var filePath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Web", "wwwroot", "Jobreport", "index.html");
var contents = string.Empty;
var gets = Request.GetQueryNameValuePairs();// GetParameters(data);
var key_search = gets.Where(t => t.Key == "search").FirstOrDefault();
var model = GetGlobalModel();
var getParams = Request.GetQueryNameValuePairs();// GetParameters(data);
//기본값을 찾아서 없애줘야한다
var searchkey = string.Empty;
if (key_search.Key != null && key_search.Value.isEmpty() == false) searchkey = key_search.Value.Trim();
var tbody = new System.Text.StringBuilder();
//테이블데이터생성
var itemcnt = 0;
//if (searchkey.isEmpty() == false)
if (System.IO.File.Exists(filePath))
{
var db = new dsMSSQLTableAdapters.vJobReportForUserTableAdapter();// EEEntitiesJobreport();
var sd = DateTime.Now.ToShortDateString();
var ed = DateTime.Now.ToShortDateString();
var rows = db.GetByDate(FCOMMON.info.Login.gcode, FCOMMON.info.Login.no, sd, ed);
//.vJobReportForUser.AsNoTracking().Where(t => t.gcode == FCOMMON.info.Login.gcode && t.id == FCOMMON.info.Login.no && t.pdate.CompareTo(sd) >= 0 && t.pdate.CompareTo(ed) <= 1).OrderByDescending(t => t.pdate);
itemcnt = rows.Count();
foreach (var item in rows)
{
tbody.AppendLine("<tr>");
tbody.AppendLine($"<th scope='row'>{item.pdate.Substring(5)}</th>");
tbody.AppendLine($"<td>{item.ww}</td>");
tbody.AppendLine($"<td>{item.name}</td>");
if (item.status == "진행 중" || item.status.EndsWith("%"))
tbody.AppendLine($"<td class='table-info text-center'>{item.status}</td>");
else
tbody.AppendLine($"<td class='text-center'>{item.status}</td>");
tbody.AppendLine($"<td>{item.type}</td>");
tbody.AppendLine($"<td><a href='/jobreport/edit/{item.idx}'>{item.projectName}</a></td>");
tbody.AppendLine($"<td>{item.hrs}</td>");
tbody.AppendLine($"<td>{item.ot}</td>");
tbody.AppendLine("<td><span class='d-inline-block text-truncate' style='max-width: 150px;'>");
tbody.AppendLine(item.description);
tbody.AppendLine("</span></td>");
tbody.AppendLine("</tr>");
}
contents = System.IO.File.ReadAllText(filePath, System.Text.Encoding.UTF8);
}
//아잍쳄이 없는경우
if (itemcnt == 0)
else
{
tbody.AppendLine("<tr>");
tbody.AppendLine("<th scope='row'>1</th>");
tbody.AppendLine("<td colspan='6'>자료가 없습니다</td>");
tbody.AppendLine("</tr>");
// 파일이 없으면 404 에러 페이지 또는 기본 메시지
contents = "<html><body><h1>404 - File Not Found</h1><p>The requested file was not found: " + filePath + "</p></body></html>";
}
var contents = result.Content.Replace("{search}", searchkey);
contents = contents.Replace("{tabledata}", tbody.ToString());
contents = contents.Replace("{cnt}", itemcnt.ToString());
//공용값 적용
ApplyCommonValue(ref contents);
//최종문자 적용
result.Content = contents;
var resp = new HttpResponseMessage()
{
Content = new StringContent(
result.Content,
contents,
System.Text.Encoding.UTF8,
"text/html")
};
return resp;
}
}
}

View File

@@ -6,16 +6,7 @@ using System.Threading.Tasks;
namespace Project.Web.Model
{
public class GroupUserModel
{
public string Gcode { get; set; }
public string uid { get; set; }
}
public class UserModel
{
public string uid { get; set; }
public string password { get; set; }
}
public class PageModel
{
public List<KeyValuePair<string, object>> RouteData { get; set; }

View File

@@ -24,7 +24,7 @@ namespace Project.OWIN
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
routeTemplate: "{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);

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,13 +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-4 gap-6 mb-8">
<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>
@@ -137,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>
@@ -151,12 +185,12 @@
</div>
</div>
<!-- 구매요청 카드 -->
<div class="glass-effect rounded-2xl p-6 card-hover animate-slide-up">
<!-- 구매요청 카드(NR) -->
<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">구매요청</p>
<p class="text-3xl font-bold text-white" id="purchaseCount">0</p>
<p class="text-white/70 text-sm font-medium">구매요청(NR)</p>
<p class="text-3xl font-bold text-white" id="purchaseCountNR">0</p>
</div>
<div class="w-12 h-12 bg-danger-500/20 rounded-full flex items-center justify-center">
<svg class="w-6 h-6 text-danger-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@@ -165,6 +199,23 @@
</div>
</div>
</div>
<!-- 구매요청 카드(CR) -->
<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>
<p class="text-3xl font-bold text-white" id="purchaseCountCR">0</p>
</div>
<div class="w-12 h-12 bg-danger-500/20 rounded-full flex items-center justify-center">
<svg class="w-6 h-6 text-danger-400" 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>
</div>
</div>
</div>
</div>
<!-- 휴가자 현황 테이블 -->
@@ -202,13 +253,214 @@
데이터 업데이트 중...
</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>
// 휴가 인원 Ajax 업데이트
function updateLeaveCount() {
showLoading();
fetch('http://127.0.0.1:9000/Dashboard/TodayCountH')
fetch('http://127.0.0.1:7979/Dashboard/TodayCountH')
.then(response => response.text())
.then(data => {
const cleanData = data.replace(/"/g, '');
@@ -225,7 +477,7 @@
// 휴가자 목록 Ajax 업데이트
function updateHolidayList() {
showLoading();
fetch('http://127.0.0.1:9000/Dashboard/GetholyUser')
fetch('http://127.0.0.1:7979/Dashboard/GetholyUser')
.then(response => response.json())
.then(data => {
let tableRows = '';
@@ -233,7 +485,7 @@
data.forEach(item => {
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 || '-'}(${item.uid})</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-warning-500/20 text-warning-300">
${item.cate || '-'}
@@ -270,6 +522,71 @@
});
}
// 구매요청 데이터 Ajax 업데이트
function updatePurchaseCount() {
showLoading();
fetch('http://127.0.0.1:7979/DashBoard/GetPurchaseWaitCount')
.then(response => response.json())
.then(data => {
if (data) {
// NR 구매요청 카운트 업데이트
if (data.NR !== undefined) {
animateNumberChange('purchaseCountNR', data.NR);
}
// CR 구매요청 카운트 업데이트
if (data.CR !== undefined) {
animateNumberChange('purchaseCountCR', data.CR);
}
}
hideLoading();
})
.catch(error => {
console.error('구매요청 데이터 업데이트 중 오류 발생:', error);
hideLoading();
});
}
// 휴가요청 데이터 Ajax 업데이트
function updateHolydayRequestCount() {
showLoading();
fetch('http://127.0.0.1:7979/DashBoard/GetHolydayRequestCount')
.then(response => response.json())
.then(data => {
if (data) {
// NR 구매요청 카운트 업데이트
if (data.HOLY !== undefined) {
animateNumberChange('leaveRequestCount', data.HOLY);
}
}
hideLoading();
})
.catch(error => {
console.error('휴가요청 데이터 업데이트 중 오류 발생:', error);
hideLoading();
});
}
// 사용자카운트 데이터 Ajax 업데이트
function updateCurrentUserCount() {
showLoading();
fetch('http://127.0.0.1:7979/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) {
const element = document.getElementById(elementId);
@@ -300,12 +617,353 @@
// 페이지 로드 시 데이터 업데이트
updateLeaveCount();
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:7979/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:7979/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:7979/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:7979/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

@@ -0,0 +1,863 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
<title>업무일지</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://unpkg.com/feather-icons"></script>
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: '#3B82F6',
secondary: '#6B7280',
success: '#10B981',
danger: '#EF4444',
warning: '#F59E0B'
}
}
}
}
</script>
</head>
<body class="bg-gray-50 min-h-screen">
<!-- 헤더 -->
<header class="bg-white shadow-sm border-b">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex justify-between items-center py-4">
<div class="flex items-center">
<i data-feather="file-text" class="w-8 h-8 text-primary mr-3"></i>
<h1 class="text-2xl font-bold text-gray-900">업무일지</h1>
</div>
<div class="flex items-center space-x-4">
<button id="refreshBtn" class="bg-primary hover:bg-blue-700 text-white px-4 py-2 rounded-lg flex items-center">
<i data-feather="refresh-cw" class="w-4 h-4 mr-2"></i>
새로고침
</button>
<div class="text-sm text-gray-600">
<span id="currentDate"></span>
</div>
</div>
</div>
</div>
</header>
<!-- 메인 컨텐츠 -->
<main class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<!-- 통계 카드 -->
<div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8">
<div class="bg-white rounded-lg shadow p-6">
<div class="flex items-center">
<div class="p-2 bg-blue-100 rounded-lg">
<i data-feather="calendar" class="w-6 h-6 text-primary"></i>
</div>
<div class="ml-4">
<p class="text-sm font-medium text-gray-600">총 업무일수</p>
<p id="totalDays" class="text-2xl font-bold text-gray-900">0</p>
</div>
</div>
</div>
<div class="bg-white rounded-lg shadow p-6">
<div class="flex items-center">
<div class="p-2 bg-green-100 rounded-lg">
<i data-feather="clock" class="w-6 h-6 text-success"></i>
</div>
<div class="ml-4">
<p class="text-sm font-medium text-gray-600">총 근무시간</p>
<p id="totalHours" class="text-2xl font-bold text-gray-900">0h</p>
</div>
</div>
</div>
<div class="bg-white rounded-lg shadow p-6">
<div class="flex items-center">
<div class="p-2 bg-orange-100 rounded-lg">
<i data-feather="zap" class="w-6 h-6 text-warning"></i>
</div>
<div class="ml-4">
<p class="text-sm font-medium text-gray-600">총 초과근무</p>
<p id="totalOT" class="text-2xl font-bold text-gray-900">0h</p>
</div>
</div>
</div>
<div class="bg-white rounded-lg shadow p-6">
<div class="flex items-center">
<div class="p-2 bg-purple-100 rounded-lg">
<i data-feather="folder" class="w-6 h-6 text-purple-600"></i>
</div>
<div class="ml-4">
<p class="text-sm font-medium text-gray-600">진행중 프로젝트</p>
<p id="activeProjects" class="text-2xl font-bold text-gray-900">0</p>
</div>
</div>
</div>
</div>
<!-- 필터 및 검색 -->
<div class="bg-white rounded-lg shadow mb-6">
<div class="p-6 border-b border-gray-200">
<div class="flex flex-col md:flex-row md:items-center md:justify-between space-y-4 md:space-y-0">
<div class="flex flex-col sm:flex-row space-y-2 sm:space-y-0 sm:space-x-4">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">조회기간</label>
<div class="flex space-x-2">
<input type="date" id="startDate" class="border border-gray-300 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent text-sm">
<span class="flex items-center text-gray-500">~</span>
<input type="date" id="endDate" class="border border-gray-300 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent text-sm">
</div>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">상태</label>
<select id="statusFilter" class="border border-gray-300 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent">
<option value="">전체</option>
<option value="진행중">진행중</option>
<option value="완료">완료</option>
<option value="대기">대기</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">프로젝트</label>
<select id="projectFilter" class="border border-gray-300 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent">
<option value="">전체</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">검색</label>
<input type="text" id="searchInput" placeholder="업무 내용 검색..." class="border border-gray-300 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent">
</div>
</div>
<div class="flex space-x-2">
<button id="clearFilterBtn" class="bg-gray-500 hover:bg-gray-600 text-white px-4 py-2 rounded-md flex items-center">
<i data-feather="x" class="w-4 h-4 mr-2"></i>
필터 초기화
</button>
<button id="exportBtn" class="bg-green-600 hover:bg-green-700 text-white px-4 py-2 rounded-md flex items-center">
<i data-feather="download" class="w-4 h-4 mr-2"></i>
엑셀 다운로드
</button>
</div>
</div>
</div>
</div>
<!-- 데이터 테이블 -->
<div class="bg-white rounded-lg shadow overflow-hidden">
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<tr>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider cursor-pointer hover:bg-gray-100" data-sort="pdate">
날짜 <i data-feather="chevron-down" class="w-4 h-4 inline ml-1"></i>
</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider cursor-pointer hover:bg-gray-100" data-sort="status">
상태 <i data-feather="chevron-down" class="w-4 h-4 inline ml-1"></i>
</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider cursor-pointer hover:bg-gray-100" data-sort="projectName">
프로젝트명 <i data-feather="chevron-down" class="w-4 h-4 inline ml-1"></i>
</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider cursor-pointer hover:bg-gray-100" data-sort="requestpart">
요청부서 <i data-feather="chevron-down" class="w-4 h-4 inline ml-1"></i>
</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider cursor-pointer hover:bg-gray-100" data-sort="package">
패키지 <i data-feather="chevron-down" class="w-4 h-4 inline ml-1"></i>
</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider cursor-pointer hover:bg-gray-100" data-sort="type">
타입 <i data-feather="chevron-down" class="w-4 h-4 inline ml-1"></i>
</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider cursor-pointer hover:bg-gray-100" data-sort="process">
프로세스 <i data-feather="chevron-down" class="w-4 h-4 inline ml-1"></i>
</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">업무내용</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider cursor-pointer hover:bg-gray-100" data-sort="hrs">
근무시간 <i data-feather="chevron-down" class="w-4 h-4 inline ml-1"></i>
</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider cursor-pointer hover:bg-gray-100" data-sort="ot">
초과근무 <i data-feather="chevron-down" class="w-4 h-4 inline ml-1"></i>
</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">초과근무 시간</th>
</tr>
</thead>
<tbody id="jobTableBody" class="bg-white divide-y divide-gray-200">
<!-- 데이터가 여기에 동적으로 로드됩니다 -->
</tbody>
</table>
</div>
<!-- 로딩 상태 -->
<div id="loadingState" class="hidden p-8 text-center">
<div class="inline-flex items-center">
<svg class="animate-spin -ml-1 mr-3 h-5 w-5 text-primary" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
<span class="text-gray-600">데이터를 불러오는 중...</span>
</div>
</div>
<!-- 빈 상태 -->
<div id="emptyState" class="hidden p-8 text-center">
<i data-feather="inbox" class="w-12 h-12 text-gray-400 mx-auto mb-4"></i>
<p class="text-gray-500">업무일지 데이터가 없습니다.</p>
</div>
</div>
<!-- 페이지네이션 -->
<div id="pagination" class="mt-6 flex items-center justify-between">
<div class="flex items-center space-x-2">
<span class="text-sm text-gray-700">페이지당 행 수:</span>
<select id="pageSize" class="border border-gray-300 rounded-md px-2 py-1 text-sm">
<option value="10">10</option>
<option value="25" selected>25</option>
<option value="50">50</option>
<option value="100">100</option>
</select>
</div>
<div class="flex items-center space-x-2">
<button id="prevPage" class="px-3 py-1 border border-gray-300 rounded-md text-sm disabled:opacity-50 disabled:cursor-not-allowed">
이전
</button>
<span id="pageInfo" class="text-sm text-gray-700">1 / 1</span>
<button id="nextPage" class="px-3 py-1 border border-gray-300 rounded-md text-sm disabled:opacity-50 disabled:cursor-not-allowed">
다음
</button>
</div>
</div>
</main>
<!-- 상세 모달 -->
<div id="detailModal" class="fixed inset-0 bg-gray-600 bg-opacity-50 overflow-y-auto h-full w-full hidden z-50">
<div class="relative top-20 mx-auto p-5 border w-11/12 md:w-3/4 lg:w-1/2 shadow-lg rounded-md bg-white">
<div class="mt-3">
<div class="flex items-center justify-between mb-4">
<h3 class="text-lg font-medium text-gray-900">업무 상세정보</h3>
<button id="closeModal" class="text-gray-400 hover:text-gray-600">
<i data-feather="x" class="w-6 h-6"></i>
</button>
</div>
<div id="modalContent" class="space-y-4">
<!-- 모달 내용이 여기에 동적으로 로드됩니다 -->
</div>
</div>
</div>
</div>
<script>
// 전역 변수
let jobData = [];
let filteredData = [];
let currentPage = 1;
let pageSize = 25;
let sortColumn = 'pdate';
let sortDirection = 'desc';
// 초기화
document.addEventListener('DOMContentLoaded', function() {
initializeApp();
loadJobData();
});
function initializeApp() {
// 현재 날짜 표시
const now = new Date();
document.getElementById('currentDate').textContent = now.toLocaleDateString('ko-KR', {
year: 'numeric',
month: 'long',
day: 'numeric',
weekday: 'long'
});
// 조회기간 기본값 설정 (이번 달)
const currentMonth = new Date(now.getFullYear(), now.getMonth(), 1);
const lastDayOfMonth = new Date(now.getFullYear(), now.getMonth() + 1, 0);
document.getElementById('startDate').value = currentMonth.toISOString().split('T')[0];
document.getElementById('endDate').value = lastDayOfMonth.toISOString().split('T')[0];
// 이벤트 리스너 등록
document.getElementById('refreshBtn').addEventListener('click', loadJobData);
document.getElementById('startDate').addEventListener('change', loadJobData);
document.getElementById('endDate').addEventListener('change', loadJobData);
document.getElementById('statusFilter').addEventListener('change', filterData);
document.getElementById('projectFilter').addEventListener('change', filterData);
document.getElementById('searchInput').addEventListener('input', filterData);
document.getElementById('clearFilterBtn').addEventListener('click', clearFilters);
document.getElementById('pageSize').addEventListener('change', function() {
pageSize = parseInt(this.value);
currentPage = 1;
renderTable();
});
document.getElementById('prevPage').addEventListener('click', function() {
if (currentPage > 1) {
currentPage--;
renderTable();
}
});
document.getElementById('nextPage').addEventListener('click', function() {
const maxPage = Math.ceil(filteredData.length / pageSize);
if (currentPage < maxPage) {
currentPage++;
renderTable();
}
});
document.getElementById('exportBtn').addEventListener('click', exportToExcel);
document.getElementById('closeModal').addEventListener('click', closeModal);
// 정렬 이벤트 리스너
document.querySelectorAll('[data-sort]').forEach(th => {
th.addEventListener('click', function() {
const column = this.getAttribute('data-sort');
if (sortColumn === column) {
sortDirection = sortDirection === 'asc' ? 'desc' : 'asc';
} else {
sortColumn = column;
sortDirection = 'asc';
}
sortData();
renderTable();
});
});
// 모달 외부 클릭 시 닫기
document.getElementById('detailModal').addEventListener('click', function(e) {
if (e.target === this) {
closeModal();
}
});
// Feather 아이콘 초기화
feather.replace();
}
async function loadJobData() {
showLoading(true);
try {
// 조회기간 파라미터 가져오기
const startDate = document.getElementById('startDate').value;
const endDate = document.getElementById('endDate').value;
// API URL 구성
let url = '/DashBoard/GetJobData';
const params = new URLSearchParams();
if (startDate) params.append('startDate', startDate);
if (endDate) params.append('endDate', endDate);
if (params.toString()) {
url += '?' + params.toString();
}
const response = await fetch(url);
if (!response.ok) {
throw new Error('데이터를 불러오는데 실패했습니다.');
}
jobData = await response.json();
filteredData = [...jobData];
updateStatistics();
updateProjectFilter();
sortData();
renderTable();
// 확장된 행들 닫기
closeAllExpandedRows();
} catch (error) {
console.error('Error loading job data:', error);
showError('데이터를 불러오는데 실패했습니다: ' + error.message);
} finally {
showLoading(false);
}
}
function updateStatistics() {
const totalDays = new Set(jobData.map(item => item.pdate)).size;
const totalHours = jobData.reduce((sum, item) => sum + (parseFloat(item.hrs) || 0), 0);
const totalOT = jobData.reduce((sum, item) => sum + (parseFloat(item.ot) || 0), 0);
const activeProjects = new Set(jobData.filter(item => item.status === '진행중').map(item => item.projectName)).size;
document.getElementById('totalDays').textContent = totalDays;
document.getElementById('totalHours').textContent = totalHours.toFixed(1) + 'h';
document.getElementById('totalOT').textContent = totalOT.toFixed(1) + 'h';
document.getElementById('activeProjects').textContent = activeProjects;
}
function updateProjectFilter() {
const projectSelect = document.getElementById('projectFilter');
const projects = [...new Set(jobData.map(item => item.projectName).filter(Boolean))];
// 기존 옵션 제거 (전체 옵션 제외)
while (projectSelect.children.length > 1) {
projectSelect.removeChild(projectSelect.lastChild);
}
// 새 옵션 추가
projects.forEach(project => {
const option = document.createElement('option');
option.value = project;
option.textContent = project;
projectSelect.appendChild(option);
});
}
function filterData() {
const statusFilter = document.getElementById('statusFilter').value;
const projectFilter = document.getElementById('projectFilter').value;
const searchTerm = document.getElementById('searchInput').value.toLowerCase();
filteredData = jobData.filter(item => {
const statusMatch = !statusFilter || item.status === statusFilter;
const projectMatch = !projectFilter || item.projectName === projectFilter;
const searchMatch = !searchTerm ||
(item.description && item.description.toLowerCase().includes(searchTerm)) ||
(item.projectName && item.projectName.toLowerCase().includes(searchTerm)) ||
(item.requestpart && item.requestpart.toLowerCase().includes(searchTerm));
return statusMatch && projectMatch && searchMatch;
});
currentPage = 1;
sortData();
renderTable();
}
function sortData() {
filteredData.sort((a, b) => {
let aVal = a[sortColumn];
let bVal = b[sortColumn];
// 날짜 정렬
if (sortColumn === 'pdate') {
aVal = new Date(aVal);
bVal = new Date(bVal);
}
// 숫자 정렬
else if (['hrs', 'ot'].includes(sortColumn)) {
aVal = parseFloat(aVal) || 0;
bVal = parseFloat(bVal) || 0;
}
// 문자열 정렬
else {
aVal = (aVal || '').toString().toLowerCase();
bVal = (bVal || '').toString().toLowerCase();
}
if (aVal < bVal) return sortDirection === 'asc' ? -1 : 1;
if (aVal > bVal) return sortDirection === 'asc' ? 1 : -1;
return 0;
});
}
function renderTable() {
const tbody = document.getElementById('jobTableBody');
const startIndex = (currentPage - 1) * pageSize;
const endIndex = startIndex + pageSize;
const pageData = filteredData.slice(startIndex, endIndex);
if (pageData.length === 0) {
showEmptyState();
return;
}
hideEmptyState();
tbody.innerHTML = '';
pageData.forEach((item, index) => {
const row = document.createElement('tr');
row.className = 'hover:bg-gray-50 cursor-pointer';
row.setAttribute('data-item-id', item.idx || index);
row.addEventListener('click', () => toggleRowDetail(item, row));
const statusColor = getStatusColor(item.status);
const otTime = item.otStart && item.otEnd ?
`${item.otStart} ~ ${item.otEnd}` : '-';
row.innerHTML = `
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
<div class="flex items-center">
<i data-feather="chevron-right" class="w-4 h-4 mr-2 text-gray-400 expand-icon"></i>
${formatDate(item.pdate)}
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<span class="inline-flex px-2 py-1 text-xs font-semibold rounded-full ${statusColor}">
${item.status || '-'}
</span>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
${item.projectName || '-'}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
${item.requestpart || '-'}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
${item.package || '-'}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
${item.type || '-'}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
${item.process || '-'}
</td>
<td class="px-6 py-4 text-sm text-gray-900">
<div class="max-w-xs truncate cursor-pointer hover:text-primary hover:underline"
title="${item.description || ''}"
onclick="event.stopPropagation(); showDetailModal(${JSON.stringify(item).replace(/"/g, '&quot;')})">
${item.description || '-'}
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
${item.hrs ? parseFloat(item.hrs).toFixed(1) + 'h' : '-'}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
${item.ot ? parseFloat(item.ot).toFixed(1) + 'h' : '-'}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
${otTime}
</td>
`;
tbody.appendChild(row);
// 확장 행 추가 (숨겨진 상태)
const expandRow = document.createElement('tr');
expandRow.className = 'hidden expand-row';
expandRow.setAttribute('data-parent-id', item.idx || index);
expandRow.innerHTML = `
<td colspan="11" class="px-6 py-4 bg-gray-50 border-t border-gray-200">
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">업무내용</label>
<div class="bg-white rounded-lg p-4 cursor-pointer hover:bg-gray-100 transition-colors border"
onclick="showDetailModal(${JSON.stringify(item).replace(/"/g, '&quot;')})">
<p class="text-sm text-gray-900 whitespace-pre-wrap">${item.description || '-'}</p>
<div class="mt-2 text-xs text-gray-500 flex items-center">
<i data-feather="maximize-2" class="w-4 h-4 mr-1"></i>
클릭하여 전체 내용 보기
</div>
</div>
</div>
</td>
`;
tbody.appendChild(expandRow);
});
updatePagination();
feather.replace();
}
function getStatusColor(status) {
switch (status) {
case '진행 중': return 'bg-blue-100 text-blue-800';
case '진행 완료': return 'bg-green-100 text-green-800';
case '대기': return 'bg-yellow-100 text-yellow-800';
default: return 'bg-gray-100 text-gray-800';
}
}
function formatDate(dateString) {
if (!dateString) return '-';
const date = new Date(dateString);
return date.toLocaleDateString('ko-KR');
}
function updatePagination() {
const maxPage = Math.ceil(filteredData.length / pageSize);
const startItem = (currentPage - 1) * pageSize + 1;
const endItem = Math.min(currentPage * pageSize, filteredData.length);
document.getElementById('pageInfo').textContent = `${currentPage} / ${maxPage}`;
document.getElementById('prevPage').disabled = currentPage <= 1;
document.getElementById('nextPage').disabled = currentPage >= maxPage;
}
function showDetailModal(item) {
// 문자열로 전달된 경우 JSON 파싱
if (typeof item === 'string') {
try {
item = JSON.parse(item);
} catch (e) {
console.error('Error parsing item:', e);
return;
}
}
const modal = document.getElementById('detailModal');
const content = document.getElementById('modalContent');
content.innerHTML = `
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label class="block text-sm font-medium text-gray-700">날짜</label>
<p class="mt-1 text-sm text-gray-900">${formatDate(item.pdate)}</p>
</div>
<div>
<label class="block text-sm font-medium text-gray-700">상태</label>
<p class="mt-1">
<span class="inline-flex px-2 py-1 text-xs font-semibold rounded-full ${getStatusColor(item.status)}">
${item.status || '-'}
</span>
</p>
</div>
<div>
<label class="block text-sm font-medium text-gray-700">프로젝트명</label>
<p class="mt-1 text-sm text-gray-900">${item.projectName || '-'}</p>
</div>
<div>
<label class="block text-sm font-medium text-gray-700">요청부서</label>
<p class="mt-1 text-sm text-gray-900">${item.requestpart || '-'}</p>
</div>
<div>
<label class="block text-sm font-medium text-gray-700">패키지</label>
<p class="mt-1 text-sm text-gray-900">${item.package || '-'}</p>
</div>
<div>
<label class="block text-sm font-medium text-gray-700">타입</label>
<p class="mt-1 text-sm text-gray-900">${item.type || '-'}</p>
</div>
<div>
<label class="block text-sm font-medium text-gray-700">프로세스</label>
<p class="mt-1 text-sm text-gray-900">${item.process || '-'}</p>
</div>
<div>
<label class="block text-sm font-medium text-gray-700">근무시간</label>
<p class="mt-1 text-sm text-gray-900">${item.hrs ? parseFloat(item.hrs).toFixed(1) + 'h' : '-'}</p>
</div>
<div>
<label class="block text-sm font-medium text-gray-700">초과근무</label>
<p class="mt-1 text-sm text-gray-900">${item.ot ? parseFloat(item.ot).toFixed(1) + 'h' : '-'}</p>
</div>
<div>
<label class="block text-sm font-medium text-gray-700">초과근무 시간</label>
<p class="mt-1 text-sm text-gray-900">${item.otStart && item.otEnd ? `${item.otStart} ~ ${item.otEnd}` : '-'}</p>
</div>
</div>
<div class="mt-4">
<label class="block text-sm font-medium text-gray-700">업무내용</label>
<p class="mt-1 text-sm text-gray-900 whitespace-pre-wrap">${item.description || '-'}</p>
</div>
`;
modal.classList.remove('hidden');
feather.replace();
}
function closeModal() {
document.getElementById('detailModal').classList.add('hidden');
}
function showSelectedJobDetail(item) {
const detailContainer = document.getElementById('selectedJobDetail');
const contentContainer = document.getElementById('selectedJobContent');
// 기존 선택된 행의 스타일 제거
document.querySelectorAll('#jobTableBody tr').forEach(row => {
row.classList.remove('bg-blue-50', 'border-l-4', 'border-blue-500');
});
// 현재 행에 선택 스타일 적용
const currentRow = event.target.closest('tr');
if (currentRow) {
currentRow.classList.add('bg-blue-50', 'border-l-4', 'border-blue-500');
}
contentContainer.innerHTML = `
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
<div>
<label class="block text-sm font-medium text-gray-700">날짜</label>
<p class="mt-1 text-sm text-gray-900">${formatDate(item.pdate)}</p>
</div>
<div>
<label class="block text-sm font-medium text-gray-700">상태</label>
<p class="mt-1">
<span class="inline-flex px-2 py-1 text-xs font-semibold rounded-full ${getStatusColor(item.status)}">
${item.status || '-'}
</span>
</p>
</div>
<div>
<label class="block text-sm font-medium text-gray-700">프로젝트명</label>
<p class="mt-1 text-sm text-gray-900">${item.projectName || '-'}</p>
</div>
<div>
<label class="block text-sm font-medium text-gray-700">요청부서</label>
<p class="mt-1 text-sm text-gray-900">${item.requestpart || '-'}</p>
</div>
<div>
<label class="block text-sm font-medium text-gray-700">패키지</label>
<p class="mt-1 text-sm text-gray-900">${item.package || '-'}</p>
</div>
<div>
<label class="block text-sm font-medium text-gray-700">타입</label>
<p class="mt-1 text-sm text-gray-900">${item.type || '-'}</p>
</div>
<div>
<label class="block text-sm font-medium text-gray-700">프로세스</label>
<p class="mt-1 text-sm text-gray-900">${item.process || '-'}</p>
</div>
<div>
<label class="block text-sm font-medium text-gray-700">근무시간</label>
<p class="mt-1 text-sm text-gray-900">${item.hrs ? parseFloat(item.hrs).toFixed(1) + 'h' : '-'}</p>
</div>
<div>
<label class="block text-sm font-medium text-gray-700">초과근무</label>
<p class="mt-1 text-sm text-gray-900">${item.ot ? parseFloat(item.ot).toFixed(1) + 'h' : '-'}</p>
</div>
<div>
<label class="block text-sm font-medium text-gray-700">초과근무 시간</label>
<p class="mt-1 text-sm text-gray-900">${item.otStart && item.otEnd ? `${item.otStart} ~ ${item.otEnd}` : '-'}</p>
</div>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">업무내용</label>
<div class="bg-gray-50 rounded-lg p-4 cursor-pointer hover:bg-gray-100 transition-colors"
onclick="showDetailModal(${JSON.stringify(item).replace(/"/g, '&quot;')})">
<p class="text-sm text-gray-900 whitespace-pre-wrap">${item.description || '-'}</p>
<div class="mt-2 text-xs text-gray-500 flex items-center">
<i data-feather="maximize-2" class="w-4 h-4 mr-1"></i>
클릭하여 전체 내용 보기
</div>
</div>
</div>
`;
detailContainer.classList.remove('hidden');
feather.replace();
// 부드러운 스크롤로 상세 내용으로 이동
detailContainer.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}
function toggleRowDetail(item, row) {
const itemId = item.idx || row.getAttribute('data-item-id');
const expandRow = document.querySelector(`tr[data-parent-id="${itemId}"]`);
const expandIcon = row.querySelector('.expand-icon');
if (expandRow.classList.contains('hidden')) {
// 확장
expandRow.classList.remove('hidden');
expandIcon.setAttribute('data-feather', 'chevron-down');
row.classList.add('bg-blue-50');
} else {
// 축소
expandRow.classList.add('hidden');
expandIcon.setAttribute('data-feather', 'chevron-right');
row.classList.remove('bg-blue-50');
}
// 아이콘 업데이트
feather.replace();
}
function closeAllExpandedRows() {
document.querySelectorAll('.expand-row').forEach(row => {
row.classList.add('hidden');
});
document.querySelectorAll('#jobTableBody tr').forEach(row => {
if (!row.classList.contains('expand-row')) {
row.classList.remove('bg-blue-50');
const icon = row.querySelector('.expand-icon');
if (icon) {
icon.setAttribute('data-feather', 'chevron-right');
}
}
});
feather.replace();
}
function showLoading(show) {
const loadingState = document.getElementById('loadingState');
const tableBody = document.getElementById('jobTableBody');
if (show) {
loadingState.classList.remove('hidden');
tableBody.style.display = 'none';
} else {
loadingState.classList.add('hidden');
tableBody.style.display = 'table-row-group';
}
}
function showEmptyState() {
document.getElementById('emptyState').classList.remove('hidden');
document.getElementById('jobTableBody').style.display = 'none';
}
function hideEmptyState() {
document.getElementById('emptyState').classList.add('hidden');
document.getElementById('jobTableBody').style.display = 'table-row-group';
}
function showError(message) {
// 간단한 에러 알림 (실제 구현에서는 더 나은 알림 시스템 사용)
alert(message);
}
function clearFilters() {
// 조회기간을 이번 달로 초기화
const now = new Date();
const currentMonth = new Date(now.getFullYear(), now.getMonth(), 1);
const lastDayOfMonth = new Date(now.getFullYear(), now.getMonth() + 1, 0);
document.getElementById('startDate').value = currentMonth.toISOString().split('T')[0];
document.getElementById('endDate').value = lastDayOfMonth.toISOString().split('T')[0];
// 다른 필터들 초기화
document.getElementById('statusFilter').value = '';
document.getElementById('projectFilter').value = '';
document.getElementById('searchInput').value = '';
// 서버에서 새로운 데이터 가져오기
loadJobData();
// 확장된 행들 닫기
closeAllExpandedRows();
}
function exportToExcel() {
if (filteredData.length === 0) {
alert('내보낼 데이터가 없습니다.');
return;
}
// 조회기간 정보 가져오기
const startDate = document.getElementById('startDate').value;
const endDate = document.getElementById('endDate').value;
const periodText = startDate && endDate ? `_${startDate}_${endDate}` : '';
// CSV 형식으로 데이터 변환
const headers = ['날짜', '상태', '프로젝트명', '요청부서', '패키지', '타입', '프로세스', '업무내용', '근무시간', '초과근무', '초과근무시작', '초과근무종료'];
const csvContent = [
headers.join(','),
...filteredData.map(item => [
formatDate(item.pdate),
item.status || '',
item.projectName || '',
item.requestpart || '',
item.package || '',
item.type || '',
item.process || '',
`"${(item.description || '').replace(/"/g, '""')}"`,
item.hrs || '',
item.ot || '',
item.otStart || '',
item.otEnd || ''
].join(','))
].join('\n');
// 파일 다운로드
const blob = new Blob(['\ufeff' + csvContent], { type: 'text/csv;charset=utf-8;' });
const link = document.createElement('a');
const url = URL.createObjectURL(blob);
link.setAttribute('href', url);
link.setAttribute('download', `업무일지${periodText}_${new Date().toISOString().split('T')[0]}.csv`);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
</script>
</body>
</html>

View File

@@ -1,114 +0,0 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>근태현황 대시보드</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container py-5">
<div class="row mb-4">
<div class="col-md-3">
<div class="card text-center">
<div class="card-body">
<h5 class="card-title">출근</h5>
<p class="card-text fs-2" id="presentCount">0</p>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-center">
<div class="card-body">
<h5 class="card-title">휴가</h5>
<p class="card-text fs-2" id="leaveCount">0</p>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-center">
<div class="card-body">
<h5 class="card-title">휴가요청</h5>
<p class="card-text fs-2" id="leaveCount">0</p>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card text-center">
<div class="card-body">
<h5 class="card-title">구매요청</h5>
<p class="card-text fs-2" id="leaveCount">0</p>
</div>
</div>
</div>
</div>
<div class="card">
<div class="card-header">
휴가자 현황
</div>
<div class="card-body p-0">
<table class="table mb-0">
<thead class="table-light">
<tr>
<th>이름</th>
<th>출근 시간</th>
<th>퇴근 시간</th>
<th>상태</th>
</tr>
</thead>
<tbody id="attendanceTable">
<!-- 데이터가 여기에 표시됩니다 -->
</tbody>
</table>
</div>
</div>
</div>
<script>
// 샘플 데이터
const attendanceData = [
{ name: '홍길동', checkIn: '09:01', checkOut: '18:00', status: '지각' },
{ name: '김철수', checkIn: '08:55', checkOut: '18:05', status: '정상' },
{ name: '이영희', checkIn: '-', checkOut: '-', status: '결근' },
{ name: '박민수', checkIn: '09:00', checkOut: '18:10', status: '정상' },
{ name: '최지우', checkIn: '09:20', checkOut: '18:00', status: '지각' }
];
function updateDashboard(data) {
let present = 0, leave = 0, late = 0, absent = 0;
let tableRows = '';
data.forEach(item => {
if (item.status === '정상' || item.status === '지각') present++;
if (item.checkOut !== '-') leave++;
if (item.status === '지각') late++;
if (item.status === '결근') absent++;
tableRows += `<tr>
<td>${item.name}</td>
<td>${item.checkIn}</td>
<td>${item.checkOut}</td>
<td>${item.status}</td>
</tr>`;
});
}
// 페이지 로드 시 대시보드 업데이트
updateDashboard(attendanceData);
// 휴가 인원 Ajax 업데이트
function updateLeaveCount() {
fetch('http://127.0.0.1:9000/Dashboard/TodayCountH')
.then(response => response.text())
.then(data => {
// 수신된 데이터가 "1" 형태로 반환되므로, 쌍따옴표를 제거하고 숫자로 변환
const cleanData = data.replace(/"/g, '');
document.getElementById('leaveCount').textContent = parseInt(cleanData, 10);
})
.catch(error => console.error('휴가 인원 업데이트 중 오류 발생:', error));
}
// 페이지 로드 시 휴가 인원 업데이트
updateLeaveCount();
</script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

View File

@@ -116,6 +116,17 @@
transform: translateY(-1.5rem) scale(0.85);
color: #3b82f6;
}
/* 드롭다운 스타일 */
select.input-field option {
background-color: #1f2937;
color: white;
}
select.input-field:focus option:checked {
background-color: #3b82f6;
}
select.input-field option:hover {
background-color: #374151;
}
</style>
</head>
<body class="gradient-bg min-h-screen flex items-center justify-center p-4">
@@ -133,21 +144,35 @@
<p class="text-white/70 text-sm">로그인하여 시스템에 접속하세요</p>
</div>
<!-- 로그인 폼 -->
<!-- 로그인 폼 -->
<form id="loginForm" class="space-y-6 animate-slide-up">
<!-- Gcode 드롭다운 -->
<div class="relative">
<select
id="gcode"
name="gcode"
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-white/60">부서를 선택하세요</option>
</select>
<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>
</svg>
</div>
</div>
<!-- 사용자 ID 입력 -->
<div class="relative">
<input
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>
@@ -161,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>
@@ -244,25 +266,27 @@
document.getElementById('loginForm').addEventListener('submit', function(e) {
e.preventDefault();
const gcode = document.getElementById('gcode').value;
const userId = document.getElementById('userId').value;
const password = document.getElementById('password').value;
const rememberMe = document.querySelector('input[type="checkbox"]').checked;
if (!userId || !password) {
showError('사용자 ID비밀번호를 입력해주세요.');
if (!gcode || !userId || !password) {
showError('그룹코드/사용자ID/비밀번호를 입력해주세요.');
return;
}
// 로딩 표시
showLoading();
// HomeController의 로그인 API 호출
fetch('http://127.0.0.1:9000/Home/Login', {
// HomeController의 로그인 API 호출
fetch('http://127.0.0.1:7979/Home/Login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
Gcode: gcode,
UserId: userId,
Password: password,
RememberMe: rememberMe
@@ -276,6 +300,11 @@
// 로그인 성공
showSuccess(data.Message);
// WebView2에 로그인 성공 메시지 전송
if (window.chrome && window.chrome.webview) {
window.chrome.webview.postMessage('LOGIN_SUCCESS');
}
// 리다이렉트 URL이 있으면 이동
if (data.RedirectUrl) {
setTimeout(() => {
@@ -342,12 +371,89 @@
}, 3000);
}
// 그룹 목록 로드
function loadUserGroups() {
fetch('http://127.0.0.1:7979/DashBoard/GetUserGroups')
.then(response => response.json())
.then(data => {
const gcodeSelect = document.getElementById('gcode');
// 기존 옵션 제거 (첫 번째 옵션 제외)
while (gcodeSelect.children.length > 1) {
gcodeSelect.removeChild(gcodeSelect.lastChild);
}
// 데이터 추가
data.forEach(group => {
if (group.gcode && group.name) {
const option = document.createElement('option');
option.value = group.gcode;
option.textContent = group.name;
option.className = 'text-gray-800';
gcodeSelect.appendChild(option);
}
});
// 이전 로그인 정보 설정
setPreviousLoginInfo();
})
.catch(error => {
console.error('그룹 목록 로드 중 오류 발생:', error);
showError('부서 목록을 불러오는 중 오류가 발생했습니다.');
});
}
// 이전 로그인 정보 설정
function setPreviousLoginInfo() {
// HomeController의 GetPreviousLoginInfo API 호출
fetch('http://127.0.0.1:7979/Home/GetPreviousLoginInfo')
.then(response => response.json())
.then(data => {
if (data.Success && data.Data) {
handlePreviousLoginInfo(data.Data);
}
})
.catch(error => {
console.error('이전 로그인 정보 로드 중 오류 발생:', error);
// 오류가 발생해도 기본 포커스 설정
setTimeout(() => {
document.getElementById('gcode').focus();
}, 100);
});
}
// 이전 로그인 정보 처리
function handlePreviousLoginInfo(data) {
let hasPreviousInfo = false;
if (data && data.Gcode) {
// 부서 선택
const gcodeSelect = document.getElementById('gcode');
gcodeSelect.value = data.Gcode;
hasPreviousInfo = true;
}
if (data && data.UserId) {
// 사용자 ID 설정 - 세미콜론으로 구분된 경우 첫 번째 요소만 사용
const userId = data.UserId.split(';')[0];
document.getElementById('userId').value = userId;
hasPreviousInfo = true;
}
// 이전 로그인 정보가 있으면 비밀번호 필드에, 없으면 부서 선택에 포커스
setTimeout(() => {
if (hasPreviousInfo) {
document.getElementById('password').focus();
} else {
document.getElementById('gcode').focus();
}
}, 100);
}
// 페이지 로드 시 애니메이션
document.addEventListener('DOMContentLoaded', function() {
// 입력 필드에 자동 포커스
setTimeout(() => {
document.getElementById('userId').focus();
}, 500);
// 그룹 목록 로드
loadUserGroups();
});
</script>
</body>

View File

@@ -116,6 +116,8 @@
this.ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem17 = new System.Windows.Forms.ToolStripSeparator();
this.webview2TestToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.btDev = new System.Windows.Forms.ToolStripMenuItem();
this.purchaseImportToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
@@ -149,8 +151,7 @@
this.toolStripButton1 = new System.Windows.Forms.ToolStripButton();
this.toolStripButton2 = new System.Windows.Forms.ToolStripButton();
this.toolStripButton3 = new System.Windows.Forms.ToolStripButton();
this.toolStripMenuItem17 = new System.Windows.Forms.ToolStripSeparator();
this.webview2TestToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.sbWeb = new System.Windows.Forms.ToolStripStatusLabel();
this.cmTab.SuspendLayout();
this.statusStrip1.SuspendLayout();
this.menuStrip1.SuspendLayout();
@@ -188,7 +189,8 @@
this.sbBCD,
this.sbLogin,
this.toolStripStatusLabel1,
this.sbLoginUseTime});
this.sbLoginUseTime,
this.sbWeb});
this.statusStrip1.Location = new System.Drawing.Point(1, 622);
this.statusStrip1.Name = "statusStrip1";
this.statusStrip1.Size = new System.Drawing.Size(1094, 22);
@@ -850,17 +852,29 @@
// 품목검색ToolStripMenuItem
//
this.ToolStripMenuItem.Name = "품목검색ToolStripMenuItem";
this.ToolStripMenuItem.Size = new System.Drawing.Size(180, 24);
this.ToolStripMenuItem.Size = new System.Drawing.Size(171, 24);
this.ToolStripMenuItem.Text = "품목 검색";
this.ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click);
//
// 대쉬보드ToolStripMenuItem
//
this.ToolStripMenuItem.Name = "대쉬보드ToolStripMenuItem";
this.ToolStripMenuItem.Size = new System.Drawing.Size(180, 24);
this.ToolStripMenuItem.Size = new System.Drawing.Size(171, 24);
this.ToolStripMenuItem.Text = "대쉬보드";
this.ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click);
//
// toolStripMenuItem17
//
this.toolStripMenuItem17.Name = "toolStripMenuItem17";
this.toolStripMenuItem17.Size = new System.Drawing.Size(168, 6);
//
// webview2TestToolStripMenuItem
//
this.webview2TestToolStripMenuItem.Name = "webview2TestToolStripMenuItem";
this.webview2TestToolStripMenuItem.Size = new System.Drawing.Size(171, 24);
this.webview2TestToolStripMenuItem.Text = "Webview2 Test";
this.webview2TestToolStripMenuItem.Click += new System.EventHandler(this.webview2TestToolStripMenuItem_Click);
//
// 즐겨찾기ToolStripMenuItem
//
this.ToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("즐겨찾기ToolStripMenuItem.Image")));
@@ -1161,17 +1175,11 @@
this.toolStripButton3.ToolTipText = "휴가신청";
this.toolStripButton3.Click += new System.EventHandler(this.toolStripButton3_Click);
//
// toolStripMenuItem17
// sbWeb
//
this.toolStripMenuItem17.Name = "toolStripMenuItem17";
this.toolStripMenuItem17.Size = new System.Drawing.Size(177, 6);
//
// webview2TestToolStripMenuItem
//
this.webview2TestToolStripMenuItem.Name = "webview2TestToolStripMenuItem";
this.webview2TestToolStripMenuItem.Size = new System.Drawing.Size(180, 24);
this.webview2TestToolStripMenuItem.Text = "Webview2 Test";
this.webview2TestToolStripMenuItem.Click += new System.EventHandler(this.webview2TestToolStripMenuItem_Click);
this.sbWeb.Name = "sbWeb";
this.sbWeb.Size = new System.Drawing.Size(31, 17);
this.sbWeb.Text = "WEB";
//
// fMain
//
@@ -1324,6 +1332,7 @@
private System.Windows.Forms.ToolStripMenuItem NRCR기준금액입력ToolStripMenuItem;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem17;
private System.Windows.Forms.ToolStripMenuItem webview2TestToolStripMenuItem;
private System.Windows.Forms.ToolStripStatusLabel sbWeb;
}
}

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;
@@ -153,7 +151,7 @@ namespace Project
// Start OWIN host
try
{
var options = new StartOptions("http://127.0.0.1:9000");
var options = new StartOptions(Pub.setting.WebServiceURL);
webApp = WebApp.Start<OWIN.Startup>(options);
Console.WriteLine("start webapp");
Pub.log.AddI("웹지원 서버 준비 완료");
@@ -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,16 +216,18 @@ namespace Project
void Func_Login()
{
if (this.webok)
//Pub.InitWebView = 2;
this.sbWeb.Text = $"Host:{(webok ? "O" : "X")},WebView:{Pub.InitWebView}";
if (webok && Pub.InitWebView == 1)
{
using (var flogIn = new Dialog.fLogin_WB())
if (flogIn.ShowDialog() != System.Windows.Forms.DialogResult.OK)
using (var f = new Dialog.fLogin_WB())
if (f.ShowDialog() != System.Windows.Forms.DialogResult.OK)
Application.ExitThread();
}
else
{
using (var flogIn = new Dialog.fLogin())
if (flogIn.ShowDialog() != System.Windows.Forms.DialogResult.OK)
using (var f = new Dialog.fLogin())
if (f.ShowDialog() != System.Windows.Forms.DialogResult.OK)
Application.ExitThread();
}
@@ -360,7 +374,13 @@ namespace Project
{
string formkey = "WORKBOOK";
if (!ShowForm(formkey))
AddForm(formkey, new FPJ0000.fJobReport());
{
if (this.webok && Pub.InitWebView == 1 && System.Diagnostics.Debugger.IsAttached)
AddForm(formkey, new Dialog.fJobReport());
else
AddForm(formkey, new FPJ0000.fJobReport());
}
}
void menu_save_cost()
@@ -997,10 +1017,8 @@ namespace Project
private void ToolStripMenuItem_Click(object sender, EventArgs e)
{
var url = "http://localhost:9000/item/find";
var url = $"{Pub.setting.WebServiceURL}/item/find";
Util.RunExplorer(url);
//var f = new Dialog.fWebView("http://localhost:9000/item/find");
//f.Show();
}
@@ -1028,7 +1046,7 @@ namespace Project
private void ToolStripMenuItem_Click(object sender, EventArgs e)
{
Util.RunExplorer("http://127.0.0.1:9000/Manual");
Util.RunExplorer($"{Pub.setting.WebServiceURL}/Manual");
}
private void ToolStripMenuItem_Click(object sender, EventArgs e)

View File

@@ -454,14 +454,14 @@
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPY4CDmcasDEu1MxmW6ixgWKbTwrBYVx0svkqL
h2GZViHDMu15QPFWhmXqUmBxDLBUZzVQwX84Xqzzg2GJpifDMs3rKOJLtZ4ADZWA6oKCpVo2IEmBtZb/
/U7m/E+5XP8/92TF/3lzYj/U9OT/S73c8D/yXNl/1W1eUEO0+6A6oWCZzgT+NebHkq/Ufyu+1fO/5GbP
/U7m/E+5XP8/92TF/3lzYj/UdOf/S73c8D/yXNl/1W1eUEO0+6A6oWCZzgT+NebHkq/Ufyu+1fO/5GbP
/0Mzc/4/6kz7f3VS5k+QGAyb7A49wbBE5xpUJxQs1RUsvtVdB1PUcaj+//XSiP/7W+3/Xi/0+tyzrRBu
QPGtrgsg9VCdCFB8s3suTFHlpY5l5wtDDl5Odvt2MUjt/7YKp73FFzs+guQKbva8g2pBBTAXFN3sKQHx
X7RGiD8u8/x/JUPrz5NsG7XCm736QNs/F93qOQ/WgA6K7/QYF9/oOg7lMjwu9vR8VOrxH4xLvDxAYkBX
lgItagErwAaK73SLQZkMTyq8smAGPKn0zgSJ1d+v58i9NZEPrIAQeFTh2fek3Os/CD8u9+qFChMPgP7f
CPdCqccGqDBx4P/+eo4XXVGn3/TE/Qfhl52Rp0BiUGns4N+Bfs2/B3r7/h/oPXP/QO9vIP0fGUPFzoDV
7O/RgGoDatw2kR0oOP/CxPp/6JpwYZDavwd65oH0Mvzd39uLTRExGKQX6PQ+W6Bpy4ECq0jBID3/DvTZ
AgBXZap4/fGa+QAAAABJRU5ErkJggg==
7O/RgGoDatw2kR0oOP/8hPp/6JpwYZDavwd65oH0Mvzd39uLTRExGKQX6PQ+W6Bpy4ECq0jBID3/DvTZ
AgBRa6pzQEH+NwAAAABJRU5ErkJggg==
</value>
</data>
<metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">

Submodule Sub/AmkorRestfulService deleted from 69b33b6e3c

Submodule Sub/arCtl updated: 249154147d...a4b2a097f8

View File

@@ -38,10 +38,6 @@
<Reference Include="arCommUtil">
<HintPath>..\..\DLL\arCommUtil.dll</HintPath>
</Reference>
<Reference Include="arControl.Net4, Version=18.7.27.1500, Culture=neutral, processorArchitecture=x86">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Sub\arCtl\bin\debug\arControl.Net4.dll</HintPath>
</Reference>
<Reference Include="ArSetting.Net4">
<HintPath>..\..\DLL\ArSetting.Net4.dll</HintPath>
</Reference>
@@ -322,6 +318,10 @@
</Compile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Sub\arCtl\arControl.csproj">
<Project>{f31c242c-1b15-4518-9733-48558499fe4b}</Project>
<Name>arControl</Name>
</ProjectReference>
<ProjectReference Include="..\FCM0000\FCM0000.csproj">
<Project>{26982882-c1ff-45f8-861c-d67558725ff1}</Project>
<Name>FCM0000</Name>

View File

@@ -4,6 +4,8 @@ using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Windows.Forms;
using FCOMMON.Models;
using System.Data;
namespace FCOMMON
{
@@ -17,21 +19,150 @@ namespace FCOMMON
return cn;
}
public struct sItemInfo
public static void GetPurchaseWaitCount(string gcode,out int cnt1,out int cnt2)
{
public int idx;
public string sid;
public string model;
public string supply;
public string name;
public string unit;
public float scale;
public string price;
public int supplyidx;
public string project;
public int qty;
cnt1 = 0;
cnt2 = 0;
var cn = getCn();
var sql1 = "select count(*) from Purchase where gcode = @gcode" +
" and state like '--%'" +
" and pdate >= @date";
var sql2 = "select count(*) from EETGW_PurchaseCR where gcode = @gcode" +
" and state like '--%'" +
" and pdate >= @date";
cn.Open();
var cmd = new System.Data.SqlClient.SqlCommand(sql1, cn);
cmd.Parameters.Add("gcode", SqlDbType.VarChar).Value = gcode;
cmd.Parameters.Add("date", SqlDbType.VarChar).Value = DateTime.Now.AddYears(-1).ToShortDateString();
cnt1 = (int)cmd.ExecuteScalar();
cmd.CommandText = sql2;
cnt2 = (int)cmd.ExecuteScalar();
cn.Dispose();
}
public static UserModel GetUserInfo(string uid)
{
var retval = new UserModel();
var cn = getCn();
var sql = "select * from Users where id = @id";
var cmd = new System.Data.SqlClient.SqlCommand(sql, cn);
cmd.Parameters.Add("id", SqlDbType.VarChar).Value = uid;
cn.Open();
var rdr = cmd.ExecuteReader();
var cnt = 0;
while (rdr.Read())
{
retval.name = rdr["name"].ToString();
retval.password = rdr["password"].ToString();
retval.id = rdr["id"].ToString();
retval.email = rdr["email"].ToString();
retval.hp = rdr["email"].ToString();
retval.tel = rdr["tel"].ToString();
retval.grade = rdr["grade"].ToString();
cnt += 1;
}
cn.Dispose();
if (cnt == 0) return null;
return retval;
}
public static UserGroupModel GetUserGroup(string gcode)
{
var retval = new UserGroupModel();
var cn = getCn();
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();
var rdr = cmd.ExecuteReader();
var cnt = 0;
while (rdr.Read())
{
retval.gcode = rdr["gcode"].ToString();
retval.name = rdr["dept"].ToString();
retval.perm = int.Parse(rdr["permission"].ToString());
cnt += 1;
}
cn.Dispose();
if (cnt == 0) return null;
return retval;
}
/// <summary>
/// 입력된 id의 그룹정보를 반환
/// </summary>
/// <param name="gcode"></param>
/// <param name="uid"></param>
/// <returns></returns>
public static GroupUserModel GetGroupUser(string gcode, string uid)
{
var retval = new GroupUserModel();
var cn = getCn();
var sql = "select * from EETGW_GroupUser where gcode = @gcode and uid = @uid";
var cmd = new System.Data.SqlClient.SqlCommand(sql, cn);
cmd.Parameters.Add("gcode", SqlDbType.VarChar).Value = gcode;
cmd.Parameters.Add("uid", SqlDbType.VarChar).Value = uid;
cn.Open();
var rdr = cmd.ExecuteReader();
var cnt = 0;
while (rdr.Read())
{
retval.Gcode = rdr["gcode"].ToString();
retval.uid = rdr["uid"].ToString();
retval.level = int.Parse(rdr["level"]?.ToString() ?? "0");
retval.Process = rdr["Process"].ToString();
cnt += 1;
}
cn.Dispose();
if (cnt == 0) return null;
return retval;
}
public static List<UserGroupModel> GetUserGroups()
{
var cn = getCn();
cn.Open();
List<UserGroupModel> retval = new List<UserGroupModel>();
var sql = " select gcode,dept,permission,managerinfo,devinfo,usemail" +
" from UserGroup " +
" order by usemail desc,dept";
var cmd = new SqlCommand(sql, cn);
try
{
var rdr = cmd.ExecuteReader();
while (rdr.Read())
{
retval.Add(new UserGroupModel
{
gcode = rdr["gcode"]?.ToString() ?? string.Empty,
name = rdr["dept"]?.ToString() ?? string.Empty,
perm = int.Parse(rdr["permission"]?.ToString() ?? "0"),
});
}
}
catch
{
}
cn.Close();
cn.Dispose();
return retval;
}
public static List<string> GetItemStorageList()
{
@@ -489,12 +620,12 @@ namespace FCOMMON
}
public static sItemInfo getLastPurchaseInfo(int idx)
public static ItemModel getLastPurchaseInfo(int idx)
{
var cn = getCn();
cn.Open();
var retval = new sItemInfo();
var retval = new ItemModel();
retval.idx = -1;
string sql = "select isnull(max(idx),-1) from Purchase where pumidx = " + idx.ToString();
@@ -530,12 +661,12 @@ namespace FCOMMON
return retval;
}
public static sItemInfo getLastPurchaseCRInfo(int idx)
public static ItemModel getLastPurchaseCRInfo(int idx)
{
var cn = getCn();
cn.Open();
var retval = new sItemInfo();
var retval = new ItemModel();
retval.idx = -1;
string sql = "select isnull(max(idx),-1) from EETGW_PurchaseCR WITH (nolock) where pumidx = " + idx.ToString();
@@ -679,12 +810,12 @@ namespace FCOMMON
return cnt == 1;
}
public static sItemInfo getItemInfo(int idx)
public static ItemModel getItemInfo(int idx)
{
var cn = getCn();
cn.Open();
var retval = new sItemInfo();
var retval = new ItemModel();
retval.idx = -1;
string sql = "select * from Items WITH (nolock) where gcode='" + FCOMMON.info.Login.gcode + "' and idx = " + idx.ToString();
@@ -709,7 +840,7 @@ namespace FCOMMON
cn.Dispose();
return retval;
}
public static int addItemInfo(sItemInfo info)
public static int addItemInfo(ItemModel info)
{
int retval = -1;
var cn = getCn();
@@ -748,12 +879,12 @@ namespace FCOMMON
cn.Dispose();
return retval;
}
public static sItemInfo getItemInfo(string sid)
public static ItemModel getItemInfo(string sid)
{
var cn = getCn();
cn.Open();
var retval = new sItemInfo();
var retval = new ItemModel();
retval.idx = -1;
string sql = "select * from Items WITH (nolock) where [gcode] = '" + FCOMMON.info.Login.gcode + "' and [sid] = '" + sid + "'";
@@ -796,7 +927,7 @@ namespace FCOMMON
var cn = getCn();
cn.Open();
var retval = new sItemInfo();
var retval = new ItemModel();
retval.idx = -1;
string sql = "select [id],[name],([name] +'(' +[id] +')') as dispName,isnull([dept],'') as dept,isnull(grade,'') as grade," +
@@ -908,7 +1039,7 @@ namespace FCOMMON
var cn = getCn();
cn.Open();
var sql = "select isnull(code,''),isnull(memo,''),isnull(svalue,''),isnull(svalue2,'')"+
var sql = "select isnull(code,''),isnull(memo,''),isnull(svalue,''),isnull(svalue2,'')" +
" from Common WITH (nolock) " +
" where gcode='" + FCOMMON.info.Login.gcode + "' and Grp = '{0}' and svalue = '{1}'";

View File

@@ -36,9 +36,6 @@
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="arControl.Net4">
<HintPath>..\..\Sub\arCtl\obj\Debug\arControl.Net4.dll</HintPath>
</Reference>
<Reference Include="ArSetting.Net4">
<HintPath>..\..\DLL\ArSetting.Net4.dll</HintPath>
</Reference>
@@ -75,6 +72,9 @@
<Reference Include="Microsoft.SqlServer.Types, Version=14.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.SqlServer.Types.14.0.314.76\lib\net40\Microsoft.SqlServer.Types.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json">
<HintPath>..\..\DLL\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
@@ -176,6 +176,10 @@
<Compile Include="IMyContract.cs" />
<Compile Include="ISO8601.cs" />
<Compile Include="keyValuedataTable.cs" />
<Compile Include="Models\GroupUserModel.cs" />
<Compile Include="Models\ItemModel.cs" />
<Compile Include="Models\UserModel.cs" />
<Compile Include="Models\UserGroupModel.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Info.cs" />
<Compile Include="Setting.cs" />
@@ -245,6 +249,10 @@
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Sub\arCtl\arControl.csproj">
<Project>{f31c242c-1b15-4518-9733-48558499fe4b}</Project>
<Name>arControl</Name>
</ProjectReference>
<ProjectReference Include="..\..\Sub\arftp\FTPClass.csproj">
<Project>{150859d3-1c5d-4e20-b324-f9ebe188d893}</Project>
<Name>FTPClass</Name>

View File

@@ -0,0 +1,12 @@
namespace FCOMMON.Models
{
public class GroupUserModel
{
public string Gcode { get; set; }
public string uid { get; set; }
public string Process { get; set; }
public int level { get; set; }
}
}

View File

@@ -0,0 +1,17 @@
namespace FCOMMON.Models
{
public class ItemModel
{
public int idx;
public string sid;
public string model;
public string supply;
public string name;
public string unit;
public float scale;
public string price;
public int supplyidx;
public string project;
public int qty;
}
}

View File

@@ -0,0 +1,9 @@
namespace FCOMMON.Models
{
public class UserGroupModel
{
public string gcode { get; set; }
public string name { get; set; }
public int perm { get; set; }
}
}

View File

@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FCOMMON.Models
{
public class UserModel
{
public string id { get; set; }
public string password { get; set; }
public string name { get; set; }
public string grade { get; set; }
public string email { get; set; }
public string hp { get; set; }
public string tel { get; set; }
}
}

View File

@@ -8,16 +8,200 @@
//180614 chi map 명령어 추가
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace FCOMMON
{
public static class AmkorRestfulService
{
public class RestfulResultDataTable
{
/// <summary>
/// 오류 및 기타상황의 메세지
/// </summary>
public string Message { get; set; }
/// <summary>
/// Restful 의 실행이 완료되었는가?
/// </summary>
public Boolean Complete { get; set; }
/// <summary>
/// Restful 실행 결과를 담고있는 RawBuffer
/// </summary>
public string Buffer { get; set; }
/// <summary>
/// Restful Service 호출 URL
/// </summary>
public string Url { get; set; }
/// <summary>
/// 결과값
/// </summary>
public System.Data.DataTable Result { get; set; }
public RestfulResultDataTable()
{
Complete = false;
Message = string.Empty;
Buffer = string.Empty;
Url = string.Empty;
Result = new System.Data.DataTable();
}
}
/// <summary>
/// SPM사이트에서 SID검색을 합니다.
/// </summary>
/// <param name="sid"></param>
/// <returns></returns>
public static RestfulResultDataTable SPMSIDSearch(string sid)
{
var retval = new RestfulResultDataTable();
retval.Url = "https://atknet.amkor.co.kr/spm/getActiveInventoryBySid/{0}";
retval.Url = string.Format(retval.Url, sid);
Boolean isError;
retval.Buffer = GetFromUrl(retval.Url, out isError);
var cols = new string[] { "plant", "location", "quantity", "part_description", "batch_no", "serial", "costcenter", "responsible", "bin_location" };
retval.Result = new DataTable();
foreach (var col in cols)
retval.Result.Columns.Add(col);
try
{
var json = JArray.Parse(retval.Buffer);
List<string> items = new List<string>();
string[] data = new string[cols.Length];
for (int i = 0; i < json.Count; i++)
{
var jdata = json[i];
for (int c = 0; c < cols.Length; c++)
{
var itemdata = jdata[cols[c]];
if (itemdata != null) data[c] = itemdata.ToString();
}
if (int.TryParse(data[2], out int value))
{
if (value > 0)
retval.Result.Rows.Add(data);
}
}
retval.Complete = retval.Result.Rows.Count > 0;
}
catch
{
retval.Complete = false;
}
retval.Result.AcceptChanges();
//if (retval.Buffer.ToLower().Contains("error") || isError)
//{
// retval.Complete = false;
// retval.Message = retval.Buffer;
// RaiseMessage(true, "get_tms_info Error : " + retval.Buffer);
//}
//else
//{
//string tmpBuffer = retval.Buffer;
//tmpBuffer = tmpBuffer.Replace((char)0x02, (char)0x0a);
//tmpBuffer = tmpBuffer.Replace((char)0x03, (char)0x09);
//retval.Result = GenerateDataTable(tmpBuffer);
//}
return retval;
}
public class MessageEventArgs : EventArgs
{
public Boolean isError { get; set; }
public string Message { get; set; }
public MessageEventArgs(bool iserr_, string msg_)
{
this.isError = iserr_;
this.Message = msg_;
}
}
public static event EventHandler<MessageEventArgs> Message;
/// <summary>
/// 웹서비스에서 받은 데이터 원문 메세지 입니다.
/// </summary>
public static event EventHandler<MessageEventArgs> RawMessage;
private static void RaiseMessage(Boolean iserr, string msg)
{
if (Message != null)
Message(null, new MessageEventArgs(iserr, msg));
}
private static void RaiseRawMessage(string url, string msg)
{
if (RawMessage != null)
RawMessage(null, new MessageEventArgs(false, "URL : " + url + "\n" + msg));
}
public static int timeout = 10000;
public static string LastQueryURL { get; private set; }
public static string LastQueryBUF { get; private set; }
private static string GetFromUrl(string url, out Boolean isError, string authid = "", string authpw = "")
{
isError = false;
string result = "";
try
{
RaiseMessage(false, "GET : " + url);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(url));
request.Timeout = timeout;
request.ReadWriteTimeout = timeout;
if (string.IsNullOrEmpty(authid) == false && string.IsNullOrEmpty(authpw) == false)
{
string authInfo = $"{authid}:{authpw}";
authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo));
request.Headers["Authorization"] = "Basic " + authInfo;
}
request.MaximumAutomaticRedirections = 4;
request.MaximumResponseHeadersLength = 4;
request.Credentials = CredentialCache.DefaultCredentials;
var response = request.GetResponse() as HttpWebResponse;
var txtReader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
result = txtReader.ReadToEnd();
LastQueryBUF = result;
LastQueryURL = url;
RaiseRawMessage(url, "RESULT\n" + result); //181026 - show data
}
catch (Exception ex)
{
isError = true;
result = ex.Message.ToString();
RaiseMessage(true, "GET-ERROR\n" + result);
LastQueryBUF = string.Empty;
}
return result;
}
}
public static partial class Util
{

View File

@@ -555,10 +555,6 @@
</Compile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Sub\AmkorRestfulService\AmkorRestfulService.csproj">
<Project>{58cfc90c-5068-46a2-a8de-0e92ee9e0990}</Project>
<Name>AmkorRestfulService</Name>
</ProjectReference>
<ProjectReference Include="..\..\Sub\arCtl\arControl.csproj">
<Project>{f31c242c-1b15-4518-9733-48558499fe4b}</Project>
<Name>arControl</Name>

View File

@@ -278,7 +278,6 @@
//
this.bindingNavigatorPositionItem.AccessibleName = "위치";
this.bindingNavigatorPositionItem.AutoSize = false;
this.bindingNavigatorPositionItem.Font = new System.Drawing.Font("맑은 고딕", 9F);
this.bindingNavigatorPositionItem.Name = "bindingNavigatorPositionItem";
this.bindingNavigatorPositionItem.Size = new System.Drawing.Size(50, 23);
this.bindingNavigatorPositionItem.Text = "0";
@@ -405,7 +404,6 @@
// tbFind
//
this.tbFind.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.tbFind.Font = new System.Drawing.Font("맑은 고딕", 9F);
this.tbFind.Name = "tbFind";
this.tbFind.Size = new System.Drawing.Size(100, 26);
this.tbFind.KeyDown += new System.Windows.Forms.KeyEventHandler(this.tbFind_KeyDown);
@@ -764,7 +762,6 @@
// dtSD
//
this.dtSD.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.dtSD.Font = new System.Drawing.Font("맑은 고딕", 9F);
this.dtSD.Name = "dtSD";
this.dtSD.Size = new System.Drawing.Size(75, 37);
this.dtSD.Text = "1982-11-23";
@@ -781,7 +778,6 @@
// dtED
//
this.dtED.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.dtED.Font = new System.Drawing.Font("맑은 고딕", 9F);
this.dtED.Name = "dtED";
this.dtED.Size = new System.Drawing.Size(75, 37);
this.dtED.Text = "1982-11-23";
@@ -838,7 +834,6 @@
// tbRequest
//
this.tbRequest.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.tbRequest.Font = new System.Drawing.Font("맑은 고딕", 9F);
this.tbRequest.Name = "tbRequest";
this.tbRequest.Size = new System.Drawing.Size(70, 37);
this.tbRequest.TextBoxTextAlign = System.Windows.Forms.HorizontalAlignment.Center;
@@ -853,7 +848,6 @@
// tbManager
//
this.tbManager.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.tbManager.Font = new System.Drawing.Font("맑은 고딕", 9F);
this.tbManager.Name = "tbManager";
this.tbManager.Size = new System.Drawing.Size(70, 37);
this.tbManager.TextBoxTextAlign = System.Windows.Forms.HorizontalAlignment.Center;
@@ -867,7 +861,6 @@
// tbAdmin
//
this.tbAdmin.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.tbAdmin.Font = new System.Drawing.Font("맑은 고딕", 9F);
this.tbAdmin.Name = "tbAdmin";
this.tbAdmin.Size = new System.Drawing.Size(70, 37);
this.tbAdmin.TextBoxTextAlign = System.Windows.Forms.HorizontalAlignment.Center;

View File

@@ -635,7 +635,7 @@ namespace FEQ0000
var iteminfo = FCOMMON.DBM.getItemInfo(sid);
if (iteminfo.idx < 0)
{
FCOMMON.DBM.sItemInfo newitem = new FCOMMON.DBM.sItemInfo();
FCOMMON.Models.ItemModel newitem = new FCOMMON.Models.ItemModel();
newitem.sid = newdr.sid;
newitem.name = newdr.pumname;
newitem.price = newdr.pumprice.ToString();

View File

@@ -1131,7 +1131,7 @@ namespace FEQ0000
return;
}
var dt = Amkor.RestfulService.SPMSIDSearch(sid);
var dt = AmkorRestfulService.SPMSIDSearch(sid);
if (dt.Complete)
{
var f = new FCM0000.fSIDListSelect(sid, dt.Result);

View File

@@ -170,7 +170,7 @@ namespace FEQ0000
var iteminfo = FCOMMON.DBM.getItemInfo(sid);
if (iteminfo.idx < 0)
{
FCOMMON.DBM.sItemInfo newitem = new FCOMMON.DBM.sItemInfo();
FCOMMON.Models.ItemModel newitem = new FCOMMON.Models.ItemModel();
newitem.sid = newdr.sid;
newitem.name = newdr.pumname;
newitem.price = newdr.pumprice.ToString();

View File

@@ -580,7 +580,7 @@ namespace FEQ0000
var iteminfo = FCOMMON.DBM.getItemInfo(sid);
if (iteminfo.idx < 0)
{
FCOMMON.DBM.sItemInfo newitem = new FCOMMON.DBM.sItemInfo();
FCOMMON.Models.ItemModel newitem = new FCOMMON.Models.ItemModel();
newitem.sid = newdr.sid;
newitem.name = newdr.pumname;
newitem.price = newdr.pumprice.ToString();

View File

@@ -163,7 +163,7 @@ namespace FEQ0000
var iteminfo = FCOMMON.DBM.getItemInfo(sid);
if (iteminfo.idx < 0)
{
FCOMMON.DBM.sItemInfo newitem = new FCOMMON.DBM.sItemInfo();
FCOMMON.Models.ItemModel newitem = new FCOMMON.Models.ItemModel();
newitem.sid = newdr.sid;
newitem.name = newdr.pumname;
newitem.price = newdr.pumprice.ToString();

View File

@@ -654,7 +654,7 @@ namespace FEQ0000
var iteminfo = FCOMMON.DBM.getItemInfo(sid);
if (iteminfo.idx < 0)
{
FCOMMON.DBM.sItemInfo newitem = new FCOMMON.DBM.sItemInfo();
FCOMMON.Models.ItemModel newitem = new FCOMMON.Models.ItemModel();
newitem.sid = newdr.sid;
newitem.name = newdr.pumname;
newitem.price = newdr.pumprice.ToString();

View File

@@ -169,7 +169,7 @@ namespace FEQ0000
var iteminfo = FCOMMON.DBM.getItemInfo(sid);
if (iteminfo.idx < 0)
{
FCOMMON.DBM.sItemInfo newitem = new FCOMMON.DBM.sItemInfo();
FCOMMON.Models.ItemModel newitem = new FCOMMON.Models.ItemModel();
newitem.sid = newdr.sid;
newitem.name = newdr.pumname;
newitem.price = newdr.pumprice.ToString();

View File

@@ -1280,7 +1280,7 @@ namespace FEQ0000
return;
}
var dt = Amkor.RestfulService.SPMSIDSearch(sid);
var dt = AmkorRestfulService.SPMSIDSearch(sid);
if (dt.Complete)
{
var f = new FCM0000.fSIDListSelect(sid, dt.Result);

View File

@@ -132,7 +132,7 @@ namespace FEQ0000.Purchase
}
else
{
var dt = Amkor.RestfulService.SPMSIDSearch(sid);
var dt = AmkorRestfulService.SPMSIDSearch(sid);
if (dt.Complete)
{
dr.sitecnt = $"{dt.Result.Rows.Count}건";
@@ -166,7 +166,7 @@ namespace FEQ0000.Purchase
}
else
{
var dt = Amkor.RestfulService.SPMSIDSearch(sid);
var dt = AmkorRestfulService.SPMSIDSearch(sid);
if (dt.Complete)
{
dr.sitecnt = $"{dt.Result.Rows.Count}건";

View File

@@ -469,7 +469,7 @@ namespace FEQ0000
var iteminfo = FCOMMON.DBM.getItemInfo(sid);
if (iteminfo.idx < 0)
{
FCOMMON.DBM.sItemInfo newitem = new FCOMMON.DBM.sItemInfo();
FCOMMON.Models.ItemModel newitem = new FCOMMON.Models.ItemModel();
newitem.sid = newdr.sid;
newitem.name = newdr.pumname;
newitem.price = newdr.pumprice.ToString();

View File

@@ -923,10 +923,6 @@
</Compile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Sub\AmkorRestfulService\AmkorRestfulService.csproj">
<Project>{58cfc90c-5068-46a2-a8de-0e92ee9e0990}</Project>
<Name>AmkorRestfulService</Name>
</ProjectReference>
<ProjectReference Include="..\..\Sub\arCtl\arControl.csproj">
<Project>{f31c242c-1b15-4518-9733-48558499fe4b}</Project>
<Name>arControl</Name>

View File

@@ -45,7 +45,7 @@ namespace FPJ0000
{
var processStr = "%";
var dtUserList = taUserList.GetData(processStr, FCOMMON.info.Login.gcode);
foreach (dsReport.ProcessUserListRow dr in dtUserList)
foreach (dsReport.ProcessUserListRow dr in dtUserList.OrderBy(t=>t.name))
{
if (String.IsNullOrEmpty(dr.outdate) == false)
{
@@ -62,7 +62,7 @@ namespace FPJ0000
{
var processStr = prc;// cmbProcess.Text;
var dtUserList = taUserList.GetData(processStr, FCOMMON.info.Login.gcode);
foreach (dsReport.ProcessUserListRow dr in dtUserList)
foreach (dsReport.ProcessUserListRow dr in dtUserList.OrderBy(t=>t.name))
{
if (String.IsNullOrEmpty(dr.outdate) == false)
{

View File

@@ -30,16 +30,16 @@
{
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(fOTConfirm));
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle2 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle3 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle4 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle5 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle6 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle7 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle8 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle9 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle10 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle11 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle12 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle13 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle14 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle15 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle16 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle17 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle18 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle19 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle20 = new System.Windows.Forms.DataGridViewCellStyle();
this.bn = new System.Windows.Forms.BindingNavigator(this.components);
this.bs = new System.Windows.Forms.BindingSource(this.components);
this.dsMSSQL = new FPJ0000.dsPRJ();
@@ -100,6 +100,8 @@
this.otEnd = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.projectNameDataGridViewTextBoxColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.descriptionDataGridViewTextBoxColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
this.ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
((System.ComponentModel.ISupportInitialize)(this.bn)).BeginInit();
this.bn.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.bs)).BeginInit();
@@ -110,6 +112,7 @@
this.splitContainer1.Panel2.SuspendLayout();
this.splitContainer1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.dv1)).BeginInit();
this.contextMenuStrip1.SuspendLayout();
this.SuspendLayout();
//
// bn
@@ -511,6 +514,7 @@
this.otEnd,
this.projectNameDataGridViewTextBoxColumn,
this.descriptionDataGridViewTextBoxColumn});
this.dv1.ContextMenuStrip = this.contextMenuStrip1;
this.dv1.DataSource = this.bs;
this.dv1.Dock = System.Windows.Forms.DockStyle.Fill;
this.dv1.EditMode = System.Windows.Forms.DataGridViewEditMode.EditProgrammatically;
@@ -553,9 +557,9 @@
// wwDataGridViewTextBoxColumn
//
this.wwDataGridViewTextBoxColumn.DataPropertyName = "ww";
dataGridViewCellStyle1.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter;
dataGridViewCellStyle1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
this.wwDataGridViewTextBoxColumn.DefaultCellStyle = dataGridViewCellStyle1;
dataGridViewCellStyle11.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter;
dataGridViewCellStyle11.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
this.wwDataGridViewTextBoxColumn.DefaultCellStyle = dataGridViewCellStyle11;
this.wwDataGridViewTextBoxColumn.HeaderText = "WW";
this.wwDataGridViewTextBoxColumn.Name = "wwDataGridViewTextBoxColumn";
this.wwDataGridViewTextBoxColumn.ReadOnly = true;
@@ -564,8 +568,8 @@
// pdateDataGridViewTextBoxColumn
//
this.pdateDataGridViewTextBoxColumn.DataPropertyName = "pdate";
dataGridViewCellStyle2.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter;
this.pdateDataGridViewTextBoxColumn.DefaultCellStyle = dataGridViewCellStyle2;
dataGridViewCellStyle12.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter;
this.pdateDataGridViewTextBoxColumn.DefaultCellStyle = dataGridViewCellStyle12;
this.pdateDataGridViewTextBoxColumn.HeaderText = "날짜";
this.pdateDataGridViewTextBoxColumn.Name = "pdateDataGridViewTextBoxColumn";
this.pdateDataGridViewTextBoxColumn.ReadOnly = true;
@@ -574,8 +578,8 @@
// WeekName
//
this.WeekName.DataPropertyName = "WeekName";
dataGridViewCellStyle3.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter;
this.WeekName.DefaultCellStyle = dataGridViewCellStyle3;
dataGridViewCellStyle13.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter;
this.WeekName.DefaultCellStyle = dataGridViewCellStyle13;
this.WeekName.HeaderText = "*";
this.WeekName.Name = "WeekName";
this.WeekName.ReadOnly = true;
@@ -616,8 +620,8 @@
// statusDataGridViewTextBoxColumn
//
this.statusDataGridViewTextBoxColumn.DataPropertyName = "status";
dataGridViewCellStyle4.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter;
this.statusDataGridViewTextBoxColumn.DefaultCellStyle = dataGridViewCellStyle4;
dataGridViewCellStyle14.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter;
this.statusDataGridViewTextBoxColumn.DefaultCellStyle = dataGridViewCellStyle14;
this.statusDataGridViewTextBoxColumn.HeaderText = "상태";
this.statusDataGridViewTextBoxColumn.Name = "statusDataGridViewTextBoxColumn";
this.statusDataGridViewTextBoxColumn.ReadOnly = true;
@@ -634,11 +638,11 @@
// otDataGridViewTextBoxColumn
//
this.otDataGridViewTextBoxColumn.DataPropertyName = "ot";
dataGridViewCellStyle5.Alignment = System.Windows.Forms.DataGridViewContentAlignment.TopCenter;
dataGridViewCellStyle5.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(224)))), ((int)(((byte)(192)))));
dataGridViewCellStyle5.ForeColor = System.Drawing.Color.Red;
dataGridViewCellStyle5.Format = "N1";
this.otDataGridViewTextBoxColumn.DefaultCellStyle = dataGridViewCellStyle5;
dataGridViewCellStyle15.Alignment = System.Windows.Forms.DataGridViewContentAlignment.TopCenter;
dataGridViewCellStyle15.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(224)))), ((int)(((byte)(192)))));
dataGridViewCellStyle15.ForeColor = System.Drawing.Color.Red;
dataGridViewCellStyle15.Format = "N1";
this.otDataGridViewTextBoxColumn.DefaultCellStyle = dataGridViewCellStyle15;
this.otDataGridViewTextBoxColumn.HeaderText = "초과";
this.otDataGridViewTextBoxColumn.Name = "otDataGridViewTextBoxColumn";
this.otDataGridViewTextBoxColumn.ReadOnly = true;
@@ -647,10 +651,10 @@
// ot2DataGridViewTextBoxColumn
//
this.ot2DataGridViewTextBoxColumn.DataPropertyName = "ot2";
dataGridViewCellStyle6.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter;
dataGridViewCellStyle6.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(255)))), ((int)(((byte)(255)))));
dataGridViewCellStyle6.Format = "N1";
this.ot2DataGridViewTextBoxColumn.DefaultCellStyle = dataGridViewCellStyle6;
dataGridViewCellStyle16.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter;
dataGridViewCellStyle16.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(255)))), ((int)(((byte)(255)))));
dataGridViewCellStyle16.Format = "N1";
this.ot2DataGridViewTextBoxColumn.DefaultCellStyle = dataGridViewCellStyle16;
this.ot2DataGridViewTextBoxColumn.HeaderText = "승인(대체)";
this.ot2DataGridViewTextBoxColumn.Name = "ot2DataGridViewTextBoxColumn";
this.ot2DataGridViewTextBoxColumn.Width = 88;
@@ -658,10 +662,10 @@
// otPMS
//
this.otPMS.DataPropertyName = "otPMS";
dataGridViewCellStyle7.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter;
dataGridViewCellStyle7.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(255)))), ((int)(((byte)(255)))));
dataGridViewCellStyle7.Format = "N1";
this.otPMS.DefaultCellStyle = dataGridViewCellStyle7;
dataGridViewCellStyle17.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter;
dataGridViewCellStyle17.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(255)))), ((int)(((byte)(255)))));
dataGridViewCellStyle17.Format = "N1";
this.otPMS.DefaultCellStyle = dataGridViewCellStyle17;
this.otPMS.HeaderText = "승인(PMS)";
this.otPMS.Name = "otPMS";
this.otPMS.Width = 91;
@@ -669,8 +673,8 @@
// otReasonDataGridViewTextBoxColumn
//
this.otReasonDataGridViewTextBoxColumn.DataPropertyName = "otReason";
dataGridViewCellStyle8.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(255)))), ((int)(((byte)(255)))));
this.otReasonDataGridViewTextBoxColumn.DefaultCellStyle = dataGridViewCellStyle8;
dataGridViewCellStyle18.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(255)))), ((int)(((byte)(255)))));
this.otReasonDataGridViewTextBoxColumn.DefaultCellStyle = dataGridViewCellStyle18;
this.otReasonDataGridViewTextBoxColumn.HeaderText = "사유";
this.otReasonDataGridViewTextBoxColumn.Name = "otReasonDataGridViewTextBoxColumn";
this.otReasonDataGridViewTextBoxColumn.Width = 54;
@@ -678,27 +682,25 @@
// otStartDataGridViewTextBoxColumn
//
this.otStartDataGridViewTextBoxColumn.DataPropertyName = "otStart";
dataGridViewCellStyle9.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter;
dataGridViewCellStyle9.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(224)))), ((int)(((byte)(192)))));
dataGridViewCellStyle9.Format = "HH:mm:ss";
this.otStartDataGridViewTextBoxColumn.DefaultCellStyle = dataGridViewCellStyle9;
dataGridViewCellStyle19.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter;
dataGridViewCellStyle19.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(224)))), ((int)(((byte)(192)))));
dataGridViewCellStyle19.Format = "HH:mm:ss";
this.otStartDataGridViewTextBoxColumn.DefaultCellStyle = dataGridViewCellStyle19;
this.otStartDataGridViewTextBoxColumn.HeaderText = "시작";
this.otStartDataGridViewTextBoxColumn.Name = "otStartDataGridViewTextBoxColumn";
this.otStartDataGridViewTextBoxColumn.ReadOnly = true;
this.otStartDataGridViewTextBoxColumn.Visible = false;
this.otStartDataGridViewTextBoxColumn.Width = 54;
//
// otEnd
//
this.otEnd.DataPropertyName = "otEnd";
dataGridViewCellStyle10.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter;
dataGridViewCellStyle10.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(224)))), ((int)(((byte)(192)))));
dataGridViewCellStyle10.Format = "HH:mm:ss";
this.otEnd.DefaultCellStyle = dataGridViewCellStyle10;
dataGridViewCellStyle20.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter;
dataGridViewCellStyle20.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(224)))), ((int)(((byte)(192)))));
dataGridViewCellStyle20.Format = "HH:mm:ss";
this.otEnd.DefaultCellStyle = dataGridViewCellStyle20;
this.otEnd.HeaderText = "종료";
this.otEnd.Name = "otEnd";
this.otEnd.ReadOnly = true;
this.otEnd.Visible = false;
this.otEnd.Width = 54;
//
// projectNameDataGridViewTextBoxColumn
@@ -717,6 +719,20 @@
this.descriptionDataGridViewTextBoxColumn.ReadOnly = true;
this.descriptionDataGridViewTextBoxColumn.Width = 51;
//
// contextMenuStrip1
//
this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.ToolStripMenuItem});
this.contextMenuStrip1.Name = "contextMenuStrip1";
this.contextMenuStrip1.Size = new System.Drawing.Size(153, 48);
//
// 목록내보내기ToolStripMenuItem
//
this.ToolStripMenuItem.Name = "목록내보내기ToolStripMenuItem";
this.ToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
this.ToolStripMenuItem.Text = "목록 내보내기";
this.ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click);
//
// fOTConfirm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F);
@@ -741,6 +757,7 @@
((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();
this.splitContainer1.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.dv1)).EndInit();
this.contextMenuStrip1.ResumeLayout(false);
this.ResumeLayout(false);
this.PerformLayout();
@@ -808,5 +825,7 @@
private System.Windows.Forms.DataGridViewTextBoxColumn otEnd;
private System.Windows.Forms.DataGridViewTextBoxColumn projectNameDataGridViewTextBoxColumn;
private System.Windows.Forms.DataGridViewTextBoxColumn descriptionDataGridViewTextBoxColumn;
private System.Windows.Forms.ContextMenuStrip contextMenuStrip1;
private System.Windows.Forms.ToolStripMenuItem ToolStripMenuItem;
}
}

View File

@@ -43,7 +43,7 @@ namespace FPJ0000
this.dtSD.Text = DateTime.Now.AddMonths(-1).ToShortDateString();
//공정목록
// var taProc = new dsReportTableAdapters.ProcessListTableAdapter();
// var taProc = new dsReportTableAdapters.ProcessListTableAdapter();
var dtProcList = FCOMMON.DBM.GroupUserProcessList();//taProc.GetData(FCOMMON.info.Login.gcode);
int curLevel = Math.Max(FCOMMON.info.Login.level, FCOMMON.DBM.getAuth(FCOMMON.DBM.eAuthType.otconfirm));
//cmbProcess.Items.Clear();
@@ -138,7 +138,7 @@ namespace FPJ0000
{
var processStr = "%";
var dtUserList = taUserList.GetData(processStr, FCOMMON.info.Login.gcode);
foreach (dsReport.ProcessUserListRow dr in dtUserList)
foreach (dsReport.ProcessUserListRow dr in dtUserList.OrderBy(t => t.name))
{
string cmbdata = string.Format("{1}({0})", dr.id, dr.name);
this.cmbUser.Items.Add(cmbdata);
@@ -150,7 +150,7 @@ namespace FPJ0000
{
var processStr = prc;// cmbProcess.Text;
var dtUserList = taUserList.GetData(processStr, FCOMMON.info.Login.gcode);
foreach (dsReport.ProcessUserListRow dr in dtUserList)
foreach (dsReport.ProcessUserListRow dr in dtUserList.OrderBy(t => t.name))
{
string cmbdata = string.Format("{1}({0})", dr.id, dr.name);
this.cmbUser.Items.Add(cmbdata);
@@ -413,7 +413,7 @@ namespace FPJ0000
private void toolStripButton1_Click(object sender, EventArgs e)
{
//전체승인
using(var f = new fOTConfirmValue())
using (var f = new fOTConfirmValue())
{
if (f.ShowDialog() != DialogResult.OK) return;
}
@@ -469,7 +469,7 @@ namespace FPJ0000
{
if (f.ShowDialog() == DialogResult.OK)
{
foreach(var row in rows)
foreach (var row in rows)
row.EndEdit();
try
@@ -492,8 +492,8 @@ namespace FPJ0000
}
}
private void toolStripButton8_Click(object sender, EventArgs e)
{
private void toolStripButton8_Click(object sender, EventArgs e)
{
var sdo = DateTime.Parse(dtSD.Text);
var sd = DateTime.Parse(sdo.AddMonths(-1).ToString("yyyy-MM-01"));
var ed = sd.AddMonths(1).AddDays(-1);
@@ -501,8 +501,8 @@ namespace FPJ0000
dtED.Text = ed.ToShortDateString();
}
private void toolStripButton7_Click(object sender, EventArgs e)
{
private void toolStripButton7_Click(object sender, EventArgs e)
{
var sdo = DateTime.Parse(dtSD.Text);
var sd = DateTime.Parse(sdo.AddMonths(1).ToString("yyyy-MM-01"));
var ed = sd.AddMonths(1).AddDays(-1);
@@ -514,5 +514,23 @@ namespace FPJ0000
{
}
private void ToolStripMenuItem_Click(object sender, EventArgs e)
{
using (var sd = new SaveFileDialog())
{
sd.Filter = "콤마로 분리된 파일|*.csv";
sd.FilterIndex = 0;
if (sd.ShowDialog() != DialogResult.OK) return;
var fn = dv1.ExportData(sd.FileName);
var dlg = AR.UTIL.MsgQ("생성된 파일을 확인할까요?");
if (dlg != DialogResult.Yes) return;
AR.UTIL.RunExplorer(fn);
}
}
}
}

View File

@@ -181,20 +181,20 @@
<data name="toolStripButton5.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAALvSURBVDhPhZLrS1NhHMf3qv6EsF70UohUyqioF6WpTQ3s
ZjrMvM0pmprowiBbTCNTF5qoUCFK0YsK7aJTm7dtzm24Veq85v0GXpa6yzm6s/ntOWdLDYR+8OF58Tzf
D+f5nofHTvBDZfyVEp0iolT3O0Sio8hKc8jYVU9HlGjpsGca03mxuvxY5PsDXGjvhD7pVi9b6FWTyeQ0
2zZhtu6yamGhMbxoQf6XWQhKR+z8DPlBT9Q94UWaZTasnXZAP8NAP8tAN81AM7UF5a9NtAzZsMkAjSMU
8j/NIOmFifpHEiJpoTbsWzDOOfF9jiErg15OsgXV+Ca+DdmJwAXjohP6BQcK5bMIfNDxjgtHywImb0ki
t0VVN5BUeROVrXUoqJchUOKLAAK/8ByCpadR1ljGXcVKM1hasyM4TsVwgqiSwI8dA01oGnuNSl0uJ4mr
CEPu21hk1gkgrL6KxOpENPYtoclkxdf+DayTnkKk3TQn4JfzD/pIspy60S68GZCiWJnBSeKrwkn4GlJf
pkA9buOu0j5GQUF6WLM5EFLQ4xawE1qkorNrEmAY16Bafx9P23IQLbuE+IpIGKbtMJBi2YLVE+5OzEQQ
LN0juPBI4jiTdxSx5XwYJ7Qo7EqDVJ4NwfMg1Ck/4+c8AwMpVjvlQA9h2eJA4GOP4KTYS+QvPoLM2hjc
rgpFTNllTpItj4W4PoV8SRDYfeOsE73sLyZYSJF+WRq3wF98aN5ffJgc8oJ/rheuFwch/VUC1EMKFCry
kPYhAcKqKBiIQE/eho4IaIeLCJS7V7iY1U0vrtPom3dyqEYXcK8mFckkKKoWIKf27s4ei33LSQQNuwLW
NmfeFfwPG3uFlD2Cs9md9lbNj+39Du9H/+Cwyyeu0eqJkyJT2yZnNuyWzp4+1+QKhcllCuMeVqwODrZ5
K02eev+Qi6Kode87zYOeOI93KrU13U/Y0nZCpDD7iRroHZLd+P5F2EB7C5vXjic2t/smyJN4PB7vD5/y
nxrD4VALAAAAAElFTkSuQmCC
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAALuSURBVDhPhZLrS1NhHMf3Kv+EsF70UghTyqioF6WpTQ3s
Zipm3uYUTW3owiBbzEXmJTRRoUKUohcV2kWnNm9zzm24ieY0Ne838LLUXc7Rnc1vzzlbzkDoBx+eF8/5
fji/7zk8dkIeKROvlmgVkaXa36ESLUVOmqOMPXV0ZImGDn+uNl4QqyqOR304xIX2T9jTXtWqmV43Go0O
k3UbJouHdTMLjZ/LZhR8nUds6ZiNnyX3ckddE1GkXmXDmlk7dHMMdPMMtLMM1DM7UP7aRuuoFdsM0DRG
oeDzHFJeGql/JKGSVmrLtgPDggMDCww5GfRzkh30TG7j+6iNCJwwLDugW7JDJp9H0MPO91w4pixw+rYk
aldYfRMpVbdQ1VaPwoYyBEn8EEjgy84jRHoG5U3l3CoWmsHKhg0hCT0MJ4guCfrUOdyM5ok3qNLmcZKE
ynDkvYtHdn0sBDXXkFyTjKahFTQbLfj2YwubpKdQaS/NCfgVfC9fSY5DO96Nt8NSFCuzOElidQQJX0f6
qzSoJq3cKh0TFBSkhw2rHaGFfS4BO2FFPbSoNgn6STVqdA/wrD0XMWWXkVgZBf2sDXpSLFuwasrViYkI
QqT7BBcfS+xn848hvoIPw5QGsu4MSOUixL4IRr3yCwYXGehJsZoZO/oIq2Y7gp64BafE3sIA8VFk18Xh
TnUY4sqvcBKRPB7ihjTyJsFg7w3zDvSzn5hgJkX656hdggDx4cUA8RHykDcC8rxxozgYma+ToBpVQKbI
R8bHJAiqo6EnAh35N7REQNudRKD0rHApp5de3qQxtOjg6Blfwv3adKSSoLAmFrl19/buWGw7DiJo9AhY
24LJI/gfVnaFtH2Cc6IuW2vvwO5BDx+IcdR5IqHJ4o6TItPbp+e2bOYu9aBzeo3C9CqFSTdrFjsH27yF
dsAwNOKkKGrT527LiDvO451Ob8v0F7S2nxQqTP7CRnqPVBd+fxE00j6Clg3f5JYOvyR5Co/H4/0Bl8Sf
DuVD3wEAAAAASUVORK5CYII=
</value>
</data>
<data name="btConf.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
@@ -227,6 +227,9 @@
TgDQASA1MVpwzwAAAABJRU5ErkJggg==
</value>
</data>
<metadata name="dsMSSQL.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>83, 17</value>
</metadata>
<metadata name="toolStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>325, 17</value>
</metadata>
@@ -255,7 +258,7 @@
iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAANSSURBVFhH7djZTxNRGAVw/gjjvq9tVWgBAbUguO+aGE18
8N0XFROj4oYitHbB0haL4i4qGhUTRew27bS1pRSEJ4kkKCZuiRhJpEQE5TjDTKPEpL13TPClJ7nP95e5
c+a7mZRkkklGQu5saSus3RyK3t7UilsbubXhOW6uf46adS24sbYF19c049rqZlxdxa2VEVxZEcHl5U24
c+a7mZRkkklGQu5saSus3RyM3t7UilsbubXhOW6uf46adS24sbYF19c049rqZlxdxa2VEVxZEcHl5U24
VNCEi/lhVC8L40JeI87ncksdQtXSEGxLQji3OIjKnCCs2c9gyeLWogDMmQFUZPijZ9PZfeL2iTPKOJjS
/dCr/L3i9okz2rizKj/KlT6I2yfO/8AZ02iAhLiLBWHY8nwwq12oVLOoyg1JxhlTWXIg6ZOrzGXRer8L
A99+oK3uDSxLGck4w0IKIPGxbmXxZwLVL2HO8UrC6Rd4yYGk75w1n0HP+z6RBwz9HMK9/RGYs33UON18
@@ -267,7 +270,7 @@
3uwUWULamfcoUTwhxhVPc5ADaXC6NDceHGoWWUK6X3+FJrMBGjlDjDsxlQJIijOkeVG1zTvistDPXRYs
613UuONTKIAkOH58aVVPR5aCu27V7A6iVOakxh2bbCcHkuD42WoqcIo0IXwpSmR2SbijkyiAJDh+tpbN
t6Ppdie+9w0ifKsTp+RPJOOOTHxKDiTB8YNft8AzPCFOyh7/05PjcUUTaIAEuESDnxZXNL6BHPg/cIfH
UQA5XHS0cQfG1pP/+uB/5PD/SkYTd3BM/V5x+2SSSYY8KSm/AKb0PpQCSEV4AAAAAElFTkSuQmCC
UQA5XHS0cQfG1pP/+uB/5PD/SkYTd3BM/V5x+2SSSYY8KSm/AHvBPpKbf2MsAAAAAElFTkSuQmCC
</value>
</data>
<data name="toolStripButton4.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
@@ -316,6 +319,9 @@
<metadata name="otEnd.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>493, 17</value>
</metadata>
<metadata name="tam.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>252, 17</value>
</metadata>

View File

@@ -687,7 +687,7 @@ namespace FPJ0000
}
else
{
var dt = Amkor.RestfulService.SPMSIDSearch(sid);
var dt = AmkorRestfulService.SPMSIDSearch(sid);
if (dt.Complete)
{
row.Cells["dvc_spm"].Value = $"{dt.Result.Rows.Count}건";
@@ -734,7 +734,7 @@ namespace FPJ0000
}
else
{
var dt = Amkor.RestfulService.SPMSIDSearch(sid);
var dt = AmkorRestfulService.SPMSIDSearch(sid);
if (dt.Complete)
{
dv1.Rows[e.RowIndex].Cells["dvc_spm"].Value = $"{dt.Result.Rows.Count}건";

View File

@@ -127,6 +127,10 @@
</Compile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Sub\arCtl\arControl.csproj">
<Project>{f31c242c-1b15-4518-9733-48558499fe4b}</Project>
<Name>arControl</Name>
</ProjectReference>
<ProjectReference Include="..\FCM0000\FCM0000.csproj">
<Project>{26982882-c1ff-45f8-861c-d67558725ff1}</Project>
<Name>FCM0000</Name>