news 2026/9/7 21:03:25

从零搭建Web简易ERP进销存系统:核心规划与技术选型

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从零搭建Web简易ERP进销存系统:核心规划与技术选型

这篇文章是《Web简易ERP进销存管理系统》系列的第 01 篇。系列目标是带着你从零搭建一个可用的 Web 进销存系统,而不是只贴概念图。先聊一个很直接的问题:市面上成熟的 ERP 系统非常多,为什么还要自己写一个简易 ERP?

答案通常是三个场景。第一,学习。Spring Boot、Vue、MySQL 这些技术,单独学容易,组合起来做一个完整业务系统很难,进销存是最适合练手的业务模型。第二,毕业设计。进销存几乎是计算机专业毕设里出现频率最高的题目之一,选一套清晰的系统设计比堆功能更重要。第三,小微企业轻量管理。很多小团队没有专门的 IT 人员,大型 ERP 太重、太贵,一个 Web 化的简易进销存系统,能解决商品资料、采购、销售、库存和基础报表的核心诉求就够了。

这篇文章是系列开篇,不写具体代码实现,先把整体规划讲清楚:系统解决什么问题、包含哪些模块、用什么技术栈、数据库怎么设计、后续怎么一步步开发。读完你会对整个项目有完整认知,后面每一期只需要照着路线图填充细节。

1. 核心能力速览

能力项说明
项目类型基于 Web 的简易 ERP 进销存管理系统
核心业务商品资料、供应商、客户、采购入库、销售出库、库存流水、库存结余、业务报表
系统形态B/S 架构,浏览器访问,无需安装客户端
常见角色管理员、采购员、销售员、仓库管理员
技术栈方案轻量方案:Flask + Vue + SQLite/MySQL;企业级方案:Spring Boot + MyBatis-Plus + MySQL + Vue
运行环境Windows / Linux 均可,需安装对应运行时和数据库
部署方式前后端分别部署,或打包后由 Nginx 托管静态文件并反向代理后端
是否支持 API后端按 RESTful 风格提供接口,方便后续对接小程序、扫码枪等
是否支持批量任务采购单、销售单支持批量导入或批量录入(需后续实现)
适合场景技术学习、毕业设计、小微企业内部轻量管理

从当前系列定位来看,这是一个教学型项目。功能不会做成 SAP、Oracle ERP 那种大而全,而是把进销存最核心的链路跑通:商品档案 → 采购入库 → 库存增加 → 销售出库 → 库存减少 → 报表统计。这条链路清晰、完整,也最容易验证业务逻辑是否正确。

2. 适用场景与使用边界

2.1 适合解决的业务问题

进销存,本质上管的是三件事:进、销、存。

进:向供应商采购商品,生成采购订单,到货后入库。销:向客户销售商品,生成销售订单,发货后出库。存:实时记录每个商品在哪个仓库、剩余多少、出入库流水是否可追溯。

系统还要解决三个基础资料的问题:商品信息、供应商信息、客户信息。商品信息包括编码、名称、规格、单位、分类、价格等;供应商信息用于采购业务;客户信息用于销售业务。基础资料越规范,后面的库存和报表越准确。

2.2 不适合做什么

在设计简易 ERP 时,有几块复杂度很高,不建议一上来就做:

  • 生产制造 BOM、工单、工序排程:这是专业 MES/ERP 的领域,不是简易系统能覆盖的。
  • 财务总账、应收应付、固定资产、成本核算:这些需要会计逻辑和严格的凭证体系,适合对接专业财务软件。
  • 多公司、多组织架构、多币种:涉及复杂的结算规则,不适合在入门项目中实现。
  • 复杂审批流:例如多级审批、自定义流程引擎,会影响核心业务的建设优先级。

因此,这个系统的业务边界要提前划清楚:只做进销存,不做财务,不做生产,不做复杂审批。把核心链路做稳定,再逐步扩展。

2.3 数据安全与合规边界

进销存系统里会存商品成本、销售价格、客户资料、库存数量等经营数据。开发和使用时需要注意:

  • 系统上线前要设置强密码和访问控制,不能把管理后台暴露到公网裸奔。
  • 涉及客户隐私信息(电话、地址)时,必须获得对方授权,并按相关法规做好隐私保护。
  • 数据要有定期备份机制,防止服务器故障导致商业数据丢失。
  • 如果后续接入扫码枪、电子秤、小程序等设备,接口调用要加鉴权,不能开放任意写入。

