fix(database): sync init.sql schema with all migrations for 100% consistency

init.sql 作为全新部署的基础 schema,必须与所有 migration 的累积效果一致。
之前存在大量不一致:

1. 所有表缺少 tenant_id 列(migration 20260126 添加):
   - users, conversations, messages, orders, payments, ledger_entries
   - daily_statistics, monthly_financial_reports, audit_logs, evolution_logs
   - documents, document_embeddings, knowledge_articles, knowledge_chunks
   - user_memories, experiences, verification_codes, service_pricing
   - coupons, user_coupons, admin_users, admins
   - 每个表同步添加了 idx_xxx_tenant 索引

2. admins 表缺少 is_super_admin 列(migration 20260126 添加)

3. 缺少 4 个完整表定义(来自 migration 和 TypeORM entity):
   - token_usages: API 调用 Token 消耗记录
   - files: 用户上传文件管理(含软删除)
   - mcp_server_configs: MCP Server 运行时配置(migration 20260206)
   - evaluation_rules: 评估门控规则配置(migration 20260206)

现在 init.sql(全新部署)= init.sql + 所有 migrations(增量升级)= 完全一致

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
hailin 2026-02-06 22:33:41 -08:00
parent 68ffa6b7eb
commit 897b86db26
1 changed files with 256 additions and 0 deletions

View File

