2. 需求分析与设计:功能模块划分、数据库E-R图与接口规范

好,咱们进入第二章。说实话,很多新手做项目,上来就撸代码,结果写到一半发现逻辑打架,接口对不上。我个人的习惯是,先花半天时间把需求理清楚,把模块画出来。这就像盖房子,图纸没画好就砌砖,后面肯定得返工。

这一章,我会带你走完三个关键步骤:功能模块划分数据库E-R图设计接口文档规范。你想想看,这三件事做扎实了,后面的开发就是「填表格」的体力活了。

2.1 功能模块划分

一个小程序电商系统,核心就五个模块:用户商品购物车订单支付。嗯,这里要注意,千万别把「支付」和「订单」混在一起,它们是两个独立的东西。

2.1.1 用户模块

用户模块不只是登录注册。我记得有一次做项目,只做了手机号登录,结果用户反馈说「我想换个头像都找不到入口」。所以,用户模块至少包含:

  • 注册与登录:微信授权登录 + 手机号绑定
  • 个人信息管理:头像、昵称、收货地址
  • 账户安全:密码修改、退出登录

2.1.2 商品模块

商品模块是门面。说白了,用户第一眼看到的就是商品列表。我建议把商品模块拆成:

  • 商品分类:一级分类、二级分类(比如「女装」→「连衣裙」)
  • 商品详情:标题、价格、库存、规格(颜色、尺寸)、轮播图
  • 搜索与筛选:按价格排序、按销量排序、按分类筛选
我的经验:商品图片一定要做压缩处理。我曾经遇到一个项目,商品图每张5MB,加载慢得用户直接卸载了。后来加了缩略图,体验瞬间提升。

2.1.3 购物车模块

购物车看似简单,其实坑不少。用户可能加购10件商品,但只结算3件。所以购物车需要:

  • 商品列表:展示加购的商品,支持勾选/取消
  • 数量修改:加号、减号,实时计算小计
  • 库存校验:结算时检查库存是否充足
注意:购物车数据建议存在后端,不要只存本地缓存。否则用户换个手机,购物车就空了,这体验很糟糕。

2.1.4 订单模块

订单模块是核心中的核心。我习惯把订单状态画成一条线:

  1. 待支付:用户提交订单,但还没付钱
  2. 已支付:支付成功,等待商家发货
  3. 已发货:商家发货,用户等待收货
  4. 已完成:用户确认收货
  5. 已取消:用户主动取消或超时未支付

每个状态都要有对应的操作按钮,比如「取消订单」、「查看物流」、「确认收货」。

2.1.5 支付模块

支付模块其实是一个「桥梁」。它连接了前端、后端和微信支付服务器。流程大概是:

  • 前端发起支付请求
  • 后端生成预支付订单,返回支付参数
  • 前端调起微信支付
  • 支付成功后,微信异步通知后端

这里有个关键点:支付结果以后端通知为准。前端显示的支付成功可能是假的,必须等后端收到微信的回调才算数。

2.2 数据库E-R图设计

E-R图,说白了就是「实体-关系图」。你想想看,用户和订单是什么关系?一个用户可以有多个订单,这就是一对多。商品和分类呢?一个分类下有多个商品,也是一对多。

我直接给你列出核心表的设计思路:

2.2.1 用户表(user)

字段名类型说明
idint主键,自增
openidvarchar(64)微信唯一标识
nicknamevarchar(32)昵称
avatarvarchar(255)头像URL
phonevarchar(11)手机号
created_atdatetime注册时间

2.2.2 商品表(product)

字段名类型说明
idint主键
category_idint分类ID,外键
titlevarchar(100)商品标题
pricedecimal(10,2)价格
stockint库存数量
imagevarchar(255)主图
statustinyint状态:1上架,0下架

2.2.3 订单表(order)

字段名类型说明
idint主键
user_idint用户ID
order_novarchar(32)订单号(唯一)
total_pricedecimal(10,2)总金额
statustinyint0待支付,1已支付,2已发货,3已完成,4已取消
created_atdatetime下单时间

2.2.4 订单商品表(order_item)

为什么要有这张表?因为一个订单可能包含多个商品。比如你买了「T恤」和「裤子」,它们会出现在同一个订单里。这张表就是用来记录订单和商品的对应关系。

字段名类型说明
idint主键
order_idint订单ID
product_idint商品ID
quantityint购买数量
pricedecimal(10,2)购买时的单价
核心关系总结:
用户 1 : N 订单
订单 1 : N 订单商品
商品 1 : N 订单商品
商品 N : 1 分类

2.3 接口文档规范(RESTful API)

接口文档是前后端沟通的「合同」。我见过太多因为接口定义不清导致的撕逼。前端说「你返回的字段名不对」,后端说「你传的参数格式错了」。所以,规范很重要。

2.3.1 RESTful 风格

说白了,RESTful 就是用 HTTP 方法来表示操作:

  • GET:获取资源(比如获取商品列表)
  • POST:创建资源(比如创建订单)
  • PUT:更新资源(比如修改收货地址)
  • DELETE:删除资源(比如删除购物车商品)

2.3.2 接口命名规范

我习惯用名词复数形式,比如:

  • GET /api/products — 获取商品列表
  • GET /api/products/:id — 获取单个商品详情
  • POST /api/orders — 创建订单
  • PUT /api/users/:id/address — 更新用户地址

注意,不要用动词,比如 /api/getProducts 这种写法是不推荐的。

2.3.3 统一返回格式

所有接口返回统一的结构,前端才好统一处理。我常用的格式是:

{
    "code": 200,
    "message": "success",
    "data": {
        // 具体数据
    }
}

错误时:

{
    "code": 400,
    "message": "参数错误:商品ID不能为空",
    "data": null
}
避坑指南:我曾经遇到一个项目,后端返回的 code 有时是数字,有时是字符串。前端每次都要做类型转换,烦得要死。所以,统一用数字类型,别搞混。

2.3.4 接口示例

我挑几个核心接口给你看看:

1. 获取商品列表

GET /api/products?category_id=1&page=1&size=10

响应:
{
    "code": 200,
    "data": {
        "list": [
            {
                "id": 1,
                "title": "纯棉T恤",
                "price": 59.90,
                "image": "https://xxx.com/t-shirt.jpg"
            }
        ],
        "total": 100,
        "page": 1,
        "size": 10
    }
}

2. 创建订单

POST /api/orders
请求体:
{
    "items": [
        {"product_id": 1, "quantity": 2},
        {"product_id": 2, "quantity": 1}
    ],
    "address_id": 5
}

响应:
{
    "code": 200,
    "data": {
        "order_id": 123,
        "order_no": "20250315123456",
        "total_price": 179.70,
        "status": 0
    }
}

3. 发起支付

POST /api/pay
请求体:
{
    "order_id": 123
}

响应:
{
    "code": 200,
    "data": {
        "pay_params": {
            "appId": "wx...",
            "timeStamp": "1710000000",
            "nonceStr": "random",
            "package": "prepay_id=wx...",
            "signType": "MD5",
            "paySign": "signature"
        }
    }
}

2.4 本章小结

好,这一章的内容就这些。你想想看,我们做了三件事:

  • 把系统拆成了5个模块,每个模块的职责清清楚楚
  • 画出了核心表的结构和关系,数据库设计心里有底
  • 定好了接口规范,前后端开发不会打架

下一章,我们会开始搭建开发环境,真正动手写代码。嗯,到时候你会觉得,前面这些设计工作,真的太值了。