Files
insightflow/backend/schema.sql
OpenClaw Bot 911e891451 Phase 8: 完成多租户SaaS架构、订阅计费系统、企业级功能
- 任务1: 多租户SaaS架构 (tenant_manager.py)
- 任务2: 订阅与计费系统 (subscription_manager.py)
- 任务3: 企业级功能 (enterprise_manager.py)
- 更新 schema.sql 添加所有相关表
- 更新 main.py 添加所有API端点
- 更新 README.md 进度表
2026-02-25 18:42:29 +08:00

1409 lines
55 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- InsightFlow Phase 3 - Database Schema
-- 支持知识生长与多文件融合
-- 项目表
CREATE TABLE IF NOT EXISTS projects (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
description TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 文件/转录表
CREATE TABLE IF NOT EXISTS transcripts (
id TEXT PRIMARY KEY,
project_id TEXT NOT NULL,
filename TEXT,
full_text TEXT,
type TEXT DEFAULT 'audio', -- 'audio' 或 'document'
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (project_id) REFERENCES projects(id)
);
-- 全局实体表(跨文件共享)
CREATE TABLE IF NOT EXISTS entities (
id TEXT PRIMARY KEY,
project_id TEXT NOT NULL,
name TEXT NOT NULL,
canonical_name TEXT, -- 规范名称(用于对齐)
type TEXT,
definition TEXT,
aliases TEXT, -- JSON 数组:["别名1", "别名2"]
embedding TEXT, -- JSON 数组:实体名称+定义的 embedding
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (project_id) REFERENCES projects(id)
);
-- 实体提及表(文件中的具体位置)
CREATE TABLE IF NOT EXISTS entity_mentions (
id TEXT PRIMARY KEY,
entity_id TEXT NOT NULL,
transcript_id TEXT NOT NULL,
start_pos INTEGER,
end_pos INTEGER,
text_snippet TEXT,
confidence REAL DEFAULT 1.0,
FOREIGN KEY (entity_id) REFERENCES entities(id),
FOREIGN KEY (transcript_id) REFERENCES transcripts(id)
);
-- 实体关系表
CREATE TABLE IF NOT EXISTS entity_relations (
id TEXT PRIMARY KEY,
project_id TEXT NOT NULL,
source_entity_id TEXT NOT NULL,
target_entity_id TEXT NOT NULL,
relation_type TEXT, -- "belongs_to", "works_with", "depends_on" 等
evidence TEXT, -- 关系来源文本
transcript_id TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (project_id) REFERENCES projects(id),
FOREIGN KEY (source_entity_id) REFERENCES entities(id),
FOREIGN KEY (target_entity_id) REFERENCES entities(id)
);
-- 术语表(项目级热词,用于 ASR 优化)
CREATE TABLE IF NOT EXISTS glossary (
id TEXT PRIMARY KEY,
project_id TEXT NOT NULL,
term TEXT NOT NULL,
pronunciation TEXT, -- 发音提示,如 "K8s" -> "Kubernetes"
frequency INTEGER DEFAULT 1,
FOREIGN KEY (project_id) REFERENCES projects(id)
);
-- Phase 5: 属性模板表
CREATE TABLE IF NOT EXISTS attribute_templates (
id TEXT PRIMARY KEY,
project_id TEXT NOT NULL,
name TEXT NOT NULL,
type TEXT NOT NULL, -- text/number/date/select/multiselect/boolean
description TEXT,
options TEXT, -- JSON 数组,用于 select/multiselect 类型
is_required INTEGER DEFAULT 0,
default_value TEXT,
sort_order INTEGER DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (project_id) REFERENCES projects(id)
);
-- Phase 5: 实体属性值表
CREATE TABLE IF NOT EXISTS entity_attributes (
id TEXT PRIMARY KEY,
entity_id TEXT NOT NULL,
template_id TEXT,
name TEXT NOT NULL,
type TEXT NOT NULL, -- text/number/date/select/multiselect
value TEXT, -- 存储实际值
options TEXT, -- JSON 数组,用于 select/multiselect
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (entity_id) REFERENCES entities(id) ON DELETE CASCADE,
FOREIGN KEY (template_id) REFERENCES attribute_templates(id) ON DELETE SET NULL,
UNIQUE(entity_id, name)
);
-- Phase 5: 属性变更历史表
CREATE TABLE IF NOT EXISTS attribute_history (
id TEXT PRIMARY KEY,
entity_id TEXT NOT NULL,
template_id TEXT,
attribute_name TEXT NOT NULL,
old_value TEXT,
new_value TEXT,
changed_by TEXT, -- 用户ID或系统
changed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
change_reason TEXT,
FOREIGN KEY (entity_id) REFERENCES entities(id) ON DELETE CASCADE,
FOREIGN KEY (template_id) REFERENCES attribute_templates(id) ON DELETE CASCADE
);
-- 创建索引以提高查询性能
CREATE INDEX IF NOT EXISTS idx_entities_project ON entities(project_id);
CREATE INDEX IF NOT EXISTS idx_entities_name ON entities(name);
CREATE INDEX IF NOT EXISTS idx_transcripts_project ON transcripts(project_id);
CREATE INDEX IF NOT EXISTS idx_mentions_entity ON entity_mentions(entity_id);
CREATE INDEX IF NOT EXISTS idx_mentions_transcript ON entity_mentions(transcript_id);
CREATE INDEX IF NOT EXISTS idx_relations_project ON entity_relations(project_id);
CREATE INDEX IF NOT EXISTS idx_glossary_project ON glossary(project_id);
-- Phase 5: 属性相关索引
CREATE INDEX IF NOT EXISTS idx_attr_templates_project ON attribute_templates(project_id);
CREATE INDEX IF NOT EXISTS idx_entity_attributes_entity ON entity_attributes(entity_id);
CREATE INDEX IF NOT EXISTS idx_entity_attributes_template ON entity_attributes(template_id);
CREATE INDEX IF NOT EXISTS idx_attr_history_entity ON attribute_history(entity_id);
-- Phase 7: 工作流相关表
-- 工作流配置表
CREATE TABLE IF NOT EXISTS workflows (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
description TEXT,
workflow_type TEXT NOT NULL, -- auto_analyze, auto_align, auto_relation, scheduled_report, custom
project_id TEXT NOT NULL,
status TEXT DEFAULT 'active', -- active, paused, error, completed
schedule TEXT, -- cron expression or interval minutes
schedule_type TEXT DEFAULT 'manual', -- manual, cron, interval
config TEXT, -- JSON: workflow specific configuration
webhook_ids TEXT, -- JSON array of webhook config IDs
is_active BOOLEAN DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_run_at TIMESTAMP,
next_run_at TIMESTAMP,
run_count INTEGER DEFAULT 0,
success_count INTEGER DEFAULT 0,
fail_count INTEGER DEFAULT 0,
FOREIGN KEY (project_id) REFERENCES projects(id)
);
-- 工作流任务表
CREATE TABLE IF NOT EXISTS workflow_tasks (
id TEXT PRIMARY KEY,
workflow_id TEXT NOT NULL,
name TEXT NOT NULL,
task_type TEXT NOT NULL, -- analyze, align, discover_relations, notify, custom
config TEXT, -- JSON: task specific configuration
task_order INTEGER DEFAULT 0,
depends_on TEXT, -- JSON array of task IDs
timeout_seconds INTEGER DEFAULT 300,
retry_count INTEGER DEFAULT 3,
retry_delay INTEGER DEFAULT 5,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (workflow_id) REFERENCES workflows(id) ON DELETE CASCADE
);
-- Webhook 配置表
CREATE TABLE IF NOT EXISTS webhook_configs (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
webhook_type TEXT NOT NULL, -- feishu, dingtalk, slack, custom
url TEXT NOT NULL,
secret TEXT, -- for signature verification
headers TEXT, -- JSON: custom headers
template TEXT, -- message template
is_active BOOLEAN DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_used_at TIMESTAMP,
success_count INTEGER DEFAULT 0,
fail_count INTEGER DEFAULT 0
);
-- 工作流执行日志表
CREATE TABLE IF NOT EXISTS workflow_logs (
id TEXT PRIMARY KEY,
workflow_id TEXT NOT NULL,
task_id TEXT, -- NULL if workflow-level log
status TEXT DEFAULT 'pending', -- pending, running, success, failed, cancelled
start_time TIMESTAMP,
end_time TIMESTAMP,
duration_ms INTEGER,
input_data TEXT, -- JSON: input parameters
output_data TEXT, -- JSON: execution results
error_message TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (workflow_id) REFERENCES workflows(id) ON DELETE CASCADE,
FOREIGN KEY (task_id) REFERENCES workflow_tasks(id) ON DELETE SET NULL
);
-- Phase 7: 工作流相关索引
CREATE INDEX IF NOT EXISTS idx_workflows_project ON workflows(project_id);
CREATE INDEX IF NOT EXISTS idx_workflows_status ON workflows(status);
CREATE INDEX IF NOT EXISTS idx_workflows_type ON workflows(workflow_type);
CREATE INDEX IF NOT EXISTS idx_workflow_tasks_workflow ON workflow_tasks(workflow_id);
CREATE INDEX IF NOT EXISTS idx_workflow_logs_workflow ON workflow_logs(workflow_id);
CREATE INDEX IF NOT EXISTS idx_workflow_logs_task ON workflow_logs(task_id);
CREATE INDEX IF NOT EXISTS idx_workflow_logs_status ON workflow_logs(status);
CREATE INDEX IF NOT EXISTS idx_workflow_logs_created ON workflow_logs(created_at);
-- Phase 7: 多模态支持相关表
-- 视频表
CREATE TABLE IF NOT EXISTS videos (
id TEXT PRIMARY KEY,
project_id TEXT NOT NULL,
filename TEXT NOT NULL,
duration REAL, -- 视频时长(秒)
fps REAL, -- 帧率
resolution TEXT, -- JSON: {"width": int, "height": int}
audio_transcript_id TEXT, -- 关联的音频转录ID
full_ocr_text TEXT, -- 所有帧OCR文本合并
extracted_entities TEXT, -- JSON: 提取的实体列表
extracted_relations TEXT, -- JSON: 提取的关系列表
status TEXT DEFAULT 'processing', -- processing, completed, failed
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (project_id) REFERENCES projects(id),
FOREIGN KEY (audio_transcript_id) REFERENCES transcripts(id)
);
-- 视频关键帧表
CREATE TABLE IF NOT EXISTS video_frames (
id TEXT PRIMARY KEY,
video_id TEXT NOT NULL,
frame_number INTEGER,
timestamp REAL, -- 时间戳(秒)
image_data BLOB, -- 帧图片数据可选可存储在OSS
image_url TEXT, -- 图片URL如果存储在OSS
ocr_text TEXT, -- OCR识别文本
extracted_entities TEXT, -- JSON: 该帧提取的实体
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (video_id) REFERENCES videos(id) ON DELETE CASCADE
);
-- 图片表
CREATE TABLE IF NOT EXISTS images (
id TEXT PRIMARY KEY,
project_id TEXT NOT NULL,
filename TEXT NOT NULL,
image_data BLOB, -- 图片数据(可选)
image_url TEXT, -- 图片URL
ocr_text TEXT, -- OCR识别文本
description TEXT, -- 图片描述LLM生成
extracted_entities TEXT, -- JSON: 提取的实体列表
extracted_relations TEXT, -- JSON: 提取的关系列表
status TEXT DEFAULT 'processing',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (project_id) REFERENCES projects(id)
);
-- 多模态实体提及表
CREATE TABLE IF NOT EXISTS multimodal_mentions (
id TEXT PRIMARY KEY,
project_id TEXT NOT NULL,
entity_id TEXT NOT NULL,
modality TEXT NOT NULL, -- audio, video, image, document
source_id TEXT NOT NULL, -- transcript_id, video_id, image_id
source_type TEXT NOT NULL, -- 来源类型
position TEXT, -- JSON: 位置信息
text_snippet TEXT, -- 提及的文本片段
confidence REAL DEFAULT 1.0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (project_id) REFERENCES projects(id),
FOREIGN KEY (entity_id) REFERENCES entities(id) ON DELETE CASCADE
);
-- 多模态实体关联表
CREATE TABLE IF NOT EXISTS multimodal_entity_links (
id TEXT PRIMARY KEY,
entity_id TEXT NOT NULL,
linked_entity_id TEXT NOT NULL, -- 关联的实体ID
link_type TEXT NOT NULL, -- same_as, related_to, part_of
confidence REAL DEFAULT 1.0,
evidence TEXT, -- 关联证据
modalities TEXT, -- JSON: 涉及的模态列表
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (entity_id) REFERENCES entities(id) ON DELETE CASCADE,
FOREIGN KEY (linked_entity_id) REFERENCES entities(id) ON DELETE CASCADE
);
-- 多模态相关索引
CREATE INDEX IF NOT EXISTS idx_videos_project ON videos(project_id);
CREATE INDEX IF NOT EXISTS idx_videos_status ON videos(status);
CREATE INDEX IF NOT EXISTS idx_video_frames_video ON video_frames(video_id);
CREATE INDEX IF NOT EXISTS idx_images_project ON images(project_id);
CREATE INDEX IF NOT EXISTS idx_images_status ON images(status);
CREATE INDEX IF NOT EXISTS idx_multimodal_mentions_project ON multimodal_mentions(project_id);
CREATE INDEX IF NOT EXISTS idx_multimodal_mentions_entity ON multimodal_mentions(entity_id);
CREATE INDEX IF NOT EXISTS idx_multimodal_mentions_modality ON multimodal_mentions(modality);
CREATE INDEX IF NOT EXISTS idx_multimodal_mentions_source ON multimodal_mentions(source_id);
CREATE INDEX IF NOT EXISTS idx_multimodal_links_entity ON multimodal_entity_links(entity_id);
CREATE INDEX IF NOT EXISTS idx_multimodal_links_linked ON multimodal_entity_links(linked_entity_id);
-- Phase 7 Task 7: 插件与集成相关表
-- 插件配置表
CREATE TABLE IF NOT EXISTS plugins (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
plugin_type TEXT NOT NULL, -- chrome_extension, feishu_bot, dingtalk_bot, zapier, make, webdav, custom
project_id TEXT,
status TEXT DEFAULT 'active', -- active, inactive, error, pending
config TEXT, -- JSON: plugin specific configuration
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_used_at TIMESTAMP,
use_count INTEGER DEFAULT 0,
FOREIGN KEY (project_id) REFERENCES projects(id)
);
-- 插件详细配置表
CREATE TABLE IF NOT EXISTS plugin_configs (
id TEXT PRIMARY KEY,
plugin_id TEXT NOT NULL,
config_key TEXT NOT NULL,
config_value TEXT,
is_encrypted BOOLEAN DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (plugin_id) REFERENCES plugins(id) ON DELETE CASCADE,
UNIQUE(plugin_id, config_key)
);
-- 机器人会话表
CREATE TABLE IF NOT EXISTS bot_sessions (
id TEXT PRIMARY KEY,
bot_type TEXT NOT NULL, -- feishu, dingtalk
session_id TEXT NOT NULL, -- 群ID或会话ID
session_name TEXT NOT NULL,
project_id TEXT,
webhook_url TEXT,
secret TEXT, -- 签名密钥
is_active BOOLEAN DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_message_at TIMESTAMP,
message_count INTEGER DEFAULT 0,
FOREIGN KEY (project_id) REFERENCES projects(id)
);
-- Webhook 端点表Zapier/Make集成
CREATE TABLE IF NOT EXISTS webhook_endpoints (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
endpoint_type TEXT NOT NULL, -- zapier, make, custom
endpoint_url TEXT NOT NULL,
project_id TEXT,
auth_type TEXT DEFAULT 'none', -- none, api_key, oauth, custom
auth_config TEXT, -- JSON: authentication configuration
trigger_events TEXT, -- JSON array: events that trigger this webhook
is_active BOOLEAN DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_triggered_at TIMESTAMP,
trigger_count INTEGER DEFAULT 0,
FOREIGN KEY (project_id) REFERENCES projects(id)
);
-- WebDAV 同步配置表
CREATE TABLE IF NOT EXISTS webdav_syncs (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
project_id TEXT NOT NULL,
server_url TEXT NOT NULL,
username TEXT NOT NULL,
password TEXT NOT NULL, -- 建议加密存储
remote_path TEXT DEFAULT '/insightflow',
sync_mode TEXT DEFAULT 'bidirectional', -- bidirectional, upload_only, download_only
sync_interval INTEGER DEFAULT 3600, -- 秒
last_sync_at TIMESTAMP,
last_sync_status TEXT DEFAULT 'pending', -- pending, success, failed
last_sync_error TEXT,
is_active BOOLEAN DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
sync_count INTEGER DEFAULT 0,
FOREIGN KEY (project_id) REFERENCES projects(id)
);
-- Chrome 扩展令牌表
CREATE TABLE IF NOT EXISTS chrome_extension_tokens (
id TEXT PRIMARY KEY,
token_hash TEXT NOT NULL UNIQUE, -- SHA256 hash of the token
user_id TEXT,
project_id TEXT,
name TEXT,
permissions TEXT, -- JSON array: read, write, delete
expires_at TIMESTAMP,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_used_at TIMESTAMP,
use_count INTEGER DEFAULT 0,
is_revoked BOOLEAN DEFAULT 0,
FOREIGN KEY (project_id) REFERENCES projects(id)
);
-- 插件相关索引
CREATE INDEX IF NOT EXISTS idx_plugins_project ON plugins(project_id);
CREATE INDEX IF NOT EXISTS idx_plugins_type ON plugins(plugin_type);
CREATE INDEX IF NOT EXISTS idx_plugins_status ON plugins(status);
CREATE INDEX IF NOT EXISTS idx_plugin_configs_plugin ON plugin_configs(plugin_id);
CREATE INDEX IF NOT EXISTS idx_bot_sessions_project ON bot_sessions(project_id);
CREATE INDEX IF NOT EXISTS idx_bot_sessions_type ON bot_sessions(bot_type);
CREATE INDEX IF NOT EXISTS idx_webhook_endpoints_project ON webhook_endpoints(project_id);
CREATE INDEX IF NOT EXISTS idx_webhook_endpoints_type ON webhook_endpoints(endpoint_type);
CREATE INDEX IF NOT EXISTS idx_webdav_syncs_project ON webdav_syncs(project_id);
CREATE INDEX IF NOT EXISTS idx_chrome_tokens_project ON chrome_extension_tokens(project_id);
CREATE INDEX IF NOT EXISTS idx_chrome_tokens_hash ON chrome_extension_tokens(token_hash);
-- ============================================
-- Phase 7 Task 6: 高级搜索与发现
-- ============================================
-- 搜索索引表
CREATE TABLE IF NOT EXISTS search_indexes (
id TEXT PRIMARY KEY,
content_id TEXT NOT NULL,
content_type TEXT NOT NULL, -- transcript, entity, relation
project_id TEXT NOT NULL,
tokens TEXT, -- JSON 数组
token_positions TEXT, -- JSON 对象
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(content_id, content_type)
);
-- 搜索词频统计表
CREATE TABLE IF NOT EXISTS search_term_freq (
term TEXT NOT NULL,
content_id TEXT NOT NULL,
content_type TEXT NOT NULL,
project_id TEXT NOT NULL,
frequency INTEGER DEFAULT 1,
positions TEXT, -- JSON 数组
PRIMARY KEY (term, content_id, content_type)
);
-- 文本 Embedding 表
CREATE TABLE IF NOT EXISTS embeddings (
id TEXT PRIMARY KEY,
content_id TEXT NOT NULL,
content_type TEXT NOT NULL,
project_id TEXT NOT NULL,
embedding TEXT, -- JSON 数组
model_name TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(content_id, content_type)
);
-- 搜索相关索引
CREATE INDEX IF NOT EXISTS idx_search_content ON search_indexes(content_id, content_type);
CREATE INDEX IF NOT EXISTS idx_search_project ON search_indexes(project_id);
CREATE INDEX IF NOT EXISTS idx_term_freq_term ON search_term_freq(term);
CREATE INDEX IF NOT EXISTS idx_term_freq_project ON search_term_freq(project_id);
CREATE INDEX IF NOT EXISTS idx_embedding_content ON embeddings(content_id, content_type);
CREATE INDEX IF NOT EXISTS idx_embedding_project ON embeddings(project_id);
-- ============================================
-- Phase 7 Task 8: 性能优化与扩展
-- ============================================
-- 缓存统计表
CREATE TABLE IF NOT EXISTS cache_stats (
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
total_requests INTEGER DEFAULT 0,
hits INTEGER DEFAULT 0,
misses INTEGER DEFAULT 0,
hit_rate REAL DEFAULT 0.0,
memory_usage INTEGER DEFAULT 0
);
-- 任务队列表
CREATE TABLE IF NOT EXISTS task_queue (
id TEXT PRIMARY KEY,
task_type TEXT NOT NULL,
status TEXT DEFAULT 'pending', -- pending, running, success, failed, retrying, cancelled
payload TEXT, -- JSON
result TEXT, -- JSON
error_message TEXT,
retry_count INTEGER DEFAULT 0,
max_retries INTEGER DEFAULT 3,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
started_at TIMESTAMP,
completed_at TIMESTAMP
);
-- 性能指标表
CREATE TABLE IF NOT EXISTS performance_metrics (
id TEXT PRIMARY KEY,
metric_type TEXT NOT NULL, -- api_response, db_query, cache_operation
endpoint TEXT,
duration_ms REAL,
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
metadata TEXT -- JSON
);
-- 性能相关索引
CREATE INDEX IF NOT EXISTS idx_cache_stats_time ON cache_stats(timestamp);
CREATE INDEX IF NOT EXISTS idx_task_status ON task_queue(status);
CREATE INDEX IF NOT EXISTS idx_task_type ON task_queue(task_type);
CREATE INDEX IF NOT EXISTS idx_task_created ON task_queue(created_at);
CREATE INDEX IF NOT EXISTS idx_metrics_type ON performance_metrics(metric_type);
CREATE INDEX IF NOT EXISTS idx_metrics_endpoint ON performance_metrics(endpoint);
CREATE INDEX IF NOT EXISTS idx_metrics_time ON performance_metrics(timestamp);
-- ============================================
-- Phase 7: 插件与集成相关表
-- ============================================
-- 插件表
CREATE TABLE IF NOT EXISTS plugins (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
plugin_type TEXT NOT NULL, -- chrome_extension, feishu_bot, dingtalk_bot, slack_bot, webhook, webdav, custom
project_id TEXT,
status TEXT DEFAULT 'active', -- active, inactive, error, pending
config TEXT, -- JSON: 插件配置
api_key TEXT UNIQUE, -- 用于认证的 API Key
api_secret TEXT, -- 用于签名验证的 Secret
webhook_url TEXT, -- 机器人 Webhook URL
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_used_at TIMESTAMP,
use_count INTEGER DEFAULT 0,
success_count INTEGER DEFAULT 0,
fail_count INTEGER DEFAULT 0,
FOREIGN KEY (project_id) REFERENCES projects(id)
);
-- 机器人会话表
CREATE TABLE IF NOT EXISTS bot_sessions (
id TEXT PRIMARY KEY,
plugin_id TEXT NOT NULL,
platform TEXT NOT NULL, -- feishu, dingtalk, slack, wechat
session_id TEXT NOT NULL, -- 平台特定的会话ID
user_id TEXT,
user_name TEXT,
project_id TEXT, -- 关联的项目ID
context TEXT, -- JSON: 会话上下文
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_message_at TIMESTAMP,
message_count INTEGER DEFAULT 0,
FOREIGN KEY (plugin_id) REFERENCES plugins(id) ON DELETE CASCADE,
FOREIGN KEY (project_id) REFERENCES projects(id),
UNIQUE(plugin_id, session_id)
);
-- Webhook 端点表(用于 Zapier/Make 集成)
CREATE TABLE IF NOT EXISTS webhook_endpoints (
id TEXT PRIMARY KEY,
plugin_id TEXT NOT NULL,
name TEXT NOT NULL,
endpoint_path TEXT NOT NULL UNIQUE, -- 如 /webhook/zapier/abc123
endpoint_type TEXT NOT NULL, -- zapier, make, custom
secret TEXT, -- 用于签名验证
allowed_events TEXT, -- JSON: 允许的事件列表
target_project_id TEXT, -- 数据导入的目标项目
is_active BOOLEAN DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_triggered_at TIMESTAMP,
trigger_count INTEGER DEFAULT 0,
FOREIGN KEY (plugin_id) REFERENCES plugins(id) ON DELETE CASCADE,
FOREIGN KEY (target_project_id) REFERENCES projects(id)
);
-- WebDAV 同步配置表
CREATE TABLE IF NOT EXISTS webdav_syncs (
id TEXT PRIMARY KEY,
plugin_id TEXT NOT NULL,
name TEXT NOT NULL,
server_url TEXT NOT NULL,
username TEXT NOT NULL,
password TEXT NOT NULL, -- 建议加密存储
remote_path TEXT DEFAULT '/',
local_path TEXT DEFAULT './sync',
sync_direction TEXT DEFAULT 'bidirectional', -- upload, download, bidirectional
sync_mode TEXT DEFAULT 'manual', -- manual, realtime, scheduled
sync_schedule TEXT, -- cron expression
file_patterns TEXT, -- JSON: 文件匹配模式列表
auto_analyze BOOLEAN DEFAULT 1, -- 同步后自动分析
last_sync_at TIMESTAMP,
last_sync_status TEXT,
is_active BOOLEAN DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
sync_count INTEGER DEFAULT 0,
FOREIGN KEY (plugin_id) REFERENCES plugins(id) ON DELETE CASCADE
);
-- 插件活动日志表
CREATE TABLE IF NOT EXISTS plugin_activity_logs (
id TEXT PRIMARY KEY,
plugin_id TEXT NOT NULL,
activity_type TEXT NOT NULL, -- message, webhook, sync, error
source TEXT NOT NULL, -- 来源标识
details TEXT, -- JSON: 详细信息
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (plugin_id) REFERENCES plugins(id) ON DELETE CASCADE
);
-- 插件相关索引
CREATE INDEX IF NOT EXISTS idx_plugins_project ON plugins(project_id);
CREATE INDEX IF NOT EXISTS idx_plugins_type ON plugins(plugin_type);
CREATE INDEX IF NOT EXISTS idx_plugins_api_key ON plugins(api_key);
CREATE INDEX IF NOT EXISTS idx_bot_sessions_plugin ON bot_sessions(plugin_id);
CREATE INDEX IF NOT EXISTS idx_bot_sessions_project ON bot_sessions(project_id);
CREATE INDEX IF NOT EXISTS idx_webhook_endpoints_plugin ON webhook_endpoints(plugin_id);
CREATE INDEX IF NOT EXISTS idx_webdav_syncs_plugin ON webdav_syncs(plugin_id);
CREATE INDEX IF NOT EXISTS idx_plugin_logs_plugin ON plugin_activity_logs(plugin_id);
CREATE INDEX IF NOT EXISTS idx_plugin_logs_type ON plugin_activity_logs(activity_type);
CREATE INDEX IF NOT EXISTS idx_plugin_logs_created ON plugin_activity_logs(created_at);
-- ============================================
-- Phase 7 Task 3: 数据安全与合规
-- ============================================
-- 审计日志表
CREATE TABLE IF NOT EXISTS audit_logs (
id TEXT PRIMARY KEY,
action_type TEXT NOT NULL, -- create, read, update, delete, login, export, etc.
user_id TEXT,
user_ip TEXT,
user_agent TEXT,
resource_type TEXT, -- project, entity, transcript, api_key, etc.
resource_id TEXT,
action_details TEXT, -- JSON: 详细操作信息
before_value TEXT, -- 变更前的值
after_value TEXT, -- 变更后的值
success INTEGER DEFAULT 1, -- 0 = 失败, 1 = 成功
error_message TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 加密配置表
CREATE TABLE IF NOT EXISTS encryption_configs (
id TEXT PRIMARY KEY,
project_id TEXT NOT NULL,
is_enabled INTEGER DEFAULT 0,
encryption_type TEXT DEFAULT 'aes-256-gcm', -- aes-256-gcm, chacha20-poly1305
key_derivation TEXT DEFAULT 'pbkdf2', -- pbkdf2, argon2
master_key_hash TEXT, -- 主密钥哈希(用于验证)
salt TEXT, -- 密钥派生盐值
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (project_id) REFERENCES projects(id)
);
-- 脱敏规则表
CREATE TABLE IF NOT EXISTS masking_rules (
id TEXT PRIMARY KEY,
project_id TEXT NOT NULL,
name TEXT NOT NULL,
rule_type TEXT NOT NULL, -- phone, email, id_card, bank_card, name, address, custom
pattern TEXT NOT NULL, -- 正则表达式
replacement TEXT NOT NULL, -- 替换模板
is_active INTEGER DEFAULT 1,
priority INTEGER DEFAULT 0,
description TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (project_id) REFERENCES projects(id)
);
-- 数据访问策略表
CREATE TABLE IF NOT EXISTS data_access_policies (
id TEXT PRIMARY KEY,
project_id TEXT NOT NULL,
name TEXT NOT NULL,
description TEXT,
allowed_users TEXT, -- JSON array: 允许访问的用户ID列表
allowed_roles TEXT, -- JSON array: 允许的角色列表
allowed_ips TEXT, -- JSON array: 允许的IP模式列表
time_restrictions TEXT, -- JSON: {"start_time": "09:00", "end_time": "18:00", "days_of_week": [0,1,2,3,4]}
max_access_count INTEGER, -- 最大访问次数限制
require_approval INTEGER DEFAULT 0, -- 是否需要审批
is_active INTEGER DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (project_id) REFERENCES projects(id)
);
-- 访问请求表(用于需要审批的访问)
CREATE TABLE IF NOT EXISTS access_requests (
id TEXT PRIMARY KEY,
policy_id TEXT NOT NULL,
user_id TEXT NOT NULL,
request_reason TEXT,
status TEXT DEFAULT 'pending', -- pending, approved, rejected, expired
approved_by TEXT,
approved_at TIMESTAMP,
expires_at TIMESTAMP,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (policy_id) REFERENCES data_access_policies(id)
);
-- 数据安全相关索引
CREATE INDEX IF NOT EXISTS idx_audit_logs_user ON audit_logs(user_id);
CREATE INDEX IF NOT EXISTS idx_audit_logs_resource ON audit_logs(resource_type, resource_id);
CREATE INDEX IF NOT EXISTS idx_audit_logs_action ON audit_logs(action_type);
CREATE INDEX IF NOT EXISTS idx_audit_logs_created ON audit_logs(created_at);
CREATE INDEX IF NOT EXISTS idx_encryption_project ON encryption_configs(project_id);
CREATE INDEX IF NOT EXISTS idx_masking_project ON masking_rules(project_id);
CREATE INDEX IF NOT EXISTS idx_access_policy_project ON data_access_policies(project_id);
CREATE INDEX IF NOT EXISTS idx_access_requests_policy ON access_requests(policy_id);
CREATE INDEX IF NOT EXISTS idx_access_requests_user ON access_requests(user_id);
-- ============================================
-- Phase 7 Task 4: 协作与共享
-- ============================================
-- 项目分享表
CREATE TABLE IF NOT EXISTS project_shares (
id TEXT PRIMARY KEY,
project_id TEXT NOT NULL,
token TEXT NOT NULL UNIQUE, -- 分享令牌
permission TEXT DEFAULT 'read_only', -- 权限级别: read_only, comment, edit, admin
created_by TEXT NOT NULL, -- 创建者
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
expires_at TIMESTAMP, -- 过期时间
max_uses INTEGER, -- 最大使用次数
use_count INTEGER DEFAULT 0, -- 已使用次数
password_hash TEXT, -- 密码保护(哈希)
is_active BOOLEAN DEFAULT 1, -- 是否激活
allow_download BOOLEAN DEFAULT 0, -- 允许下载
allow_export BOOLEAN DEFAULT 0, -- 允许导出
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
);
-- 评论表
CREATE TABLE IF NOT EXISTS comments (
id TEXT PRIMARY KEY,
project_id TEXT NOT NULL,
target_type TEXT NOT NULL, -- 目标类型: entity, relation, transcript, project
target_id TEXT NOT NULL, -- 目标ID
parent_id TEXT, -- 父评论ID(支持回复)
author TEXT NOT NULL, -- 作者ID
author_name TEXT, -- 作者显示名
content TEXT NOT NULL, -- 评论内容
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
resolved BOOLEAN DEFAULT 0, -- 是否已解决
resolved_by TEXT, -- 解决者
resolved_at TIMESTAMP, -- 解决时间
mentions TEXT, -- JSON数组: 提及的用户
attachments TEXT, -- JSON数组: 附件
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
FOREIGN KEY (parent_id) REFERENCES comments(id) ON DELETE CASCADE
);
-- 变更历史表
CREATE TABLE IF NOT EXISTS change_history (
id TEXT PRIMARY KEY,
project_id TEXT NOT NULL,
change_type TEXT NOT NULL, -- 变更类型: create, update, delete, merge, split
entity_type TEXT NOT NULL, -- 实体类型: entity, relation, transcript, project
entity_id TEXT NOT NULL, -- 实体ID
entity_name TEXT, -- 实体名称(用于显示)
changed_by TEXT NOT NULL, -- 变更者ID
changed_by_name TEXT, -- 变更者显示名
changed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
old_value TEXT, -- JSON: 旧值
new_value TEXT, -- JSON: 新值
description TEXT, -- 变更描述
session_id TEXT, -- 会话ID(批量变更关联)
reverted BOOLEAN DEFAULT 0, -- 是否已回滚
reverted_at TIMESTAMP, -- 回滚时间
reverted_by TEXT, -- 回滚者
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
);
-- 团队成员表
CREATE TABLE IF NOT EXISTS team_members (
id TEXT PRIMARY KEY,
project_id TEXT NOT NULL,
user_id TEXT NOT NULL, -- 用户ID
user_name TEXT, -- 用户名
user_email TEXT, -- 用户邮箱
role TEXT DEFAULT 'viewer', -- 角色: owner, admin, editor, viewer, commenter
joined_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
invited_by TEXT, -- 邀请者
last_active_at TIMESTAMP, -- 最后活跃时间
permissions TEXT, -- JSON数组: 具体权限列表
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
UNIQUE(project_id, user_id) -- 每个项目每个用户只能有一条记录
);
-- 协作与共享相关索引
CREATE INDEX IF NOT EXISTS idx_shares_project ON project_shares(project_id);
CREATE INDEX IF NOT EXISTS idx_shares_token ON project_shares(token);
CREATE INDEX IF NOT EXISTS idx_comments_project ON comments(project_id);
CREATE INDEX IF NOT EXISTS idx_comments_target ON comments(target_type, target_id);
CREATE INDEX IF NOT EXISTS idx_comments_parent ON comments(parent_id);
CREATE INDEX IF NOT EXISTS idx_change_history_project ON change_history(project_id);
CREATE INDEX IF NOT EXISTS idx_change_history_entity ON change_history(entity_type, entity_id);
CREATE INDEX IF NOT EXISTS idx_change_history_session ON change_history(session_id);
CREATE INDEX IF NOT EXISTS idx_team_members_project ON team_members(project_id);
CREATE INDEX IF NOT EXISTS idx_team_members_user ON team_members(user_id);
-- ============================================
-- Phase 7 Task 6: 高级搜索与发现
-- ============================================
-- 搜索索引表
CREATE TABLE IF NOT EXISTS search_indexes (
id TEXT PRIMARY KEY,
project_id TEXT NOT NULL,
content_type TEXT NOT NULL, -- transcript, entity, relation
content_id TEXT NOT NULL,
content_text TEXT NOT NULL,
tokens TEXT, -- JSON array of tokens
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (project_id) REFERENCES projects(id),
UNIQUE(project_id, content_type, content_id)
);
-- 文本 Embedding 表
CREATE TABLE IF NOT EXISTS embeddings (
id TEXT PRIMARY KEY,
project_id TEXT NOT NULL,
content_type TEXT NOT NULL, -- transcript, entity
content_id TEXT NOT NULL,
text TEXT NOT NULL,
embedding TEXT NOT NULL, -- JSON array of floats
model TEXT NOT NULL, -- 使用的模型名称
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (project_id) REFERENCES projects(id),
UNIQUE(project_id, content_type, content_id)
);
-- 全文搜索虚拟表 (FTS5)
CREATE VIRTUAL TABLE IF NOT EXISTS fts_transcripts USING fts5(
content_text,
content_id UNINDEXED,
project_id UNINDEXED,
content_type UNINDEXED
);
-- 搜索相关索引
CREATE INDEX IF NOT EXISTS idx_search_indexes_project ON search_indexes(project_id);
CREATE INDEX IF NOT EXISTS idx_search_indexes_type ON search_indexes(content_type);
CREATE INDEX IF NOT EXISTS idx_search_indexes_content ON search_indexes(content_id);
CREATE INDEX IF NOT EXISTS idx_embeddings_project ON embeddings(project_id);
CREATE INDEX IF NOT EXISTS idx_embeddings_type ON embeddings(content_type);
CREATE INDEX IF NOT EXISTS idx_embeddings_content ON embeddings(content_id);
CREATE INDEX IF NOT EXISTS idx_embeddings_model ON embeddings(model);
-- ============================================
-- Phase 7 Task 8: 性能优化与扩展
-- ============================================
-- 缓存统计表
CREATE TABLE IF NOT EXISTS cache_stats (
id TEXT PRIMARY KEY,
stat_date DATE NOT NULL,
cache_type TEXT NOT NULL, -- redis, memory
total_keys INTEGER DEFAULT 0,
memory_usage INTEGER DEFAULT 0, -- bytes
hit_count INTEGER DEFAULT 0,
miss_count INTEGER DEFAULT 0,
evicted_count INTEGER DEFAULT 0,
expired_count INTEGER DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(stat_date, cache_type)
);
-- 任务队列表
CREATE TABLE IF NOT EXISTS task_queue (
id TEXT PRIMARY KEY,
task_type TEXT NOT NULL, -- audio_analysis, report_generation, entity_extraction
status TEXT NOT NULL, -- pending, running, success, failure, retry, revoked
project_id TEXT NOT NULL,
params TEXT NOT NULL, -- JSON
result TEXT, -- JSON
error TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
started_at TIMESTAMP,
completed_at TIMESTAMP,
retry_count INTEGER DEFAULT 0,
priority INTEGER DEFAULT 5, -- 0=high, 5=normal, 10=low
worker_id TEXT, -- 执行任务的 worker
FOREIGN KEY (project_id) REFERENCES projects(id)
);
-- 性能指标表
CREATE TABLE IF NOT EXISTS performance_metrics (
id TEXT PRIMARY KEY,
metric_type TEXT NOT NULL, -- api_response, db_query, cache_operation
endpoint TEXT NOT NULL,
duration_ms REAL NOT NULL,
status_code INTEGER,
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
metadata TEXT -- JSON: 额外信息
);
-- 数据库分片映射表
CREATE TABLE IF NOT EXISTS shard_mappings (
id TEXT PRIMARY KEY,
project_id TEXT NOT NULL UNIQUE,
shard_id TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
migrated_at TIMESTAMP,
FOREIGN KEY (project_id) REFERENCES projects(id)
);
-- 性能相关索引
CREATE INDEX IF NOT EXISTS idx_cache_stats_date ON cache_stats(stat_date);
CREATE INDEX IF NOT EXISTS idx_task_queue_project ON task_queue(project_id);
CREATE INDEX IF NOT EXISTS idx_task_queue_status ON task_queue(status);
CREATE INDEX IF NOT EXISTS idx_task_queue_type ON task_queue(task_type);
CREATE INDEX IF NOT EXISTS idx_task_queue_created ON task_queue(created_at);
CREATE INDEX IF NOT EXISTS idx_metrics_type ON performance_metrics(metric_type);
CREATE INDEX IF NOT EXISTS idx_metrics_endpoint ON performance_metrics(endpoint);
CREATE INDEX IF NOT EXISTS idx_metrics_timestamp ON performance_metrics(timestamp);
CREATE INDEX IF NOT EXISTS idx_shard_mappings_project ON shard_mappings(project_id);
CREATE INDEX IF NOT EXISTS idx_shard_mappings_shard ON shard_mappings(shard_id);
-- ============================================
-- Phase 8 Task 1: 多租户 SaaS 架构
-- ============================================
-- 租户主表
CREATE TABLE IF NOT EXISTS tenants (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
slug TEXT UNIQUE NOT NULL,
description TEXT,
tier TEXT DEFAULT 'free',
status TEXT DEFAULT 'pending',
owner_id TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
expires_at TIMESTAMP,
settings TEXT DEFAULT '{}',
resource_limits TEXT DEFAULT '{}',
metadata TEXT DEFAULT '{}'
);
-- 租户域名表
CREATE TABLE IF NOT EXISTS tenant_domains (
id TEXT PRIMARY KEY,
tenant_id TEXT NOT NULL,
domain TEXT UNIQUE NOT NULL,
status TEXT DEFAULT 'pending',
verification_token TEXT NOT NULL,
verification_method TEXT DEFAULT 'dns',
verified_at TIMESTAMP,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
is_primary INTEGER DEFAULT 0,
ssl_enabled INTEGER DEFAULT 0,
ssl_expires_at TIMESTAMP,
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE
);
-- 租户品牌配置表
CREATE TABLE IF NOT EXISTS tenant_branding (
id TEXT PRIMARY KEY,
tenant_id TEXT UNIQUE NOT NULL,
logo_url TEXT,
favicon_url TEXT,
primary_color TEXT,
secondary_color TEXT,
custom_css TEXT,
custom_js TEXT,
login_page_bg TEXT,
email_template TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE
);
-- 租户成员表
CREATE TABLE IF NOT EXISTS tenant_members (
id TEXT PRIMARY KEY,
tenant_id TEXT NOT NULL,
user_id TEXT, -- NULL for pending invitations
email TEXT NOT NULL,
role TEXT DEFAULT 'member',
permissions TEXT DEFAULT '[]',
invited_by TEXT,
invited_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
joined_at TIMESTAMP,
last_active_at TIMESTAMP,
status TEXT DEFAULT 'pending',
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE
);
-- 租户权限定义表
CREATE TABLE IF NOT EXISTS tenant_permissions (
id TEXT PRIMARY KEY,
tenant_id TEXT NOT NULL,
name TEXT NOT NULL,
code TEXT NOT NULL,
description TEXT,
resource_type TEXT NOT NULL,
actions TEXT NOT NULL,
conditions TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE,
UNIQUE(tenant_id, code)
);
-- 租户资源使用统计表
CREATE TABLE IF NOT EXISTS tenant_usage (
id TEXT PRIMARY KEY,
tenant_id TEXT NOT NULL,
date DATE NOT NULL,
storage_bytes INTEGER DEFAULT 0,
transcription_seconds INTEGER DEFAULT 0,
api_calls INTEGER DEFAULT 0,
projects_count INTEGER DEFAULT 0,
entities_count INTEGER DEFAULT 0,
members_count INTEGER DEFAULT 0,
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE,
UNIQUE(tenant_id, date)
);
-- 租户相关索引
CREATE INDEX IF NOT EXISTS idx_tenants_slug ON tenants(slug);
CREATE INDEX IF NOT EXISTS idx_tenants_owner ON tenants(owner_id);
CREATE INDEX IF NOT EXISTS idx_tenants_status ON tenants(status);
CREATE INDEX IF NOT EXISTS idx_domains_tenant ON tenant_domains(tenant_id);
CREATE INDEX IF NOT EXISTS idx_domains_domain ON tenant_domains(domain);
CREATE INDEX IF NOT EXISTS idx_domains_status ON tenant_domains(status);
CREATE INDEX IF NOT EXISTS idx_members_tenant ON tenant_members(tenant_id);
CREATE INDEX IF NOT EXISTS idx_members_user ON tenant_members(user_id);
CREATE INDEX IF NOT EXISTS idx_usage_tenant ON tenant_usage(tenant_id);
CREATE INDEX IF NOT EXISTS idx_usage_date ON tenant_usage(date);
-- ============================================
-- Phase 8 Task 2: 订阅与计费系统
-- ============================================
-- 订阅计划表
CREATE TABLE IF NOT EXISTS subscription_plans (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
tier TEXT UNIQUE NOT NULL, -- free/pro/enterprise
description TEXT,
price_monthly REAL DEFAULT 0,
price_yearly REAL DEFAULT 0,
currency TEXT DEFAULT 'CNY',
features TEXT DEFAULT '[]', -- JSON array
limits TEXT DEFAULT '{}', -- JSON object
is_active INTEGER DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
metadata TEXT DEFAULT '{}'
);
-- 订阅表
CREATE TABLE IF NOT EXISTS subscriptions (
id TEXT PRIMARY KEY,
tenant_id TEXT NOT NULL,
plan_id TEXT NOT NULL,
status TEXT DEFAULT 'pending', -- active/cancelled/expired/past_due/trial/pending
current_period_start TIMESTAMP,
current_period_end TIMESTAMP,
cancel_at_period_end INTEGER DEFAULT 0,
canceled_at TIMESTAMP,
trial_start TIMESTAMP,
trial_end TIMESTAMP,
payment_provider TEXT, -- stripe/alipay/wechat/bank_transfer
provider_subscription_id TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
metadata TEXT DEFAULT '{}',
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE,
FOREIGN KEY (plan_id) REFERENCES subscription_plans(id)
);
-- 用量记录表
CREATE TABLE IF NOT EXISTS usage_records (
id TEXT PRIMARY KEY,
tenant_id TEXT NOT NULL,
resource_type TEXT NOT NULL, -- transcription/storage/api_call/export
quantity REAL DEFAULT 0,
unit TEXT NOT NULL, -- minutes/mb/count/page
recorded_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
cost REAL DEFAULT 0,
description TEXT,
metadata TEXT DEFAULT '{}',
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE
);
-- 支付记录表
CREATE TABLE IF NOT EXISTS payments (
id TEXT PRIMARY KEY,
tenant_id TEXT NOT NULL,
subscription_id TEXT,
invoice_id TEXT,
amount REAL NOT NULL,
currency TEXT DEFAULT 'CNY',
provider TEXT NOT NULL, -- stripe/alipay/wechat/bank_transfer
provider_payment_id TEXT,
status TEXT DEFAULT 'pending', -- pending/processing/completed/failed/refunded/partial_refunded
payment_method TEXT,
payment_details TEXT DEFAULT '{}', -- JSON
paid_at TIMESTAMP,
failed_at TIMESTAMP,
failure_reason TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE,
FOREIGN KEY (subscription_id) REFERENCES subscriptions(id) ON DELETE SET NULL,
FOREIGN KEY (invoice_id) REFERENCES invoices(id) ON DELETE SET NULL
);
-- 发票表
CREATE TABLE IF NOT EXISTS invoices (
id TEXT PRIMARY KEY,
tenant_id TEXT NOT NULL,
subscription_id TEXT,
invoice_number TEXT UNIQUE NOT NULL,
status TEXT DEFAULT 'draft', -- draft/issued/paid/overdue/void/credit_note
amount_due REAL DEFAULT 0,
amount_paid REAL DEFAULT 0,
currency TEXT DEFAULT 'CNY',
period_start TIMESTAMP,
period_end TIMESTAMP,
description TEXT,
line_items TEXT DEFAULT '[]', -- JSON array
due_date TIMESTAMP,
paid_at TIMESTAMP,
voided_at TIMESTAMP,
void_reason TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE,
FOREIGN KEY (subscription_id) REFERENCES subscriptions(id) ON DELETE SET NULL
);
-- 退款表
CREATE TABLE IF NOT EXISTS refunds (
id TEXT PRIMARY KEY,
tenant_id TEXT NOT NULL,
payment_id TEXT NOT NULL,
invoice_id TEXT,
amount REAL NOT NULL,
currency TEXT DEFAULT 'CNY',
reason TEXT,
status TEXT DEFAULT 'pending', -- pending/approved/rejected/completed/failed
requested_by TEXT NOT NULL,
requested_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
approved_by TEXT,
approved_at TIMESTAMP,
completed_at TIMESTAMP,
provider_refund_id TEXT,
metadata TEXT DEFAULT '{}',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE,
FOREIGN KEY (payment_id) REFERENCES payments(id) ON DELETE CASCADE,
FOREIGN KEY (invoice_id) REFERENCES invoices(id) ON DELETE SET NULL
);
-- 账单历史表
CREATE TABLE IF NOT EXISTS billing_history (
id TEXT PRIMARY KEY,
tenant_id TEXT NOT NULL,
type TEXT NOT NULL, -- subscription/usage/payment/refund
amount REAL NOT NULL,
currency TEXT DEFAULT 'CNY',
description TEXT,
reference_id TEXT, -- 关联的订阅/支付/退款ID
balance_after REAL DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
metadata TEXT DEFAULT '{}',
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE
);
-- 订阅相关索引
CREATE INDEX IF NOT EXISTS idx_subscriptions_tenant ON subscriptions(tenant_id);
CREATE INDEX IF NOT EXISTS idx_subscriptions_status ON subscriptions(status);
CREATE INDEX IF NOT EXISTS idx_subscriptions_plan ON subscriptions(plan_id);
CREATE INDEX IF NOT EXISTS idx_usage_records_tenant ON usage_records(tenant_id);
CREATE INDEX IF NOT EXISTS idx_usage_records_type ON usage_records(resource_type);
CREATE INDEX IF NOT EXISTS idx_usage_records_recorded ON usage_records(recorded_at);
CREATE INDEX IF NOT EXISTS idx_payments_tenant ON payments(tenant_id);
CREATE INDEX IF NOT EXISTS idx_payments_status ON payments(status);
CREATE INDEX IF NOT EXISTS idx_payments_provider ON payments(provider);
CREATE INDEX IF NOT EXISTS idx_invoices_tenant ON invoices(tenant_id);
CREATE INDEX IF NOT EXISTS idx_invoices_status ON invoices(status);
CREATE INDEX IF NOT EXISTS idx_invoices_number ON invoices(invoice_number);
CREATE INDEX IF NOT EXISTS idx_refunds_tenant ON refunds(tenant_id);
CREATE INDEX IF NOT EXISTS idx_refunds_status ON refunds(status);
CREATE INDEX IF NOT EXISTS idx_refunds_payment ON refunds(payment_id);
CREATE INDEX IF NOT EXISTS idx_billing_history_tenant ON billing_history(tenant_id);
CREATE INDEX IF NOT EXISTS idx_billing_history_created ON billing_history(created_at);
CREATE INDEX IF NOT EXISTS idx_billing_history_type ON billing_history(type);
-- ============================================
-- Phase 8 Task 3: 企业级功能
-- ============================================
-- SSO 配置表
CREATE TABLE IF NOT EXISTS sso_configs (
id TEXT PRIMARY KEY,
tenant_id TEXT NOT NULL,
provider TEXT NOT NULL, -- wechat_work/dingtalk/feishu/okta/azure_ad/google/custom_saml
status TEXT DEFAULT 'disabled', -- disabled/pending/active/error
entity_id TEXT,
sso_url TEXT,
slo_url TEXT,
certificate TEXT, -- X.509 证书
metadata_url TEXT,
metadata_xml TEXT,
client_id TEXT,
client_secret TEXT,
authorization_url TEXT,
token_url TEXT,
userinfo_url TEXT,
scopes TEXT DEFAULT '["openid", "email", "profile"]',
attribute_mapping TEXT DEFAULT '{}', -- JSON: 属性映射
auto_provision INTEGER DEFAULT 1, -- 自动创建用户
default_role TEXT DEFAULT 'member',
domain_restriction TEXT DEFAULT '[]', -- JSON: 允许的邮箱域名
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_tested_at TIMESTAMP,
last_error TEXT,
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE
);
-- SAML 认证请求表
CREATE TABLE IF NOT EXISTS saml_auth_requests (
id TEXT PRIMARY KEY,
tenant_id TEXT NOT NULL,
sso_config_id TEXT NOT NULL,
request_id TEXT NOT NULL UNIQUE,
relay_state TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
expires_at TIMESTAMP NOT NULL,
used INTEGER DEFAULT 0,
used_at TIMESTAMP,
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE,
FOREIGN KEY (sso_config_id) REFERENCES sso_configs(id) ON DELETE CASCADE
);
-- SAML 认证响应表
CREATE TABLE IF NOT EXISTS saml_auth_responses (
id TEXT PRIMARY KEY,
request_id TEXT NOT NULL,
tenant_id TEXT NOT NULL,
user_id TEXT,
email TEXT,
name TEXT,
attributes TEXT DEFAULT '{}', -- JSON: SAML 属性
session_index TEXT,
processed INTEGER DEFAULT 0,
processed_at TIMESTAMP,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (request_id) REFERENCES saml_auth_requests(request_id) ON DELETE CASCADE,
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE
);
-- SCIM 配置表
CREATE TABLE IF NOT EXISTS scim_configs (
id TEXT PRIMARY KEY,
tenant_id TEXT NOT NULL,
provider TEXT NOT NULL,
status TEXT DEFAULT 'disabled',
scim_base_url TEXT,
scim_token TEXT,
sync_interval_minutes INTEGER DEFAULT 60,
last_sync_at TIMESTAMP,
last_sync_status TEXT,
last_sync_error TEXT,
last_sync_users_count INTEGER DEFAULT 0,
attribute_mapping TEXT DEFAULT '{}',
sync_rules TEXT DEFAULT '{}',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE
);
-- SCIM 用户表
CREATE TABLE IF NOT EXISTS scim_users (
id TEXT PRIMARY KEY,
tenant_id TEXT NOT NULL,
external_id TEXT NOT NULL,
user_name TEXT NOT NULL,
email TEXT NOT NULL,
display_name TEXT,
given_name TEXT,
family_name TEXT,
active INTEGER DEFAULT 1,
groups TEXT DEFAULT '[]',
raw_data TEXT DEFAULT '{}',
synced_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE,
UNIQUE(tenant_id, external_id)
);
-- 审计日志导出表
CREATE TABLE IF NOT EXISTS audit_log_exports (
id TEXT PRIMARY KEY,
tenant_id TEXT NOT NULL,
export_format TEXT NOT NULL, -- json/csv/pdf/xlsx
start_date TIMESTAMP NOT NULL,
end_date TIMESTAMP NOT NULL,
filters TEXT DEFAULT '{}',
compliance_standard TEXT, -- soc2/iso27001/gdpr/hipaa/pci_dss
status TEXT DEFAULT 'pending', -- pending/processing/completed/failed
file_path TEXT,
file_size INTEGER,
record_count INTEGER,
checksum TEXT,
downloaded_by TEXT,
downloaded_at TIMESTAMP,
expires_at TIMESTAMP,
created_by TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
completed_at TIMESTAMP,
error_message TEXT,
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE
);
-- 数据保留策略表
CREATE TABLE IF NOT EXISTS data_retention_policies (
id TEXT PRIMARY KEY,
tenant_id TEXT NOT NULL,
name TEXT NOT NULL,
description TEXT,
resource_type TEXT NOT NULL, -- project/transcript/entity/audit_log/user_data
retention_days INTEGER NOT NULL,
action TEXT NOT NULL, -- archive/delete/anonymize
conditions TEXT DEFAULT '{}',
auto_execute INTEGER DEFAULT 0,
execute_at TEXT, -- cron 表达式
notify_before_days INTEGER DEFAULT 7,
archive_location TEXT,
archive_encryption INTEGER DEFAULT 1,
is_active INTEGER DEFAULT 1,
last_executed_at TIMESTAMP,
last_execution_result TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE
);
-- 数据保留任务表
CREATE TABLE IF NOT EXISTS data_retention_jobs (
id TEXT PRIMARY KEY,
policy_id TEXT NOT NULL,
tenant_id TEXT NOT NULL,
status TEXT DEFAULT 'pending', -- pending/running/completed/failed
started_at TIMESTAMP,
completed_at TIMESTAMP,
affected_records INTEGER DEFAULT 0,
archived_records INTEGER DEFAULT 0,
deleted_records INTEGER DEFAULT 0,
error_count INTEGER DEFAULT 0,
details TEXT DEFAULT '{}',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (policy_id) REFERENCES data_retention_policies(id) ON DELETE CASCADE,
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE
);
-- 企业级功能相关索引
CREATE INDEX IF NOT EXISTS idx_sso_tenant ON sso_configs(tenant_id);
CREATE INDEX IF NOT EXISTS idx_sso_provider ON sso_configs(provider);
CREATE INDEX IF NOT EXISTS idx_saml_requests_config ON saml_auth_requests(sso_config_id);
CREATE INDEX IF NOT EXISTS idx_saml_requests_expires ON saml_auth_requests(expires_at);
CREATE INDEX IF NOT EXISTS idx_saml_responses_request ON saml_auth_responses(request_id);
CREATE INDEX IF NOT EXISTS idx_scim_config_tenant ON scim_configs(tenant_id);
CREATE INDEX IF NOT EXISTS idx_scim_users_tenant ON scim_users(tenant_id);
CREATE INDEX IF NOT EXISTS idx_scim_users_external ON scim_users(external_id);
CREATE INDEX IF NOT EXISTS idx_audit_export_tenant ON audit_log_exports(tenant_id);
CREATE INDEX IF NOT EXISTS idx_audit_export_status ON audit_log_exports(status);
CREATE INDEX IF NOT EXISTS idx_retention_tenant ON data_retention_policies(tenant_id);
CREATE INDEX IF NOT EXISTS idx_retention_type ON data_retention_policies(resource_type);
CREATE INDEX IF NOT EXISTS idx_retention_jobs_policy ON data_retention_jobs(policy_id);
CREATE INDEX IF NOT EXISTS idx_retention_jobs_status ON data_retention_jobs(status);