Skip to content

design - 设计命令

design 命令是 Claude Code 的智能系统设计工具,帮助开发者创建清晰的架构设计、接口规范和系统文档。

命令概述

design 命令提供:

  • 系统架构设计
  • 数据库模型设计
  • API 接口设计
  • UI/UX 设计规范
  • 技术方案设计

基本用法

创建新设计

bash
# 完整系统设计
claude design --type system --name "用户管理系统"

# API 设计
claude design --type api --name "用户API" --version v1

# 数据库设计
claude design --type database --name "用户数据模型"

# UI 组件设计
claude design --type component --name "用户资料卡片"

基于现有代码设计

bash
# 从现有代码生成设计文档
claude design --from-code ./src/components/UserProfile.jsx

# 逆向工程整个模块
claude design --reverse-engineer ./src/modules/user-management

配置选项

基础选项

选项类型默认值描述
--typestringsystem设计类型
--formatstringmarkdown输出格式
--detailstringstandard详细程度
--interactivebooleanfalse交互式设计模式

输出选项

选项类型默认值描述
--outputstring./docs/design输出目录
--templatestring-使用的模板
--diagramsbooleantrue生成图表
--examplesbooleantrue包含示例代码

设计类型详解

1. 系统架构设计

微服务架构设计

bash
# 设计微服务架构
claude design --type system --architecture microservices --name "电商平台"

生成的架构文档:

markdown
# 电商平台系统架构设计

## 1. 架构概览

