Trong môi trường làm việc hiện đại, việc thống kê khối lượng công việc một cách hiệu quả đóng vai trò then chốt trong việc đánh giá hiệu suất, tối ưu hóa phân bổ nguồn lực và nâng cao hiệu quả cộng tác của đội nhóm. Tuy nhiên, các phương pháp thống kê thủ công truyền thống thường tốn thời gian, công sức và dễ gây sai sót, không đáp ứng được nhu cầu quản lý của các doanh nghiệp ngày nay.
Để giải quyết thách thức này, chúng tôi đã thiết kế và triển khai một hệ thống thống kê khối lượng công việc dựa trên nền tảng Java, Spring Boot và MySQL. Hệ thống tận dụng khả năng đa nền tảng của Java và sự tinh gọn, hiệu quả của Spring Boot, mang đến một giao diện trực quan, dễ sử dụng và mạnh mẽ cho người dùng. Việc tích hợp cơ sở dữ liệu MySQL đảm bảo tính tin cậy và bảo mật dữ liệu của hệ thống.
Bài viết này sẽ đi sâu vào phân tích yêu cầu, ý tưởng thiết kế, lựa chọn công nghệ, quy trình triển khai cũng như kiểm thử và tối ưu hóa hệ thống thống kê khối lượng công việc này. Chúng tôi kỳ vọng hệ thống sẽ giúp các doanh nghiệp nắm bắt chính xác tình hình công việc của nhân viên, tối ưu hóa quy trình làm việc và nâng cao hiệu quả hoạt động tổng thể. Đồng thời, bài viết cũng mong muốn cung cấp tài liệu tham khảo hữu ích cho các nhà nghiên cứu và nhà phát triển trong lĩnh vực liên quan.
Công nghệ sử dụng
- Ngôn ngữ: Java
- Framework: Spring Boot
- Công nghệ Frontend: JavaScript, Vue.js, CSS3
- Công cụ phát triển: IntelliJ IDEA / Eclipse
- Cơ sở dữ liệu: MySQL 5.7/8.0
- Công cụ quản lý cơ sở dữ liệu: phpStudy / Navicat
- JDK phiên bản: 1.8
- Maven: apache-maven 3.8.1-bin
- Môi trường Frontend: Node.js 12/14/16
Các chức năng chính của hệ thống
- Quản lý thông tin người quản lý: Giao diện cho phép quản trị viên tra cứu, thêm mới, sửa đổi và xóa thông tin người quản lý. Hỗ trợ tìm kiếm theo tên người quản lý một cách tương đối.
- Quản lý thông tin thực đơn: Cho phép xem, sửa đổi, hoặc hủy bỏ (xóa) thông tin thực đơn đã được đăng tải. Hỗ trợ tìm kiếm tương đối theo tên thực đơn, loại thực đơn và các điều kiện khác.
- Quản lý bản ghi công việc: Người quản trị có thể thực hiện các thao tác như thêm mới, sửa đổi, tra cứu bản ghi công việc dựa trên các điều kiện tìm kiếm khác nhau.
- Quản lý thông tin thông báo: Cung cấp chức năng thêm mới, sửa đổi và tra cứu thông tin thông báo.
Mã nguồn tiêu biểu
1. Module Đăng nhập
package com.controller;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import com.annotation.IgnoreAuth;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.entity.TokenEntity;
import com.entity.UserEntity;
import com.service.TokenService;
import com.service.UserService;
import com.utils.CommonUtil;
import com.utils.MD5Util;
import com.utils.MPUtil;
import com.utils.PageUtils;
import com.utils.R;
import com.utils.ValidatorUtils;
/**
* Liên quan đến đăng nhập
*/
@RequestMapping("users")
@RestController
public class UserController{
@Autowired
private UserService userService;
@Autowired
private TokenService tokenService;
/**
* Đăng nhập
*/
@IgnoreAuth
@PostMapping(value = "/login")
public R login(String username, String password, String captcha, HttpServletRequest request) {
UserEntity user = userService.selectOne(new EntityWrapper<UserEntity>().eq("username", username));
if(user==null || !user.getPassword().equals(password)) {
return R.error("Tên đăng nhập hoặc mật khẩu không đúng");
}
String token = tokenService.generateToken(user.getId(),username, "users", user.getRole());
return R.ok().put("token", token);
}
/**
* Đăng ký
*/
@IgnoreAuth
@PostMapping(value = "/register")
public R register(@RequestBody UserEntity user){
// ValidatorUtils.validateEntity(user);
if(userService.selectOne(new EntityWrapper<UserEntity>().eq("username", user.getUsername())) !=null) {
return R.error("Người dùng đã tồn tại");
}
userService.insert(user);
return R.ok();
}
/**
* Đăng xuất
*/
@GetMapping(value = "logout")
public R logout(HttpServletRequest request) {
request.getSession().invalidate();
return R.ok("Đăng xuất thành công");
}
/**
* Đặt lại mật khẩu
*/
@IgnoreAuth
@RequestMapping(value = "/resetPass")
public R resetPass(String username, HttpServletRequest request){
UserEntity user = userService.selectOne(new EntityWrapper<UserEntity>().eq("username", username));
if(user==null) {
return R.error("Tài khoản không tồn tại");
}
user.setPassword("123456");
userService.update(user,null);
return R.ok("Mật khẩu đã được đặt lại thành: 123456");
}
/**
* Danh sách
*/
@RequestMapping("/page")
public R page(@RequestParam Map params,UserEntity user){
EntityWrapper<UserEntity> ew = new EntityWrapper<UserEntity>();
PageUtils page = userService.queryPage(params, MPUtil.sort(MPUtil.between(MPUtil.allLike(ew, user), params), params));
return R.ok().put("data", page);
}
/**
* Danh sách
*/
@RequestMapping("/list")
public R list( UserEntity user){
EntityWrapper<UserEntity> ew = new EntityWrapper<UserEntity>();
ew.allEq(MPUtil.allEQMapPre( user, "user"));
return R.ok().put("data", userService.selectListView(ew));
}
/**
* Thông tin
*/
@RequestMapping("/info/{id}")
public R info(@PathVariable("id") String id){
UserEntity user = userService.selectById(id);
return R.ok().put("data", user);
}
/**
* Lấy thông tin người dùng hiện tại từ session
*/
@RequestMapping("/session")
public R getCurrUser(HttpServletRequest request){
Long id = (Long)request.getSession().getAttribute("userId");
UserEntity user = userService.selectById(id);
return R.ok().put("data", user);
}
/**
* Lưu
*/
@PostMapping("/save")
public R save(@RequestBody UserEntity user){
// ValidatorUtils.validateEntity(user);
if(userService.selectOne(new EntityWrapper<UserEntity>().eq("username", user.getUsername())) !=null) {
return R.error("Người dùng đã tồn tại");
}
userService.insert(user);
return R.ok();
}
/**
* Cập nhật
*/
@RequestMapping("/update")
public R update(@RequestBody UserEntity user){
// ValidatorUtils.validateEntity(user);
userService.updateById(user);//Cập nhật toàn bộ
return R.ok();
}
/**
* Xóa
*/
@RequestMapping("/delete")
public R delete(@RequestBody Long[] ids){
userService.deleteBatchIds(Arrays.asList(ids));
return R.ok();
}
}
2. Module Tải lên tệp
package com.controller;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.UUID;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.annotation.IgnoreAuth;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.entity.ConfigEntity;
import com.entity.EIException;
import com.service.ConfigService;
import com.utils.R;
/**
* Bảng ánh xạ tệp tải lên
*/
@RestController
@RequestMapping("file")
@SuppressWarnings({"unchecked","rawtypes"})
public class FileController{
@Autowired
private ConfigService configService;
/**
* Tải lên tệp
*/
@RequestMapping("/upload")
public R upload(@RequestParam("file") MultipartFile file,String type) throws Exception {
if (file.isEmpty()) {
throw new EIException("Tệp tải lên không được để trống");
}
String fileExt = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")+1);
File path = new File(ResourceUtils.getURL("classpath:static").getPath());
if(!path.exists()) {
path = new File("");
}
File upload = new File(path.getAbsolutePath(),"/upload/");
if(!upload.exists()) {
upload.mkdirs();
}
String fileName = new Date().getTime()+"."+fileExt;
File dest = new File(upload.getAbsolutePath()+"/"+fileName);
file.transferTo(dest);
FileUtils.copyFile(dest, new File("C:\\Users\\Desktop\\jiadian\\springbootl7own\\src\\main\\resources\\static\\upload"+"/"+fileName));
if(StringUtils.isNotBlank(type) && type.equals("1")) {
ConfigEntity configEntity = configService.selectOne(new EntityWrapper<ConfigEntity>().eq("name", "faceFile"));
if(configEntity==null) {
configEntity = new ConfigEntity();
configEntity.setName("faceFile");
configEntity.setValue(fileName);
} else {
configEntity.setValue(fileName);
}
configService.insertOrUpdate(configEntity);
}
return R.ok().put("file", fileName);
}
/**
* Tải xuống tệp
*/
@IgnoreAuth
@RequestMapping("/download")
public ResponseEntity download(@RequestParam String fileName) {
try {
File path = new File(ResourceUtils.getURL("classpath:static").getPath());
if(!path.exists()) {
path = new File("");
}
File upload = new File(path.getAbsolutePath(),"/upload/");
if(!upload.exists()) {
upload.mkdirs();
}
File file = new File(upload.getAbsolutePath()+"/"+fileName);
if(file.exists()){
/*if(!fileService.canRead(file, SessionManager.getSessionUser())){
getResponse().sendError(403);
}*/
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.setContentDispositionFormData("attachment", fileName);
return new ResponseEntity(FileUtils.readFileToByteArray(file),headers, HttpStatus.CREATED);
}
} catch (IOException e) {
e.printStackTrace();
}
return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
3. Lớp tiện ích đóng gói mã nguồn
package com.utils;
import java.util.HashMap;
import java.util.Map;
/**
* Trả về dữ liệu
*/
public class R extends HashMap {
private static final long serialVersionUID = 1L;
public R() {
put("code", 0);
}
public static R error() {
return error(500, "Lỗi không xác định, vui lòng liên hệ quản trị viên");
}
public static R error(String msg) {
return error(500, msg);
}
public static R error(int code, String msg) {
R r = new R();
r.put("code", code);
r.put("msg", msg);
return r;
}
public static R ok(String msg) {
R r = new R();
r.put("msg", msg);
return r;
}
public static R ok(Map<String, Object> map) {
R r = new R();
r.putAll(map);
return r;
}
public static R ok() {
return new R();
}
public R put(String key, Object value) {
super.put(key, value);
return this;
}
}