164-基于Python的甜点销售数据可视化分析系统
甜点销售数据可视化分析系统 — 技术文档
一、项目概述
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 结构:
{"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 前端错误提示
登录/注册页面使用 JSfetch提交表单,根据 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):
{"msg":"登录成功","is_admin":true}Cookie:token=eyJ...; HttpOnly; Max-Age=86400; Path=/
失败响应 (401):
{"detail":"用户名或密码错误"}POST /api/register
用户注册,返回 JWT Cookie。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| username | string | ✅ | 用户名 (唯一) |
| password | string | ✅ | 密码 |
成功响应 (200):
{"msg":"注册成功","is_admin":false}失败响应 (400):
{"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) |
响应:
{"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 | ✅ | 购买日期 |
响应:
{"msg":"添加成功"}PUT /api/sales/{sale_id} — 🔒 管理员
更新销售记录,请求体为 JSON。
DELETE /api/sales/{sale_id} — 🔒 管理员
删除销售记录。
6.3 用户管理接口 — 🔒 管理员
GET /api/users
获取用户列表。
响应:
[{"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):
{"detail":"不能删除自己"}PUT /api/users/{user_id}/toggle_admin
切换用户管理员状态(不可修改自己)。
响应:
{"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 | 日度产品销售河流 | 时间×产品 |
通用响应格式:
[{"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 安装依赖
pipinstall-rrequirements.txtrequirements.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 启动服务
cdsweet 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 访问地址
| 页面 | URL |
|---|---|
| 登录 | http://localhost:8001/login |
| 概览 | http://localhost:8001/ |
| 数据分析 | http://localhost:8001/analysis |
| 数据管理 | http://localhost:8001/data |
| 用户管理 | http://localhost:8001/users |
| 个人中心 | http://localhost:8001/profile |
| 可视化大屏 | http://localhost:8001/bigscreen |
九、安全设计
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是否在项目根目录,首次启动需从此文件导入数据。
