骑行装备销售订单数据可视化分析系统 — 技术文档

1. 项目概述

1.1 项目简介

本系统是一个基于 Flask 框架的骑行装备销售订单数据可视化分析平台(Ride BI),提供多维度销售数据分析、交互式图表展示、用户权限管理等功能。系统从 CSV 数据文件导入订单数据到 MySQL 数据库,通过 RESTful API 提供数据查询,前端使用 ECharts 渲染各类可视化图表。

1.2 技术栈

层级技术
后端框架Flask 3.x(Python)
数据库MySQL(通过 PyMySQL 驱动)
前端渲染Jinja2 模板 + 原生 JavaScript
图表库ECharts 5.5.1
UI 框架Bootstrap 5.3.3
图标库Lucide Icons
密码加密werkzeug(PBKDF2)
会话管理Flask Session(服务端)

1.3 系统特点

  • 零前端框架依赖:纯原生 JavaScript 实现,无 React/Vue/Angular,加载快、兼容性好
  • 角色权限分离:管理员与普通用户功能严格隔离
  • 全量筛选联动:所有图表支持日期、省份、产品、销售员四维筛选
  • 操作审计:所有数据变更自动记录操作日志
  • 响应式布局:CSS Grid 自适应桌面和平板设备

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2. 项目结构

ride/
├── app.py                      # 主应用文件(Flask 工厂函数 + 53 个路由)
├── config.py                   # 配置文件(数据库、密钥、分页参数)
├── db.py                       # 数据库层(连接管理、DDL、CRUD 辅助函数)
├── auth.py                     # 认证工具(密码哈希、用户查询、操作日志)
├── decorators.py               # 装饰器(@login_required, @admin_required)
├── data_utils.py               # 数据工具(筛选构建、校验、JSON 序列化)
├── importer.py                 # CSV 数据导入器
├── requirements.txt            # Python 依赖
├── 骑行装备销售订单数据.csv     # 原始数据文件(78,262 行)
│
├── blueprints/
│   ├── __init__.py
│   └── auth_bp.py              # 认证蓝图(登录、注册、个人中心)
│
├── scripts/
│   └── init_db.py              # 数据库初始化脚本
│
├── static/
│   ├── css/
│   │   └── app.css             # 全局样式(22KB)
│   └── js/
│       ├── common.js           # 公共工具库(RideBI 对象)
│       ├── dashboard.js        # 经营总览图表
│       ├── region.js           # 区域分析图表
│       ├── product.js          # 产品结构图表
│       ├── salesperson.js      # 销售员表现图表
│       ├── customer.js         # 客户价值图表
│       ├── delivery.js         # 履约时效图表
│       ├── manage.js           # 数据管理(订单 CRUD)
│       └── admin.js            # 管理员用户管理
│
└── templates/
    ├── base.html               # 基础布局模板
    ├── dashboard.html          # 经营总览
    ├── region.html             # 区域分析
    ├── product.html            # 产品结构
    ├── salesperson.html        # 销售员表现
    ├── customer.html           # 客户价值
    ├── delivery.html           # 履约时效
    ├── manage.html             # 数据管理
    ├── bookmarks.html          # 我的收藏
    ├── announcements.html      # 系统公告
    ├── auth/
    │   ├── login.html          # 登录页
    │   ├── register.html       # 注册页
    │   └── profile.html        # 个人中心
    └── admin/
        ├── users.html          # 用户管理
        ├── logs.html           # 操作日志
        └── announcements.html  # 公告管理

3. 数据库设计

3.1 连接配置

参数
主机localhost
端口3306
用户root
密码123456
数据库design_141_ride
字符集utf8mb4
排序规则utf8mb4_unicode_ci

3.2 数据表概览

系统共 7 张数据表:

表名用途数据量
order_items订单明细(核心业务表)78,262 行
users用户账号系统生成
operation_logs操作审计日志系统生成
bookmarks用户收藏用户创建
announcements系统公告管理员创建
favorites图表收藏用户创建
alerts预警阈值管理员配置

3.3 表结构详情

