Skip to content

ShopAgent 技术文档

1. 项目概述

ShopAgent 是一个基于 Flask 的轻量级购物网站项目,前端使用 Vue 3 CDN 方式构建交互页面,后端提供商品、用户、点击记录、最近浏览商品、人工客服工单等 REST API,数据存储使用 MySQL。

项目面向“电商商品展示 + 售前 Agent 辅助导购”场景,核心目标是:

  • 展示商品列表、分类、价格、标签、热门标识和商品详情。
  • 支持用户注册、登录、退出登录和登录状态校验。
  • 记录用户点击商品的行为,用于生成最近点击商品上下文。
  • 未登录用户使用浏览器 localStorage 临时保存点击记录,登录后可同步到数据库。
  • 将最近点击商品、登录状态、用户名等上下文传入 Dify Chatbot,辅助售前咨询。
  • 支持 Dify “转人工”分支调用后端接口,生成客服工单,并可选通过 SMTP 邮件通知客服。

项目入口页面标题为“阿里飞飞购物网站”,页面包含商品分类、商品搜索、最近点击、Dify 预留区、商品卡片和商品详情弹窗。


2. 技术栈

2.1 后端技术栈

类型技术/依赖当前版本/说明
编程语言Python适用于 Flask Web 服务开发
Web 框架Flask3.0.3
WSGI 工具库Werkzeug3.0.3,用于密码哈希校验等能力
数据库驱动PyMySQL1.1.1,用于连接 MySQL
数据库MySQL使用 InnoDB、utf8mb4、JSON 字段、外键约束
会话管理Flask Session基于 app.secret_key 维护登录状态
密码安全Werkzeug Password Hashgenerate_password_hash / check_password_hash
邮件通知Python smtplib用于转人工工单邮件通知,可选配置

2.2 前端技术栈

类型技术/依赖说明
页面模板Jinja2 TemplateFlask 默认模板引擎,页面位于 templates/index.html
前端框架Vue 3 CDN通过 https://unpkg.com/vue@3/dist/vue.global.prod.js 引入,无需 npm/Vite
网络请求Fetch API前端统一调用后端 REST API
本地存储localStorage保存未登录用户点击记录
样式原生 CSS样式文件位于 static/css/style.css
静态资源SVG 图片商品图片位于 static/images/
Agent 集成Dify Chatbot Embed动态插入 Dify 官方脚本,并提供 iframe 兜底方案

2.3 依赖文件

项目依赖集中在 requirements.txt

txt
Flask==3.0.3
Werkzeug==3.0.3
PyMySQL==1.1.1

3. 项目目录结构

text
ShopAgent/
├── app.py                    # Flask 后端主程序,包含数据库初始化和 API 路由
├── mysql_schema.sql           # MySQL 建库建表 SQL 脚本
├── requirements.txt           # Python 依赖列表
├── templates/
│   └── index.html             # 前端主页面模板
├── static/
│   ├── css/
│   │   └── style.css          # 页面样式
│   ├── js/
│   │   └── app.js             # Vue 前端逻辑、API 调用、Dify 集成
│   └── images/
│       ├── product-1.svg      # 默认商品图片
│       ├── product-2.svg
│       ├── product-3.svg
│       ├── product-4.svg
│       ├── product-5.svg
│       ├── product-6.svg
│       ├── product-7.svg
│       └── product-8.svg
└── .idea/                     # IDE 配置文件,非运行必需

4. 核心功能介绍

4.1 商品展示与搜索

项目内置 8 个默认商品,覆盖电脑办公、数码配件、家用电器、家具生活等分类。后端启动时会自动检查数据库,如果 products 表为空,则写入默认商品数据。

商品支持:

  • 按分类筛选。
  • 按商品名称、描述、分类、标签模糊搜索。
  • 热门商品优先展示。
  • 点击商品卡片后打开商品详情弹窗。

相关后端接口:

接口方法功能
/api/categoriesGET获取商品分类列表
/api/productsGET获取商品列表,支持 categorykeywordlimit 查询参数
/api/products/<product_id>GET获取单个商品详情

4.2 用户注册与登录

