358 lines
12 KiB
Markdown
358 lines
12 KiB
Markdown
# 美家卡智影 - 数据库设计规范
|
||
|
||
> 企业级统一数据库命名和设计规范,遵循 "轻量云 + 全本地业务数据" 架构设计。
|
||
|
||
---
|
||
|
||
## 一、整体设计原则
|
||
|
||
| 原则 | 说明 |
|
||
|------|------|
|
||
| **统一前缀** | 所有业务表统一使用 `mjk_` 前缀(美家卡全称缩写)|
|
||
| **无外键设计** | 不使用数据库外键约束,数据一致性由业务层保证,架构更简洁灵活 |
|
||
| **软删除优先** | 使用 `deleted_at` 时间戳做软删除,保留历史数据便于排查 |
|
||
| **全小写下划线** | 命名全小写,单词用下划线分隔 |
|
||
|
||
---
|
||
|
||
## 二、表命名规范
|
||
|
||
### 命名格式
|
||
|
||
```
|
||
mjk_{module}_{description}[_logs]
|
||
```
|
||
|
||
- `mjk_` - 统一项目前缀
|
||
- `module` - 业务模块名称
|
||
- `description` - 内容描述
|
||
- `_logs` 后缀 - 日志/统计类表(按事件增长)
|
||
|
||
### 示例
|
||
|
||
| 表名 | 说明 |
|
||
|------|------|
|
||
| `mjk_users` | 用户账户表 |
|
||
| `mjk_model_usage_logs` | AI 模型调用日志表 |
|
||
| `mjk_avatars` | 数字人名片表(已废弃,数据迁移到本地)|
|
||
| `mjk_interface_request_logs` | 接口请求记录表 |
|
||
|
||
---
|
||
|
||
## 三、字段命名规范
|
||
|
||
| 场景 | 规则 | 示例 |
|
||
|------|------|------|
|
||
| **主键** | 统一命名 `id`,类型 `BIGSERIAL` / `BIGINT` | `id BIGSERIAL PRIMARY KEY` |
|
||
| **外键引用** | 格式 `{referenced_table}_{primary_key}`,不要加前缀 | 引用 `mjk_users.id` → `user_id` |
|
||
| **布尔类型** | 前缀 `is_` 或 `has_` | `is_deleted`, `has_attachment` |
|
||
| **时间戳** | 后缀 `_at`,类型 `TIMESTAMP WITH TIME ZONE` | `created_at`, `updated_at`, `started_at`, `finished_at` |
|
||
| **状态字段** | 字段名固定 `status`,类型 `VARCHAR(N)`,存储枚举字符串 | `status VARCHAR(20) NOT NULL` |
|
||
| **软删除** | 字段名 `deleted_at`,允许 `NULL`,`NULL` 表示未删除 | `deleted_at TIMESTAMP WITH TIME ZONE` |
|
||
|
||
---
|
||
|
||
## 四、约束与索引命名规范
|
||
|
||
| 对象 | 命名格式 | 示例 |
|
||
|------|---------|------|
|
||
| **主键** | `{table_name}_pkey`(PostgreSQL 默认) | `mjk_interface_request_logs_pkey` |
|
||
| **唯一约束** | `uk_{table_name}_{column_list}` | `uk_mjk_interface_request_logs_request_id` |
|
||
| **普通索引** | `idx_{table_name}_{column_list}` | `idx_mjk_interface_request_logs_user_id` |
|
||
|
||
---
|
||
|
||
## 五、所有业务表结构
|
||
|
||
---
|
||
|
||
### 1. `mjk_users` - 用户基本信息表
|
||
|
||
存储用户基本认证信息,云端只存账户,不存业务数据。
|
||
|
||
```sql
|
||
CREATE TABLE mjk_users (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
mobile VARCHAR(20) UNIQUE NOT NULL,
|
||
nickname VARCHAR(64),
|
||
avatar_url TEXT,
|
||
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||
);
|
||
|
||
-- 索引
|
||
CREATE UNIQUE INDEX idx_mjk_users_mobile ON mjk_users(mobile);
|
||
```
|
||
|
||
**字段说明**:
|
||
| 字段 | 说明 |
|
||
|------|------|
|
||
| `id` | 用户唯一ID |
|
||
| `mobile` | 手机号(登录账号,唯一)|
|
||
| `nickname` | 用户昵称 |
|
||
| `avatar_url` | 头像URL |
|
||
| `created_at` | 创建时间 |
|
||
| `updated_at` | 最后更新时间 |
|
||
|
||
---
|
||
|
||
### 2. `mjk_user_credits` - 用户积分账户记录表
|
||
|
||
记录用户积分账户的所有变动(充值、消费),每个变动一条记录。
|
||
|
||
```sql
|
||
CREATE TABLE mjk_user_credits (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
user_id VARCHAR(50) NOT NULL,
|
||
change_type VARCHAR(20) NOT NULL, -- recharge / consume
|
||
change_credits INTEGER NOT NULL, -- 变动积分数(充值正,消费负)
|
||
balance_before INTEGER NOT NULL, -- 变动前余额
|
||
balance_after INTEGER NOT NULL, -- 变动后余额
|
||
interface_type VARCHAR(50), -- 消费接口类型(消费时才有)
|
||
request_id VARCHAR(64), -- 关联接口请求ID
|
||
remark VARCHAR(200), -- 备注(充值订单号等)
|
||
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||
);
|
||
|
||
-- 索引
|
||
CREATE INDEX idx_mjk_user_credits_user_id ON mjk_user_credits(user_id);
|
||
CREATE INDEX idx_mjk_user_credits_created_at ON mjk_user_credits(created_at);
|
||
CREATE INDEX idx_mjk_user_credits_change_type ON mjk_user_credits(change_type);
|
||
```
|
||
|
||
**字段说明**:
|
||
| 字段 | 说明 |
|
||
|------|------|
|
||
| `id` | 记录ID |
|
||
| `user_id` | 关联用户ID |
|
||
| `change_type` | 变动类型:`recharge`(充值) / `consume`(消费) |
|
||
| `change_credits` | 变动积分,充值为正,消费为负 |
|
||
| `balance_before` | 变动前积分余额 |
|
||
| `balance_after` | 变动后积分余额 |
|
||
| `interface_type` | 消费接口类型(仅消费时有)|
|
||
| `request_id` | 关联接口请求ID(可用于追溯)|
|
||
| `remark` | 备注,充值时存订单号 |
|
||
| `created_at` | 变动时间 |
|
||
|
||
**余额计算**:用户当前余额 = `sum(change_credits)`,可以随时计算,也可以在用户表存冗余字段加速查询。
|
||
|
||
---
|
||
|
||
### 3. `mjk_model_usage_logs` - AI 模型调用日志表
|
||
|
||
记录每一次 AI 模型调用,用于成本统计和监控。
|
||
|
||
```sql
|
||
CREATE TABLE mjk_model_usage_logs (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
model_id VARCHAR(100) NOT NULL,
|
||
platform_id VARCHAR(50) NOT NULL,
|
||
task_type VARCHAR(50) NOT NULL,
|
||
prompt_tokens INTEGER NOT NULL DEFAULT 0,
|
||
completion_tokens INTEGER NOT NULL DEFAULT 0,
|
||
total_tokens INTEGER NOT NULL DEFAULT 0,
|
||
cost_cny FLOAT NOT NULL DEFAULT 0.0,
|
||
response_time_ms INTEGER,
|
||
success BOOLEAN NOT NULL DEFAULT TRUE,
|
||
error_message TEXT,
|
||
user_id VARCHAR(50),
|
||
project_id VARCHAR(50),
|
||
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||
);
|
||
|
||
-- 索引
|
||
CREATE INDEX idx_mjk_model_usage_logs_user_id ON mjk_model_usage_logs(user_id);
|
||
CREATE INDEX idx_mjk_model_usage_logs_created_at ON mjk_model_usage_logs(created_at);
|
||
```
|
||
|
||
**字段说明**:
|
||
- `model_id` - AI 模型ID
|
||
- `platform_id` - AI 平台ID(openai/volcengine/klingai 等)
|
||
- `task_type` - 任务类型(script/polish/chat 等)
|
||
- `prompt_tokens` - 输入 Token 数
|
||
- `completion_tokens` - 输出 Token 数
|
||
- `total_tokens` - 总 Token 数
|
||
- `cost_cny` - 消耗金额(人民币元)
|
||
- `response_time_ms` - 响应时间(毫秒)
|
||
- `success` - 是否成功
|
||
- `error_message` - 错误信息
|
||
- `user_id` - 关联用户ID
|
||
- `project_id` - 关联项目ID
|
||
- `created_at` - 创建时间
|
||
|
||
---
|
||
|
||
### 4. `mjk_interface_request_logs` - 接口请求记录表(新增)
|
||
|
||
**按后端接口类型记录所有用户请求,统计积分消耗**。这张表是顶层的接口请求统计,每一次前端调用后端接口都记一条。
|
||
|
||
```sql
|
||
CREATE TABLE mjk_interface_request_logs (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
request_id VARCHAR(64) NOT NULL,
|
||
user_id VARCHAR(50) NOT NULL,
|
||
interface_type VARCHAR(50) NOT NULL,
|
||
interface_name VARCHAR(100),
|
||
status VARCHAR(20) NOT NULL,
|
||
cost_credits INTEGER NOT NULL DEFAULT 0,
|
||
started_at TIMESTAMP WITH TIME ZONE NOT NULL,
|
||
finished_at TIMESTAMP WITH TIME ZONE,
|
||
error_message TEXT,
|
||
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||
);
|
||
|
||
-- 唯一约束
|
||
ALTER TABLE mjk_interface_request_logs
|
||
ADD CONSTRAINT uk_mjk_interface_request_logs_request_id
|
||
UNIQUE (request_id);
|
||
|
||
-- 索引
|
||
CREATE INDEX idx_mjk_interface_request_logs_user_id
|
||
ON mjk_interface_request_logs(user_id);
|
||
CREATE INDEX idx_mjk_interface_request_logs_interface_type
|
||
ON mjk_interface_request_logs(interface_type);
|
||
CREATE INDEX idx_mjk_interface_request_logs_status
|
||
ON mjk_interface_request_logs(status);
|
||
CREATE INDEX idx_mjk_interface_request_logs_created_at
|
||
ON mjk_interface_request_logs(created_at);
|
||
```
|
||
|
||
**字段说明**:
|
||
| 字段 | 说明 |
|
||
|------|------|
|
||
| `id` | 日志记录自增ID |
|
||
| `request_id` | 本次请求唯一ID(全局唯一)|
|
||
| `user_id` | 请求用户ID |
|
||
| `interface_type` | 接口类型(枚举见下方)|
|
||
| `interface_name` | 接口名称(可读描述)|
|
||
| `status` | 请求状态:`success` / `failed` |
|
||
| `cost_credits` | 消耗积分数 |
|
||
| `started_at` | 请求开始时间 |
|
||
| `finished_at` | 请求结束时间 |
|
||
| `error_message` | 失败原因 |
|
||
| `created_at` | 记录创建时间 |
|
||
|
||
**`interface_type` 枚举值**:
|
||
|
||
| 值 | 说明 |
|
||
|----|------|
|
||
| `script_generate` | 脚本生成 |
|
||
| `script_polish` | 脚本润色 |
|
||
| `avatar_clone` | 数字人克隆 |
|
||
| `video_generate` | 数字人视频生成 |
|
||
| `subtitle_generate` | 字幕打轴生成 |
|
||
| `image_generate` | 封面图片生成 |
|
||
|
||
---
|
||
|
||
### 5. `mjk_avatars` - 数字人名片表(已废弃)
|
||
|
||
> **迁移计划**:原 `avatars` 表已废弃,所有数字人元数据全量迁移到用户本地存储。
|
||
> 路径:`~/Documents/Meijiaka/avatars/{avatar_id}/meta.json`
|
||
|
||
保留本表仅用于存量数据兼容,后续可删除。
|
||
|
||
```sql
|
||
CREATE TABLE mjk_avatars (
|
||
id VARCHAR(64) PRIMARY KEY,
|
||
user_id VARCHAR(50) NOT NULL,
|
||
name VARCHAR(64) NOT NULL,
|
||
voice_id VARCHAR(64),
|
||
element_id BIGINT,
|
||
voice_task_id VARCHAR(128),
|
||
element_task_id VARCHAR(128),
|
||
video_url TEXT NOT NULL,
|
||
trial_url TEXT,
|
||
status VARCHAR(32) NOT NULL DEFAULT 'pending',
|
||
fail_reason TEXT,
|
||
deleted_at TIMESTAMP WITH TIME ZONE,
|
||
created_at TIMESTAMP WITH TIME ZONE NOT NULL,
|
||
updated_at TIMESTAMP WITH TIME ZONE NOT NULL
|
||
);
|
||
|
||
-- 索引
|
||
CREATE INDEX idx_mjk_avatars_user_id ON mjk_avatars(user_id);
|
||
CREATE INDEX idx_mjk_avatars_voice_task_id ON mjk_avatars(voice_task_id);
|
||
CREATE INDEX idx_mjk_avatars_element_task_id ON mjk_avatars(element_task_id);
|
||
```
|
||
|
||
---
|
||
|
||
## 六、本地存储结构(业务数据)
|
||
|
||
所有业务数据(项目、脚本、数字人)都存在用户本地磁盘,云端只存储日志和统计:
|
||
|
||
```
|
||
~/Documents/Meijiaka/
|
||
├── config.json # 全局应用配置
|
||
├── projects/
|
||
│ └── {project_id}/
|
||
│ ├── meta.json # 项目元数据
|
||
│ ├── segments.json # 脚本/分镜数据
|
||
│ └── assets/ # 媒体文件
|
||
├── avatars/
|
||
│ └── {avatar_id}/
|
||
│ ├── meta.json # 数字人元数据(id/name/voice_id/element_id/status 等)
|
||
│ └── source.mp4 # 原始上传视频
|
||
└── cache/ # 临时文件
|
||
```
|
||
|
||
**`avatars/{avatar_id}/meta.json` 结构**:
|
||
|
||
```json
|
||
{
|
||
"id": "avt_xxx",
|
||
"name": "我的数字人",
|
||
"voiceId": "kling-voice-id",
|
||
"elementId": 12345678,
|
||
"voiceTaskId": "kling-task-id",
|
||
"elementTaskId": "kling-task-id",
|
||
"videoUrl": "https://.../source.mp4",
|
||
"trialUrl": "https://.../trial.wav",
|
||
"status": "succeed",
|
||
"failReason": null,
|
||
"createdAt": "2026-04-16T10:00:00Z",
|
||
"updatedAt": "2026-04-16T10:05:00Z"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 七、架构总结
|
||
|
||
| 数据类型 | 存储位置 | 说明 |
|
||
|---------|----------|------|
|
||
| 用户基本信息 | 云端 `mjk_users` | 必须存云端 |
|
||
| 用户积分变动记录 | 云端 `mjk_user_credits` | 记录充值/消费流水,统计用户余额 |
|
||
| AI 模型调用日志 | 云端 `mjk_model_usage_logs` | AI 模型细粒度调用日志(成本统计)|
|
||
| 接口请求记录 | 云端 `mjk_interface_request_logs` | 按后端接口记录请求、状态、消耗积分 |
|
||
| 项目/脚本/分镜 | 用户本地 JSON | 全本地业务数据 |
|
||
| 数字人元数据/原始视频 | 用户本地文件 | 全本地业务数据(原云端表已废弃)|
|
||
| 合成输出视频 | 用户本地文件 | 全本地 |
|
||
|
||
完美符合设计理念:**轻量云账号 + 全本地业务数据**。
|
||
|
||
---
|
||
|
||
## 八、迁移说明
|
||
|
||
### 从无前缀版本迁移到统一前缀版本
|
||
|
||
1. 使用 Alembic 自动重命名所有现有表
|
||
```sql
|
||
ALTER TABLE users RENAME TO mjk_users;
|
||
ALTER TABLE model_usage_logs RENAME TO mjk_model_usage_logs;
|
||
ALTER TABLE avatars RENAME TO mjk_avatars;
|
||
```
|
||
2. 新建两张表:
|
||
- `mjk_user_credits` - 用户积分变动记录表
|
||
- `mjk_interface_request_logs` - 接口请求记录表
|
||
3. 修改所有 SQLAlchemy 模型中的 `__tablename__`
|
||
4. 后续:将 `mjk_avatars` 数据迁移到用户本地后可删除该表
|
||
|
||
---
|
||
|
||
*版本:v1.1*
|
||
*创建日期:2026-04-16*
|
||
*更新:新增 `mjk_user_credits` 积分账户表*
|