【开源】基于JAVA+Vue+SpringBoot的超市账单管理系统

在这里插入图片描述


目录

  • 一、摘要
    • 1.1 项目介绍
    • 1.2 项目录屏
  • 二、功能模块
  • 三、系统设计
    • 3.1 总体设计
    • 3.2 前端设计
    • 3.3 后端设计
    • 在这里插入图片描述
  • 四、系统展示
  • 五、核心代码
    • 5.1 查询供应商
    • 5.2 查询商品
    • 5.3 新增超市账单
    • 5.4 编辑超市账单
    • 5.5 查询超市账单
  • 六、免责说明


一、摘要

1.1 项目介绍

基于JAVA+Vue+SpringBoot+MySQL的超市账单管理系统,包含供应商模块、商品管理模块、超市账单模块,还包含系统自带的用户管理、部门管理、角色管理、菜单管理、日志管理、数据字典管理、文件管理、图表展示等基础模块,超市账单管理系统基于角色的访问控制,给超市管理员、店长使用,可将权限精确到按钮级别,您可以自定义角色并分配权限,系统适合设计精确的权限约束需求。

1.2 项目录屏


二、功能模块

本管理系统主要是适用于中小型超市账单的管理,既要能让用户能够快速上手,也要保证基本功能的齐全,还要易于系统的维护。所以一个比较成熟的超市账单管理系统应包含以下几个模块:

  1. 登录模块:用户通过账号密码可以登入不用权限的账号。
  2. 用户管理模块:查看用户信息、修改用户信息、批量或单个删除用户、增加用户信息、禁用和启动用户账号功能可以在该模块实现。
  3. 供应商管理模块:查看供应商信息、修改供应商信息、批量或单独删除供应商、增加供应商的功能在该模块实现。
  4. 账单管理模块:查看账单信息、修改账单信息、批量或单独删除账单、增加账单的功能在该模块实现。
  5. 部门管理模块:可以建立不同的部门,批量或单独删除某一个部门,修改部门信息以及可以给某个部门设立一个或者多个子部门。
  6. 权限管理模块:不同账号所拥有的权限可以该模块进行分配。
  7. 日志管理模块:系统操作人员登陆系统的时间会被记录在该管理模块下。
  8. 退出登陆模块:退出当前账户到登陆页面。

三、系统设计

本系统主要分为前端和后端两个组成部分,在前端我将采用当下比较流行的技术VUE和Element UI搭建起简洁大方的前端页面,方便用户操作和用户的体验感。

在后端我将采用当下比较流行的技术SpringBoot来完成开发,因为SpringBoot兼容了许多框架,可以帮助我快速搭建起整个系统的框架,其中最核心的框架就是SSM框架,当一个用户在网站页面上发送请求,控制层接收到用户的请求,调用业务层去实现,业务管理层调用不同的执行方法去处理,然后业务层调用DAO层去数据库里进行增删改查的操作,最后将数据结果给用户反馈。

在数据库设计方面,如何设计一个合理安全的数据库,首先要考虑的就是对一个数据库中所有表的属性设置,包括属性的的长度、类型、主外键的设置、索引的设置等等。然后在实际设计开发系统的过程中可以参考一些成熟典型的系统的设计思想,可以帮助我们大大提高程序的可行性、完整性和安全性。

3.1 总体设计

.
在这里插入图片描述

根据本系统的业务功能需求分析,设计出该系统的简易功能设计图(如图3-1),首先在登陆界面输入账号密码,然后就可以进入主界面,根据不同的账号权限,能呈现出不同的系统界面。在登陆界面中包括了员工管理功能,商品管理功能,供应商管理功能,账单管理功能、部门管理功能、系统操作权限管理功能和系统日志输出功能。增删改查四种操作均可在员工管理界面,商品管理界面,供应商管理界面,账单管理、部门管理界面中使用。在权限管理界面,如果是管理员身份登陆可以给用户赋予权限,也可以撤销权限。当要查看一些操作记录和用户登陆系统时间的操作可以在系统监控功能模块中的日志输出查看。

3.2 前端设计

