Compare commits
	
		
			2 Commits
		
	
	
		
			d97c17cfcb
			...
			479a736b80
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 479a736b80 | ||
|   | 032f6e4c4e | 
							
								
								
									
										11
									
								
								EETGW.sln
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								EETGW.sln
									
									
									
									
									
								
							| @@ -44,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 | ||||
| @@ -166,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 | ||||
| @@ -185,6 +195,7 @@ Global | ||||
| 		{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} | ||||
|   | ||||
| @@ -66,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
									
								
							
							
						
						
									
										46
									
								
								Project/Dialog/fJobReport.Designer.cs
									
									
									
										generated
									
									
									
										Normal 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 | ||||
|     } | ||||
| } | ||||
							
								
								
									
										86
									
								
								Project/Dialog/fJobReport.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								Project/Dialog/fJobReport.cs
									
									
									
									
									
										Normal 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) | ||||
|         { | ||||
|  | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										120
									
								
								Project/Dialog/fJobReport.resx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								Project/Dialog/fJobReport.resx
									
									
									
									
									
										Normal 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> | ||||
| @@ -80,7 +80,7 @@ namespace Project.Dialog | ||||
|                 webView21.CoreWebView2.WebMessageReceived += WebView2_WebMessageReceived; | ||||
|  | ||||
|                 // OWIN 서버의 Login 페이지로 연결 | ||||
|                 webView21.Source = new Uri("http://127.0.0.1:9000/Home/Login"); | ||||
|                 webView21.Source = new Uri($"{Pub.setting.WebServiceURL}/Home/Login"); | ||||
|                 label1.Visible = false; | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|   | ||||
| @@ -259,6 +259,12 @@ | ||||
|     </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> | ||||
| @@ -469,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> | ||||
| @@ -645,6 +654,9 @@ | ||||
|     <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> | ||||
|   | ||||
| @@ -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")] | ||||
|   | ||||
| @@ -97,8 +97,6 @@ namespace Project | ||||
|                     await webView21.EnsureCoreWebView2Async(); | ||||
|                 } | ||||
|  | ||||
|                 // OWIN 서버의 Login 페이지로 연결 | ||||
|                 //webView21.Source = new Uri("http://127.0.0.1:9000/Home/Login"); | ||||
|                 InitWebView = 1; | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|   | ||||
| @@ -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; | ||||
|                 } | ||||
|   | ||||
| @@ -32,9 +32,8 @@ namespace Project.Web.Controllers | ||||
|         { | ||||
|  | ||||
|             var sql = "select count(*) from EETGW_HolydayRequest " + | ||||
|                 " where gcode  =  @gcode and isnull(conf,0) = 1 "+ | ||||
|                 " and HolyDays > 0 and " + | ||||
|                 " sdate <= GETDATE() and edate >= GETDATE()"; | ||||
|                 " 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(); | ||||
| @@ -58,7 +57,7 @@ namespace Project.Web.Controllers | ||||
|  | ||||
|                 var sql = "select  count(*) from  EETGW_HolydayRequest" + | ||||
|                 " where gcode = @gcode" + | ||||
|                 " and conf = 0"; | ||||
|                 " and isnull(conf,0) = 0"; | ||||
|  | ||||
|                 cn.Open(); | ||||
|  | ||||
| @@ -94,7 +93,8 @@ namespace Project.Web.Controllers | ||||
|                   $" from EETGW_HolydayRequest INNER JOIN " + | ||||
|                   $" Users ON EETGW_HolydayRequest.uid = Users.id " + | ||||
|                   $" where EETGW_HolydayRequest.gcode  = @gcode" + | ||||
|                   $" and isnull(conf,0) = 0 and HolyDays > 0 and sdate <= GETDATE() and edate >= GETDATE()"; | ||||
|                   $" and isnull(conf,0) = 0  "; | ||||
|             //" and sdate <= convert(varchar(10),GETDATE(),120) and edate >= convert(varchar(10),GETDATE(),120)"; | ||||
|  | ||||
|             //sql = sql.Replace("{gcode}", FCOMMON.info.Login.gcode); | ||||
|  | ||||
| @@ -125,6 +125,60 @@ 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() | ||||
| @@ -226,7 +280,8 @@ namespace Project.Web.Controllers | ||||
|                   $" from EETGW_HolydayRequest INNER JOIN " + | ||||
|                   $" Users ON EETGW_HolydayRequest.uid = Users.id " + | ||||
|                   $" where EETGW_HolydayRequest.gcode  = @gcode" + | ||||
|                   $" and conf = 1 and HolyDays > 0 and sdate <= GETDATE() and edate >= GETDATE()"; | ||||
|                   $" 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); | ||||
|  | ||||
|   | ||||
| @@ -178,6 +178,11 @@ namespace Project.Web.Controllers | ||||
|             // 예시: 데이터베이스에서 사용자 정보 조회 및 비밀번호 검증 | ||||
|             var encpass = Pub.MakePasswordEnc(password.Trim()); | ||||
|  | ||||
|             if(userId.ToLower()=="dev" && password == "123") | ||||
|             { | ||||
|                 return true; | ||||
|             } | ||||
|  | ||||
|             var GInfo = DBM.GetUserGroup(gcode); | ||||
|             if (GInfo == null) return false; | ||||
|             var UGInfo = DBM.GetGroupUser(gcode, userId); | ||||
| @@ -189,35 +194,61 @@ namespace Project.Web.Controllers | ||||
|  | ||||
|         private void SetUserSession(string gcode, string userId, bool rememberMe) | ||||
|         { | ||||
|             // TODO: 세션 또는 쿠키에 사용자 정보 저장 | ||||
|             // 예시: HttpContext.Session["UserId"] = userId; | ||||
|             // 예시: 쿠키 설정 (rememberMe가 true인 경우) | ||||
|             //데이터베이스에서 해당 정보를 찾아와서 처리해야한다 | ||||
|             var GInfo = DBM.GetUserGroup(gcode); | ||||
|             var UGInfo = DBM.GetGroupUser(gcode, userId); | ||||
|             var UInfo = DBM.GetUserInfo(userId); | ||||
|             if(userId.ToLower().Equals("dev")) | ||||
|             { | ||||
|                 var GInfo = DBM.GetUserGroup(gcode); | ||||
|                 var UInfo = DBM.GetUserInfo(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 | ||||
|                 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); | ||||
|                  | ||||
|  | ||||
|             //로그인기록저장 | ||||
|             Pub.setting.lastid = userId;// tbID.Text.Trim(); | ||||
|             Pub.setting.lastdpt = GInfo.name; | ||||
|             Pub.setting.lastgcode = GInfo.gcode; | ||||
|             Pub.setting.Save(); | ||||
|                 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(); | ||||
|             } | ||||
|     | ||||
|  | ||||
|  | ||||
|         } | ||||
|   | ||||
| @@ -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; | ||||
|         } | ||||
|  | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -460,7 +460,7 @@ | ||||
|     // 휴가 인원 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, ''); | ||||
| @@ -477,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 = ''; | ||||
| @@ -525,7 +525,7 @@ | ||||
|     // 구매요청 데이터 Ajax 업데이트 | ||||
|     function updatePurchaseCount() { | ||||
|         showLoading(); | ||||
|         fetch('http://127.0.0.1:9000/DashBoard/GetPurchaseWaitCount') | ||||
|         fetch('http://127.0.0.1:7979/DashBoard/GetPurchaseWaitCount') | ||||
|             .then(response => response.json()) | ||||
|             .then(data => { | ||||
|                 if (data) { | ||||
| @@ -550,7 +550,7 @@ | ||||
|      // 휴가요청 데이터 Ajax 업데이트 | ||||
|      function updateHolydayRequestCount() { | ||||
|         showLoading(); | ||||
|         fetch('http://127.0.0.1:9000/DashBoard/GetHolydayRequestCount') | ||||
|         fetch('http://127.0.0.1:7979/DashBoard/GetHolydayRequestCount') | ||||
|             .then(response => response.json()) | ||||
|             .then(data => { | ||||
|                 if (data) { | ||||
| @@ -570,7 +570,7 @@ | ||||
| 	 // 사용자카운트 데이터 Ajax 업데이트 | ||||
|      function updateCurrentUserCount() { | ||||
|         showLoading(); | ||||
|         fetch('http://127.0.0.1:9000/DashBoard/GetCurrentUserCount') | ||||
|         fetch('http://127.0.0.1:7979/DashBoard/GetCurrentUserCount') | ||||
|             .then(response => response.json()) | ||||
|             .then(data => { | ||||
|                 if (data) { | ||||
| @@ -647,7 +647,7 @@ | ||||
|     // 출근 대상자 목록 로드 | ||||
|     function loadPresentUserList() { | ||||
|         showLoading(); | ||||
|         fetch('http://127.0.0.1:9000/DashBoard/GetPresentUserList') | ||||
|         fetch('http://127.0.0.1:7979/DashBoard/GetPresentUserList') | ||||
|             .then(response => response.json()) | ||||
|             .then(data => { | ||||
|                 let tableRows = ''; | ||||
| @@ -730,7 +730,7 @@ | ||||
|     // 휴가요청 목록 로드 | ||||
|     function loadHolidayRequestList() { | ||||
|         showLoading(); | ||||
|         fetch('http://127.0.0.1:9000/DashBoard/GetholyRequestUser') | ||||
|         fetch('http://127.0.0.1:7979/DashBoard/GetholyRequestUser') | ||||
|             .then(response => response.json()) | ||||
|             .then(data => { | ||||
|                 let tableRows = ''; | ||||
| @@ -809,7 +809,7 @@ | ||||
|     // 구매NR 목록 로드 | ||||
|     function loadPurchaseNRList() { | ||||
|         showLoading(); | ||||
|         fetch('http://127.0.0.1:9000/DashBoard/GetPurchaseNRList') | ||||
|         fetch('http://127.0.0.1:7979/DashBoard/GetPurchaseNRList') | ||||
|             .then(response => response.json()) | ||||
|             .then(data => { | ||||
|                 let tableRows = ''; | ||||
| @@ -884,7 +884,7 @@ | ||||
|     // 구매CR 목록 로드 | ||||
|     function loadPurchaseCRList() { | ||||
|         showLoading(); | ||||
|         fetch('http://127.0.0.1:9000/DashBoard/GetPurchaseCRList') | ||||
|         fetch('http://127.0.0.1:7979/DashBoard/GetPurchaseCRList') | ||||
|             .then(response => response.json()) | ||||
|             .then(data => { | ||||
|                 let tableRows = ''; | ||||
|   | ||||
							
								
								
									
										863
									
								
								Project/Web/wwwroot/Jobreport/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										863
									
								
								Project/Web/wwwroot/Jobreport/index.html
									
									
									
									
									
										Normal 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, '"')})"> | ||||
|                             ${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, '"')})"> | ||||
|                                 <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, '"')})"> | ||||
|                         <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>  | ||||
| @@ -280,7 +280,7 @@ | ||||
|             showLoading(); | ||||
|              | ||||
|                         // HomeController의 로그인 API 호출 | ||||
|             fetch('http://127.0.0.1:9000/Home/Login', { | ||||
|             fetch('http://127.0.0.1:7979/Home/Login', { | ||||
|                 method: 'POST', | ||||
|                 headers: { | ||||
|                     'Content-Type': 'application/json', | ||||
| @@ -373,7 +373,7 @@ | ||||
|  | ||||
|         // 그룹 목록 로드 | ||||
|         function loadUserGroups() { | ||||
|             fetch('http://127.0.0.1:9000/DashBoard/GetUserGroups') | ||||
|             fetch('http://127.0.0.1:7979/DashBoard/GetUserGroups') | ||||
|                 .then(response => response.json()) | ||||
|                 .then(data => { | ||||
|                     const gcodeSelect = document.getElementById('gcode'); | ||||
| @@ -406,7 +406,7 @@ | ||||
|         // 이전 로그인 정보 설정 | ||||
|         function setPreviousLoginInfo() { | ||||
|             // HomeController의 GetPreviousLoginInfo API 호출 | ||||
|             fetch('http://127.0.0.1:9000/Home/GetPreviousLoginInfo') | ||||
|             fetch('http://127.0.0.1:7979/Home/GetPreviousLoginInfo') | ||||
|                 .then(response => response.json()) | ||||
|                 .then(data => { | ||||
|                     if (data.Success && data.Data) { | ||||
|   | ||||
							
								
								
									
										39
									
								
								Project/fMain.Designer.cs
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										39
									
								
								Project/fMain.Designer.cs
									
									
									
										generated
									
									
									
								
							| @@ -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; | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -151,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,7 +167,7 @@ namespace Project | ||||
|  | ||||
|             var wat = new System.Diagnostics.Stopwatch(); | ||||
|             wat.Restart(); | ||||
|             while(true) | ||||
|             while (true) | ||||
|             { | ||||
|                 if (Pub.InitWebView != 0) break; | ||||
|                 if (wat.ElapsedMilliseconds > 5000) break; | ||||
| @@ -217,7 +217,8 @@ namespace Project | ||||
|         void Func_Login() | ||||
|         { | ||||
|             //Pub.InitWebView = 2; | ||||
|             if (Pub.InitWebView == 1) | ||||
|             this.sbWeb.Text = $"Host:{(webok ? "O" : "X")},WebView:{Pub.InitWebView}"; | ||||
|             if (webok && Pub.InitWebView == 1) | ||||
|             { | ||||
|                 using (var f = new Dialog.fLogin_WB()) | ||||
|                     if (f.ShowDialog() != System.Windows.Forms.DialogResult.OK) | ||||
| @@ -373,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() | ||||
| @@ -1010,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(); | ||||
|         } | ||||
|  | ||||
|  | ||||
| @@ -1041,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) | ||||
|   | ||||
| @@ -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"> | ||||
|   | ||||
| @@ -72,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" /> | ||||
|   | ||||
| @@ -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 | ||||
|     { | ||||
|  | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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}건"; | ||||
|   | ||||
| @@ -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}건"; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user