基于LNMP环境的考勤加班小助手的设计
1. 背景
加班小助手软件的开发主要是自己想偷懒,由于职业关系,作为一名程序猿,每月还要核对自己的加班时间是一件很繁琐的事情,基于此再结合自己的技能开发这样的一个小助手,能够帮自己统计每个月的加班时间,不用再费劲的核对了。
2. 功能需求
1、能够自动统计每个月的加班时间、休息时间及总时间;
2、周末加班时间和工作日加班时间分开统计显示;
3、界面能显示详细的加班列表;
4、每次添加时间,删除时间,清除数据,列表及各栏统计信息都能自动变换
3. 软件架构
该小助手软件开发基于phpstudy开发环境,在phpstudy配置LNMP环境,程序页面文件保存在phpstudy中的www目录下。
该软件主要由前端界面,后端PHP文件及数据库三大模块组成。
前端界面主要实现各统计信息数据的显示,列表详细信息的显示;
后端php文件主要负接收前端的http请求及其参数,根据请求解析处理数据,实现与数据库的交互;
数据库主要负责各统计信息及列表详细信息的存储;
4. 功能实现
前端页面加载jquery.js文件,界面设计采用bootstrap响应式框架,时间控件通过加载laydate.js文件来实现;
1、能够自动统计每个月的加班时间、休息时间及总时间
此需求实现如下:页面加载完成后通过调用异步ajax向后端php发起http请求,http响应采用json数据格式,前端自定义javascript代码解析http响应的json数据,通过DOM操作将具体的数据显示在界面具体位置。
2、界面能显示详细的加班列表
此需求实现如下:页面加载完成后通过调用异步ajax向后端php发起http请求,http响应采用json数据格式,前端自定义javascript代码解析http响应的json数据,通过DOM操作将具体的数据显示在界面表格中。
3、添加时间,删除时间
前端js自定义事件点击函数add(),delete(),clearAll(),各方法中调用jquery中的ajax方法,向php后端异步请求数据,php后端接收请求后根据参数调用php函数库中一系列数据库方法,从数据库中读写数据,再将读写的数据封装成json数据格式响应至前端。前端自定义javascript代码解析http响应的json数据,通过DOM操作将具体的数据显示在界面具体位置。
5、核心代码
- 前端界面设计代码
<head>
<meta charset="UTF-8">
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
<title>软件主界面</title>
<script src="./js/jquery-3.3.1.min.js"></script>
<script src="./bootstrap/js/bootstrap.min.js"></script>
<script src="./js/bootstrap-datetimepicker.min.js"></script>
<script src="./layDate/laydate/laydate.js"></script>
<link rel="stylesheet" href="./bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="./css/bootstrap-datetimepicker.min.css">
<link rel="stylesheet" href="./layDate/laydate/theme/default/laydate.css">
</head>
<body>
<div class="container" id="app">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">新增信息</h3>
</div>
<div class="panel-body row">
<div class="form-inline col-lg-12">
<div class="form-group col-lg-4">
<label>所选日期:</label>
<input type="text" class="form-control" name="date" id="date">
</div>
<div class="form-group col-lg-4">
<label>周末:</label>
<input type="checkbox" class="form-control glyphicon-check" name="select" id="select">
</div>
</div>
</div>
<div class="panel-body row">
<div class="form-inline col-lg-12">
<div class="form-group col-lg-4">
<label>加班: </label>
<input type="text" class="form-control" name="worktime" id="worktime">
</div>
<div class="form-group col-lg-4">
<label>请假:</label>
<input type="text" class="form-control" name="resttime" id="resttime">
</div>
<div class="form-group col-lg-2">
<input type="button" value="添加" class="btn btn-primary" id="addtime" onclick="add()">
</div>
</div>
</div>
<div class="panel-heading">
<h3 class="panel-title">统计信息</h3>
</div>
<div class="panel-body row">
<div class="form-inline col-lg-12">
<div class="form-group col-lg-8">
<label>休息时间:</label>
<input class="form-control" type="text" id="restvalue">
</div>
<div class="form-group col-lg-4">
<input type="button" value="全部清空" class="btn btn-danger" id="clearall" onclick="clearAll()">
</div>
</div>
</div>
<div class="panel-body row">
<div class="form-inline col-lg-12">
<div class="form-group col-lg-4">
<label>工作日: </label>
<input class="form-control" type="text" id="workvalue">
</div>
<div class="form-group col-lg-4">
<label>周末:</label>
<input class="form-control" type="text" id="weekvalue">
</div>
<div class="form-group col-lg-4">
<label>总计:</label>
<input class="form-control" type="text" id="totalvalue">
</div>
</div>
</div>
<div class="panel-heading">
<h3 class="panel-title">详细列表</h3>
</div>
<div class="panel-body row" id="tablemsg">
</div>
</div>
</div>
<script>
laydate.render({
elem: '#date', //指定元素
type: 'date'
});
</script>
</body>
- 前端加载各统计数据js代码
$.ajax({
type:'GET',
url:'getdata.php',
success:function (res) {
//console.log(res);
var ret = JSON.parse(res);
if(ret.length == 0){
$('#restvalue').val(0);
$('#workvalue').val(0);
$('#weekvalue').val(0);
$('#totalvalue').val(0);
}else{
$('#restvalue').val(ret[0][1]);
$('#workvalue').val(ret[0][2]);
$('#weekvalue').val(ret[0][3]);
$('#totalvalue').val(ret[0][4]);
}
}
});
- 前端获取表格数据js代码
$.ajax({
type:'GET',
url:'getdata2.php',
success:function (res) {
var in_str = '<table class="table table-bordered table-striped table-hover">\n' +
' <thead>\n' +
' <th>序号</th>\n' +
' <th>加班日期</th>\n' +
' <th>加班时间</th>\n' +
' <th>请假时间</th>\n' +
' <th>操作</th>\n' +
' </thead>\n' ;
var ret = JSON.parse(res);
for(var i=0;i<ret.length;i++){
var num = i+1;
//in_str = in_str + '<tr>';
in_str = in_str + '<tr><td>'+ num + '</td>';
for(var j=1;j<ret[i].length;j++){
in_str = in_str + '<td>' + ret[i][j] + '</td>';
}
//in_str = in_str + '<td><a href=\'delete.php?id=' + ret[i][0] + '\'' + 'οnclick=\'return del_check();\'>删除</a></td>';
in_str = in_str + '<td><a οnclick=\'del(' + ret[i][0] + ')\'>删除</a></td>';
in_str = in_str + '</tr>\n'
}
in_str = in_str + ' </table>';
document.getElementById('tablemsg').innerHTML = in_str;
//console.log(in_str);
}
});
- 添加时间js代码
//增加记录
function add(){
var sv = 0;
var type = 'get';
var dataType = "text";
var dateValue = $('#date').val();
var selectValue = $('#select').is(':checked');
alert(selectValue);
if(selectValue){
sv = 1;
}else {
sv = 2;
}
var workValue = $('#worktime').val();
var restValue = $('#resttime').val();
$.ajax({
type:'GET',
url: 'add.php'+'?dv=' + dateValue + '&sv=' + sv + '&wv=' + workValue + '&rv=' + restValue,
success:function (res) {
//console.log(res);
}
});
$.ajax({
type:'GET',
url:'getdata.php',
success:function (res) {
//console.log(res);
var ret = JSON.parse(res);
if(ret.length == 0){
$('#restvalue').val(0);
$('#workvalue').val(0);
$('#weekvalue').val(0);
$('#totalvalue').val(0);
}else{
$('#restvalue').val(ret[0][1]);
$('#workvalue').val(ret[0][2]);
$('#weekvalue').val(ret[0][3]);
$('#totalvalue').val(ret[0][4]);
}
}
});
$.ajax({
type:'GET',
url:'getdata2.php',
success:function (res) {
var in_str = '<table class="table table-bordered table-striped table-hover">\n' +
' <thead>\n' +
' <th>序号</th>\n' +
' <th>加班日期</th>\n' +
' <th>加班时间</th>\n' +
' <th>请假时间</th>\n' +
' <th>操作</th>\n' +
' </thead>\n' ;
var ret = JSON.parse(res);
for(var i=0;i<ret.length;i++){
var num = i+1;
//in_str = in_str + '<tr>';
in_str = in_str + '<tr><td>'+ num + '</td>';
for(var j=1;j<ret[i].length;j++){
in_str = in_str + '<td>' + ret[i][j] + '</td>';
}
//in_str = in_str + '<td><a href=\'delete.php?id=' + ret[i][0] + '\'' + 'οnclick=\'return del_check();\'>删除</a></td>';
in_str = in_str + '<td><a οnclick=\'del(' + ret[i][0] + ')\'>删除</a></td>';
in_str = in_str + '</tr>\n'
}
in_str = in_str + ' </table>';
document.getElementById('tablemsg').innerHTML = in_str;
//console.log(in_str);
}
});
}
- 删除记录、与清除全部js代码
删除记录、与清除全部事件js代码实现原理与添加记录类似,主要把其中请求的url对应改变为后端对应的php文件即可。 - 后端创建数据文件代码
<?php
//$conn = @mysqli_connect("localhost","root","root","attendanceinfo") or die("数据库连接失败!".mysqli_error());
//@mysqli_query($conn,"set names utf8");
header("Content-type:text/html;charset=utf-8");
// 创建连接
$conn=mysql_connect('localhost','root','root');//三个参数分别对应服务器名,账号,密码
// 检测连接
if (!$conn) {
die("连接服务器失败: " . mysql_connect_error());//连接服务器失败退出程序
}
// 创建数据库命名为attendanceinfo
$sql_database = "CREATE DATABASE attendanceinfo";
if (mysql_query($sql_database,$conn)) {
echo "数据库创建成功</br>";
} else {
echo "数据库创建失败: " . mysql_error()."</br>";
}
//连接数据库attendanceinfo
$sele=mysql_select_db( 'attendanceinfo' );
if(!$sele){
die("连接数据库失败: ".mysql_error());//连接数据库失败退出程序
}
// 创建数据表命名为employee1,主键为id(不为空整型),变量名为rest(4位不为空整型),变量名为workday(4位不为空整型),变量名为weekend(4位不为空整型),变量名为total(4位不为空整型)
$sql_table1 = "CREATE TABLE employee1( ".
"id INT NOT NULL AUTO_INCREMENT, ".
"rest INT(4) NOT NULL, ".
"workday INT(4) NOT NULL, ".
"weekend INT(4) NOT NULL, ".
"total INT(4) NOT NULL, ".
"PRIMARY KEY ( id )); ";
$retval = mysql_query( $sql_table1, $conn );
if(! $retval ){
echo '数据表创建失败: ' . mysql_error()."</br>";
}else{
echo "数据表创建成功</br>";
}
// 创建数据表命名为employee2,主键为id(不为空整型),变量名为date(255位不为空字符串),变量名为workday(4位不为空整型),变量名为rest(4位不为空整型)
$sql_table2 = "CREATE TABLE employee2( ".
"id INT NOT NULL AUTO_INCREMENT, ".
"date CHAR(255) NOT NULL, ".
"checkis INT(4) NOT NULL, ".
"workday INT(4) NOT NULL, ".
"rest INT(4) NOT NULL, ".
"PRIMARY KEY ( id )); ";
$retval = mysql_query( $sql_table2, $conn );
if(! $retval ){
echo '数据表创建失败: ' . mysql_error()."</br>";
}else{
echo "数据表创建成功</br>";
}
mysql_query('set names utf8');
mysql_close($conn);//关闭连接
?>
- 后端从数据库获取表格employee1中的统计信息
<?php
$conn = @mysql_connect("localhost","root","root") or die("数据库连接失败!".mysql_error());
mysql_select_db("attendanceinfo",$conn);
@mysql_query("set names utf8");
$query_info = "select * from employee1 where id=1";
$query = mysql_query($query_info);
$res = array();
while($row = mysql_fetch_array($query)){
$tmp = array();
array_push($tmp,$row['id']);
array_push($tmp,$row['rest']);
array_push($tmp,$row['workday']);
array_push($tmp,$row['weekend']);
array_push($tmp,$row['total']);
array_push($res,$tmp);
}
mysql_close($conn);
$json_str = json_encode($res,true);
echo $json_str;
?>
- 后端从数据库表格employee2中获取表格列表详细数据
<?php
$conn = @mysql_connect("localhost","root","root") or die("数据库连接失败!".mysql_error());
mysql_select_db("attendanceinfo",$conn);
@mysql_query("set names utf8");
$sql = "select * from employee2";
$query = mysql_query($sql);
$res = array();
while($row = mysql_fetch_array($query)){
$tmp = array();
array_push($tmp,$row['id']);
array_push($tmp,$row['date']);
array_push($tmp,$row['workday']);
array_push($tmp,$row['rest']);
array_push($res,$tmp);
}
mysql_close($conn);
$json_str = json_encode($res,true);
echo $json_str;
?>
- 后端php增加记录
<?php
$conn = @mysql_connect("localhost","root","root") or die("数据库连接失败!".mysql_error());
mysql_select_db("attendanceinfo",$conn);
@mysql_query("set names utf8");
//获取从前端页面传送的数据
$datev = isset($_GET['dv'])?$_GET['dv']:'';//获取日期
$checkv = isset($_GET['sv'])?$_GET['sv']:'';//获取是否周末值
$workv = isset($_GET['wv'])?$_GET['wv']:'0';//获取加班时间
$restv = isset($_GET['rv'])?$_GET['rv']:'0';//获取休息时间
$weekend = $workday = 0;
if($checkv == 1){//判断加班时间是工作日加班还是周末加班
$weekend = $workv;//若选中加班时间则是周末加班
$checkis = 1;
}else{
$workday = $workv;//若不选择加班时间则是工作日加班
$checkis = 0;
}
//查询读取数据库employee2中数据
$query_info = "select * from employee2 where date like '%$datev%'";
$sql = @mysql_query($query_info);
$result = mysql_fetch_object($sql);
if(!$result){
//若数据库表格employee2中无此记录,将此记录插入表格employee2中
$insert_info = "insert into employee2(date,checkis,workday,rest) values('$datev','$checkis','$workv','$restv')";
$sql = @mysql_query($insert_info);
//echo "数据库表格employee2记录为空********<br>";
//计算统计信息各数据并将数据写入表格employee1
$query_info = "select * from employee1 where id=1";
$sql = @mysql_query($query_info);
$result1 = mysql_fetch_object($sql);
if(!$result1){//表格数据为空则历史数据为空,初始化休息总时间,工作日总时间、周末总时间和全部总时间为0
$resttotal = $worktotal = $spectotal = $numtotal = 0;
$total = $workv - $restv;
$resttotal += $restv;//最新休息时间
$worktotal += $workday;//最新工作日加班时间
$spectotal += $weekend;//最新周末加班时间
$numtotal += $total;//最近统计加班时间
$insert_info = "insert into employee1(id,rest,workday,weekend,total) values(1,'$resttotal','$worktotal','$spectotal','$numtotal')";
$sql = @mysql_query($insert_info);
//echo "数据库表格employee1为空----<br>";
}
else{//表格数据不为空则从数据库读取历史休息总时间,工作日总时间、周末总时间和全部总时间
$resttotal = $result1->rest;
$worktotal = $result1->workday;
$spectotal = $result1->weekend;
$numtotal = $result1->total;
$total = $workv - $restv;
$resttotal += $restv;//最新休息时间
$worktotal += $workday;//最新工作日加班时间
$spectotal += $weekend;//最新周末加班时间
$numtotal += $total;//最近统计加班时间
$insert_info = "update employee1 set rest='$resttotal',workday='$worktotal',weekend='$spectotal',total='$numtotal' where id=1";
$sql = @mysql_query($insert_info);
//echo "数据库表格employee1为不空------<br>";
}
}else{
//若employee2中存在此记录,先读取数据库中该记录
$olddate = $result->date;
$oldcheckis = $result->checkis;
$oldworkday = $result->workday;
$oldrestv = $result->rest;
//若employee2中存在此记录,则更新该记录至employee2中
$update_info = "update employee2 set checkis='$checkis',workday='$workv',rest='$restv' where date like '%$datev%'";
$sql = @mysql_query($update_info);
echo "数据库表格employee2记录为不空*********<br>";
$query_info = "select * from employee1 where id=1";
$sql = @mysql_query($query_info);
$result1 = mysql_fetch_object($sql);
$resttotal = $result1->rest;
$worktotal = $result1->workday;
$spectotal = $result1->weekend;
$numtotal = $result1->total;
$total = $workv - $restv;
$resttotal += $restv - $oldrestv ;//最新休息时间
if($checkis == 1){
$worktotal += $workday;//最新工作日加班时间
$spectotal += $weekend - $oldworkday;//最新周末加班时间
}else{
$worktotal += $workday - $oldworkday;//最新工作日加班时间
$spectotal += $weekend;//最新周末加班时间
}
$numtotal = $worktotal + $spectotal - $resttotal;
$insert_info = "update employee1 set rest='$resttotal',workday='$worktotal',weekend='$spectotal',total='$numtotal' where id=1";
$sql = @mysql_query($insert_info);
}
mysql_close($conn);
?>
- 后端php删除记录
<?php
header("Content-type:text/html;charset=utf-8"); //设置文件编码格式
$conn = @mysql_connect("localhost","root","root") or die("数据库连接失败!".mysql_error());
mysql_select_db("attendanceinfo",$conn);
@mysql_query("set names utf8");
//读取数据库employee1中未删除前的数据
$query_info = "select * from employee1 where id=1";
$sql = @mysql_query($query_info);
$result1 = mysql_fetch_object($sql);
$resttotal = $result1->rest;
$worktotal = $result1->workday;
$spectotal = $result1->weekend;
$numtotal = $result1->total;
//读取数据库employee2中未删除前的数据
$query_info = "select * from employee2 where id='".$_GET['id']."'";
$sql = @mysql_query($query_info);
$result2 = mysql_fetch_object($sql);
$id2 = $result2->id;
$date2 = $result2->date;
$check2 = $result2->checkis;
$workday2 = $result2->workday;
$rest2 = $result2->rest;
//处理数据,计算删除employee2中对应记录后employee1中的新数据
if($check2 == 1){//判断check2值,若为1则记录为周末记录
$spectotal = $spectotal - $workday2;
}else{
$worktotal = $worktotal - $workday2;
}
$resttotal = $resttotal - $rest2;
$numtotal = $worktotal + $spectotal - $resttotal;
//将新数据更新至employee1表中
$insert_info = "update employee1 set rest='$resttotal',workday='$worktotal',weekend='$spectotal',total='$numtotal' where id=1";
$sql = @mysql_query($insert_info);
//删除employee2表中对应记录
$sqlstr = "delete from employee2 where id = '".$_GET['id']."'";
$result = mysql_query($sqlstr);
mysql_close($conn);
?>
- 后端清空数据库中全部表格数据
<?php
$conn = @mysql_connect("localhost","root","root") or die("数据库连接失败!".mysql_error());
mysql_select_db("attendanceinfo",$conn);
@mysql_query("set names utf8");
mysql_query("truncate table employee1");
mysql_query("truncate table employee2");
mysql_close($conn);
?>
6、总结
总的来说,PHP+MYSQL的设计其实就是分层设计的思想,从上往下自定义依次是数据展示层,数据处理层,数据存储层,前端界面负责数据在页面的展示,后端php负责与数据库的交互及交互结果数据的解析和处理,数据库负责数据的存储。各层之间的交互通过对应的通信协议或php库中已有的函数或方法实现。至于各层数据的存储的格式如json格式或其他xml文件等根据实际需求中具体要存的数据决定。