一个简单的前端页面构成三个基本要素:HTML、CSS、JavaScript。有了这三要素就可以完成一个前端页面的开发。Vue框架同样兼容这三个要素,并且如果真要自己写出一个美观的页面是十分麻烦的,但Vue支持使用其他的组件库,例如Element UI,是一款网站快速成型工具,上面有许多美观的页面组件。相比于传统的前端页面开发,是通过操作DOM,形成基本的视图结构,然后再通过CSS的修饰,让页面变得美观,最后在涉及交互部分,就需要用到JavaScript来接收用户请求,并通事件响应来进行交互操作,并且在事件的处理函数中涉及到各种数据的修改。我们知道一个网站包含的页面元素是非常多的,在结构和很庞大的页面中,如果视图和数据都混合在一起,要想操作其中的一个元素的难度就会很大,正所谓牵一发而动全身。而Vue的核心在于它主关注视图层,它将视图单独剥离出来,主要目的就是分离视图层和数据层,而实现分离是通过MVVM模式,MVVM的核心是ViewModel层,它能够随时观察到数据的变化,并对视图对应的内容实时进行更新,当视图发生改变的同时,数据也会随之发生变化,这就是双向绑定。

3.3 后端设计

在后端方面我将选择基于SpringBoot框架来进行开发。之所以选择用框架来开发是学过Javaweb的同学都知道,开发一个web应用,从最初开始接触Servlet结合Tomcat服务器,然后再通过手动连接JDBC来进行数据连接,在IDEA软件上写SQL查询语句。这样就会导致一个问题,会产生大量繁杂冗余的代码,并且代码出错率高,不容易排查,大大加长了开发时间。

所以我将运用框架来开发系统,利用SpringBoot框架进行系统开发,可以快速搭建出系统的框架,只需要我们把依赖和配置文件导入,剩下的就是编写业务逻辑功能。经过2个月我自己对Spring的学习研究,总结出SpringBoot框架
开发便捷的原因是从以下三个策略出发。

  1. SpringBoot可以通过启动器来管理项目所需要的依赖,无需指定依赖的版本。
  2. SpringBoot利用几个核心注解做到了根据添加的依赖进行自动配置,不需要配置xml文件。
  3. SpringBoot内置了许多项目所需要的功能,例如数据监控、用户认证。

在还没有使用SpringBoot框架之前,我也早早听说了这个框架厉害的传闻,并且一直流传着一句话“约定大于配置”,在还没有深入学习之前,我还是对这句话一知半解,但随着深入学习,我开始慢慢理解这句话的含义,简单的理解来说就是在使用SpringBoot框架的项目中,在没有规定配置的地方,都是采用默认的配置,而开发人员仅仅需要做的就是当有特殊需求的时候,通过config模块中根据需求自定义配置就可以了,这样就帮助开发人员大大减少了配置工作,这就是所谓的“约定”。

并且SpringBoot集成了很多框架配置和应用模板,当需要什么框架和模板,直接开箱就能使用。但在SpringBoot项目开发中,本质最主要的还是SSM框架,SSM框架就是Spring、SpringMVC、Mybatis,在使用SpringBoot时,它就会默认配置好这个框架的使用方式。整个系统的执行流程(如图4-1),从客户端发送请求到服务器,控制层接收到用户的请求,调用业务层去实现,业务管理层调用不同的执行方法去处理,业务层调用DAO层去数据库里进行增删改查的操作,然后将数据结果反馈给用户。

在这里插入图片描述

四、系统展示

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


五、核心代码

5.1 查询供应商

@RequestMapping(value = "/getByPage", method = RequestMethod.GET)
@ApiOperation(value = "分页获取供应商")
public Result<IPage<Supplier>> getByPage(@ModelAttribute Supplier supplier, @ModelAttribute PageVo page){

    QueryWrapper<Supplier> qw = new QueryWrapper<>();
    if(StrUtil.isNotBlank(supplier.getAddress())) {
        qw.eq("address",supplier.getAddress());
    }
    if(StrUtil.isNotBlank(supplier.getMobile())) {
        qw.eq("mobile",supplier.getMobile());
    }
    if(StrUtil.isNotBlank(supplier.getName())) {
        qw.eq("name",supplier.getName());
    }
    if(StrUtil.isNotBlank(supplier.getType())) {
        qw.eq("type",supplier.getType());
    }
    IPage<Supplier> data = iSupplierService.page(PageUtil.initMpPage(page),qw);
    return new ResultUtil<IPage<Supplier>>().setData(data);
}

5.2 查询商品