3.3.1 order_items(订单明细表)
CREATE TABLE IF NOT EXISTS order_items (
    id              BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
    order_id        VARCHAR(32) NOT NULL COMMENT '订单编号',
    customer_name   VARCHAR(160) NOT NULL COMMENT '客户名称',
    customer_id     VARCHAR(40) NOT NULL COMMENT '客户编号',
    province        VARCHAR(32) NOT NULL COMMENT '省份',
    salesperson_id  INT NOT NULL COMMENT '销售员编号',
    order_date      DATE NOT NULL COMMENT '订单日期',
    est_delivery    DATE NOT NULL COMMENT '预计送达日期',
    act_delivery_date DATE NOT NULL COMMENT '实际送达日期',
    product_id      INT NOT NULL COMMENT '产品编号',
    product_name    VARCHAR(120) NOT NULL COMMENT '产品名称',
    quantity        INT NOT NULL COMMENT '数量',
    price           DECIMAL(14,4) NOT NULL COMMENT '单价',
    amount          DECIMAL(16,4) NOT NULL COMMENT '金额',
    created_at      TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at      TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (id),
    KEY idx_order_date (order_date),
    KEY idx_order_id (order_id),
    KEY idx_customer_id (customer_id),
    KEY idx_province (province),
    KEY idx_product_name (product_name),
    KEY idx_salesperson (salesperson_id),
    KEY idx_amount (amount)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

字段说明:

字段类型说明
idBIGINT自增主键
order_idVARCHAR(32)订单编号,如 ORD-00001
customer_nameVARCHAR(160)客户全称
customer_idVARCHAR(40)客户编号,如 CUS-001
provinceVARCHAR(32)省份名称
salesperson_idINT销售员编号
order_dateDATE下单日期(2024-01-01 至 2025-12-31)
est_deliveryDATE预计送达日期
act_delivery_dateDATE实际送达日期
product_idINT产品编号
product_nameVARCHAR(120)产品名称
quantityINT购买数量
priceDECIMAL(14,4)单价(元)
amountDECIMAL(16,4)金额 = 数量 × 单价
3.3.2 users(用户表)
CREATE TABLE IF NOT EXISTS users (
    id              BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
    username        VARCHAR(64) NOT NULL,
    password_hash   VARCHAR(256) NOT NULL,
    nickname        VARCHAR(64) NOT NULL DEFAULT '',
    email           VARCHAR(120) DEFAULT NULL,
    phone           VARCHAR(20) DEFAULT NULL,
    role            ENUM('admin', 'user') NOT NULL DEFAULT 'user',
    status          TINYINT NOT NULL DEFAULT 1 COMMENT '1=active 0=disabled',
    last_login_at   DATETIME DEFAULT NULL,
    created_at      TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at      TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (id),
    UNIQUE KEY uk_username (username)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
3.3.3 operation_logs(操作日志表)
CREATE TABLE IF NOT EXISTS operation_logs (
    id          BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
    user_id     BIGINT UNSIGNED NOT NULL,
    username    VARCHAR(64) NOT NULL,
    action      VARCHAR(32) NOT NULL COMMENT 'login/logout/create/update/delete/export',
    target_type VARCHAR(32) DEFAULT NULL COMMENT 'order/user/announcement/bookmark',
    target_id   VARCHAR(32) DEFAULT NULL,
    detail      TEXT DEFAULT NULL,
    ip          VARCHAR(45) DEFAULT NULL,
    created_at  TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (id),
    KEY idx_user_id (user_id),
    KEY idx_action (action),
    KEY idx_created_at (created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
3.3.4 bookmarks(收藏表)
CREATE TABLE IF NOT EXISTS bookmarks (
    id              BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
    user_id         BIGINT UNSIGNED NOT NULL,
    title           VARCHAR(200) NOT NULL,
    bookmark_type   VARCHAR(20) NOT NULL DEFAULT 'page' COMMENT 'page/chart/report',
    target_url      VARCHAR(500) NOT NULL,
    description     TEXT DEFAULT NULL,
    sort_order      INT NOT NULL DEFAULT 0,
    created_at      TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at      TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (id),
    KEY idx_user_id (user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
3.3.5 announcements(公告表)
CREATE TABLE IF NOT EXISTS announcements (
    id          BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
    title       VARCHAR(200) NOT NULL,
    content     TEXT NOT NULL,
    author_id   BIGINT UNSIGNED NOT NULL,
    status      TINYINT NOT NULL DEFAULT 1 COMMENT '1=published 0=draft',
    pinned      TINYINT NOT NULL DEFAULT 0,
    view_count  INT NOT NULL DEFAULT 0,
    created_at  TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at  TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (id),
    KEY idx_status (status),
    KEY idx_pinned (pinned),
    KEY idx_created_at (created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
3.3.6 favorites(图表收藏表)
CREATE TABLE IF NOT EXISTS favorites (
    id              BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
    user_id         BIGINT UNSIGNED NOT NULL,
    target_type     VARCHAR(32) NOT NULL COMMENT 'chart/report',
    target_key      VARCHAR(128) NOT NULL,
    filter_snapshot TEXT DEFAULT NULL,
    created_at      TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (id),
    UNIQUE KEY uk_user_target (user_id, target_type, target_key)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
3.3.7 alerts(预警表)
CREATE TABLE IF NOT EXISTS alerts (
    id              BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
    alert_type      VARCHAR(32) NOT NULL COMMENT 'delivery_delay/sales_drop',
    metric_name     VARCHAR(64) NOT NULL,
    threshold_value DECIMAL(14,4) NOT NULL,
    threshold_unit  VARCHAR(16) DEFAULT NULL COMMENT 'days/percent/yuan',
    current_value   DECIMAL(14,4) DEFAULT NULL,
    status          ENUM('normal','warning','critical') NOT NULL DEFAULT 'normal',
    province        VARCHAR(32) DEFAULT NULL,
    last_checked_at DATETIME DEFAULT NULL,
    created_at      TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

3.4 数据导入

数据通过 importer.py 从 CSV 文件批量导入:

from importer import import_csv
import_csv(csv_path="骑行装备销售订单数据.csv", reset=True, batch_size=1000)
  • 编码:utf-8-sig(处理 BOM 头)
  • 批量大小:1000 行/批次
  • 使用 executemany 提高插入效率
  • reset=True 会先清空 order_items 表再导入

4. 后端架构

4.1 应用工厂模式

app.py 使用 create_app() 工厂函数创建 Flask 应用:

def create_app():
    app = Flask(__name__)
    app.config.from_object(Config)
    
    # 注册蓝图
    from blueprints.auth_bp import auth_bp
    app.register_blueprint(auth_bp, url_prefix="/auth")
    
    # 初始化数据库
    init_database()
    seed_admin()
    
    # 注册所有路由
    register_routes(app)
    
    return app

4.2 模块职责

模块文件职责
配置config.py数据库连接、密钥、分页参数、默认管理员
数据库db.py连接管理、表 DDL、CRUD 辅助函数
认证auth.py密码哈希、用户 CRUD、登录日志
装饰器decorators.py登录/管理员权限校验
数据工具data_utils.py筛选条件构建、表单校验、JSON 序列化
导入器importer.pyCSV 批量导入
认证蓝图auth_bp.py登录、注册、个人中心路由
主应用app.py所有业务路由(53 个端点)

4.3 数据库访问层

db.py 提供统一的数据库访问接口:

# 查询多条
rows = fetch_all("SELECT * FROM order_items WHERE province = %s", ["北京"])

# 查询单条
row = fetch_one("SELECT * FROM users WHERE id = %s", [1])

# 执行写操作
result = execute("INSERT INTO announcements (...) VALUES (...)", [...])
# 返回 {"affected": 1, "lastrowid": 42}

# 批量插入
execute_many("INSERT INTO order_items (...) VALUES (...)", [row1, row2, ...])

连接管理:每次请求创建新连接,使用 contextmanager 管理事务:

  • 正常退出 → conn.commit()
  • 异常退出 → conn.rollback()
  • 最终 → conn.close()

4.4 权限控制

通过两个装饰器实现:

@login_required   # 需要登录(session 中有 user_id)
@admin_required   # 需要管理员角色(session 中 role == "admin")

行为差异

  • /api/* 路径:返回 JSON 错误(401/403)
  • 页面路径:重定向到登录页或首页

4.5 筛选条件构建

data_utils.py 中的 build_filters() 函数统一处理所有图表 API 的筛选参数:

def build_filters(args, include_keyword=False):
    conditions = []
    params = []
    
    start = args.get("start")
    end = args.get("end")
    province = args.get("province")
    product = args.get("product")
    salesperson = args.get("salesperson")
    
    if start:
        conditions.append("order_date >= %s")
        params.append(start)
    if end:
        conditions.append("order_date <= %s")
        params.append(end)
    if province:
        conditions.append("province = %s")
        params.append(province)
    if product:
        conditions.append("product_name = %s")
        params.append(product)
    if salesperson:
        conditions.append("salesperson_id = %s")
        params.append(int(salesperson))
    
    where = "WHERE " + " AND ".join(conditions) if conditions else ""
    return where, params

所有图表 API 接受以下通用查询参数:

参数说明示例
start开始日期2024-01-01
end结束日期2025-12-31
province省份筛选北京
product产品筛选碳纤维公路车架
salesperson销售员筛选3

4.6 JSON 序列化

data_utils.py 中的 jsonable() 函数处理 MySQL 返回的特殊类型:

def jsonable(value):
    if isinstance(value, Decimal):
        return float(value)
    if isinstance(value, (datetime, date)):
        return value.isoformat()
    if isinstance(value, dict):
        return {k: jsonable(v) for k, v in value.items()}
    if isinstance(value, (list, tuple)):
        return [jsonable(v) for v in value]
    return value

4.7 产品分类逻辑

通过 SQL CASE WHEN 表达式将产品名称映射到品类:

PRODUCT_CATEGORY_SQL = """
CASE
    WHEN product_name LIKE '%车架%' THEN '车架'
    WHEN product_name LIKE '%轮组%' OR product_name LIKE '%轮%' THEN '轮组'
    WHEN product_name LIKE '%头盔%' OR product_name LIKE '%眼镜%' 
         OR product_name LIKE '%手套%' OR product_name LIKE '%骑行服%'
         OR product_name LIKE '%锁鞋%' OR product_name LIKE '%鞋%' THEN '骑行穿戴'
    WHEN product_name LIKE '%链条%' OR product_name LIKE '%飞轮%'
         OR product_name LIKE '%刹车%' OR product_name LIKE '%变速%'
         OR product_name LIKE '%坐垫%' OR product_name LIKE '%把带%' THEN '零部件'
    WHEN product_name LIKE '%码表%' OR product_name LIKE '%车灯%'
         OR product_name LIKE '%水壶%' OR product_name LIKE '%包%'
         OR product_name LIKE '%打气筒%' OR product_name LIKE '%工具%' THEN '配件'
    WHEN product_name LIKE '%公路车%' OR product_name LIKE '%山地车%'
         OR product_name LIKE '%整车%' THEN '整车'
    ELSE '其他'
END
"""

5. API 接口文档

5.1 公共 API

5.1.1 健康检查
GET /api/health

认证:无需登录

响应

{
    "success": true,
    "database": "design_141_ride",
    "rows": 78262
}
5.1.2 筛选选项
GET /api/filters

认证:需要登录

响应

{
    "success": true,
    "provinces": [{"name": "北京"}, {"name": "上海"}, ...],
    "products": [{"name": "碳纤维公路车架"}, ...],
    "salespeople": [{"id": 1}, {"id": 2}, ...]
}
5.1.3 核心指标
GET /api/summary

认证:需要登录

响应

{
    "success": true,
    "data": {
        "total_revenue": 12345678.00,
        "total_orders": 5432,
        "total_customers": 1234,
        "on_time_rate": 85.6,
        "avg_order_amount": 2273.50,
        "avg_delivery_days": 8.3
    }
}
5.1.4 经营洞察
GET /api/insights

认证:需要登录

响应

{
    "success": true,
    "data": {
        "top_province": {"province": "广东", "revenue": 1234567},
        "top_product": {"product_name": "碳纤维公路车架", "revenue": 987654},
        "best_month": {"month": "2025-06", "revenue": 234567},
        "delay_risk": [{"province": "西藏", "delay_rate": 35.2}]
    }
}

5.2 图表 API

所有图表 API 均需登录,支持通用筛选参数。

5.2.1 销售趋势
GET /api/charts/trend

响应

{
    "success": true,
    "data": [
        {"month": "2024-01", "revenue": 123456, "orders": 345, "moving_avg": 120000},
        ...
    ]
}
5.2.2 省份排名
GET /api/charts/province

响应

{
    "success": true,
    "data": [
        {"province": "广东", "revenue": 1234567, "orders": 890, "customers": 456},
        ...
    ]
}
5.2.3 产品帕累托
GET /api/charts/product

响应

{
    "success": true,
    "data": [
        {"name": "碳纤维公路车架", "revenue": 987654, "quantity": 345, "cum_pct": 15.3},
        ...
    ]
}
5.2.4 品类结构
GET /api/charts/category

响应

{
    "success": true,
    "data": [
        {"name": "车架", "revenue": 3456789, "quantity": 1234, "orders": 987},
        ...
    ]
}
5.2.5 销售员表现
GET /api/charts/salesperson

响应

{
    "success": true,
    "data": [
        {"id": 1, "revenue": 987654, "orders": 234, "customers": 123, "on_time_rate": 88.5},
        ...
    ]
}
5.2.6 省份履约
GET /api/charts/delivery

响应

{
    "success": true,
    "data": [
        {"province": "北京", "total": 500, "on_time": 430, "on_time_rate": 86.0, "avg_days": 7.2},
        ...
    ]
}
5.2.7 客户排名
GET /api/charts/customer

响应

{
    "success": true,
    "data": [
        {"customer_id": "CUS-001", "customer_name": "张三", "revenue": 98765, "orders": 23},
        ...
    ]
}
5.2.8 价格-销量散点
GET /api/charts/price-quantity

响应

{
    "success": true,
    "data": [
        {"name": "碳纤维公路车架", "price": 3999, "quantity": 156, "revenue": 623844},
        ...
    ]
}
5.2.9 月度热力图
GET /api/charts/heatmap

响应

{
    "success": true,
    "data": [
        {"month": 1, "weekday": 0, "revenue": 123456},
        ...
    ],
    "months": ["2024-01", "2024-02", ...],
    "weekdays": ["周一", "周二", ...]
}
5.2.10 同比收入
GET /api/charts/yoy-revenue

响应

{
    "success": true,
    "data": [
        {"month": "01", "revenue_2024": 987654, "revenue_2025": 1234567, "growth_rate": 25.0},
        ...
    ]
}
5.2.11 省份地图
GET /api/charts/province-map

响应

{
    "success": true,
    "data": [
        {"name": "广东", "revenue": 1234567, "orders": 890, "customers": 456},
        ...
    ]
}
5.2.12 销售员月度趋势
GET /api/charts/salesperson-trend

响应

{
    "success": true,
    "data": [
        {"salesperson_id": 1, "month": "2024-01", "revenue": 98765, "orders": 23},
        ...
    ]
}
5.2.13 销售员雷达图
GET /api/charts/salesperson-radar

响应

{
    "success": true,
    "data": [
        {
            "id": 1,
            "revenue": 987654,
            "orders": 234,
            "customers": 123,
            "on_time_rate": 88.5,
            "avg_order_amount": 4220.0,
            "total_revenue": 987654
        },
        ...
    ],
    "indicators": [
        {"name": "销售额", "max": 1500000},
        {"name": "订单数", "max": 400},
        ...
    ]
}
5.2.14 履约趋势
GET /api/charts/delivery-trend

响应

{
    "success": true,
    "data": [
        {"month": "2024-01", "total": 450, "delayed": 67, "on_time_rate": 85.1, "avg_days": 8.2},
        ...
    ]
}
5.2.15 延迟分布
GET /api/charts/delivery-distribution

响应

{
    "success": true,
    "data": [
        {"bucket": "提前3天以上", "count": 1234},
        {"bucket": "准时(±1天)", "count": 3456},
        {"bucket": "延迟1-3天", "count": 890},
        ...
    ]
}
5.2.16 RFM 客户分析
GET /api/charts/customer-rfm

响应

{
    "success": true,
    "data": [
        {"customer_id": "CUS-001", "customer_name": "张三", "recency": 15, "frequency": 8, "monetary": 45678, "segment": "Champions"},
        ...
    ],
    "summary": {
        "Champions": 123,
        "Loyal": 234,
        "New": 345,
        "At Risk": 167,
        "Lost": 89,
        "Potential": 145
    }
}

RFM 分段规则

  • Champions:R≥75%, F≥75%, M≥75%
  • Loyal:F≥75%, M≥75%
  • New:R≥75%, F<25%
  • At Risk:R<25%, M≥50%
  • Lost:R<25%, F<25%, M<25%
  • Potential:其余客户
5.2.17 购买频次分布
GET /api/charts/customer-frequency

响应

{
    "success": true,
    "data": [
        {"frequency": "1次", "count": 456},
        {"frequency": "2-3次", "count": 234},
        ...
    ]
}
5.2.18 新老客户趋势
GET /api/charts/customer-retention

响应

{
    "success": true,
    "data": [
        {"month_label": "2024-01", "new_customers": 123, "returning_customers": 456},
        ...
    ]
}
5.2.19 客户省份分布
GET /api/charts/customer-province

响应

{
    "success": true,
    "data": [
        {"name": "广东", "customers": 234, "revenue": 1234567},
        ...
    ]
}
5.2.20 客户产品偏好
GET /api/charts/customer-product

响应

{
    "success": true,
    "data": [
        {"name": "碳纤维公路车架", "customers": 123, "quantity": 345, "revenue": 987654},
        ...
    ]
}

5.3 订单 CRUD API(管理员)

5.3.1 查询订单列表
GET /api/orders?page=1&per_page=15&keyword=&start=&end=&province=&product=&salesperson=

响应

{
    "success": true,
    "data": [...],
    "pagination": {
        "page": 1,
        "per_page": 15,
        "total": 78262,
        "pages": 5218
    }
}
5.3.2 获取单条订单
GET /api/orders/<id>
5.3.3 创建订单
POST /api/orders
Content-Type: application/json

{
    "order_id": "ORD-78263",
    "customer_name": "新客户",
    "customer_id": "CUS-999",
    "province": "北京",
    "salesperson_id": "1",
    "order_date": "2025-06-01",
    "est_delivery": "2025-06-08",
    "act_delivery_date": "2025-06-07",
    "product_id": "1",
    "product_name": "碳纤维公路车架",
    "quantity": "2",
    "price": "3999",
    "amount": "7998"
}
5.3.4 更新订单
PUT /api/orders/<id>
Content-Type: application/json

{ ... 同创建 ... }
5.3.5 删除订单
DELETE /api/orders/<id>

5.4 收藏 API

GET    /api/bookmarks          # 获取当前用户收藏列表
POST   /api/bookmarks          # 创建收藏
DELETE /api/bookmarks/<id>     # 删除收藏

5.5 公告 API

GET /api/announcements          # 获取已发布公告列表(分页)
GET /api/announcements/<id>     # 获取公告详情(自动增加浏览量)

5.6 管理员 API

GET    /api/admin/users                      # 用户列表
POST   /api/admin/users                      # 创建用户
PUT    /api/admin/users/<id>                 # 更新用户
PUT    /api/admin/users/<id>/reset-password  # 重置密码
DELETE /api/admin/users/<id>                 # 删除用户

GET    /api/admin/logs                       # 操作日志

GET    /api/admin/announcements              # 公告列表(含草稿)
POST   /api/admin/announcements              # 创建公告
PUT    /api/admin/announcements/<id>         # 更新公告
DELETE /api/admin/announcements/<id>         # 删除公告

GET    /api/export/orders                    # 导出订单 CSV

6. 前端架构

6.1 页面结构

系统共 11 个功能页面,通过顶部导航栏组织:

[Ride BI]  [经营总览]  [维度分析 ▼]  [数据管理]  [公告]  [...]  [用户 ▼]
                              ├── 区域分析
                              ├── 产品结构
                              ├── 销售员表现
                              ├── 履约时效
                              └── 客户价值

用户菜单(登录后可见):

  • 个人中心
  • 我的收藏
  • 用户管理(管理员)
  • 操作日志(管理员)
  • 公告管理(管理员)
  • 退出登录

6.2 公共工具库(common.js)

RideBI 全局对象提供以下工具:

方法说明
RideBI.api(path, params)GET 请求封装,自动处理 401 跳转
RideBI.postApi(path, data)POST 请求封装
RideBI.byId(id)document.getElementById 简写
RideBI.fmtNumber(v)数字格式化(千分位)
RideBI.fmtMoney(v)金额格式化(人民币)
RideBI.fmtMoneyShort(v)金额简写(万/亿)
RideBI.fmtPercent(v)百分比格式化
RideBI.baseOption()ECharts 基础配置(配色、网格、提示框)
RideBI.currentParams()从筛选栏收集当前筛选参数
RideBI.loadSavedFilters()从 sessionStorage 恢复筛选状态
RideBI.fillSelect(sel, rows, getVal, getLabel)填充下拉选项
RideBI.chart(id)获取/创建 ECharts 实例
RideBI.resizeCharts()自适应所有图表尺寸
RideBI.showToast(msg, type)显示提示消息
RideBI.initBookmark(btnId, title, url)初始化收藏按钮

6.3 页面 JS 文件职责

文件行数职责
common.js240公共工具库(RideBI 对象)
dashboard.js133KPI 指标、趋势图、同比图、经营洞察
region.js132省份排名柱状图、热力地图、履约风险图
product.js147产品帕累托图、品类饼图、价格散点图、热力图
salesperson.js163销售员贡献图、月度趋势图、雷达图
customer.js214客户排名、RFM 气泡图、频次分布、留存趋势
delivery.js147准时率仪表盘、省份履约、月度趋势、延迟分布
manage.js243订单表格、筛选、分页、新增/编辑/删除弹窗
admin.js128用户管理表格、新增/编辑弹窗

6.4 图表类型分布

图表类型数量使用页面
柱状图(Bar)8区域、产品、销售员、客户、履约
折线图(Line)5总览趋势、履约趋势、销售员趋势
饼图(Pie)2品类结构、履约风险
散点图(Scatter)2价格-销量、RFM
雷达图(Radar)1销售员能力
仪表盘(Gauge)1准时率
热力图(Heatmap)2月度热力图、省份地图
地图(Map)1省份销售热力
帕累托图(Bar+Line)1产品累计占比
堆叠面积图1新老客户趋势

6.5 配色方案

palette = ["#0f766e", "#14b8a6", "#ea580c", "#f59e0b", "#0284c7", "#16a34a", "#dc2626", "#8b5cf6"]

主色调为青绿色系(#0f766e / #14b8a6),辅以橙色(#ea580c)作为对比色。

6.6 CSS 布局系统

核心类名

类名用途
.workbench-head页面头部(标题 + 元信息 + 操作按钮)
.filter-bar筛选栏(Flex 布局,自动换行)
.kpi-gridKPI 指标卡片网格
.chart-grid图表卡片网格(3 列自适应)
.chart-grid-22 列图表网格
.chart-card单个图表卡片
.chart-wide跨 2 列
.chart-full跨满整行
.table-shell数据表格容器
.table-toolbar表格工具栏
.pagination-bar分页栏
.announce-overlay自定义弹窗遮罩
.announce-dialog自定义弹窗对话框

响应式断点

断点图表列数
>1200px3 列
768-1200px2 列
<768px1 列

7. 功能模块详解

7.1 经营总览(Dashboard)

路由GET /

功能

  • 6 个 KPI 指标卡(销售额、订单数、客户数、准时率、客单金额、平均履约天数)
  • 销售趋势折线图(含移动平均线)
  • 经营洞察面板(最佳省份、最佳产品、最佳月份、延迟风险)
  • 同比收入对比柱状图
  • 6 个快捷入口卡片

API 调用链

/api/summary → KPI 指标
/api/charts/trend → 趋势图
/api/insights → 洞察面板
/api/charts/yoy-revenue → 同比图

7.2 区域分析(Region)

路由GET /region

图表

  1. 省份销售排名:Top 15 省份柱状图 + 折线(订单数双轴)
  2. 销售热力地图:中国地图着色(按销售额)
  3. 省份履约风险:双轴图(准时率柱状 + 平均履约天数折线)

API 调用链

/api/charts/province → 排名图
/api/charts/province-map → 地图
/api/charts/delivery → 履约风险

7.3 产品结构(Product)

路由GET /product

图表

  1. 产品帕累托图:Top 12 产品柱状(收入)+ 折线(累计占比%)
  2. 品类结构:饼图(按品类分组)
  3. 价格-销量关系:散点图(价格 vs 销量,气泡大小 = 收入)
  4. 月度热力图:月份 × 星期几 收入热力矩阵

API 调用链

/api/charts/product → 帕累托
/api/charts/category → 品类
/api/charts/price-quantity → 散点
/api/charts/heatmap → 热力图

7.4 销售员表现(Salesperson)

路由GET /salesperson

图表

  1. 销售员贡献度:柱状图(收入)+ 折线(准时率)
  2. 月度销售趋势:多系列折线图(各销售员月收入)
  3. 绩效雷达图:多维指标对比(销售额、订单数、客户数、准时率、客单金额)

API 调用链

/api/charts/salesperson → 贡献度
/api/charts/salesperson-trend → 趋势
/api/charts/salesperson-radar → 雷达

7.5 客户价值(Customer)

路由GET /customer

图表

  1. 客户价值排名:Top 15 客户柱状图
  2. RFM 客户分群:气泡图(Recency vs Frequency,气泡大小 = Monetary,颜色 = 分群)
  3. 购买频次分布:柱状图
  4. 新老客户趋势:堆叠面积图
  5. 客户省份分布:双轴图(客户数柱状 + 销售额折线)
  6. 客户产品偏好:柱状图

API 调用链

/api/charts/customer → 排名
/api/charts/customer-rfm → RFM
/api/charts/customer-frequency → 频次
/api/charts/customer-retention → 留存
/api/charts/customer-province → 省份
/api/charts/customer-product → 产品

7.6 履约时效(Delivery)

路由GET /delivery

图表

  1. 整体准时率:仪表盘(Gauge)
  2. 省份履约对比:柱状图(准时率)
  3. 月度履约趋势:双轴(延迟订单数柱状 + 准时率折线)
  4. 延迟天数分布:柱状图(延迟区间分布)

API 调用链

/api/charts/delivery → 省份履约
/api/charts/delivery-trend → 趋势
/api/charts/delivery-distribution → 分布

7.7 数据管理(Manage)

路由GET /manage(仅管理员)

功能

  • 订单列表(分页、筛选、排序)
  • 关键词搜索(订单号、客户名、产品名)
  • 日期范围筛选
  • 省份/产品/销售员下拉筛选
  • 每页条数切换(10/15/30/50)
  • 新增订单(弹窗表单)
  • 编辑订单(弹窗表单,自动回填)
  • 删除订单(确认后删除)
  • 金额自动计算(数量 × 单价)

表单校验

  • 必填:订单号、客户名称、客户编号、省份、销售员、日期、产品、数量、单价
  • 类型校验:数量 ≥ 1,单价 ≥ 0
  • 金额自动计算:amount = quantity × price

7.8 认证系统

登录

  • 用户名 + 密码(JSON POST)
  • 密码使用 werkzeug PBKDF2 哈希验证
  • 登录成功后写入 Session(user_id, username, nickname, role)
  • Session 永久有效,24 小时过期
  • 登录日志自动记录

注册

  • 用户名 + 密码 + 昵称(JSON POST)
  • 用户名唯一性校验
  • 默认角色:user
  • 注册成功后自动登录

个人中心

  • 查看/修改昵称、邮箱、手机
  • 修改密码(需验证原密码)

7.9 权限矩阵

功能管理员普通用户
查看总览/分析页面
筛选图表
收藏页面
查看公告
订单 CRUD
用户管理
公告管理
操作日志全部仅自己
数据导出

8. 部署与运行

8.1 环境要求

  • Python 3.8+
  • MySQL 5.7+ 或 8.0+
  • pip(Python 包管理)

8.2 安装步骤

# 1. 安装依赖
pip install -r requirements.txt

# 2. 配置数据库(修改 config.py 或设置环境变量)
export DB_HOST=localhost
export DB_PORT=3306
export DB_USER=root
export DB_PASSWORD=123456
export DB_NAME=design_141_ride

# 3. 初始化数据库并导入数据
python scripts/init_db.py --reset

# 4. 启动应用
python app.py

8.3 初始化脚本参数

python scripts/init_db.py [OPTIONS]

--reset          删除并重建所有表
--skip-import    跳过 CSV 数据导入
--csv <path>     指定 CSV 文件路径

8.4 环境变量

变量名默认值说明
SECRET_KEYride-bi-141-fixed-secret-key-2024Flask 会话密钥
SESSION_LIFETIME86400会话过期时间(秒)
DB_HOSTlocalhost数据库主机
DB_PORT3306数据库端口
DB_USERroot数据库用户
DB_PASSWORD123456数据库密码
DB_NAMEdesign_141_ride数据库名

8.5 默认账号

角色用户名密码
管理员adminadmin123

8.6 访问地址

http://127.0.0.1:5001

9. 数据字典

9.1 订单状态枚举

字段含义
users.roleadmin管理员
users.roleuser普通用户
users.status1正常
users.status0禁用
announcements.status1已发布
announcements.status0草稿
alerts.statusnormal正常
alerts.statuswarning预警
alerts.statuscritical严重

9.2 操作类型枚举

action 值含义
login用户登录
logout用户登出
create新增记录
update修改记录
delete删除记录
export导出数据

9.3 RFM 客户分群

分群条件含义
ChampionsR≥75%, F≥75%, M≥75%冠军客户
LoyalF≥75%, M≥75%忠实客户
NewR≥75%, F<25%新客户
At RiskR<25%, M≥50%流失风险
LostR<25%, F<25%, M<25%已流失
Potential其余潜力客户

10. 扩展指南

10.1 新增图表页面

  1. 创建模板 templates/xxx.html(继承 base.html
  2. 创建 JS static/js/xxx.js
  3. app.py 中添加页面路由
  4. app.py 中添加数据 API
  5. base.html 导航栏中添加入口

10.2 新增 API 端点

@app.route("/api/charts/new-chart")
@login_required
def chart_new_chart():
    where, params = build_filters(request.args)
    rows = fetch_all(f"SELECT ... FROM order_items {where}", params)
    return jsonify(jsonable({"success": True, "data": rows}))

10.3 新增筛选维度

  1. data_utils.pybuild_filters() 中添加条件
  2. api/filters 端点中添加选项数据
  3. base.html 或页面模板中添加筛选控件
  4. common.jscurrentParams() 中添加映射

10.4 数据库迁移

如需新增表,在 db.py 中:

  1. 定义 CREATE TABLE SQL
  2. 添加到 ALL_TABLES 列表
  3. 运行 init_database() 自动创建

11. 已知限制

  1. 无 ORM:全部使用原生 SQL,复杂查询需要手动拼接
  2. 单进程:Flask 开发服务器不支持并发,生产环境需用 Gunicorn/uWSGI
  3. 无前端构建:纯原生 JS,无模块化/打包/压缩
  4. Session 存储:默认内存存储,重启丢失(已通过固定 SECRET_KEY 解决)
  5. pandas 未使用:requirements.txt 中声明但代码中未引用
  6. CSV 数据静态:数据更新需重新导入,无实时数据源接入

12. 代码统计

类型文件数总行数
Python 后端10~2,500
JavaScript 前端9~1,550
HTML 模板16~1,200
CSS 样式1~1,100
合计36~6,350

更多推荐