@ -13,6 +13,8 @@ CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; -- UUID生成函数
-- =========================================== -- ===========================================
CREATE TABLE users ( CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
-- 租户ID多租户支持
tenant_id UUID,
-- 用户类型: ANONYMOUS(匿名访客), REGISTERED(已注册用户) -- 用户类型: ANONYMOUS(匿名访客), REGISTERED(已注册用户)
type VARCHAR(20) NOT NULL DEFAULT 'ANONYMOUS' type VARCHAR(20) NOT NULL DEFAULT 'ANONYMOUS'
CHECK (type IN ('ANONYMOUS', 'REGISTERED')), CHECK (type IN ('ANONYMOUS', 'REGISTERED')),
@ -48,6 +50,9 @@ COMMENT ON COLUMN users.fingerprint IS '浏览器指纹,用于识别和关联
COMMENT ON COLUMN users.source_channel IS '用户来源渠道,用于统计分析'; COMMENT ON COLUMN users.source_channel IS '用户来源渠道,用于统计分析';
COMMENT ON COLUMN users.tags IS '用户标签JSON数组格式用于用户分群'; COMMENT ON COLUMN users.tags IS '用户标签JSON数组格式用于用户分群';
CREATE INDEX idx_users_tenant ON users(tenant_id);
CREATE INDEX idx_users_tenant_phone ON users(tenant_id, phone);
CREATE INDEX idx_users_tenant_fingerprint ON users(tenant_id, fingerprint);
CREATE INDEX idx_users_fingerprint ON users(fingerprint); CREATE INDEX idx_users_fingerprint ON users(fingerprint);
CREATE INDEX idx_users_phone ON users(phone); CREATE INDEX idx_users_phone ON users(phone);
CREATE INDEX idx_users_type ON users(type); CREATE INDEX idx_users_type ON users(type);
@ -60,6 +65,8 @@ CREATE INDEX idx_users_created_at ON users(created_at);
-- =========================================== -- ===========================================
CREATE TABLE conversations ( CREATE TABLE conversations (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
-- 租户ID多租户支持
tenant_id UUID,
-- 所属用户ID -- 所属用户ID
user_id UUID REFERENCES users(id) ON DELETE CASCADE, user_id UUID REFERENCES users(id) ON DELETE CASCADE,
-- 对话状态: ACTIVE(进行中), ENDED(已结束), ARCHIVED(已归档), DELETED(软删除) -- 对话状态: ACTIVE(进行中), ENDED(已结束), ARCHIVED(已归档), DELETED(软删除)
@ -99,6 +106,7 @@ COMMENT ON COLUMN conversations.category IS '主要咨询的移民类别,用
COMMENT ON COLUMN conversations.has_converted IS '是否产生付费转化,用于计算转化率'; COMMENT ON COLUMN conversations.has_converted IS '是否产生付费转化,用于计算转化率';
COMMENT ON COLUMN conversations.rating IS '用户对对话的评分1-5分'; COMMENT ON COLUMN conversations.rating IS '用户对对话的评分1-5分';
CREATE INDEX idx_conversations_tenant ON conversations(tenant_id);
CREATE INDEX idx_conversations_user_id ON conversations(user_id); CREATE INDEX idx_conversations_user_id ON conversations(user_id);
CREATE INDEX idx_conversations_status ON conversations(status); CREATE INDEX idx_conversations_status ON conversations(status);
CREATE INDEX idx_conversations_category ON conversations(category); CREATE INDEX idx_conversations_category ON conversations(category);
@ -111,6 +119,8 @@ CREATE INDEX idx_conversations_has_converted ON conversations(has_converted) WHE
-- =========================================== -- ===========================================
CREATE TABLE messages ( CREATE TABLE messages (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
-- 租户ID多租户支持
tenant_id UUID,
-- 所属对话ID -- 所属对话ID
conversation_id UUID REFERENCES conversations(id) ON DELETE CASCADE, conversation_id UUID REFERENCES conversations(id) ON DELETE CASCADE,
-- 消息角色: user(用户), assistant(AI助手), system(系统) -- 消息角色: user(用户), assistant(AI助手), system(系统)
@ -134,6 +144,7 @@ COMMENT ON COLUMN messages.role IS '消息角色: user=用户发送, assistant=A
COMMENT ON COLUMN messages.type IS '消息类型,用于区分普通文本、工具调用、支付请求等'; COMMENT ON COLUMN messages.type IS '消息类型,用于区分普通文本、工具调用、支付请求等';
COMMENT ON COLUMN messages.metadata IS '元数据,存储工具调用参数、结果等扩展信息'; COMMENT ON COLUMN messages.metadata IS '元数据,存储工具调用参数、结果等扩展信息';
CREATE INDEX idx_messages_tenant ON messages(tenant_id);
CREATE INDEX idx_messages_conversation_id ON messages(conversation_id); CREATE INDEX idx_messages_conversation_id ON messages(conversation_id);
CREATE INDEX idx_messages_role ON messages(role); CREATE INDEX idx_messages_role ON messages(role);
CREATE INDEX idx_messages_created_at ON messages(created_at); CREATE INDEX idx_messages_created_at ON messages(created_at);
@ -144,6 +155,8 @@ CREATE INDEX idx_messages_created_at ON messages(created_at);
-- =========================================== -- ===========================================
CREATE TABLE orders ( CREATE TABLE orders (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
-- 租户ID多租户支持
tenant_id UUID,
-- 订单号用于展示格式ORD + 年月日 + 序号) -- 订单号用于展示格式ORD + 年月日 + 序号)
order_no VARCHAR(50) UNIQUE, order_no VARCHAR(50) UNIQUE,
-- 所属用户ID -- 所属用户ID
@ -199,6 +212,7 @@ COMMENT ON COLUMN orders.order_no IS '订单号,用于对外展示,格式:
COMMENT ON COLUMN orders.service_type IS '服务类型: ASSESSMENT=移民评估, CONSULTATION=付费咨询, DOCUMENT_REVIEW=文档审核'; COMMENT ON COLUMN orders.service_type IS '服务类型: ASSESSMENT=移民评估, CONSULTATION=付费咨询, DOCUMENT_REVIEW=文档审核';
COMMENT ON COLUMN orders.metadata IS '扩展数据,如评估结果详情等'; COMMENT ON COLUMN orders.metadata IS '扩展数据,如评估结果详情等';
CREATE INDEX idx_orders_tenant ON orders(tenant_id);
CREATE INDEX idx_orders_order_no ON orders(order_no); CREATE INDEX idx_orders_order_no ON orders(order_no);
CREATE INDEX idx_orders_user_id ON orders(user_id); CREATE INDEX idx_orders_user_id ON orders(user_id);
CREATE INDEX idx_orders_status ON orders(status); CREATE INDEX idx_orders_status ON orders(status);
@ -212,6 +226,8 @@ CREATE INDEX idx_orders_paid_at ON orders(paid_at) WHERE paid_at IS NOT NULL;
-- =========================================== -- ===========================================
CREATE TABLE payments ( CREATE TABLE payments (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
-- 租户ID多租户支持
tenant_id UUID,
-- 关联的订单ID -- 关联的订单ID
order_id UUID REFERENCES orders(id) ON DELETE CASCADE, order_id UUID REFERENCES orders(id) ON DELETE CASCADE,
-- 支付方式 -- 支付方式
@ -247,6 +263,7 @@ COMMENT ON TABLE payments IS '支付表 - 存储支付交易记录';
COMMENT ON COLUMN payments.transaction_id IS '第三方支付平台的交易号,用于对账'; COMMENT ON COLUMN payments.transaction_id IS '第三方支付平台的交易号,用于对账';
COMMENT ON COLUMN payments.callback_payload IS '支付回调的原始数据,用于问题排查和对账'; COMMENT ON COLUMN payments.callback_payload IS '支付回调的原始数据,用于问题排查和对账';
CREATE INDEX idx_payments_tenant ON payments(tenant_id);
CREATE INDEX idx_payments_order_id ON payments(order_id); CREATE INDEX idx_payments_order_id ON payments(order_id);
CREATE INDEX idx_payments_status ON payments(status); CREATE INDEX idx_payments_status ON payments(status);
CREATE INDEX idx_payments_method ON payments(method); CREATE INDEX idx_payments_method ON payments(method);
@ -259,6 +276,8 @@ CREATE INDEX idx_payments_created_at ON payments(created_at);
-- =========================================== -- ===========================================
CREATE TABLE ledger_entries ( CREATE TABLE ledger_entries (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
-- 租户ID多租户支持
tenant_id UUID,
-- 流水号(唯一标识) -- 流水号(唯一标识)
entry_no VARCHAR(50) UNIQUE NOT NULL, entry_no VARCHAR(50) UNIQUE NOT NULL,
-- 流水类型 -- 流水类型
@ -309,6 +328,7 @@ COMMENT ON COLUMN ledger_entries.entry_type IS '流水类型: INCOME=收入, REF
COMMENT ON COLUMN ledger_entries.balance_after IS '该笔流水后的账户余额快照,用于对账'; COMMENT ON COLUMN ledger_entries.balance_after IS '该笔流水后的账户余额快照,用于对账';
COMMENT ON COLUMN ledger_entries.accounting_period IS '会计期间格式YYYY-MM用于月度报表'; COMMENT ON COLUMN ledger_entries.accounting_period IS '会计期间格式YYYY-MM用于月度报表';
CREATE INDEX idx_ledger_entries_tenant ON ledger_entries(tenant_id);
CREATE INDEX idx_ledger_entries_entry_no ON ledger_entries(entry_no); CREATE INDEX idx_ledger_entries_entry_no ON ledger_entries(entry_no);
CREATE INDEX idx_ledger_entries_entry_type ON ledger_entries(entry_type); CREATE INDEX idx_ledger_entries_entry_type ON ledger_entries(entry_type);
CREATE INDEX idx_ledger_entries_order_id ON ledger_entries(order_id); CREATE INDEX idx_ledger_entries_order_id ON ledger_entries(order_id);
@ -324,6 +344,8 @@ CREATE INDEX idx_ledger_entries_business_type ON ledger_entries(business_type);
-- =========================================== -- ===========================================
CREATE TABLE daily_statistics ( CREATE TABLE daily_statistics (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
-- 租户ID多租户支持
tenant_id UUID,
-- 统计日期 -- 统计日期
stat_date DATE NOT NULL, stat_date DATE NOT NULL,
-- 统计维度: OVERALL(总体), CHANNEL(渠道), CATEGORY(移民类别) -- 统计维度: OVERALL(总体), CHANNEL(渠道), CATEGORY(移民类别)
@ -393,6 +415,7 @@ COMMENT ON COLUMN daily_statistics.dimension IS '统计维度: OVERALL=总体统
COMMENT ON COLUMN daily_statistics.conversion_rate IS '转化率 = 支付订单数 / 新对话数'; COMMENT ON COLUMN daily_statistics.conversion_rate IS '转化率 = 支付订单数 / 新对话数';
COMMENT ON COLUMN daily_statistics.estimated_api_cost IS '预估Claude API成本基于Token消耗计算'; COMMENT ON COLUMN daily_statistics.estimated_api_cost IS '预估Claude API成本基于Token消耗计算';
CREATE INDEX idx_daily_statistics_tenant ON daily_statistics(tenant_id);
CREATE INDEX idx_daily_statistics_stat_date ON daily_statistics(stat_date DESC); CREATE INDEX idx_daily_statistics_stat_date ON daily_statistics(stat_date DESC);
CREATE INDEX idx_daily_statistics_dimension ON daily_statistics(dimension, dimension_value); CREATE INDEX idx_daily_statistics_dimension ON daily_statistics(dimension, dimension_value);
@ -402,6 +425,8 @@ CREATE INDEX idx_daily_statistics_dimension ON daily_statistics(dimension, dimen
-- =========================================== -- ===========================================
CREATE TABLE monthly_financial_reports ( CREATE TABLE monthly_financial_reports (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
-- 租户ID多租户支持
tenant_id UUID,
-- 报表月份格式YYYY-MM -- 报表月份格式YYYY-MM
report_month VARCHAR(7) NOT NULL UNIQUE, report_month VARCHAR(7) NOT NULL UNIQUE,
@ -472,6 +497,7 @@ COMMENT ON COLUMN monthly_financial_reports.report_month IS '报表月份,格
COMMENT ON COLUMN monthly_financial_reports.revenue_by_category IS '按移民类别的收入明细JSON格式'; COMMENT ON COLUMN monthly_financial_reports.revenue_by_category IS '按移民类别的收入明细JSON格式';
COMMENT ON COLUMN monthly_financial_reports.status IS 'DRAFT=草稿可修改, CONFIRMED=已确认, LOCKED=已锁定不可修改'; COMMENT ON COLUMN monthly_financial_reports.status IS 'DRAFT=草稿可修改, CONFIRMED=已确认, LOCKED=已锁定不可修改';
CREATE INDEX idx_monthly_financial_reports_tenant ON monthly_financial_reports(tenant_id);
CREATE INDEX idx_monthly_financial_reports_month ON monthly_financial_reports(report_month DESC); CREATE INDEX idx_monthly_financial_reports_month ON monthly_financial_reports(report_month DESC);
CREATE INDEX idx_monthly_financial_reports_status ON monthly_financial_reports(status); CREATE INDEX idx_monthly_financial_reports_status ON monthly_financial_reports(status);
@ -481,6 +507,8 @@ CREATE INDEX idx_monthly_financial_reports_status ON monthly_financial_reports(s
-- =========================================== -- ===========================================
CREATE TABLE audit_logs ( CREATE TABLE audit_logs (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
-- 租户ID多租户支持
tenant_id UUID,
-- 操作者ID用户或管理员 -- 操作者ID用户或管理员
actor_id UUID, actor_id UUID,
-- 操作者类型: USER, ADMIN, SYSTEM -- 操作者类型: USER, ADMIN, SYSTEM
@ -520,6 +548,7 @@ COMMENT ON COLUMN audit_logs.action IS '操作类型,如: CREATE, UPDATE, DELE
COMMENT ON COLUMN audit_logs.old_values IS '操作前的数据快照,用于审计和回滚'; COMMENT ON COLUMN audit_logs.old_values IS '操作前的数据快照,用于审计和回滚';
COMMENT ON COLUMN audit_logs.new_values IS '操作后的数据快照'; COMMENT ON COLUMN audit_logs.new_values IS '操作后的数据快照';
CREATE INDEX idx_audit_logs_tenant ON audit_logs(tenant_id);
CREATE INDEX idx_audit_logs_actor_id ON audit_logs(actor_id); CREATE INDEX idx_audit_logs_actor_id ON audit_logs(actor_id);
CREATE INDEX idx_audit_logs_actor_type ON audit_logs(actor_type); CREATE INDEX idx_audit_logs_actor_type ON audit_logs(actor_type);
CREATE INDEX idx_audit_logs_action ON audit_logs(action); CREATE INDEX idx_audit_logs_action ON audit_logs(action);
@ -566,6 +595,8 @@ CREATE INDEX idx_outbox_aggregate ON outbox(aggregate_type, aggregate_id);
-- =========================================== -- ===========================================
CREATE TABLE documents ( CREATE TABLE documents (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
-- 租户ID多租户支持
tenant_id UUID,
-- 文档标题 -- 文档标题
title VARCHAR(255) NOT NULL, title VARCHAR(255) NOT NULL,
-- 文档内容(原始文本) -- 文档内容(原始文本)
@ -600,6 +631,7 @@ COMMENT ON TABLE documents IS '知识文档表 - 存储移民知识库文档,
COMMENT ON COLUMN documents.category IS '移民类别GENERAL表示通用知识'; COMMENT ON COLUMN documents.category IS '移民类别GENERAL表示通用知识';
COMMENT ON COLUMN documents.last_verified_at IS '最后验证时间,确保信息的时效性'; COMMENT ON COLUMN documents.last_verified_at IS '最后验证时间,确保信息的时效性';
CREATE INDEX idx_documents_tenant ON documents(tenant_id);
CREATE INDEX idx_documents_category ON documents(category); CREATE INDEX idx_documents_category ON documents(category);
CREATE INDEX idx_documents_is_active ON documents(is_active); CREATE INDEX idx_documents_is_active ON documents(is_active);
CREATE INDEX idx_documents_tags ON documents USING GIN(tags); CREATE INDEX idx_documents_tags ON documents USING GIN(tags);
@ -611,6 +643,8 @@ CREATE INDEX idx_documents_created_at ON documents(created_at);
-- =========================================== -- ===========================================
CREATE TABLE document_embeddings ( CREATE TABLE document_embeddings (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
-- 租户ID多租户支持
tenant_id UUID,
-- 所属文档ID -- 所属文档ID
document_id UUID REFERENCES documents(id) ON DELETE CASCADE, document_id UUID REFERENCES documents(id) ON DELETE CASCADE,
-- 分块序号 -- 分块序号
@ -628,6 +662,7 @@ CREATE TABLE document_embeddings (
COMMENT ON TABLE document_embeddings IS '文档向量嵌入表 - 存储文档分块的向量,用于语义搜索'; COMMENT ON TABLE document_embeddings IS '文档向量嵌入表 - 存储文档分块的向量,用于语义搜索';
COMMENT ON COLUMN document_embeddings.embedding IS '1536维向量使用text-embedding-3-small模型生成'; COMMENT ON COLUMN document_embeddings.embedding IS '1536维向量使用text-embedding-3-small模型生成';
CREATE INDEX idx_document_embeddings_tenant ON document_embeddings(tenant_id);
CREATE INDEX idx_document_embeddings_document_id ON document_embeddings(document_id); CREATE INDEX idx_document_embeddings_document_id ON document_embeddings(document_id);
-- IVFFlat索引用于快速向量相似度搜索 -- IVFFlat索引用于快速向量相似度搜索
CREATE INDEX idx_document_embeddings_embedding ON document_embeddings CREATE INDEX idx_document_embeddings_embedding ON document_embeddings
@ -669,6 +704,8 @@ CREATE INDEX idx_system_configs_group ON system_configs(config_group);
-- =========================================== -- ===========================================
CREATE TABLE admin_users ( CREATE TABLE admin_users (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
-- 租户ID多租户支持
tenant_id UUID,
-- 用户名(唯一) -- 用户名(唯一)
username VARCHAR(100) UNIQUE NOT NULL, username VARCHAR(100) UNIQUE NOT NULL,
-- 邮箱 -- 邮箱
@ -703,6 +740,7 @@ COMMENT ON TABLE admin_users IS '管理员用户表 - 存储后台管理员信
COMMENT ON COLUMN admin_users.role IS 'SUPER_ADMIN=超级管理员, ADMIN=管理员, OPERATOR=操作员, VIEWER=只读用户'; COMMENT ON COLUMN admin_users.role IS 'SUPER_ADMIN=超级管理员, ADMIN=管理员, OPERATOR=操作员, VIEWER=只读用户';
COMMENT ON COLUMN admin_users.failed_login_attempts IS '连续登录失败次数,超过阈值锁定账户'; COMMENT ON COLUMN admin_users.failed_login_attempts IS '连续登录失败次数,超过阈值锁定账户';
CREATE INDEX idx_admin_users_tenant ON admin_users(tenant_id);
CREATE INDEX idx_admin_users_username ON admin_users(username); CREATE INDEX idx_admin_users_username ON admin_users(username);
CREATE INDEX idx_admin_users_email ON admin_users(email); CREATE INDEX idx_admin_users_email ON admin_users(email);
CREATE INDEX idx_admin_users_role ON admin_users(role); CREATE INDEX idx_admin_users_role ON admin_users(role);
@ -714,6 +752,8 @@ CREATE INDEX idx_admin_users_is_active ON admin_users(is_active);
-- =========================================== -- ===========================================
CREATE TABLE experiences ( CREATE TABLE experiences (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
-- 租户ID多租户支持
tenant_id UUID,
-- 经验类型 -- 经验类型
type VARCHAR(50) NOT NULL type VARCHAR(50) NOT NULL
CHECK (type IN ('FAQ_PATTERN', 'USER_CONCERN', 'EFFECTIVE_RESPONSE', 'CONVERSION_PATTERN', 'CONFUSION_POINT')), CHECK (type IN ('FAQ_PATTERN', 'USER_CONCERN', 'EFFECTIVE_RESPONSE', 'CONVERSION_PATTERN', 'CONFUSION_POINT')),
@ -749,6 +789,7 @@ COMMENT ON TABLE experiences IS '经验库表 - 存储从对话中提取的经
COMMENT ON COLUMN experiences.type IS '经验类型: FAQ_PATTERN=常见问题模式, USER_CONCERN=用户关注点, EFFECTIVE_RESPONSE=有效回答, CONVERSION_PATTERN=转化模式, CONFUSION_POINT=困惑点'; COMMENT ON COLUMN experiences.type IS '经验类型: FAQ_PATTERN=常见问题模式, USER_CONCERN=用户关注点, EFFECTIVE_RESPONSE=有效回答, CONVERSION_PATTERN=转化模式, CONFUSION_POINT=困惑点';
COMMENT ON COLUMN experiences.confidence IS '置信度,值越高表示该经验越可靠'; COMMENT ON COLUMN experiences.confidence IS '置信度,值越高表示该经验越可靠';
CREATE INDEX idx_experiences_tenant ON experiences(tenant_id);
CREATE INDEX idx_experiences_type ON experiences(type); CREATE INDEX idx_experiences_type ON experiences(type);
CREATE INDEX idx_experiences_category ON experiences(category); CREATE INDEX idx_experiences_category ON experiences(category);
CREATE INDEX idx_experiences_confidence ON experiences(confidence DESC); CREATE INDEX idx_experiences_confidence ON experiences(confidence DESC);
@ -760,6 +801,8 @@ CREATE INDEX idx_experiences_is_applied ON experiences(is_applied);
-- =========================================== -- ===========================================
CREATE TABLE evolution_logs ( CREATE TABLE evolution_logs (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
-- 租户ID多租户支持
tenant_id UUID,
-- 触发人管理员ID -- 触发人管理员ID
triggered_by UUID REFERENCES admin_users(id), triggered_by UUID REFERENCES admin_users(id),
-- 变更类型 -- 变更类型
@ -792,6 +835,7 @@ COMMENT ON TABLE evolution_logs IS '进化日志表 - 记录系统配置和行
COMMENT ON COLUMN evolution_logs.type IS '变更类型: PROMPT_UPDATE=提示词更新, KNOWLEDGE_UPDATE=知识库更新, RULE_UPDATE=规则更新, BEHAVIOR_UPDATE=行为更新'; COMMENT ON COLUMN evolution_logs.type IS '变更类型: PROMPT_UPDATE=提示词更新, KNOWLEDGE_UPDATE=知识库更新, RULE_UPDATE=规则更新, BEHAVIOR_UPDATE=行为更新';
COMMENT ON COLUMN evolution_logs.status IS '变更状态流转: PROPOSED -> APPROVED -> APPLIED, 可回滚为ROLLED_BACK'; COMMENT ON COLUMN evolution_logs.status IS '变更状态流转: PROPOSED -> APPROVED -> APPLIED, 可回滚为ROLLED_BACK';
CREATE INDEX idx_evolution_logs_tenant ON evolution_logs(tenant_id);
CREATE INDEX idx_evolution_logs_status ON evolution_logs(status); CREATE INDEX idx_evolution_logs_status ON evolution_logs(status);
CREATE INDEX idx_evolution_logs_type ON evolution_logs(type); CREATE INDEX idx_evolution_logs_type ON evolution_logs(type);
CREATE INDEX idx_evolution_logs_triggered_by ON evolution_logs(triggered_by); CREATE INDEX idx_evolution_logs_triggered_by ON evolution_logs(triggered_by);
@ -803,6 +847,8 @@ CREATE INDEX idx_evolution_logs_created_at ON evolution_logs(created_at DESC);
-- =========================================== -- ===========================================
CREATE TABLE verification_codes ( CREATE TABLE verification_codes (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
-- 租户ID多租户支持
tenant_id UUID,
-- 手机号 -- 手机号
phone VARCHAR(20) NOT NULL, phone VARCHAR(20) NOT NULL,
-- 验证码 -- 验证码
@ -821,6 +867,7 @@ CREATE TABLE verification_codes (
COMMENT ON TABLE verification_codes IS '验证码表 - 存储手机验证码,支持防刷和过期机制'; COMMENT ON TABLE verification_codes IS '验证码表 - 存储手机验证码,支持防刷和过期机制';
CREATE INDEX idx_verification_codes_tenant ON verification_codes(tenant_id);
CREATE INDEX idx_verification_codes_phone ON verification_codes(phone); CREATE INDEX idx_verification_codes_phone ON verification_codes(phone);
CREATE INDEX idx_verification_codes_expires_at ON verification_codes(expires_at); CREATE INDEX idx_verification_codes_expires_at ON verification_codes(expires_at);
CREATE INDEX idx_verification_codes_ip ON verification_codes(ip_address); CREATE INDEX idx_verification_codes_ip ON verification_codes(ip_address);
@ -831,6 +878,8 @@ CREATE INDEX idx_verification_codes_ip ON verification_codes(ip_address);
-- =========================================== -- ===========================================
CREATE TABLE service_pricing ( CREATE TABLE service_pricing (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
-- 租户ID多租户支持
tenant_id UUID,
-- 服务类型 -- 服务类型
service_type VARCHAR(50) NOT NULL service_type VARCHAR(50) NOT NULL
CHECK (service_type IN ('ASSESSMENT', 'CONSULTATION', 'DOCUMENT_REVIEW')), CHECK (service_type IN ('ASSESSMENT', 'CONSULTATION', 'DOCUMENT_REVIEW')),
@ -864,6 +913,7 @@ COMMENT ON TABLE service_pricing IS '服务定价表 - 存储各类服务的定
COMMENT ON COLUMN service_pricing.original_price IS '原价,用于显示折扣效果'; COMMENT ON COLUMN service_pricing.original_price IS '原价,用于显示折扣效果';
COMMENT ON COLUMN service_pricing.effective_from IS '价格生效开始时间,支持定时调价'; COMMENT ON COLUMN service_pricing.effective_from IS '价格生效开始时间,支持定时调价';
CREATE INDEX idx_service_pricing_tenant ON service_pricing(tenant_id);
CREATE INDEX idx_service_pricing_service_type ON service_pricing(service_type); CREATE INDEX idx_service_pricing_service_type ON service_pricing(service_type);
CREATE INDEX idx_service_pricing_is_active ON service_pricing(is_active); CREATE INDEX idx_service_pricing_is_active ON service_pricing(is_active);
@ -873,6 +923,8 @@ CREATE INDEX idx_service_pricing_is_active ON service_pricing(is_active);
-- =========================================== -- ===========================================
CREATE TABLE coupons ( CREATE TABLE coupons (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
-- 租户ID多租户支持
tenant_id UUID,
-- 优惠券码 -- 优惠券码
code VARCHAR(50) UNIQUE NOT NULL, code VARCHAR(50) UNIQUE NOT NULL,
-- 优惠券名称 -- 优惠券名称
@ -911,6 +963,7 @@ CREATE TABLE coupons (
COMMENT ON TABLE coupons IS '优惠券表 - 存储优惠券信息,支持固定金额和百分比折扣'; COMMENT ON TABLE coupons IS '优惠券表 - 存储优惠券信息,支持固定金额和百分比折扣';
CREATE INDEX idx_coupons_tenant ON coupons(tenant_id);
CREATE INDEX idx_coupons_code ON coupons(code); CREATE INDEX idx_coupons_code ON coupons(code);
CREATE INDEX idx_coupons_is_active ON coupons(is_active); CREATE INDEX idx_coupons_is_active ON coupons(is_active);
CREATE INDEX idx_coupons_valid_until ON coupons(valid_until); CREATE INDEX idx_coupons_valid_until ON coupons(valid_until);
@ -921,6 +974,8 @@ CREATE INDEX idx_coupons_valid_until ON coupons(valid_until);
-- =========================================== -- ===========================================
CREATE TABLE user_coupons ( CREATE TABLE user_coupons (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
-- 租户ID多租户支持
tenant_id UUID,
-- 用户ID -- 用户ID
user_id UUID REFERENCES users(id) ON DELETE CASCADE, user_id UUID REFERENCES users(id) ON DELETE CASCADE,
-- 优惠券ID -- 优惠券ID
@ -938,6 +993,7 @@ CREATE TABLE user_coupons (
COMMENT ON TABLE user_coupons IS '用户优惠券表 - 记录用户领取和使用优惠券的情况'; COMMENT ON TABLE user_coupons IS '用户优惠券表 - 记录用户领取和使用优惠券的情况';
CREATE INDEX idx_user_coupons_tenant ON user_coupons(tenant_id);
CREATE INDEX idx_user_coupons_user_id ON user_coupons(user_id); CREATE INDEX idx_user_coupons_user_id ON user_coupons(user_id);
CREATE INDEX idx_user_coupons_coupon_id ON user_coupons(coupon_id); CREATE INDEX idx_user_coupons_coupon_id ON user_coupons(coupon_id);
CREATE INDEX idx_user_coupons_status ON user_coupons(status); CREATE INDEX idx_user_coupons_status ON user_coupons(status);
@ -1198,6 +1254,8 @@ COMMENT ON VIEW v_channel_statistics IS '渠道统计视图 - 按来源渠道汇
-- =========================================== -- ===========================================
CREATE TABLE knowledge_articles ( CREATE TABLE knowledge_articles (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
-- 租户ID多租户支持
tenant_id UUID,
-- 文章标题 -- 文章标题
title VARCHAR(500) NOT NULL, title VARCHAR(500) NOT NULL,
-- 文章内容纯文本或Markdown -- 文章内容纯文本或Markdown
@ -1241,6 +1299,7 @@ COMMENT ON COLUMN knowledge_articles.source IS '内容来源MANUAL手动添
COMMENT ON COLUMN knowledge_articles.embedding IS '文章向量1536维用于pgvector语义搜索'; COMMENT ON COLUMN knowledge_articles.embedding IS '文章向量1536维用于pgvector语义搜索';
COMMENT ON COLUMN knowledge_articles.quality_score IS '质量评分,根据引用和反馈自动计算'; COMMENT ON COLUMN knowledge_articles.quality_score IS '质量评分,根据引用和反馈自动计算';
CREATE INDEX idx_knowledge_articles_tenant ON knowledge_articles(tenant_id);
CREATE INDEX idx_knowledge_articles_category ON knowledge_articles(category); CREATE INDEX idx_knowledge_articles_category ON knowledge_articles(category);
CREATE INDEX idx_knowledge_articles_published ON knowledge_articles(is_published); CREATE INDEX idx_knowledge_articles_published ON knowledge_articles(is_published);
CREATE INDEX idx_knowledge_articles_quality ON knowledge_articles(quality_score DESC); CREATE INDEX idx_knowledge_articles_quality ON knowledge_articles(quality_score DESC);
@ -1252,6 +1311,8 @@ CREATE INDEX idx_knowledge_articles_embedding ON knowledge_articles USING ivffla
-- =========================================== -- ===========================================
CREATE TABLE knowledge_chunks ( CREATE TABLE knowledge_chunks (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
-- 租户ID多租户支持
tenant_id UUID,
-- 所属文章ID -- 所属文章ID
article_id UUID NOT NULL REFERENCES knowledge_articles(id) ON DELETE CASCADE, article_id UUID NOT NULL REFERENCES knowledge_articles(id) ON DELETE CASCADE,
-- 块内容 -- 块内容
@ -1275,6 +1336,7 @@ COMMENT ON TABLE knowledge_chunks IS '知识块表 - 文章分块,用于精确
COMMENT ON COLUMN knowledge_chunks.chunk_type IS '块类型,用于理解内容结构'; COMMENT ON COLUMN knowledge_chunks.chunk_type IS '块类型,用于理解内容结构';
COMMENT ON COLUMN knowledge_chunks.metadata IS '元数据,包含章节标题、前后块链接等'; COMMENT ON COLUMN knowledge_chunks.metadata IS '元数据,包含章节标题、前后块链接等';
CREATE INDEX idx_knowledge_chunks_tenant ON knowledge_chunks(tenant_id);
CREATE INDEX idx_knowledge_chunks_article ON knowledge_chunks(article_id); CREATE INDEX idx_knowledge_chunks_article ON knowledge_chunks(article_id);
CREATE INDEX idx_knowledge_chunks_embedding ON knowledge_chunks USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100); CREATE INDEX idx_knowledge_chunks_embedding ON knowledge_chunks USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);
@ -1284,6 +1346,8 @@ CREATE INDEX idx_knowledge_chunks_embedding ON knowledge_chunks USING ivfflat (e
-- =========================================== -- ===========================================
CREATE TABLE user_memories ( CREATE TABLE user_memories (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
-- 租户ID多租户支持
tenant_id UUID,
-- 用户ID -- 用户ID
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
-- 记忆类型 -- 记忆类型
@ -1328,6 +1392,7 @@ COMMENT ON COLUMN user_memories.memory_type IS '记忆类型,用于分类管
COMMENT ON COLUMN user_memories.importance IS '重要性评分,影响检索优先级'; COMMENT ON COLUMN user_memories.importance IS '重要性评分,影响检索优先级';
COMMENT ON COLUMN user_memories.is_expired IS '是否过期,用户情况变化时标记'; COMMENT ON COLUMN user_memories.is_expired IS '是否过期,用户情况变化时标记';
CREATE INDEX idx_user_memories_tenant ON user_memories(tenant_id);
CREATE INDEX idx_user_memories_user ON user_memories(user_id); CREATE INDEX idx_user_memories_user ON user_memories(user_id);
CREATE INDEX idx_user_memories_type ON user_memories(memory_type); CREATE INDEX idx_user_memories_type ON user_memories(memory_type);
CREATE INDEX idx_user_memories_importance ON user_memories(user_id, importance DESC); CREATE INDEX idx_user_memories_importance ON user_memories(user_id, importance DESC);
@ -1404,6 +1469,10 @@ CREATE INDEX idx_system_experiences_embedding ON system_experiences USING ivffla
-- =========================================== -- ===========================================
CREATE TABLE admins ( CREATE TABLE admins (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
-- 租户ID多租户支持
tenant_id UUID,
-- 是否为超级管理员(跨租户管理)
is_super_admin BOOLEAN DEFAULT FALSE,
-- 用户名(登录用) -- 用户名(登录用)
username VARCHAR(50) NOT NULL UNIQUE, username VARCHAR(50) NOT NULL UNIQUE,
-- 密码哈希 -- 密码哈希
@ -1437,6 +1506,8 @@ COMMENT ON TABLE admins IS '管理员表 - 管理后台用户,支持多角色
COMMENT ON COLUMN admins.role IS '角色SUPER_ADMIN超管,ADMIN管理员,OPERATOR运营,VIEWER只读'; COMMENT ON COLUMN admins.role IS '角色SUPER_ADMIN超管,ADMIN管理员,OPERATOR运营,VIEWER只读';
COMMENT ON COLUMN admins.permissions IS '细粒度权限列表JSON数组格式'; COMMENT ON COLUMN admins.permissions IS '细粒度权限列表JSON数组格式';
CREATE INDEX idx_admins_tenant ON admins(tenant_id);
CREATE INDEX idx_admins_super_admin ON admins(is_super_admin);
CREATE INDEX idx_admins_username ON admins(username); CREATE INDEX idx_admins_username ON admins(username);
CREATE INDEX idx_admins_role ON admins(role); CREATE INDEX idx_admins_role ON admins(role);
CREATE INDEX idx_admins_active ON admins(is_active); CREATE INDEX idx_admins_active ON admins(is_active);
@ -1445,6 +1516,191 @@ CREATE INDEX idx_admins_active ON admins(is_active);
INSERT INTO admins (username, password_hash, name, role, permissions) VALUES INSERT INTO admins (username, password_hash, name, role, permissions) VALUES
('admin', '$2b$10$rQNDjKwYXOw8FNrFcD3e0.T8KCqVJLqDQT9gQR2KPnDqPvqK8VpKi', '系统管理员', 'SUPER_ADMIN', '["*"]'); ('admin', '$2b$10$rQNDjKwYXOw8FNrFcD3e0.T8KCqVJLqDQT9gQR2KPnDqPvqK8VpKi', '系统管理员', 'SUPER_ADMIN', '["*"]');
-- ===========================================
-- Token使用量记录表 (token_usages)
-- 记录每次API调用的Token消耗
-- ===========================================
CREATE TABLE token_usages (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
-- 租户ID多租户支持
tenant_id UUID NOT NULL,
-- 用户ID
user_id UUID,
-- 对话ID
conversation_id UUID NOT NULL,
-- 消息ID
message_id UUID,
-- 模型名称
model VARCHAR(50) NOT NULL,
-- 输入Token数
input_tokens INT DEFAULT 0,
-- 输出Token数
output_tokens INT DEFAULT 0,
-- 缓存创建Token数
cache_creation_tokens INT DEFAULT 0,
-- 缓存读取Token数
cache_read_tokens INT DEFAULT 0,
-- 总Token数
total_tokens INT DEFAULT 0,
-- 预估成本(美元)
estimated_cost DECIMAL(10, 6) DEFAULT 0,
-- 意图类型
intent_type VARCHAR(30),
-- 工具调用次数
tool_calls INT DEFAULT 0,
-- 回复长度
response_length INT DEFAULT 0,
-- 延迟(毫秒)
latency_ms INT DEFAULT 0,
-- 创建时间
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
COMMENT ON TABLE token_usages IS 'Token使用量记录表 - 记录每次API调用的Token消耗和成本';
CREATE INDEX idx_token_usages_tenant ON token_usages(tenant_id);
CREATE INDEX idx_token_usages_user ON token_usages(user_id);
CREATE INDEX idx_token_usages_conversation ON token_usages(conversation_id);
CREATE INDEX idx_token_usages_created ON token_usages(created_at);
CREATE INDEX idx_token_usages_model ON token_usages(model);
-- ===========================================
-- 文件表 (files)
-- 存储用户上传的文件信息
-- ===========================================
CREATE TABLE files (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
-- 租户ID多租户支持
tenant_id UUID NOT NULL,
-- 用户ID
user_id UUID NOT NULL,
-- 对话ID
conversation_id UUID,
-- 原始文件名
original_name VARCHAR(500) NOT NULL,
-- 存储路径
storage_path VARCHAR(1000) NOT NULL,
-- MIME类型
mime_type VARCHAR(100) NOT NULL,
-- 文件类型
type VARCHAR(50) NOT NULL,
-- 文件大小(字节)
size BIGINT NOT NULL,
-- 状态
status VARCHAR(50) DEFAULT 'uploading',
-- 缩略图路径
thumbnail_path VARCHAR(1000),
-- 元数据
metadata JSONB,
-- 提取的文本内容
extracted_text TEXT,
-- 错误信息
error_message VARCHAR(1000),
-- 创建时间
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
-- 更新时间
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
-- 软删除时间
deleted_at TIMESTAMP WITH TIME ZONE
);
COMMENT ON TABLE files IS '文件表 - 存储用户上传的文件信息';
CREATE INDEX idx_files_tenant ON files(tenant_id);
CREATE INDEX idx_files_tenant_user ON files(tenant_id, user_id);
CREATE INDEX idx_files_user_created ON files(user_id, created_at);
CREATE INDEX idx_files_conversation_created ON files(conversation_id, created_at);
-- ===========================================
-- MCP服务器配置表 (mcp_server_configs)
-- 运行时MCP Server管理配置
-- ===========================================
CREATE TABLE mcp_server_configs (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
-- 租户IDNULL=全局)
tenant_id UUID,
-- 服务器唯一标识(用于工具名前缀)
server_id VARCHAR(100) NOT NULL,
-- 显示名称
name VARCHAR(255) NOT NULL,
-- 描述
description TEXT,
-- 传输方式: stdio 或 sse
transport VARCHAR(20) NOT NULL CHECK (transport IN ('stdio', 'sse')),
-- 命令stdio模式
command VARCHAR(500),
-- 命令参数stdio模式
args JSONB,
-- 环境变量stdio模式
env JSONB,
-- URLsse模式
url VARCHAR(500),
-- 工具是否可并发
tools_concurrency_safe BOOLEAN DEFAULT TRUE,
-- 连接超时(毫秒)
connect_timeout_ms INTEGER DEFAULT 10000,
-- 工具调用超时(毫秒)
tool_timeout_ms INTEGER DEFAULT 30000,
-- 是否启用
enabled BOOLEAN DEFAULT TRUE,
-- 创建时间
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
-- 更新时间
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
-- 创建者ID
created_by UUID,
-- 更新者ID
updated_by UUID,
-- 唯一约束同一租户下server_id唯一
CONSTRAINT uq_mcp_server_tenant_server_id UNIQUE (tenant_id, server_id)
);
COMMENT ON TABLE mcp_server_configs IS 'MCP服务器配置表 - 运行时MCP Server管理';
CREATE INDEX idx_mcp_server_configs_tenant ON mcp_server_configs(tenant_id);
CREATE INDEX idx_mcp_server_configs_enabled ON mcp_server_configs(tenant_id, enabled);
-- ===========================================
-- 评估规则表 (evaluation_rules)
-- 管理员可配置的质量评估门控规则
-- ===========================================
CREATE TABLE evaluation_rules (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
-- 租户ID
tenant_id UUID,
-- 适用的咨询阶段('*'表示所有阶段)
stage VARCHAR(50) NOT NULL,
-- 规则类型
rule_type VARCHAR(50) NOT NULL,
-- 规则名称
name VARCHAR(255) NOT NULL,
-- 规则描述
description TEXT,
-- 规则配置参数JSON
config JSONB NOT NULL DEFAULT '{}',
-- 是否启用
enabled BOOLEAN DEFAULT TRUE,
-- 优先级(越小越先执行)
priority INTEGER DEFAULT 0,
-- 失败时的动作: RETRY, SUPPLEMENT, WARN_AND_PASS, ESCALATE
failure_action VARCHAR(20) NOT NULL DEFAULT 'WARN_AND_PASS',
-- 创建者ID
created_by UUID,
-- 更新者ID
updated_by UUID,
-- 创建时间
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
-- 更新时间
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
COMMENT ON TABLE evaluation_rules IS '评估规则表 - 管理员可配置的质量评估门控规则';
COMMENT ON COLUMN evaluation_rules.stage IS '适用阶段: greeting, info_collection 等,* 表示所有阶段';
COMMENT ON COLUMN evaluation_rules.failure_action IS '失败动作: RETRY=重试, SUPPLEMENT=补充, WARN_AND_PASS=警告放行, ESCALATE=升级';
CREATE INDEX idx_evaluation_rules_tenant ON evaluation_rules(tenant_id);
CREATE INDEX idx_evaluation_rules_tenant_stage ON evaluation_rules(tenant_id, stage, enabled);
-- =========================================== -- ===========================================
-- 结束 -- 结束
-- =========================================== -- ===========================================