### 整体架构
```mermaid
graph TB
    subgraph "客户端层"
        WebApp[Web应用]
        MobileApp[移动应用]
        AdminPanel[管理后台]
    end
    
    subgraph "网关层"
        APIGateway[API网关]
        LoadBalancer[负载均衡器]
    end
    
    subgraph "服务层"
        UserService[用户服务]
        ProductService[商品服务]
        OrderService[订单服务]
        PaymentService[支付服务]
        NotificationService[通知服务]
    end
    
    subgraph "数据层"
        UserDB[(用户数据库)]
        ProductDB[(商品数据库)]
        OrderDB[(订单数据库)]
        Cache[(Redis缓存)]
    end
    
    subgraph "基础设施"
        MessageQueue[消息队列]
        FileStorage[文件存储]
        LogCenter[日志中心]
        Monitor[监控中心]
    end
    
    WebApp --> APIGateway
    MobileApp --> APIGateway
    AdminPanel --> APIGateway
    
    APIGateway --> LoadBalancer
    LoadBalancer --> UserService
    LoadBalancer --> ProductService
    LoadBalancer --> OrderService
    LoadBalancer --> PaymentService
    
    UserService --> UserDB
    ProductService --> ProductDB
    OrderService --> OrderDB
    OrderService --> PaymentService
    
    UserService --> Cache
    ProductService --> Cache
    
    OrderService --> MessageQueue
    PaymentService --> MessageQueue
    NotificationService --> MessageQueue

服务详细设计

用户服务 (User Service)

职责: 用户身份认证、用户信息管理、权限控制

技术栈:

  • 框架: Spring Boot 3.0
  • 数据库: PostgreSQL
  • 缓存: Redis
  • 消息队列: RabbitMQ

核心功能:

  • 用户注册/登录
  • 用户信息CRUD
  • 权限管理
  • 身份验证

API 端点:

POST   /api/v1/users/register     # 用户注册
POST   /api/v1/users/login        # 用户登录
GET    /api/v1/users/profile      # 获取用户信息
PUT    /api/v1/users/profile      # 更新用户信息
DELETE /api/v1/users/{id}         # 删除用户

数据模型:

sql
CREATE TABLE users (
    id BIGSERIAL PRIMARY KEY,
    email VARCHAR(255) UNIQUE NOT NULL,
    password_hash VARCHAR(255) NOT NULL,
    username VARCHAR(100) UNIQUE NOT NULL,
    first_name VARCHAR(100),
    last_name VARCHAR(100),
    phone VARCHAR(20),
    avatar_url VARCHAR(255),
    status VARCHAR(20) DEFAULT 'active',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

商品服务 (Product Service)

职责: 商品信息管理、分类管理、库存管理

核心功能:

  • 商品CRUD操作
  • 分类管理
  • 库存管理
  • 价格管理

事件发布:

  • ProductCreated
  • ProductUpdated
  • StockChanged
  • PriceChanged

通信模式

同步通信 (HTTP/REST)

  • 用户查询个人信息
  • 商品信息查询
  • 实时数据获取

异步通信 (消息队列)

  • 订单创建通知
  • 库存更新
  • 邮件发送
  • 数据同步

数据一致性策略

最终一致性

对于非关键业务数据,采用最终一致性:

  • 用户信息更新
  • 商品信息同步
  • 日志记录

强一致性

对于关键业务数据,采用强一致性:

  • 订单创建
  • 支付处理
  • 库存扣减

容错设计

熔断器模式

java
@Component
public class PaymentServiceClient {
    
    @CircuitBreaker(name = "payment-service", fallbackMethod = "fallbackPayment")
    public PaymentResult processPayment(PaymentRequest request) {
        return paymentServiceCall(request);
    }
    
    public PaymentResult fallbackPayment(PaymentRequest request, Exception ex) {
        return PaymentResult.failed("服务暂时不可用,请稍后重试");
    }
}

重试机制

yaml
resilience4j:
  retry:
    instances:
      payment-service:
        max-attempts: 3
        wait-duration: 1s
        exponential-backoff-multiplier: 2

性能设计

缓存策略

  • L1缓存: 本地缓存 (Caffeine)
  • L2缓存: 分布式缓存 (Redis)
  • CDN缓存: 静态资源缓存

数据库优化

  • 读写分离
  • 分库分表
  • 索引优化
  • 连接池配置

安全设计

身份认证

  • JWT Token 认证
  • OAuth2 集成
  • 双因素认证

数据安全

  • 数据加密存储
  • 传输加密 (TLS)
  • 敏感信息脱敏

监控设计

应用监控

  • Prometheus + Grafana
  • 自定义业务指标
  • 告警规则配置

日志管理

  • ELK Stack (Elasticsearch + Logstash + Kibana)
  • 结构化日志
  • 分布式链路追踪

2. 部署架构

容器化部署

yaml
# docker-compose.yml
version: '3.8'
services:
  user-service:
    image: ecommerce/user-service:latest
    ports:
      - "8081:8080"
    environment:
      - SPRING_PROFILES_ACTIVE=prod
      - DATABASE_URL=postgresql://postgres:5432/userdb
    depends_on:
      - postgres
      - redis
      
  product-service:
    image: ecommerce/product-service:latest
    ports:
      - "8082:8080"
    environment:
      - SPRING_PROFILES_ACTIVE=prod
      - DATABASE_URL=postgresql://postgres:5432/productdb

Kubernetes 部署

yaml
# k8s-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: user-service
spec:
  replicas: 3
  selector:
    matchLabels:
      app: user-service
  template:
    metadata:
      labels:
        app: user-service
    spec:
      containers:
      - name: user-service
        image: ecommerce/user-service:latest
        ports:
        - containerPort: 8080
        env:
        - name: DATABASE_URL
          valueFrom:
            secretKeyRef:
              name: db-secret
              key: url

3. 技术决策记录

ADR-001: 选择微服务架构

状态: 已接受 决策日期: 2024-01-15

背景: 需要构建一个可扩展的电商平台

决策: 采用微服务架构

理由:

  • 团队规模较大 (30+ 开发者)
  • 不同业务模块有不同的扩展需求
  • 希望使用不同的技术栈
  • 需要独立部署和发布

后果:

  • 增加了系统复杂性
  • 需要额外的基础设施
  • 网络通信开销
  • 数据一致性挑战

ADR-002: 选择 PostgreSQL 作为主数据库

状态: 已接受
决策日期: 2024-01-16

背景: 需要选择合适的数据库技术

决策: 使用 PostgreSQL 作为主要关系型数据库

理由:

  • 优秀的 ACID 特性
  • 丰富的数据类型支持
  • 强大的查询优化器
  • 活跃的社区支持

4. 风险评估与缓解

高风险项

  1. 服务间通信失败

    • 风险: 服务不可用导致业务中断
    • 缓解: 实现熔断器和降级策略
  2. 数据一致性问题

    • 风险: 分布式事务失败
    • 缓解: 使用Saga模式和补偿事务
  3. 性能瓶颈

    • 风险: 高并发下系统性能下降
    • 缓解: 实施缓存策略和负载均衡

中等风险项

  1. 技术栈多样性

    • 风险: 维护成本增加
    • 缓解: 制定技术标准和培训计划
  2. 运维复杂性

    • 风险: 部署和监控复杂
    • 缓解: 自动化工具和标准化流程

#### 单体架构设计
```bash
# 设计单体应用架构
claude design --type system --architecture monolith --name "内容管理系统"

2. API 接口设计

RESTful API 设计

bash
# 设计RESTful API
claude design --type api --style rest --name "用户管理API"

生成的API设计文档:

markdown
# 用户管理API设计文档

## API 概览

### 基础信息
- **Base URL**: `https://api.example.com/v1`
- **认证方式**: Bearer Token (JWT)
- **数据格式**: JSON
- **字符编码**: UTF-8

