甜点销售数据可视化分析系统 --- 技术文档
一、项目概述
1.1 项目简介
本项目是一个基于 Python 的甜点销售数据可视化分析系统,面向甜点零售场景,提供从数据管理到多维度分析、可视化大屏展示的一站式解决方案。系统涵盖用户认证、角色权限、数据 CRUD、多维图表分析及数据大屏等核心功能。
1.2 技术栈
| 层级 | 技术 | 版本 |
|---|---|---|
| 后端框架 | FastAPI | 0.115.0 |
| 数据库 | SQLite3 | 内置 |
| 模板引擎 | Jinja2 | 3.1.4 |
| 可视化 | ECharts | 5.5.0 |
| ECharts 扩展 | echarts-liquidfill | 3.1.0 |
| 用户认证 | JWT (PyJWT) | 2.9.0 |
| 密码加密 | passlib + bcrypt | 1.7.4 / 4.0.1 |
| ASGI 服务器 | Uvicorn | 0.30.6 |
1.3 运行环境
- Python 3.11+
- Windows / Linux / macOS
- 浏览器:Chrome 80+、Edge 80+、Firefox 78+

















二、系统架构
2.1 整体架构
┌─────────────────────────────────────────────────────┐
│ 浏览器 (前端) │
│ ECharts 渲染引擎 + Jinja2 模板 + CSS 甜品主题样式 │
└──────────────────────┬──────────────────────────────┘
│ HTTP / Cookie
┌──────────────────────▼──────────────────────────────┐
│ FastAPI (后端) │
│ ┌──────────┐ ┌──────────┐ ┌───────────────────┐ │
│ │ 页面路由 │ │ REST API │ │ 权限中间件 │ │
│ └──────────┘ └──────────┘ └───────────────────┘ │
└──────────────────────┬──────────────────────────────┘
│ SQLite3
┌──────────────────────▼──────────────────────────────┐
│ sweet.db (SQLite) │
│ users 表 │ sales 表 │
└─────────────────────────────────────────────────────┘
2.2 目录结构
sweet/
├── run.py # 启动入口
├── requirements.txt # Python 依赖
├── 甜点销售数据.csv # 原始数据源 (10000 条)
└── app/
├── __init__.py
├── main.py # FastAPI 应用:路由、API、权限控制 (656 行)
├── database.py # 数据库初始化、CSV 导入、迁移 (87 行)
├── auth.py # JWT 认证、密码哈希 (33 行)
├── static/
│ ├── css/
│ │ └── style.css # 甜品主题粉色风格 (701 行)
│ ├── js/
│ │ ├── echarts.min.js # ECharts 核心库
│ │ └── echarts-liquidfill.min.js # 水球图扩展
│ └── img/
└── templates/
├── login.html # 登录页
├── register.html # 注册页
├── dashboard.html # 概览仪表盘
├── analysis.html # 数据分析 (18 种图表)
├── data.html # 数据管理 (管理员)
├── users.html # 用户管理 (管理员)
├── profile.html # 个人中心
└── bigscreen.html # 可视化大屏
2.3 代码规模
| 文件 | 行数 |
|---|---|
| app/main.py | 656 |
| app/static/css/style.css | 701 |
| app/templates/analysis.html | 586 |
| app/templates/profile.html | 222 |
| app/templates/data.html | 146 |
| app/templates/dashboard.html | 146 |
| app/templates/bigscreen.html | 158 |
| app/templates/users.html | 108 |
| app/templates/register.html | 71 |
| app/templates/login.html | 61 |
| app/database.py | 87 |
| app/auth.py | 33 |
| 总计 | 3039 |
三、数据库设计
3.1 users 表
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | INTEGER | PK, AUTO | 用户 ID |
| username | TEXT | UNIQUE, NOT NULL | 用户名 |
| password | TEXT | NOT NULL | bcrypt 哈希密码 |
| is_admin | INTEGER | DEFAULT 0 | 1=管理员, 0=普通用户 |
| created_at | TEXT | DEFAULT datetime | 注册时间 |
预置账号:
- 管理员:
admin/123456 - 普通用户:
user/123456
角色分配规则: 系统中第一个注册的用户自动成为管理员,后续注册用户均为普通用户。
3.2 sales 表
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | INTEGER | PK, AUTO | 记录 ID |
| customer_id | INTEGER | NOT NULL | 顾客 ID |
| product_id | INTEGER | NOT NULL | 产品 ID |
| product_name | TEXT | NOT NULL | 产品名称 |
| quantity | INTEGER | NOT NULL | 购买数量 |
| price | REAL | NOT NULL | 单价 |
| purchase_date | TEXT | NOT NULL | 购买日期 |
| total_price | REAL | NOT NULL | 总价 (数量×单价) |
3.3 数据集概况
| 指标 | 值 |
|---|---|
| 记录总数 | 10,000 |
| 产品种类 | 10 |
| 客户数量 | 1,000 |
| 时间范围 | 2024-02-12 ~ 2025-02-11 |
| 总销售额 | ¥2,763,145 |
10 种甜点产品:
| 序号 | 产品名称 |
|---|---|
| 1 | 巧克力熔岩蛋糕 |
| 2 | 抹茶红豆蛋糕 |
| 3 | 提拉米苏 |
| 4 | 柠檬塔 |
| 5 | 椰香芒果布丁 |
| 6 | 焦糖玛奇朵冰淇淋 |
| 7 | 芒果慕斯 |
| 8 | 草莓千层蛋糕 |
| 9 | 蓝莓芝士蛋糕 |
| 10 | 黑森林樱桃蛋糕 |
3.4 数据库初始化流程
启动 → CREATE TABLE IF NOT EXISTS → 检查 is_admin 列是否存在
↓ 否
ALTER TABLE ADD COLUMN
↓
检查是否有管理员账号
↓ 否
INSERT 默认 admin 账号
↓
检查 sales 是否为空
↓ 是
从 CSV 导入 10000 条数据
数据库支持热迁移:如果已有旧版数据库(无 is_admin 字段),系统会自动 ALTER TABLE 添加该列,无需手动迁移。
四、认证与权限
4.1 JWT 认证流程
用户提交登录表单
↓
FastAPI 校验用户名密码
↓
生成 JWT Token (payload: user_id, username, is_admin, exp)
↓
设置 HttpOnly Cookie (token=xxx, max_age=86400)
↓
返回 JSONResponse { msg, is_admin }
↓
前端 JS 读取响应,成功则跳转 /
JWT Payload 结构:
json
{
"user_id": 1,
"username": "admin",
"is_admin": true,
"exp": 1779724439
}
4.2 角色权限矩阵
| 功能 | 管理员 | 普通用户 |
|---|---|---|
| 概览仪表盘 | ✅ | ✅ |
| 数据分析 | ✅ | ✅ |
| 可视化大屏 | ✅ | ✅ |
| 个人中心 | ✅ | ✅ |
| 数据管理 (CRUD) | ✅ | ❌ |
| 用户管理 | ✅ | ❌ |
| 数据写入 API | ✅ | ❌ |
| 用户管理 API | ✅ | ❌ |
4.3 权限实现
页面级别: 路由函数中检查 user.get("is_admin"),非管理员重定向到首页。
API 级别: require_admin() 函数校验 JWT 中的 is_admin 字段,不满足则返回 403。
前端级别: 侧边栏导航使用 Jinja2 {% if user.is_admin %} 条件渲染,管理员才可见数据管理和用户管理入口。
4.4 前端错误提示
登录/注册页面使用 JS fetch 提交表单,根据 HTTP 状态码显示中文提示:
| 状态码 | 提示信息 |
|---|---|
| 200 | 跳转首页 |
| 401 | 用户名或密码错误 |
| 400 | 用户名已存在 |
| 前端校验 | 两次密码输入不一致 |
| 网络异常 | 网络错误,请稍后重试 |
五、页面功能详解
5.1 登录页 (/login)
- 甜品风格粉色渐变背景 + 浮动光斑动画
- 毛玻璃卡片效果登录框
- 🧁 图标装饰
- 前端 JS 异步提交,失败时红色错误提示框
- 底部链接跳转注册页
5.2 注册页 (/register)
- 与登录页相同的甜品主题风格
- 🍰 图标装饰
- 前端校验两次密码一致性
- 第一个注册用户自动成为管理员
5.3 概览仪表盘 (/)
核心指标卡片 (5 项):
| 图标 | 指标 | 数据源 |
|---|---|---|
| 💰 | 总销售额 | overview.revenue |
| 📦 | 总销量 | overview.qty |
| 🧾 | 订单总数 | overview.cnt |
| 👥 | 客户总数 | overview.customers |
| 💎 | 平均客单价 | overview.avg_order |
图表 (4 个):
| 图表 | 类型 | API |
|---|---|---|
| 月度销售趋势 | 折线+柱状混合 | monthly_trend |
| 产品销售额占比 | 环形饼图 | product_sales |
| 产品销量排行 | 横向条形图 | product_sales |
| 订单金额分布 | 饼图 | price_distribution |
5.4 数据分析 (/analysis)
18 种图表,6 行布局:
第一行 --- 时间维度:
| 图表 | 类型 | 说明 |
|---|---|---|
| 📈 月度销售趋势 | 折线+柱状 | 销售额面积折线 + 销量柱状,双 Y 轴 |
| 📅 星期销售分析 | 渐变柱状 | 7 天销售额对比 |
第二行 --- 产品维度:
| 图表 | 类型 | 说明 |
|---|---|---|
| 🏆 产品销售额排行 | 横向渐变条形 | 按销售额降序 |
| 🍩 产品销量占比 | 玫瑰饼图 | 南丁格尔玫瑰图效果 |
第三行 --- 客户维度:
| 图表 | 类型 | 说明 |
|---|---|---|
| 👥 TOP10 高消费客户 | 横向条形 | 消费金额前 10 |
| 📦 购买数量分布 | 饼图 | 不同购买件数的订单占比 |
第四行 --- 交叉维度:
| 图表 | 类型 | 说明 |
|---|---|---|
| 🌡️ 产品-星期热力图 | 热力图 | 10 产品 × 7 天订单量矩阵 |
| 🎯 产品多维雷达图 | 雷达图 | 销量/销售额/订单数/均客单价 |
第五行 --- 结构维度:
| 图表 | 类型 | 说明 |
|---|---|---|
| 📊 产品月度销售堆叠图 | 堆叠柱状 | 各产品月度销售额堆叠 |
| 💰 订单金额分布 | 柱状 | 0-50/50-100/100-200/200-500/500+ |
第六行 --- 单值维度:
| 图表 | 类型 | 说明 |
|---|---|---|
| ⏱️ 产品平均单价 | 横向条形 | 各产品均价对比 |
| 🔻 销售漏斗图 | 漏斗图 | 产品销售额漏斗 |
| 🌊 产品订单量涟漪图 | 涟漪散点 | effectScatter 动画 |
第七行 --- 特殊图表:
| 图表 | 类型 | 说明 |
|---|---|---|
| 🎯 总销售额仪表盘 | Gauge 仪表 | 目标 300 万达成率 |
| 🟩 产品销售矩形树图 | Treemap | 面积表示销售占比 |
| ☀️ 星期×产品旭日图 | Sunburst | 层级:星期→产品 |
第八行 --- 多维与对比:
| 图表 | 类型 | 说明 |
|---|---|---|
| ∥ 产品多维平行坐标图 | Parallel | 均购量/均单价/均客单价/总销售额 |
| 📊 产品订单量对比柱状图 | 渐变条形 | 按订单量降序 |
第九行 --- 流向与趋势:
| 图表 | 类型 | 说明 |
|---|---|---|
| 🔀 产品→金额等级桑基图 | Sankey | 产品流向小/中/高/大额订单 |
| 🌊 产品销售主题河流图 | ThemeRiver | 时间维度上的销售河流 |
第十行 --- 形象化图表:
| 图表 | 类型 | 说明 |
|---|---|---|
| 🍫 产品销量象形柱图 | PictorialBar | 矩形纹理重复填充 |
| 💧 销售目标完成率水球图 | LiquidFill | echarts-liquidfill 波浪效果 |
| 🎨 产品收入结构组合图 | 组合图 | 柱状+虚线+帕累托累计曲线 |
5.5 数据管理 (/data) --- 仅管理员
- 产品名称 + 日期范围筛选
- 分页表格(每页 20 条)
- 添加/编辑/删除销售记录
- 弹窗表单,Toast 提示
- 写入操作需管理员权限,API 级别校验
5.6 用户管理 (/users) --- 仅管理员
- 用户列表表格(ID、用户名、角色、注册时间)
- 切换管理员状态按钮
- 删除用户按钮(不可删除自己)
- Toast 提示操作结果
5.7 个人中心 (/profile)
用户信息卡片:
- 🧁 头像 + 用户名 + 注册时间
- 管理员/活跃用户徽章
- 管理数据量 + 系统用户数
分析图表 (4 个):
| 图表 | 类型 | 说明 |
|---|---|---|
| 🧑🤝🧑 客户消费等级分布 | 环形饼图 | 低/中/高/超高消费客户数 |
| 🍩 产品关注度偏好 | 环形饼图 | TOP5 产品订单占比 |
| 📈 月度订单趋势 | 面积折线图 | 月度订单数量变化 |
| 🔍 单价 vs 销量散点图 | 散点图 | 产品均价与总销量关系 |
修改密码:
- 原密码 + 新密码 + 确认新密码
- 前端校验密码一致性
- 后端校验原密码正确性
5.8 可视化大屏 (/bigscreen)
- 深色主题全屏布局,无需登录
- 实时时钟显示 + 返回首页按钮
- 5 项核心指标卡片
- 6 个图表:月度趋势、产品占比、销量排行、星期分布、热力图
- Flex 弹性布局自适应屏幕
- 每 5 分钟自动刷新
六、API 接口文档
6.1 认证接口
POST /api/login
用户登录,返回 JWT Cookie。
请求: application/x-www-form-urlencoded
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| username | string | ✅ | 用户名 |
| password | string | ✅ | 密码 |
成功响应 (200):
json
{
"msg": "登录成功",
"is_admin": true
}
Cookie: token=eyJ...; HttpOnly; Max-Age=86400; Path=/
失败响应 (401):
json
{
"detail": "用户名或密码错误"
}
POST /api/register
用户注册,返回 JWT Cookie。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| username | string | ✅ | 用户名 (唯一) |
| password | string | ✅ | 密码 |
成功响应 (200):
json
{
"msg": "注册成功",
"is_admin": false
}
失败响应 (400):
json
{
"detail": "用户名已存在"
}
POST /api/logout
退出登录,删除 Cookie,302 重定向到登录页。
6.2 数据 CRUD 接口
GET /api/sales
分页查询销售数据。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
| page | int | 1 | 页码 |
| size | int | 20 | 每页条数 (1-100) |
| product | string | - | 按产品名筛选 |
| start_date | string | - | 起始日期 (YYYY-MM-DD) |
| end_date | string | - | 结束日期 (YYYY-MM-DD) |
响应:
json
{
"total": 10000,
"page": 1,
"size": 20,
"data": [{ "id": 1, "customer_id": 66, "product_name": "提拉米苏", ... }]
}
POST /api/sales --- 🔒 管理员
新增销售记录。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| customer_id | int | ✅ | 顾客 ID |
| product_id | int | ✅ | 产品 ID |
| product_name | string | ✅ | 产品名称 |
| quantity | int | ✅ | 数量 |
| price | float | ✅ | 单价 |
| purchase_date | string | ✅ | 购买日期 |
响应:
json
{ "msg": "添加成功" }
PUT /api/sales/{sale_id} --- 🔒 管理员
更新销售记录,请求体为 JSON。
DELETE /api/sales/{sale_id} --- 🔒 管理员
删除销售记录。
6.3 用户管理接口 --- 🔒 管理员
GET /api/users
获取用户列表。
响应:
json
[
{ "id": 1, "username": "admin", "is_admin": 1, "created_at": "2026-05-25 00:00:00" },
{ "id": 2, "username": "user", "is_admin": 0, "created_at": "2026-05-25 00:00:00" }
]
DELETE /api/users/{user_id}
删除用户(不可删除自己)。
失败响应 (400):
json
{ "detail": "不能删除自己" }
PUT /api/users/{user_id}/toggle_admin
切换用户管理员状态(不可修改自己)。
响应:
json
{ "msg": "更新成功", "is_admin": 1 }
6.4 分析接口
| 接口 | 说明 | 维度 |
|---|---|---|
| GET /api/analysis/overview | 核心指标汇总 | 全局 |
| GET /api/analysis/product_sales | 产品销量/销售额/均价/订单数 | 产品 |
| GET /api/analysis/monthly_trend | 月度销售额/销量/订单数 | 时间×指标 |
| GET /api/analysis/weekday | 星期销售额/订单数 | 时间 |
| GET /api/analysis/price_distribution | 订单金额区间分布 | 金额 |
| GET /api/analysis/quantity_distribution | 购买数量分布 | 数量 |
| GET /api/analysis/top_customers | TOP10 高消费客户 | 客户 |
| GET /api/analysis/product_monthly | 产品月度销售额 | 产品×时间 |
| GET /api/analysis/daily_trend | 日度销售额/订单数 | 时间 |
| GET /api/analysis/customer_heatmap | 产品×星期订单热力矩阵 | 产品×时间 |
| GET /api/analysis/revenue_rank | 产品销售额排名 | 产品 |
| GET /api/analysis/sunburst | 星期×产品层级数据 | 时间×产品 |
| GET /api/analysis/parallel | 产品多维指标 (均购量/均单价/均客单价/总销售额) | 产品×多维 |
| GET /api/analysis/sankey | 产品→金额等级流向 | 产品→金额 |
| GET /api/analysis/theme_river | 日度产品销售河流 | 时间×产品 |
通用响应格式:
json
[
{ "product_name": "提拉米苏", "total_qty": 5764, "total_revenue": 292205.0, "avg_price": 281.24, "order_count": 1039 }
]
6.5 个人中心接口
GET /api/profile/stats --- 🔒 登录
获取个人中心统计数据。
POST /api/profile/change_password --- 🔒 登录
修改密码。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| old_password | string | ✅ | 原密码 |
| new_password | string | ✅ | 新密码 |
七、前端设计
7.1 设计风格
- 主题:甜品风格粉色系
- 主色:#ec407a (Pink 500)
- 辅色:#ffa726 (Orange 400)、#ab47bc (Purple 400)、#26a69a (Teal 400)
- 背景:#fff0f5 (Pink 100) 渐变至 #fff8f0 (Cream)
- 圆角:16px (卡片)、10px (按钮/输入框)
- 阴影:粉色系半透明投影
- 动画:浮动光斑背景、卡片 hover 上浮、按钮点击下沉
7.2 响应式断点
| 断点 | 侧边栏 | 图表网格 | 大屏网格 |
|---|---|---|---|
| >1200px | 240px 固定 | 2列/3列 | 3列 |
| 768-1200px | 60px 仅图标 | 1列 | 2列 |
| <768px | 60px 仅图标 | 1列 | 1列 |
7.3 ECharts 图表类型汇总
| 图表类型 | ECharts series.type | 使用位置 |
|---|---|---|
| 折线图 | line | 仪表盘、分析、大屏、个人中心 |
| 柱状图 | bar | 仪表盘、分析、大屏 |
| 饼图 | pie | 仪表盘、分析、大屏、个人中心 |
| 环形饼图 | pie (radius) | 仪表盘、分析、个人中心 |
| 玫瑰图 | pie (roseType) | 分析 |
| 横向条形图 | bar (横向) | 仪表盘、分析、大屏 |
| 雷达图 | radar | 分析 |
| 热力图 | heatmap | 分析、大屏 |
| 堆叠柱状图 | bar (stack) | 分析 |
| 仪表盘 | gauge | 分析 |
| 漏斗图 | funnel | 分析 |
| 涟漪散点图 | effectScatter | 分析 |
| 矩形树图 | treemap | 分析 |
| 旭日图 | sunburst | 分析 |
| 平行坐标图 | parallel | 分析 |
| 桑基图 | sankey | 分析 |
| 主题河流图 | themeRiver | 分析 |
| 象形柱图 | pictorialBar | 分析 |
| 水球图 | liquidFill | 分析 |
| 组合图 | bar+line | 分析 |
| 散点图 | scatter | 个人中心 |
共计 21 种图表类型,18 种出现在数据分析页。
八、部署与运行
8.1 安装依赖
bash
pip install -r requirements.txt
requirements.txt 内容:
fastapi==0.115.0
uvicorn==0.30.6
jinja2==3.1.4
python-multipart==0.0.9
pyjwt==2.9.0
passlib==1.7.4
bcrypt==4.0.1
注意:bcrypt 版本锁定为 4.0.1,与 passlib 兼容。4.2+ 版本会导致
module 'bcrypt' has no attribute '__about__'错误。
8.2 启动服务
bash
cd sweet
python run.py
服务默认运行在 http://localhost:8001,支持热重载。
8.3 首次运行
系统启动时自动执行:
- 创建 SQLite 数据库
app/sweet.db - 创建 users / sales 表
- 若无管理员,自动创建
admin/123456 - 若 sales 为空,自动从 CSV 导入 10000 条数据
- 若是旧数据库(无 is_admin 字段),自动 ALTER TABLE 迁移
8.4 访问地址
九、安全设计
9.1 认证安全
| 措施 | 说明 |
|---|---|
| 密码哈希 | bcrypt (cost factor 12) |
| JWT HttpOnly Cookie | 防 XSS 窃取 token |
| Token 过期 | 24 小时自动失效 |
| Cookie Path | / 全站可用 |
9.2 权限安全
| 层级 | 机制 |
|---|---|
| 页面路由 | 后端检查 is_admin,非法访问 302 重定向 |
| 写入 API | require_admin() 装饰器,非管理员返回 403 |
| 前端导航 | Jinja2 条件渲染,非管理员看不到管理入口 |
| 自保护 | 管理员不可删除自己、不可修改自己的管理员状态 |
十、关键代码说明
10.1 database.py --- 数据库初始化与迁移
init_db(): 幂等初始化,支持 CREATE IF NOT EXISTS + ALTER TABLE 迁移_import_csv(): 读取 UTF-8 编码的 CSV,批量 INSERT 10000 条记录- 首次无管理员时,自动 INSERT
admin/123456(is_admin=1)
10.2 auth.py --- 认证模块
create_token(user_id, username, is_admin): 生成 JWT,payload 包含 is_admindecode_token(token): 解码验证,过期/无效返回 Nonehash_password()/verify_password(): bcrypt 封装
10.3 main.py --- 核心路由
get_current_user(): 从 Cookie 读取 token 并解码require_admin(): 认证 + 管理员权限双重校验- 登录/注册 API:成功时
JSONResponse+set_cookie,失败时HTTPException - 分析 API:15 个端点覆盖全局、产品、时间、客户、交叉、流向等维度
十一、常见问题
Q: 启动报错 module 'bcrypt' has no attribute '__about__'
A: bcrypt 版本过高,与 passlib 不兼容。执行 pip install bcrypt==4.0.1。
Q: 数据库损坏如何重建
A: 删除 app/sweet.db 文件,重启服务即可自动重建并导入数据。
Q: 忘记管理员密码
A: 删除 app/sweet.db,重启服务后自动创建 admin/123456。
Q: 如何新增管理员
A: 以 admin 登录,进入用户管理,点击"设为管理员"按钮。
Q: 大屏页面打不开
A: 大屏无需登录,直接访问 /bigscreen。如仍无法访问,检查端口是否正确。
Q: 图表数据为空
A: 检查 甜点销售数据.csv 是否在项目根目录,首次启动需从此文件导入数据。