RaisFastRaisFast
Full-Stack Development

电商实战

构建在线商城 — 商品、购物车、订单和支付集成。

你将构建什么

一个电商商城,包含:

  • 商品目录与分类
  • 购物车(游客 + 已登录用户)
  • 结算流程
  • 订单管理
  • 支付集成

内置电商模块

RaisFast 内置了电商 API — 无需为核心电商功能定义内容类型:

模块端点描述
商品/api/v1/admin/products商品 CRUD
分类/api/v1/admin/categories商品分类
订单/api/v1/admin/orders订单管理
支付/api/v1/admin/payments支付处理
钱包/api/v1/admin/wallets用户余额

第 1 步 — 创建商品

# 创建商品分类
curl -X POST http://localhost:9898/api/v1/admin/categories \
  -H "Authorization: Bearer TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"电子产品","slug":"electronics"}'

# 创建商品
curl -X POST http://localhost:9898/api/v1/admin/products \
  -H "Authorization: Bearer TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "无线耳机",
    "slug": "wireless-headphones",
    "price": 699.00,
    "currency": "CNY",
    "stock": 50,
    "description": "高品质降噪无线耳机",
    "category_id": "CATEGORY_ID"
  }'

第 2 步 — 商品目录(前端)

import { client } from "@/lib/client";
import { useState, useEffect } from "react";

export function ProductCatalog() {
  const [products, setProducts] = useState([]);
  const [cart, setCart] = useState([]);

  useEffect(() => {
    client.setToken(localStorage.getItem("access_token")!);
    client.products.list({ page: 1, limit: 20 }).then((res) => {
      setProducts(res.data);
    });
  }, []);

  function addToCart(product) {
    setCart((prev) => {
      const existing = prev.find((item) => item.id === product.id);
      if (existing) {
        return prev.map((item) =>
          item.id === product.id
            ? { ...item, quantity: item.quantity + 1 }
            : item
        );
      }
      return [...prev, { ...product, quantity: 1 }];
    });
  }

  return (
    <div className="grid grid-cols-3 gap-6">
      {products.map((product) => (
        <div key={product.id} className="border rounded-lg p-4">
          <h3 className="font-semibold">{product.name}</h3>
          <p className="text-gray-600 text-sm mt-1">{product.description}</p>
          <div className="flex justify-between items-center mt-4">
            <span className="text-lg font-bold">¥{product.price}</span>
            <button
              onClick={() => addToCart(product)}
              className="px-4 py-2 bg-blue-600 text-white rounded"
            >
              加入购物车
            </button>
          </div>
        </div>
      ))}
    </div>
  );
}

第 3 步 — 结算流程

async function checkout(cart, shippingAddress) {
  // 1. 创建订单
  const order = await client.orders.create({
    items: cart.map((item) => ({
      product_id: item.id,
      quantity: item.quantity,
      price: item.price,
    })),
    shipping_address: shippingAddress,
  });

  // 2. 发起支付
  const payment = await client.payments.create({
    order_id: order.id,
    method: "wallet", // 或 "stripe"、"alipay" 等
  });

  return { order, payment };
}

第 4 步 — 订单管理

export function OrderHistory() {
  const [orders, setOrders] = useState([]);

  useEffect(() => {
    client.orders.list({ page: 1, limit: 20 }).then((res) => {
      setOrders(res.data);
    });
  }, []);

  return (
    <div className="space-y-4">
      {orders.map((order) => (
        <div key={order.id} className="border rounded-lg p-4">
          <div className="flex justify-between">
            <span className="font-semibold">订单 #{order.id.slice(-8)}</span>
            <span className="text-sm text-gray-500">{order.status}</span>
          </div>
          <div className="mt-2 text-sm text-gray-600">
            {order.items.length} 件商品 — ¥{order.total}
          </div>
        </div>
      ))}
    </div>
  );
}

用内容类型扩展商品字段

如果内置的商品 Schema 不够用,用内容类型扩展:

name = "ProductExtra"
table = "product_extras"
plural = "product_extras"

[fields.product_id]
type = "text"
required = true

[fields.specs]
type = "json"

[fields.weight]
type = "number"

[fields.dimensions]
type = "json"

下一步

准备好部署了吗?跟着部署指南开始。

On this page