任务F:工时统计

这家传统的贸易公司采取的是时薪制,也就是按小时计算工资,普通员工的每小时薪资按 50 来算;管理者的时薪按 80 来算。目前公司的考勤规则是这样的:

考勤规则说明:

  1. 提前打卡:可以计入有效工时,例如:8:40 打卡,那么 8:40 至 9:00 之间的 20 分钟可以计入有效工时。但提前打卡最多只能提前 30 分钟,例如 8:20 打卡,计入有效工时的部分只能是 8:30~9:00 之间的半小时;

  2. 滞后打卡:可以计入有效工时,例如:12:20 打卡,那么 12:00 至 12:20 之间的20 分钟可以计入有效工时。但滞后打卡最多只能滞后 30 分钟,例如 12:40 打卡,计入有效工时的部分只能是 12:00~12:30 之间的半小时;

  3. 迟到遵从下列规则:

    a) 5 分钟内不算迟到;

    b) 5~10 分钟:扣除 1 小时的时薪;
    c) 10~30 分钟:扣除 2 小时时薪;
    d) 30 分钟以上:扣除 4 小时时薪(封顶)。

  4. 早退遵从下列规则:
    a) 5 分钟内不算早退;
    b) 5~10 分钟:扣除 1 小时的时薪;
    c) 10~30 分钟:扣除 2 小时时薪;
    d) 30 分钟以上:扣除 4 小时时薪(封顶)。

  5. 加班规则:仅计入 20:00~22:00 之间的有效工时,无论提前或滞后都无效。例如 19:30~22:30,那么只计算 20:00~22:00 之间的工时;例如 20:10~21:50,
    那么也仅计入这段时间内的有效工时。

上班 扣钱 下班 扣钱
8.30前 30分钟加班 11.30前 -4
8.30-9.00 加班 11.30-11.50 -2
9.00-9.05 0 11.50-11.55 -1
9.05-9.10 -1 11.55-12.00 0
9.10-9.30 -2 12.00-12.30 加班
9.30后 -4 12.30 以后 30分钟加班
————————— ————————— ————————— —————————
13.00前 30加班 18.前 -4
13.00-13.30 加班 18.00-18.20 -2
13.30-13.35 0 18.20-18.25 -1
13.35-13.40 -1 18.25-18.30 0
13.40-14.00 -2 18.30-19. 加班
14.后 -4 19.以后 30分钟加班
————————— ————————— ————————— —————————
20.00-22.00 这段时间内才算有效

请依据提供的《C4 基础-工时统计-原始数据.xlsx》,统计出当日每位员工应发放的薪资及当日薪资总计,并将数据保存到数据库中,并且能通过浏览器显示和分析。展示出来的数据格式如下图所示(仅示例,非真实结果):

功能要求:
将 Excel 表格上传到后台并使用 Servlet/JSP/JSTL 展示结果;
使用 Maven 完成依赖管理和编译构建;
每日薪资数据及统计需保存到 MySQL 数据库;
统计结果需要排序后显示(同时标识出前三名)。

实现思路:

使用第三方库(如 POI)读入 Excel 数据;
将日期计算封装成工具类。

答:

解答思路:

  1. 定义一个 User 类,里面存储了用户的各种信息,包括姓名、岗位、原始工作时间、有效工时、应得薪资,以及对应的 gettersetter
  2. 创建一个 UserDAO 类,类中实现对所得数据进行操作的方法,包括排序展示、增、查;
  3. 用 POI 读入 Excel 数据;
  4. 调用 UserDAO 里的各种方法,计算出各个员工的有效工时、应得薪资,并赋值给对象里的相应变量;
  5. 将读取到的数据用 UserDAO 数据库中add方法添加至数据库;
  6. 访问 list.jsp 时,调用 UserDAO 类的 list 方法,展示用户数据至浏览器。

关于各个类的具体功能,就写在类前的注释里。这里暂时先不写了。

1. User 类