3. 系统整体架构设计

简易 ERP 采用典型的前后端分离架构,也可以根据技术栈不同选择服务端渲染模式。这里推荐前后端分离,因为接口清晰、便于后续扩展。

整体架构分为三层:

  • 展示层:Web 前端页面,包括登录、首页看板、基础资料管理、业务单据、库存查询、报表图表。
  • 业务层:后端服务,处理权限、业务规则、事务控制、数据校验。
  • 数据层:数据库存储,核心是基础资料表、业务单据表、库存流水表和报表统计表。

模块划分推荐如下:

模块主要功能
系统管理用户管理、角色管理、菜单权限、操作日志
基础资料商品分类、商品信息、供应商、客户、仓库
采购管理采购订单、采购入库、采购退货(可选)
销售管理销售订单、销售出库、销售退货(可选)
库存管理库存查询、库存流水、库存盘点、预警
报表统计采购报表、销售报表、库存报表、利润统计(简化版)

这个模块划分适合第一版迭代。后续如果需要,可以在报表模块增加图表展示,也可以把采购和销售模块的订单与入库/出库流程分离。

4. 技术选型建议

进销存系统的技术选型,主要看你当前的目的是什么。有两种路线比较常见。

4.1 轻量快速路线:Flask / FastAPI + Vue + SQLite

该组合适合 Python 技术栈学习、课程设计,或者快速做原型验证。后端使用 Flask 或 FastAPI,前端使用 Vue 3 + Element Plus,数据库先用 SQLite 起步,后期可以切换到 MySQL。

优点:

  • 环境准备简单,Python 安装后即可启动。
  • Flask 代码量少,适合快速理解业务逻辑。
  • SQLite 文件数据库无需额外安装服务,方便本地开发和演示。

缺点:

  • 高并发能力一般,适合小团队内部试用。
  • SQLite 在多用户并发写入时会有锁竞争,正式环境建议切换 MySQL。

4.2 企业级学习路线:Spring Boot + MyBatis-Plus + MySQL + Vue

该组合适合 Java 技术栈学习、毕业设计,或者作为可扩展的系统底座。后端使用 Spring Boot,ORM 使用 MyBatis-Plus 减少 SQL 编写,前端使用 Vue 3 + Vite + Element Plus,数据库使用 MySQL 8.x。

优点:

  • 生态成熟,岗位需求量大,学完直接能写企业级项目。
  • Spring Boot 的事务管理可以很好地保证采购入库、销售出库的库存一致性。
  • 后续对接小程序、APP 或者第三方系统都比较方便。

缺点:

  • 环境安装和项目配置相对复杂,需要 JDK、Maven、MySQL。

做选择时不用太纠结。如果是 Java 方向,选方案二;如果是 Python 方向或快速验证,选方案一。系列后续文章会以 Spring Boot + Vue 为主路线讲解,但核心设计思路两种方案通用。

5. 数据库设计核心思路

进销存系统的数据库设计,最关键的是库存数据。不能只存一张“当前库存表”,一定要有流水表来记录每一次出入库变化。否则一旦出现数据错误,很难追溯。

推荐的表结构设计思路如下:

5.1 核心表清单

表名用途
sys_user用户表
sys_role角色表
sys_user_role用户角色关联表
biz_category商品分类表
biz_product商品信息表
biz_supplier供应商表
biz_customer客户表
biz_warehouse仓库表
biz_purchase_order采购订单主表
biz_purchase_order_item采购订单明细表
biz_purchase_inbound采购入库单主表
biz_purchase_inbound_item采购入库单明细表
biz_sale_order销售订单主表
biz_sale_order_item销售订单明细表
biz_sale_outbound销售出库单主表
biz_sale_outbound_item销售出库单明细表
biz_stock_balance库存结余表
biz_stock_flow库存流水表
biz_stock_check盘点记录表(可选)

5.2 商品信息表示例

商品表不需要设计得太复杂,但编码、名称、规格、单位、分类、默认进价、默认售价都属于常规必填项。