@RequestMapping(value = "/getByPage", method = RequestMethod.GET)
@ApiOperation(value = "查询商品")
public Result<IPage<Commodity>> getByPage(@ModelAttribute Commodity commodity, @ModelAttribute PageVo page){
    QueryWrapper<Commodity> qw = new QueryWrapper<>();
    if(StrUtil.isNotBlank(commodity.getName())) {
        qw.eq("name",commodity.getName());
    }
    if(StrUtil.isNotBlank(commodity.getType())) {
        qw.eq("type",commodity.getType());
    }
    if(StrUtil.isNotBlank(commodity.getStock())) {
        qw.eq("stock",commodity.getStock());
    }
    if(StrUtil.isNotBlank(commodity.getSupplierId())) {
        qw.eq("supplier_id",commodity.getSupplierId());
    }
    if(StrUtil.isNotBlank(commodity.getUnitPrice())) {
        qw.eq("unit_price",commodity.getUnitPrice());
    }
    IPage<Commodity> data = iCommodityService.page(PageUtil.initMpPage(page),qw);
    for (Commodity com : data.getRecords()) {
        Supplier supplier = iSupplierService.getById(com.getSupplierId());
        if(supplier != null) {
            com.setSupplierName(supplier.getName());
        }
    }
    return new ResultUtil<IPage<Commodity>>().setData(data);
}

5.3 新增超市账单

@RequestMapping(value = "/insert", method = RequestMethod.POST)
@ApiOperation(value = "新增账单")
public Result<Bill> insert(Bill bill) {
    bill.setDateTime(DateUtils.getCompleteNowDate());
    bill.setUserId(securityUtil.getCurrUser().getId());
    String price = bill.getPrice();
    String number = bill.getNumber();
    Double sum = Double.parseDouble(price) * Double.parseDouble(number);
    sum = Math.ceil(sum * 10.0) / 10.0;
    bill.setSum(sum + "");
    if(iBillService.saveOrUpdate(bill)){
        return new ResultUtil<Bill>().setData(bill);
    }
    return new ResultUtil<Bill>().setErrorMsg("新增账单失败");
}

5.4 编辑超市账单

@RequestMapping(value = "/update", method = RequestMethod.POST)
@ApiOperation(value = "编辑账单")
public Result<Bill> update(Bill bill) {
    if(iBillService.saveOrUpdate(bill)){
        return new ResultUtil<Bill>().setData(bill);
    }
    return new ResultUtil<Bill>().setErrorMsg("编辑账单失败");
}

5.5 查询超市账单

@RequestMapping(value = "/getByPage", method = RequestMethod.GET)
@ApiOperation(value = "查询账单")
public Result<IPage<Bill>> getByPage(@ModelAttribute Bill bill, @ModelAttribute PageVo page){
    QueryWrapper<Bill> qw = new QueryWrapper<>();
    if(!ZwzNullUtils.isNull(bill.getUserId())) {
        qw.eq("user_id",bill.getUserId());
    }
    if(!ZwzNullUtils.isNull(bill.getCommodityId())) {
        qw.eq("commodity_id",bill.getCommodityId());
    }
    if(!ZwzNullUtils.isNull(bill.getSupplierId())) {
        qw.eq("supplier_id",bill.getSupplierId());
    }
    IPage<Bill> data = iBillService.page(PageUtil.initMpPage(page),qw);
    for (Bill bill1 : data.getRecords()) {
        Supplier supplier = iSupplierService.getById(bill1.getSupplierId());
        if(supplier != null) {
            bill1.setSupplierName(supplier.getName());
        } else {
            bill1.setSupplierName("无");
        }
        Commodity commodity = iCommodityService.getById(bill1.getCommodityId());
        if(commodity != null) {
            bill1.setCommodityName(commodity.getName());
        } else {
            bill1.setCommodityName("无");
        }
        User user = iUserService.getById(bill1.getUserId());
        if(user != null) {
            bill1.setUserName(user.getNickname());
        } else {
            bill1.setUserName("无");
        }
    }
    return new ResultUtil<IPage<Bill>>().setData(data);
}

六、免责说明

  • 本项目仅供个人学习使用,商用授权请联系博主,否则后果自负。
  • 博主拥有本软件构建后的应用系统全部内容所有权及独立的知识产权,拥有最终解释权。
  • 如有问题,欢迎在仓库 Issue 留言,看到后会第一时间回复,相关意见会酌情考虑,但没有一定被采纳的承诺或保证。

