131-基于Flask的美国新泽西州自动售货机销售数据可视化分析系统

基于Flask的美国新泽西州自动售货机销售数据可视化分析系统 --- 技术文档


目录

  1. 项目概述
  2. 系统架构
  3. 技术栈与依赖
  4. 项目目录结构
  5. 数据库设计
  6. 后端设计
  7. 前端设计
  8. 功能模块详解
  9. API接口文档
  10. 数据处理流程
  11. 部署与运行
  12. 配置说明
  13. 安全设计
  14. 已知问题与改进方向

1. 项目概述

1.1 项目背景

本系统是一个面向美国新泽西州自动售货机运营场景的销售数据可视化分析平台。系统以 Flask 为后端框架、MySQL 为数据存储、ECharts 为可视化引擎,将来自 5 个销售地点、4 大商品品类的 9,617 条交易记录,通过多维度交互式仪表盘呈现,帮助运营者快速洞察经营状况、优化商品策略、提升设备效率。

1.2 核心能力

能力维度 说明
经营总览 关键KPI指标卡片、销售趋势、品类占比、支付方式分布
时间洞察 日历热力图、星期维度分析、月度品类趋势、环比增长
深度分析 价格-品类交叉分析、地点畅销商品、核心洞察卡片
商品策略 商品贡献树图、SKU四象限矩阵、价格带分布、ABC分类
设备画像 设备效率象限图、雷达图、品类组合分析、设备排名
运营建议 销售预测、补货优先级、ABC分类表、品类-设备堆叠图
交易明细 可筛选/搜索/分页的交易列表,支持CSV导出
数据管理 管理员对销售记录的增删改查(CRUD)

1.3 数据范围

  • 数据来源vending_machine_sales.csv(1.5 MB,9,617条记录)
  • 时间跨度:2025年全年(日期经过归一化处理)
  • 地理覆盖:5个销售地点(Brunswick Sq Mall 等)
  • 商品品类:Food、Carbonated、Non Carbonated、Water
  • 支付方式:Cash、Credit




















2. 系统架构

2.1 整体架构图

复制代码
┌─────────────────────────────────────────────────────────┐
│                      浏览器 (Browser)                     │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐ │
│  │ Bootstrap │  │  ECharts │  │   CSS    │  │    JS    │ │
│  │   5.3.3   │  │   5.5.1  │  │ styles   │  │dashboard │ │
│  └──────────┘  └──────────┘  └──────────┘  └──────────┘ │
└────────────────────────┬────────────────────────────────┘
                         │ HTTP (GET/POST/PUT/DELETE)
                         ▼
┌─────────────────────────────────────────────────────────┐
│                  Flask Application (app.py)               │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐ │
│  │ 路由层   │  │ 认证装饰 │  │ 过滤构建 │  │ 错误处理 │ │
│  │ Routes   │  │ Decorators│  │build_where│  │ Handler  │ │
│  └──────────┘  └──────────┘  └──────────┘  └──────────┘ │
│  ┌──────────┐  ┌──────────┐                              │
│  │ 模板渲染 │  │ JSON序列化│                              │
│  │ Jinja2   │  │json_value │                              │
│  └──────────┘  └──────────┘                              │
└────────────────────────┬────────────────────────────────┘
                         │ PyMySQL (TCP 3306)
                         ▼
┌─────────────────────────────────────────────────────────┐
│                    MySQL 数据库                            │
│  ┌──────────┐  ┌──────────────┐  ┌──────────────┐       │
│  │  users   │  │ vending_sales│  │ import_logs  │       │
│  └──────────┘  └──────────────┘  └──────────────┘       │
└─────────────────────────────────────────────────────────┘
                         ▲
                         │ CSV 导入
┌─────────────────────────────────────────────────────────┐
│              vending_machine_sales.csv                    │
│           (9,617条原始交易记录 + 脚本工具)                  │
└─────────────────────────────────────────────────────────┘

2.2 请求处理流程

复制代码
浏览器发起请求
    │
    ▼
Flask 路由匹配
    │
    ▼
@app.before_request ──→ load_logged_in_user() 从 session 加载用户
    │
    ▼
装饰器检查 ──→ @login_required / @admin_required
    │
    ├─ 页面请求 ──→ render_template() ──→ Jinja2 渲染 HTML
    │
    └─ API请求  ──→ build_where() 构建动态 WHERE 子句
                     │
                     ▼
                  SQL 查询 (PyMySQL + DictCursor)
                     │
                     ▼
                  json_rows() 序列化 Decimal/date
                     │
                     ▼
                  jsonify() 返回 JSON 响应

2.3 架构特点

  • 单文件后端 :所有路由、API端点、辅助函数集中在 app.py(1,167行),无蓝图拆分
  • 连接按需分配 :通过 Flask g 对象实现每个请求一个数据库连接,请求结束自动关闭
  • 统一过滤机制build_where() 函数为所有API端点提供一致的动态SQL过滤能力
  • 前端无框架:使用原生 JavaScript + ECharts,无 React/Vue 等框架依赖

3. 技术栈与依赖

3.1 后端技术栈

