# Supabase 数据库适配说明 ## 概述 推送消息接收服务的数据库结构已适配现有的 `ak_users` 和 `ak_devices` 表结构,以避免重复创建表和数据冲突。所有推送消息相关的表都使用 `ps_` 前缀命名。 ## 主要变更 ### 1. 移除独立表 - ❌ 移除独立的 `devices` 表 - ❌ 移除独立的 `users` 表 - ✅ 使用现有的 `public.ak_devices` 表 - ✅ 使用现有的 `public.ak_users` 表 ### 2. 表命名规范 - ✅ `ps_push_messages` - 推送消息主表 - ✅ `ps_push_types` - 推送类型配置表 - ✅ `ps_message_processing_logs` - 消息处理日志表 - ✅ `ps_system_stats` - 系统统计表 ### 3. 修改关联字段 - `ps_push_messages.user_id`: VARCHAR(255) → UUID,关联到 `public.ak_users(id)` - `ps_push_messages.device_id`: VARCHAR(255) → UUID,关联到 `public.ak_devices(id)` #### `ps_push_messages` 表结构 ```sql CREATE TABLE ps_push_messages ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), message_id VARCHAR(255), push_type VARCHAR(50) NOT NULL, user_id UUID REFERENCES public.ak_users(id) ON DELETE SET NULL, device_id UUID REFERENCES public.ak_devices(id) ON DELETE SET NULL, raw_data JSONB NOT NULL, parsed_data JSONB, received_at TIMESTAMPTZ DEFAULT NOW(), processing_status VARCHAR(20) DEFAULT 'pending', -- 其他字段... ); ``` ### 4. 适配表结构 #### `public.ak_users` 表结构 ```sql CREATE TABLE public.ak_users ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), username VARCHAR(64) UNIQUE NOT NULL, email VARCHAR(128) UNIQUE NOT NULL, password_hash VARCHAR(256) NOT NULL, gender VARCHAR(16) DEFAULT 'other', birthday DATE, height_cm INT, weight_kg INT, bio TEXT, phone VARCHAR(32), avatar_url TEXT, region_id UUID REFERENCES public.ak_regions(id), school_id UUID REFERENCES public.ak_schools(id), grade_id UUID REFERENCES public.ak_grades(id), class_id UUID REFERENCES public.ak_classes(id), role VARCHAR(32) DEFAULT 'student', created_at TIMESTAMPTZ DEFAULT now(), updated_at TIMESTAMPTZ DEFAULT now(), auth_id UUID REFERENCES auth.users(id) ON DELETE CASCADE, preferred_language UUID REFERENCES public.ak_languages(id) ); ``` #### `public.ak_devices` 表结构 ```sql CREATE TABLE public.ak_devices ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID REFERENCES public.ak_users(id) ON DELETE CASCADE, device_type VARCHAR(32) NOT NULL, device_name VARCHAR(64), device_mac VARCHAR(64), bind_time TIMESTAMPTZ DEFAULT now(), status VARCHAR(16) DEFAULT 'active', extra JSONB ); ``` ### 5. 数据库操作调整 #### 设备信息处理 ```javascript // 旧方式:自动创建/更新设备 await this.upsertDevice(deviceData); // 新方式:检查并更新现有设备状态 await this.upsertDevice({ device_id: deviceData.device_id, // 必须是现有设备的 UUID metadata: deviceData.metadata }); ``` #### 用户信息处理 ```javascript // 旧方式:自动创建/更新用户 await this.upsertUser(userData); // 新方式:检查现有用户(不自动创建) await this.upsertUser({ user_id: userData.user_id // 必须是现有用户的 UUID }); ``` ## API 调用变更 ### 推送消息接口 ```javascript // 发送推送消息时,user_id 和 device_id 必须使用 UUID 格式 const response = await fetch('/api/push/message', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-API-Key': 'your-api-key' }, body: JSON.stringify({ type: 'HEALTH', data: { user_id: '123e4567-e89b-12d3-a456-426614174000', // UUID 格式 device_id: '987fcdeb-51a2-43d7-8f9e-123456789abc', // UUID 格式 H: 72, // 心率 O: 98, // 血氧 T: 36.5 // 体温 } }) }); ``` ### 错误处理 如果推送消息中包含不存在的 user_id 或 device_id: - 消息仍会被存储到 `push_messages` 表 - 会在日志中记录警告信息 - 不会自动创建用户或设备记录 ## 部署注意事项 ### 1. 数据库初始化 确保在执行 `database/supabase-init.sql` 之前,现有的 `ak_users` 和 `ak_devices` 表已经存在。 ### 2. 外键约束 推送消息表与现有表建立了外键关联: - `ps_push_messages.user_id` → `public.ak_users(id)` - `ps_push_messages.device_id` → `public.ak_devices(id)` ### 3. 权限设置 确保 Supabase Service Role 对现有表有适当的访问权限。 ## 数据完整性 ### 推送消息存储 - ✅ 所有推送消息都会完整存储 - ✅ 支持 user_id 或 device_id 为 NULL 的情况 - ✅ 通过外键约束保证数据一致性 ### 统计和查询 - ✅ 可以通过关联查询获取用户和设备的详细信息 - ✅ 统计功能完全兼容现有表结构 ## 使用建议 1. **用户和设备管理**:通过专门的用户管理和设备管理接口创建和维护用户、设备信息 2. **推送消息**:只负责接收和存储推送消息,不处理用户/设备的创建 3. **数据关联**:通过外键关联获取完整的用户和设备信息 4. **监控告警**:监控日志中关于不存在用户/设备的警告信息