下载本系统代码或使用本系统的用户,必须同意以下内容,否则请勿下载!

  1. 出于自愿而使用/开发本软件,了解使用本软件的风险,且同意自己承担使用本软件的风险。
  2. 利用本软件构建的网站的任何信息内容以及导致的任何版权纠纷和法律争议及后果和博主无关,博主对此不承担任何责任。
  3. 在任何情况下,对于因使用或无法使用本软件而导致的任何难以合理预估的损失(包括但不仅限于商业利润损失、业务中断与业务信息丢失),博主概不承担任何责任。
  4. 必须了解使用本软件的风险,博主不承诺提供一对一的技术支持、使用担保,也不承担任何因本软件而产生的难以预料的问题的相关责任。

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【大数据架构】OLAP实时分析引擎选型

OLAP引擎面临的挑战 常见OLAP引擎对比 OLAP分析场景中&#xff0c;一般认为QPS达到1000就算高并发&#xff0c;而不是像电商、抢红包等业务场景中&#xff0c;10W以上才算高并发&#xff0c;毕竟数据分析场景&#xff0c;数据海量&#xff0c;计算复杂&#xff0c;QPS能够达到1…

手部受伤手术完就万事大吉?不!还有50%靠康复

在骨科急诊病人中&#xff0c;手外伤约占就诊人数的四分之一&#xff0c;比如常见的擦伤、撕裂伤、挫伤、肌肉拉伤、关节韧带扭伤、骨折及关节脱位等。对于此类损伤&#xff0c;手术的功劳占一半&#xff0c;另一半则是术前术后的功能康复训练。 所以&#xff0c;对手外伤病人来…

systick_config 建立系统时钟

1.systick_config&#xff0c; 建立1ms&#xff08;可以改&#xff09;的系统时钟&#xff0c;包含计数值&#xff0c; 初始值&#xff0c;中断 2. 计数值 SystemCoreClock&#xff0c;对于STM32F4xx 系统时钟为168M, 那么假如168M为1S, /1000为1ms, /1000000为1us 3. SysTick_…

如何使用 Helm 在 K8s 上集成 Prometheus 和 Grafana|Part 2

在 Part 1 中&#xff0c;我们一起了解了什么是 Prometheus 和 Grafana&#xff0c;以及使用这些工具的前提条件和优势。在本部分&#xff0c;将继续带您学习如何安装 Helm 以及如何使用 Prometheus Helm Charts。 开始使用 Helm 和 Helm Chart ArtifactHub 为 Helm Chart 提供…

限流算法之计数器法

文章目录 一、计数器法是什么&#xff1f;二、模拟限流算法java版效果 一、计数器法是什么&#xff1f; 计数器法是限流算法里最简单也是最容易实现的一种算法。 比如&#xff1a;对于一个接口来说&#xff0c;我们1分钟的访问次数不能超过100个。那么我们可以这么做&#xff…

删除sys_file表中的文件信息后同步操作表单中对应的文件字段信息

需求&#xff1a;由于系统的表单文件上传/删除操作与表单的保存操作不同时进行&#xff0c;所以需要调整 细节&#xff1a;&#xff08;某个表&#xff1a;A表&#xff09;表单的文件字段只是保存了上传文件的id&#xff0c;名称&#xff0c;真正的文件保存是保存在一个系统的文…

异步编程利器:CompletableFuture深度解析

本文已收录至Github&#xff0c;推荐阅读 &#x1f449; Java随想录 微信公众号&#xff1a;Java随想录 文章目录 摘要如何使用源码解析基本结构内部原理执行流程 方法介绍创建对象异步执行任务链式操作异步任务组合异常处理取值与状态超时控制与取消操作依赖完成并发限制记忆…

yum来安装php727

yum 安装php727,一键安装&#xff0c;都是安装在系统的默认位置&#xff0c;方便快捷 先确定linux平台中centos的版本信息&#xff0c;一下内容针对el7 查看linux版本 &#xff1a; cat /etc/redhat-release 查看内核版本命令&#xff1a; cat /proc/version (0)如果有安装好…

频率阈图像滤波

介绍 频率阈图像滤波是一种在频域中进行图像处理的方法&#xff0c;它基于图像的频率分布来实现滤波效果。具体步骤如下&#xff1a; 将原始图像转换到频域&#xff1a;使用快速傅里叶变换&#xff08;FFT&#xff09;将图像从空间域转换到频域。对频域图像应用频率阈滤波器&a…

力扣 | 139. 单词拆分