技术 版本要求 用途
Python 3.10+ 运行时环境
Flask >= 3.1 Web框架,路由、模板、会话管理
PyMySQL >= 1.1 MySQL数据库驱动,纯Python实现
Werkzeug >= 3.1 WSGI工具库,密码哈希(generate_password_hash / check_password_hash
pandas >= 2.2 仅在Jupyter探索笔记本中使用,应用代码未引用

3.2 前端技术栈

技术 版本 用途
Bootstrap 5.3.3 (CDN) 响应式布局、表单、组件
Bootstrap Icons 1.11.3 (CDN) 图标库
ECharts 5.5.1 (CDN) 数据可视化图表引擎
Google Fonts - Fira Sans(正文)+ Fira Code(等宽数字)
原生 JavaScript ES6+ 页面逻辑、API调用、图表渲染

3.3 数据库

技术 说明
MySQL 5.7+ / 8.0+,字符集 utf8mb4,排序规则 utf8mb4_unicode_ci
存储引擎 InnoDB

3.4 依赖安装

bash 复制代码
pip install -r requirements.txt

requirements.txt 内容:

复制代码
Flask>=3.1
PyMySQL>=1.1
pandas>=2.2
Werkzeug>=3.1

4. 项目目录结构

复制代码
America/
│
├── app.py                              # 主应用文件 (1,167行)
│                                       #   - 所有页面路由 (12个)
│                                       #   - 所有API端点 (22个)
│                                       #   - 认证/授权装饰器
│                                       #   - 辅助函数
│                                       #   - 错误处理
│
├── config.py                           # 配置类 (21行)
│                                       #   - 数据库连接参数
│                                       #   - 应用密钥
│                                       #   - CSV路径、显示年份、分页大小
│
├── database.py                         # 数据库模块 (250行)
│                                       #   - 连接管理
│                                       #   - Schema DDL(3张表)
│                                       #   - 管理员种子数据
│                                       #   - CSV导入逻辑
│
├── requirements.txt                    # Python依赖清单
├── vending_machine_sales.csv           # 原始数据文件 (1.5MB, 9,618行)
├── 关于自动售货机销售数据集的探索.ipynb    # 数据探索Jupyter笔记本
├── .gitignore                          # Git忽略规则
├── 技术文档.md                          # 本文档
│
├── scripts/                            # 工具脚本
│   ├── setup_database.py               #   一键初始化:建库、建表、种子数据、导入CSV
│   ├── convert_sales_year.py           #   CSV文件内日期年份转换
│   └── shift_database_year.py          #   数据库内日期年份迁移
│
├── static/                             # 静态资源
│   ├── css/
│   │   └── styles.css                  #   自定义样式 (942行)
│   └── js/
│       └── dashboard.js                #   前端逻辑 (1,333行)
│
└── templates/                          # Jinja2模板
    ├── auth_base.html                  #   认证页面基础布局(登录/注册分屏)
    ├── login.html                      #   登录页
    ├── register.html                   #   注册页
    ├── base.html                       #   主应用布局(侧边栏+顶栏)
    ├── dashboard.html                  #   经营总览
    ├── time_insights.html              #   时间洞察
    ├── analysis.html                   #   深度分析
    ├── product_strategy.html           #   商品策略
    ├── machine_portrait.html           #   设备画像
    ├── operations.html                 #   运营建议
    ├── records.html                    #   交易明细
    ├── profile.html                    #   个人中心
    ├── admin_data.html                 #   数据管理(管理员)
    └── db_error.html                   #   数据库错误页

5. 数据库设计

5.1 ER关系图

复制代码
┌──────────────────────┐       ┌──────────────────────────────────┐
│       users          │       │         vending_sales            │
├──────────────────────┤       ├──────────────────────────────────┤
│ PK  id INT           │       │ PK  id BIGINT                    │
│     username VARCHAR │       │     status VARCHAR(40)           │
│     email VARCHAR    │       │     device_id VARCHAR(80)        │
│     password_hash    │       │     location VARCHAR(120)        │
│     real_name VARCHAR│       │     machine VARCHAR(160)         │
│     phone VARCHAR    │       │     product VARCHAR(255)         │
│     role VARCHAR     │       │     category VARCHAR(80)         │
│     last_login DATETIME│     │     transaction_id BIGINT        │
│     created_at       │       │     trans_date DATE              │
│     updated_at       │       │     payment_type VARCHAR(40)     │
└──────────────────────┘       │     r_coil INT                   │
                               │     r_price DECIMAL(10,2)        │
                               │     r_qty INT                    │
                               │     m_coil INT                   │
                               │     m_price DECIMAL(10,2) NULL   │
                               │     m_qty INT                    │
                               │     line_total DECIMAL(10,2)     │
                               │     trans_total DECIMAL(10,2)    │
                               │     prcd_date DATE               │
                               │     created_at DATETIME          │
                               └──────────────────────────────────┘

┌──────────────────────┐
│    import_logs       │
├──────────────────────┤
│ PK  id INT           │
│     file_name VARCHAR│
│     row_count INT    │
│     imported_by VARCHAR│
│     imported_at DATETIME│
└──────────────────────┘

5.2 表结构详细定义

5.2.1 users 表 --- 用户账户
字段 类型 约束 说明
id INT AUTO_INCREMENT, PK 用户ID
username VARCHAR(80) NOT NULL, UNIQUE 用户名(登录凭证)
email VARCHAR(160) NOT NULL, UNIQUE 邮箱(登录凭证+唯一性)
password_hash VARCHAR(255) NOT NULL Werkzeug生成的密码哈希
real_name VARCHAR(80) DEFAULT '' 真实姓名
phone VARCHAR(40) DEFAULT '' 联系电话
role VARCHAR(30) DEFAULT 'analyst' 角色:analyst(分析师) / admin(管理员)
last_login DATETIME NULL 最后登录时间
created_at DATETIME DEFAULT CURRENT_TIMESTAMP 创建时间
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE 更新时间

默认种子数据admin / admin123 / admin@example.com,角色为 admin

5.2.2 vending_sales 表 --- 销售记录
字段 类型 约束 说明
id BIGINT AUTO_INCREMENT, PK 记录ID
status VARCHAR(40) NOT NULL 交易状态(如 "Processed")
device_id VARCHAR(80) NOT NULL 设备编号(如 "VJ300320611")
location VARCHAR(120) NOT NULL 销售地点(如 "Brunswick Sq Mall")
machine VARCHAR(160) NOT NULL 机器名称(如 "BSQ Mall x1366 - ATT")
product VARCHAR(255) NOT NULL 商品名称
category VARCHAR(80) NOT NULL 商品品类(Food/Carbonated/Non Carbonated/Water)
transaction_id BIGINT NOT NULL 交易编号
trans_date DATE NOT NULL 交易日期
payment_type VARCHAR(40) NOT NULL 支付方式(Cash/Credit)
r_coil INT NOT NULL 实际货道编号
r_price DECIMAL(10,2) NOT NULL 实际售价(美元)
r_qty INT NOT NULL 实际数量
m_coil INT NOT NULL 主机货道编号
m_price DECIMAL(10,2) NULL 主机价格(可为空)
m_qty INT NOT NULL 主机数量
line_total DECIMAL(10,2) NOT NULL 行小计金额
trans_total DECIMAL(10,2) NOT NULL 交易总金额
prcd_date DATE NOT NULL 处理日期
created_at DATETIME DEFAULT CURRENT_TIMESTAMP 记录创建时间

索引

索引名 字段 用途
idx_sales_date trans_date 日期范围过滤、趋势分析
idx_sales_location location 地点筛选、地点维度聚合
idx_sales_machine machine 机器筛选、设备效率分析
idx_sales_category category 品类筛选、品类维度聚合
idx_sales_product product 商品筛选、商品排名
idx_sales_payment payment_type 支付方式筛选
idx_sales_transaction transaction_id 交易去重统计
5.2.3 import_logs 表 --- 导入日志
字段 类型 约束 说明
id INT AUTO_INCREMENT, PK 日志ID
file_name VARCHAR(255) NOT NULL 导入文件名
row_count INT NOT NULL 导入行数
imported_by VARCHAR(80) DEFAULT 'system' 导入操作者
imported_at DATETIME DEFAULT CURRENT_TIMESTAMP 导入时间

6. 后端设计

6.1 应用初始化 (app.py 第26-28行)

python 复制代码
app = Flask(__name__)
app.config.from_object(Config)

Flask应用从 config.Config 类加载配置,所有配置项均支持环境变量覆盖。

6.2 数据库连接管理

连接工厂 (database.py 第35-47行):

python 复制代码
def connect(use_database=True):
    kwargs = {
        "host": Config.DB_HOST,
        "port": Config.DB_PORT,
        "user": Config.DB_USER,
        "password": Config.DB_PASSWORD,
        "charset": Config.DB_CHARSET,
        "cursorclass": DictCursor,    # 返回字典而非元组
        "autocommit": False,           # 手动事务管理
    }
    if use_database:
        kwargs["database"] = Config.DB_NAME
    return pymysql.connect(**kwargs)

请求级连接 (app.py 第38-48行):

python 复制代码
def get_db():
    if "db" not in g:
        g.db = connect()
    return g.db

@app.teardown_appcontext
def close_db(error=None):
    conn = g.pop("db", None)
    if conn is not None:
        conn.close()

每个HTTP请求通过Flask的 g 对象获取一个数据库连接,请求结束后自动关闭,避免连接泄漏。

6.3 认证与授权

6.3.1 用户加载 (app.py 第104-116行)
python 复制代码
@app.before_request
def load_logged_in_user():
    user_id = session.get("user_id")
    g.user = None
    if user_id is not None:
        g.user = query_one(
            "SELECT id, username, email, real_name, phone, role, last_login, created_at "
            "FROM users WHERE id=%s", (user_id,))

每次请求前从 session 中读取 user_id,查询数据库加载用户信息到 g.user

6.3.2 登录验证装饰器 (app.py 第82-89行)
python 复制代码
def login_required(view):
    @wraps(view)
    def wrapped_view(*args, **kwargs):
        if g.user is None:
            return redirect(url_for("login", next=request.path))
        return view(*args, **kwargs)
    return wrapped_view
6.3.3 管理员验证装饰器 (app.py 第92-101行)
python 复制代码
def admin_required(view):
    @wraps(view)
    def wrapped_view(*args, **kwargs):
        if g.user is None:
            return redirect(url_for("login", next=request.path))
        if g.user.get("role") != "admin":
            return jsonify({"success": False, "message": "权限不足,仅管理员可操作。"}), 403
        return view(*args, **kwargs)
    return wrapped_view

6.4 统一过滤机制

6.4.1 过滤参数收集 (app.py 第124-129行)
python 复制代码
FILTER_MAP = {
    "location": "location",
    "machine": "machine",
    "category": "category",
    "payment_type": "payment_type",
}

def get_filter_values():
    values = {key: request.args.get(key, "").strip() for key in FILTER_MAP}
    values["date_from"] = request.args.get("date_from", "").strip()
    values["date_to"] = request.args.get("date_to", "").strip()
    values["search"] = request.args.get("search", "").strip()
    return values
6.4.2 动态WHERE构建 (app.py 第132-155行)
python 复制代码
def build_where(filters=None, include_search=False):
    filters = filters or get_filter_values()
    clauses = ["1=1"]
    params = []

    for arg_name, column_name in FILTER_MAP.items():
        value = filters.get(arg_name)
        if value:
            clauses.append(f"{column_name}=%s")
            params.append(value)

    if filters.get("date_from"):
        clauses.append("trans_date >= %s")
        params.append(filters["date_from"])
    if filters.get("date_to"):
        clauses.append("trans_date <= %s")
        params.append(filters["date_to"])

    if include_search and filters.get("search"):
        keyword = f"%{filters['search']}%"
        clauses.append("(product LIKE %s OR machine LIKE %s OR location LIKE %s OR category LIKE %s)")
        params.extend([keyword, keyword, keyword, keyword])

    return " WHERE " + " AND ".join(clauses), params

此函数是系统的核心过滤引擎,所有 22 个 API 端点均调用它来构建参数化的 SQL WHERE 子句,确保:

  • 支持按地点、机器、品类、支付方式精确过滤
  • 支持日期范围过滤(trans_date >= AND <=
  • 支持关键词模糊搜索(可选,仅交易明细使用)
  • 全部使用参数化查询,防止SQL注入

6.5 JSON序列化辅助

python 复制代码
def json_value(value):
    if isinstance(value, Decimal):
        return float(value)      # MySQL DECIMAL → Python float
    if isinstance(value, date):
        return value.isoformat() # Python date → "2025-01-15"
    return value

def json_rows(rows):
    return [{key: json_value(value) for key, value in row.items()} for row in rows]

6.6 错误处理

python 复制代码
@app.errorhandler(pymysql.MySQLError)
def handle_database_error(error):
    if request.path.startswith("/api/"):
        return jsonify({"success": False, "message": str(error)}), 500
    return render_template("db_error.html", error=error), 500

数据库异常统一捕获:API请求返回JSON错误,页面请求渲染错误模板。

6.7 页面路由一览

路由 方法 装饰器 模板 说明
/ GET --- --- 重定向到 dashboard 或 login
/login GET/POST --- login.html 登录(支持用户名或邮箱)
/register GET/POST --- register.html 用户注册
/logout GET @login_required --- 清除session,跳转登录
/dashboard GET @login_required dashboard.html 经营总览
/time-insights GET @login_required time_insights.html 时间洞察
/analysis GET @login_required analysis.html 深度分析
/product-strategy GET @login_required product_strategy.html 商品策略
/machine-portrait GET @login_required machine_portrait.html 设备画像
/operations GET @login_required operations.html 运营建议
/records GET @login_required records.html 交易明细
/records/export GET @login_required --- CSV导出
/profile GET/POST @login_required profile.html 个人中心
/admin/data GET @admin_required admin_data.html 数据管理

7. 前端设计

7.1 布局系统

7.1.1 认证页面布局 (auth_base.html)

采用左右分屏设计:

  • 左侧:品牌展示区,深色背景,显示系统名称、数据集统计(9,617条记录、5个地点、4个品类)
  • 右侧:表单区域,包含登录或注册表单
7.1.2 主应用布局 (base.html)
复制代码
┌──────────────────────────────────────────────────────┐
│  侧边栏 (260px固定)    │      主内容区 (可滚动)       │
│                        │  ┌────────────────────────┐ │
│  ┌──────────────────┐  │  │  顶栏:页面标题+用户菜单 │ │
│  │ 系统Logo/标题    │  │  ├────────────────────────┤ │
│  ├──────────────────┤  │  │                        │ │
│  │ 经营总览         │  │  │    页面内容区域         │ │
│  │ 时间洞察         │  │  │    (卡片+图表+表格)     │ │
│  │ 深度分析         │  │  │                        │ │
│  │ 商品策略         │  │  │                        │ │
│  │ 设备画像         │  │  │                        │ │
│  │ 运营建议         │  │  │                        │ │
│  │ 交易明细         │  │  │                        │ │
│  │ ────────────── │  │  │                        │ │
│  │ 个人中心         │  │  │                        │ │
│  │ 数据管理 (admin) │  │  │                        │ │
│  └──────────────────┘  │  └────────────────────────┘ │
└──────────────────────────────────────────────────────┘
  • 侧边栏:深海军蓝背景(#0f1f3d),260px固定宽度
  • 主内容区:可滚动,最大宽度自适应
  • 响应式:940px以下侧边栏收缩为图标网格,640px以下单列布局

7.2 CSS设计系统 (static/css/styles.css)

7.2.1 色彩方案
色彩角色 色值 用途
主色 (Primary) #1e40af 按钮、链接、活跃状态
强调色 (Accent) #f59e0b 高亮指标、重要标记
侧边栏背景 #0f1f3d 深海军蓝
成功色 绿色系 正增长、成功提示
危险色 玫红色系 负增长、警告提示
表面色 浅灰白 卡片背景、分割线
7.2.2 卡片系统
  • .metric-card:KPI指标卡片,带图标、数值、标签
  • .insight-card:洞察卡片,带标题、描述、徽章
  • .signal-card:信号卡片,用于设备画像
  • .panel:通用内容面板,带阴影和圆角
  • 所有卡片支持 hover 上浮效果(transform: translateY(-2px)
7.2.3 响应式断点
断点 布局变化
> 1180px 双列网格布局
940px - 1180px 侧边栏收缩为图标网格
640px - 940px 单列布局
< 640px 紧凑单列,缩小间距
7.2.4 无障碍支持
css 复制代码
@media (prefers-reduced-motion: reduce) {
    * { transition: none !important; animation: none !important; }
}

7.3 JavaScript架构 (static/js/dashboard.js)

7.3.1 启动流程
javascript 复制代码
document.addEventListener("DOMContentLoaded", boot);

async function boot() {
    const page = document.body.dataset.page;  // 从 <body data-page="xxx"> 读取
    const options = await fetchJson("/api/options");
    fillSelect("#filter-location", options.locations);
    fillSelect("#filter-machine", options.machines);
    // ... 填充所有过滤器下拉框

    const loaders = {
        dashboard: loadDashboard,
        time_insights: loadTimeInsights,
        analysis: loadAnalysis,
        product_strategy: loadProductStrategy,
        machine_portrait: loadMachinePortrait,
        operations: loadOperations,
        records: loadRecords,
        admin_data: loadAdminSales,
    };
    if (loaders[page]) loaders[page]();
}
7.3.2 API调用封装
javascript 复制代码
async function fetchJson(url) {
    const resp = await fetch(url);
    if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
    const json = await resp.json();
    if (!json.success) throw new Error(json.message || "请求失败");
    return json.data;
}
7.3.3 过滤器参数收集
javascript 复制代码
function paramsFromForm() {
    const params = new URLSearchParams();
    document.querySelectorAll(".filter-bar select, .filter-bar input").forEach(el => {
        if (el.value) params.set(el.name, el.value);
    });
    return params;
}
7.3.4 页面加载器并行策略

每个页面的加载函数使用 Promise.all() 并行请求多个API端点:

javascript 复制代码
async function loadDashboard() {
    const params = paramsFromForm();
    const [summary, trend, category, topProducts, machineSales, payment, locationCat] =
        await Promise.all([
            fetchJson(`/api/summary?${params}`),
            fetchJson(`/api/sales-trend?${params}`),
            fetchJson(`/api/category-share?${params}`),
            fetchJson(`/api/top-products?${params}`),
            fetchJson(`/api/machine-sales?${params}`),
            fetchJson(`/api/payment-mix?${params}`),
            fetchJson(`/api/location-category?${params}`),
        ]);
    renderKPICards(summary);
    renderTrendChart(trend);
    // ... 渲染所有图表
}
7.3.5 图表类型汇总
图表类型 ECharts图表 使用页面
折线+柱状组合图 type: 'line' + type: 'bar' 经营总览(销售趋势)
饼图/环形图 type: 'pie' 经营总览(品类占比)、经营总览(支付分布)
水平柱状图 type: 'bar' (横向) 经营总览(Top15商品)、深度分析(价格品类)
日历热力图 type: 'heatmap' + calendar 时间洞察
堆叠面积图 type: 'line' + stack + areaStyle 时间洞察(月度品类趋势)
树图 type: 'treemap' 商品策略(品类贡献)
散点图 type: 'scatter' 商品策略(SKU矩阵)、设备画像(效率象限)
堆叠柱状图 type: 'bar' + stack 商品策略(价格带)、设备画像(品类组合)
雷达图 type: 'radar' 运营建议(设备效率对比)
预测折线图 type: 'line' (历史+预测双系列) 运营建议(销售预测)

8. 功能模块详解

8.1 经营总览 (Dashboard)

页面文件templates/dashboard.html
加载函数loadDashboard()
调用API/api/summary, /api/sales-trend, /api/category-share, /api/top-products, /api/machine-sales, /api/payment-mix, /api/location-category

功能说明

组件 说明
KPI指标卡片 (x4) 总销售额、总交易笔数、总销量、机器/商品数量
销售趋势图 按月或按日的销售额折线+交易笔数柱状组合图
品类占比饼图 4个品类的销售额占比环形图
Top15商品柱状图 按销售额或销量排名的水平柱状图
机器销售排名 各机器的销售额排名柱状图
支付方式分布 Cash/Credit的交易笔数占比饼图
地点-品类热力图 地点×品类的销售额交叉热力矩阵

8.2 时间洞察 (Time Insights)

页面文件templates/time_insights.html
加载函数loadTimeInsights()
调用API/api/time-calendar, /api/weekday-performance, /api/month-category-trend, /api/growth-overview

功能说明

组件 说明
指标卡片 (x4) 活跃天数、峰值日、最佳星期、最佳增长月份
日历热力图 全年365天的每日销售额热力图,颜色深浅表示销售额高低
星期维度分析 周一至周日的平均日销售额对比柱状图
月度品类趋势 4个品类的月度销售额堆叠面积图
增长明细表 每月的销售额、销量、笔数、客单价、日均销售额、环比增长率

8.3 深度分析 (Analysis)

页面文件templates/analysis.html
加载函数loadAnalysis()
调用API/api/insights, /api/price-category, /api/location-products

功能说明

组件 说明
核心洞察卡片 (x4) 销售额最高机器、销量最高商品、销量最高地点、支付方式排名
价格-品类柱状图 Top20品类+价格组合的水平柱状图
地点畅销商品表 每个地点的最畅销商品、销售额、销量
分析发现 关键数据洞察总结

8.4 商品策略 (Product Strategy)

页面文件templates/product_strategy.html
加载函数loadProductStrategy()
调用API/api/category-share, /api/product-matrix, /api/category-price-bands, /api/top-products

功能说明

组件 说明
指标卡片 (x4) 明星SKU数量、Top商品、补货压力SKU、长尾SKU数量
品类贡献树图 按品类→商品层级展示销售额贡献的矩形树图
SKU四象限矩阵 以销售额为X轴、销量为Y轴的散点图,划分为四个象限
价格带堆叠柱状图 各品类在5个价格带(<1.50, 1.50-$2.49, ...)的销售额分布
策略表格 商品详情表,含SKU定位标签(明星/利润/走量/长尾)

SKU四象限分类逻辑

复制代码
                    高销售额
                       │
        利润SKU        │       明星SKU
     (高销低量)        │     (高销高量)
                       │
  ─────────────────────┼─────────────────── 高销量
                       │
        长尾观察        │       走量SKU
     (低销低量)        │     (低销高量)
                       │
                    低销售额

阈值:销售额和销量均取第70百分位数作为分界线

8.5 设备画像 (Machine Portrait)

页面文件templates/machine_portrait.html
加载函数loadMachinePortrait()
调用API/api/machine-efficiency, /api/machine-sales, /api/category-machine

功能说明

组件 说明
指标卡片 (x4) 机器总数、收入最高机器、日均表现最佳、低效预警数量
效率象限散点图 X轴=日均销售额,Y轴=SKU效率(销售额/SKU数),气泡大小=总销量
日均销售排名柱状图 各机器的日均销售额排名
品类组合堆叠柱状图 各机器的品类销售额占比堆叠图
设备画像详情表 每台机器的详细效率指标

8.6 运营建议 (Operations)

页面文件templates/operations.html
加载函数loadOperations()
调用API/api/forecast, /api/machine-efficiency, /api/category-machine, /api/product-abc, /api/replenishment

功能说明

组件 说明
预测英雄卡片 未来14天预测销售额、基准日均销售额
高优先级补货数 需要优先补货的商品数量
ABC覆盖率 A类商品数量及其销售额占比
预测折线图 历史60天实际销售额 + 7日移动平均 + 14天预测线
设备雷达图 多维度效率对比(日均销售额、SKU数、品类数、活跃天数、客单价)
品类-设备堆叠图 各机器的品类组合销售额
ABC分类表 商品ABC分级(A=累计70%、B=累计90%、C=其余)
补货优先级表 Top30补货候选商品,含优先级标签和建议操作

预测算法 (/api/forecast):

python 复制代码
# 1. 取最近14天的日均销售额作为基准
recent = data[-14:]
baseline = sum(item["sales"] for item in recent) / len(recent)

# 2. 对未来每一天应用周期调整
for offset in range(1, days + 1):
    weekly_adjustment = 1 + (((offset - 1) % 7) - 3) * 0.015
    forecast_sales = baseline * weekly_adjustment

补货优先级规则 (/api/replenishment):

优先级 条件 标签颜色 建议操作
总销量 >= 100 或 日均销量 >= 1.2 红色 (danger) 优先补货
总销量 >= 45 或 日均销量 >= 0.55 黄色 (warning) 稳定补货
其他 灰色 (secondary) 观察陈列

8.7 交易明细 (Records)

页面文件templates/records.html
加载函数loadRecords()
调用API/api/records, /records/export

功能说明

  • 分页表格展示所有交易记录(默认每页20条)
  • 支持按地点、机器、品类、支付方式、日期范围过滤
  • 支持关键词搜索(商品名、机器名、地点名、品类名)
  • 支持CSV导出(UTF-8 BOM编码,兼容Excel中文)

8.8 个人中心 (Profile)

页面文件templates/profile.html
路由处理/profile (GET/POST)

功能说明

  • 查看/编辑个人资料(真实姓名、电话、邮箱)
  • 修改密码(需验证原密码,新密码至少6位)
  • 邮箱唯一性校验

8.9 数据管理 (Admin Data)

页面文件templates/admin_data.html
加载函数loadAdminSales()
权限要求 :仅 admin 角色

功能说明

  • 分页表格展示所有销售记录(含全部18个字段)
  • 弹窗表单新增记录
  • 弹窗表单编辑记录
  • 确认后删除记录

9. API接口文档

9.1 通用说明

  • 基础路径 :所有API以 /api/ 开头
  • 认证:所有API需要登录(session cookie)
  • 响应格式
json 复制代码
{
    "success": true,
    "data": { ... }
}

错误响应:

json 复制代码
{
    "success": false,
    "message": "错误描述"
}
  • 过滤参数(所有分析类API通用):
参数 类型 说明
location string 地点精确匹配
machine string 机器精确匹配
category string 品类精确匹配
payment_type string 支付方式精确匹配
date_from string 起始日期 (YYYY-MM-DD)
date_to string 结束日期 (YYYY-MM-DD)

9.2 接口列表

GET /api/options --- 获取过滤器选项

说明:返回所有过滤器下拉框的可选值。

响应

json 复制代码
{
    "success": true,
    "data": {
        "locations": ["Brunswick Sq Mall", ...],
        "machines": ["BSQ Mall x1366 - ATT", ...],
        "categories": ["Carbonated", "Food", "Non Carbonated", "Water"],
        "payments": ["Cash", "Credit"],
        "dates": { "min_date": "2025-01-01", "max_date": "2025-12-31" }
    }
}
GET /api/summary --- 经营汇总KPI

响应

json 复制代码
{
    "success": true,
    "data": {
        "row_count": 9617,
        "transaction_count": 8500,
        "product_count": 120,
        "machine_count": 5,
        "sales_total": 28500.00,
        "quantity_total": 9617,
        "avg_line_total": 2.96,
        "min_date": "2025-01-01",
        "max_date": "2025-12-31"
    }
}
GET /api/sales-trend --- 销售趋势

参数

参数 默认值 说明
granularity month month 按月 / day 按日

响应

json 复制代码
{
    "success": true,
    "data": [
        { "period": "2025-01", "sales": 2500.00, "quantity": 850, "transactions": 720 },
        ...
    ]
}
GET /api/time-calendar --- 日历热力图数据

响应

json 复制代码
{
    "success": true,
    "data": [
        {
            "date": "2025-01-01",
            "week_index": 1,
            "weekday": 2,
            "sales": 150.50,
            "quantity": 52,
            "transactions": 45
        },
        ...
    ]
}
GET /api/weekday-performance --- 星期维度表现

响应

json 复制代码
{
    "success": true,
    "data": [
        {
            "weekday": 0,
            "sales": 3500.00,
            "quantity": 1200,
            "transactions": 1000,
            "active_days": 52,
            "avg_line_total": 2.92,
            "daily_sales": 67.31,
            "daily_quantity": 23.08
        },
        ...
    ]
}

weekday 值:0=周一, 1=周二, ..., 6=周日

GET /api/month-category-trend --- 月度品类趋势

响应

json 复制代码
{
    "success": true,
    "data": [
        { "period": "2025-01", "category": "Carbonated", "sales": 800.00, "quantity": 280 },
        { "period": "2025-01", "category": "Food", "sales": 600.00, "quantity": 200 },
        ...
    ]
}
GET /api/growth-overview --- 月度增长概览

响应

json 复制代码
{
    "success": true,
    "data": [
        {
            "period": "2025-01",
            "sales": 2500.00,
            "quantity": 850,
            "transactions": 720,
            "active_days": 31,
            "avg_ticket": 3.47,
            "daily_sales": 80.65,
            "mom_rate": null
        },
        {
            "period": "2025-02",
            "sales": 2800.00,
            "mom_rate": 12.00
        },
        ...
    ]
}

mom_rate:环比增长率(%),第一个月为 null

GET /api/forecast --- 销售预测

参数

参数 默认值 范围 说明
days 14 7-45 预测天数

响应

json 复制代码
{
    "success": true,
    "data": {
        "history": [
            { "date": "2025-11-01", "sales": 100.00, "quantity": 35, "moving_avg": 95.50 },
            ...
        ],
        "forecast": [
            { "date": "2025-12-18", "sales": 98.50, "quantity": 34 },
            ...
        ],
        "baseline": 97.50,
        "projected_sales": 1379.00
    }
}
GET /api/category-share --- 品类占比

响应

json 复制代码
{
    "success": true,
    "data": [
        { "name": "Carbonated", "sales": 8500.00, "quantity": 2800, "row_count": 2800 },
        ...
    ]
}
GET /api/machine-efficiency --- 设备效率

响应

json 复制代码
{
    "success": true,
    "data": [
        {
            "location": "Brunswick Sq Mall",
            "machine": "BSQ Mall x1366 - ATT",
            "sales": 6500.00,
            "quantity": 2200,
            "row_count": 2200,
            "transactions": 1900,
            "active_days": 300,
            "product_count": 45,
            "category_count": 4,
            "avg_line_total": 2.95,
            "daily_sales": 21.67,
            "daily_quantity": 7.33,
            "sales_per_sku": 144.44
        },
        ...
    ]
}
GET /api/category-machine --- 品类×设备交叉

响应

json 复制代码
{
    "success": true,
    "data": [
        { "machine": "BSQ Mall x1366 - ATT", "category": "Carbonated", "sales": 2000.00, "quantity": 700 },
        ...
    ]
}
GET /api/replenishment --- 补货建议

响应

json 复制代码
{
    "success": true,
    "data": [
        {
            "location": "Brunswick Sq Mall",
            "machine": "BSQ Mall x1366 - ATT",
            "product": "Red Bull - Energy Drink",
            "category": "Carbonated",
            "quantity": 150,
            "sales": 525.00,
            "active_days": 120,
            "transactions": 140,
            "avg_price": 3.50,
            "daily_quantity": 1.25,
            "priority": "高",
            "action": "优先补货",
            "badge": "danger"
        },
        ...
    ]
}
GET /api/product-abc --- ABC分类

响应

json 复制代码
{
    "success": true,
    "data": [
        {
            "product": "Red Bull - Energy Drink",
            "category": "Carbonated",
            "sales": 1500.00,
            "quantity": 430,
            "grade": "A",
            "cumulative_ratio": 5.26,
            "sales_ratio": 5.26
        },
        ...
    ]
}

分类规则:A类=累计占比≤70%,B类=累计占比≤90%,C类=其余。

GET /api/product-matrix --- SKU矩阵

响应

json 复制代码
{
    "success": true,
    "data": [
        {
            "product": "Red Bull - Energy Drink",
            "category": "Carbonated",
            "sales": 1500.00,
            "quantity": 430,
            "transactions": 400,
            "active_days": 200,
            "machine_count": 3,
            "avg_price": 3.50,
            "daily_quantity": 2.15,
            "sales_per_machine": 500.00,
            "position": "明星 SKU",
            "badge": "primary"
        },
        ...
    ]
}

position 值:明星 SKU / 利润 SKU / 走量 SKU / 长尾观察

GET /api/category-price-bands --- 品类价格带

响应

json 复制代码
{
    "success": true,
    "data": [
        {
            "category": "Carbonated",
            "price_band": "$2.50-$3.49",
            "sort_order": 3,
            "sales": 3000.00,
            "quantity": 1000,
            "product_count": 15
        },
        ...
    ]
}

价格带定义:< $1.50, $1.50-$2.49, $2.50-$3.49, $3.50-$4.49, >= $4.50

GET /api/top-products --- Top商品

参数

参数 默认值 说明
metric sales sales 按销售额排序 / quantity 按销量排序

响应

json 复制代码
{
    "success": true,
    "data": [
        { "product": "...", "category": "...", "sales": 1500.00, "quantity": 430, "transactions": 400 },
        ...
    ]
}

返回前15条。

GET /api/machine-sales --- 机器销售排名

响应

json 复制代码
{
    "success": true,
    "data": [
        {
            "location": "Brunswick Sq Mall",
            "machine": "BSQ Mall x1366 - ATT",
            "sales": 6500.00,
            "quantity": 2200,
            "transactions": 1900,
            "avg_line_total": 2.95
        },
        ...
    ]
}
GET /api/payment-mix --- 支付方式分布

响应

json 复制代码
{
    "success": true,
    "data": [
        { "payment_type": "Credit", "sales": 18000.00, "quantity": 6000, "row_count": 6000, "transactions": 5200 },
        { "payment_type": "Cash", "sales": 10500.00, "quantity": 3617, "row_count": 3617, "transactions": 3300 }
    ]
}
GET /api/location-category --- 地点×品类交叉

响应

json 复制代码
{
    "success": true,
    "data": [
        { "location": "Brunswick Sq Mall", "category": "Carbonated", "sales": 2000.00, "quantity": 700 },
        ...
    ]
}
GET /api/price-category --- 价格×品类Top20

响应

json 复制代码
{
    "success": true,
    "data": [
        { "category": "Carbonated", "price": 3.50, "label": "Carbonated $3.50", "sales": 1500.00, "quantity": 430 },
        ...
    ]
}
GET /api/location-products --- 地点畅销商品

响应

json 复制代码
{
    "success": true,
    "data": [
        { "location": "Brunswick Sq Mall", "product": "Red Bull", "sales": 500.00, "quantity": 143 },
        ...
    ]
}

每个地点返回销量最高的一个商品。

GET /api/insights --- 核心洞察

响应

json 复制代码
{
    "success": true,
    "data": {
        "top_machine": { "machine": "...", "location": "...", "sales": 6500.00, "quantity": 2200 },
        "top_product": { "product": "...", "category": "...", "sales": 1500.00, "quantity": 430 },
        "top_location": { "location": "...", "sales": 8000.00, "quantity": 2800 },
        "payment_rank": [
            { "payment_type": "Credit", "row_count": 6000 },
            { "payment_type": "Cash", "row_count": 3617 }
        ]
    }
}
GET /api/records --- 交易记录分页

额外参数

参数 默认值 说明
page 1 页码
size 20 每页条数 (5-100)
search --- 关键词搜索

响应

json 复制代码
{
    "success": true,
    "data": [
        {
            "id": 1,
            "trans_date": "2025-01-01",
            "location": "...",
            "machine": "...",
            "product": "...",
            "category": "...",
            "payment_type": "Credit",
            "r_price": 3.50,
            "r_qty": 1,
            "line_total": 3.50,
            "trans_total": 3.50,
            "transaction_id": 14515778905
        },
        ...
    ],
    "page": 1,
    "size": 20,
    "total": 9617
}
GET /records/export --- CSV导出

说明:导出当前过滤条件下的所有交易记录为CSV文件。

响应Content-Type: text/csv; charset=utf-8,文件名 vending_sales_export.csv,UTF-8 BOM编码。

GET /api/admin/sales --- 管理员记录列表

权限 :仅 admin 角色

参数 :同 /api/records,额外返回全部18个字段。

POST /api/admin/sales --- 新增记录

权限 :仅 admin 角色

请求体 (JSON):

json 复制代码
{
    "status": "Processed",
    "device_id": "VJ300320611",
    "location": "Brunswick Sq Mall",
    "machine": "BSQ Mall x1366 - ATT",
    "product": "Red Bull - Energy Drink",
    "category": "Carbonated",
    "transaction_id": 14515778905,
    "trans_date": "2025-01-01",
    "payment_type": "Credit",
    "r_coil": 148,
    "r_price": 3.50,
    "r_qty": 1,
    "m_coil": 148,
    "m_price": 3.50,
    "m_qty": 1,
    "line_total": 3.50,
    "trans_total": 3.50,
    "prcd_date": "2025-01-01"
}
GET /api/admin/sales/{id} --- 获取单条记录

权限 :仅 admin 角色

PUT /api/admin/sales/{id} --- 更新记录

权限 :仅 admin 角色,请求体同新增。

DELETE /api/admin/sales/{id} --- 删除记录

权限 :仅 admin 角色


10. 数据处理流程

10.1 CSV导入流程

复制代码
vending_machine_sales.csv
    │
    ▼
import_sales_csv() [database.py]
    │
    ├─ 1. init_schema() --- 确保数据库和表存在
    │
    ├─ 2. TRUNCATE TABLE vending_sales --- 清空旧数据
    │
    ├─ 3. 逐行读取CSV (UTF-8-BOM编码)
    │     │
    │     ▼
    │   _row_to_tuple() --- 字段映射与类型转换
    │     ├─ 文本字段:_clean_text() 去除空白
    │     ├─ 日期字段:_parse_date() MM/DD/YYYY → date对象,年份替换为 DATA_DISPLAY_YEAR
    │     ├─ 金额字段:_parse_decimal() 字符串 → Decimal
    │     └─ 整数字段:_parse_int() 字符串 → int
    │
    ├─ 4. 批量插入 (每500条一批)
    │     cursor.executemany(insert_sql, batch)
    │
    ├─ 5. 记录导入日志到 import_logs 表
    │
    └─ 6. conn.commit() 提交事务

10.2 日期归一化处理

原始CSV中的日期可能是任意年份,系统通过 _parse_date() 函数将所有日期的年份统一替换为 DATA_DISPLAY_YEAR(默认2025):

python 复制代码
def _parse_date(value):
    parsed = datetime.strptime(value.strip(), "%m/%d/%Y").date()
    try:
        return parsed.replace(year=Config.DATA_DISPLAY_YEAR)
    except ValueError:
        # 处理2月29日等闰年边界情况
        return parsed.replace(year=Config.DATA_DISPLAY_YEAR, day=28)

10.3 工具脚本

scripts/setup_database.py --- 一键初始化
bash 复制代码
python scripts/setup_database.py

执行流程:

  1. 创建数据库(如不存在)
  2. 创建三张表(users, vending_sales, import_logs)
  3. 插入默认管理员账户
  4. 导入CSV数据到 vending_sales 表
scripts/convert_sales_year.py --- CSV日期年份转换
bash 复制代码
python scripts/convert_sales_year.py 2024

直接修改CSV文件中的日期年份,用于将数据集调整到不同年份展示。

scripts/shift_database_year.py --- 数据库日期年份迁移
bash 复制代码
python scripts/shift_database_year.py 2024

直接在数据库中更新已导入记录的日期年份,无需重新导入CSV。


11. 部署与运行

11.1 环境要求

组件 要求
Python 3.10 或更高版本
MySQL 5.7 或更高版本
pip 最新版本

11.2 安装步骤

步骤一:克隆/下载项目
bash 复制代码
cd "F:\code\131-基于Flask的美国新泽西州自动售货机销售数据可视化分析系统\America"
步骤二:安装Python依赖
bash 复制代码
pip install -r requirements.txt
步骤三:配置MySQL

确保MySQL服务已启动,默认配置为:

  • 主机:localhost
  • 端口:3306
  • 用户:root
  • 密码:123456

如需修改,设置环境变量或编辑 config.py

步骤四:初始化数据库
bash 复制代码
python scripts/setup_database.py

此命令会自动创建数据库、建表、插入管理员账户、导入CSV数据。

步骤五:启动应用
bash 复制代码
python app.py

应用将在 http://127.0.0.1:5000 启动(Flask开发服务器,debug模式)。

步骤六:访问系统
  1. 打开浏览器访问 http://127.0.0.1:5000
  2. 使用默认管理员账户登录:
    • 用户名:admin
    • 密码:admin123
  3. 也可注册新账户(默认角色为 analyst

11.3 生产环境部署建议

当前系统使用Flask内置开发服务器,生产环境建议:

  1. WSGI服务器:使用 Gunicorn 或 uWSGI 替代 Flask 内置服务器

    bash 复制代码
    pip install gunicorn
    gunicorn -w 4 -b 0.0.0.0:5000 app:app
  2. 反向代理:使用 Nginx 作为反向代理,处理静态文件和SSL

  3. 密钥安全 :通过环境变量设置 SECRET_KEY,不要使用默认值

  4. 数据库安全:修改默认MySQL密码,限制访问权限


12. 配置说明

12.1 配置项一览 (config.py)

配置项 环境变量 默认值 说明
SECRET_KEY SECRET_KEY design-131-sell-dev-secret Flask session密钥
DB_HOST DB_HOST localhost MySQL主机地址
DB_PORT DB_PORT 3306 MySQL端口
DB_USER DB_USER root MySQL用户名
DB_PASSWORD DB_PASSWORD 123456 MySQL密码
DB_NAME DB_NAME design_131_sell 数据库名
DB_CHARSET --- utf8mb4 数据库字符集
CSV_PATH CSV_PATH 项目目录/vending_machine_sales.csv CSV文件路径
DATA_DISPLAY_YEAR DATA_DISPLAY_YEAR 2025 数据展示年份
RECORD_PAGE_SIZE RECORD_PAGE_SIZE 20 交易记录分页大小

12.2 环境变量配置示例

bash 复制代码
# Windows PowerShell
$env:SECRET_KEY = "my-production-secret-key"
$env:DB_PASSWORD = "strong-password"
$env:DB_NAME = "vending_analytics"

# Linux/macOS
export SECRET_KEY="my-production-secret-key"
export DB_PASSWORD="strong-password"
export DB_NAME="vending_analytics"

13. 安全设计

13.1 认证安全

措施 实现
密码存储 Werkzeug generate_password_hash() --- PBKDF2-SHA256 + 随机盐
密码验证 Werkzeug check_password_hash() --- 时序安全比较
会话管理 Flask session(服务端签名的cookie)
密码策略 最少6位,注册和修改时强制校验

13.2 授权安全

措施 实现
路由保护 @login_required 装饰器,未登录重定向到登录页
角色控制 @admin_required 装饰器,非管理员返回403
页面级控制 侧边栏管理员入口仅对 admin 角色可见

13.3 数据安全

措施 实现
SQL注入防护 全部使用参数化查询(%s 占位符),无字符串拼接SQL
XSS防护 Jinja2模板默认自动转义HTML
CSRF Flask session cookie 的 SameSite 属性(未显式设置CSRF token)

13.4 当前安全局限

问题 说明
无CSRF Token 表单提交缺少CSRF保护,存在跨站请求伪造风险
无登录限流 无登录失败次数限制,存在暴力破解风险
无HTTPS 开发环境未配置SSL/TLS
默认密钥 SECRET_KEY 使用硬编码默认值,生产环境必须修改
无审计日志 除导入日志外,无用户操作审计

14. 已知问题与改进方向

14.1 已知问题

编号 问题 说明
1 pandas依赖冗余 requirements.txt 中声明了 pandas>=2.2,但应用代码未引用
2 单文件架构 app.py 1,167行,dashboard.js 1,333行,可维护性随功能增长下降
3 无前端构建工具 CSS/JS无压缩、无Source Map、无模块化
4 预测算法简单 基于移动平均+周期调整,未考虑季节性、趋势、异常值
5 无数据校验 API端点对输入数据的校验不够严格
6 连接池缺失 每次请求新建数据库连接,高并发下性能瓶颈

14.2 改进方向

方向 建议
架构重构 拆分Flask蓝图(Blueprint),按功能模块组织路由
前端工程化 引入Vite/Webpack打包,使用Vue/React重构前端
数据库优化 引入连接池(SQLAlchemy + Pool),优化慢查询
认证增强 添加CSRF Token、登录限流、JWT token支持
预测模型 使用Prophet或ARIMA等时间序列模型替代简单移动平均
测试覆盖 添加单元测试(pytest)和API集成测试
部署优化 Docker容器化部署,CI/CD流水线
数据源扩展 支持实时数据接入、多数据源合并

附录A:CSV数据字段映射

CSV列名 数据库字段 类型转换 说明
Status status _clean_text() 交易状态
Device ID device_id _clean_text() 设备编号
Location location _clean_text() 销售地点
Machine machine _clean_text() 机器名称
Product product _clean_text() 商品名称
Category category _clean_text() 商品品类
Transaction transaction_id _parse_int() 交易编号
TransDate trans_date _parse_date() + 年份替换 交易日期
Type payment_type _clean_text() 支付方式
RCoil r_coil _parse_int() 实际货道
RPrice r_price _parse_decimal() 实际售价
RQty r_qty _parse_int() 实际数量
MCoil m_coil _parse_int() 主机货道
MPrice m_price _parse_decimal() 主机价格
MQty m_qty _parse_int() 主机数量
LineTotal line_total _parse_decimal() 行小计
TransTotal trans_total _parse_decimal() 交易总额
Prcd Date prcd_date _parse_date() + 年份替换 处理日期

附录B:前端页面与API对应关系

页面 data-page 调用的API端点
经营总览 dashboard /api/options, /api/summary, /api/sales-trend, /api/category-share, /api/top-products, /api/machine-sales, /api/payment-mix, /api/location-category
时间洞察 time_insights /api/options, /api/time-calendar, /api/weekday-performance, /api/month-category-trend, /api/growth-overview
深度分析 analysis /api/options, /api/insights, /api/price-category, /api/location-products
商品策略 product_strategy /api/options, /api/category-share, /api/product-matrix, /api/category-price-bands, /api/top-products
设备画像 machine_portrait /api/options, /api/machine-efficiency, /api/machine-sales, /api/category-machine
运营建议 operations /api/options, /api/forecast, /api/machine-efficiency, /api/category-machine, /api/product-abc, /api/replenishment
交易明细 records /api/options, /api/records
数据管理 admin_data /api/options, /api/admin/sales

附录C:ECharts配置参考

系统中所有图表均使用 ECharts 5.5.1,以下为核心配置模式:

javascript 复制代码
// 通用图表初始化模式
const chart = echarts.init(document.getElementById("chart-dom"));
chart.setOption({
    title: { text: "图表标题", left: "center" },
    tooltip: { trigger: "axis" },
    legend: { bottom: 0 },
    xAxis: { type: "category", data: [...] },
    yAxis: { type: "value" },
    series: [{ type: "bar", data: [...] }]
});

// 窗口自适应
window.addEventListener("resize", () => chart.resize());

文档版本:1.0

最后更新:2025-05-20

项目版本:基于Flask的美国新泽西州自动售货机销售数据可视化分析系统

相关推荐
努力努力再努力wz1 小时前
【QT入门系列】QWidget 六大常用属性详解:windowOpacity、cursor、font、focus、toolTip 与 styleSheet
android·开发语言·数据结构·c++·qt·mysql·算法
子榆.1 小时前
CANN PyTorch适配器深度拆解:从.cuda()到.npu()到底发生了什么
人工智能·pytorch·python
chushiyunen1 小时前
python使用笔记(linux环境)
linux·笔记·python
神仙别闹1 小时前
基于MFC(C++)实现(界面)学委作业管理系统
开发语言·c++·mfc
三品吉他手会点灯1 小时前
C语言学习笔记 - 41.数据类型 - scanf函数核心知识点复习
c语言·开发语言·笔记·学习
撩得Android一次心动1 小时前
C语言基础笔记3【个人用】
android·c语言·开发语言·笔记
谢白羽1 小时前
Voicebox 深度指南:开源本地 AI 语音工作室完整评测与上手教程
人工智能·python·开源·tts·voicebox
薇茗1 小时前
【初阶数据结构】 升沉有序的平仄 排序 3
c语言·开发语言·数据结构·算法·排序算法·文件归并排序
2401_868534781 小时前
论快速应用开发方法及应用
大数据·python