CREATE TABLE biz_product ( id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键', product_code VARCHAR(50) NOT NULL UNIQUE COMMENT '商品编码', product_name VARCHAR(200) NOT NULL COMMENT '商品名称', category_id BIGINT COMMENT '分类ID', spec VARCHAR(100) COMMENT '规格型号', unit VARCHAR(20) COMMENT '计量单位', default_purchase_price DECIMAL(10,2) DEFAULT 0 COMMENT '默认进价', default_sale_price DECIMAL(10,2) DEFAULT 0 COMMENT '默认售价', status TINYINT DEFAULT 1 COMMENT '状态:1启用 0停用', create_time DATETIME DEFAULT CURRENT_TIMESTAMP, update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, deleted TINYINT DEFAULT 0 COMMENT '逻辑删除' ) COMMENT '商品信息表';

5.3 库存结余表与流水表

库存结余表保存当前仓库、当前商品的实时库存,用于查询。库存流水表记录每一次入库、出库、盘点、调整的操作,用于追溯。结余表可以冗余“最后更新时间”,但算法要统一。

CREATE TABLE biz_stock_balance ( id BIGINT PRIMARY KEY AUTO_INCREMENT, product_id BIGINT NOT NULL COMMENT '商品ID', warehouse_id BIGINT NOT NULL COMMENT '仓库ID', quantity DECIMAL(12,2) DEFAULT 0 COMMENT '当前库存数量', update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, UNIQUE KEY uk_product_warehouse (product_id, warehouse_id) ) COMMENT '库存结余表'; CREATE TABLE biz_stock_flow ( id BIGINT PRIMARY KEY AUTO_INCREMENT, product_id BIGINT NOT NULL COMMENT '商品ID', warehouse_id BIGINT NOT NULL COMMENT '仓库ID', change_type VARCHAR(20) NOT NULL COMMENT '类型:PURCHASE_IN SALE_OUT STOCK_IN STOCK_OUT CHECK', change_quantity DECIMAL(12,2) NOT NULL COMMENT '变动数量,入库正,出库负', before_quantity DECIMAL(12,2) COMMENT '变动前库存', after_quantity DECIMAL(12,2) COMMENT '变动后库存', biz_type VARCHAR(50) COMMENT '关联业务类型', biz_no VARCHAR(50) COMMENT '关联业务单号', remark VARCHAR(255) COMMENT '备注', create_by BIGINT COMMENT '操作人', create_time DATETIME DEFAULT CURRENT_TIMESTAMP ) COMMENT '库存流水表';

在业务实现中,采购入库、销售出库这些操作必须在同一个数据库事务里完成两件事:更新库存结余表,写入库存流水表。这样才能保证库存数据可追溯、不会凭空消失。

6. 项目目录结构与启动流程

不管是 Java 后端还是 Python 后端,项目目录结构都应该遵循分层设计:controller、service、mapper/repository、entity/model、dto、config 等。

6.1 后端目录结构示例(Spring Boot)

erp-backend/ ├── src/main/java/com/example/erp/ │ ├── ErpApplication.java │ ├── controller/ │ │ ├── AuthController.java │ │ ├── ProductController.java │ │ ├── PurchaseController.java │ │ ├── SaleController.java │ │ └── StockController.java │ ├── service/ │ │ ├── impl/ │ │ └── ... │ ├── mapper/ │ ├── entity/ │ ├── dto/ │ ├── config/ │ └── common/ ├── src/main/resources/ │ ├── application.yml │ ├── mapper/ │ └── db/ │ └── init.sql └── pom.xml

6.2 前端目录结构示例(Vue 3 + Vite)

erp-frontend/ ├── src/ │ ├── api/ │ │ ├── product.js │ │ ├── purchase.js │ │ ├── sale.js │ │ └── stock.js │ ├── assets/ │ ├── components/ │ ├── router/ │ ├── store/ │ ├── views/ │ │ ├── Login.vue │ │ ├── dashboard/ │ │ ├── product/ │ │ ├── purchase/ │ │ ├── sale/ │ │ └── stock/ │ ├── App.vue │ └── main.js ├── package.json └── vite.config.js

6.3 通用启动命令模板

实际启动命令需要按项目实际情况调整。下面给出通用模板:

# 后端启动(Spring Boot) cd erp-backend mvn spring-boot:run # 后端启动(Flask) cd erp-backend pip install -r requirements.txt python app.py # 前端启动 cd erp-frontend npm install npm run dev

启动后,前端开发服务器一般会占用一个端口(例如 5173),后端接口服务占用另一个端口(例如 8080)。如果出现端口被占用,可以分别修改配置文件中的端口号。前后端联调时,需要在前端设置 API 代理地址,把/api请求转发到后端服务。

7. 功能流程演示与验证计划

虽然是系统整体介绍,但也需要把核心业务流程和验证方式讲清楚。后续每个功能模块都会按下面的流程开发。

7.1 主业务流

一个完整的进销存主流程如下:

  1. 管理员登录系统。
  2. 维护基础资料:新增商品分类、商品信息、供应商、客户、仓库。
  3. 采购员创建采购订单,选择供应商和商品,填写数量和进价。
  4. 采购订单审核通过后,仓库管理员执行入库操作。
  5. 系统自动增加库存结余,并记录一条采购入库流水。
  6. 销售员创建销售订单,选择客户和商品,填写数量和售价。
  7. 销售订单审核通过后,仓库管理员执行出库操作。
  8. 系统自动扣减库存,并记录一条销售出库流水。
  9. 库存报表和销售报表实时更新,管理者可以查看毛利和库存情况。

7.2 功能验证清单

验证点输入 / 操作预期结果
用户登录输入正确账号密码登录成功,进入首页;错误密码提示失败
商品新增新增商品编码、名称、价格商品列表展示新商品,重复编码被拦截
采购入库创建采购单并入库库存结余增加,库存流水生成
销售出库创建销售单并出库库存结余减少,库存流水生成
库存防负出库数量大于当前库存系统提示库存不足或不允许负数(可按业务开关控制)
权限控制普通用户访问用户管理菜单返回无权限提示
数据一致性并发执行多笔出库库存最终结果正确,无超卖或负数

7.3 判断成功的标准

一套进销存系统能不能用,不只看页面是否好看,关键看两点:

第一,库存流水是否完整。每一次数量变动都能在流水表里找到对应的业务单号和时间。第二,库存结余是否准确。在任意时间点,库存结余等于所有入库流水数量减去所有出库流水数量。如果出现不一致,说明事务控制或业务逻辑有问题。

8. 接口 API 设计示例

前后端分离模式下,后端提供 RESTful API。以下是一组基础接口约定,实际开发中需要根据项目模块调整。

方法路径功能
POST/api/auth/login用户登录
GET/api/product/page商品分页查询
POST/api/product新增商品
PUT/api/product/{id}修改商品
DELETE/api/product/{id}删除商品
GET/api/stock/balance库存结余查询
POST/api/purchase/inbound创建采购入库单
POST/api/sale/outbound创建销售出库单
GET/api/report/sale销售报表查询

下面给出一个通用的 API 调用示例,使用 Python requests 模拟创建采购入库单。实际接口路径和字段需要按你的项目定义来调整:

import requests url = "http://127.0.0.1:8080/api/purchase/inbound" headers = { "Authorization": "Bearer <TOKEN>", "Content-Type": "application/json" } payload = { "supplierId": 1, "warehouseId": 1, "items": [ { "productId": 10, "quantity": 20, "purchasePrice": 15.5 } ], "remark": "第一批测试采购入库" } response = requests.post(url, json=payload, headers=headers, timeout=30) print(response.status_code) print(response.json())

对应返回结果可以设计为:

{ "code": 200, "message": "success", "data": { "inboundNo": "RK202501010001", "stockFlows": 1 } }

接口设计要注意几点:所有写操作都需要校验登录状态和操作权限;采购入库、销售出库这类影响库存的接口必须有事务控制;返回结果统一封装 code、message、data,方便前端处理。

9. 关键问题与排查思路

开发 Web 进销存系统过程中,遇到问题最多的集中在数据库、跨域、库存和部署几个方面。

问题现象可能原因排查方式解决方案
后端服务启动失败端口被占用或配置错误查看启动日志,检查端口占用更换端口或关闭占用进程
数据库连接失败MySQL 未启动、账号密码错误、库不存在检查 application.yml 配置确认数据库服务和账号权限
前端请求接口跨域前后端域名或端口不一致打开浏览器控制台查看 CORS 报错后端配置跨域或前端配置代理
库存出现负数未做库存校验或并发问题检查出库接口逻辑和事务出库前查询库存,数量不足直接拦截;必要时加锁
采购入库后库存没变事务未提交或流程未执行完查看后端日志,检查库存流水确认入库存方法事务生效,异常时回滚
页面刷新后 404前端路由是 history 模式检查 Nginx 部署配置Nginx 配置 try_files 指向 index.html
数据异常但无日志日志级别太低或异常被吞调整日志级别为 DEBUG打印关键流水日志,记录操作人和时间
多人同时出库超卖高并发下单行更新竞争查看数据库锁和流水记录对库存扣减使用条件更新WHERE quantity >= ?

9.1 库存扣减的常见实现

库存扣减是进销存最容易出 Bug 的地方。推荐使用乐观更新加条件判断:

UPDATE biz_stock_balance SET quantity = quantity - #{quantity}, update_time = NOW() WHERE product_id = #{productId} AND warehouse_id = #{warehouseId} AND quantity >= #{quantity};

如果更新影响行数为 0,说明库存不足,直接抛出业务异常,回滚事务。同时,无论成功失败,都写入一条库存流水记录。

10. 开发路线图与后续系列安排

为了让整套系统可落地,建议按下面的路线推进。每期解决一个明确问题,做完一期就能跑通一个阶段。

阶段主题产出
01系统整体介绍需求分析、模块划分、技术选型、数据库设计思路(本文)
02开发环境搭建JDK、MySQL、Vue 项目初始化,前后端运行成功
03数据库建库与基础代码建表 SQL、项目骨架、统一返回结果和异常处理
04用户登录与权限管理登录接口、JWT、角色权限、前端路由守卫
05基础资料模块产品分类、商品信息、供应商、客户、仓库管理
06采购入库模块采购订单、采购入库、库存更新
07销售出库模块销售订单、销售出库、库存扣减
08库存查询与流水库存结余、库存流水、库存预警
09报表统计与首页看板销售报表、采购报表、商品销售排行
10部署上线与操作手册Linux 部署、Nginx 配置、数据备份、使用说明

第一期的重点是把业务边界和技术方向定下来。不要急着写代码,先把模块、表和流程想清楚,后面开发会顺畅很多。最容易踩的坑有两个:一是库存没有流水表,出问题只能手工改数据库;二是权限设计得过于复杂,导致迟迟做不完核心业务。建议第一次开发时,权限只做“管理员、采购员、销售员、仓库管理员”四种角色,权限控制到菜单级别即可。核心优先,先把采购入库、销售出库、库存流水跑通,再优化权限和报表。

下一期,也就是系列第 02 篇,会带你完整搭建开发环境:安装 JDK、Maven、MySQL,初始化 Spring Boot 后端项目和 Vue 3 前端项目,并让一个最简单的“Hello World”接口在前端页面上显示出来。这是整个系统开发的第一步,也是很多新手上手时最容易卡住的一步。到时候可以先把环境装好,下一篇直接跟着操作。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/7 21:02:20

AI编程代理的软件工厂:从上下文到CI/CD的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/7 21:01:50

《奥拉星》秘宝神银河加强后PVE实战评测:控制变量与数据对比

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/7 20:58:36

板式换热器维护保养全指南:以HS-COOLER KS25为例

那台HS-COOLER KS25-BCV-421L2400热交换器&#xff0c;在厂里一干就是六七年&#xff0c;从没出过岔子。直到去年夏天&#xff0c;车间反馈说换热效率明显下降&#xff0c;冷却水出口温度怎么都压不下来。我过去一看&#xff0c;压差表读数比刚装那会儿翻了一倍还多&#xff0c…

作者头像 李华
网站建设 2026/9/7 20:58:08

GlobeLand30中国区域裁剪与面积统计实操指南

拿到一套覆盖全国、精度到 30 米、分类标准统一的土地利用数据&#xff0c;GlobeLand30 基本是绕不开的名字。它由国内权威机构牵头研制&#xff0c;对外提供 GeoTIFF 格式栅格文件&#xff0c;从 2000 年、2010 年、2020 年三期公开版本&#xff0c;到目前正在陆续更新的 2025…

作者头像 李华
网站建设 2026/9/7 20:56:58

GitHub如何成为程序员求职的硬通货?

1. 为什么GitHub成为程序员求职的硬通货&#xff1f;2026年的技术招聘市场正在经历一场静默革命。作为从业12年的全栈开发者&#xff0c;我亲眼目睹GitHub从版本控制工具演变为技术人才的"第二简历"。去年帮助37位学员优化GitHub后&#xff0c;他们的面试邀约率平均提…

作者头像 李华