### 设计原则
1. **RESTful**: 遵循REST架构风格
2. **一致性**: 统一的命名和响应格式
3. **版本控制**: 通过URL路径进行版本管理
4. **安全性**: 完善的认证和授权机制

## 资源设计

### 用户资源 (Users)

#### 1. 创建用户
```http
POST /v1/users
Content-Type: application/json
Authorization: Bearer {token}

{
  "email": "user@example.com",
  "password": "securePassword123",
  "username": "johndoe",
  "profile": {
    "firstName": "John",
    "lastName": "Doe",
    "phone": "+1234567890"
  }
}

响应:

json
{
  "success": true,
  "data": {
    "id": 12345,
    "email": "user@example.com",
    "username": "johndoe",
    "profile": {
      "firstName": "John",
      "lastName": "Doe",
      "phone": "+1234567890",
      "avatar": null
    },
    "status": "active",
    "createdAt": "2024-01-20T10:30:00Z",
    "updatedAt": "2024-01-20T10:30:00Z"
  },
  "meta": {
    "version": "v1",
    "timestamp": "2024-01-20T10:30:00Z"
  }
}

2. 获取用户列表

http
GET /v1/users?page=1&limit=20&status=active&sort=createdAt:desc
Authorization: Bearer {token}

查询参数:

参数类型必需默认值描述
pageinteger1页码
limitinteger20每页数量 (最大100)
statusstring-用户状态筛选
sortstringcreatedAt:desc排序字段和方向
searchstring-搜索关键词

响应:

json
{
  "success": true,
  "data": {
    "users": [
      {
        "id": 12345,
        "email": "user@example.com",
        "username": "johndoe",
        "profile": {
          "firstName": "John",
          "lastName": "Doe"
        },
        "status": "active",
        "createdAt": "2024-01-20T10:30:00Z"
      }
    ],
    "pagination": {
      "currentPage": 1,
      "perPage": 20,
      "total": 150,
      "totalPages": 8,
      "hasNext": true,
      "hasPrev": false
    }
  }
}

错误处理设计

标准错误响应

json
{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "输入数据验证失败",
    "details": [
      {
        "field": "email",
        "message": "邮箱格式无效",
        "code": "INVALID_FORMAT"
      },
      {
        "field": "password",
        "message": "密码长度不能少于8位",
        "code": "TOO_SHORT"
      }
    ],
    "timestamp": "2024-01-20T10:30:00Z",
    "requestId": "req_1234567890"
  }
}

HTTP状态码使用

状态码含义使用场景
200OK成功获取资源
201Created成功创建资源
204No Content成功删除资源
400Bad Request请求参数错误
401Unauthorized未认证
403Forbidden权限不足
404Not Found资源不存在
409Conflict资源冲突
422Unprocessable Entity语义错误
429Too Many Requests请求频率限制
500Internal Server Error服务器内部错误

认证和授权

JWT Token 结构

json
{
  "header": {
    "alg": "HS256",
    "typ": "JWT"
  },
  "payload": {
    "sub": "12345",
    "username": "johndoe",
    "email": "user@example.com",
    "role": "user",
    "permissions": ["read:profile", "write:profile"],
    "iat": 1642680000,
    "exp": 1642683600
  }
}

权限控制

http
# 需要特定权限的端点
GET /v1/admin/users
Authorization: Bearer {token}
Required-Permission: read:all_users

API 版本控制

URL版本控制

/v1/users     # 版本1
/v2/users     # 版本2

版本兼容性

  • 向后兼容: 新版本保持对旧版本的兼容
  • 废弃通知: 提前通知版本废弃计划
  • 迁移指南: 提供版本升级指南

速率限制

限制策略

http
# 响应头
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1642680000
X-RateLimit-Window: 3600

限制级别

  • 用户级别: 每个用户的请求限制
  • IP级别: 每个IP地址的请求限制
  • 端点级别: 特定端点的请求限制

文档和SDK

自动化文档生成

  • OpenAPI 3.0 规范
  • Swagger UI 界面
  • 代码示例生成

SDK支持

javascript
// JavaScript SDK 示例
import { UserAPI } from '@example/api-client';

const userAPI = new UserAPI({
  baseURL: 'https://api.example.com/v1',
  apiKey: 'your-api-key'
});

// 创建用户
const user = await userAPI.createUser({
  email: 'user@example.com',
  password: 'password123',
  profile: {
    firstName: 'John',
    lastName: 'Doe'
  }
});

// 获取用户列表
const users = await userAPI.getUsers({
  page: 1,
  limit: 20,
  status: 'active'
});

### 3. 数据库设计

#### 关系型数据库设计
```bash
# 设计数据库模型
claude design --type database --engine postgresql --name "电商数据模型"

生成的数据库设计:

