一、考勤系統(tǒng)需求分析
1.背景
隨著信息技術(shù)的高速發(fā)展,各行各業(yè)都充分利用信息平臺(tái)提高自己的管理效率。當(dāng)今國(guó)內(nèi)各企業(yè)已紛紛建立企業(yè)局域網(wǎng),依托局域網(wǎng)使用各種信息管理系統(tǒng),使管理效率顯著提高。
2.系統(tǒng)目標(biāo)
該系統(tǒng)將實(shí)現(xiàn)五大功能(登陸功能、注冊(cè)功能、打卡功能、查詢功能、統(tǒng)計(jì)功能),將使考勤管理更加系統(tǒng)化、信息化、高效化、準(zhǔn)確化,讓管理更上一層臺(tái)階;同時(shí)滿足快速有效的打卡需求,提高員工的出勤率以及積極性。
3.功能需求
各大功能模塊
- 登陸功能模塊
- 注冊(cè)功能模塊
- 打卡功能模塊
- 查詢功能模塊
- 統(tǒng)計(jì)功能模塊
功能模塊圖

4.非功能需求
非功能性需求是指除功能性需求以外的所有需求,一般分為部署環(huán)境需求,接口需求,安全需求,性能需求,界面需求。
(1)部署環(huán)境需求:部署環(huán)境一般是指客戶所在公司或者部門的IT環(huán)境,電腦系統(tǒng)環(huán)境,與該軟件相關(guān)的構(gòu)件。
(2)接口需求:數(shù)據(jù)通信協(xié)議,比如TCP/IP、UDP協(xié)議等。
(3)安全需求:該系統(tǒng)對(duì)安全性需求不高,能保證數(shù)據(jù)不丟失則行。
(4)性能需求:至少可以允許同一個(gè)時(shí)間20個(gè)用戶訪問系統(tǒng)。查詢服務(wù)用戶通過電腦提交命令道返回結(jié)果不超過2秒鐘。具有較高的穩(wěn)定性
(5)界面需求:界面設(shè)計(jì)應(yīng)該簡(jiǎn)潔易懂,該部分需求應(yīng)該不斷優(yōu)化,直至符合用戶習(xí)慣。
5.軟件與硬件
系統(tǒng)拓?fù)鋱D

6.設(shè)計(jì)和實(shí)現(xiàn)的限制
對(duì)于一個(gè)現(xiàn)代化的考勤來說,考勤管理是必須的。如何把每天發(fā)生的考勤信息如實(shí)地記錄下來,保證考勤工作有條理地進(jìn)行,同時(shí)確保相關(guān)數(shù)據(jù)的安全,信息處理的高效,并且保證系統(tǒng)的實(shí)用性強(qiáng)。詳細(xì)設(shè)計(jì)階段的根本目標(biāo)是確定應(yīng)該怎樣具體的實(shí)現(xiàn)所要求的系統(tǒng),也就是說,經(jīng)過這個(gè)階段的設(shè)計(jì)工作,應(yīng)該得出目標(biāo)系統(tǒng)的精確描述,從而在編碼階段可以把這個(gè)描述直接翻譯成用某總程序設(shè)計(jì)語言書寫的程序。詳細(xì)設(shè)計(jì)的目標(biāo)不僅僅是邏輯上正確地實(shí)現(xiàn)每個(gè)模塊的功能,更重要的是設(shè)計(jì)的處理過程應(yīng)該盡可能簡(jiǎn)明易懂。
- 設(shè)計(jì)限制
- 系統(tǒng)體系結(jié)構(gòu)的搭建
- 開發(fā)軟件,包括:ASP、IIS、SQL Server、Dreamweaver
- 數(shù)據(jù)庫(kù)的設(shè)計(jì),包括:概念結(jié)構(gòu)設(shè)計(jì)和邏輯結(jié)構(gòu)設(shè)計(jì)
- 軟硬件平臺(tái)搭建
- 實(shí)現(xiàn)限制
- 登陸功能模塊
- 注冊(cè)功能模塊
- 打卡功能模塊
- 查詢功能模塊
- 統(tǒng)計(jì)功能模塊
二、考勤系統(tǒng)數(shù)據(jù)庫(kù)設(shè)計(jì)
1.標(biāo)識(shí)實(shí)體
- 打卡機(jī)
- 員工
2.E-R圖

