Python桌面应用之XX学院水卡报表查询系统(Tkinter+cx_Oracle)

一、功能样式

Python桌面应用之XX学院水卡报表查询系统功能:

连接Oracle数据库,查询XX学院水卡操作总明细报表,汇总数据报表,个人明细报表,进行预览并且支持导出报表

1.总明细报表样式
明细
2.汇总明细样式
汇总明细

3.个人明细样式
个人明细
4.导出报表样式
导出
5.错误提示样式
tip
tip2

二、核心点

1. 安装cx_Oracle:使用cx_Oracle三方库连接Oracle,该库使用的python版本略低,可以在[https://cx-oracle.readthedocs.io/en/latest/](https://cx-oracle.readthedocs.io/en/latest/进行查询,安装前先确定:python版本、Orale客户端版本(要不都是64位,要不都是32位),安装cx_Oracle的版本位数是跟python的位数相关的。
使用代码进行测试

import cx_Oracle
# 账户  密码  ip:1521/实例名
conn = cx_Oracle.connect('system','Yxq123456','127.0.0.1:1521/ecard'
# 挂载数据库连接游标
self.cursor = conn.cursor()
print('连接数据库成功!')

2. 多参数查询Sql: sql语句使用:参数名来定义参数,多参数使用cursor.execute(sql,(参数1,参数2)).fetchall()来查询

sql = "select a.outid ,a.name ,b.opfare,b.opdt,b.dscrp from base_customers a,rec_cust_acc b where a.customerid = b. customerid and b.opdt >= to_date(:preopdt,'yyyy-MM-dd HH24:mi:ss') and b.opdt <= to_date(:nextopdt,'yyyy-MM-dd HH24:mi:ss') order by b.opdt desc"
preopdt=self.pretimeInput.get()
nextopdt=self.nexttimeInput.get()
data = self.cursor.execute(sql,(preopdt,nextopdt)).fetchall()

**3. Treeview表格组件的使用:**这里使用了三个报表,其实可以将打开的Treeview做成一个表格class类,要使用的时候直接生成要使用的对象,传入该对象的大小,heading标题,data数据即可。

# 明细查询def Consumedetail(self):self.consumedetail = tk.Tk()self.consumedetail.title('XX学院明细查询')self.consumedetail.geometry("1000x600")# 加载滚动条scrollBar = tk.Scrollbar(self.consumedetail)scrollBar.pack(side = tk.RIGHT,fill = tk.Y)self.tree = ttk.Treeview(self.consumedetail, columns=('outid', 'name', 'opfare', 'opdt','dscrp'), show="headings", displaycolumns="#all",yscrollcommand = scrollBar.set)self.tree.pack()self.tree.heading('outid', text="学号", anchor=tk.W)self.tree.heading('name', text="姓名", anchor=tk.W)self.tree.heading('opfare', text="交易金额", anchor=tk.W)self.tree.heading('opdt', text="交易日期", anchor=tk.W)self.tree.heading('dscrp', text="交易类型", anchor=tk.W)# 设置关联scrollBar.config(command = self.tree.yview)# 每次打开清空页面for item in self.tree.get_children():self.consumedetail.tree.delete(item)sql = "select a.outid ,a.name ,b.opfare,b.opdt,b.dscrp from base_customers a,rec_cust_acc b where a.customerid = b. customerid and b.opdt >= to_date(:preopdt,'yyyy-MM-dd HH24:mi:ss') and b.opdt <= to_date(:nextopdt,'yyyy-MM-dd HH24:mi:ss') order by b.opdt desc"preopdt=self.pretimeInput.get()nextopdt=self.nexttimeInput.get()data = self.cursor.execute(sql,(preopdt,nextopdt)).fetchall()# print(data)# data = [['2013090101','张三','100','2023-10-19','PC存款']]for itm in data:self.tree.insert("",tk.END,values=itm)self.tree.pack(padx=10,pady=10, fill=tk.BOTH,expand=1)exportbtn = tk.Button(self.consumedetail,text='导出',width=8,command=self.export).pack()

4. 导出数据自定义文件名:报表里面导出数据,其实使用遍历treeview组件数据,在进行整理后写入csv文件,自定义文件名是使用filedialog.asksaveasfilename来打开文件框,里面的文件类型使用参数filetypes ,输入文件名后获取名称生成文件。这里导出的文件就只是csv文件,如果需要其他文件类型,可以自行导入其他三方库。

     def export(self):# 导出export        # 打开文件夹选择对话框# 更新标签文本# print(folder_path)list = []columns = []# 获取表格内容idfor row_id in self.tree.get_children():list.append(self.tree.item(row_id)['values'])print(len(self.tree.get_children()))   # 通过第一行获取列数生成标题# print(self.tree.item)if len(self.tree.get_children()) != 0:print('ok')folder_path = filedialog.asksaveasfilename(title='请选择一个文件',filetypes=[("CSV", ".csv")]) for i in range(0,len(self.tree.item('I001')['values'])):columns.append(self.tree.heading(column=i)['text'])# 导出csvwith open(f'{folder_path}.csv','w',newline='') as csvfile:fieldnames = columnswriter = csv.writer(csvfile)writer.writerow(fieldnames)writer.writerows(list)else:messagebox.showwarning("提示", "没有数据,无法导出")return

5.遍历Treeview表格数据与标题:获取Treeview里面的数据与标题,这里现获取id值,然后通过item获取[‘values’]值,获取标题这里先遍历了第一行有多少数据,然后使用self.tree.heading(column=i)['text']来获取标题。

 # 获取表格内容id
for row_id in self.tree.get_children():list.append(self.tree.item(row_id)['values'])
 # 通过第一行获取列数生成标题
for i in range(0,len(self.tree.item('I001')['values'])):columns.append(self.tree.heading(column=i)['text'])

三、完整代码

import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
import cx_Oracle
import time
import csv
from tkinter import filedialog# mainapp
class mainApp(object):def __init__(self,parent,**kwargs):self.root = parentcurrent_timestamp = time.time()# 将时间戳转换为本地时间的struct_time对象local_time = time.localtime(current_timestamp)# 使用strftime()方法将struct_time对象格式化为指定的时间字符串  # 挂在self时间self.pretime = time.strftime("%Y-%m-%d 00:00:00", local_time)self.nexttime = time.strftime("%Y-%m-%d %H:%M:%S", local_time)conn = cx_Oracle.connect('system','Yxq123456','127.0.0.1:1521/ecard')# conn = cx_Oracle.connect('ccense','XCXY123*','127.0.0.1:1521/ecard')# 挂载数据库连接游标self.cursor = conn.cursor()print('连接数据库成功!')self.root.config(**kwargs)self.root.title('XX学院')self.root.resizable(False, False)self.create_widgets()# 获取屏幕尺寸screen_width = self.root.winfo_screenwidth()screen_height = self.root.winfo_screenheight()# 确定窗口位置,并设置大小x_coordinate = (screen_width / 2) - 300 # 300是窗口的宽度y_coordinate = (screen_height / 2) - 200 # 200是窗口的高度self.root.geometry('650x400+{}+{}'.format(int(x_coordinate), int(y_coordinate)))# self.root.geometry("600x400")# 创建UIdef create_widgets(self):self.titleLab = tk.Label(self.root,text='XX学院水卡报表管理系统',font=("kaiti",18)).place(x=190,y=30)self.outidLab = tk.Label(self.root,text='学号:').place(x=80,y=100)self.outidInput = tk.Entry(self.root, width=20)self.outidInput.place(x=130,y=100)# 姓名# 学号self.nameLab = tk.Label(self.root,text='姓名:').place(x=380,y=100)self.nameInput = tk.Entry(self.root,width=20)self.nameInput.place(x=430,y=100)# 起始时间self.mustLabel1 = tk.Label(self.root,text='*',font=('Arial', 16),fg = 'red').place(x=45,y=160)self.pretimeLab = tk.Label(self.root,text='起始时间:').place(x=55,y=160)self.pretimeInput = tk.Entry(self.root, width=20)self.pretimeInput.place(x=130,y=160)self.pretimeInput.insert(0,self.pretime)# 终始时间self.mustLabel2 = tk.Label(self.root,text='*',font=('Arial', 16),fg = 'red').place(x=350,y=160)self.nexttimeLab = tk.Label(self.root,text='终止时间:').place(x=360,y=160)self.nexttimeInput = tk.Entry(self.root,width=20)self.nexttimeInput.place(x=430,y=160)self.nexttimeInput.insert(0,self.nexttime)self.consumeBtn = tk.Button(self.root,text='明细查询',command=self.Consumedetail,width=10).place(x=130,y=260)self.sumBtn = tk.Button(root,text='汇总查询',command=self.sumDetail,width=10).place(x=300,y=260)self.personBtn = tk.Button(root,text='个人查询',command=self.personDetail,width=10).place(x=480,y=260)# 明细查询def Consumedetail(self):self.consumedetail = tk.Tk()self.consumedetail.title('XX学院明细查询')self.consumedetail.geometry("1000x600")# 加载滚动条scrollBar = tk.Scrollbar(self.consumedetail)scrollBar.pack(side = tk.RIGHT,fill = tk.Y)self.tree = ttk.Treeview(self.consumedetail, columns=('outid', 'name', 'opfare', 'opdt','dscrp'), show="headings", displaycolumns="#all",yscrollcommand = scrollBar.set)self.tree.pack()self.tree.heading('outid', text="学号", anchor=tk.W)self.tree.heading('name', text="姓名", anchor=tk.W)self.tree.heading('opfare', text="交易金额", anchor=tk.W)self.tree.heading('opdt', text="交易日期", anchor=tk.W)self.tree.heading('dscrp', text="交易类型", anchor=tk.W)# 设置关联scrollBar.config(command = self.tree.yview)# 每次打开清空页面for item in self.tree.get_children():self.consumedetail.tree.delete(item)sql = "select a.outid ,a.name ,b.opfare,b.opdt,b.dscrp from base_customers a,rec_cust_acc b where a.customerid = b. customerid and b.opdt >= to_date(:preopdt,'yyyy-MM-dd HH24:mi:ss') and b.opdt <= to_date(:nextopdt,'yyyy-MM-dd HH24:mi:ss') order by b.opdt desc"preopdt=self.pretimeInput.get()nextopdt=self.nexttimeInput.get()data = self.cursor.execute(sql,(preopdt,nextopdt)).fetchall()# print(data)# data = [['2013090101','张三','100','2023-10-19','PC存款']]for itm in data:self.tree.insert("",tk.END,values=itm)self.tree.pack(padx=10,pady=10, fill=tk.BOTH,expand=1)exportbtn = tk.Button(self.consumedetail,text='导出',width=8,command=self.export).pack()# 汇总查询def sumDetail(self):sql = "select sum(opfare),count(acccode),dscrp from rec_cust_acc where opdt >= to_date(:preopdt,'yyyy-MM-dd HH24:mi:ss') and opdt <= to_date(:nextopdt,'yyyy-MM-dd HH24:mi:ss') group by dscrp"self.sumtail = tk.Tk()self.sumtail.title('XX学院汇总查询')self.sumtail.geometry("800x600")# 加载滚动条# exportbtn = Button(sumtail,text='导出',width=8,command=export).pack()scrollBar = tk.Scrollbar(self.sumtail)scrollBar.pack(side = tk.RIGHT,fill = tk.Y)self.tree = ttk.Treeview(self.sumtail, columns=('sum', 'count', 'dscrp'), show="headings", displaycolumns="#all",yscrollcommand = scrollBar.set)self.tree.pack()self.tree.heading('sum', text="总金额", anchor=tk.W)self.tree.heading('count', text="总次数", anchor=tk.W)self.tree.heading('dscrp', text="交易类型", anchor=tk.W)# 设置关联scrollBar.config(command = self.tree.yview)# 每次打开清空页面for item in self.tree.get_children():self.tree.delete(item)# sql = "select a.outid ,a.name ,b.opfare,b.opdt,b.dscrp from base_customers a,rec_cust_acc b where a.customerid = b. customerid and b.opdt >= to_date(:preopdt,'yyyy-MM-dd HH24:mi:ss') and b.opdt <= to_date(:nextopdt,'yyyy-MM-dd HH24:mi:ss') order by b.opdt desc"preopdt=self.pretimeInput.get()nextopdt=self.nexttimeInput.get()data = self.cursor.execute(sql,(preopdt,nextopdt)).fetchall()# print(data)for itm in data:self.tree.insert("",tk.END,values=itm)self.tree.pack(padx=10,pady=10, fill=tk.BOTH,expand=1)exportbtn = tk.Button(self.sumtail,text='导出',width=8,command=self.export).pack()# 个人明细def personDetail(self):if(self.outidInput.get()):print('outid not is null')sql="select a.outid ,a.name ,b.opfare,b.oddfare,b.opdt,b.dscrp from base_customers a,rec_cust_acc b where a.customerid = b. customerid and b.opdt >= to_date(:preopdt,'yyyy-MM-dd HH24:mi:ss') and b.opdt <= to_date(:nextopdt,'yyyy-MM-dd HH24:mi:ss') and a.outid = :outid order by b.opdt desc"outidname = self.outidInput.get()elif(self.nameInput.get()):sql="select a.outid ,a.name ,b.opfare,b.oddfare,b.opdt,b.dscrp from base_customers a,rec_cust_acc b where a.customerid = b. customerid and b.opdt >= to_date(:preopdt,'yyyy-MM-dd HH24:mi:ss') and b.opdt <= to_date(:nextopdt,'yyyy-MM-dd HH24:mi:ss') and a.name like :name order by b.opdt desc"outidname = self.nameInput.get()else:messagebox.showwarning("提示", "请输入学号或者姓名!")returnself.persontail = tk.Tk()self.persontail.title('XX学院个人查询')self.persontail.geometry("1200x600")# 加载滚动条# exportbtn = Button(persontail,text='导出',width=8,command=export).pack()scrollBar = tk.Scrollbar(self.persontail)scrollBar.pack(side = tk.RIGHT,fill = tk.Y)self.tree = ttk.Treeview(self.persontail, columns=('outid', 'name', 'opfare','oddfare', 'opdt','dscrp'), show="headings", displaycolumns="#all",yscrollcommand = scrollBar.set)self.tree.pack()self.tree.heading('outid', text="学号", anchor=tk.W)self.tree.heading('name', text="姓名", anchor=tk.W)self.tree.heading('opfare', text="交易金额", anchor=tk.W)self.tree.heading('oddfare', text="账户余额", anchor=tk.W)self.tree.heading('opdt', text="交易日期", anchor=tk.W)self.tree.heading('dscrp', text="交易类型", anchor=tk.W)# 设置关联scrollBar.config(command = self.tree.yview)# 每次打开清空页面for item in self.tree.get_children():self.tree.delete(item)# sql = "select a.outid ,a.name ,b.opfare,b.opdt,b.dscrp from base_customers a,rec_cust_acc b where a.customerid = b. customerid and b.opdt >= to_date(:preopdt,'yyyy-MM-dd HH24:mi:ss') and b.opdt <= to_date(:nextopdt,'yyyy-MM-dd HH24:mi:ss') order by b.opdt desc"preopdt=self.pretimeInput.get()nextopdt=self.nexttimeInput.get()# print(outidname)data = self.cursor.execute(sql,(preopdt,nextopdt,outidname)).fetchall()# print(data)for itm in data:self.tree.insert("",tk.END,values=itm)self.tree.pack(padx=10,pady=10, fill=tk.BOTH,expand=1)def export():# 导出export        # 打开文件夹选择对话框folder_path = filedialog.asksaveasfilename(title='请选择一个文件',filetypes=[("CSV", ".csv")]) # 更新标签文本print(folder_path)list = []for row_id in self.tree.get_children():list.append(self.tree.item(row_id)['values'])with open(f'{folder_path}.csv','w',newline='') as csvfile:fieldnames = ['学号', '姓名', '交易金额','账户余额','交易日期','交易类型']writer = csv.writer(csvfile)writer.writerow(fieldnames)writer.writerows(list)exportbtn = tk.Button(self.persontail,text='导出',width=8,command=self.export).pack()def export(self):# 导出export        # 打开文件夹选择对话框# 更新标签文本# print(folder_path)list = []columns = []# 获取表格内容idfor row_id in self.tree.get_children():list.append(self.tree.item(row_id)['values'])print(len(self.tree.get_children()))   # 通过第一行获取列数生成标题# print(self.tree.item)if len(self.tree.get_children()) != 0:print('ok')folder_path = filedialog.asksaveasfilename(title='请选择一个文件',filetypes=[("CSV", ".csv")]) for i in range(0,len(self.tree.item('I001')['values'])):columns.append(self.tree.heading(column=i)['text'])# 导出csvwith open(f'{folder_path}.csv','w',newline='') as csvfile:fieldnames = columnswriter = csv.writer(csvfile)writer.writerow(fieldnames)writer.writerows(list)else:messagebox.showwarning("提示", "没有数据,无法导出")returnif __name__ == "__main__":root = tk.Tk()app =  mainApp(root)root.mainloop()

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

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

相关文章

安卓使用android studio跨进程通信之AIDL

我写这篇文章不想从最基础的介绍开始,我直接上步骤吧. 1.创建服务端 1.1:创建服务端项目:我的as版本比较高,页面就是这样的 1.2:创建AIDL文件,右键项目,选中aidl aidl名字可以自定义也可以默认 basicTypes是自带的,可以删掉,也可以不删,然后把你自己所需的接口写上去 1.3:创建…

微信小程序开发之后台数据交互及wxs应用

目录 一.后端准备 1.1. 应用配置 1.2. 数据源配置 二、数据库 2.1. 创建 2.2.数据表 2.3.数据测试 三、前端 3.1.请求方法整合 3.2.数据请求 3.3.WXS的使用 3.4.样式美化 3.5. 页面 今天就到这里了哦&#xff0c;希望能帮到你哦&#xff01;&#xff01;&#xf…

解密Java中神奇的Synchronized关键字

文章目录 &#x1f389; 定义&#x1f389; JDK6以前&#x1f389; 偏向锁和轻量级锁&#x1f4dd; 偏向锁&#x1f4dd; 轻量级锁&#x1f4dd; 自旋锁&#x1f4dd; 重量级锁&#x1f525; 1. 加锁&#x1f525; 2. 等待&#x1f525; 3. 撤销 &#x1f389; 锁优化&#x1f…

红队打靶:Misdirection打靶思路详解(vulnhub)

目录 写在开头 第一步&#xff1a;主机发现与端口扫描 第二步&#xff1a;Web渗透&#xff08;80端口&#xff0c;战术放弃&#xff09; 第三步&#xff1a;Web渗透&#xff08;8080端口&#xff09; 第四步&#xff1a;sudo bash提权 第五步&#xff1a;/etc/passwd利…

一文搞懂UART通信协议

目录 1、UART简介 2、UART特性 3、UART协议帧 3.1、起始位 3.2、数据位 3.3、奇偶校验位 3.4、停止位 4、UART通信步骤 1、UART简介 UART&#xff08;Universal Asynchronous Receiver/Transmitter&#xff0c;通用异步收发器&#xff09;是一种双向、串行、异步的通信…

【c++Leetcode】141. Linked List Cycle

问题入口 思想&#xff1a;Floyds Tortoise and Hare 这个算法简单来说就是设置一个慢指针&#xff08;一次移动一个位置&#xff09;和一个快指针&#xff08;一次移动两个位置&#xff09;。在遍历过程中&#xff0c;如果慢指针和快指针都指向同一个元素&#xff0c;证明环…

spacy.load(“en_core_web_trf“)报错TypeError: issubclass() arg 1 must be a class

使用spacy时遇到的问题 写在最前面&#xff1a; 安装spacy和en_core_web_trf时需要保证二者版本一致 安装及查看对应spacy版本 安装 pip install spacy查看版本 import spacy spacy.__version__安装en_core_web_trf 直接安装&#xff08;如果可以的话&#xff09; pytho…

Flutter视图原理之StatefulWidget,InheritedWidget

目录 StatefulElement1. 构造函数2. build3. _firstBuild3. didChangeDependencies4. setState InheritedElement1. Element类2. _updateInheritance3. InheritedWidget数据向下传递3.1 dependOnInheritedWidgetOfExactType 4. InheritedWidget的状态绑定4.1. ProxyElement 在f…

SettingsProvider

Android Settings 系列文章&#xff1a; Android Settings解析SettingsIntelligenceSettingsProvider 首语 为啥要聊到这个模块呢&#xff1f;因为Settings里存在大量的设置项&#xff0c;这些设置项的状态需要保存&#xff0c;它们就是通过SettingsProvider来处理的。以状态…

.net6部署到linux上(CentOS Linux 7)

目录 一、先在linux上配置.net环境 添加 Microsoft 包存储库 安装 SDK 安装运行时 检查 SDK 版本可使用终端查看当前安装的 .NET SDK 版本。 打开终端并运行以下命令。 二、创建.net6 mvc项目 并发布 创建项目 修改默认端口 打包发布到文件夹 运行打包项目查看项目是否…

macOS telnet替代方式

前言 经过使用Linux&#xff0c;常常用Linux的telnet查看端口畅通&#xff0c;是否有防火墙&#xff0c;但是在mac上已经没有这个命令了&#xff0c;那么怎么使用这个命令或者有没有其他替代呢&#xff0c;win和linux是否可以使用相同的替代。macOS可以原生用nc命令替代&#…

C算法:使用选择排序实现从(大到小/从小到大)排序数组,且元素交换不可使用第三变量。

需求&#xff1a; 使用选择排序实现从(大到小/从小到大)排序&#xff0c;且元素交换不可使用第三变量 (异或交换法) 代码实现&#xff1a; #include <stdio.h> void maopao(int* array,int len,int(*swap)(int a,int b)) {int i,j;for(i0;i<len-1;i){for(ji1;j<…

【数据结构与算法】two X 树的遍历以及功能实现

前言&#xff1a; 前面我们已经提到过树、二叉树的概念及结构、堆排序、Top-k问题等的知识点&#xff0c;这篇文章我们来详解一下二叉树的链式结构等问题。 &#x1f4a5;&#x1f388;个人主页:​​​​​​Dream_Chaser&#xff5e; &#x1f388;&#x1f4a5; ✨✨专栏:htt…

安全渗透测试网络基础知识之路由技术

#1.静态路由技术 ##1.1路由技术种类: 静态路由技术、动态路由技术 ##1.2静态路由原理 静态路由是网络中一种手动配置的路由方式,用于指定数据包在网络中的传输路径。与动态路由协议不同,静态路由需要管理员手动配置路由表,指定目的网络和下一跳路由器的关联关系。 比较适合…

【智能家居】

面向Apple developer学习&#xff1a;AirPlay | Apple Developer Documentation Airplay AirPlay允许人们将媒体内容从iOS、ipad、macOS和tvOS设备无线传输到支持AirPlay的Apple TV、HomePod以及电视和扬声器上。 网页链接的最佳实践 首选系统提供的媒体播放器。内置的媒体播…

SpringCloud和Kubernetes的区别

又见小道仙&#xff1a; https://blog.csdn.net/Tomwildboar/article/details/129531315 对于SpringCloud在实际项目中并未使用过&#xff0c;只是自学过SpringCloud和SpringCloud Alibaba&#xff0c;也基于学习搭建过demo。 对于Kubernetes&#xff0c;目前这家公司就是使用…

Web APIs——事件监听以及案例

1、事件监听 什么是事件&#xff1f; 事件是在编程时系统内发生的动作或者发生的事情 比如用户在网页上单击一个按钮 什么是事件监听&#xff1f; 就是让程序检测是否有事件产生&#xff0c;一旦有事件触发&#xff0c;就立即调用一个函数做出响应&#xff0c;也称为绑定事…

【RocketMQ集群】Linux搭建RocketMQ双主双从集群

在当今大数据时代&#xff0c;消息队列系统成为了构建高可用、可扩展和可靠的分布式应用的重要组件之一。而Apache RocketMQ作为一款开源的分布式消息中间件&#xff0c;以其高吞吐量、低延迟和可靠性而备受青睐。为了满足大规模应用的需求&#xff0c;搭建RocketMQ集群是一种常…

K8S集群中Node节点资源不足导致Pod无法运行的故障排查思路

K8S集群中Node节点资源不足导致Pod无法运行的故障排查思路 Node节点资源不足可能会产生的故障 故障一&#xff1a;Pod数量太多超出物理节点的限制每一台Node节点中默认限制最多运行110个Pod资源&#xff0c;当一个应用程序有成百上千的Pod资源时&#xff0c;如果不扩容Node节…

基于springboot实现基于Java的超市进销存系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现基于Java的超市进销存系统演示 摘要 随着信息化时代的到来&#xff0c;管理系统都趋向于智能化、系统化&#xff0c;超市进销存系统也不例外&#xff0c;但目前国内仍都使用人工管理&#xff0c;市场规模越来越大&#xff0c;同时信息量也越来越庞大&#x…