系统支持基础账号体系:

  • 注册时校验用户名和密码不能为空。
  • 密码长度至少 4 位。
  • 用户名唯一。
  • 密码不会明文保存,而是通过 Werkzeug 生成哈希后写入数据库。
  • 登录成功后将 user_idusername 写入 Flask Session。

相关后端接口:

接口方法功能
/api/registerPOST用户注册,成功后自动登录
/api/loginPOST用户登录
/api/logoutPOST退出登录并清空 Session
/api/meGET获取当前登录状态和用户信息

4.3 商品点击记录

点击记录用于分析用户兴趣,并作为 Dify 售前 Agent 的上下文输入。

处理逻辑:

  1. 用户未登录时,前端将点击记录保存到浏览器 localStorage
  2. 用户登录后,前端调用同步接口,把匿名点击记录写入 MySQL。
  3. 用户已登录时,点击商品会直接写入 clicks 表。
  4. 最近点击商品接口会按用户、商品聚合点击次数,并按最后点击时间倒序返回。

相关后端接口:

接口方法功能
/api/clicksPOST登录用户写入商品点击记录
/api/clicks/syncPOST登录后同步匿名点击记录
/api/recent-productsGET获取登录用户最近点击商品,支持 limit 参数

前端未登录点击记录 key:

js
simple_shop_anonymous_product_clicks

4.4 Dify 售前 Agent 集成

前端通过 static/js/app.js 动态插入 Dify Chatbot 配置和脚本。

当前配置字段:

js
const DIFY_CHATBOT_TOKEN = "CZOJ6kUDprFbdjub";
const DIFY_BASE_URL = "http://8.163.40.249";
const DIFY_SCRIPT_URL = `${DIFY_BASE_URL}/embed.min.js`;

传给 Dify 的 inputs 包含:

字段说明
logged_in当前用户是否登录,字符串形式:true / false
username当前登录用户名,未登录为空字符串
contact用户联系方式,当前代码预留字段
recent_clicked_products最近点击商品列表 JSON 字符串

最近点击商品会被标准化为如下结构:

json
{
  "id": 1,
  "name": "轻薄商务笔记本",
  "category": "电脑办公",
  "price": 4999,
  "description": "适合办公、学习和轻度开发的轻薄笔记本。",
  "tags": ["办公", "便携", "高性能"],
  "hot": 1,
  "last_clicked_at": "2026-05-24T10:00:00",
  "click_count": 1
}

为了提升兼容性,项目还做了以下兜底处理:

  • 如果浏览器不是安全上下文导致 navigator.mediaDevices 不可用,会提供兼容兜底,避免 Dify 语音能力报错影响页面。
  • 如果 Dify 官方 embed.min.js 加载失败或加载后未创建 DOM,会自动创建 iframe 兜底气泡。
  • 页面提供“预览传给 Agent 的数据”按钮,便于调试 Dify 上下文输入。

4.5 转人工客服工单

项目提供 /api/support/handoff 接口,供 Dify 的“转人工”节点调用。

接口会把用户问题保存到 support_requests 表中。如果配置了 SMTP 环境变量,则会同步发送邮件通知客服;未配置 SMTP 时只写入数据库,不影响接口成功返回。

请求字段:

字段必填说明
username用户名
contact用户联系方式
question用户问题
reason转人工原因
conversation_summary会话摘要

成功响应示例:

json
{
  "message": "已提交人工客服工单",
  "ticket_id": 1,
  "email_sent": false
}

5. 系统架构说明

5.1 整体架构

text
浏览器
  ├─ Vue 3 页面交互
  ├─ Fetch API 调用 Flask 后端
  ├─ localStorage 保存匿名点击记录
  └─ Dify Chatbot 嵌入脚本 / iframe 兜底


Flask 后端 app.py
  ├─ 页面渲染:index.html
  ├─ 用户认证:注册 / 登录 / 退出 / 当前用户
  ├─ 商品接口:分类 / 列表 / 详情
  ├─ 点击追踪:记录点击 / 同步匿名点击 / 最近点击商品
  ├─ 客服工单:保存转人工请求
  └─ 邮件通知:可选 SMTP