sql
-- 电商数据模型设计
-- 数据库: PostgreSQL 15+
-- 字符集: UTF8
-- 排序规则: zh_CN.UTF-8

-- 用户表
CREATE TABLE users (
    id BIGSERIAL PRIMARY KEY,
    email VARCHAR(255) UNIQUE NOT NULL,
    username VARCHAR(100) UNIQUE NOT NULL,
    password_hash VARCHAR(255) NOT NULL,
    salt VARCHAR(32) NOT NULL,
    first_name VARCHAR(100),
    last_name VARCHAR(100),
    phone VARCHAR(20),
    date_of_birth DATE,
    gender VARCHAR(10) CHECK (gender IN ('male', 'female', 'other')),
    avatar_url VARCHAR(255),
    status VARCHAR(20) DEFAULT 'active' CHECK (status IN ('active', 'inactive', 'suspended', 'deleted')),
    email_verified BOOLEAN DEFAULT FALSE,
    phone_verified BOOLEAN DEFAULT FALSE,
    last_login_at TIMESTAMP,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 用户地址表
CREATE TABLE user_addresses (
    id BIGSERIAL PRIMARY KEY,
    user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    type VARCHAR(20) DEFAULT 'shipping' CHECK (type IN ('shipping', 'billing')),
    is_default BOOLEAN DEFAULT FALSE,
    recipient_name VARCHAR(100) NOT NULL,
    phone VARCHAR(20),
    country VARCHAR(100) NOT NULL,
    province VARCHAR(100),
    city VARCHAR(100) NOT NULL,
    district VARCHAR(100),
    street_address TEXT NOT NULL,
    postal_code VARCHAR(20),
    latitude DECIMAL(10, 8),
    longitude DECIMAL(11, 8),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 商品分类表
CREATE TABLE categories (
    id BIGSERIAL PRIMARY KEY,
    parent_id BIGINT REFERENCES categories(id) ON DELETE SET NULL,
    name VARCHAR(100) NOT NULL,
    slug VARCHAR(100) UNIQUE NOT NULL,
    description TEXT,
    image_url VARCHAR(255),
    sort_order INTEGER DEFAULT 0,
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 商品表
CREATE TABLE products (
    id BIGSERIAL PRIMARY KEY,
    category_id BIGINT REFERENCES categories(id) ON DELETE SET NULL,
    sku VARCHAR(100) UNIQUE NOT NULL,
    name VARCHAR(200) NOT NULL,
    slug VARCHAR(200) UNIQUE NOT NULL,
    description TEXT,
    short_description VARCHAR(500),
    price DECIMAL(10, 2) NOT NULL CHECK (price >= 0),
    compare_price DECIMAL(10, 2) CHECK (compare_price >= price),
    cost_price DECIMAL(10, 2),
    weight DECIMAL(8, 3),
    dimensions JSONB, -- {length: 10, width: 5, height: 3}
    status VARCHAR(20) DEFAULT 'active' CHECK (status IN ('active', 'inactive', 'draft', 'archived')),
    visibility VARCHAR(20) DEFAULT 'public' CHECK (visibility IN ('public', 'private', 'hidden')),
    track_inventory BOOLEAN DEFAULT TRUE,
    inventory_quantity INTEGER DEFAULT 0 CHECK (inventory_quantity >= 0),
    allow_backorder BOOLEAN DEFAULT FALSE,
    requires_shipping BOOLEAN DEFAULT TRUE,
    is_digital BOOLEAN DEFAULT FALSE,
    meta_title VARCHAR(200),
    meta_description VARCHAR(500),
    tags TEXT[], -- PostgreSQL数组类型
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 商品图片表
CREATE TABLE product_images (
    id BIGSERIAL PRIMARY KEY,
    product_id BIGINT NOT NULL REFERENCES products(id) ON DELETE CASCADE,
    url VARCHAR(255) NOT NULL,
    alt_text VARCHAR(200),
    sort_order INTEGER DEFAULT 0,
    is_primary BOOLEAN DEFAULT FALSE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 商品属性表
CREATE TABLE product_attributes (
    id BIGSERIAL PRIMARY KEY,
    product_id BIGINT NOT NULL REFERENCES products(id) ON DELETE CASCADE,
    name VARCHAR(100) NOT NULL,
    value TEXT NOT NULL,
    sort_order INTEGER DEFAULT 0,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 订单表
CREATE TABLE orders (
    id BIGSERIAL PRIMARY KEY,
    order_number VARCHAR(50) UNIQUE NOT NULL,
    user_id BIGINT REFERENCES users(id) ON DELETE SET NULL,
    status VARCHAR(20) DEFAULT 'pending' CHECK (status IN ('pending', 'confirmed', 'processing', 'shipped', 'delivered', 'cancelled', 'refunded')),
    payment_status VARCHAR(20) DEFAULT 'pending' CHECK (payment_status IN ('pending', 'paid', 'failed', 'refunded', 'partially_refunded')),
    fulfillment_status VARCHAR(20) DEFAULT 'unfulfilled' CHECK (fulfillment_status IN ('unfulfilled', 'partial', 'fulfilled')),
    
    -- 金额信息
    subtotal DECIMAL(10, 2) NOT NULL DEFAULT 0,
    tax_amount DECIMAL(10, 2) DEFAULT 0,
    shipping_amount DECIMAL(10, 2) DEFAULT 0,
    discount_amount DECIMAL(10, 2) DEFAULT 0,
    total_amount DECIMAL(10, 2) NOT NULL DEFAULT 0,
    
    -- 地址信息 (JSON存储,避免外键依赖)
    billing_address JSONB,
    shipping_address JSONB,
    
    -- 其他信息
    notes TEXT,
    customer_notes TEXT,
    processed_at TIMESTAMP,
    shipped_at TIMESTAMP,
    delivered_at TIMESTAMP,
    cancelled_at TIMESTAMP,
    cancel_reason TEXT,
    
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 订单商品表
CREATE TABLE order_items (
    id BIGSERIAL PRIMARY KEY,
    order_id BIGINT NOT NULL REFERENCES orders(id) ON DELETE CASCADE,
    product_id BIGINT REFERENCES products(id) ON DELETE SET NULL,
    
    -- 商品快照 (防止商品信息变更影响历史订单)
    product_name VARCHAR(200) NOT NULL,
    product_sku VARCHAR(100),
    product_image_url VARCHAR(255),
    
    quantity INTEGER NOT NULL CHECK (quantity > 0),
    unit_price DECIMAL(10, 2) NOT NULL CHECK (unit_price >= 0),
    total_price DECIMAL(10, 2) NOT NULL CHECK (total_price >= 0),
    
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 购物车表
CREATE TABLE carts (
    id BIGSERIAL PRIMARY KEY,
    user_id BIGINT REFERENCES users(id) ON DELETE CASCADE,
    session_id VARCHAR(255), -- 支持匿名用户购物车
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    CONSTRAINT cart_user_or_session CHECK (user_id IS NOT NULL OR session_id IS NOT NULL)
);

-- 购物车商品表
CREATE TABLE cart_items (
    id BIGSERIAL PRIMARY KEY,
    cart_id BIGINT NOT NULL REFERENCES carts(id) ON DELETE CASCADE,
    product_id BIGINT NOT NULL REFERENCES products(id) ON DELETE CASCADE,
    quantity INTEGER NOT NULL CHECK (quantity > 0),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    UNIQUE(cart_id, product_id)
);

-- 支付记录表
CREATE TABLE payments (
    id BIGSERIAL PRIMARY KEY,
    order_id BIGINT NOT NULL REFERENCES orders(id) ON DELETE CASCADE,
    payment_method VARCHAR(50) NOT NULL, -- 'credit_card', 'paypal', 'alipay', etc.
    payment_provider VARCHAR(50), -- 'stripe', 'paypal', 'alipay', etc.
    transaction_id VARCHAR(255),
    amount DECIMAL(10, 2) NOT NULL CHECK (amount > 0),
    currency VARCHAR(3) DEFAULT 'CNY',
    status VARCHAR(20) DEFAULT 'pending' CHECK (status IN ('pending', 'processing', 'succeeded', 'failed', 'cancelled', 'refunded')),
    failure_reason TEXT,
    metadata JSONB, -- 存储支付提供商返回的额外数据
    processed_at TIMESTAMP,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 优惠券表
CREATE TABLE coupons (
    id BIGSERIAL PRIMARY KEY,
    code VARCHAR(50) UNIQUE NOT NULL,
    name VARCHAR(100) NOT NULL,
    description TEXT,
    type VARCHAR(20) NOT NULL CHECK (type IN ('percentage', 'fixed_amount', 'free_shipping')),
    value DECIMAL(10, 2) NOT NULL CHECK (value > 0),
    minimum_amount DECIMAL(10, 2) DEFAULT 0,
    usage_limit INTEGER, -- 总使用次数限制
    usage_limit_per_customer INTEGER DEFAULT 1, -- 每个客户使用次数限制
    used_count INTEGER DEFAULT 0,
    is_active BOOLEAN DEFAULT TRUE,
    starts_at TIMESTAMP,
    expires_at TIMESTAMP,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 优惠券使用记录表
CREATE TABLE coupon_usages (
    id BIGSERIAL PRIMARY KEY,
    coupon_id BIGINT NOT NULL REFERENCES coupons(id) ON DELETE CASCADE,
    order_id BIGINT NOT NULL REFERENCES orders(id) ON DELETE CASCADE,
    user_id BIGINT REFERENCES users(id) ON DELETE SET NULL,
    discount_amount DECIMAL(10, 2) NOT NULL,
    used_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    UNIQUE(coupon_id, order_id)
);

-- 评论表
CREATE TABLE reviews (
    id BIGSERIAL PRIMARY KEY,
    product_id BIGINT NOT NULL REFERENCES products(id) ON DELETE CASCADE,
    user_id BIGINT REFERENCES users(id) ON DELETE SET NULL,
    order_item_id BIGINT REFERENCES order_items(id) ON DELETE SET NULL,
    rating INTEGER NOT NULL CHECK (rating >= 1 AND rating <= 5),
    title VARCHAR(200),
    content TEXT NOT NULL,
    is_verified_purchase BOOLEAN DEFAULT FALSE,
    is_approved BOOLEAN DEFAULT FALSE,
    helpful_count INTEGER DEFAULT 0,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 索引创建
-- 用户表索引
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_username ON users(username);
CREATE INDEX idx_users_status ON users(status);
CREATE INDEX idx_users_created_at ON users(created_at);

-- 商品表索引
CREATE INDEX idx_products_category_id ON products(category_id);
CREATE INDEX idx_products_sku ON products(sku);
CREATE INDEX idx_products_status ON products(status);
CREATE INDEX idx_products_name ON products USING gin(to_tsvector('chinese', name));
CREATE INDEX idx_products_created_at ON products(created_at);
CREATE INDEX idx_products_price ON products(price);

-- 订单表索引
CREATE INDEX idx_orders_user_id ON orders(user_id);
CREATE INDEX idx_orders_status ON orders(status);
CREATE INDEX idx_orders_created_at ON orders(created_at);
CREATE INDEX idx_orders_order_number ON orders(order_number);

-- 复合索引
CREATE INDEX idx_order_items_order_product ON order_items(order_id, product_id);
CREATE INDEX idx_cart_items_cart_product ON cart_items(cart_id, product_id);

-- 触发器函数:更新 updated_at 字段
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = CURRENT_TIMESTAMP;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- 为需要的表添加触发器
CREATE TRIGGER update_users_updated_at 
    BEFORE UPDATE ON users 
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

CREATE TRIGGER update_products_updated_at 
    BEFORE UPDATE ON products 
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

CREATE TRIGGER update_orders_updated_at 
    BEFORE UPDATE ON orders 
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

-- 视图:用户订单统计
CREATE VIEW user_order_stats AS
SELECT 
    u.id,
    u.username,
    u.email,
    COUNT(o.id) as total_orders,
    COALESCE(SUM(o.total_amount), 0) as total_spent,
    COALESCE(AVG(o.total_amount), 0) as avg_order_value,
    MAX(o.created_at) as last_order_date
FROM users u
LEFT JOIN orders o ON u.id = o.user_id AND o.status != 'cancelled'
GROUP BY u.id, u.username, u.email;

-- 存储过程:更新商品库存
CREATE OR REPLACE FUNCTION update_product_inventory(
    p_product_id BIGINT,
    p_quantity_change INTEGER
) RETURNS BOOLEAN AS $$
DECLARE
    current_quantity INTEGER;
BEGIN
    -- 获取当前库存
    SELECT inventory_quantity INTO current_quantity 
    FROM products 
    WHERE id = p_product_id;
    
    -- 检查库存是否足够
    IF current_quantity + p_quantity_change < 0 THEN
        RETURN FALSE;
    END IF;
    
    -- 更新库存
    UPDATE products 
    SET inventory_quantity = inventory_quantity + p_quantity_change,
        updated_at = CURRENT_TIMESTAMP
    WHERE id = p_product_id;
    
    RETURN TRUE;
END;
$$ LANGUAGE plpgsql;

4. UI 组件设计

React 组件设计

bash
# 设计UI组件
claude design --type component --framework react --name "用户资料卡片"

生成的组件设计:

markdown
# 用户资料卡片组件设计

## 组件概览

### 组件名称: UserProfileCard
### 用途: 展示用户基本信息和操作按钮
### 框架: React 18+ with TypeScript

## 设计规范

### 视觉设计
```css
/* 组件样式 */
.user-profile-card {
  background: #ffffff;
  border-radius: 12px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  padding: 24px;
  max-width: 400px;
  transition: box-shadow 0.2s ease;
}

.user-profile-card:hover {
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
}

.user-avatar {
  width: 80px;
  height: 80px;
  border-radius: 50%;
  object-fit: cover;
  border: 3px solid #f0f0f0;
}

.user-info {
  margin-left: 16px;
  flex: 1;
}

.user-name {
  font-size: 20px;
  font-weight: 600;
  color: #1a1a1a;
  margin: 0 0 4px 0;
}

.user-email {
  font-size: 14px;
  color: #666666;
  margin: 0 0 8px 0;
}

.user-status {
  display: inline-flex;
  align-items: center;
  padding: 4px 8px;
  border-radius: 4px;
  font-size: 12px;
  font-weight: 500;
}

.status-active {
  background: #e7f5e7;
  color: #2d7d2d;
}

.status-inactive {
  background: #ffeaea;
  color: #d32f2f;
}

组件接口

typescript
// UserProfileCard.types.ts
export interface UserProfileCardProps {
  user: User;
  size?: 'small' | 'medium' | 'large';
  showActions?: boolean;
  actions?: ActionButton[];
  onUserClick?: (user: User) => void;
  onActionClick?: (action: string, user: User) => void;
  className?: string;
  style?: React.CSSProperties;
}

export interface User {
  id: string | number;
  name: string;
  email: string;
  avatar?: string;
  status: 'active' | 'inactive' | 'suspended';
  role?: string;
  lastLoginAt?: string;
  createdAt: string;
}

export interface ActionButton {
  key: string;
  label: string;
  icon?: React.ReactNode;
  variant?: 'primary' | 'secondary' | 'danger';
  disabled?: boolean;
}

组件实现

tsx
// UserProfileCard.tsx
import React from 'react';
import { User, UserProfileCardProps, ActionButton } from './UserProfileCard.types';
import './UserProfileCard.css';

const UserProfileCard: React.FC<UserProfileCardProps> = ({
  user,
  size = 'medium',
  showActions = true,
  actions = [],
  onUserClick,
  onActionClick,
  className = '',
  style
}) => {
  const defaultActions: ActionButton[] = [
    { key: 'edit', label: '编辑', variant: 'primary' },
    { key: 'delete', label: '删除', variant: 'danger' }
  ];
  
  const finalActions = actions.length > 0 ? actions : defaultActions;
  
  const handleUserClick = () => {
    if (onUserClick) {
      onUserClick(user);
    }
  };
  
  const handleActionClick = (actionKey: string, event: React.MouseEvent) => {
    event.stopPropagation();
    if (onActionClick) {
      onActionClick(actionKey, user);
    }
  };
  
  const getStatusColor = (status: string) => {
    switch (status) {
      case 'active': return 'status-active';
      case 'inactive': return 'status-inactive';
      case 'suspended': return 'status-suspended';
      default: return 'status-inactive';
    }
  };
  
  const formatLastLogin = (lastLoginAt?: string) => {
    if (!lastLoginAt) return '从未登录';
    
    const date = new Date(lastLoginAt);
    const now = new Date();
    const diffMs = now.getTime() - date.getTime();
    const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
    
    if (diffDays === 0) return '今天';
    if (diffDays === 1) return '昨天';
    if (diffDays < 7) return `${diffDays}天前`;
    
    return date.toLocaleDateString('zh-CN');
  };
  
  return (
    <div 
      className={`user-profile-card user-profile-card--${size} ${className}`}
      style={style}
      onClick={handleUserClick}
    >
      <div className="user-profile-header">
        <img 
          src={user.avatar || '/default-avatar.png'} 
          alt={`${user.name}的头像`}
          className="user-avatar"
          onError={(e) => {
            (e.target as HTMLImageElement).src = '/default-avatar.png';
          }}
        />
        
        <div className="user-info">
          <h3 className="user-name">{user.name}</h3>
          <p className="user-email">{user.email}</p>
          <div className="user-meta">
            <span className={`user-status ${getStatusColor(user.status)}`}>
              {user.status === 'active' ? '活跃' : 
               user.status === 'inactive' ? '未激活' : '已暂停'}
            </span>
            {user.role && (
              <span className="user-role">{user.role}</span>
            )}
          </div>
        </div>
      </div>
      
      <div className="user-profile-details">
        <div className="detail-item">
          <span className="detail-label">最后登录:</span>
          <span className="detail-value">{formatLastLogin(user.lastLoginAt)}</span>
        </div>
        <div className="detail-item">
          <span className="detail-label">注册时间:</span>
          <span className="detail-value">
            {new Date(user.createdAt).toLocaleDateString('zh-CN')}
          </span>
        </div>
      </div>
      
      {showActions && finalActions.length > 0 && (
        <div className="user-profile-actions">
          {finalActions.map((action) => (
            <button
              key={action.key}
              className={`action-button action-button--${action.variant || 'secondary'}`}
              disabled={action.disabled}
              onClick={(e) => handleActionClick(action.key, e)}
            >
              {action.icon && <span className="action-icon">{action.icon}</span>}
              {action.label}
            </button>
          ))}
        </div>
      )}
    </div>
  );
};

export default UserProfileCard;

使用示例

tsx
// 基本使用
<UserProfileCard
  user={{
    id: 1,
    name: '张三',
    email: 'zhangsan@example.com',
    avatar: 'https://example.com/avatar.jpg',
    status: 'active',
    role: '管理员',
    lastLoginAt: '2024-01-20T10:30:00Z',
    createdAt: '2024-01-01T00:00:00Z'
  }}
/>

// 自定义操作
<UserProfileCard
  user={userData}
  actions={[
    { key: 'view', label: '查看详情', variant: 'primary' },
    { key: 'message', label: '发送消息', variant: 'secondary' },
    { key: 'suspend', label: '暂停用户', variant: 'danger' }
  ]}
  onActionClick={(action, user) => {
    console.log(`执行操作: ${action}`, user);
  }}
/>

// 只读模式
<UserProfileCard
  user={userData}
  showActions={false}
  onUserClick={(user) => {
    // 跳转到用户详情页
    router.push(`/users/${user.id}`);
  }}
/>

响应式设计

css
/* 响应式适配 */
@media (max-width: 768px) {
  .user-profile-card {
    padding: 16px;
    max-width: 100%;
  }
  
  .user-profile-header {
    flex-direction: column;
    text-align: center;
  }
  
  .user-info {
    margin-left: 0;
    margin-top: 12px;
  }
  
  .user-profile-actions {
    flex-direction: column;
    gap: 8px;
  }
}

@media (max-width: 480px) {
  .user-avatar {
    width: 60px;
    height: 60px;
  }
  
  .user-name {
    font-size: 18px;
  }
  
  .action-button {
    width: 100%;
  }
}

可访问性

tsx
// 可访问性增强
<div 
  className="user-profile-card"
  role="button"
  tabIndex={0}
  aria-label={`用户 ${user.name} 的资料卡片`}
  onKeyDown={(e) => {
    if (e.key === 'Enter' || e.key === ' ') {
      handleUserClick();
    }
  }}
>
  <img 
    src={user.avatar} 
    alt={`${user.name}的头像`}
    role="img"
  />
  
  <button
    className="action-button"
    aria-label={`${action.label} ${user.name}`}
    disabled={action.disabled}
  >
    {action.label}
  </button>
</div>

测试用例

tsx
// UserProfileCard.test.tsx
import { render, screen, fireEvent } from '@testing-library/react';
import UserProfileCard from './UserProfileCard';

const mockUser = {
  id: 1,
  name: '张三',
  email: 'zhangsan@example.com',
  status: 'active' as const,
  createdAt: '2024-01-01T00:00:00Z'
};

describe('UserProfileCard', () => {
  test('渲染用户基本信息', () => {
    render(<UserProfileCard user={mockUser} />);
    
    expect(screen.getByText('张三')).toBeInTheDocument();
    expect(screen.getByText('zhangsan@example.com')).toBeInTheDocument();
    expect(screen.getByText('活跃')).toBeInTheDocument();
  });
  
  test('点击用户卡片触发回调', () => {
    const onUserClick = jest.fn();
    render(<UserProfileCard user={mockUser} onUserClick={onUserClick} />);
    
    fireEvent.click(screen.getByRole('button'));
    expect(onUserClick).toHaveBeenCalledWith(mockUser);
  });
  
  test('点击操作按钮触发回调', () => {
    const onActionClick = jest.fn();
    render(
      <UserProfileCard 
        user={mockUser} 
        onActionClick={onActionClick}
        actions={[{ key: 'edit', label: '编辑', variant: 'primary' }]}
      />
    );
    
    fireEvent.click(screen.getByText('编辑'));
    expect(onActionClick).toHaveBeenCalledWith('edit', mockUser);
  });
  
  test('隐藏操作按钮', () => {
    render(<UserProfileCard user={mockUser} showActions={false} />);
    
    expect(screen.queryByText('编辑')).not.toBeInTheDocument();
    expect(screen.queryByText('删除')).not.toBeInTheDocument();
  });
});

## 相关命令

- [`analyze`](./analyze.md) - 代码分析命令
- [`build`](./build.md) - 构建命令
- [`generate`](./generate.md) - 代码生成命令

## 最佳实践

### 1. 设计原则
- 遵循单一职责原则
- 保持接口简洁明了
- 考虑扩展性和维护性

### 2. 文档完整性
- 包含详细的API文档
- 提供使用示例
- 说明设计决策和权衡

### 3. 协作效率
- 使用标准化的设计模板
- 及时同步设计变更
- 维护设计版本历史

---

*design 命令 - 将想法转化为蓝图*

Claude Code 使用指南