SpringBoot+Vue物流仓储管理系统

news2024/11/17 17:44:03

项目背景

        在信息化的时代,效率和速度就变得尤为重要了,具有高效率和速度就具有更好的竞争力,更受客户欢迎。与此同时,网购与人们的生活息息相关,顾客在网上购买的商品需要通过物流公司对这些商品进行管理和配送,那么物流的管理在这个过程中就显得尤为重要了,怎样高效快速的对仓库的商品进行管理,直接影响物流的速度,从而影响顾客的满意程度,这将直接关系到公司利益的盈亏。

        现在也有很多成熟的网上仓库管理系统,对仓库商品进行很好的管理,但是不是所有的仓库公司的商品都是一样的,那些流程也不是一成不变的,所以这些成熟的网上仓库管理系统不可能适应所有的仓库公司。所以我想做一个通用性强功能简约的仓库管理系统,来适应大部分仓库公司的基本需求,虽然这样不能满足这些仓库公司的一些特定的要求,但是所有公司可以在此基础上进行简单的修改和添加就能满足自己仓库管理的功能,这样一来一个基本的通用性强的仓库管理系统我觉得就很有意义了。所以本次项目就是做一个针对仓库公司的仓库管理系统。


系统架构

本项目采用前后端分离的思想,划分为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项目管理工具

功能概况

  1. 基础管理:商品管理、来往单位、员工管理、仓库管理
  2. 销售管理:销售开票、销售记录
  3. 配送管理:申请配送、配送列表
  4. 运输管理:车辆资料、驾驶员资料
  5. 图表分析:入库分析、出库分析(使用echarts技术)
  6. 系统管理:安全设置、操作员管理、权限列表
  7. 日志管理:登录日志、操作日志
  8. 登录注册:邮箱登录、邮箱验证码登录、用户注册(默认注册后就是超级管理员)

功能截图

登录页

 注册页

 商品管理

来往单位

员工管理 

仓库管理 

销售开票 

销售记录 

配送列表 

 申请配送

车辆管理 

驾驶员资料 

登录日志 

操作日志


功能核心代码

用户登录功能实现:

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源码分类即可看到文章

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/111513.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

十五、Docker 网络

1、概述 Docker 容器和服务如此强大的原因之一是您可以将它们连接在一起&#xff0c;或将它们连接到非 Docker 工作负载。Docker 容器和服务甚至不需要知道它们部署在 Docker 上&#xff0c;或者它们的对等体是否也是 Docker 工作负载。无论您的 Docker 主机运行 Linux、Window…

Doo Prime 为泰国 SOS 儿童村送温暖,公益有起点爱心无疆界

一年一度的圣诞节即将来临&#xff0c;在这欢乐的时刻&#xff0c; Doo Prime 荣幸地宣布 &#xff0c;向泰国 SOS 儿童村捐赠了 35 万泰铢 ( 约合 1.23 万美元 )&#xff0c;作为泰国南部城市合艾府 SOS 儿童村的房屋翻修费用。 Doo Prime 希望 SOS 儿童村的孩子们都能在温馨…

【小程序】网络数据请求

目录 1. 小程序中网络数据请求的限制 2. 配置 request 合法域名 3. 发起 GET 请求 4. 发起 POST 请求 5. 在页面刚加载时请求数据 5. 跳过 request 合法域名校验 6. 关于跨域和 Ajax 的说明 1. 小程序中网络数据请求的限制 出于安全性方面的考虑&#xff0c;小程序官方…

【目标检测】Objects as Points

目录概述细节anchor-base vs anchor free网络结构标注损失函数学习资料概述 本文是一个anchor-free的目标检测算法。 【2019】【CenterNet】 研究的问题&#xff1a; 如何更好地将目标检测问题建模为关键点检测问题 提出的方法&#xff1a; 一个简单高效的目标检测方法Cent…

抖音年货节增长秘籍:横向做阵地,纵向定节奏,提前深种草

抖音好物年货节即将到来&#xff0c;对于品牌来说&#xff0c;这将是新一年首次生意爆发的机会。为了更好的融入抖音电商生态&#xff0c;做好数字化经营主阵地&#xff0c;品牌面临多个新挑战&#xff1a; 大促Bigday流量费用高&#xff0c;品牌怎样更高效获取流量&#xff1f…

数据库设计说明书(GB8567——88)基于协同的在线表格forture-sheet

数据库设计说明书&#xff08;GB8567——88&#xff09; 1引言 1.1编写目的 数据库的设计是为了以后编码、测试以及维护阶段的后台数据的存储做准备。应用于系统开发前期&#xff0c;为后期数据库设计指引方向。 预期的读者&#xff1a;系统开发人员、系统测试人员和系统维…

瑞昱rtl819x-SDK-v3.4.14b的watchdog分析

watchdog 看门狗&#xff0c;又叫watchdog timer&#xff0c;是一个定时器电路&#xff0c;一般有一个输入&#xff0c;叫喂狗或踢狗&#xff1b;一个输出到MCU 的 RST 端&#xff0c;MCU 正常工作的时候&#xff0c;每隔一段时间输出一个信号到喂狗端&#xff0c;给 WDT 清零…

