furniture-3d-system-Wu/docs/migration-guide.md
WuYongJie ff41839238 feat: 实现Apple风格UI系统和产品上传功能
- 完整实现Apple HIG 2025设计系统
- 添加Modal弹窗组件(毛玻璃效果、流畅动画)
- 添加FileUpload文件上传组件(拖拽、批量上传、进度显示)
- 实现产品上传功能(支持DWG/GLB/GLTF文件)
- 优化产品列表展示(可折叠的产品+SKU结构)
- 实现Tab切换功能(3D模型管理、五金件、BOM、文档)
- 修复主题系统hydration错误
- 优化按钮和间距,符合Apple设计规范
- 添加分享页面的Apple风格重设计
- 创建测试数据脚本
2025-12-12 20:16:41 +08:00

5.6 KiB
Raw Blame History

数据库迁移指南:Product-SKU 结构

概述

本指南说明如何从当前的单一Product结构迁移到Product-SKU结构。

迁移前准备

1. 备份当前数据库

# 导出当前数据
pg_dump -U postgres -d furniture_3d > backup_$(date +%Y%m%d).sql

2. 检查当前数据

-- 查看当前产品数量
SELECT COUNT(*) FROM "Product";

-- 查看产品示例
SELECT id, name, sku, category FROM "Product" LIMIT 5;

迁移步骤

步骤 1: 应用新的Schema

# 1. 备份当前schema
cp prisma/schema.prisma prisma/schema-old.prisma

# 2. 替换为新schema
cp prisma/schema-new.prisma prisma/schema.prisma

# 3. 生成迁移文件
npx prisma migrate dev --name add_product_sku_structure --create-only

# 4. 查看生成的迁移SQL
cat prisma/migrations/[timestamp]_add_product_sku_structure/migration.sql

步骤 2: 自定义迁移SQL

编辑生成的迁移文件,添加数据迁移逻辑:

-- 迁移文件示例
-- prisma/migrations/[timestamp]_add_product_sku_structure/migration.sql

-- 1. 创建新表
CREATE TABLE "ProductSKU" (
  "id" TEXT NOT NULL,
  "productId" TEXT NOT NULL,
  "skuCode" TEXT NOT NULL,
  "attributes" JSONB NOT NULL,
  "price" DECIMAL(10,2) NOT NULL,
  "costPrice" DECIMAL(10,2),
  "stock" INTEGER NOT NULL DEFAULT 0,
  "images" TEXT[],
  "modelUrl" TEXT,
  "isActive" BOOLEAN NOT NULL DEFAULT true,
  "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  "updatedAt" TIMESTAMP(3) NOT NULL,
  
  CONSTRAINT "ProductSKU_pkey" PRIMARY KEY ("id")
);

-- 2. 修改Product表
ALTER TABLE "Product" RENAME COLUMN "sku" TO "modelNumber";
ALTER TABLE "Product" ADD COLUMN "description" TEXT;
ALTER TABLE "Product" ALTER COLUMN "category" DROP NOT NULL;

-- 3. 数据迁移:为每个现有Product创建默认SKU
INSERT INTO "ProductSKU" (
  "id",
  "productId",
  "skuCode",
  "attributes",
  "price",
  "stock",
  "images",
  "modelUrl",
  "isActive",
  "createdAt",
  "updatedAt"
)
SELECT 
  gen_random_uuid()::text,
  p."id",
  p."modelNumber" || '-DEFAULT',
  '{"variant": "默认规格"}'::jsonb,
  0.00,
  0,
  CASE WHEN p."thumbnailUrl" IS NOT NULL 
    THEN ARRAY[p."thumbnailUrl"] 
    ELSE ARRAY[]::text[] 
  END,
  p."modelUrl",
  true,
  p."createdAt",
  p."updatedAt"
FROM "Product" p;

-- 4. 创建索引
CREATE UNIQUE INDEX "ProductSKU_skuCode_key" ON "ProductSKU"("skuCode");
CREATE INDEX "ProductSKU_productId_idx" ON "ProductSKU"("productId");
CREATE INDEX "ProductSKU_isActive_idx" ON "ProductSKU"("isActive");
CREATE INDEX "Product_modelNumber_idx" ON "Product"("modelNumber");
CREATE INDEX "Product_category_idx" ON "Product"("category");

-- 5. 添加外键约束
ALTER TABLE "ProductSKU" ADD CONSTRAINT "ProductSKU_productId_fkey" 
  FOREIGN KEY ("productId") REFERENCES "Product"("id") ON DELETE CASCADE ON UPDATE CASCADE;

步骤 3: 执行迁移

# 执行迁移
npx prisma migrate deploy

# 生成Prisma Client
npx prisma generate

步骤 4: 验证迁移

-- 验证Product表
SELECT COUNT(*) FROM "Product";

-- 验证ProductSKU表
SELECT COUNT(*) FROM "ProductSKU";

-- 验证每个Product都有至少一个SKU
SELECT 
  p."id",
  p."name",
  p."modelNumber",
  COUNT(s."id") as sku_count
FROM "Product" p
LEFT JOIN "ProductSKU" s ON p."id" = s."productId"
GROUP BY p."id", p."name", p."modelNumber"
HAVING COUNT(s."id") = 0;  -- 应该返回0行

-- 查看迁移后的数据示例
SELECT 
  p."modelNumber",
  p."name",
  s."skuCode",
  s."attributes",
  s."price"
FROM "Product" p
JOIN "ProductSKU" s ON p."id" = s."productId"
LIMIT 5;

回滚方案

如果迁移出现问题,可以回滚:

# 1. 恢复旧schema
cp prisma/schema-old.prisma prisma/schema.prisma

# 2. 从备份恢复数据库
psql -U postgres -d furniture_3d < backup_[date].sql

# 3. 重新生成Prisma Client
npx prisma generate

应用代码更新

1. 更新API Endpoints

旧代码(单一Product)

// 获取产品列表
const products = await prisma.product.findMany({
  include: {
    assemblySteps: true,
    shareLinks: true
  }
})

新代码(Product-SKU)

// 获取产品列表(包含SKU信息)
const products = await prisma.product.findMany({
  include: {
    skus: {
      where: { isActive: true }
    },
    assemblySteps: true,
    shareLinks: true,
    _count: {
      select: { skus: true }
    }
  }
})

2. 更新UI组件

ProductListItem 组件更新

// 旧版本
interface ProductListItemProps {
  product: {
    id: string
    name: string
    sku: string
    category: string
  }
}

// 新版本
interface ProductListItemProps {
  product: {
    id: string
    modelNumber: string
    name: string
    category: string
    _count: {
      skus: number
    }
    skus: Array<{
      skuCode: string
      price: number
      stock: number
    }>
  }
}

测试清单

  • 产品列表显示正常
  • 产品详情页显示所有SKU
  • SKU选择器工作正常
  • 价格和库存显示正确
  • 装配步骤仍然可用
  • 分享链接功能正常
  • 3D模型加载正常
  • 搜索功能支持型号和SKU搜索

注意事项

  1. 数据一致性:确保每个Product至少有一个active的SKU
  2. 性能优化:在productId和skuCode上创建索引
  3. API兼容性:考虑保留旧API一段时间,逐步迁移
  4. 前端缓存:清除前端缓存,避免使用旧数据结构
  5. 监控:迁移后密切监控错误日志和性能指标

下一步

  1. 实现SKU管理界面
  2. 添加批量导入SKU功能
  3. 实现SKU规格筛选
  4. 优化产品搜索(支持SKU搜索)
  5. 添加库存预警功能