import java.util.Date;/*** @author: xxm* @Date: 2021/11/26 20:11* Employer 类,里面储存了的各种信息* 包括:* 员工个人信息:姓名、岗位* 员工的原始数据:早中晚的上下班打卡时间,共 6 个,命名方式为: 时间段 + 上/下班时间* 员工的有效工时:分早中晚 3 个时间端,一共 6 个,命名方式为: 时间段 + 有效时间* 员工的总有效工时* 员工的应得薪水*/
public class User {/*** 个人信息部分*/String name;String post;/*** 上下班时间部分*/Date morningToWorkTime;Date morningOffWorkTime;Date afternoonToWorkTime;Date afternoonOffWorkTime;Date nightToWorkTime;Date nightOffWorkTime;/*** 有效工时部分*/long morningEffectiveWorkTime;long afternoonEffectiveWorkTime;long nightEffectiveWorkTime;long totalEffectiveWorkTime;/*** 应得薪酬*/int wage;
}

2. 添加 POI 依赖

pom.xml 文件中添加以下代码

 <!--POI 依赖--><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>3.15</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>3.15</version></dependency>

3. User 类

import java.math.BigDecimal;
import java.util.Date;/*** @author: xxm* @Date: 2021/11/26 20:11* Employer 类,里面储存了的各种信息* 包括:* 员工个人信息:姓名、岗位* 员工的原始数据:早中晚的上下班打卡时间,共 6 个,命名方式为: 时间段 + 上/下班时间* 员工的有效工时:分早中晚 3 个时间端,一共 6 个,命名方式为: 时间段 + 有效时间* 员工的总有效工时* 员工的应得薪水* 各个字段的 getter 和 setter*/
public class User {/*** 个人信息部分*/String name;String post;/*** 上下班时间部分*/Date morningToWorkTime;Date morningOffWorkTime;Date afternoonToWorkTime;Date afternoonOffWorkTime;Date nightToWorkTime;Date nightOffWorkTime;/*** 有效工时部分*/double morningEffectiveWorkTime;double afternoonEffectiveWorkTime;double nightEffectiveWorkTime;double totalEffectiveWorkTime;/*** 应得薪酬*/double wage;/*** 薪资排名*/String rank;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPost() {return post;}public void setPost(String post) {this.post = post;}public Date getMorningToWorkTime() {return morningToWorkTime;}public void setMorningToWorkTime(Date morningToWorkTime) {this.morningToWorkTime = morningToWorkTime;}public Date getMorningOffWorkTime() {return morningOffWorkTime;}public void setMorningOffWorkTime(Date morningOffWorkTime) {this.morningOffWorkTime = morningOffWorkTime;}public Date getAfternoonToWorkTime() {return afternoonToWorkTime;}public void setAfternoonToWorkTime(Date afternoonToWorkTime) {this.afternoonToWorkTime = afternoonToWorkTime;}public Date getAfternoonOffWorkTime() {return afternoonOffWorkTime;}public void setAfternoonOffWorkTime(Date afternoonOffWorkTime) {this.afternoonOffWorkTime = afternoonOffWorkTime;}public Date getNightToWorkTime() {return nightToWorkTime;}public void setNightToWorkTime(Date nightToWorkTime) {this.nightToWorkTime = nightToWorkTime;}public Date getNightOffWorkTime() {return nightOffWorkTime;}public void setNightOffWorkTime(Date nightOffWorkTime) {this.nightOffWorkTime = nightOffWorkTime;}public double getMorningEffectiveWorkTime() {return morningEffectiveWorkTime;}public void setMorningEffectiveWorkTime(double morningEffectiveWorkTime) {this.morningEffectiveWorkTime = morningEffectiveWorkTime;}public double getAfternoonEffectiveWorkTime() {return afternoonEffectiveWorkTime;}public void setAfternoonEffectiveWorkTime(double afternoonEffectiveWorkTime) {this.afternoonEffectiveWorkTime = afternoonEffectiveWorkTime;}public double getNightEffectiveWorkTime() {return nightEffectiveWorkTime;}public void setNightEffectiveWorkTime(double nightEffectiveWorkTime) {this.nightEffectiveWorkTime = nightEffectiveWorkTime;}public double getTotalEffectiveWorkTime() {return totalEffectiveWorkTime;}public void setTotalEffectiveWorkTime(double totalEffectiveWorkTime) {this.totalEffectiveWorkTime = totalEffectiveWorkTime;}public double getWage() {return wage;}public void setWage(double wage) {this.wage = wage;}public String  getRank() {return rank;}public void setRank(String  rank) {this.rank = rank;}
}

