项目背景
在信息化的时代,效率和速度就变得尤为重要了,具有高效率和速度就具有更好的竞争力,更受客户欢迎。与此同时,网购与人们的生活息息相关,顾客在网上购买的商品需要通过物流公司对这些商品进行管理和配送,那么物流的管理在这个过程中就显得尤为重要了,怎样高效快速的对仓库的商品进行管理,直接影响物流的速度,从而影响顾客的满意程度,这将直接关系到公司利益的盈亏。
现在也有很多成熟的网上仓库管理系统,对仓库商品进行很好的管理,但是不是所有的仓库公司的商品都是一样的,那些流程也不是一成不变的,所以这些成熟的网上仓库管理系统不可能适应所有的仓库公司。所以我想做一个通用性强功能简约的仓库管理系统,来适应大部分仓库公司的基本需求,虽然这样不能满足这些仓库公司的一些特定的要求,但是所有公司可以在此基础上进行简单的修改和添加就能满足自己仓库管理的功能,这样一来一个基本的通用性强的仓库管理系统我觉得就很有意义了。所以本次项目就是做一个针对仓库公司的仓库管理系统。
系统架构
本项目采用前后端分离的思想,划分为Vue前端项目和SpringBoot后端项目
前端使用Vue.js、Ant Vue Design等框架技术,由vue脚手架来构建项目,其中使用到axios异步请求技术发起请求
后端使用SpringBoot、Spring MVC、Spring Data JPA等框架技术,是一个由maven构建的项目,后端控制层统一采用Restful风格接受前端发送的请求。整个项目使用到了以下组件
- Lombok(快速生成getter、setter、有参/无参构造方法)
- JWT(生成用户登录凭证)
- SpringSecurity(权限认证框架)
数据库使用Mysql来存储数据,系统搭建只需创建数据库,系统自动创建表,无需手动创建
系统开发工具
- IntelliJ IDEA
- VSCode
- Navicat Premium 15
系统开发环境
- JDK1.8
- Node.js
- Maven项目管理工具
功能概况
- 基础管理:商品管理、来往单位、员工管理、仓库管理
- 销售管理:销售开票、销售记录
- 配送管理:申请配送、配送列表
- 运输管理:车辆资料、驾驶员资料
- 图表分析:入库分析、出库分析(使用echarts技术)
- 系统管理:安全设置、操作员管理、权限列表
- 日志管理:登录日志、操作日志
- 登录注册:邮箱登录、邮箱验证码登录、用户注册(默认注册后就是超级管理员)
功能截图
登录页
注册页
商品管理
来往单位
员工管理
仓库管理
销售开票
销售记录
配送列表
申请配送
车辆管理
驾驶员资料
登录日志
操作日志
功能核心代码
用户登录功能实现:
package com.example.api.controller;
import com.example.api.exception.AccountAndPasswordError;
import com.example.api.model.dto.LoginDto;
import com.example.api.model.entity.Admin;
import com.example.api.model.entity.LoginLog;
import com.example.api.model.enums.Role;
import com.example.api.model.support.ResponseResult;
import com.example.api.repository.AdminRepository;
import com.example.api.service.AdminService;
import com.example.api.service.LoginLogService;
import com.example.api.utils.JwtTokenUtil;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/api/admin")
@Slf4j
public class AdminController {
//获取日志对象
Logger logger = LoggerFactory.getLogger(AdminController.class);
@Resource
private AdminService adminService;
@Resource
private AdminRepository adminRepository;
@Resource
private LoginLogService loginLogService;
@GetMapping("hasInit")
public boolean hasInit() {
return adminRepository.existsAdminByRoles(Role.ROLE_SUPER_ADMIN.getValue());
}
@PostMapping("/init")
public Admin init(@RequestBody Admin admin) throws Exception {
admin.setRoles(Role.ROLE_SUPER_ADMIN.getValue());
return adminService.save(admin);
}
@GetMapping("")
@PreAuthorize("hasAnyRole('ROLE_SUPER_ADMIN' ,'ROLE_ADMIN')")
public List<Admin> findAll() {
return adminService.findAll();
}
@DeleteMapping("")
@PreAuthorize("hasAnyRole('ROLE_SUPER_ADMIN' ,'ROLE_ADMIN')")
public void delete(String id) {
adminService.delete(id);
}
@PostMapping("")
@PreAuthorize("hasAnyRole('ROLE_SUPER_ADMIN' ,'ROLE_ADMIN')")
public Admin save(@RequestBody Admin admin) throws Exception {
return adminService.save(admin);
}
@PostMapping("/login")
public Map<String, Object> loginByEmail(String type, @RequestBody LoginDto dto, HttpServletRequest request) throws Exception {
Map<String, Object> map = new HashMap<>();
Admin admin = null;
String token = null;
try {
admin = type.equals("email") ? adminService.loginByEmail(dto) : adminService.loginByPassword(dto);
token = adminService.createToken(admin,
dto.isRemember() ? JwtTokenUtil.REMEMBER_EXPIRATION_TIME : JwtTokenUtil.EXPIRATION_TIME);
}catch (Exception e){
throw new Exception("邮箱或密码错误");
}finally {
loginLogService.recordLog(dto,admin,request);
}
map.put("admin", admin);
map.put("token", token);
return map;
}
@GetMapping("/sendEmail")
public ResponseResult sendEmail(String email) throws Exception {
Boolean flag = adminService.sendEmail(email);
ResponseResult res = new ResponseResult();
if (flag){
res.setMsg("发送成功,请登录邮箱查看");
}else {
res.setMsg("发送验证码失败,请检查邮箱服务");
}
res.setStatus(flag);
return res;
}
}
日志管理功能
1、登录日志功能实现
实体类LoginLog
@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
public class LoginLog {
@Id
@GeneratedValue(generator = "uuid2")
@GenericGenerator(name = "uuid2", strategy = "org.hibernate.id.UUIDGenerator")
private String id;
//登录邮箱
private String email;
//登录状态
private Integer status;
//用户的IP地址
private String ip;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
//登录时间
private Date date;
//浏览器
private String browser;
}
控制层Controller
@RestController
@RequestMapping("/api/admin")
@Slf4j
public class AdminController {
//获取日志对象
Logger logger = LoggerFactory.getLogger(AdminController.class);
@PostMapping("/login")
public Map<String, Object> loginByEmail(String type, @RequestBody LoginDto dto, HttpServletRequest request) throws Exception {
Map<String, Object> map = new HashMap<>();
Admin admin = null;
String token = null;
try {
admin = type.equals("email") ? adminService.loginByEmail(dto) : adminService.loginByPassword(dto);
token = adminService.createToken(admin,
dto.isRemember() ? JwtTokenUtil.REMEMBER_EXPIRATION_TIME : JwtTokenUtil.EXPIRATION_TIME);
}catch (Exception e){
throw new Exception("邮箱或密码错误");
}finally {
//记录登录日志
loginLogService.recordLog(dto,admin,request);
}
map.put("admin", admin);
map.put("token", token);
return map;
}
}
2、记录操作日志的功能,主要采用了Spring AOP技术实现,对含有@Log注解的控制层方法进行日志记录的功能
实体类SystemLog
package com.example.api.model.entity;
import com.example.api.model.enums.BusincessType;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import java.time.LocalDateTime;
@Entity
@Data
@NoArgsConstructor
public class SystemLog {
@Id
@GeneratedValue(generator = "uuid2")
@GenericGenerator(name = "uuid2", strategy = "org.hibernate.id.UUIDGenerator")
//主键
private String id;
//账号
private String account;
//功能模块
private String module;
//操作类型
@Column(columnDefinition = "varchar(30) default 'LTD' not null")
private String busincessType;
//用户IP
@Column(columnDefinition = "varchar(40) default 'LTD' not null")
private String ip;
//请求方法
@Column(columnDefinition = "varchar(100) default 'LTD' not null")
private String method;
//操作时间
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime time;
}
操作日志注解如下:
@Target(ElementType.METHOD) //目标类型
@Retention(RetentionPolicy.RUNTIME) //作用范围
@Documented
public @interface Log {
/*
功能模块
*/
String moudle() default "";
/*
操作类型
*/
BusincessType type();
}
业务操作类型枚举类
package com.example.api.model.enums;
/*
业务操作类型
*/
public enum BusincessType {
OTHER("其他"), //其他
QUERY("查询"), //查询
INSERT("新增"), //新增
UPDATE("更新"), //更新
DELETE("删除"), //删除
EXPORT("导出"), //导出
FORCE("退出"); //强制退出
private BusincessType(String name){
this.name=name;
}
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}
如何获取源码?进入《亦码》小程序,找到springboot源码分类即可看到文章