C#winform上下班打卡系统Demo
C# winform上下班打卡系统Demo
系统效果如图所示

7个label控件(lblUsername、lblLoggedInEmployeeId、lab_IP、lblCheckOutTime、lblCheckInTime、lab_starttime、lab_endtime)、3个按钮、1个dataGridView控件、2个groupBox控件
C#代码实现
using System;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Windows.Forms;namespace WindowsFormsApp1
{public partial class 员工打卡 : Form{private string loggedInUsername;private string loggedInEmployeeId;private string connectionString = "server=127.0.0.1;uid=sa;pwd=xyz@0123456;database=test";public 员工打卡(string username, string employeeId){InitializeComponent();loggedInUsername = username;loggedInEmployeeId = employeeId;CheckTodaysPunchInRecord();}[DllImport("user32.dll")]public static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);[DllImport("user32.dll")]public static extern bool EnableMenuItem(IntPtr hMenu, uint uIDEnableItem, uint uEnable);// 禁用窗口大小改变private const uint SC_SIZE = 0xF000;private const uint MF_BYCOMMAND = 0x0000;private const uint MF_GRAYED = 0x0001;protected override void OnLoad(EventArgs e){base.OnLoad(e);IntPtr hMenu = GetSystemMenu(this.Handle, false);if (hMenu != IntPtr.Zero){EnableMenuItem(hMenu, SC_SIZE, MF_BYCOMMAND | MF_GRAYED);}}private void 员工打卡_Load(object sender, EventArgs e){lblUsername.Text = "当前登录用户:" + loggedInUsername;lblLoggedInEmployeeId.Text = "工号:" + loggedInEmployeeId.ToString();// 设置日期控件的显示格式为年-月-日startTime.Format = DateTimePickerFormat.Custom;startTime.CustomFormat = "yyyy-MM-dd";// 设置日期控件的显示格式为年-月-日endTime.Format = DateTimePickerFormat.Custom;endTime.CustomFormat = "yyyy-MM-dd";//不显示出dataGridView1的最后一行空白dataGridView1_Result.AllowUserToAddRows = false;// 设置数据和列名居中对齐dataGridView1_Result.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;dataGridView1_Result.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;// 设置列名加粗dataGridView1_Result.ColumnHeadersDefaultCellStyle.Font = new System.Drawing.Font(dataGridView1_Result.ColumnHeadersDefaultCellStyle.Font, FontStyle.Bold);// 设置列宽自适应dataGridView1_Result.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;LoadData();GetIP();}private void GetIP(){// 获取本机IP地址IPHostEntry ipHost = Dns.GetHostEntry(Dns.GetHostName());foreach (IPAddress ip in ipHost.AddressList){if (ip.AddressFamily == AddressFamily.InterNetwork){lab_IP.Text = "IP地址:" + ip.ToString(); // 添加到label1的Text属性中}}}private void btnCheckIn_Click(object sender, EventArgs e){if (IsPunchInRecordExists()){MessageBox.Show("你已打过上班卡。", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Asterisk);return;}DateTime currentTime = DateTime.Now;string punchInTime = currentTime.ToString("yyyy-MM-dd HH:mm:ss");string status = currentTime.TimeOfDay < new TimeSpan(8, 30, 0) ? "正常" : "迟到";InsertPunchInRecord(punchInTime, status);lblCheckInTime.Text = punchInTime;lblCheckInTime.Visible = true;// 刷新DataGridView显示最新打卡记录RefreshDataGridView();}private bool IsPunchInRecordExists(){DateTime currentDate = DateTime.Now.Date;string query = $"SELECT COUNT(*) FROM PunchIn WHERE emp_code='{loggedInEmployeeId}' AND punch_in_time >= '{currentDate}'";using (SqlConnection connection = new SqlConnection(connectionString)){connection.Open();using (SqlCommand command = new SqlCommand(query, connection)){int count = (int)command.ExecuteScalar();return count > 0;}}}private void RefreshDataGridView(){// 执行查询语句string query = $@"SELECT a.id,a1.username AS 用户名,a.emp_code AS 工号,CONVERT(VARCHAR(19), a.punch_in_time, 120) AS 上班打卡时间,a.status AS 上班打卡状态,CONVERT(VARCHAR(19), b.punch_out_time, 120) AS 下班打卡时间,b.status AS 下班打卡状态FROM (SELECT * FROM Employee) a1LEFT JOIN PunchIn a ON a1.emp_code = a.emp_codeLEFT JOIN PunchOut b ON a.emp_code = b.emp_code AND CONVERT(DATE, a.punch_in_time) = CONVERT(DATE, b.punch_out_time)AND b.punch_out_time = (SELECT MAX(punch_out_time)FROM PunchOutWHERE emp_code = a.emp_code AND CONVERT(DATE, punch_out_time) = CONVERT(DATE, a.punch_in_time))WHERE a.emp_code = '{loggedInEmployeeId}' AND MONTH(a.punch_in_time) = MONTH(GETDATE()) AND YEAR(a.punch_in_time) = YEAR(GETDATE())ORDER BY a.id, a.emp_code, a.punch_in_time";Console.WriteLine("执行的SQL语句是:" + query);// 执行查询并获取结果// 你可以使用适合你数据库的查询方法DataTable dataTable = ExecuteQuery(query);// 将查询结果绑定到DataGridView的数据源dataGridView1_Result.DataSource = dataTable;}private DataTable ExecuteQuery(string query){// 创建连接和命令对象并执行查询using (SqlConnection connection = new SqlConnection(connectionString)){connection.Open();using (SqlCommand command = new SqlCommand(query, connection)){// 创建适配器并填充数据到DataTableSqlDataAdapter adapter = new SqlDataAdapter(command);DataTable dataTable = new DataTable();adapter.Fill(dataTable);return dataTable;}}}private void InsertPunchInRecord(string punchInTime, string status){string query = $"INSERT INTO PunchIn (emp_code, punch_in_time, status) VALUES ('{loggedInEmployeeId}', '{punchInTime}', '{status}')";using (SqlConnection connection = new SqlConnection(connectionString)){connection.Open();using (SqlCommand command = new SqlCommand(query, connection)){command.ExecuteNonQuery();}}}private void CheckTodaysPunchInRecord(){DateTime currentDate = DateTime.Now.Date;string query = $"SELECT punch_in_time FROM PunchIn WHERE emp_code='{loggedInEmployeeId}' AND punch_in_time >= '{currentDate}'";using (SqlConnection connection = new SqlConnection(connectionString)){connection.Open();using (SqlCommand command = new SqlCommand(query, connection)){object result = command.ExecuteScalar();if (result != null){string punchInTime = ((DateTime)result).ToString("yyyy-MM-dd HH:mm:ss");lblCheckInTime.Text = punchInTime;lblCheckInTime.Visible = true;}}}}private void btnCheckOut_Click(object sender, EventArgs e){DateTime currentTime = DateTime.Now;string punchOutTime = currentTime.ToString("yyyy-MM-dd HH:mm:ss");if (IsInvalidPunchOutTime(currentTime)){MessageBox.Show("21点30到23:59:59点打下班卡无效。");return;}string status = currentTime.TimeOfDay < new TimeSpan(18, 0, 0) ? "早退" : "正常"; // 判断下班打卡时间是否在18:00之前InsertPunchOutRecord(punchOutTime, status);lblCheckOutTime.Text = punchOutTime;lblCheckOutTime.Visible = true;// 刷新DataGridView显示最新打卡记录RefreshDataGridView();}private bool IsInvalidPunchOutTime(DateTime currentTime){TimeSpan startTime = new TimeSpan(21, 30, 0);TimeSpan endTime = new TimeSpan(23, 59, 59);TimeSpan currentTimeOfDay = currentTime.TimeOfDay;return currentTimeOfDay >= startTime && currentTimeOfDay <= endTime;}private void InsertPunchOutRecord(string punchOutTime, string status){string query = $"INSERT INTO PunchOut (emp_code, punch_out_time, status) VALUES ('{loggedInEmployeeId}', '{punchOutTime}', '{status}')";using (SqlConnection connection = new SqlConnection(connectionString)){connection.Open();using (SqlCommand command = new SqlCommand(query, connection)){command.ExecuteNonQuery();}}}private void btn_Serch_Click(object sender, EventArgs e){// 获取所选时间范围DateTime startDate = startTime.Value.Date;DateTime endDate = endTime.Value.Date.AddDays(1).AddSeconds(-1);// 构建 SQL 查询语句string query = $@"SELECT a.id,a1.username AS 用户名,a.emp_code AS 工号,CONVERT(VARCHAR(19), a.punch_in_time, 120) AS 上班打卡时间,a.status AS 上班打卡状态,CONVERT(VARCHAR(19), b.punch_out_time, 120) AS 下班打卡时间,b.status AS 下班打卡状态FROM (SELECT * FROM Employee) a1LEFT JOIN PunchIn a ON a1.emp_code = a.emp_codeLEFT JOIN PunchOut b ON a.emp_code = b.emp_code AND CONVERT(DATE, a.punch_in_time) = CONVERT(DATE, b.punch_out_time)AND b.punch_out_time = (SELECT MAX(punch_out_time)FROM PunchOutWHERE emp_code = a.emp_code AND CONVERT(DATE, punch_out_time) = CONVERT(DATE, a.punch_in_time))WHERE a.punch_in_time BETWEEN @StartDate AND @EndDateAND a.emp_code = '{loggedInEmployeeId}'ORDER BY a.id, a.emp_code, a.punch_in_time";using (SqlConnection connection = new SqlConnection(connectionString)){using (SqlCommand command = new SqlCommand(query, connection)){// 添加查询参数command.Parameters.AddWithValue("@StartDate", startDate);command.Parameters.AddWithValue("@EndDate", endDate);Console.WriteLine("查询的SQL语句:" + query);// 打开数据库连接connection.Open();// 创建数据适配器和数据表SqlDataAdapter adapter = new SqlDataAdapter(command);DataTable table = new DataTable();// 填充数据表adapter.Fill(table);// 关闭数据库连接connection.Close();// 绑定数据表到 DataGridView 控件dataGridView1_Result.DataSource = table;}}}private void LoadData(){// 获取所选时间范围DateTime startDate = startTime.Value.Date;DateTime endDate = endTime.Value.Date.AddDays(1).AddSeconds(-1);string query = $@"SELECT a.id,a1.username AS 用户名,a.emp_code AS 工号,CONVERT(VARCHAR(19), a.punch_in_time, 120) AS 上班打卡时间,a.status AS 上班打卡状态,CONVERT(VARCHAR(19), b.punch_out_time, 120) AS 下班打卡时间,b.status AS 下班打卡状态FROM (SELECT * FROM Employee) a1LEFT JOIN PunchIn a ON a1.emp_code = a.emp_codeLEFT JOIN PunchOut b ON a.emp_code = b.emp_code AND CONVERT(DATE, a.punch_in_time) = CONVERT(DATE, b.punch_out_time)AND b.punch_out_time = (SELECT MAX(punch_out_time)FROM PunchOutWHERE emp_code = a.emp_code AND CONVERT(DATE, punch_out_time) = CONVERT(DATE, a.punch_in_time))WHERE a.punch_in_time BETWEEN @StartDate AND @EndDateAND a.emp_code = '{loggedInEmployeeId}'ORDER BY a.id, a.emp_code, a.punch_in_time";Console.WriteLine("开始时间:" + startDate);Console.WriteLine("结束时间:" + endDate);using (SqlConnection connection = new SqlConnection(connectionString)){using (SqlCommand command = new SqlCommand(query, connection)){// 添加查询参数command.Parameters.AddWithValue("@StartDate", startDate);command.Parameters.AddWithValue("@EndDate", endDate);Console.WriteLine("一加载时获取数据查询的SQL语句:" + query);// 打开数据库连接connection.Open();// 创建数据适配器和数据表SqlDataAdapter adapter = new SqlDataAdapter(command);DataTable table = new DataTable();// 填充数据表adapter.Fill(table);// 关闭数据库连接connection.Close();// 绑定数据表到 DataGridView 控件dataGridView1_Result.DataSource = table;}}}}
}相关文章:
C#winform上下班打卡系统Demo
C# winform上下班打卡系统Demo 系统效果如图所示 7个label控件(lblUsername、lblLoggedInEmployeeId、lab_IP、lblCheckOutTime、lblCheckInTime、lab_starttime、lab_endtime)、3个按钮、1个dataGridView控件、2个groupBox控件 C#代码实现 using System; using System.Dat…...
P1 Qt的认识及环境配置
目录 前言 01 下载Qt Creator windows下载安装包拷贝到Linux Linux直接下载 02 Linux 安装Qt 前言 🎬 个人主页:ChenPi 🐻推荐专栏1: 《C_ChenPi的博客-CSDN博客》✨✨✨ 🔥 推荐专栏2: 《Linux C应用编程(概念类…...
单元测试Nunit的几种断言
Nunit提供了一些辅助函数用于确定好某个被测试函数是否正常工作。通常把这些函数称为断言 断言是单元测试最基本的组成部分。因此,NUnit程序库以Assert类的静态方法的形式提供了不同形式的多种断言 1. Assert.AreEqual:比较两个值是否相等。用于比较数…...
前端中的响应式布局与各个端适配
什么是响应式布局? 响应式布局指的是同一页面在不同屏幕尺寸下有不同的布局。在移动互联网高度发达的今天,我们在桌面浏览器上开发的网页已经无法满足在移动设备上查看的需求。传统的开发方式是PC端开发一套页面,手机端再开发一套页面。但是…...
2023年5个自动化EDA库推荐
EDA或探索性数据分析是一项耗时的工作,但是由于EDA是不可避免的,所以Python出现了很多自动化库来减少执行分析所需的时间。EDA的主要目标不是制作花哨的图形或创建彩色的图形,而是获得对数据集的理解,并获得对变量之间的分布和相关…...
7-1 查找书籍
给定n本书的名称和定价,本题要求编写程序,查找并输出其中定价最高和最低的书的名称和定价。 输入格式: 输入第一行给出正整数n(<10),随后给出n本书的信息。每本书在一行中给出书名,即长度不超过30的字…...
【无线网络技术】——无线广域网(学习笔记)
📖 前言:无线广域网(WWAN)是指覆盖全国或全球范围内的无线网络,提供更大范围内的无线接入,与无线个域网、无线局域网和无线城域网相比,它更加强调的是快速移动性。典型的无线广域网:蜂窝移动通信系统和卫星…...
【java+vue+微信小程序项目】从零开始搭建——健身房管理平台(2)后端跨域、登录模块、springboot分层架构、IDEA修改快捷键、vue代码风格
项目笔记为项目总结笔记,若有错误欢迎指出哟~ 【项目专栏】 【java+vue+微信小程序项目】从零开始搭建——健身房管理平台(1)spring boot项目搭建、vue项目搭建、微信小程序项目搭建 【java+vue+微信小程序项目】从零开始搭建——健身房管理平台(2)后端跨域、登录模块、sp…...
NGINX相关配置
全局配置 NGINX配置信息 nginx 官方帮助文档:http://nginx.org/en/docs/Nginx的配置文件的组成部分: 主配置文件:/conf/nginx.conf(/nginx/conf/nginx.conf) 子配置文件: include conf.d/*.conf#事件驱动相关的配置 同步 event { worker_…...
如何将idea中导入的文件夹中的项目识别为maven项目
问题描述 大家经常遇到导入某个文件夹的时候,需要将某个子文件夹识别为maven项目 解决方案...
CleanMyMac4.16中文最新版本下载
当很多人还在为电脑运行缓慢、工作问题不能快速得到解决而烦恼的时候,我已经使用过了多款系统清理工具,并找到了最适合我的那一款。我的电脑是超耐用的Mac book,接下来给大家介绍三种在众多苹果电脑清理软件的排名较高的软件。 一、Maintena…...
谷歌正式发布最强 AI 模型 Gemini
2023年12月6日,谷歌公司宣布推出其被认为是规模最大、功能最强大的人工智能模型 Gemini。 Gemini将分为三个不同的套件:Gemini Ultra、Gemini Pro和Gemini Nano。 Gemini Ultra被认为具备最强大的能力,Gemini Pro则可扩展至多任务&#x…...
无人机语音中继电台 U-ATC118
简介 甚高频无线电中继通讯系统使用经过适航认证的机载电台连接数字网络传输模块,通过网络远程控制无缝实现无人机操作员与塔台直接语音通话。无人机操作员可以从地面控制站远程操作机载电台进行频率切换、静噪开关、PTT按钮,电台虚拟面板与真实面板布局…...
两种测量方式的自适应卡尔曼滤波数据融合
文章目录 测试效果代码CMakeLists.txt参考测试效果 代码 #include <iostream> #include <Eigen/Dense> #include...
.Net6支持的操作系统版本(.net8已来,你还在用.netframework4.5吗)
机缘 不知不觉,.NET8都已经面世,而我们一直还停留在.netframework4.5开发阶段,最近准备抽空研究一下.Net6,一是为了提高技术积累,一方面想着通过这次的学习,看有没有可能将老的FX版本替换到.Net6开发上,经过查找官方资料,对.Net6支持的系统版本做一个分享,方便大家后期…...
CopyOnWriteArraySet怎么用
简介 CopyOnWriteArraySet是一个线程安全的无序集合,它基于“写时复制”的思想实现。它继承自AbstractSet,可以将其理解成线程安全的HashSet。 CopyOnWriteArraySet在读取操作比较频繁、写入操作相对较少的情况下可以提高程序的性能和可靠性。它的线程…...
uniapp得app云打包问题
获取appid,具体可以查看详情 也可以配置图标,获取直接生成即可 发行 打包配置 自有证书测试使用时候不需要使用 编译打包 最后找到安装包apk安装到手机 打包前,图片命名使用要非中文,否则无法打包成功会报错...
Linux bin包生成
需求背景: 在实际项目时我们很少把源码用个tar给到客户,这样显得很不专业,且有的时候我们提供补丁,那么这个时候我们提供一个补丁的bin包可以直接安装运行就显得很高大上了。 物料准备 准备一台liunx,虚拟机亦可&am…...
Java多人聊天
服务端 import java.io.*; import java.net.*; import java.util.ArrayList; public class Server{public static ServerSocket server_socket;public static ArrayList<Socket> socketListnew ArrayList<Socket>(); public static void main(String []args){try{…...
自动驾驶:传感器初始标定
手眼标定 机器人手眼标定AxxB(eye to hand和eye in hand)及平面九点法标定 Ax xB问题求解,旋转和平移分步求解法 手眼标定AXXB求解方法(文献总结) 基于靶的方法 相机标定 (1) ApriTag (2) 棋盘格:cv::f…...
观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
【Python】 -- 趣味代码 - 小恐龙游戏
文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...
Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...
DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...
【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...
USB Over IP专用硬件的5个特点
USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...
云原生玩法三问:构建自定义开发环境
云原生玩法三问:构建自定义开发环境 引言 临时运维一个古董项目,无文档,无环境,无交接人,俗称三无。 运行设备的环境老,本地环境版本高,ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...