4. UserDAO 类

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;import java.sql.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;/*** @author: xxm* @Date: 2021/11/26 20:58* UserDAO 类* 类中包含读取 Excel 的方法、对所得数据进行操作的方法,包括增、查、排序、展示、计算有效工时*/
public class UserDAO {/*** 方法 0:* initialTable 方法* 其功能为:在数据库中创建表,如果改变存在则先删除表再创建*/public void intialTable() {//连接数据库、执行 sql 语句try {Class.forName("com.mysql.cj.jdbc.Driver");} catch (ClassNotFoundException e) {e.printStackTrace();}//初始化的 sql 语句,如果表存在则 DROP ,不存在则创建String sql = "DROP TABLE  IF EXISTS wageTable;";String sql2 ="CREATE TABLE wageTable(username VARCHAR(32) NOT NULL,post VARCHAR(8) NOT NULL,wage FLOAT(8) NOT NULL,theRank CHAR(8),PRIMARY KEY(username));";try (Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/study?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai", "root", "root");PreparedStatement pstmt = conn.prepareStatement(sql)) {pstmt.execute(sql);pstmt.execute(sql2);} catch (SQLException e) {e.printStackTrace();}}/*** 方法 1:* readExcel 方法,其功能为接受一个传入的字符串(路径),并将其数据存储到 User 数组中,然后将这个数组返回。*/public List<User> readExcel(String path) throws Exception {List<User> users = new ArrayList<User>();//1. 获取工作簿XSSFWorkbook workbook = new XSSFWorkbook(path);//2. 获取工作表XSSFSheet sheet = workbook.getSheetAt(0);//3. 获取行int rowNumber = sheet.getLastRowNum();//4. 获取单元格for (int i = 2; i < rowNumber; i++) {XSSFRow row = sheet.getRow(i);int cellNum = row.getLastCellNum();//5. 获取单元格内容,并将其各个属性添加至一个 User 对象,添加至数组中User user = new User();for (int j = 0; j < cellNum; j++) {Cell cell = row.getCell(j);//用 SimpleDateFormat 来将 String 类型的字符串转化为 Date 类型SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");switch (j) {//姓名case 0:String name = cell.getStringCellValue();user.setName(name);break;//岗位case 1:String post = cell.getStringCellValue();user.setPost(post);break;//上午case 2:String m1 = cell.getStringCellValue();Date dateM1 = sdf.parse(m1);user.setMorningToWorkTime(dateM1);break;case 3:String m2 = cell.getStringCellValue();Date dateM2 = sdf.parse(m2);user.setMorningOffWorkTime(dateM2);break;//下午case 4:String a1 = cell.getStringCellValue();Date dateA1 = sdf.parse(a1);user.setAfternoonToWorkTime(dateA1);break;case 5:String a2 = cell.getStringCellValue();Date dateA2 = sdf.parse(a2);user.setAfternoonOffWorkTime(dateA2);break;//晚上case 6:String n1 = cell.getStringCellValue();Date dateN1 = sdf.parse(n1);user.setNightToWorkTime(dateN1);break;case 7:String n2 = cell.getStringCellValue();Date dateN2 = sdf.parse(n2);user.setNightOffWorkTime(dateN2);break;default:break;}}users.add(user);}return users;}/*** 方法 2:* figureEffectiveWorkTime 方法* 其作用为:接收传入的一个 User 数组,算出其成员的各个有效工作时间*/public void figureEffectiveWorkTime(List<User> users) throws Exception {SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");//上午上班的几个时间点long t0830 = sdf.parse("8:30").getTime();long t0900 = sdf.parse("9:00").getTime();long t0905 = sdf.parse("9:05").getTime();long t0910 = sdf.parse("9:10").getTime();long t0930 = sdf.parse("9:30").getTime();//上午下班的几个时间点long t1130 = sdf.parse("11:30").getTime();long t1150 = sdf.parse("11:50").getTime();long t1155 = sdf.parse("11:55").getTime();long t1200 = sdf.parse("12:00").getTime();long t1230 = sdf.parse("12:30").getTime();//下午上班的几个时间点long t1300 = sdf.parse("13:00").getTime();long t1330 = sdf.parse("13:30").getTime();long t1335 = sdf.parse("13:35").getTime();long t1340 = sdf.parse("13:40").getTime();long t1400 = sdf.parse("14:00").getTime();//下午下班的几个时间点long t1800 = sdf.parse("18:00").getTime();long t1820 = sdf.parse("18:20").getTime();long t1825 = sdf.parse("18:25").getTime();long t1830 = sdf.parse("18:30").getTime();long t1900 = sdf.parse("19:00").getTime();//晚上加班的几个时间点long t2000 = sdf.parse("20:00").getTime();long t2200 = sdf.parse("22:00").getTime();//遍历获取有效时间for (User user : users) {long morningEffWorkTime = 0;long afternoonEffWorkTime = 0;long nightEffWorkTime = 0;//1. 上午上班打卡if (t0830 - user.getMorningToWorkTime().getTime() <= 0) {morningEffWorkTime = 30 * 60 * 1000;} else if (t0900 - user.getMorningToWorkTime().getTime() >= 0) {morningEffWorkTime = t0900 - user.getMorningToWorkTime().getTime();} else if (t0905 - user.getMorningToWorkTime().getTime() >= 0) {continue;} else if (t0910 - user.getMorningToWorkTime().getTime() >= 0) {morningEffWorkTime = -1 * 60 * 60 * 1000;} else if (t0930 - user.getMorningToWorkTime().getTime() >= 0) {morningEffWorkTime = -2 * 60 * 60 * 1000;} else {morningEffWorkTime = -4 * 60 * 60 * 1000;}//2. 上午下班打卡if (user.getMorningOffWorkTime().getTime() - t1130 <= 0) {morningEffWorkTime += -4 * 60 * 60 * 1000;} else if (user.getMorningOffWorkTime().getTime() - t1150 <= 0) {morningEffWorkTime += -2 * 60 * 60 * 1000;} else if (user.getMorningOffWorkTime().getTime() - t1155 <= 0) {morningEffWorkTime += -1 * 60 * 60 * 1000;} else if (user.getMorningOffWorkTime().getTime() - t1200 <= 0) {continue;} else if (user.getMorningOffWorkTime().getTime() - t1230 <= 0) {morningEffWorkTime += t1230 - user.getMorningOffWorkTime().getTime();} else {morningEffWorkTime += 30 * 60 * 1000;}//3. 上午上班时间,并计算上午上班有效时间,将其存入 User 对象中if (user.getMorningToWorkTime().getTime() < t0900) {if (user.getMorningOffWorkTime().getTime() < t1200) {morningEffWorkTime += user.getMorningOffWorkTime().getTime() - t0900;} else {morningEffWorkTime += t1200 - t0900;}} else {if (user.getMorningOffWorkTime().getTime() < t1200) {morningEffWorkTime += user.getMorningOffWorkTime().getTime() - user.getMorningToWorkTime().getTime();} else {morningEffWorkTime += t1200 - user.getMorningToWorkTime().getTime();}}user.setMorningEffectiveWorkTime(morningEffWorkTime / 1000.0 / 60 / 60);//4. 下午上班if (t1300 - user.getAfternoonToWorkTime().getTime() <= 0) {afternoonEffWorkTime = 30 * 60 * 1000;} else if (t1330 - user.getAfternoonToWorkTime().getTime() >= 0) {afternoonEffWorkTime = t0900 - user.getAfternoonToWorkTime().getTime();} else if (t1335 - user.getAfternoonToWorkTime().getTime() >= 0) {continue;} else if (t1340 - user.getAfternoonToWorkTime().getTime() >= 0) {afternoonEffWorkTime = -1 * 60 * 60 * 1000;} else if (t1400 - user.getAfternoonToWorkTime().getTime() >= 0) {afternoonEffWorkTime = -2 * 60 * 60 * 1000;} else {afternoonEffWorkTime = -4 * 60 * 60 * 1000;}//5. 下午下班if (user.getAfternoonToWorkTime().getTime() - t1800 <= 0) {afternoonEffWorkTime += -4 * 60 * 60 * 1000;} else if (user.getAfternoonToWorkTime().getTime() - t1820 <= 0) {afternoonEffWorkTime += -2 * 60 * 60 * 1000;} else if (user.getAfternoonToWorkTime().getTime() - t1825 <= 0) {afternoonEffWorkTime += -1 * 60 * 60 * 1000;} else if (user.getAfternoonToWorkTime().getTime() - t1830 <= 0) {break;} else if (user.getAfternoonToWorkTime().getTime() - t1900 <= 0) {afternoonEffWorkTime += t1230 - user.getAfternoonToWorkTime().getTime();} else {afternoonEffWorkTime += 30 * 60 * 1000;}//6. 上午上班时间,并计算上午上班有效时间,将其存入 User 对象中if (user.getAfternoonToWorkTime().getTime() < t1330) {if (user.getAfternoonOffWorkTime().getTime() < t1830) {afternoonEffWorkTime += user.getAfternoonOffWorkTime().getTime() - t1330;} else {afternoonEffWorkTime += t1830 - t1330;}} else {if (user.getAfternoonOffWorkTime().getTime() < t1830) {afternoonEffWorkTime += user.getAfternoonOffWorkTime().getTime() - user.getAfternoonToWorkTime().getTime();} else {afternoonEffWorkTime += t1830 - user.getAfternoonToWorkTime().getTime();}}user.setAfternoonEffectiveWorkTime(afternoonEffWorkTime / 1000 / 60 / 60.0);//晚上加班有效时间,并将其存入 User 对象中if (user.getNightToWorkTime().getTime() - t2000 < 0) {if (user.getNightOffWorkTime().getTime() - t2200 > 0) {nightEffWorkTime = 2 * 60 * 60 * 1000;} else {nightEffWorkTime = user.getNightOffWorkTime().getTime() - user.getNightToWorkTime().getTime();}} else {if (user.getNightOffWorkTime().getTime() - t2200 > 0) {nightEffWorkTime = t2000 - user.getNightToWorkTime().getTime();} else {nightEffWorkTime = t2000 - user.getNightToWorkTime().getTime();}}user.setNightEffectiveWorkTime(nightEffWorkTime / 1000 / 60 / 60.0);//总的有效工作时间:long totalEffWorkTime = morningEffWorkTime + afternoonEffWorkTime + nightEffWorkTime;user.setTotalEffectiveWorkTime(totalEffWorkTime / 1000 / 60 / 60.0);}}/*** 方法 3:* figureWage 方法,其作用为:接收传入的一个 User 数组,算出其当日的应得工资*/public void figureWage(List<User> users) {for (User user : users) {if (user.getTotalEffectiveWorkTime() <= 0) {user.setWage(0);} else if ("普通员工".equals(user.getPost())) {double wage2 = (double) Math.round(50 * user.getTotalEffectiveWorkTime() * 100) / 100;user.setWage(wage2);} else if ("管理岗".equals(user.getPost())) {double wage2 = (double) Math.round(80 * user.getTotalEffectiveWorkTime() * 100) / 100;user.setWage(wage2);}}}/*** 方法 4:* sortByWage 方法,其作用为,获取所有人的工资,并按工资排序,*/public void sortByWage(List<User> users) {//声明数组,将 users 里的对象里的工资添加进去ArrayList<Double> list = new ArrayList<>();for (User user : users) {list.add(user.getWage());}//降序排序list.sort((o1, o2) -> o2.compareTo(o1));//把排名存入 User 对象中(只保存前三名)int rankNum = 3;for (int i = 0; i < rankNum; i++) {for (User user : users) {if (list.get(i) == user.getWage()) {user.setRank("第" + (list.indexOf(list.get(i)) + 1) + "名");}}}for (int j = rankNum; j < list.size(); j++) {for (User user : users) {if (user.getWage() == list.get(j)) {user.setRank(" ");}}}}/*** 方法 5:* addUserToDatabase 方法,其作用为将 User 对象的数据保存至数据库*/public void addUserToDatabase(User user) throws Exception {//定义 sql 语句String sql = "INSERT INTO wageTable (username,post,wage,theRank) VALUES (?,?,?,?)";//连接数据库、执行 sql 语句Class.forName("com.mysql.cj.jdbc.Driver");try (Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/study?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai", "root", "root");PreparedStatement pstmt = conn.prepareStatement(sql)) {pstmt.setString(1, user.getName());pstmt.setString(2, user.getPost());pstmt.setDouble(3, user.getWage());pstmt.setString(4, user.getRank());int num = pstmt.executeUpdate();}}/*** 方法 5:* userList 方法,其作用为读取数据库,返回一个 User 数组,数组中的对象只包含 名字、应得工资、排名、岗位 4 个信息*/public List<User> userList() throws Exception {List<User> users = new ArrayList<User>();Class.forName("com.mysql.cj.jdbc.Driver");//定义 sql 语句String sql = "SELECT username,wage,theRank,post FROM wageTable";try (Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/study?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai", "root", "root");PreparedStatement pstmt = conn.prepareStatement(sql)) {ResultSet rs = pstmt.executeQuery();//处理结果,使用 getString方法,获取用户信息,并且使用 set 方法将值传递给 user 对象,然后加入到 list中while (rs.next()) {User user = new User();if ("管理岗".equals(rs.getString(4))) {user.setName(rs.getString(1) + "(管理)");}user.setName(rs.getString(1));user.setWage(rs.getDouble(2));user.setRank(rs.getString(3));users.add(user);}} catch (Exception e) {e.printStackTrace();}return users;}}

5. UserListServlet 类

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;/*** @author: xxm* @Date: 2021/11/30 9:13* UserListServlet 类,作用为以表格的形式显示所有用户的薪资信息*/
@WebServlet(name = "UserListServlet", urlPatterns = "/list")
public class UserListServlet extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setContentType("text/html; charset=UTF-8");String path = "E:\\Develop\\人才实训基地\\笔记\\任务书\\技术训练营\\技术训练营-TD:工时统计-原始数据.xlsx";try {UserDAO userDAO = new UserDAO();//初始化数据库userDAO.intialTable();//读取excelList<User> users = userDAO.readExcel(path);//计算有效时间、工资,并排序userDAO.figureEffectiveWorkTime(users);userDAO.figureWage(users);userDAO.sortByWage(users);//将用户信息添加至数据库,顺便累加,求出总薪资double totalWage = 0;for (User user : users) {userDAO.addUserToDatabase(user);totalWage += user.wage;}//展示用户数据List<User> usersForList = new UserDAO().userList();StringBuffer sb = new StringBuffer();sb.append("<table align='center' border='1' cellspacing='0'>\r\n");sb.append("<tr><td>    员工姓名    </td><td>    当日薪资    </td><td>  备注  </td></tr>\r\n");//注意,这里在员工姓名栏里用了2个占位符,以留给岗位以空间String trFormat = "<tr><td>%s</td><td>%f</td><td>%s</td></tr>\r\n";for (User user : usersForList) {String tr = String.format(trFormat, user.getName(), user.getWage(), user.getRank());System.out.println(user.getWage());sb.append(tr);}//表尾,总薪资trFormat = "<tr><td>当日薪资总计</td><td>%f</td><td></td></tr>\r\n";String tr = String.format(trFormat, totalWage);sb.append(tr);sb.append("</table>");resp.getWriter().write(sb.toString());} catch (Exception e) {e.printStackTrace();}}
}

运行效果

输入网址 http://localhost:8080/list

如图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VWleEmfw-1640050472275)(https://i.loli.net/2021/11/30/5Tgl6vYdiKrktPZ.png)]

任务 F :工时统计相关推荐

  1. 基于JAVA springboot + MYSQL +VUE的项目管理系统(含数据库),包括工时统计、原型预览、效果图管理等

    平台介绍 无鱼工时管理系统,是一款轻量级工时记录和管理工具,包括项目管理,工时上报,工时日报,工时统计等功能. 无鱼工时管理系统可通过员工工时上报的方式,来记录项目所花费的工时,帮助企业进行项目工时统 ...

  2. Java搭建实战springboot基于若依项目工时统计成本核算管理源码

    大家好啊,我是测评君,欢迎来到web测评. 本期给大家带来一套基于若依开发的springboot项目工时统计成本核算管理源码,该系统是前后端分离的架构,前端使用Vue2,后端使用SpringBoot2 ...

  3. SpringBoot基于若依项目工时统计成本核算管理源码带文字教程

    该系统是前后端分离的架构,前端使用Vue2,后端使用SpringBoot2. 技术架构 技术框架:SpringBoot2.0.0 + Mybatis1.3.2 + Shiro + swagger-ui ...

  4. 研发项目工时统计工具哪个好?9大工时管理系统盘点

    工时管理是项目型企业的重要需求,特别是在人力成本占比较高的行业,如软件开发.设计咨询.会计律师等.工时管理可以帮助企业核算项目人工成本,控制成本投入,提高项目利润,客观考核员工绩效,优化资源分配等. ...

  5. 综合工时制-跨零点到节假日的工时统计异常问题的思考

    项目场景: 提示:这里简述项目相关背景: 涉及到跨零点的班次(前半部分是工作日,后半部分是节假日,如:9月30日 22:00 - 08:00(次日)的班次),需要系统实现自动拆分:按照正常的逻辑,会对 ...

  6. 工厂人员定位系统源码,支持智能考勤、工时统计、行为检测、历史轨迹回放、人员管理、电子围栏功能

    系统概述: 工厂人员定位系统,采用UWB定位技术,通过在厂区内部署一定数量的定位基站,以及为人员.车辆.物资佩戴标签卡的形式,实时获取人员精确位置,精度高达10cm. 工厂人员定位系统可实现物资/车辆 ...

  7. 一款轻量级项目工时统计系统,源码分享

    Java项目工时统计成本核算管理系统源码 技术:Java 1.8 + MySQL 8 +Vue 项目基于前后端分离架构,服务端主要技术:SpringBoot   前端主要是Vue. 源码类型:全开源免 ...

  8. mysql 工时统计_有如下数据,要统计1月3号工时不足8小时的员工姓名及总工时,该sql语句该怎么写(用的mysql哈)...

    登记时间 姓名 工时 2014-01-03 08:42:20 A 2 2014-01-03 16:18:02 B 2 2014-01-03 14:57:54 B 3 2014-01-03 14:54: ...

  9. 问题 F: 成绩统计

    题目描述 把百分制的考试成绩转换为五个等级: 90-100:Excellent 80-89:Good 70-79:Average 60-69:Pass 0-59:Failing 统计每个等级的成绩,并 ...

  10. 钉钉考勤报表--工时统计小程序

    # 起因: 老婆大人:今天弄一天的公司的考勤报表,看的我眼睛都花了.这工作太难了,老公,我不想干了...我:说说老婆大人:公司用的钉钉,一个月会导出一份excel报表,让我统计每个人投入工时.你是不知 ...

最新文章

  1. 使用CSS 3创建不规则图形
  2. 顺序表-顺序表表示集合-交集( for + whlie ,不断遍历)
  3. c# ftp类[转]
  4. python培训好学吗-Python爬虫培训好学吗?
  5. 学习对象对神经网络迭代次数的影响
  6. malloc,realloc,calloc的使用场合及特点,以及malloc的实现原理
  7. trie树java_【数据结构】Trie树的应用:查询IP地址的ISP(Java实现)
  8. android 照片拼接长图_我才发现,微信里面有一个功能,能将手机照片自动拼成长图...
  9. 更新npm至最新版本
  10. oracle catalog命令,db2 catalog tcpip 命令咨询?
  11. Flask框架项目实例:**租房网站(二)
  12. 1)python,现在用过的,后面推出每日练习语法与深度挖掘应用
  13. awk命令详解+示例
  14. 『原创经典』标准日本语初级笔记完整版(1)
  15. 带圆圈的数字和markdown常用表达式记录(持续更新中)
  16. Linux下安装hbase
  17. LAGON ATOLL
  18. xgboost算法_XGBoost算法背后的数学:尽可能简单地解释XGBoost算法背后的数学机制...
  19. 【学习笔记】sed 命令及参数详解
  20. 看看什么叫老牛吃嫩草

热门文章

  1. C++跨平台串口通信类库CSerialPort 2022-11-07
  2. vmware vSAN 入门
  3. 在linux配置端口映射,Linux 配置端口映射
  4. win7开机动画怎么换
  5. cc2530设计性实验代码八
  6. Oracle的安装步骤(详细图示)
  7. MySQL 时间函数
  8. (CSCD 理工科)中文科技核心期刊汇总
  9. 基于AMPL的tsp旅行商问题
  10. Jmeter安装TPS插件