简介:本资源是一套完整的超市进销存管理系统源码及设计文档,面向软件开发初学者、课程设计学生与中小型零售企业信息化实践者,旨在解决商品采购、销售、库存协同管理中的数据分散、人工统计易错、响应滞后等实际问题。压缩包共103个文件,含24个C#业务逻辑文件(.cs)、18个ASPX页面文件(如queryStock.aspx、AddSales.aspx等核心功能页)、24张JPG/GIF格式用例图与界面截图,以及CSS样式、数据库文件(.mdf/.ldf)和配置文件,整体仅2.03MB,轻量易部署。已有4379人学习下载,资源突出实用性与教学友好性:不仅提供可运行的B/S架构系统源码,更附带完整用例图,直观呈现员工、顾客、供应商三类角色与进货、销售、库存预警等核心功能的交互关系,便于理解系统架构与需求分析过程。
1. 超市进销存管理系统(附用例图):不是画完就完事的UML作业,而是能跑通“采购→入库→销售→盘点”闭环的最小可行模型
你手头那份标着“超市进销存管理系统”的课程设计文档,大概率正躺在压缩包里吃灰——用例图线条工整、Actor摆放对称、< >箭头画得像教科书,但一问“顾客退货时库存怎么扣?供应商换货后应付账款怎么更新?”,立刻卡壳。这不是UML练习题,而是一套带业务约束的轻量级状态机:它必须让“商品”在采购单、入库单、销售单、盘点单之间流转时,库存数量、成本价、应付/应收余额三者始终守恒;它要求“管理员”和“收银员”权限不能靠文字描述,而要体现在用例粒度上——比如“修改商品售价”只能由管理员触发,“查询当前库存”收银员可读但不可改。这份资源的价值,正在于它把软件工程课上容易被忽略的业务规则落地为可验证的用例边界:每个用例都对应一个明确的前置条件(如“销售前库存≥1”)、后置条件(如“销售单生成后,对应商品库存减1,应收账款增1”)和异常流(如“库存不足时拒绝生成销售单,并返回缺货商品列表”)。适合正在做课程设计、需要快速验证业务逻辑合理性、又不想被数据库字段名和Spring Boot配置绕晕的本科生和初级开发。
2. 用例图不是装饰画:从超市业务流反推用例边界与参与者职责
2.1 为什么必须先画业务流程图再画用例图?
很多同学直接打开StarUML拖拽Actor和椭圆,结果画出的用例图成了功能清单(“添加商品”“删除商品”“修改商品”),却漏掉了关键约束。真实超市场景中,“删除商品”根本不存在——商品下架只是将状态设为“停售”,历史销售记录仍需保留;而“修改商品”实际拆分为两个用例:“调整售价”(仅管理员)和“更新商品规格”(如包装单位从“袋”改为“箱”,影响所有未结算单据)。正确做法是先梳理核心业务流:
- 采购流:采购员提交采购申请 → 仓库确认到货 → 生成入库单 → 更新库存与应付账款
- 销售流:收银员扫描商品 → 系统校验库存 → 生成销售单 → 扣减库存、增加应收账款 → 打印小票
- 盘点流:管理员发起盘点任务 → 仓管员录入实盘数 → 系统比对账面数 → 生成盘盈/盘亏单 → 调整库存与损益
这个流程决定了用例图的骨架:采购员、仓库管理员、收银员、财务人员是四个独立Actor(不能合并为“员工”),因为他们的操作权限和触发时机完全不同。例如“生成入库单”只能由仓库管理员执行,且必须在“确认到货”之后;而“打印小票”是收银员专属动作,且必须在销售单生成成功后才可触发。
2.2 用例粒度控制:避免“大而全”用例导致后续开发失控
常见错误是把“管理商品”作为一个用例,里面塞进增删改查所有操作。这会导致后续类设计时职责爆炸——一个GoodsManager类要处理UI交互、库存校验、日志记录、权限检查。正确的粒度划分原则是:每个用例对应一个原子业务事务,且该事务有明确的成功/失败出口。本系统中关键用例拆分如下:
| 用例名称 | 参与者 | 前置条件 | 后置条件 | 关键约束 |
|---|---|---|---|---|
| 创建采购申请 | 采购员 | 无 | 生成待审批采购单,状态为“草稿” | 商品ID必须存在,数量>0 |
| 审核采购申请 | 仓库管理员 | 采购单状态为“草稿” | 状态变更为“已批准”,生成采购计划 | 需校验供应商资质有效性 |
| 登记入库 | 仓库管理员 | 采购单状态为“已批准”,且到货实物与单据一致 | 库存增加,应付账款增加,入库单状态为“完成” | 实际入库数≤采购单数量,单价按合同价 |
| 生成销售单 | 收银员 | 扫描商品ID有效,库存≥1 | 销售单状态为“已生成”,库存减1,应收账款增1 | 若多商品,任一商品库存不足则整单失败 |
| 执行盘点 | 仓管员 | 盘点任务已创建且未开始 | 生成盘点差异报告,库存按实盘数修正 | 盘点期间禁止销售与入库操作 |
提示:用例名称必须用动宾结构(“生成销售单”而非“销售单管理”),动词体现主动行为,宾语明确操作对象。这是后续映射到Controller层方法名的直接依据(如
createSalesOrder())。
2.3 < >与< >的实战判别法:什么时候该用,什么时候是设计失误?
学生常滥用<<include>>,比如把“登录”作为所有用例的包含关系。但登录本质是横切关注点(Cross-cutting Concern),不应污染业务用例逻辑。本系统中真正需要<<include>>的只有两类场景:
- 强制依赖的子流程:如“登记入库”必须包含“校验采购单有效性”,因为无有效采购单则无法入库;
- 复用性极高的原子操作:如“生成销售单”和“生成采购申请”都需“选择商品”,且选择逻辑完全一致(弹窗搜索+多选),此时用
<<include>>合理。
而<<extend>>只用于可选的、改变主流程行为的扩展点。例如:
- 主用例“生成销售单”可被“使用会员卡”扩展:当顾客出示会员卡时,系统额外计算积分并更新会员等级;
- 主用例“登记入库”可被“处理破损商品”扩展:若扫描到破损商品,系统额外生成破损报告并通知采购员。
注意:如果扩展用例的触发条件过于复杂(如“当商品单价高于市场均价10%时触发价格预警”),说明主用例设计过粗——应将“价格校验”本身作为独立用例,由采购员在“创建采购申请”后手动触发,而非隐式扩展。
3. 用例图落地:用StarUML 5.0.4实操绘制与校验要点
3.1 StarUML环境准备与项目结构初始化
本资源配套的StarUML工程文件(.star格式)基于StarUML 5.0.4构建,兼容Windows/macOS/Linux。安装后需注意两点:
- 禁用自动同步云服务:在
Preferences → General → Auto Sync中关闭,避免本地修改被云端覆盖; - 设置字体为等宽字体:
Preferences → Appearance → Font选择Consolas或Monaco,确保中文不重叠(UML图中中文标签易因字体渲染错位)。
新建项目后,右键Model → Add Diagram → Use Case Diagram,命名为Supermarket_System_UseCase。关键操作不是画图,而是建立模型层级:在左侧Model Explorer中,右键Use Case Diagram→Add → Package,创建三个包:Business_Actors(存放所有Actor)、Core_Usecases(核心用例)、Extension_Usecases(扩展用例)。这种结构便于后期导出为不同模块的代码包。
3.2 绘制Actor与用例:位置布局背后的业务逻辑暗示
Actor位置不是随意摆放,而是反映其在业务中的信息流向与控制权:
- 将
采购员置于图左上方,仓库管理员置于图右上方,暗示采购流从左向右推进; 收银员放在图下方中央,财务人员放在图右下方,体现销售流自上而下、财务结算在末端;- 所有用例椭圆严格水平排列,禁止倾斜或堆叠——StarUML中倾斜椭圆会被解析为无效元素,导出图片时可能丢失。
绘制时务必启用View → Grid(网格线),用Ctrl+Shift+G对齐Actor图标中心点。每个Actor图标右键Properties → Name,输入真实角色名(如“采购员”而非“Actor1”),并在Documentation字段填写职责简述(如“负责提交采购申请、跟踪到货进度”)。这一步看似琐碎,却是后续生成需求文档的基础。
3.3 关系连线规范:箭头方向即数据流向,虚线非装饰
用例间关系连线必须遵循UML 2.5规范,箭头方向代表控制流或数据流向:
- Association(实线):Actor与用例间连线,表示该Actor可触发此用例。注意:一个Actor可关联多个用例,但一个用例只能关联一个主Actor(如“生成销售单”只关联“收银员”,“审核采购申请”只关联“仓库管理员”);
- < >(虚线+< >):从基础用例指向被包含用例,箭头朝向被包含方。例如“登记入库” → “校验采购单有效性”,表示前者调用后者;
- < >(虚线+< >):从扩展用例指向基础用例,箭头朝向基础用例。例如“处理破损商品” → “登记入库”,表示前者在特定条件下增强后者。
提示:StarUML中
<<include>>和<<extend>>需手动添加构造型(Stereotype)。右键连线 →Add Stereotype→ 输入<<include>>,不能直接写文字,否则导出PDF时构造型会丢失。
3.4 校验用例图完整性的三个硬指标
画完图后,必须通过以下三项检查,否则无法进入后续开发:
- Actor覆盖率检查:每个Actor至少关联3个用例,且覆盖采购、销售、盘点三大主线。若“财务人员”只关联“查看应收账款”,说明财务核算流程缺失;
- 用例完整性检查:核心用例必须包含
Precondition(前置条件)、Postcondition(后置条件)、Main Flow(主流程)、Alternative Flows(备选流)四段文字描述。StarUML中右键用例 →Open Specification填写,禁止留空; - 关系无环检查:用例间不能形成循环依赖。例如“A包含B,B包含C,C又包含A”是致命错误。StarUML自带
Diagram → Validate功能,勾选Check for circular dependencies即可一键检测。
4. 从用例图到代码:用Python Flask快速验证业务逻辑闭环
4.1 为什么选Flask而非Spring Boot做原型验证?
课程设计阶段最怕陷入框架配置泥潭。Spring Boot虽强大,但pom.xml依赖冲突、application.yml多环境配置、JPA实体映射错误,往往耗掉三天调试时间。而Flask用不到50行代码就能跑通一个用例的核心逻辑:
# app.py from flask import Flask, request, jsonify from datetime import datetime app = Flask(__name__) # 模拟内存数据库(实际项目需替换为SQLite/MySQL) inventory = {"apple": {"quantity": 100, "unit_price": 5.0}} accounts_payable = 0.0 # 应付账款总额 @app.route('/api/sales', methods=['POST']) def create_sales_order(): data = request.get_json() item_id = data.get('item_id') quantity = data.get('quantity', 1) # 【前置条件】校验商品存在且库存充足 if item_id not in inventory: return jsonify({"error": "商品不存在"}), 400 if inventory[item_id]["quantity"] < quantity: return jsonify({"error": "库存不足", "available": inventory[item_id]["quantity"]}), 400 # 【核心业务逻辑】扣减库存,增加应收账款 inventory[item_id]["quantity"] -= quantity sales_amount = quantity * inventory[item_id]["unit_price"] # 【后置条件】返回销售单摘要 sales_order = { "order_id": f"SO{datetime.now().strftime('%Y%m%d%H%M%S')}", "item_id": item_id, "quantity": quantity, "total_amount": sales_amount, "timestamp": datetime.now().isoformat() } return jsonify(sales_order), 201 if __name__ == '__main__': app.run(debug=True)这段代码直接映射“生成销售单”用例:
if item_id not in inventory对应前置条件“商品ID必须存在”;inventory[item_id]["quantity"] < quantity对应“库存≥1”的校验;inventory[item_id]["quantity"] -= quantity是后置条件“库存减1”的实现;- 返回的
sales_orderJSON结构,就是用例图中“销售单”实体的最小化表现。
4.2 用例驱动的测试用例编写:用pytest验证业务规则
光有接口不够,必须用测试用例证明业务规则被严格执行。针对“生成销售单”,编写三个测试场景:
# test_sales.py import pytest from app import app, inventory @pytest.fixture def client(): app.config['TESTING'] = True return app.test_client() def test_create_sales_success(client): """正常销售:库存充足,应成功扣减""" response = client.post('/api/sales', json={"item_id": "apple", "quantity": 2}) assert response.status_code == 201 assert inventory["apple"]["quantity"] == 98 # 初始100,扣2 def test_create_sales_insufficient_stock(client): """库存不足:应返回400错误及可用库存数""" response = client.post('/api/sales', json={"item_id": "apple", "quantity": 150}) assert response.status_code == 400 data = response.get_json() assert data["error"] == "库存不足" assert data["available"] == 98 # 上次测试后剩余98 def test_create_sales_invalid_item(client): """商品不存在:应返回400错误""" response = client.post('/api/sales', json={"item_id": "banana", "quantity": 1}) assert response.status_code == 400 assert response.get_json()["error"] == "商品不存在"运行pytest test_sales.py -v,三个测试全部通过,才说明“生成销售单”用例的业务规则被代码准确实现。这是用例图价值的终极验证——它不再是纸上谈兵,而是可执行、可测试的契约。
4.3 用例图到数据库表的映射:避免过度设计的三张核心表
很多同学一上来就设计10+张表,结果连主外键都连不对。本系统只需三张表支撑全部用例:
| 表名 | 字段 | 说明 | 对应用例 |
|---|---|---|---|
goods | id(PK),name,unit_price,status(enum: 'on_sale','out_of_stock','discontinued') | 商品主数据表,status字段替代“删除”操作 | 创建采购申请、生成销售单 |
inventory | goods_id(FK),quantity,last_updated | 库存快照表,每次出入库更新此表 | 登记入库、生成销售单、执行盘点 |
sales_order | id(PK),goods_id(FK),quantity,amount,created_at,status(enum: 'pending','completed','cancelled') | 销售单流水表,记录每笔交易 | 生成销售单、打印小票 |
注意:应付账款、应收账款不单独建表,而是通过
inventory表的quantity变化 +sales_order表的amount累计值动态计算。课程设计阶段,宁可牺牲部分财务精度,也要保证核心业务流可验证。
5. 避坑指南:用例图与代码落地过程中的五个血泪经验
5.1 现象:用例图中“管理员”能执行所有操作,但代码里权限校验形同虚设
原因:用例图未区分“系统管理员”与“业务管理员”。超市场景中,“修改商品售价”需财务总监审批,而“调整库存阈值”只需仓管主管操作。但图中统一用“管理员”Actor,导致后续开发时所有管理接口都加同一套JWT权限,失去业务意义。
解决:在用例图中拆分Actor——System_Admin(负责用户账号、菜单配置)、Warehouse_Admin(负责库存、盘点)、Finance_Admin(负责账款、报表)。每个Actor只关联其职责范围内的用例,并在Flask路由装饰器中按角色校验:
@app.route('/api/goods/price', methods=['PUT']) @role_required(['Finance_Admin']) # 仅财务管理员可调用 def update_price(): ...5.2 现象:StarUML导出的PNG图片模糊,答辩PPT里用例图看不清文字
原因:StarUML默认导出分辨率72dpi,而PPT需300dpi以上。且中文标签在导出时因字体嵌入问题出现乱码。
解决:导出前执行三步操作:①File → Export → Image;② 在弹窗中勾选Vector Graphics (SVG)而非PNG;③ 导出SVG后,用Inkscape(免费矢量工具)打开,File → Save As选择PDF格式,勾选Embed fonts。PDF插入PPT后可任意缩放不失真。
5.3 现象:用例“执行盘点”在代码中写成简单更新库存,但实际需生成盘盈/盘亏单
原因:用例图未定义“盘点差异报告”这一输出物,导致开发者以为盘点=直接改库存数。但业务规则要求:盘盈需计入营业外收入,盘亏需查明原因(人为损耗/自然损耗/盗窃)并走审批流。
解决:在“执行盘点”用例的Postcondition中明确写出:“生成inventory_adjustment记录,包含adjustment_type(enum: 'surplus','shortage')、reason(text)、approver_id(FK)字段”。代码中必须新增adjustments表,并在盘点接口中插入此记录。
5.4 现象:用例“生成销售单”返回JSON含order_id,但前端无法打印小票
原因:用例图只关注系统内部逻辑,忽略了“打印小票”是独立用例,需调用硬件打印机API。而学生常把打印逻辑硬编码在销售接口里,导致测试时因无打印机报错。
解决:在用例图中将“打印小票”作为<<extend>>扩展点,与“生成销售单”关联。代码中分离职责:销售接口只返回订单数据,另建/api/print/receipt接口接收订单ID,调用pycups库连接本地打印机。这样单元测试可跳过打印环节,专注业务逻辑。
5.5 现象:用例图中“采购员”与“供应商”间有Association,但代码里没体现供应商管理
原因:误将“供应商”当作外部系统,未建模其数据。实际采购申请必须关联供应商ID,入库单需记录供应商联系人,应付账款需按供应商汇总。
解决:新增suppliers表(id,name,contact_person,phone,bank_account),并在purchase_orders表中添加supplier_id外键。用例图中采购员与供应商的Association,应映射为采购申请表与供应商表的关联关系,而非仅流程示意。
6. 进阶技巧:用PlantUML自动化生成用例图源码,杜绝StarUML手工绘图误差
6.1 PlantUML语法精要:用文本代码定义用例图的确定性优势
StarUML拖拽绘图最大的问题是一致性难维持:改一个用例名,所有关联线要重新对齐;换一个Actor位置,整张图布局崩塌。而PlantUML用纯文本描述,版本控制友好,且语法天然约束UML规范。本资源配套的usecase.puml文件核心片段如下:
@startuml left to right direction actor "采购员" as buyer actor "仓库管理员" as warehouse_mgr actor "收银员" as cashier actor "财务人员" as finance rectangle "超市进销存系统" { buyer --> (创建采购申请) warehouse_mgr --> (审核采购申请) warehouse_mgr --> (登记入库) cashier --> (生成销售单) finance --> (生成应付账款报表) (创建采购申请) .> (校验供应商资质) : <<include>> (登记入库) .> (校验采购单有效性) : <<include>> (生成销售单) .> (计算会员积分) : <<extend>> } note right of (计算会员积分) 当顾客出示有效会员卡时触发 需校验会员等级与积分规则 end note @enduml关键语法点:
left to right direction强制布局方向,避免默认上下布局导致Actor挤在一起;actor "xxx" as yyy定义Actor别名,后续连线用yyy更简洁;.>表示虚线箭头,:后紧跟构造型,PlantUML自动渲染<<include>>;note块添加业务注释,导出图片时显示为便签,比StarUML的Documentation字段更直观。
6.2 一键生成与校验:用VS Code插件实现闭环工作流
安装VS Code的PlantUML插件(作者:jebbs),配置settings.json指定Graphviz路径后,即可实现:
- 实时预览:
.puml文件保存时,右侧自动弹出渲染图,修改文本即刷新; - 导出高清图:右键 →
Export Current Diagram→ 选择PNG,分辨率自动设为300dpi; - 语法校验:编辑器底部状态栏显示
PlantUML: OK或错误行号,如Unknown actor: "采购员"会立即提示拼写错误。
提示:将
usecase.puml加入Git仓库,每次修改前git commit -m "update usecase: add <<extend>> for member discount"。这样答辩时可展示“用例图演进史”,比静态截图更有说服力。
6.3 用例图与代码的双向追溯:用注释锚点打通设计与实现
PlantUML支持#anchor语法,可在用例上添加唯一标识,与代码注释联动:
(生成销售单) as UC_SALES_CREATE UC_SALES_CREATE .> (校验库存) : <<include>> note right of UC_SALES_CREATE ID: UC_SALES_CREATE 对应代码: app.py: create_sales_order() end note在Python代码中添加对应注释:
# app.py @app.route('/api/sales', methods=['POST']) def create_sales_order(): """ UC_SALES_CREATE: 生成销售单 前置条件: 商品存在且库存充足 后置条件: 库存扣减,应收账款增加 """ ...这样,当导师问“这个用例在代码哪实现?”,你可直接打开VS Code,Ctrl+P输入UC_SALES_CREATE,跳转到PlantUML文件和Python文件的对应位置。设计与代码不再割裂,而是同一枚硬币的两面。
从那以后我每次画用例图,都强制走一遍PlantUML文本编写 → VS Code实时预览 → 导出PDF插入PPT → 对照代码添加锚点注释的流程。哪怕多花半小时,也比答辩时被问“这个用例在哪实现的?”当场卡壳强。希望帮到你。
本文还有配套的精品资源,点击获取