MySQL 数据库
  ├─ users
  ├─ products
  ├─ clicks
  └─ support_requests

5.2 典型业务流程

用户浏览商品流程

text
用户打开首页
  → Flask 返回 index.html
  → Vue 初始化
  → 调用 /api/me 检查登录态
  → 调用 /api/categories 加载分类
  → 调用 /api/products 加载商品
  → 页面渲染商品列表

商品点击与 Dify 上下文流程

text
用户点击商品
  → 打开商品详情弹窗
  → 判断用户是否登录
      ├─ 未登录:写入 localStorage
      └─ 已登录:POST /api/clicks 写入 MySQL
  → 刷新最近点击商品
  → 更新 window.difyChatbotConfig.inputs
  → Dify Agent 获取用户兴趣上下文

登录后匿名点击同步流程

text
用户登录 / 注册成功
  → 前端读取 localStorage 匿名点击记录
  → POST /api/clicks/sync
  → 后端校验商品是否存在
  → 写入 clicks 表,source = anonymous_synced
  → 前端清空 localStorage 点击记录
  → 刷新最近点击商品

6. 数据库设计

6.1 users 表

用户账号表。

字段类型说明
idINT UNSIGNED主键,自增
usernameVARCHAR(80)用户名,唯一
password_hashVARCHAR(255)密码哈希
created_atDATETIME创建时间

约束与索引:

  • 主键:id
  • 唯一索引:uq_users_username(username)

6.2 products 表

商品表。

字段类型说明
idINT UNSIGNED主键,自增
nameVARCHAR(120)商品名称
categoryVARCHAR(80)商品分类
priceDECIMAL(10,2)商品价格
imageVARCHAR(255)商品图片路径
descriptionTEXT商品描述
tagsJSON商品标签
hotTINYINT(1)是否热门商品

索引:

  • idx_products_category(category)
  • idx_products_hot(hot)

6.3 clicks 表

商品点击记录表。

字段类型说明
idBIGINT UNSIGNED主键,自增
user_idINT UNSIGNED用户 ID
product_idINT UNSIGNED商品 ID
clicked_atDATETIME点击时间
sourceVARCHAR(32)点击来源,例如 logged_inanonymous_synced

约束与索引:

  • 外键:user_id 关联 users(id),用户删除时级联删除点击记录。
  • 外键:product_id 关联 products(id),商品删除时级联删除点击记录。
  • 索引:idx_clicks_user_clicked_at(user_id, clicked_at)
  • 索引:idx_clicks_product_id(product_id)

6.4 support_requests 表

客服工单表。

字段类型说明
idBIGINT UNSIGNED主键,自增
usernameVARCHAR(80)用户名,可为空
contactVARCHAR(120)联系方式,可为空
questionTEXT用户问题
reasonVARCHAR(255)转人工原因
conversation_summaryTEXT会话摘要
statusVARCHAR(32)工单状态,默认 pending
created_atDATETIME创建时间

索引:

  • idx_support_requests_status_created_at(status, created_at)

7. API 文档

7.1 页面接口

GET /

返回首页 HTML 页面。


7.2 商品接口

GET /api/categories

获取商品分类。

响应示例:

json
{
  "categories": ["电脑办公", "家具生活", "家用电器", "数码配件"]
}

GET /api/products

获取商品列表。

查询参数:

参数必填说明
category商品分类,默认 全部
keyword搜索关键词
limit返回数量限制,最大 50

响应示例:

json
{
  "products": [
    {
      "id": 1,
      "name": "轻薄商务笔记本",
      "category": "电脑办公",
      "price": 4999,
      "image": "/static/images/product-1.svg",
      "description": "适合办公、学习和轻度开发的轻薄笔记本。",
      "tags": ["办公", "便携", "高性能"],
      "hot": 1
    }
  ]
}

GET /api/products/<product_id>

获取指定商品详情。

异常响应:

json
{
  "message": "商品不存在"
}

7.3 用户接口

POST /api/register

注册用户,成功后自动登录。

请求示例:

json
{
  "username": "test",
  "password": "1234"
}