SQL注入渗透与攻防(八)之延时注入

目录 基于时间的SQL盲注 - 延时注入 案列演示 基于时间的SQL盲注 - 延时注入 关于延时注入的使用场景一般在我们测试的注入点没有报错信息又没有回显点的情况下进行的。通过对于时间的延时判断来猜解数据。在实战过程中并不推荐大家通过延时注入去判断数据库&#xff0c;因为…

转行做程序员,难吗

在互联网急速发展的这几年里&#xff0c;程序员这个职业&#xff0c;成为了很多人的心之所向。虽然高薪背后往往伴随着高强度的工作节奏和压力&#xff0c;但是也不妨碍大量的人在编程培训或者自学编程的道路上前仆后继。 那么转行程序员真的容易吗&#xff1f;下面就跟大家分享…

无需编程即可将chatgpt接入自己的微信公众号

ChatGpt是openai推出的GPT3文本生成机器人。该机器人主要完成文本生成相关任务。机器人可以自主进行写作、翻译、修改语法、角色扮演的&#xff0c;甚至编写程序。网上有很多接入方法&#xff0c;大部份需要编程&#xff0c;并且需要注册openai账号获取appkey。本文所介绍的方法…

datagridview如何根据不同的按钮显示不同的表

以我设计的为例&#xff1a; 双击按钮&#xff0c;会自动创建三个事件 以第一个按钮为例&#xff1a;在其中添加如下代码 SqlConnection sqlcon new SqlConnection(); sqlcon.ConnectionString "";//双引号内填入你的数据库连接字符 sqlcon.Open(); string sql &…

UG NX二次开发(C#)-获取模型文件的预览图片

文章目录 1.前言2. 模型文件预览图介绍3.采用二次开发的方法获取模型的预览图4.验证1.前言 UG NX保持的prt文件中保存了模型的预览位图,但是采用UG NX二次开发时不能直接提取出来,本文讲解一下将prt文件的预览位图提取出来并单独保存。 2. 模型文件预览图介绍 如果我们在UG…

【字体】写代码编程字体展示推荐

写代码编程字体展示推荐 零、适合写代码编程的字体 什么样的字体适合写代码用&#xff1f;一般来讲&#xff0c;写代码的字体要求字母的宽度一致、轮廓清晰美观、l1i&#xff0c;0oO易于分辨、清晰易分辨的标点等&#xff0c;甚至有强迫症的还要中文与英文严格2:1对齐。下面收…

机器学习 | 决策树

一.基本原理 决策树是一种树状结构模型&#xff0c;每一个根节点都是一个特征判断&#xff0c;它的叶子节点就是它的特征分类结果 决策树是一种分类和回归的基本模型&#xff0c;是一棵树的形式&#xff0c;其实就是将平时所说的 if-else 语句构建成了树的形式。决策树主要包…

使用 SQL 别名简化查询并自定义结果

别名能够在不影响基础表或视图的情况下临时重命名表或列。作为大多数甚至所有关系数据库管理系统都支持的 SQL 功能&#xff0c;别名是简化查询和/或自定义结果集中列标题的好方法。在这篇文章中&#xff0c;我们将使用 Navicat Premium 16 来完成这两项工作。 重命名列 许多…

带宽消耗以及Swap(上)

今天我们来看一个真实的案例。事情是这样的,之前有人在微信上问我一个问题,这个问题的现象很典型:典型的 TPS 上不去,响应时间增加,资源用不上。 大概的情况是这样的:有两台 4C8G 的服务器,一台服务器上有 2 个 Tomcat,一台服务器上是 DB。压测的混合场景有 4 个功能模…

【验证码逆向专栏】某验三代滑块验证码逆向分析

声明 本文章中所有内容仅供学习交流&#xff0c;抓包内容、敏感网址、数据接口均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff0c;若有侵权&#xff0c;请联系我立即删除&#xff01; 本文章未经许可禁止转载…

k8s教程(20)-pod之定时任务

文章目录01 引言02 基本语法03 案例04 文末01 引言 声明&#xff1a;本文为《Kubernetes权威指南&#xff1a;从Docker到Kubernetes实践全接触&#xff08;第5版&#xff09;》的读书笔记 Kubernetes从1.5版本开始增加了一种新类型的Job&#xff0c;即类似Linux Cron的定时任务…

SpringMVC、SSM整合

SpringMVC的工作原理&#xff08;底层Servlet的工作流程&#xff09; DispatcherServletHandlerMapping &#xff0c;返回值 HandlerExecutionChainHandlerAdapterViewResolverView ~~老版本&#xff08;过去式&#xff09; 一、搭建springmvc 第一步&#xff1a;配置打包…

互联网行业逐步回暖!就业显示有74%学员跨专业学编程!

三年以来&#xff0c;居家办公、隔离等影响已深入每个人的生活。就业形势承受着巨大的压力&#xff0c;同时就业环境也发生巨大变化&#xff0c;越来越多的人都面临转行&#xff01; 达妹被问到最多的问题是&#xff1a; 跨专业学编程的疑虑 非科班出身零基础能学会编程吗? 数…