主要是要注意组合的顺序是任意的&#xff01;所以就要先选择目标字串&#xff0c;再选择wordDict public boolean wordBreak(String s, List<String> wordDict) {// dp[i]: 表示前 i 个字符组成的子串是否可以被 wordDict 中的字符串组合而成boolean[] dp new boolean[s…

Prometheus实战篇:Prometheus告警简介

Prometheus告警简介 简介 告警能力在Prometheus的架构中被划分为俩个独立的部分.如下图所示,通过在Prometheus中定义AlertRule(告警规则),Prometheus会周期性的对告警规则进行计算,如果满足告警触发条件就会向Alertmanager发送告警信息 alertManager作为一个独立的组件,负责接…

Jenkins-Pipeline语法总结大全

这里写目录标题 pipeline的组成1、pipeline最简单结构1.1、pipeline1.2、stages1.3、stage1.4、steps1.5、agent 2、post3、pipeline支持的命令3.1、environment3.2、tools3.3、input3.4、options3.5、parameters3.6、parallel3.7、triggers3.8、when pipeline的组成 1、pipel…

GPT-4与DALL·E 3:跨界融合,开启绘画与文本的新纪元

在人工智能的发展浪潮中&#xff0c;MidTool&#xff08;https://www.aimidtool.com/&#xff09;的GPT-4与DALLE 3的集成代表了一个跨越式的进步。这一集成不仅仅是技术的结合&#xff0c;更是艺术与文字的完美融合&#xff0c;它为创意产业带来了革命性的变革。本文将探讨GPT…

12.22 探探 数分 已HR面

岗位信息 1222 3.30PM 1面 40min 能感觉数据基建还不是很完善 因此 问了一些指标体系的问题还挺多 自我介绍能力考察1.说说你是怎么异常归因的以付费场景项目为例2.归因中如果遇到一个页面同时存在有3个实验在跑 无法归因出数据的异常是哪个改动造成的怎么办&#xff1f;3.讲…

抖捧AI实景自动直播,开启2024直播新篇章!

在如今互联网的时代&#xff0c;各个行业的实体商家都面临着新的挑战与机遇&#xff0c;而传统做线下经营的方式&#xff0c;已经逐渐被直播与短视频宣传所超越&#xff0c;但还有不少商家思维存在于传统的宣传方式上&#xff0c;也错失了很多的机会&#xff0c;今天就给大家介…

基于JavaWeb+BS架构+SpringBoot+Vue基于web的多媒体素材管理系统的设计和实现

基于JavaWebBS架构SpringBootVue基于web的多媒体素材管理系统的设计和实现 文末获取源码Lun文目录前言主要技术系统设计功能截图订阅经典源码专栏Java项目精品实战案例《500套》 源码获取 文末获取源码 Lun文目录 1 绪 论 1 1.1选题背景与意义 1 1.1 研究背景 1 1.2 研究意义…

操作系统--虚拟内存--物理内存

虚拟内存地址: 出现的原因&#xff1a;单片机时代&#xff0c;cpu直接操作物理内存&#xff0c;每次只能有一个进程操作&#xff0c;如果多个 在 4GB 物理内存的机器上&#xff0c;申请 8G 内存会怎么样&#xff1f; 1、明确是32位机器&#xff0c;还是64位机器 32位&#xf…

api网关-kong

选型 api网关相关功能 服务的路由 动态路由负载均衡 服务发现 限流 熔断、降级 流量管理 黑白名单反爬策略 控制台&#xff1a;通过清晰的UI界面对网关集群进行各项配置。 集群管理&#xff1a;Goku网关节点是无状态的&#xff0c;配置信息自动同步&#xff0c;支持节点水…

照片动起来-yanderifier

&#x1f3e1; 个人主页&#xff1a;IT贫道-CSDN博客 &#x1f6a9; 私聊博主&#xff1a;私聊博主加WX好友&#xff0c;获取更多资料哦~ &#x1f514; 博主个人B栈地址&#xff1a;豹哥教你学编程的个人空间-豹哥教你学编程个人主页-哔哩哔哩视频 目录 图片动起来实现步骤 …

典型的无人机打击技术

无人机打击技术主要指的是用于中和、摧毁或干扰无人机&#xff08;UAV&#xff09;的各种技术手段。 这些技术随着无人机的广泛使用而迅速发展&#xff0c;特别是在军事和安全领域。下面是一些主要的无人机打击技术及其原理&#xff1a; 射频干扰&#xff08;RF Jamming&#x…