微信小程序电商实战 04:微信云开发环境搭建与数据库设计
微信小程序电商实战 01 技术选型 | 02 脚手架搭建 | 03 NutUI 配置 | 04 云开发环境 ← 本文 | 05 商品模块 | 06 购物车与订单 | 07 微信支付 | 08 用户中心 | 09 性能优化 | 10 上线部署
# 微信云开发环境
## 控制台配置
### 创建云开发环境
- 开发环境(dev)
- 生产环境(prod)
### 开通服务
- 云数据库
- 云存储
- 云函数
## 数据库设计(6张表)
### products 商品表
- 基础信息 + SKU + 图片
### categories 分类表
### users 用户表
- openid + 地址列表
### carts 购物车表
### orders 订单表
- 状态机:待付→待发→待收→完成
### order_items 订单商品表
## 云存储
### 商品图片目录结构
### 上传权限配置
## 云函数封装
### callFunction 统一封装
### 错误处理
### TypeScript 类型
## 权限配置
### 数据库读写权限
### 云存储上传权限
一、初始化云开发
1. 开通环境
在微信开发者工具中:
- 点击工具栏「云开发」按钮
- 创建环境,推荐创建两个:
wxshop-dev(开发)和wxshop-prod(生产) - 记录两个环境的 环境 ID(格式类似
wxshop-dev-xxxxxx)
2. 在 Taro 项目中初始化
// src/utils/cloud.ts
import Taro from '@tarojs/taro'
const ENV_ID = import.meta.env.VITE_CLOUD_ENV
let isInited = false
export function initCloud() {
if (isInited) return
// @ts-ignore — wx 对象在小程序运行时环境存在
wx.cloud.init({
env: ENV_ID,
traceUser: true,
})
isInited = true
}
在 app.ts 的 onLaunch 中调用:
// src/app.ts
import { initCloud } from '@/utils/cloud'
// app.vue 的 onLaunch
onLaunch() {
initCloud()
}
二、数据库设计
云数据库是 MongoDB-like 的文档数据库,无需预先定义 Schema,但规划好结构对后续开发很重要。
flowchart LR
A[users] -->|1:N| B[orders]
B -->|1:N| C[order_items]
C -->|N:1| D[products]
D -->|N:1| E[categories]
A -->|1:1| F[carts]
F -->|引用| D
collections/products — 商品表
{
"_id": "prod_001",
"name": "经典白T恤",
"categoryId": "cat_001",
"price": 199,
"originalPrice": 299,
"coverImage": "cloud://wxshop-dev.xxx/products/prod_001/cover.jpg",
"images": ["cloud://...", "cloud://..."],
"description": "商品详细描述(富文本/图片列表)",
"stock": 100,
"soldCount": 256,
"status": 1,
"skuTree": [
{ "k": "颜色", "k_s": "s1", "v": [{ "id": 1, "name": "白色" }, { "id": 2, "name": "黑色" }] },
{ "k": "尺寸", "k_s": "s2", "v": [{ "id": 10, "name": "S" }, { "id": 11, "name": "M" }] }
],
"skuList": [
{ "skuId": "sku_001", "s1": 1, "s2": 10, "price": 199, "stock": 50, "image": "" }
],
"createdAt": "2026-01-01T00:00:00Z",
"updatedAt": "2026-06-01T00:00:00Z"
}
collections/categories — 分类表
{
"_id": "cat_001",
"name": "上衣",
"icon": "cloud://...",
"sort": 1,
"parentId": null
}
collections/users — 用户表
{
"_id": "user_001",
"_openid": "oXXXXX...",
"nickName": "张三",
"avatarUrl": "https://...",
"phone": "138xxxx1234",
"addresses": [
{
"id": "addr_001",
"name": "张三",
"phone": "138xxxx1234",
"province": "广东省",
"city": "深圳市",
"district": "南山区",
"detail": "科技园南区xx栋",
"isDefault": true
}
],
"createdAt": "2026-01-01T00:00:00Z"
}
collections/orders — 订单表
{
"_id": "order_202601010001",
"_openid": "oXXXXX...",
"orderNo": "20260101000001",
"status": 1,
"statusText": "待付款",
"totalAmount": 398,
"shippingAmount": 0,
"address": { /* 快照,不引用原始地址 */ },
"prepayId": "",
"transactionId": "",
"payTime": null,
"shipTime": null,
"receiveTime": null,
"createdAt": "2026-06-01T10:00:00Z",
"updatedAt": "2026-06-01T10:00:00Z"
}
订单状态机:
stateDiagram-v2
[*] --> 待付款: 创建订单
待付款 --> 已取消: 超时/主动取消
待付款 --> 待发货: 支付成功
待发货 --> 待收货: 商家发货
待收货 --> 已完成: 确认收货
待收货 --> 售后中: 申请退货
已完成 --> 售后中: 申请售后
售后中 --> 已退款: 审核通过
已取消 --> [*]
已完成 --> [*]
已退款 --> [*]
collections/order_items — 订单商品表
{
"_id": "oi_001",
"orderId": "order_202601010001",
"_openid": "oXXXXX...",
"productId": "prod_001",
"skuId": "sku_001",
"productName": "经典白T恤",
"skuDesc": "白色 / M",
"coverImage": "cloud://...",
"price": 199,
"quantity": 2,
"totalPrice": 398
}
三、云存储目录结构
cloud://wxshop-dev.xxx/
├── products/
│ ├── {productId}/
│ │ ├── cover.jpg # 封面图(600x600)
│ │ ├── detail-1.jpg # 详情图
│ │ └── detail-2.jpg
├── avatars/
│ └── {openid}.jpg
└── banners/
└── banner-1.jpg
在云开发控制台 → 存储 → 权限设置中,将权限设为「所有用户可读,仅创建者可写」。
四、数据库权限配置
在云开发控制台 → 数据库 → 对应集合 → 权限设置:
| 集合 | 权限模式 | 说明 |
|---|---|---|
| products | 所有用户可读,仅管理端可写 | 商品信息公开 |
| categories | 所有用户可读,仅管理端可写 | 分类公开 |
| users | 仅创建者可读写 | 用户隐私 |
| carts | 仅创建者可读写 | 购物车隐私 |
| orders | 仅创建者可读,云函数写 | 订单用云函数操作 |
| order_items | 仅创建者可读,云函数写 | 同上 |
五、封装云函数调用层
统一封装,方便后续 Mock 和错误处理:
// src/api/cloud.ts
import Taro from '@tarojs/taro'
interface CloudResult<T = any> {
data: T
errMsg: string
}
export async function callCloud<T = any>(name: string, data: Record<string, any> = {}): Promise<T> {
const res = await Taro.cloud.callFunction({
name,
data,
}) as CloudResult<T>
if (res.errMsg !== 'cloud.callFunction:ok') {
throw new Error(res.errMsg)
}
return res.data
}
// src/api/product.ts
import { callCloud } from './cloud'
import type { Product } from '@/types/product'
export const getProductList = (params: { categoryId?: string; page: number; pageSize: number }) =>
callCloud<{ list: Product[]; total: number }>('product', { action: 'list', ...params })
export const getProductDetail = (id: string) =>
callCloud<Product>('product', { action: 'detail', id })
六、创建第一个云函数
在 cloudfunctions/ 目录下创建 product 云函数:
cloudfunctions/
└── product/
├── index.js
└── package.json
// cloudfunctions/product/index.js
const cloud = require('wx-server-sdk')
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV })
const db = cloud.database()
exports.main = async (event) => {
const { action } = event
if (action === 'list') {
const { categoryId, page = 1, pageSize = 10 } = event
const query = db.collection('products').where({ status: 1 })
if (categoryId) query.where({ categoryId })
const [countRes, listRes] = await Promise.all([
query.count(),
query.skip((page - 1) * pageSize).limit(pageSize).get(),
])
return { list: listRes.data, total: countRes.total }
}
if (action === 'detail') {
const res = await db.collection('products').doc(event.id).get()
return res.data
}
return { error: 'unknown action' }
}
在微信开发者工具中右键 cloudfunctions/product → 「上传并部署」。
微信小程序电商实战 01 技术选型 | 02 脚手架搭建 | 03 NutUI 配置 | 04 云开发环境 ← 本文 | 05 商品模块 | 06 购物车与订单 | 07 微信支付 | 08 用户中心 | 09 性能优化 | 10 上线部署
实操清单
- 在微信开发者工具开通云开发,创建 dev 和 prod 两个环境,记录环境 ID
- 将环境 ID 填入
.env.development和.env.production - 在
app.vue的onLaunch中调用initCloud(),运行后控制台无报错 - 在云数据库控制台创建 6 个集合:products、categories、users、carts、orders、order_items
- 按本文设计配置各集合的读写权限
- 在 products 集合手动插入一条测试商品数据
- 配置云存储权限为「所有用户可读,仅创建者可写」,上传一张测试图片
- 创建
src/api/cloud.ts统一封装callCloud() - 创建
cloudfunctions/product/index.js,实现 list 和 detail action - 在微信开发者工具中上传部署 product 云函数
- 在小程序端调用
getProductList()并打印结果,验证云函数调用通路畅通