名称: 数据库管理器 描述: 管理CookMode V2的Supabase数据库架构、迁移和查询。当用户需要创建/修改表、编写迁移、更新RLS策略或排查数据库问题时使用此技能。
数据库管理器技能
您的角色
您专门负责CookMode V2的Supabase PostgreSQL数据库操作。您帮助用户管理架构、编写迁移、配置行级安全性(RLS)和排查数据库问题。
何时使用此技能
当用户想要以下操作时调用此技能:
- 创建或修改数据库表
- 编写SQL迁移
- 添加/更新RLS策略
- 调试数据库错误
- 优化查询
- 添加新的数据库功能
当前数据库架构
表概览
-
ingredient_checks
- 跟踪食材完成状态
- 跨客户端实时同步
-
step_checks
- 跟踪指令步骤完成情况
- 跨客户端实时同步
-
recipe_status
- 工作流状态:已收集、已完成、已装盘、已打包
- 每个食谱一个状态
-
recipe_order_counts
- 每个食谱的订单数量(1-50)
- 用于食材缩放
-
recipe_chef_names
- 厨师分配(带颜色徽章)
- 包含
name和color字段
架构文件
- 主文件:
/supabase-schema.sql - 迁移文件:
/supabase-migration-*.sql
表架构
ingredient_checks
CREATE TABLE ingredient_checks (
recipe_slug TEXT NOT NULL,
ingredient_index INTEGER NOT NULL,
component_name TEXT NOT NULL,
ingredient_text TEXT,
is_checked BOOLEAN DEFAULT FALSE,
updated_at TIMESTAMP DEFAULT NOW(),
PRIMARY KEY (recipe_slug, ingredient_index, component_name)
);
step_checks
CREATE TABLE step_checks (
recipe_slug TEXT NOT NULL,
step_index INTEGER NOT NULL,
step_text TEXT,
is_checked BOOLEAN DEFAULT FALSE,
updated_at TIMESTAMP DEFAULT NOW(),
PRIMARY KEY (recipe_slug, step_index)
);
recipe_status
CREATE TABLE recipe_status (
recipe_slug TEXT PRIMARY KEY,
status TEXT CHECK (status IN ('gathered', 'complete', 'plated', 'packed')),
updated_at TIMESTAMP DEFAULT NOW()
);
recipe_order_counts
CREATE TABLE recipe_order_counts (
recipe_slug TEXT PRIMARY KEY,
order_count INTEGER DEFAULT 1 CHECK (order_count >= 1 AND order_count <= 50),
updated_at TIMESTAMP DEFAULT NOW()
);
recipe_chef_names
CREATE TABLE recipe_chef_names (
recipe_slug TEXT PRIMARY KEY,
name TEXT NOT NULL,
color TEXT NOT NULL DEFAULT '#9333ea',
updated_at TIMESTAMP DEFAULT NOW()
);
行级安全性(RLS)
CookMode V2当前使用宽松RLS - 所有用户可以读写所有数据。
-- 启用RLS
ALTER TABLE ingredient_checks ENABLE ROW LEVEL SECURITY;
-- 允许所有操作(当前策略)
CREATE POLICY "启用所有访问" ON ingredient_checks
FOR ALL USING (true);
注意:这适用于受信任的厨房环境。对于多租户设置,请实现用户特定策略。
实时订阅
启用实时同步的表:
ingredient_checksstep_checksrecipe_statusrecipe_order_countsrecipe_chef_names
在/js/hooks/useRealtime.js:15-80中配置
迁移最佳实践
创建迁移
- 命名约定:
supabase-migration-{功能名称}.sql - 包含回滚: 添加手动回滚步骤的注释
- 本地测试: 应用前验证迁移
迁移模板
-- 迁移: 添加新功能
-- 日期: 2025-01-XX
-- 描述: 更改的简要描述
-- ============================================
-- 新表
-- ============================================
CREATE TABLE IF NOT EXISTS new_table (
id SERIAL PRIMARY KEY,
recipe_slug TEXT NOT NULL,
data TEXT,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- ============================================
-- 索引
-- ============================================
CREATE INDEX idx_new_table_recipe ON new_table(recipe_slug);
-- ============================================
-- 行级安全性
-- ============================================
ALTER TABLE new_table ENABLE ROW LEVEL SECURITY;
CREATE POLICY "启用所有访问" ON new_table
FOR ALL USING (true);
-- ============================================
-- 回滚(手动)
-- ============================================
-- DROP TABLE IF EXISTS new_table CASCADE;
常见数据库操作
添加新表
- 定义带约束的架构
- 添加性能索引
- 启用RLS并创建策略
- 在此技能中记录
- 如果需要实时更新则更新钩子
修改现有表
-- 添加新列
ALTER TABLE recipe_status
ADD COLUMN priority INTEGER DEFAULT 0;
-- 修改列
ALTER TABLE recipe_chef_names
ALTER COLUMN color SET DEFAULT '#10b981';
-- 添加约束
ALTER TABLE recipe_order_counts
ADD CONSTRAINT valid_count CHECK (order_count > 0);
查询数据
在钩子中使用Supabase客户端:
// 选择
const { data, error } = await supabase
.from('recipe_status')
.select('*')
.eq('recipe_slug', 'truffle-mashed-potatoes');
// 更新或插入
const { error } = await supabase
.from('recipe_order_counts')
.upsert({
recipe_slug: 'chocolate-cake',
order_count: 5
}, {
onConflict: 'recipe_slug'
});
// 删除
const { error } = await supabase
.from('step_checks')
.delete()
.eq('recipe_slug', 'old-recipe');
数据库连接
配置
Supabase连接在/js/hooks/useSupabase.js中配置:
- URL: 来自环境或配置
- 匿名密钥: 客户端访问的公共密钥
- 实时: 用于实时更新的WebSocket连接
初始化流程
useSupabase()创建客户端- 返回
{supabase, isSupabaseConnected} - 应用在操作前检查连接
故障排除
常见问题
问题: 更改未同步
- 检查useRealtime.js中的实时订阅
- 验证表是否有RLS策略
- 检查浏览器控制台中的Supabase错误
问题: 约束违反
- 查看表约束(CHECK、UNIQUE、FK)
- 插入/更新前验证数据
问题: RLS阻止查询
- 验证策略是否允许操作
- 检查用户认证状态
调试查询
-- 检查表结构
\d+ ingredient_checks
-- 查看所有策略
SELECT * FROM pg_policies WHERE tablename = 'recipe_status';
-- 检查实时配置
SELECT * FROM pg_publication_tables WHERE pubname = 'supabase_realtime';
性能考虑
索引
当前索引目标:
- 主键(自动)
- 外键列
- 频繁过滤的列(recipe_slug)
乐观更新
UI立即更新,异步同步到数据库:
// 乐观更新
setCompletedIngredients(prev => ({ ...prev, [key]: true }));
// 然后同步到Supabase
await supabase.from('ingredient_checks').upsert(...);
架构演进
修改架构时:
- 切勿在没有备份的情况下删除数据
- 所有更改使用迁移
- 使用真实数据量测试
- 如果数据访问更改则更新钩子
- 在CLAUDE.md中记录更改
示例:添加食谱备注表
-- 迁移: 添加食谱备注功能
CREATE TABLE recipe_notes (
id SERIAL PRIMARY KEY,
recipe_slug TEXT NOT NULL,
note_text TEXT NOT NULL,
created_by TEXT,
created_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_recipe_notes_slug ON recipe_notes(recipe_slug);
ALTER TABLE recipe_notes ENABLE ROW LEVEL SECURITY;
CREATE POLICY "启用所有访问" ON recipe_notes FOR ALL USING (true);
然后更新/js/hooks/useRecipeData.js以获取和管理备注。
记住:保持数据库简单且适合厨师使用,就像UI一样!