3. 数据模型设计:货架数据结构定义、状态枚举与模拟数据生成

好,咱们进入第三个环节。说实话,很多初学者一上来就急着写界面、画图表,结果做到一半发现数据对不上、状态乱套了。我个人的习惯是——先把数据模型想清楚,再动手写代码。这就像盖房子,地基没打好,后面全是坑。

这一章,我们就来定义货架的数据结构,明确状态枚举,再生成一批模拟数据。嗯,内容不多,但很关键。

3.1 货架数据结构:到底要存哪些信息?

先问一个问题:一个货架,在系统里应该长什么样?

你想想看,我们做的是「货架状态可视化」,那至少得知道:

  • 这个货架在哪?(位置信息)
  • 它现在是什么状态?(满/空/缺货)
  • 它放的是什么商品?(品类)
  • 它最多能放多少?现在有多少?(容量数据)

我在项目中遇到过一种情况:有人把货架编号和商品名称硬编码在一起,结果换商品时整个数据结构都得改。所以,我建议把货架本身的信息和商品信息分开,但又通过关联字段连起来。

下面是我常用的一个数据结构定义,用 Python 的字典来表示:

shelf = {
    "id": "A-01-01",          # 货架编号:区域-排-层
    "zone": "A",              # 所属区域
    "row": 1,                 # 第几排
    "level": 1,               # 第几层
    "category": "饮料",       # 商品品类
    "capacity": 50,           # 最大容量(件)
    "current_stock": 30,      # 当前库存(件)
    "status": "normal",       # 状态枚举值
    "last_updated": "2025-01-15 14:30:00"  # 最后更新时间
}

你看,这个结构很清晰。每个字段都有明确的含义。其中 status 字段就是我们接下来要重点讲的状态枚举。

小提示: 我习惯把 id 设计成有意义的编码,比如 "A-01-01" 一眼就能看出是 A 区第 1 排第 1 层。这在排查问题时特别方便。

3.2 状态枚举:满、空、缺货,怎么定义?

货架的状态,说白了就三种:

  • 满(full):库存量接近或等于容量,不需要补货。
  • 空(empty):库存量为 0,必须立即补货。
  • 缺货(low):库存量低于某个阈值,需要关注。

但这里有个细节——「缺货」的阈值怎么定?

我曾经在一个项目中,直接把阈值写死成 10%。结果有个货架容量是 1000,10% 就是 100 件,其实还够卖两天,但系统疯狂报警。后来我改成按「安全库存天数」来算,才解决了问题。

不过咱们这个课程是入门级的,先简化处理。我建议用容量百分比来定义:

状态 枚举值 判断条件 说明
full current_stock >= capacity * 0.8 库存充足,无需补货
缺货 low current_stock <= capacity * 0.2 库存偏低,建议补货
empty current_stock == 0 完全没货,必须补货

嗯,这里要注意:fulllow 之间其实还有一个「正常」状态。但为了简化,我们只定义这三种极端情况。中间状态可以统一归为 normal

避坑指南: 我曾经把 emptylow 混在一起,结果导致缺货预警和紧急补货的流程冲突。记住,empty 是红色警报,low 是黄色预警,级别完全不同。

3.3 模拟数据生成:让数据「活」起来

好了,数据结构定义好了,状态枚举也清楚了。接下来我们要生成一批模拟数据,用来测试我们的可视化界面。

为什么要模拟数据?因为真实数据往往涉及隐私或权限问题,而且你不可能为了开发一个仪表盘,真的去仓库里摆满货架再一个个数。所以,自己造数据是最快的。

我写了一个简单的 Python 脚本来生成模拟数据。核心思路是:

  • 定义几个区域(A、B、C)
  • 每个区域有若干排和层
  • 随机分配品类和库存量
  • 根据库存量计算状态

来看代码:

import random
from datetime import datetime

def generate_shelf_data():
    zones = ['A', 'B', 'C']
    categories = ['饮料', '零食', '日用品', '粮油', '调味品']
    shelves = []
    
    shelf_id = 1
    for zone in zones:
        for row in range(1, 4):        # 每区3排
            for level in range(1, 5):  # 每排4层
                capacity = random.choice([30, 50, 80, 100])
                current_stock = random.randint(0, capacity)
                
                # 根据库存量判断状态
                if current_stock == 0:
                    status = "empty"
                elif current_stock <= capacity * 0.2:
                    status = "low"
                elif current_stock >= capacity * 0.8:
                    status = "full"
                else:
                    status = "normal"
                
                shelf = {
                    "id": f"{zone}-{row:02d}-{level:02d}",
                    "zone": zone,
                    "row": row,
                    "level": level,
                    "category": random.choice(categories),
                    "capacity": capacity,
                    "current_stock": current_stock,
                    "status": status,
                    "last_updated": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                }
                shelves.append(shelf)
                shelf_id += 1
    
    return shelves

# 生成数据
data = generate_shelf_data()
print(f"共生成 {len(data)} 个货架数据")
print(data[:3])  # 打印前3个看看效果

运行这个脚本,你会得到类似这样的输出:

共生成 36 个货架数据
[
  {'id': 'A-01-01', 'zone': 'A', 'row': 1, 'level': 1, 'category': '饮料', 'capacity': 50, 'current_stock': 42, 'status': 'full', 'last_updated': '2025-01-15 14:30:00'},
  {'id': 'A-01-02', 'zone': 'A', 'row': 1, 'level': 2, 'category': '零食', 'capacity': 80, 'current_stock': 5, 'status': 'low', 'last_updated': '2025-01-15 14:30:00'},
  {'id': 'A-01-03', 'zone': 'A', 'row': 1, 'level': 3, 'category': '日用品', 'capacity': 100, 'current_stock': 0, 'status': 'empty', 'last_updated': '2025-01-15 14:30:00'}
]

你看,三个货架分别展示了 fulllowempty 三种状态。这就是我们后面做可视化要用到的数据基础。

核心要点: 模拟数据要尽量贴近真实场景。比如库存量不要总是整数,状态分布要合理(不能全是满的,也不能全是空的)。我一般会让 30% 的货架处于满状态,20% 处于空状态,30% 缺货,剩下 20% 正常。这样可视化效果才真实。

3.4 本章小结

这一章我们做了三件事:

  1. 定义了货架的数据结构——包含编号、区域、容量、库存等关键字段。
  2. 明确了状态枚举——满(full)、空(empty)、缺货(low),并给出了判断条件。
  3. 生成了模拟数据——用 Python 脚本批量生成 36 个货架数据,覆盖了所有状态。

有了这些数据,下一章我们就可以开始搭建可视化仪表盘了。说实话,数据模型设计这一步虽然看起来枯燥,但它是整个项目的基石。你想想看,如果数据结构没设计好,后面改起来有多痛苦?

好,这一章就到这里。下一章我们开始画图,让数据「看得见」。