Initial commit of akmon project

This commit is contained in:
2026-01-20 08:04:15 +08:00
commit 77a2bab985
1309 changed files with 343305 additions and 0 deletions

View File

@@ -0,0 +1,167 @@
# 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. **监控告警**:监控日志中关于不存在用户/设备的警告信息