目录
编写签到成功页面(移动端)
实现考勤成功页面(持久层)
实现考勤成功页面(业务层)
实现考勤成功页面(Web层)
一、查询用户的入职日期
二、实现查询考勤结果的Web方法
实现考勤成功页面(移动端)
一、为超级管理员设置入职日期
二、修改系统时间
设计用户页面(移动端)
实现用户页面数据加载
一、编写后端项目代码
设计我的考勤页面(移动端)
实现我的考勤页面(Web层 & 业务层)
一、编写业务层代码
二、编写Web层代码
实现我的考勤页面(移动端)
编写签到成功页面(移动端)
……
实现考勤成功页面(持久层)
LEFT JOIN:前表可以在后表中无数据。
CASE WHEN … THEN … END as xx:替换查询出的数字为汉字。
CAST(date AS CHAR) AS date:转成字符串要用CHAR。
因为下面代码,所以要转为字符串类型,方便比较日期。
String date=one.toString("yyyy-MM-dd");
for (HashMap<String,String> map:checkinList){
if(map.containsValue(date)){
status=map.get("status");
flag=true;
break;
}
}
编写 TbCheckinDao.xml 中的SQL语句,查询员工当天签到情况、员工请考勤日期总数
<select id="searchTodayCheckin" parameterType="int" resultType="HashMap">
SELECT
u.name,
u.photo,
d.dept_name AS deptName,
ck.address,
CASE
WHEN ck.status=1 THEN '正常'
WHEN ck.status=2 THEN '迟到'
END as status,
CASE
WHEN ck.risk=1 THEN '低风险'
WHEN ck.risk=2 THEN '中风险'
WHEN ck.risk=3 THEN '高风险'
END as risk,
DATE_FORMAT(ck.create_time,"%H:%i") AS checkinTime,
ck.date
FROM tb_user u
LEFT JOIN tb_dept d ON u.dept_id=d.id
LEFT JOIN tb_checkin ck ON u.id=ck.user_id AND ck.date=CURRENT_DATE
WHERE u.id=#{userId} AND u.status=1
</select>
<select id="searchCheckinDays" parameterType="int" resultType="long">
SELECT COUNT(*) AS count
FROM tb_checkin
WHERE user_id=#{userId}
</select>
<select id="searchWeekCheckin" parameterType="HashMap" resultType="HashMap">
SELECT
CAST(date AS CHAR) AS date,
IF(status=1,"正常","迟到") AS status
FROM tb_checkin
WHERE user_id=#{userId}
AND date BETWEEN #{startDate} AND #{endDate}
</select>
编写 TbCheckinDao.java 接口中的抽象方法。
@Mapper
public interface TbCheckinDao {
……
public HashMap searchTodayCheckin(int userId);
public long searchCheckinDays(int userId);
public ArrayList<HashMap> searchWeekCheckin(HashMap param);
}
编写 TbHolidaysDao.xml 文件,添加查询语句。
<select id="searchHolidaysInRange" parameterType="HashMap" resultType="String">
SELECT date
FROM tb_holidays
WHERE date BETWEEN #{startDate} AND #{endDate}
</select>
编写 TbHolidaysDao.java 接口,定义抽象方法。
@Mapper
public interface TbHolidaysDao {
……
public ArrayList<String> searchHolidaysInRange(HashMap param);
}
编写 TbWorkdayDao.xml 文件,添加查询语句。
<select id="searchWorkdayInRange" parameterType="HashMap" resultType="String">
SELECT date
FROM tb_workday
WHERE date BETWEEN #{startDate} AND #{endDate}
</select>
编写 TbWorkdayDao.java 接口,定义抽象方法。
@Mapper
public interface TbWorkdayDao {
……
public ArrayList<String> searchWorkdayInRange(HashMap param);
}
实现考勤成功页面(业务层)
上一小节,我们在Dao中声明了三个抽象的方法,于是现在我们要在业务层定义三个方法,分别对应Dao的三个抽象方法。
编写 CheckinService.java 接口,声明三个抽象方法。
public interface CheckinService {
……
public HashMap searchTodayCheckin(int userId);
public long searchCheckinDays(int userId);
public ArrayList<HashMap> searchWeekCheckin(HashMap param);
}
在 CheckinServiceImpl.java 类中,实现三个抽象方法。
@Service
@Scope("prototype")
@Slf4j
public class CheckinServiceImpl implements CheckinService {
……
@Override
public HashMap searchTodayCheckin(int userId) {
HashMap map=checkinDao.searchTodayCheckin(userId);
return map;
}
@Override
public long searchCheckinDays(int userId) {
long days=checkinDao.searchCheckinDays(userId);
return days;
}
@Override
public ArrayList<HashMap> searchWeekCheckin(HashMap param) {
ArrayList<HashMap> checkinList=checkinDao.searchWeekCheckin(param);
ArrayList holidaysList=holidaysDao.searchHolidaysInRange(param);
ArrayList workdayList=workdayDao.searchWorkdayInRange(param);
DateTime startDate=DateUtil.parseDate(param.get("startDate").toString());
DateTime endDate=DateUtil.parseDate(param.get("endDate").toString());
DateRange range=DateUtil.range(startDate,endDate,DateField.DAY_OF_MONTH);
ArrayList<HashMap> list=new ArrayList<>();
range.forEach(one->{
String date=one.toString("yyyy-MM-dd");
String type="工作日";
if(one.isWeekend()){
type="节假日";
}
if(holidaysList!=null&&holidaysList.contains(date)){
type="节假日";
}
else if(workdayList!=null&&workdayList.contains(date)){
type="工作日";
}
String status="";
if(type.equals("工作日")&&DateUtil.compare(one,DateUtil.date())<=0){
status="缺勤";
boolean flag=false;
for (HashMap<String,String> map:checkinList){
if(map.containsValue(date)){
status=map.get("status");
flag=true;
break;
}
}
DateTime endTime=DateUtil.parse(DateUtil.today()+" "+constants.attendanceEndTime);
String today=DateUtil.today();
if(date.equals(today)&&DateUtil.date().isBefore(endTime)&&flag==false){
status="";
}
}
HashMap map=new HashMap();
map.put("date",date);
map.put("status",status);
map.put("type",type);
map.put("day",one.dayOfWeekEnum().toChinese("周"));
list.add(map);
});
return list;
}
}
实现考勤成功页面(Web层)
一、查询用户的入职日期
因为在Emos系统中,当天没有考勤的员工就算做缺勤。有一种特殊请款我们必须引起注意,假设A员工周三入职的,从周三开始执行人脸考勤。那么在考勤成功页面,我们看到周一和周二的考勤结果都是缺勤,这个是不对的。所以我们要先查询出来员工的入职日期,查询本周考勤的时候,应该从员工入职日期开始算起。
编写 TbUserDao.xml 文件,查询员工的入职日期。
<select id="searchUserHiredate" parameterType="int" resultType="String">
SELECT hiredate FROM tb_user WHERE id=#{userId} AND status = 1
</select>
// MyBatis会把日期格式转为字符串格式。
编写 TbUserDao.java 接口,定义抽象方法。
public interface TbUserDao {
……
public String searchUserHiredate(int userId);
}
在 UserService.java 接口中,声明抽象方法。
public interface UserService {
……
public String searchUserHiredate(int userId);
}
在 UserServiceImpl.java 中,实现抽象方法。
public class UserServiceImpl implements UserService {
……
@Override
public String searchUserHiredate(int userId) {
String hiredate = userDao.searchUserHiredate(userId);
return hiredate;
}
}
二、实现查询考勤结果的Web方法
编写 CheckinController.java 中的Web方法,查询用户签到的结果。
@RequestMapping("/checkin")
@RestController
@Api("签到模块Web接口")
@Slf4j
public class CheckinController {
……
@Autowired
private UserService userService;
@Autowired
private SystemConstants constants;
@GetMapping("/searchTodayCheckin")
@ApiOperation("查询用户当日签到数据")
public R searchTodayCheckin(@RequestHeader("token") String token){
int userId=jwtUtil.getUserId(token);
HashMap map=checkinService.searchTodayCheckin(userId);
map.put("attendanceTime",constants.attendanceTime);
map.put("closingTime",constants.closingTime);
long days=checkinService.searchCheckinDays(userId);
map.put("checkinDays",days);
DateTime hiredate=DateUtil.parse(userService.searchUserHiredate(userId));
DateTime startDate=DateUtil.beginOfWeek(DateUtil.date());
if(startDate.isBefore(hiredate)){
startDate=hiredate;
}
DateTime endDate=DateUtil.endOfWeek(DateUtil.date());
HashMap param=new HashMap();
param.put("startDate",startDate.toString());
param.put("endDate",endDate.toString());
param.put("userId",userId);
ArrayList<HashMap> list=checkinService.searchWeekCheckin(param);
map.put("weekCheckin",list);
return R.ok().put("result",map);
}
}
实现考勤成功页面(移动端)
一、为超级管理员设置入职日期
因为在查询考勤结果的时候用到了员工入职日期,管理者创建员工记录的时候,要手动设置员工的入职日期,但是注册超级管理员的时候并没有填写入职日期,现在我们还没有做到员工管理页面,所以暂时手工在数据表里面设置超级管理员的入职日期。
二、修改系统时间
因为Emos系统的签到时间是从08:30到09:30,为了实验签到功能,所以我们要修改系统时间在签到时间段之内。另外,如果你是周六、周日调试项目,需要在 tb_workday 表中加入当天日期,这样原本的周末就变成了工作日,可以考勤了。
设计用户页面(移动端)
……
实现用户页面数据加载
一、编写后端项目代码
在 TbUserDao.xml 中定义查询用户概要信息的SQL语句。
<select id="searchUserSummary" parameterType="int" resultType="HashMap">
SELECT u.name, u.photo, d.dept_name AS deptName
FROM tb_user u LEFT JOIN tb_dept d ON u.dept_id=d.id
WHERE u.id=#{userId} AND u.status=1
</select>
在 TbUserDao.java 接口中,定义抽象方法。
@Mapper
public interface TbUserDao {
……
public HashMap searchUserSummary(int userId);
}
在 UserService.java 接口中,定义抽象方法。
public interface UserService {
……
public HashMap searchUserSummary(int userId);
}
在 UserServiceImpl.java 中,定义实现方法。
public class UserServiceImpl implements UserService {
……
@Override
public HashMap searchUserSummary(int userId) {
HashMap map = userDao.searchUserSummary(userId);
return map;
}
}
在 UserController.java 中,定义Web方法。
@RestController
@RequestMapping("/user")
@Api("用户模块Web接口")
public class UserController {
……
@GetMapping("/searchUserSummary")
@ApiOperation("查询用户摘要信息")
public R searchUserSummary(@RequestHeader("token") String token){
int userId=jwtUtil.getUserId(token);
HashMap map=userService.searchUserSummary(userId);
return R.ok().put("result",map);
}
}
设计我的考勤页面(移动端)
……
实现我的考勤页面(Web层 & 业务层)
查询月考勤持久层代码 和 查询周考勤持久层代码相通。
一、编写业务层代码
在 CheckinService.java 接口中添加查询月考勤的抽象方法。
public interface CheckinService {
……
public ArrayList<HashMap> searchMonthCheckin(HashMap param);
}
在 CheckinServiceImpl.java 类中添加实现方法。
public class CheckinServiceImpl implements CheckinService {
……
@Override
public ArrayList<HashMap> searchMonthCheckin(HashMap param) {
return this.searchWeekCheckin(param);
}
}
二、编写Web层代码
创建 SearchMonthCheckinForm.java 类,接受提交数据。
@Data
@ApiModel
public class SearchMonthCheckinForm {
@NotNull
@Range(min=2000,max = 3000)
private Integer year;
@NotNull
@Range(min=1,max = 12)
private Integer month;
}
在 CheckinController.java 中,定义Web
@RequestMapping("/checkin")
@RestController
@Api("签到模块Web接口")
@Slf4j
public class CheckinController {
……
@PostMapping("/searchMonthCheckin")
@ApiOperation("查询用户某月签到数据")
public R searchMonthCheckin(@Valid @RequestBody SearchMonthCheckinForm form,@RequestHeader("token") String token){
int userId=jwtUtil.getUserId(token);
DateTime hiredate=DateUtil.parse(userService.searchUserHiredate(userId));
String month=form.getMonth()<10?"0"+form.getMonth():form.getMonth().toString();
DateTime startDate=DateUtil.parse(form.getYear()+"-"+month+"-01");
if(startDate.isBefore(DateUtil.beginOfMonth(hiredate))){
throw new EmosException("只能查询考勤之后日期的数据");
}
if(startDate.isBefore(hiredate)){
startDate=hiredate;
}
DateTime endDate=DateUtil.endOfMonth(startDate);
HashMap param=new HashMap();
param.put("userId",userId);
param.put("startDate",startDate.toString());
param.put("endDate",endDate.toString());
ArrayList<HashMap> list=checkinService.searchMonthCheckin(param);
int sum_1=0,sum_2=0,sum_3=0;
for(HashMap<String,String> one:list){
String type=one.get("type");
String status=one.get("status");
if("工作日".equals(type)){
if("正常".equals(status)){
sum_1++;
}
else if("迟到".equals(status)){
sum_2++;
}
else if("缺勤".equals(status)){
sum_3++;
}
}
}
return R.ok().put("list",list).put("sum_1",sum_1).put("sum_2",sum_2).put("sum_3",sum_3);
}
}
实现我的考勤页面(移动端)
array.length = 0; 清空数组