响应示例:

json
{
  "message": "注册成功",
  "user": {
    "id": 1,
    "username": "test"
  }
}

POST /api/login

用户登录。

请求示例:

json
{
  "username": "test",
  "password": "1234"
}

响应示例:

json
{
  "message": "登录成功",
  "user": {
    "id": 1,
    "username": "test"
  }
}

POST /api/logout

退出登录。

响应示例:

json
{
  "message": "已退出登录"
}

GET /api/me

获取当前用户状态。

响应示例:

json
{
  "logged_in": true,
  "user": {
    "id": 1,
    "username": "test"
  }
}

7.4 点击记录接口

POST /api/clicks

登录用户写入商品点击记录。

请求示例:

json
{
  "product_id": 1
}

响应示例:

json
{
  "message": "点击记录已写入数据库"
}

POST /api/clicks/sync

同步匿名点击记录到数据库。

请求示例:

json
{
  "clicks": [
    {
      "product_id": 1,
      "clicked_at": "2026-05-24T10:00:00.000Z"
    }
  ]
}

响应示例:

json
{
  "message": "匿名点击记录已同步",
  "saved_count": 1
}

GET /api/recent-products

获取最近点击商品。

查询参数:

参数必填说明
limit数量限制,默认 5,最大 20

响应示例:

json
{
  "logged_in": true,
  "products": [
    {
      "id": 1,
      "name": "轻薄商务笔记本",
      "category": "电脑办公",
      "price": 4999,
      "image": "/static/images/product-1.svg",
      "description": "适合办公、学习和轻度开发的轻薄笔记本。",
      "tags": ["办公", "便携", "高性能"],
      "hot": 1,
      "last_clicked_at": "2026-05-24T10:00:00",
      "click_count": 3
    }
  ]
}

7.5 人工客服接口

POST /api/support/handoff

提交转人工客服工单。

请求示例:

json
{
  "username": "test",
  "contact": "test@example.com",
  "question": "我想了解笔记本电脑的售后政策",
  "reason": "用户需要人工解释售后条款",
  "conversation_summary": "用户咨询轻薄商务笔记本的保修和退换货问题"
}

响应示例:

json
{
  "message": "已提交人工客服工单",
  "ticket_id": 1,
  "email_sent": false
}

8. 环境变量配置

8.1 Flask 与 MySQL 配置

环境变量默认值说明
SHOP_SECRET_KEYSHOP_SECRET_KEYFlask Session 密钥,生产环境必须修改
MYSQL_HOST127.0.0.1MySQL 主机
MYSQL_PORT3306MySQL 端口
MYSQL_USERrootMySQL 用户名
MYSQL_PASSWORD123456MySQL 密码
MYSQL_DATABASEshop_agent数据库名称
MYSQL_CHARSETutf8mb4数据库字符集

8.2 SMTP 邮件配置

如果需要转人工邮件通知,需要配置以下变量:

环境变量必填说明
SUPPORT_EMAIL_TO客服接收邮箱
SMTP_HOSTSMTP 服务器地址
SMTP_PORTSMTP 端口,默认 587
SMTP_USERSMTP 登录账号
SMTP_PASSWORDSMTP 登录密码
SMTP_USE_TLS是否启用 TLS,默认 true
SMTP_FROM发件人,默认使用 SMTP_USER

项目总结

ShopAgent 是一个适合教学、课程设计或原型验证的轻量级电商导购项目。项目的主要特点是:

  • 后端使用 Flask 快速提供 REST API。
  • 数据层使用 MySQL 保存用户、商品、点击记录和客服工单。
  • 前端使用 Vue 3 CDN,无需复杂前端构建流程。
  • 支持未登录与已登录两种点击追踪方案。
  • 与 Dify Chatbot 集成,把用户最近点击商品作为售前 Agent 上下文。
  • 提供转人工接口,可沉淀客服工单并通过 SMTP 邮件通知客服。

该项目可以作为“电商网站 + AI 售前客服”的基础版本,后续可继续扩展订单、购物车、支付、商品管理后台、推荐系统、客服工单后台等功能。