3.數(shù)據(jù)表

4.數(shù)據(jù)庫(kù)表
- 一個(gè)數(shù)據(jù)庫(kù):kaoqin
- 三個(gè)表,分別是card_machine(打卡機(jī)表)、worker(員工表)、statistic(打卡信息表)
create DATABASE kaoqin
use kaoqin
create table card_machine(
number varchar(15) primary key,
location varchar(10),
machine_type varchar(10),
methods varchar(10)
)
use kaoqin
create table worker(
number varchar(15) primary key,
gender varchar(10),
age varchar(5),
department varchar(15)
)
use kaoqin
create table statistic(
number varchar(15) primary key,
machine_number varchar(15),
worker_number varchar(15),
shijian varchar(10),
cishu varchar(10),
foreign key(machine_number) references card_machine(number),
foreign key(worker_number) references worker(number)
)
三、考勤系統(tǒng)界面設(shè)計(jì)
1.考勤系統(tǒng)功能實(shí)現(xiàn)——登錄
(1)登錄界面設(shè)計(jì)

(2)登錄界面實(shí)現(xiàn)代碼
- 點(diǎn)擊登錄按鈕實(shí)現(xiàn)登錄功能
// 點(diǎn)擊“登錄”按鈕則登錄系統(tǒng)
private void bt_Login_Click(object sender, EventArgs e)
{
String connStr = ConfigurationManager.ConnectionStrings["Attendance"].ConnectionString;
SqlConnection sqlConn = new SqlConnection(connStr);
try
{
// 連接數(shù)據(jù)庫(kù)
sqlConn.Open();
// 構(gòu)造命令發(fā)送給數(shù)據(jù)庫(kù)
String sqlStr = "select * from employee where ID=@id and PASSWORD=@pwd";
SqlCommand cmd = new SqlCommand(sqlStr, sqlConn);
// 注意是用用戶ID登錄,而不是用戶名,用戶名可能會(huì)重復(fù)
cmd.Parameters.Add(new SqlParameter("@id", this.tb_User.Text.Trim()));
cmd.Parameters.Add(new SqlParameter("@pwd", this.tb_Password.Text.Trim()));
SqlDataReader dr = cmd.ExecuteReader();
// 如果從數(shù)據(jù)庫(kù)中查詢到記錄,則表示可以登錄
if (dr.HasRows)
{
dr.Read();
WorkerInfo.userPwd = dr["PASSWORD"].ToString();
WorkerInfo.userId = dr["ID"].ToString();
WorkerInfo.userDepartment = dr["department"].ToString();
WorkerInfo.userGender = dr["gender"].ToString();
WorkerInfo.userAuthority = dr["authority"].ToString();
WorkerInfo.userName = dr["name"].ToString()
MessageBox.Show(WorkerInfo.userAuthority + "登錄成功");
if (WorkerInfo.userAuthority == "common")
{
// 顯示普通員工員主界面
MainFormUser formUser = new MainFormUser();
formUser.Show();
// 隱藏登錄界面
this.Hide();
}
if (WorkerInfo.userAuthority == "manager")
{
// 顯示庫(kù)管員主界面
MainFormAdmin formAdmin = new MainFormAdmin();
formAdmin.Show();
// 隱藏登錄界面
this.Hide();
}
}
else
{
MessageBox.Show("用戶名或密碼錯(cuò)誤", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
catch (Exception exp)
{
MessageBox.Show("訪問數(shù)據(jù)庫(kù)錯(cuò)誤:" + exp.Message);
}
finally
{
sqlConn.Close();
}
}
2.考勤系統(tǒng)功能實(shí)現(xiàn)——注冊(cè)
1.員工注冊(cè)界面設(shè)計(jì)

2.注冊(cè)界面實(shí)現(xiàn)代碼
- 錄入界面加載同時(shí)自動(dòng)給定新員工號(hào)
private void RecordForm2_Load(object sender, EventArgs e)
{
String connStr = ConfigurationManager.ConnectionStrings["Attendance"].ConnectionString;
SqlConnection sqlConn = new SqlConnection(connStr);
try
{
// 連接數(shù)據(jù)庫(kù)
sqlConn.Open();
// 構(gòu)造命令發(fā)送給數(shù)據(jù)庫(kù)
String sqlStr = "select MAX(id+1) as id from employee";
SqlCommand cmd = new SqlCommand(sqlStr, sqlConn);
SqlDataReader dr = cmd.ExecuteReader();
//取出數(shù)據(jù)庫(kù)中的值并賦給文本框
if (dr.HasRows)
{
dr.Read();
this.worker_Id.Text = dr["ID"].ToString();
}
}
catch (Exception exp)
{
MessageBox.Show("訪問數(shù)據(jù)庫(kù)錯(cuò)誤:" + exp.Message);
}
finally
{
sqlConn.Close();
}
}
- 點(diǎn)擊“錄入”按鍵實(shí)現(xiàn)注冊(cè)功能
// 點(diǎn)擊“確認(rèn)”按鈕,則錄入員工
private void bt_Ok_Click(object sender, EventArgs e)
{
String id = this.worker_Id.Text.Trim();
String name = this.worker_Name.Text.Trim();
String gender = this.worker_Gender.Text.Trim();
String department = this.worker_Department.Text.Trim();
String authority = this.worker_Authority.Text.Trim();
String password = this.worker_Password.Text.Trim();
// 更新數(shù)據(jù)庫(kù)
String connStr = ConfigurationManager.ConnectionStrings["Attendance"].ConnectionString;
SqlConnection sqlConn = new SqlConnection(connStr);
try
{
// 連接數(shù)據(jù)庫(kù)
sqlConn.Open();
// 構(gòu)造命令
String sqlStr = "insert into employee(ID, name, gender, department, authority, PASSWORD) values(@id, @name, @gender, @department, @authority, @password)";
SqlCommand cmd = new SqlCommand(sqlStr, sqlConn);
// SQL字符串參數(shù)賦值
cmd.Parameters.Add(new SqlParameter("@id", id));
cmd.Parameters.Add(new SqlParameter("@name", name));
cmd.Parameters.Add(new SqlParameter("@gender",gender ));
cmd.Parameters.Add(new SqlParameter("@department", department));
cmd.Parameters.Add(new SqlParameter("@authority", authority));
cmd.Parameters.Add(new SqlParameter("@password", password));
// 將命令發(fā)送給數(shù)據(jù)庫(kù)
int res = cmd.ExecuteNonQuery();
// 根據(jù)返回值判斷是否插入成功
if (res != 0)
{
MessageBox.Show("員工信息錄入成功");
}
else
{
MessageBox.Show("員工信息錄入失敗");
}
}
catch (Exception exp)
{
MessageBox.Show("訪問數(shù)據(jù)庫(kù)錯(cuò)誤:" + exp.Message);
}
finally
{
sqlConn.Close();
}
}
3.考勤系統(tǒng)功能實(shí)現(xiàn)——打卡
1.打卡界面設(shè)計(jì)

2.打卡界面實(shí)現(xiàn)代碼
- 打開串口
private void buttonOpenCOM_Click(object sender, EventArgs e)
{
// 串口已打開,此時(shí)需要關(guān)閉
if (serialPort1.IsOpen)
{
serialPort1.Close();
this.toolStripStatusLabel1.Text = "已關(guān)閉串口" + serialPort1.PortName.ToString();
buttonOpenCOM.Text = "打開";
return;
}
// 否則打開串口
else
{
serialPort1.PortName = comboBoxCOMList.Text;
InitSerialPort();
try
{
serialPort1.Open();
this.toolStripStatusLabel1.Text = "已打開串口" + serialPort1.PortName.ToString();
buttonOpenCOM.Text = "關(guān)閉";
}
catch (Exception ex)
{
this.toolStripStatusLabel1.Text = "打開串口失敗,原因:" + ex.Message;
return;
}
}
}
- 關(guān)閉串口
private void ServiceForm_FormClosing(object sender, FormClosingEventArgs e)
{
// 如果關(guān)閉窗口時(shí),串口仍然為打開狀態(tài),則需要關(guān)閉串口
if (serialPort1.IsOpen)
{
serialPort1.Close();
}
}
- 向卡片寫入信息
private void bt_Register_Click(object sender, EventArgs e)
{
if (!serialPort1.IsOpen)
{
this.toolStripStatusLabel1.Text = "請(qǐng)先打開串口";
return;
}
this.toolStripStatusLabel1.Text = "未找到有效的卡";
// '666'填充為'00000666'
string stuffId = this.tb_EmployeeId.Text.PadLeft(8, '0');
// '00000666'轉(zhuǎn)變成'66060000'
stuffId = ISO15693CardHandler.CovertEndian(stuffId);
// 檢查輸入數(shù)據(jù)的錯(cuò)誤
// ISO15693為32位,4字節(jié),8字符
if (stuffId.Length != 8)
{
MessageBox.Show("請(qǐng)輸入4字節(jié)的16進(jìn)制數(shù)據(jù)!", "錯(cuò)誤", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
// 檢查16進(jìn)制字符錯(cuò)誤
if (!ISO15693CardHandler.CheckValidHexBytes(stuffId))
{
MessageBox.Show("寫入數(shù)據(jù)的16進(jìn)制格式錯(cuò)誤!", "錯(cuò)誤", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
// [TODO] 尋卡,將RFID卡號(hào)讀出來
if (!serialPort1.IsOpen)
{
MessageBox.Show("串口未打開!", "錯(cuò)誤", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
string response_card = "";
/*
* 每發(fā)送完一個(gè)指令后,睡眠M(jìn)ILLISECOND_IN_SLEEP毫秒,防止數(shù)據(jù)無法正常讀取
*/
serialPort1.Write(ISO15693Card.COMMAND_WRITE_REG);
Thread.Sleep(MILLISECOND_IN_SLEEP);
if (serialPort1.BytesToRead > 0) response_card = serialPort1.ReadExisting();
serialPort1.Write(ISO15693Card.COMMAND_SET_AGC);
Thread.Sleep(MILLISECOND_IN_SLEEP);
if (serialPort1.BytesToRead > 0) response_card = serialPort1.ReadExisting();
serialPort1.Write(ISO15693Card.COMMAND_SET_RECV_MODE);
Thread.Sleep(MILLISECOND_IN_SLEEP);
if (serialPort1.BytesToRead > 0) response_card = serialPort1.ReadExisting();
serialPort1.Write(ISO15693Card.COMMAND_INVEN_CARD);//尋卡
Thread.Sleep(MILLISECOND_IN_SLEEP);
if (serialPort1.BytesToRead > 0) response_card = serialPort1.ReadExisting();//獲取返回的字符串
List<ISO15693Card> cards = ISO15693CardHandler.InventoryCard(response_card);//解析返回的字符串,獲取尋到的卡ID
// [TODO] 向RFID卡第00塊寫入職員編號(hào)數(shù)據(jù),無論成功與否,均應(yīng)該在狀態(tài)欄顯示提示信息
//檢查輸入數(shù)據(jù)的錯(cuò)誤
//ISO15693為32位,4字節(jié),8字符
if (tb_EmployeeId.Text.Length != 8)
{
MessageBox.Show("請(qǐng)輸入4字節(jié)的16進(jìn)制數(shù)據(jù)!", "錯(cuò)誤", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
//檢查16進(jìn)制字符錯(cuò)誤
if (!ISO15693CardHandler.CheckValidHexBytes(tb_EmployeeId.Text))
{
MessageBox.Show("寫入數(shù)據(jù)的16進(jìn)制格式錯(cuò)誤!", "錯(cuò)誤", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
WriteSingleBlock(
ISO15693CardHandler.CovertEndian(cards[0].ID),
"00",
tb_EmployeeId.Text);
}
- 卡片打卡(向數(shù)據(jù)庫(kù)寫入員工號(hào)、日期、時(shí)間等信息)
// [TODO] 向數(shù)據(jù)庫(kù)中插入一條打卡記錄,插入成功后顯示打卡成功
//獲取時(shí)間、日期等數(shù)據(jù);
string date = DateTime.Now.ToString("yyyy-MM-dd");
string time = DateTime.Now.ToString("hh:mm:ss");
// 更新數(shù)據(jù)庫(kù)
String connStr = ConfigurationManager.ConnectionStrings["Attendance"].ConnectionString;
SqlConnection sqlConn = new SqlConnection(connStr);
try
{
// 連接數(shù)據(jù)庫(kù)
sqlConn.Open();
// 構(gòu)造命令
String sqlStr = "insert into record(employee_id, date, time, machine_id) values(@employee_id, @date, @time, @machine_id)";
SqlCommand cmd = new SqlCommand(sqlStr, sqlConn);
// SQL字符串參數(shù)賦值
cmd.Parameters.Add(new SqlParameter("@employee_id", stuffId));
cmd.Parameters.Add(new SqlParameter("@time", time));
cmd.Parameters.Add(new SqlParameter("@date", date));
cmd.Parameters.Add(new SqlParameter("@machine_id", ""));
// 將命令發(fā)送給數(shù)據(jù)庫(kù)
int res = cmd.ExecuteNonQuery();
// 根據(jù)返回值判斷是否插入成功
if (res != 0)
{
MessageBox.Show("打卡成功");
}
else
{
MessageBox.Show("打卡失敗");
}
}
catch (Exception exp)
{
MessageBox.Show("訪問數(shù)據(jù)庫(kù)錯(cuò)誤:" + exp.Message);
}
finally
{
sqlConn.Close();
}
4.考勤系統(tǒng)功能實(shí)現(xiàn)——查詢
1.查詢界面設(shè)計(jì)
-
普通員工查詢界面
普通員工查詢界面
員工查詢 -
管理員查詢界面
管理員查詢界面
管理查詢
2.查詢界面實(shí)現(xiàn)代碼
- 普通員工查詢個(gè)人考勤信息
//點(diǎn)擊查詢,查詢個(gè)人信息
private void button1_Click(object sender, EventArgs e)
{
// 連接字符串,注意與實(shí)際環(huán)境保持一致
String connStr = ConfigurationManager.ConnectionStrings["Attendance"].ConnectionString;
SqlConnection sqlConn = new SqlConnection(connStr);
try
{
// 連接數(shù)據(jù)庫(kù)
sqlConn.Open();
// 構(gòu)造命令
String sqlStr = "select * from record where employee_id = @employee ";
SqlCommand cmd = new SqlCommand(sqlStr, sqlConn);
cmd.Parameters.Add(new SqlParameter("@employee", WorkerInfo.userId));
// 將該查詢過程綁定到DataAdapter
SqlDataAdapter adp = new SqlDataAdapter();
adp.SelectCommand = cmd;
// 將DataSet和DataAdapter綁定
DataSet ds = new DataSet();
// 自定義一個(gè)表(MyGoods)來標(biāo)識(shí)數(shù)據(jù)庫(kù)的record表
adp.Fill(ds, "record");
// 指定DataGridView的數(shù)據(jù)源為DataSet的dgv_kaoqin_m表
this.dgv_kaoqin_m.DataSource = ds.Tables["record"];
}
catch (Exception exp)
{
MessageBox.Show("訪問數(shù)據(jù)庫(kù)錯(cuò)誤:" + exp.Message);
}
finally
{
sqlConn.Close();
}
}
- 管理員查詢所有人員的考勤信息
// 查詢數(shù)據(jù)
private void bt_Query_Click(object sender, EventArgs e)
{
// 連接字符串,注意與實(shí)際環(huán)境保持一致
String connStr = ConfigurationManager.ConnectionStrings["Attendance"].ConnectionString;
SqlConnection sqlConn = new SqlConnection(connStr);
try
{
// 連接數(shù)據(jù)庫(kù)
sqlConn.Open();
// 構(gòu)造命令
//符合員工號(hào)查詢
if (tb_Id.Text.Trim() != "")
{
String sqlStr = "select * from record where employee_id=@id";
SqlCommand cmd = new SqlCommand(sqlStr, sqlConn);
cmd.Parameters.Add(new SqlParameter("@id", this.tb_Id.Text.Trim()));
// 將該查詢過程綁定到DataAdapter
SqlDataAdapter adp = new SqlDataAdapter();
adp.SelectCommand = cmd;
// 將DataSet和DataAdapter綁定
DataSet ds = new DataSet();
// 自定義一個(gè)表(MyGoods)來標(biāo)識(shí)數(shù)據(jù)庫(kù)的GOODS表
adp.Fill(ds, "records");
// 指定DataGridView的數(shù)據(jù)源為DataSet的MyGoods表
this.dgv_kaoqin_m.DataSource = ds.Tables["records"];
}
//符合日期查詢
if (tb_date.Text != "")
{
String sqlStr1 = "select * from record where date=@date";
SqlCommand cmd1 = new SqlCommand(sqlStr1, sqlConn);
cmd1.Parameters.Add(new SqlParameter("@date", Convert.ToDateTime(tb_date.Text)));
//Convert.ToDateTime(dateTimePicker1.Value)
// 將該查詢過程綁定到DataAdapter
SqlDataAdapter adp = new SqlDataAdapter();
adp.SelectCommand = cmd1;
// 將DataSet和DataAdapter綁定
DataSet ds = new DataSet();
// 自定義一個(gè)表(MyGoods)來標(biāo)識(shí)數(shù)據(jù)庫(kù)的GOODS表
adp.Fill(ds, "records");
// 指定DataGridView的數(shù)據(jù)源為DataSet的MyGoods表
this.dgv_kaoqin_m.DataSource = ds.Tables["records"];
}
//員工號(hào)、日期共同查詢
if (tb_date.Text.Trim() != "" && tb_Id.Text.Trim() != "")
{
String sqlStr2 = "select * from record where date=@date and employee_id=@id";
SqlCommand cmd2 = new SqlCommand(sqlStr2, sqlConn);
cmd2.Parameters.Add(new SqlParameter("@date", Convert.ToDateTime(tb_date.Text)));
cmd2.Parameters.Add(new SqlParameter("@id", this.tb_Id.Text.Trim()));
// 將該查詢過程綁定到DataAdapter
SqlDataAdapter adp = new SqlDataAdapter();
adp.SelectCommand = cmd2;
// 將DataSet和DataAdapter綁定
DataSet ds = new DataSet();
// 自定義一個(gè)表(MyGoods)來標(biāo)識(shí)數(shù)據(jù)庫(kù)的GOODS表
adp.Fill(ds, "records");
// 指定DataGridView的數(shù)據(jù)源為DataSet的MyGoods表
this.dgv_kaoqin_m.DataSource = ds.Tables["records"];
}
//無條件查詢
if (tb_date.Text.Trim() == "" && tb_Id.Text.Trim() == "")
{
String sqlStr3 = "select * from record where 1=1";
SqlCommand cmd3 = new SqlCommand(sqlStr3, sqlConn);
//Convert.ToDateTime(dateTimePicker1.Value)
// 將該查詢過程綁定到DataAdapter
SqlDataAdapter adp = new SqlDataAdapter();
adp.SelectCommand = cmd3;
// 將DataSet和DataAdapter綁定
DataSet ds = new DataSet();
// 自定義一個(gè)表(MyGoods)來標(biāo)識(shí)數(shù)據(jù)庫(kù)的GOODS表
adp.Fill(ds, "records");
// 指定DataGridView的數(shù)據(jù)源為DataSet的MyGoods表
this.dgv_kaoqin_m.DataSource = ds.Tables["records"];
}
}
catch (Exception exp)
{
MessageBox.Show("訪問數(shù)據(jù)庫(kù)錯(cuò)誤:" + exp.Message);
}
finally
{
sqlConn.Close();
}
}
5.考勤系統(tǒng)功能實(shí)現(xiàn)——統(tǒng)計(jì)
1.統(tǒng)計(jì)界面設(shè)計(jì)


2.統(tǒng)計(jì)界面實(shí)現(xiàn)代碼
private void bt_Query_Click(object sender, EventArgs e)
{
// 連接字符串,注意與實(shí)際環(huán)境保持一致
String connStr = ConfigurationManager.ConnectionStrings["Attendance"].ConnectionString;
SqlConnection sqlConn = new SqlConnection(connStr);
try
{
// 連接數(shù)據(jù)庫(kù)
sqlConn.Open();
// 構(gòu)造命令
String sqlStr = @"select t4.department,count(*) as count from(
select t3.*, t.name, t.department from (
select t1.employee_id, t1.date, datediff(n,t1.time,t2.time) as diff
from record t1
inner join record t2
on t1.date = t2.date
and t1.employee_id=t2.employee_id
and t1.machine_id =1
and t2.machine_id =2
and t1.date>=@start
and t1.date<=@end
) t3,employee t where t3.employee_id=t.id
) t4 where t4.diff<540 group by t4.department";
SqlCommand cmd = new SqlCommand(sqlStr, sqlConn);
cmd.Parameters.Add(new SqlParameter("@start", this.dtp_start.Value.ToShortDateString()));
cmd.Parameters.Add(new SqlParameter("@end", this.dtp_stop.Value.ToShortDateString()));
// 將該查詢過程綁定到DataAdapter
SqlDataAdapter adp = new SqlDataAdapter();
adp.SelectCommand = cmd;
// 將DataSet和DataAdapter綁定
DataSet ds = new DataSet();
// 自定義一個(gè)表來標(biāo)識(shí)數(shù)據(jù)庫(kù)的record表
adp.Fill(ds, "tongjib");
// 指定DataGridView的數(shù)據(jù)源為DataSet的cx表
this.dataGridView1.DataSource = ds.Tables["tongjib"];
}
catch (Exception exp)
{
MessageBox.Show("訪問數(shù)據(jù)庫(kù)錯(cuò)誤:" + exp.Message);
}
finally
{
sqlConn.Close();
}
}
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
// 點(diǎn)擊查看詳情
if (e.RowIndex != -1 && e.ColumnIndex == 0)
{
// 獲取部門名稱
string department = this.dataGridView1["department", e.RowIndex].Value.ToString();
detail detailForm = new detail(department, this.dtp_start.Value, this.dtp_stop.Value);
detailForm.Show();
}
}
private void aggregate_Load(object sender, EventArgs e)
{
// 固定上半部分,下半部分隨窗口大小調(diào)整
this.splitContainer1.IsSplitterFixed = false;
this.splitContainer1.FixedPanel = FixedPanel.Panel1;
// 設(shè)置開始時(shí)間默認(rèn)值
this.dtp_start.Text = "2014/7/1";
}
四、考勤系統(tǒng)測(cè)試
-
登錄
登錄實(shí)現(xiàn) -
注冊(cè)
注冊(cè)實(shí)現(xiàn) -
查詢
查詢實(shí)現(xiàn)

-
統(tǒng)計(jì)
統(tǒng)計(jì)
五、考勤系統(tǒng)發(fā)布和安裝
-
在確認(rèn)無誤后對(duì)程序進(jìn)行發(fā)布
發(fā)布 -
安裝程序
安裝
六、實(shí)訓(xùn)總結(jié)
通過此次的實(shí)訓(xùn),我們深入了解到前端開發(fā)的步驟和方法,在考勤系統(tǒng)的搭建中,先制定計(jì)劃,再進(jìn)行需求分析,接著擬定開發(fā)步驟,一步一個(gè)腳印、穩(wěn)扎穩(wěn)打地從登錄到注冊(cè)、打卡、查詢、統(tǒng)計(jì);雖然開發(fā)過程中遇到很多的困難和疑問,但有老師的指導(dǎo)和引領(lǐng),我們也在其中成長(zhǎng)了,也收獲了許多。
C#作為面向?qū)ο蟮拈_發(fā)語言,對(duì)于前端開發(fā)十分重要,相對(duì)于web開發(fā),C#有著更易于設(shè)計(jì)的優(yōu)勢(shì),更易懂的編程語言;但是遺憾的是,C#語言中有許多生僻的變量、屬性我們從未接觸過,在完成此次實(shí)訓(xùn)后,我們對(duì)其有了更深的見解。









