WuYongJie 63ec6b7dfb fix: 修复排行榜按钮消失、tag排序和输入框浅色模式问题
1. 排行榜悬浮窗关闭后小按钮消失问题
   - 修复面板居中模式关闭时按钮位置错误
   - 保存并恢复按钮的居中状态

2. 首页tag按钮按素材数量排序
   - 添加按素材数量降序排序逻辑

3. 上传弹窗输入框浅色模式文字不可见
   - 添加 text-slate-900 确保浅色模式下文字可见
   - 添加 placeholder 样式确保占位符正确显示
2025-12-14 21:41:29 +08:00
..
2025-12-03 14:39:06 +08:00

数据迁移和验证脚本

本目录包含模板系统优化的数据迁移和验证脚本。

脚本列表

1. migrate-template-data.ts

功能: 迁移旧素材的templateId和验证模板version字段

使用场景:

  • 首次部署模板系统优化时
  • 发现有素材没有templateId时
  • 数据库恢复后需要重新迁移时

运行方式:

npm run migrate:template-data

执行内容:

  1. 检查并更新模板version字段(设置为1)
  2. 为没有templateId的素材分配默认内置模板
  3. 验证数据完整性
  4. 生成迁移报告

输出示例:

开始数据迁移...

步骤 1: 检查模板version字段...
✓ 所有模板都有version字段

步骤 2: 检查没有templateId的素材...
发现 150 个素材没有templateId,正在分配默认模板...
✓ 素材templateId迁移完成: 成功 150, 失败 0

步骤 3: 验证数据完整性...
  模板总数: 10
  有version的模板: 10
  素材总数(未删除): 500
  有templateId的素材: 500
  字段总数: 45
  有templateId的字段: 45
  字段池定义总数: 12

✓ 数据完整性验证完成

============================================================
迁移报告
============================================================
模板: 10/10 有version字段
素材: 500/500 有templateId
字段: 45/45 有templateId
字段池: 12 个定义
============================================================

✓ 数据迁移成功完成!

注意事项:

  • 脚本是幂等的,可以多次运行
  • 只处理未删除的素材(deletedAt为null)
  • 根据materialType自动分配对应的内置模板
  • 如果迁移失败,会显示详细的错误信息

2. verify-template-data.ts

功能: 验证模板系统数据的完整性和一致性

使用场景:

  • 数据迁移后验证
  • 定期数据健康检查
  • 发现数据问题时诊断
  • 部署前验证

运行方式:

npm run verify:template-data

验证内容:

  1. 模板数据

    • 模板名称完整性
    • version字段存在性
    • materialKind有效性
  2. 素材数据

    • templateId完整性
    • templateId引用有效性
  3. 字段数据

    • templateId完整性
    • 字段key唯一性(同一模板内)
  4. 字段池数据

    • 字段池key唯一性
  5. 孤立数据检查

    • 没有字段的模板(警告)
    • 没有素材的模板(警告)

输出示例:

开始数据验证...

验证 1: 检查模板数据...
验证 2: 检查素材数据...
验证 3: 检查字段数据...
验证 4: 检查字段池数据...
验证 5: 检查孤立数据...

================================================================================
验证报告
================================================================================

模板:
  ✓ 模板名称完整性
    ✓ 所有模板都有名称
  ✓ 模板version字段
    ✓ 所有模板都有version
  ✓ 模板materialKind有效性
    ✓ 所有模板的materialKind都有效

素材:
  ✓ 素材templateId完整性
    ✓ 所有素材都有templateId
  ✓ 素材templateId引用有效性
    ✓ 所有素材的templateId引用都有效

字段:
  ✓ 字段templateId完整性
    ✓ 所有字段都有templateId
  ✓ 字段key唯一性
    ✓ 所有字段key在模板内唯一

字段池:
  ✓ 字段池key唯一性
    ✓ 所有字段池key唯一

孤立数据:
  ✓ 没有字段的模板
    ⚠ 2 个模板没有字段(可能是草稿)
  ✓ 没有素材的模板
    ⚠ 3 个模板没有素材(可能是新建的)

================================================================================
统计信息
================================================================================
模板总数: 10 (活跃: 8)
字段总数: 45
素材总数: 500
字段池定义: 12 (启用筛选: 8)
================================================================================

✓ 所有验证通过!

注意事项:

  • 孤立数据检查只是警告,不会导致验证失败
  • 可以定期运行以监控数据健康状态
  • 如果发现问题,会显示详细的错误信息

使用流程

首次部署

# 1. 备份数据库
pg_dump -h <host> -U <user> -d <database> -F c -f backup.dump

# 2. 应用数据库迁移
npx prisma migrate deploy

# 3. 运行数据迁移
npm run migrate:template-data

# 4. 验证数据
npm run verify:template-data

定期检查

# 每周或每月运行一次
npm run verify:template-data

问题诊断

# 如果发现数据问题
npm run verify:template-data

# 查看详细的验证报告
# 根据报告修复问题

# 修复后重新验证
npm run verify:template-data

故障排除

问题 1: 数据库连接失败

错误信息: Error: Can't reach database server

解决方案:

  1. 检查DATABASE_URL环境变量
  2. 确认数据库服务正在运行
  3. 检查网络连接

问题 2: 迁移脚本执行失败

错误信息: Error: 数据库错误

解决方案:

  1. 查看详细的错误日志
  2. 检查数据库权限
  3. 验证数据完整性
  4. 手动修复问题数据后重新运行

问题 3: 验证失败

错误信息: ✗ X 个素材没有templateId

解决方案:

  1. 运行迁移脚本:npm run migrate:template-data
  2. 重新验证:npm run verify:template-data

问题 4: TypeScript编译错误

错误信息: Cannot find module '@prisma/client'

解决方案:

# 重新生成Prisma客户端
npm run prisma:generate

# 重新运行脚本
npm run migrate:template-data

开发说明

添加新的迁移逻辑

编辑 migrate-template-data.ts,在主函数中添加新的步骤:

async function migrateTemplateData() {
  // ... 现有步骤

  // 新步骤
  console.log('步骤 X: 执行新的迁移...')
  // 迁移逻辑
  console.log('✓ 新迁移完成\n')

  // ... 验证和报告
}

添加新的验证规则

编辑 verify-template-data.ts,添加新的验证:

async function verifyTemplateData(): Promise<boolean> {
  // ... 现有验证

  // 新验证
  console.log('验证 X: 检查新规则...')
  const newCheck = await prisma.model.count({ where: { /* 条件 */ } })
  results.push({
    category: '分类',
    passed: newCheck === 0,
    message: '验证描述',
    details: newCheck === 0 ? '✓ 通过' : `✗ ${newCheck} 个问题`
  })

  // ... 报告生成
}

相关文档