员工考勤对接前端,后端未实装
This commit is contained in:
@ -0,0 +1,194 @@
|
|||||||
|
package com.sipai.controller.administration;
|
||||||
|
|
||||||
|
import net.sf.json.JSONArray;
|
||||||
|
import net.sf.json.JSONObject;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.ui.Model;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.servlet.ModelAndView;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
@RequestMapping("/administration/attendance")
|
||||||
|
public class AttendanceController {
|
||||||
|
private static final DateTimeFormatter DAY_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||||
|
|
||||||
|
@RequestMapping("/showList.do")
|
||||||
|
public String showList(HttpServletRequest request, Model model) {
|
||||||
|
return "/administration/attendanceRecordList";
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping("/getList.do")
|
||||||
|
public ModelAndView getList(HttpServletRequest request, Model model,
|
||||||
|
@RequestParam(value = "page") Integer page,
|
||||||
|
@RequestParam(value = "rows") Integer rows,
|
||||||
|
@RequestParam(value = "sort", required = false) String sort,
|
||||||
|
@RequestParam(value = "order", required = false) String order) {
|
||||||
|
String name = safe(request.getParameter("search_name"));
|
||||||
|
String dept = safe(request.getParameter("search_dept"));
|
||||||
|
String status = safe(request.getParameter("search_status"));
|
||||||
|
String start = safe(request.getParameter("search_start"));
|
||||||
|
String end = safe(request.getParameter("search_end"));
|
||||||
|
|
||||||
|
LocalDate startDate = parseDay(start);
|
||||||
|
LocalDate endDate = parseDay(end);
|
||||||
|
List<Map<String, Object>> allRows = buildMockRows();
|
||||||
|
List<Map<String, Object>> filtered = new ArrayList<Map<String, Object>>();
|
||||||
|
|
||||||
|
for (Map<String, Object> item : allRows) {
|
||||||
|
String employeeNo = str(item.get("employeeNo"));
|
||||||
|
String employeeName = str(item.get("employeeName"));
|
||||||
|
String deptName = str(item.get("deptName"));
|
||||||
|
String st = str(item.get("status"));
|
||||||
|
LocalDate day = parseDay(str(item.get("attendanceDate")));
|
||||||
|
|
||||||
|
if (!name.isEmpty()) {
|
||||||
|
String q = name.toLowerCase();
|
||||||
|
if (!employeeNo.toLowerCase().contains(q) && !employeeName.toLowerCase().contains(q)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!dept.isEmpty() && !dept.equals(deptName)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!status.isEmpty() && !status.equals(st)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (startDate != null && day != null && day.isBefore(startDate)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (endDate != null && day != null && day.isAfter(endDate)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
filtered.add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
sortRows(filtered, sort, order);
|
||||||
|
int total = filtered.size();
|
||||||
|
int from = Math.max(0, (page - 1) * rows);
|
||||||
|
int to = Math.min(total, from + rows);
|
||||||
|
List<Map<String, Object>> pageRows = from >= to ? Collections.<Map<String, Object>>emptyList() : filtered.subList(from, to);
|
||||||
|
|
||||||
|
JSONObject result = new JSONObject();
|
||||||
|
result.put("total", total);
|
||||||
|
result.put("rows", JSONArray.fromObject(pageRows));
|
||||||
|
model.addAttribute("result", result.toString());
|
||||||
|
return new ModelAndView("result");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void sortRows(List<Map<String, Object>> rows, String sort, String order) {
|
||||||
|
final boolean asc = "asc".equalsIgnoreCase(order);
|
||||||
|
final String sortField = (sort == null || sort.trim().isEmpty() || "id".equals(sort)) ? "attendanceDate" : sort;
|
||||||
|
Collections.sort(rows, new Comparator<Map<String, Object>>() {
|
||||||
|
@Override
|
||||||
|
public int compare(Map<String, Object> a, Map<String, Object> b) {
|
||||||
|
int cmp;
|
||||||
|
if ("employeeNo".equals(sortField)) {
|
||||||
|
cmp = str(a.get("employeeNo")).compareTo(str(b.get("employeeNo")));
|
||||||
|
} else if ("employeeName".equals(sortField)) {
|
||||||
|
cmp = str(a.get("employeeName")).compareTo(str(b.get("employeeName")));
|
||||||
|
} else if ("deptName".equals(sortField)) {
|
||||||
|
cmp = str(a.get("deptName")).compareTo(str(b.get("deptName")));
|
||||||
|
} else if ("status".equals(sortField)) {
|
||||||
|
cmp = str(a.get("status")).compareTo(str(b.get("status")));
|
||||||
|
} else if ("checkInTime".equals(sortField)) {
|
||||||
|
cmp = str(a.get("checkInTime")).compareTo(str(b.get("checkInTime")));
|
||||||
|
} else {
|
||||||
|
cmp = str(a.get("attendanceDate")).compareTo(str(b.get("attendanceDate")));
|
||||||
|
}
|
||||||
|
if (!asc) {
|
||||||
|
cmp = -cmp;
|
||||||
|
}
|
||||||
|
if (cmp == 0) {
|
||||||
|
return str(a.get("employeeNo")).compareTo(str(b.get("employeeNo")));
|
||||||
|
}
|
||||||
|
return cmp;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<Map<String, Object>> buildMockRows() {
|
||||||
|
String[][] employees = {
|
||||||
|
{"E0001", "张三", "生产部"},
|
||||||
|
{"E0002", "李四", "设备部"},
|
||||||
|
{"E0003", "王五", "品控部"},
|
||||||
|
{"E0004", "赵六", "仓储部"},
|
||||||
|
{"E0005", "钱七", "行政部"}
|
||||||
|
};
|
||||||
|
|
||||||
|
List<Map<String, Object>> rows = new ArrayList<Map<String, Object>>();
|
||||||
|
LocalDate today = LocalDate.now();
|
||||||
|
int idSeq = 1;
|
||||||
|
|
||||||
|
for (int d = 0; d < 45; d++) {
|
||||||
|
LocalDate day = today.minusDays(d);
|
||||||
|
String dayStr = DAY_FMT.format(day);
|
||||||
|
for (int i = 0; i < employees.length; i++) {
|
||||||
|
String[] emp = employees[i];
|
||||||
|
int flag = d + i;
|
||||||
|
|
||||||
|
String status = "正常";
|
||||||
|
String checkIn = "08:55";
|
||||||
|
String checkOut = "18:05";
|
||||||
|
String workHours = "8.5";
|
||||||
|
|
||||||
|
if (flag % 19 == 0) {
|
||||||
|
status = "缺卡";
|
||||||
|
checkOut = "--";
|
||||||
|
workHours = "4.2";
|
||||||
|
} else if (flag % 11 == 0) {
|
||||||
|
status = "迟到";
|
||||||
|
checkIn = "09:" + (10 + (flag % 20));
|
||||||
|
workHours = "7.8";
|
||||||
|
} else if (flag % 13 == 0) {
|
||||||
|
status = "早退";
|
||||||
|
checkOut = "17:" + (20 + (flag % 30));
|
||||||
|
workHours = "7.1";
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> row = new LinkedHashMap<String, Object>();
|
||||||
|
row.put("id", "mock-" + idSeq++);
|
||||||
|
row.put("employeeNo", emp[0]);
|
||||||
|
row.put("employeeName", emp[1]);
|
||||||
|
row.put("deptName", emp[2]);
|
||||||
|
row.put("attendanceDate", dayStr);
|
||||||
|
row.put("checkInTime", checkIn);
|
||||||
|
row.put("checkOutTime", checkOut);
|
||||||
|
row.put("workHours", workHours);
|
||||||
|
row.put("status", status);
|
||||||
|
row.put("source", "第三方接口(MOCK)");
|
||||||
|
rows.add(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String safe(String s) {
|
||||||
|
return s == null ? "" : s.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String str(Object o) {
|
||||||
|
return o == null ? "" : String.valueOf(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static LocalDate parseDay(String day) {
|
||||||
|
if (day == null || day.trim().isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return LocalDate.parse(day.trim(), DAY_FMT);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
201
src/main/webapp/jsp/administration/attendanceRecordList.jsp
Normal file
201
src/main/webapp/jsp/administration/attendanceRecordList.jsp
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
<%@ page language="java" pageEncoding="UTF-8"%>
|
||||||
|
<%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c"%>
|
||||||
|
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
|
||||||
|
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
|
||||||
|
<%@ page import="com.sipai.entity.base.ServerObject"%>
|
||||||
|
<%@ taglib uri="http://www.springsecurity.org/jsp" prefix="security"%>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<head>
|
||||||
|
<title><%= ServerObject.atttable.get("TOPTITLE")%></title>
|
||||||
|
<jsp:include page="/jsp/inc.jsp"></jsp:include>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
var dosearch = function () {
|
||||||
|
$("#table").bootstrapTable('refresh', {pageNumber: 1});
|
||||||
|
};
|
||||||
|
|
||||||
|
var resetSearch = function () {
|
||||||
|
$('#search_name').val('');
|
||||||
|
$('#search_dept').val('');
|
||||||
|
$('#search_status').val('');
|
||||||
|
$('#search_start').val('');
|
||||||
|
$('#search_end').val('');
|
||||||
|
dosearch();
|
||||||
|
};
|
||||||
|
|
||||||
|
var statusFormatter = function (value) {
|
||||||
|
if (value === '正常') {
|
||||||
|
return '<span class="label label-success">正常</span>';
|
||||||
|
}
|
||||||
|
if (value === '迟到') {
|
||||||
|
return '<span class="label label-warning">迟到</span>';
|
||||||
|
}
|
||||||
|
if (value === '早退') {
|
||||||
|
return '<span class="label label-primary">早退</span>';
|
||||||
|
}
|
||||||
|
return '<span class="label label-danger">' + value + '</span>';
|
||||||
|
};
|
||||||
|
|
||||||
|
$(function () {
|
||||||
|
$('#search_start,#search_end').datepicker({
|
||||||
|
format: 'yyyy-mm-dd',
|
||||||
|
autoclose: true,
|
||||||
|
language: 'zh-CN',
|
||||||
|
clearBtn: true
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#table').bootstrapTable({
|
||||||
|
url: ext.contextPath + '/administration/attendance/getList.do',
|
||||||
|
cache: false,
|
||||||
|
striped: true,
|
||||||
|
pagination: true,
|
||||||
|
pageList: [10, 20, 50],
|
||||||
|
pageSize: 20,
|
||||||
|
pageNumber: 1,
|
||||||
|
sidePagination: 'server',
|
||||||
|
sortName: 'attendanceDate',
|
||||||
|
sortOrder: 'desc',
|
||||||
|
queryParams: function (params) {
|
||||||
|
return {
|
||||||
|
rows: params.limit,
|
||||||
|
page: params.offset / params.limit + 1,
|
||||||
|
sort: params.sort,
|
||||||
|
order: params.order,
|
||||||
|
search_name: $('#search_name').val(),
|
||||||
|
search_dept: $('#search_dept').val(),
|
||||||
|
search_status: $('#search_status').val(),
|
||||||
|
search_start: $('#search_start').val(),
|
||||||
|
search_end: $('#search_end').val()
|
||||||
|
};
|
||||||
|
},
|
||||||
|
columns: [{
|
||||||
|
field: 'employeeNo',
|
||||||
|
title: '工号',
|
||||||
|
sortable: true,
|
||||||
|
align: 'center',
|
||||||
|
valign: 'middle'
|
||||||
|
}, {
|
||||||
|
field: 'employeeName',
|
||||||
|
title: '姓名',
|
||||||
|
sortable: true,
|
||||||
|
align: 'center',
|
||||||
|
valign: 'middle'
|
||||||
|
}, {
|
||||||
|
field: 'deptName',
|
||||||
|
title: '部门',
|
||||||
|
sortable: true,
|
||||||
|
align: 'center',
|
||||||
|
valign: 'middle'
|
||||||
|
}, {
|
||||||
|
field: 'attendanceDate',
|
||||||
|
title: '日期',
|
||||||
|
sortable: true,
|
||||||
|
align: 'center',
|
||||||
|
valign: 'middle'
|
||||||
|
}, {
|
||||||
|
field: 'checkInTime',
|
||||||
|
title: '上班打卡',
|
||||||
|
sortable: true,
|
||||||
|
align: 'center',
|
||||||
|
valign: 'middle'
|
||||||
|
}, {
|
||||||
|
field: 'checkOutTime',
|
||||||
|
title: '下班打卡',
|
||||||
|
align: 'center',
|
||||||
|
valign: 'middle'
|
||||||
|
}, {
|
||||||
|
field: 'workHours',
|
||||||
|
title: '工时(小时)',
|
||||||
|
align: 'center',
|
||||||
|
valign: 'middle'
|
||||||
|
}, {
|
||||||
|
field: 'status',
|
||||||
|
title: '状态',
|
||||||
|
sortable: true,
|
||||||
|
align: 'center',
|
||||||
|
valign: 'middle',
|
||||||
|
formatter: statusFormatter
|
||||||
|
}, {
|
||||||
|
field: 'source',
|
||||||
|
title: '数据来源',
|
||||||
|
align: 'center',
|
||||||
|
valign: 'middle'
|
||||||
|
}],
|
||||||
|
onLoadSuccess: function () {
|
||||||
|
adjustBootstrapTableView("table");
|
||||||
|
},
|
||||||
|
onLoadError: function () {
|
||||||
|
console.info("加载考勤数据失败");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body onload="initMenu()" class="hold-transition ${cu.themeclass} sidebar-mini">
|
||||||
|
<div class="wrapper">
|
||||||
|
<div class="content-wrapper">
|
||||||
|
<section class="content-header">
|
||||||
|
<h1 id="head_title"></h1>
|
||||||
|
<ol class="breadcrumb">
|
||||||
|
<li><a id='head_firstlevel' href="#"><i class="fa fa-dashboard"></i> </a></li>
|
||||||
|
</ol>
|
||||||
|
</section>
|
||||||
|
<section class="content container-fluid">
|
||||||
|
<div id="mainAlertdiv"></div>
|
||||||
|
<div id="subDiv"></div>
|
||||||
|
|
||||||
|
<div class="box box-primary">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h3 class="box-title">员工考勤记录</h3>
|
||||||
|
<span class="text-muted" style="margin-left: 10px;">当前为第三方考勤接口模拟数据(MOCK)</span>
|
||||||
|
</div>
|
||||||
|
<div class="box-body">
|
||||||
|
<div class="form-inline" style="margin-bottom: 10px;">
|
||||||
|
<div class="form-group" style="margin-right: 8px;">
|
||||||
|
<input type="text" id="search_name" class="form-control input-sm" style="width: 180px;"
|
||||||
|
placeholder="姓名/工号">
|
||||||
|
</div>
|
||||||
|
<div class="form-group" style="margin-right: 8px;">
|
||||||
|
<select id="search_dept" class="form-control input-sm" style="width: 120px;">
|
||||||
|
<option value="">全部部门</option>
|
||||||
|
<option value="生产部">生产部</option>
|
||||||
|
<option value="设备部">设备部</option>
|
||||||
|
<option value="品控部">品控部</option>
|
||||||
|
<option value="仓储部">仓储部</option>
|
||||||
|
<option value="行政部">行政部</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="form-group" style="margin-right: 8px;">
|
||||||
|
<select id="search_status" class="form-control input-sm" style="width: 100px;">
|
||||||
|
<option value="">全部状态</option>
|
||||||
|
<option value="正常">正常</option>
|
||||||
|
<option value="迟到">迟到</option>
|
||||||
|
<option value="早退">早退</option>
|
||||||
|
<option value="缺卡">缺卡</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="form-group" style="margin-right: 8px;">
|
||||||
|
<input type="text" id="search_start" class="form-control input-sm" style="width: 120px;"
|
||||||
|
placeholder="开始日期">
|
||||||
|
</div>
|
||||||
|
<div class="form-group" style="margin-right: 8px;">
|
||||||
|
<input type="text" id="search_end" class="form-control input-sm" style="width: 120px;"
|
||||||
|
placeholder="结束日期">
|
||||||
|
</div>
|
||||||
|
<div class="btn-group btn-group-sm">
|
||||||
|
<button type="button" class="btn btn-default" onclick="dosearch();"><i
|
||||||
|
class="fa fa-search"></i> 查询
|
||||||
|
</button>
|
||||||
|
<button type="button" class="btn btn-default" onclick="resetSearch();"><i
|
||||||
|
class="fa fa-undo"></i> 重置
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<table id="table"></table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user